In my app i have a UIWebview in which all the activity is taking place.
The app works perfect on ios6 but with iOS 7 my UIwebview content is colliding with the status bar.
Is there a way i can set the view for my UIWindow to show this properly.
if([[[UIDevice currentDevice] systemVersion] integerValue] >= 7) {
if (self.window.rootViewController.view.frame.origin.y <=0) {
screenBounds = CGRectMake(0, 20, self.window.bounds.size.width, self.window.bounds.size.height-20);
}
}
self.window.rootViewController = self.viewController;
Thanks,
Try:
if ([self respondsToSelector:#selector(edgesForExtendedLayout)])
self.edgesForExtendedLayout = UIRectEdgeNone;
in the viewDidLoad method of your view controller.
Related
I noticed a bug in iOS 9, or may be I am not using something correctly.
In the following code in an empty project targeted for iPhone :
UIBarButtonItem *anotherButton = [[UIBarButtonItem alloc] initWithTitle:#"Show" style:UIBarButtonItemStylePlain target:self action:#selector(test:)];
self.navigationItem.rightBarButtonItem = anotherButton;
self.navBar.items = #[self.navigationItem];
I added a custom button to a navigation bar property. I noticed that after rotation from portrait to landscape, the button moves down and it is not centered correctly in the navigation bar.
Portrait Screen
Landscape Screen
This code works fine if I compile for iOS 8.4 for example, but not on iOS 9.
Has anyone encountered this?
Thanks!
I've seen something similar on the iPad. When I start the app in portrait, then rotate to landscape, the View Controller its navigationItem.titleView doesn't align correctly anymore. I simply reset it after rotation as follows in Swift:
override func viewWillTransitionToSize(size: CGSize, withTransitionCoordinator coordinator: UIViewControllerTransitionCoordinator) {
coordinator.animateAlongsideTransition(nil) { (coordinator) -> Void in
self.navigationItem.titleView = someView
}
}
Swift 3:
override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) {
coordinator.animate(alongsideTransition: nil) { (coordinator) -> Void in
self.navigationItem.titleView = self.someView
}
}
I have managed to fix the problem with custom navigation bar class with and overridden method:
-(void) layoutSubviews
{
[super layoutSubviews];
for (UIView *view in self.subviews)
{
if ([view isKindOfClass:[UIView class]] ||
[view isKindOfClass:[UIButton class]] ||
[view isKindOfClass:[UISearchBar class]] ||
[view isKindOfClass:[UILabel class]])
{
CGRect frame = view.frame;
frame.origin.y = (self.frame.size.height - frame.size.height) / 2.f;
view.frame = frame;
}
}
}
Other type of view classes can be added in the if statement. Its not the cleanest solution, but it will do for now.
In iOS 8 and lower show a UIActionSheet when keyboard is presented will present the action sheet over the keyboard. With iOS 9 this is no longer the case.
In my app we have a chat functionality and want the show a action over the keyboard. We used to use UIActionSheet which worked fine until iOS 8. In iOS 9 the action sheet is present behind the keyboard. I've tried both UIActionSheet and UIAlertController.
What we want is a action sheet like in messages.app
I've tried placing the action sheet in it own window and overriding canBecomeFirstResponder which just made the keyboard disappear.
I have implemented exactly this in our app. The trick is to have the alert controller appear on a different window. This is how the UIActionSheet implementation does it, and works great on iOS 8, but on 9, Apple has moved the keyboard implementation to a window which has a very high window level (10000000). The fix is to give your alert window an even higher window level (as a custom double value, not using the provided constants).
When using a custom window which will have transparency, make sure to read my answer here, regarding background color, to prevent window becoming black during rotation transitions.
_alertWindow = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
_alertWindow.rootViewController = [UIViewController new];
_alertWindow.windowLevel = 10000001;
_alertWindow.hidden = NO;
_alertWindow.tintColor = [[UIWindow valueForKey:#"keyWindow"] tintColor];
__weak __typeof(self) weakSelf = self;
UIAlertController* alert = [UIAlertController alertControllerWithTitle:#"Test" message:nil preferredStyle:UIAlertControllerStyleActionSheet];
[alert addAction:[UIAlertAction actionWithTitle:#"Cancel" style:UIAlertActionStyleCancel handler:^(UIAlertAction * _Nonnull action) {
weakSelf.alertWindow.hidden = YES;
weakSelf.alertWindow = nil;
}]];
[alert addAction:[UIAlertAction actionWithTitle:#"Test" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
weakSelf.alertWindow.hidden = YES;
weakSelf.alertWindow = nil;
}]];
[_alertWindow.rootViewController presentViewController:alert animated:YES completion:nil];
The answer supplied by Leo is broken as of iOS 11, because Apple now prevents you from setting a windowLevel above 10000000. A fix is to implement a custom UIWindow and override the windowLevel receiver:
#interface TopWindow : UIWindow #end
#implementation TopWindow
- (UIWindowLevel) windowLevel {
return 20000000.000;
}
#end
// usage:
UIWindow* w = [[TopWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
w.rootViewController = [UIViewController new];
w.hidden = NO;
[w.rootViewController presentViewController:yourActionSheetController animated:YES completion:nil];
This approach should be backwards compatible, but haven't tested all known versions. Happy hacking!
Based on Leo Natan's answer, I've created a Swift extension for presenting an alert sheet over the keyboard.
In my brief testing, the alertWindow is deallocated after the alert is dismissed, I believe because there's no strong reference to it outside of the alert. This means there's no need to hide or deallocate it in your UIAlertActions.
extension UIAlertController {
func presentOverKeyboard(animated: Bool, completion: (() -> Void)?) {
let alertWindow = UIWindow(frame: UIScreen.mainScreen().bounds)
// If you need a white/hidden/other status bar, use an appropriate VC.
// You may not need a custom class, and you can just use UIViewController()
alertWindow.rootViewController = whiteStatusBarVC()
alertWindow.windowLevel = 10000001
alertWindow.hidden = false
// Set to a tint if you'd like
alertWindow.tintColor = UIColor.greenColor()
alertWindow.rootViewController?.presentViewController(self, animated: animated, completion: completion)
}
}
private class whiteStatusBarVC: UIViewController {
private override func preferredStatusBarStyle() -> UIStatusBarStyle {
return .LightContent
}
}
use UIAlertController instead of UIActionSheet
My app's home screen has a UIScrollView that contains a UIWebView and a UIButton. The scroll view's content size is set accordingly after loading the web view.
The user can return to the home screen at anytime by simply pressing an icon in a tab bar. This action clears all of the view controllers out of the navigation controller and adds the home screen's controller to the navigation controller. The home screen is redisplayed correctly and the scroll view works just fine.
The problem I'm encountering is when the user presses a "back" button to return the to home screen, which pops the current view controller. The page redisplays fine, but you can't scroll anymore.
I've stepped through the code numerous times and the scroll view's content size is being set to the same value no matter which way you return to the home screen.
It's important to note that the scrollview only stops working under iOS 7. It works as expected under iOS 6.
The web page is loaded in viewWillAppear:
-(void)viewWillAppear:(BOOL)animated
{
NSString *fullURL = #"http://somewhere.com/app-homepage/index.html";
NSURL *url = [NSURL URLWithString:fullURL];
NSURLRequest *requestObj = [NSURLRequest requestWithURL:url];
[self.webView loadRequest:requestObj];
[self.scrollView setContentOffset:CGPointZero];
}
The scroll view is dynamically resized in webViewDidFinishLoad:
- (void)webViewDidFinishLoad:(UIWebView *)webView
{
webView.scrollView.scrollEnabled = NO;
CGRect frame = webView.frame;
frame.size.height = 1;
webView.frame = frame;
CGSize fittingSize = [webView sizeThatFits:CGSizeZero];
frame.size = fittingSize;
self.webViewHeightConstraint.constant = frame.size.height;
self.featuredCelebritiesButtonTopVerticalSpaceConstraint.constant = frame.size.height + 8;
CGSize svContentSize = self.scrollView.contentSize;
svContentSize.height = frame.size.height + 65;
self.scrollView.contentSize = svContentSize;
webView.frame = frame;
[self.activity stopAnimating];
}
Hi there I have an app where I have set supported interface orientation is set as landscape (left home button), landscape(right home button) in .plist file
and in the testviewcontroller.m file
I have the code: -
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
return (interfaceOrientation == UIInterfaceOrientationLandscapeLeft || interfaceOrientation == UIInterfaceOrientationLandscapeRight);
}
what changes do I have to make for it to appear normal on ios6 simulator
Thanks
found an answer: -
if ([[UIDevice currentDevice].systemVersion floatValue] < 6.0)
{
// how the view was configured before IOS6
[self.window addSubview: navigationController.view];
[self.window makeKeyAndVisible];
}
else
{
// this is the code that will start the interface to rotate once again
[self.window setRootViewController: self.navigationController];
}
from this link -
IOS 6 force device orientation to landscape
but now with another problem in ios6 - clicking on a textbox doesn't invoke the keyboard
https://developer.apple.com/library/prerelease/ios/#releasenotes/General/RN-iOSSDK-6_0/_index.html
The UIKit section explains how to do rotations in iOS6.
if ([[UIDevice currentDevice].systemVersion floatValue] < 6.0)
{
// how the view was configured before IOS6
[self.window addSubview: navigationController.view];
[self.window makeKeyAndVisible];
}
else
{
// this is the code that will start the interface to rotate once again
[self.window setRootViewController: self.navigationController];
}
I have developped a litle function to insert text in UITextView and scroll down automatically. It works fine with iOS 5 but since i have updated Xcode to Xcode 4.5 with iOS6, this method no longer works.
Could you help me ?
Here is this method :
- (void) insertTextInAPP : (UITextView*) tv : (NSString*) s {
NSRange range = {[tv.text length], 0};
[tv setSelectedRange:range];
[tv insertText:s];
[tv insertText:#"\n"];
range.location = [tv.text length];
[tv scrollRangeToVisible:range];
}
And i use this function like this :
NSString *newEventString = [[NSString alloc] initWithFormat : #"Test"];
[self insertTextInAPP:self.outPutTextView: newEventString];
It works just fine here (iOS 6, Xcode 5.5). Of course, I needed to change (UITextView) tv to (UITextView*) tv and "Test" to #"Test", but other than that it was alright.
What happens when you try it?