iOS Unable to simultaneously satisfy constraints in loadView - ios

I'm getting the Unable to simultaneously satisfy constraints error.
I don't get the error when the viewcontroller establishes itself using viewDidLoad but it does get the error when using loadView...
Why is this happening?
I thought the only difference between loadView and viewDidLoad is that viewDidLoad occurs after loadView. At least, that seems to be the going explanation...

I don't know whether my answer would completely address your issue,but it might act as a starting point to resolve your issue.
There are quite a few points(you might be aware of) which needs to be noted before you use loadView:
loadView is a method that gets called when view is loading,viewDidLoad is method that will be executed after the
view is loaded.
loadView is recommended when you are willing to create the view programatically instead of setting in xib file,other wise there is
no point in using or calling loadView(It all depends on your
application requirement though).
Don't call super loadView if you initialise your view from story
board or xib file.
If you initialise your view from story board, do not call
[super loadView] and you must assign your rootView to self.view
property, if you call [super loadView] inside the method, you better never override this method and put your code in viewDidLoad method..
If you are using xib file to set up the view,do the modifications of objects set up in viewDidLoad and don't call loadView,if you are creating the view programatically,initialise the view in the loadView and do the additional set up in viewDidLoad.
The constraint error generally pops up in story board or xib file,when "Use AutoLayout" is selected,if you unselect it,the error disappears,since you are creating the view programatically in loadView,it is your responsibility to see to it that the auto layout option is disabled i.e. you need to make use of setTranslatesAutoresizingMaskIntoConstraints property by setting it to "NO".
You can also refer to some of related questions here and there which could well get you out of this issue.
Thanks and happy coding :)

Related

UIViewController lifecycle function loadview() frame question

I have been mainly working with storyboard until I recently moving to only creating controller with code.
I followed our coding standard to create some subview in the loadView() function, inside which, the first line is super.loadView().
From what I observed, after I called super.loadView(), the frame of self.view is already set correctly with the viewController itself, which is exactly the frame of the viewController.
My more experience colleagues are saying this was 100% not working in the old days that it should give u CGRectZero instead and probably I should not rely on it.
I want to hear more suggestion from other people.
Here is my sample project setup:
1. create a simple proj
2. add a button in the first VC
3. create second VC by code, override loadView() function in second VC, call super.loadView() there and print self.view.bounds next line
4. self.present or use navigation controller from VC1 in the button action to present or push to VC2
5. it always give me correct frame of the second VC.
Please let me know.
----------- Edit -------------
To clarify my question, I know the lifecycle functions like viewDidLayoutSubviews or layoutSubViews to return the correct view. I am NOT asking these.
My question is why loadView() IS returning me the CORRECT frame now.
Unfortunatelly I cannot give any insights as to what is happening under the hood - what I can do though, is tell you that according to the documentation you shouldn’t be calling super.loadView() :
You can override this method in order to create your views manually. If you choose to do so, assign the root view of your view hierarchy to the view property. The views you create should be unique instances and should not be shared with any other view controller object. Your custom implementation of this method should not call super.
(Emphasis mine)
1) I have been mainly working with storyboard until I recently moving to only creating controller with code.
I followed our coding standard to create some subview in the loadView() function, inside which, the first line is super.loadView().
Since you are using xibs, use viewDidLoad over loadView because of If you use Interface Builder to create your views and initialize the view controller, you must not override this method. as stated in loadView in Apple Docs.
2) My more experience colleagues are saying this was 100% not working in the old days that it should give u CGRectZero instead and probably I should not rely on it.
I want to hear more suggestion from other people.
The proper frame for the viewController.view will be when viewWillLayoutSubviews is called. As for its subviews, viewDidLayoutSubviews is what you will need
view frame inside loadView and viewDidLoad are Nib frame size. Your colleagues are correct that it will not return a proper size. This is noticeable upon running an iPad app with viewcontroller presented modally, or run your app on different screen size as contrast to what the device is in xib
ALSO, this question is directly related to yours:
Why am I having to manually set my view's frame in viewDidLoad?

Add/Remove dynamically UIViews from a Storyboard's UIViewController

I'm new to IOS programming so I apologize if my question is obvious.
I created a UIViewController in storyboard, which contains a UIScrollView and multiple subviews.
These subviews (most often UITextViews) are filled with content from an external API, and content can thus be nil : in this case I would need to remove that subview which is empty.
For now I set this view as an IBOutlet and in viewDidLoad, if content is nil, I call
[self.thatView removeFromSuperView];
Is there a more efficient way to do that, for instance in loadView, in order to prevent that view to even load?
Is the usual method to handle subviews layoutSubviews?
Thx for your help
Any call before viewDidLoad will cause you problems unfortunately, you need to finish the load of a view before you dismiss it.

