UIViewController hangs in Xcode 7 - ios

Not sure whether title is correct or not, I'm calling newViewController on button click but it is not rendering that. as it was working fine in Xcode 6.4 but in Xcode 7 its hangs the UI and not showing new view controller after pushViewController.
this is the error logs which print on console
Unable to simultaneously satisfy constraints.
Probably at least one of the constraints in the following list is one you don't want. Try this: (1) look at each constraint and try to figure out which you don't expect; (2) find the code that added the unwanted constraint or constraints and fix it. (Note: If you're seeing NSAutoresizingMaskLayoutConstraints that you don't understand, refer to the documentation for the UIView property translatesAutoresizingMaskIntoConstraints)
(
"<NSLayoutConstraint:0x16bbe0c0 V:[UIView:0x157fb230(45)]>",
"<NSLayoutConstraint:0x16bbc390 V:[UIView:0x157fb230(0)]>"
)
Will attempt to recover by breaking constraint
<NSLayoutConstraint:0x16bbe0c0 V:[UIView:0x157fb230(45)]>
Make a symbolic breakpoint at UIViewAlertForUnsatisfiableConstraints to catch this in the debugger.
The methods in the UIConstraintBasedLayoutDebugging category on UIView listed in <UIKit/UIView.h> may also be helpful.
I add break point in viewDidLoad of next controller it is calling that but not loading that ViewController.
EDIT
I seen that CPU usage are at 100% and second thing that my Viewcontroller have tableView so when i debug then it call my CellForRowatIndexPath for all the rows, so not sure where it exactly getting freezed my ViewController.
UPDATE
I'm updating my question again, I removed that error constrains (i.e. 45 and 0) now I'm not getting any constrains warning or error on console but still my UIView is freezes. Please help Thanks

