Trouble loading view when using size classes - objective-c

I'm having this weird problem with size classes.
I noticed that any UIView which isn't installed in Any-Any size class is not part of the subviews when viewDidLoad is called.
Meaning I don't have access to it via my outlet nor does it appear in the [self.view subviews] array.
The subviews are placed fine on screen, and the first time I get to access them is in viewDidAppear.
I'm developing my app only for portrait iPhones so I set my Storyboard for compact width and regular height.
Am I doing something wrong? Do I need my storyboard to support Any-Any even though I don't really use this configuration?

AutoLayout hasn't completed until after the final viewDidLayoutSubviews call just before viewDidAppear.
- (void)viewDidLayoutSubviews
{
[super viewDidLayoutSubviews];
//Do your job with views or with its constraints...
}

You need your storyboard to support Any-Any even though you don't really use this configuration.
You have to enable Size Classes in Interface Builder, to do that please refer the following link.
https://developer.apple.com/library/ios/recipes/xcode_help-IB_adaptive_sizes/chapters/EnablingAdaptiveSizeDesign.html#//apple_ref/doc/uid/TP40014436-CH1-SW1

Related

Need a way to force a UIInterfaceOrientation rotation without iOS device rotating

I need to know if there is a way to tell a iOS7 device to set a views orientation without the device being rotated. Some way in code to trigger the device to calling the code that tells it which way to display the view.
If the device is in landscape and remains held in landscape orientation while a certain change happens I want to force a change to show the view in portrait orientation, at which point the user would need to turn the device to look at it properly. I'll explain why below
Looking at my app might make my description clearer - it is free to download
I have a number of view controllers (embedded in navigationControllers) and only one of them needs to be rotated into landscape and then only under certain conditions.
Solutions here on StackOverflow seem to be to make a category on UINavigationController giving it shouldAutorotate and supportedInterfaceOrientations methods and then use those methods in the individual viewControllers to block or allow rotations.
This has worked for me .... however
On the one view controller I wish to rotate , I don't want it to rotate all the time.
This view controller is the diveSiteDetailsController, (if you have downloaded the app you need to select dive sites on the first page then click the '+' to see it). It has a UISegmentedController and 4 subviews (3 tableviews and 1 other UIView). The current version on the App Store works fine now i've solved this - but looking at it may help you understand my issue better).
On diveSiteDetailViewController the UISegmentedController is used to switch between the 4 subviews.
All the subviews are used to enter data about the same dive site but as there is a lot of potential data, I have broken it into logical chucks each of which is a subview - location, data (depths,currents, visibility), type of environment and notes.
The .hidden property of each subview is used to make them appear and disappear.
I only want the second subview to rotate (the data view - it has some sliders on it that are easier to work with if in landscape).
restricting this rotation is easy - iI achieved it like this
- (NSUInteger)supportedInterfaceOrientations{
if (self.dsDataRangeSlidingTV.hidden) {
return UIInterfaceOrientationMaskPortrait;
}
return UIInterfaceOrientationMaskAllButUpsideDown;
}
Now the view will only rotate to landscape when the data table view is displayed.
However, once in landscape, if I chose a different subview with the UISegmentedController then they are, obviously, shown in landscape also as the iOS device hasn't done a rotation. This is the situation I am trying to avoid.
Rotating the iOS device will return those views to portrait as expected but i need to trigger the device to to reevaluate its display when I use the UISegmentedController to switch from the data subview to another subview and its that triggering that I don't know how to do.
any suggestions greatly received.
Heres a workaround that is working for me
I've added the following few lines to the end of my method that responds to the UISegmentedControl being tapped.
UIViewController *aDummyController = [[UIViewController alloc]init];
[self presentViewController:aDummyController animated:NO completion:nil];
[self dismissViewControllerAnimated:NO completion:nil];
adding a new viewController and popping it off triggers the rotation . This is a kludgey way of achieving what I wanted.
I found the solution in this post
Is there a documented way to set the iPhone orientation?
all credit to Josh who although not the accepted answer is the one that 99 people currently have up voted.
I still have a bug in that, if I were holding the device in landscape (although the display is portrait view) whilst on the screen that segues into the diveSiteDetailsController then the initial view the diveSiteDetailsController display will be in landscape.
To get around this I created a Bool property called notThisTime on the diveSiteDetailsController and set it to true in the prepareFor Segue on the viewController that called it.
i then did changed supportedInterfaceOrientation to
- (NSUInteger)supportedInterfaceOrientations
{// DLog(#"Running %# '%#'", self.class, NSStringFromSelector(_cmd));
if (self.notThisTime){
return UIInterfaceOrientationMaskPortrait;
}
if (!self.dsDataRangeSlidingTV.hidden) {
return UIInterfaceOrientationMaskAllButUpsideDown;
}
then at the end of the ViewDidLoad method I added
self.notThisTime = NO;
I would still love to hear from anyone with a suggestion how better to handle this. pushing and popping a dummy view to get the iPhone to do an orientation check seems like a work around for something that should just be available as a standard method call.
One final Note - the iOS simulator does not like this - you need to check on the device - it sometimes tries to draw the iPhone container in landscape while the screen is drawn vertically - however it does work fine on the iPhone

Unable to resize a UIView

I'm using xcode 4.5 (incase that makes any difference) along with a Storyboard and I'm trying to do something seemingly very simple without any luck. In my storyboard view I have placed a UIView component as you can see in the image here http://www.shopow.co.uk/assets/storyboard-view.png where the green section is the UIView which has a height of 100
In the viewDidLoad method I've added the following code
NSLog(#"View Height: %f", self.testView.bounds.size.height);
CGRect viewFrame = self.testView.frame;
CGSize newSize = CGSizeMake(viewFrame.size.width, 300);
viewFrame.size = newSize;
self.testView.frame = viewFrame;
NSLog(#"View Height: %f", self.testView.bounds.size.height);
From what I've read about resizing stuff I'd assume the green section to resize to be 300 high however this doesn't happen although the output in the log window shows the following
2012-10-19 13:05:28.015 TableTest[54318:c07] View Height: 460.000000
2012-10-19 13:05:28.016 TableTest[54318:c07] View Height: 300.000000
Notice the initial height being 460 rather than 100 which may mean something!
iOS simulator shows this http://www.shopow.co.uk/assets/simulator-view.png
I must be overlooking something obvious as far as I can tell this is not working as expected. Any guidance would be greatly appreciated.
I'm not sure if it will fix your problem, but you should really do your view resizing in viewWillAppear rather than viewDidLoad.
viewDidLoad literally means what it says, 'the view has loaded'. However, at this point your nib may not have set up the view as you would expect.
As a test, try logging the following in both viewDidLoad and viewWillAppear
NSLog(#"frame: %#", NSStringFromCGRect(self.view.frame));
You should see that in both methods you get different results. The viewWillAppear method is more likely to be correct as the view has been set up and is ready to be presented.
I personally don't use Interface Builder all that much as it causes more headaches than I can deal with but perhaps your auto-resizing masks or elastic constraints are set which is affecting the dimensions of your view?
Like #CaptainRedmuff said, you're calling it in the wrong method. viewDidLoad is called after the view is loaded, which means the frame has already been set. The method you're looking for is loadView, as viewWillAppear:animated and viewDidAppear:animated are being called after viewDidLoad.
OP wasn't really clear how he solved it. In case anyone else is having this problem.
If your view is showing the same layout as what you see in your storyboard despite the fact that you are programmatically resizing/changing its property in some way, this is because auto-layout is causing havoc.
Just select the view that you want to programmatically change and go to File Inspector in the Attributes pane. Deselect the checkbox next to Use Auto layout. Run again and you'll see your problem magically disappear.

Change layer of images

Is there a way to change the "layer" that UIImageView objects are drawn in? Whenever I add an image view to a view controller it defaults to drawing the most recently added one on top of all the others. So if I decide to add a "background" image it is now a "foreground" image and blocks everything else.
There isn't anything in the IB options or in the UIImageView class reference and I haven't been able to find anything here on SO. It's been a problem for a while and it's weird that I haven't seen anything about it before... I think it might just be my semantics coming from a delphi background.
Anyway, does anyone know about this issue / ICANHAZTEHCODEZ to fix it? Or is this just like the UIScrollView problem and poorly supported by the development environment.
This happens when I try to use the editor to arrange the subviews.
You can bring a SubView to Front or Send it background programmatically using
[self.view bringSubviewToFront:yourImageView];
and
[self.view sendSubviewToBack:yourImageView];
when self.view must be the superview of your imageView
In IB, select a UIControl and from top menu bar select Editor->arrage->send to front or back
When you use UIView's addSubview: method, it will add it to the top of the view stack resulting in what you are seeing.
There are numerous other UIView methods you can use to determine the order of subviews. E.g.:
- (void)insertSubview:(UIView *)view aboveSubview:(UIView *)siblingSubview;
- (void)insertSubview:(UIView *)view atIndex:(NSInteger)index;
- (void)sendSubviewToBack:(UIView *)view;
- (void)bringSubviewToFront:(UIView *)view;

How to hide or remove the UIwebview when a action is done?

I have two IBActions. In one action I am loading the UIWebview to display a PDF File from my bundle. On clicking the other button the whole UIWebView should get removed from superview.
I have tried using:
[webview removeFromSuperview];
and
webview.hidden=YES;
Neither of these are working. They are hiding my UIWebView for a second, but then it appears again.
Is is
I have created UIWEBVIEW programatically and added the UIWebvieWDelegate in the interface file. But when initializing the UIWebView I didnt set webview.delegate=self; Is it the problem?
have you connected Referencing Outlet to the class's #property in the Interface Builder?
If you don't do it, it would be the a possible reason why you cannot reach the UIWebView in your source code. for your sake, you should check the pointer of webview, if it is nil chronically, there is 100% you have not connected them each other.
I was trying to make a thing like this. The solution that worked for me was to add UIview object as subview to view with the frame of webview and bringing it to top.... When u want to make uiwebview visible, just remove that uiview object from superview.
OK, it seems old question, but also i can see there are almost thousand people have view it, and may have the same problem. so my answer for anyone my have the same issue in the future.
I just been doing something smiler and want to hide the web view when at a certain action.
I have tried the following
-(void)viewDidLoad
{
[super viewDidLoad];
process = [ProcessingData new];
[DetailView setHidden:YES];
DetailView.hidden = YES;
[DetailView removeFromSuperview];
self.DetailView = nil;
}
however it is still not working, as i have few labels in the WebView which are don't disappear when the view load, when I looked at the "StoryBoard" i notes that the labels are not subview of the
can u see the hierarchy of the libels under the WebView, they are subview of the main view, where they suppose to be same as the table view hierarchy
so in may case the WebView is hiding but the labels are not as they are not a part of the Webview.
how to sort this problem, if you really don't need web view use the normal one, otherwise you have to hide all the labels in that view. hope thats helpe
I don't know obj-c but still posting a solution that worked for me in swift. basically you have to use the main thread to remove the webview.
DispatchQueue.main.async {
print("\nremoving webview\n")
self.myWebView.stringByEvaluatingJavaScript(from: "document.body.innerHTML='';")
self.myWebView.removeFromSuperview()
}

How do I rotate the contents of a UIWebView?

I have made a very simple web browser app using a web view. Now I need to get the app so that when the iPhone is rotated, the text of the page is rotated as well.
How do I do this?
I am very confused by the auto-resize dialog, so it is possible I have done something wrong there.
Any help would be appreciated!
I think you sholud rotate UIWebView widget, not its contents. Contents should rotate as well. To support rotating add following code to your view controller:
- (BOOL)shouldAutorotateToInterfaceOrientation:
(UIInterfaceOrientation)interfaceOrientation {
return YES;
}
Rotated widget might look different then expected. Adjust struts and springs in Interface Builder.
I think you need to give us some sample code in order to determine what goes wrong. It is as Jacek says, the only think you should need to do is to support auto rotation on the UIWebView itself. The content should be rotated automatically.
I think you are confused by device orientation and view frame.
In most cases UIViews do change with respect to the orientation change. But to clarify - it is not because of the orientation change, but the layout change.
Only UIViewControllers need to consider device orientation - UIViews do NOT. When the device orientation changes, the UIViewController captures the event from its instance methods:
– willRotateToInterfaceOrientation:duration:
– willAnimateRotationToInterfaceOrientation:duration:
– didRotateFromInterfaceOrientation:
The UIViewController then re-layout the views - leading to reframing of the UIViews. In many cases, iOS can helps you in simplifying the relayout process by setting the UIViewAutoresizeMask. For example:
myWebview.autoresizeMask = UIVIewAutoresizeMaskFlexibleHeight | UIVIewAutoresizeMaskFlexibleHeight;
implies that when webview's superview changed its bounds, the webview will change accordingly.
As a summary, UIView only takes care of its frame / bounds etc.