When I set a property in code does it matter if the storyboard option is enabled or disabled?

Consider UITableView's refreshing option.
If I have code in place to set up and display a refresher, should I keep it enabled or disabled in storyboard (With the little check-boxes)?
I figure it is not usually critical, but I would imagine that there are certain things that can cause bugs when overlooked, like if setting the refresher as 'off' in storyboard also changed some scrolling properties that were not covered in code (even though it doesn't-).
I am presuming that written code takes priority over storyboard options, and any storyboard settings are configured at compile time.
Is something that I need to be concerned with?
Every change you do in your UIViewControllers method -(void)viewDidLoad will be performed after the view has been loaded, so it will override the Storyboard/nib settings. And from this point on, all the code changes should be preserved (maybe some layout code can be problematic because of Auto-Layout etc.)
As the UIViewController documentation says:
viewDidLoad
Called after the controller’s view is loaded into memory.
- (void)viewDidLoad
This method is called after the view controller has loaded its view hierarchy into memory. This method is called regardless of whether the view hierarchy was loaded from a nib file or created programmatically in the loadView method. You usually override this method to perform additional initialization on views that were loaded from nib files.

When to use viewDidLoad and when to use awakeFromNib

I've gotten pretty comfortable using the viewDidLoad method to execute things I want done at the beginning of a view, but reading one of Apple's tutorials they set the data controller for the class in the awakeFromNib method and did nothing in the awakeFromNib. I swapped it and it seemingly worked identically in my app, but I'm not sure if it was better to have it in awakeFromNib or viewDidLoad.
When should I use either one?
awakeFromNib is called when the associated nib file with a class is loaded . Any class that can own a nib can use it. viewDidLoad is used only by view controllers. It is usually called when loading from nib as well but it can also be called by a view created in memory (very rare circumstance.). If you are using controllers, then I would suggest you to use viewDidLoad
For more Refer this Answer
viewDidLoad is associated with the view controller. If you need to initialize another control unarchived from the nib (e.g. UITableViewCell prototype) you cannot overload viewDidLoad, you need to overload awakeFromNib.

Is it ok to call [super loadView]?

I thought that I should never call [super loadView] but something is confusing me.
In description of loadView (UIViewController Class Reference) it is said that "Your custom implementation of this method should not call super.",
but in ZoomingPDFViewer example that they gave, loadView implementation (ZoomingPDFViewerViewController) is calling [super loadView].
I have tried to call it from my loadView method and it works ok, but I just don't understand then what does it mean to not call super.
You definitely should not be calling [super loadView]. I'd say you found a bug in the ZoomingPDFViewer example.
You override loadView when you want to programatically create the view hierarchy for your view controller (not using a xib).
As you pointed out, the docs clearly state that you should not call super.
Your custom implementation of this method should not call super.
I assume this is to avoid loading both from a xib and programatically creating a view as this method is used by the base to load a view from a xib:
If the view controller has an associated nib file, this method loads
the view from the nib file.
Note also that even if during allocation of your UIViewController object you pass nil for the nibNameOrNil parameter that the UIViewController implementation of loadView will try to load any xib with the associated class name in it.
A view controller has an associated nib file if the nibName property
returns a non-nil value, which occurs if the view controller was
instantiated from a storyboard, if you explicitly assigned it a nib
file using the initWithNibName:bundle: method, or if iOS finds a nib
file in the app bundle with a name based on the view controller’s
class name. If the view controller does not have an associated nib
file, this method creates a plain UIView object instead.
The real intent of this method is to give you full control of building the view hierarchy without relying on the built in xib loading mechanism.:
You can override this method in order to create your views manually.
Personally, I override loadView if: 1.) The xib I would make for it is really trivial or 2.) The layout of the control is very dynamic, so creating a xib with a static layout has little benefit.
NSViewController tries to initialize a view from a nib in -loadView. Since your nib name is not set for your controller, it will just give you a self.view = nil; I would assume UIViewController works the same way.
So it should be safe, but you it's completely unnecessary.
If you dont have a view created in your IB, then you should call [super loadView] in your code to give a view to your program.
In case of your custom views, you are suppose to create a view with the interfaz builder, so you dont need to call it.
If you create your ViewController programmatically, you could call super.loadView() instead of self.view = UIView(frame: UIScreen.main.bounds) at the beginning of override func loadView().
However, do NOT call self.view before super.loadView(), since the former will trigger the latter if view did not been loaded.
I don't think it's a good idea to explain Apple's documentation like a robot.

Resources