It seems like you have two conflicting height constraints in one of your views. One is telling your view to have 0 height, the other tells it to have 45.
Also not related to the error message: You do not need the "Align center X to Superview" constraint, as that will be implicit because of leading/trailing constraints.
EDIT:
Try the implementing the following initializer and instantiate it with [MyViewControllerClass new]. I have had trouble previously with the default behavior of the viewcontroller loading a nib with the same name as the view controller by default. This is of course assuming you're not using a storyboard, in which case I can't really help.
- (instancetype)init
{
self = [super initWithNibName:#"MyNibName" bundle:nil]
if (self)
{
}
return self
}

I had this problem as well and it had to do with placeholder text (I am using storyboard). Clear out any placeholder text you have in fields and see if it works! Mine does. If that helps, just set the placeholder text in code as opposed to storyboard. I answered a similar question here:
Instantiating Modal view controller freezes the app - Probable issue with Xcode 7

Related

xcode reporting constraint error at runtime - but can't find it?

I am getting this error during runtime:
Will attempt to recover by breaking constraint
<NSLayoutConstraint:0x7ff70350c8a0 UITableViewCellContentView:0x7ff7058511c0.trailingMargin == UIView:0x7ff705851f00.trailing>
Make a symbolic breakpoint at UIViewAlertForUnsatisfiableConstraints to catch this in the debugger.
The methods in the UIConstraintBasedLayoutDebugging category on UIView listed in <UIKit/UIView.h> may also be helpful.
2016-08-29 16:53:12.533 xxxx[7125:4051730] Unable to simultaneously satisfy constraints.
Probably at least one of the constraints in the following list is one you don't want.
Try this:
(1) look at each constraint and try to figure out which you don't expect;
(2) find the code that added the unwanted constraint or constraints and fix it.
(
"<NSLayoutConstraint:0x7ff705a0aca0 UITableViewCellContentView:0x7ff705853420.trailingMargin == UIView:0x7ff7058546f0.trailing - 10>",
"<NSLayoutConstraint:0x7ff705a0ad90 UITableViewCellContentView:0x7ff705853420.trailingMargin == UIView:0x7ff7058546f0.trailing>"
)
However, I have been unable to identify from where it gets
UITableViewCellContentView:0x7ff705853420.trailingMargin ==
UIView:0x7ff7058546f0.trailing
I can not find in the IDE. I have tried searching code for where I set constraints - but nothing that match the error as far as I can tell.
Is it possible there is a constraint defined that Xcode IDE does not show?
You can extend NSLayoutConstraint and override description to return slightly more human readable information when a constraint breaks:
extension NSLayoutConstraint {
override public var description: String {
let id = identifier ?? "NO ID"
return "id: \(id), constant: \(constant)"
}
}
The tedious part of this is that you have to manually set an id for each constraint, though you can limit the amount of work needed by commenting out the extension and only setting identifiers for constraints that are related to the standard constraint warning.
You can try opening MainStoryBoard as source code and search there. The problem is you have 2 same constrains (trailing margin to UIView), one of them is 0, other is 10. It is possible it was not deleted from source code of storyboard.

How to update constraint in code using objective c

In my xib file, I have a constraint for height for the label in my xib file.
And in my objective c, I tried to change it using
self.heightConstraint.constant = newHeight;
But nothing is changed when I run it in simulator. I have used debugger and make sure that line is executed. And in Spark tool, I see the label height is the old height.
How can I adjust the height dynamically?
Updated:
I have changed my code to add a nil check.
if (self.heightConstraint != nil) {
self.heightConstraint.constant = newHeight;
}
My code still get executed, but nothing get changed.
There's nothing wrong with your code itself:
self.heightConstraint.constant = newHeight;
But the reason this changes nothing in your interface, even though it is being executed, is that self.heightConstraint is not a reference to a constraint in your interface. (It is probably nil.)
I agree with Matt. The likely reason your code isn't working is that you have a broken outlet link. In general, when code that tries to do something with an outlet or action doesn't work, the most likely cause is a broken outlet or action connection.
Rule of thumb: When debugging stereo or computer hardware, check the cables.
Corollary for for iOS or Mac OS apps in Xcode: When debugging UI code, check your IBOutlet and IBAction connections.
At what part of the view controller lifecycle are you changing the constraints? You may need to call setNeedsLayout on the parent view.

updateViewConstraints called when creating constraints in viewDidLoad

Currently I'm experiencing a strange behavior. I removed the auto resizing mask from a view for viewForHeaderInSection. When I'm doing this the app crashes because I tried to remove a constraint which is nil.
I'm creating the concerned constraints in viewDidLoad in my parent controller. In debug mode I found out that when the system tries to create a constraint where my child view controller is involved (which has the removed auto resizing mask from the section header view) it directly jumps to updateViewConstraints. Of course the constraints are nil because the weren't created yet.
If I add again the auto resizing mask the app works, but I can't do what I'm trying to do (to layout my views correctly).
If I create my constraints in updateViewConstraints the app also works.
I don't understand why this is happening. On a similar view controller it is working without problems. Sometimes I think auto layout is more a pain than a gain. On a server error an alert was displayed. Here the view could be correctly loaded. Seems that this is a kind of timing problem.
I want to know why this is happening and how should I proceed in future that such an error doesn't happen anymore. Am I doing something wrong?
Edit:
Don't know if it helps but if I call setNeedsLayout and layoutIfNeeded on the view of my child view controller in viewDidLoad of my parent then also the app crashes.
Edit 2:
Seems that it occurs when I add multiple views with constraints on different places to my view controller. For my table I add an empty message if there are currently no entries. If I don't add the label as subview to my table everything works fine.
So when I'm allowed to add my constraints? Currently I add them right after the view was added as subview. For the empty message it is in viewDidLoad and for the section header it is viewForHeaderInSection. Do I have to use something like setNeedsLayout?
Edit 3:
Adding a subview to the table view isn't a good idea at all (especially when using auto layout). For now I'm using the background view, but that's not the solution I'm looking for.
You do not need to change the value of translatesAutoresizingMaskIntoConstraints unless you actually have set the autoresizingMask to something other than 0. If you are using constraints, the solution is to completely ignore autoresizingMask and translatesAutoresizingMaskIntoConstraints.
Now I got the same problem again. My workaround didn't worked:
// on iOS 7 this would bring "Auto Layout still required after executing -layoutSubviews. UITableView's implementation of -layoutSubviews needs to call super." and the app crashes
// on iOS 8 this is needed, otherwise "Unable to simultaneously satisfy constraints."
// bug?
if (UIDevice.CurrentDevice.CheckSystemVersion (8, 0)) {
sectionHeader.TranslatesAutoresizingMaskIntoConstraints = false;
}
What I've found out so far is that it has to do with the headerview and the empty message (view). When both are used I get this problem. Either the app crashes or I get
Unable to simultaneously satisfy constraints
depending if I have the autoresizing mask turned off or not. Interestingly, only iOS 8 made this problem with my workaround. A solution would be to set a boolean variable in viewDidLoad if the constraints have been set up and check for this in updateViewConstraints. But I wanted to know the real cause for this and not using a workaround for a workaround ...
Every time I retrieve new data for my table I checked if the number of records is zero or not. If they were zero I showed my empty message. The problem seems to be caused by the reloadData, which I called before this check. Than UITableViewHeaderFooterContentView got a height of zero from the NSAutoresizingMaskLayoutConstraint. Restructuring my code to this variant
if (myList.Count == 0) {
this.TableView.BackgroundView = emptyMessage;
this.TableView.SeparatorStyle = UITableViewCellSeparatorStyle.None;
} else {
this.TableView.BackgroundView = null;
this.TableView.SeparatorStyle = UITableViewCellSeparatorStyle.SingleLine;
if (emptyMessage != null) {
emptyMessage.RemoveFromSuperview ();
}
}
// call this afterwards!
TableView.ReloadData();
seems to solve my issue.

Could not instantiate class named IBNSLayoutConstraint

I'm using XCode6 beta and trying out Swift. When I put some auto layout constraints in a view controller the app crashes with the following error:
Terminating app due to uncaught exception 'NSInvalidUnarchiveOperationException', reason: 'Could not instantiate class named IBNSLayoutConstraint'
You're getting this error because you've set a constraint to an IBOutlet that is removed at runtime. This happens when you set the constraint to be a placeholder in Interface Builder. Since the constraint is removed, when it goes to unarchive it, it throws an error saying it can't do so.
There are two ways to correct this.
Method 1
Right-click on your Storyboard > Open As > Source Code
In the opened storyboard xml, search for placeholder="YES".
You'll find constraints that are set to be removed at runtime. Remove the placeholder attribute from the constraint, save and close.
Run the app and your problem should be fixed.
Method 2
Find the constraint that's causing your problems in Interface Builder. Uncheck the Placeholder option in the GUI. This should be one of the constraints that's set to an IBOutlet in the ViewController that's causing your crash.
This is what it should look like:
Alternative
Assuming you actually want the constraint to be a placeholder, then you'll need to remove any referencing outlets. To do this, select the constraint that you wish to be a placeholder. Then open the connections inspector (the button furthest to the right that looks like this: (->) ) and then remove any referencing outlets that may exist on that constraint.
I had the same problem just now and the following worked for me.
I released a working version of my app to the App Store, came back to work on it again a few days later tapping onto one my tabs in the UITabBarController it crashed with the error:
Terminating app due to uncaught exception 'NSInvalidUnarchiveOperationException', reason: 'Could not instantiate class named IBNSLayoutConstraint'
I didn't have any placeholder layout constraints that I was aware of or constraint outlets that shouldn't have been defined.
The solution for me was to simply turn size classes off and keep size class data for iPhone (App is only for iPhone). This must've deleted anything I'd missed in the size classes. I want size classes so I turned them back on and the app just worked again.
This might not be necessarily a constraint problem. For me it was caused by not having checked "Installed" for a size class that was applying to my layout, see here
There was some problem with using size classes. I disabled that option from the storyboard properties and use only auto layout. It wasn't such a big problem since the app is iPhone only.
What ended up happening to me was that I cut a subview inside of Interface Builder to copy it into another xib. This left the subview in original xib Interface builder with it being greyed out. After removing the subview from it's original place (by selecting and deleting). I was able to get rid of the error.
There is an option in the inspector window when you select the xib file that will not use the constrains under "Show file the inspector" in the inspector called "Use autolayout".
I made a change to a scroll view so that it would let the picker controls embedded in it work properly using a solution I found elsewhere in Stackoverflow.
My new storyboard simply added these attributes to the scroll view, which seemed fine to me.
delaysContentTouches="NO" canCancelContentTouches="NO"
But in addition, I saw in my storyboard in another scene the following new fragment:
<variation key="default">
<mask key="subviews">
<exclude reference="86H-aM-wei"/>
</mask>
</variation>
I have no idea where it came from. At first I ignored it because everything seemed to work find on my dev machine. But when the build was built as Release and tested, I got the crash. Removing that spurious(?) fragment fixed the crash and has not seemed to impact anything else.
I had this issue when I had a button in a custom UICollectionViewCell, and had some of its constraints as IBOutlets on that class. I moved the button from the cell to the parent view controller and the IBOutlets were still referenced in the cell but didn't actually exist on the cell so blew everything up. Just needed to remove those IBOutlets and everything worked fine again!

Where should I be setting autolayout constraints when creating views programmatically

I see different examples where constraints are set. Some set them in viewDidLoad / loadView (after the subview was added). Others set them in the method updateViewConstraints, which gets called by viewDidAppear.
When I try setting constraints in updateViewContraints there can be a jumpiness to the layout, e.g. slight delay before the view appears. Also, if I use this method, should I clear out existing constraints first i.e. [self.view [removeConstraints:self.view.constraints]?
I set up my constraints in viewDidLoad/loadView (I'm targeting iOS >= 6). updateViewConstraints is useful for changing values of constraints, e.g. if some constraint is dependent on the orientation of the screen (I know, it's a bad practice) you can change its constant in this method.
Adding constraints in viewDidLoad is showed during the session "Introduction to Auto Layout for iOS and OS X" (WWDC 2012), starting from 39:22. I think it's one of those things that are said during lectures but don't land in the documentation.
UPDATE: I've noticed the mention of setting up constraints in Resource Management in View Controllers:
If you prefer to create views programmatically, instead of using a
storyboard, you do so by overriding your view controller’s loadView
method. Your implementation of this method should do the following:
(...)
3.If you are using auto layout, assign sufficient constraints to each of
the views you just created to control the position and size of your
views. Otherwise, implement the viewWillLayoutSubviews and
viewDidLayoutSubviews methods to adjust the frames of the subviews in
the view hierarchy. See “Resizing the View Controller’s Views.”
UPDATE 2: During WWDC 2015 Apple gave a new explanation of updateConstraints and updateViewConstraints recommended usage:
Really, all this is is a way for views to have a chance to make changes to constraints just in time for the next layout pass, but it's often not actually needed.
All of your initial constraint setup should ideally happen inside Interface Builder.
Or if you really find that you need to allocate your constraints programmatically, some place like viewDidLoad is much better.
Update constraints is really just for work that needs to be repeated periodically.
Also, it's pretty straightforward to just change constraints when you find the need to do that; whereas, if you take that logic apart from the other code that's related to it and you move it into a separate method that gets executed at a later time, your code becomes a lot harder to follow, so it will be harder for you to maintain, it will be a lot harder for other people to understand.
So when would you need to use update constraints?
Well, it boils down to performance.
If you find that just changing your constraints in place is too slow, then update constraints might be able to help you out.
It turns out that changing a constraint inside update constraints is actually faster than changing a constraint at other times.
The reason for that is because the engine is able to treat all the constraint changes that happen in this pass as a batch.
I recommend creating a BOOL and setting them in the -updateConstraints of UIView (or -updateViewConstraints, for UIViewController).
-[UIView updateConstraints]: (apple docs)
Custom views that set up constraints themselves should do so by overriding this method.
Both -updateConstraints and -updateViewConstraints may be called multiple times during a view's lifetime. (Calling setNeedsUpdateConstraints on a view will trigger this to happen, for example.) As a result, you need to make sure to prevent creating and activating duplicate constraints -- either using a BOOL to only perform certain constraint setup only once, or by making sure to deactivate/remove existing constraints before creating & activating new ones.
For example:
- (void)updateConstraints { // for view controllers, use -updateViewConstraints
if (!_hasLoadedConstraints) {
_hasLoadedConstraints = YES;
// create your constraints
}
[super updateConstraints];
}
Cheers to #fresidue in the comments for pointing out that Apple's docs recommend calling super as the last step. If you call super before making changes to some constraints, you may hit a runtime exception (crash).
This should be done in ViewDidLoad, as per WWDC video from Apple and the documentation.
No idea why people recommend updateConstraints. If you do in updateConstraints you will hit issues with NSAutoresizingMaskLayoutConstraint with auto resizing because your views have already taken into account the auto masks. You would need to remove them in updateConstraints to make work.
UpdateConstraints should be for just that, when you need to 'update' them, make changes etc from your initial setup.
Do it in view did layout subviews method
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
}
I have this solution to change constraints before those who are in the storyboard are loaded.
This solution removes any lags after the view is loaded.
-(void)updateViewConstraints{
dispatch_async(dispatch_get_main_queue(), ^{
//Modify here your Constraint -> Activate the new constraint and deactivate the old one
self.yourContraintA.active = true;
self.yourContraintB.active= false;
//ecc..
});
[super updateViewConstraints]; // This must be the last thing that you do here -> if! ->Crash!
}
You can set them in viewWillLayoutSubviews: too:
override func viewWillLayoutSubviews() {
if(!wasViewLoaded){
wasViewLoaded = true
//update constraint
//also maybe add a subview
}
}
This worked for me:
Swift 4.2
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
// Modify your constraints in here
...
}
Although honestly I am not sure if it is worth it. It seems a bit slower to load than in viewDidLoad(). I just wanted to move them out of the latter, because it's getting massive.
Add your constraints in viewWillLayoutSubviews() to add constraints programmatically
See Apple Documentation in Custom Layout Section
If possible, use constraints to define all of your layouts. The
resulting layouts are more robust and easier to debug. You should only
override the viewWillLayoutSubviews or layoutSubviews methods when you
need to create a layout that cannot be expressed with constraints
alone.
Following example is to pass any view to another class. create my view from storyboard
Swift 5.0
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
DispatchQueue.main.async {
self.abcInstance = ABC(frame: self.myView.frame)
}
}
If you miss DispatchQueue.main.async, it will take time to update constraints in viewWillAppear. Create myView in storyboard and give constraints same as screen width & height, then try printing frame of myView. It will give accurate value in DispatchQueue.main.async or in viewDidAppear but not give accurate value in viewWillAppear without DispatchQueue.main.async.

Resources