iOS & Xcode 6: Auto Layout Text Scaling on a Button - ios

I have a Today Extension with a button and UIImage. The button and image scale and center themselves correctly except the button's text is not scaled. I am writing this extension in Swift. I have tried these so far:
myButton.titleLabel.adjustsFontSizeToFitWidth = true
myButton.adjustsFontSizeToFitWidth = true
Both return errors.

Without seeing more code or the specific errors, the only thing I can see is that titleLabel is an optional. As written, the compiler would show the error 'UILabel? does not have a member named 'adjustsFontSizeToFitWidth'. Writing the line as myButton.titleLabel?.adjustsFontSizeToFitWidth = true should fix the error.
Also, UIButton doesn't have a member named 'adjustFontSizeToFitWidth' so the second line would throw the same error as above.
Try fixing that error as indicated above and see if your AutoLayout issue works.

Related

Xcode compile fails on internal error

I am having issues compiling a previously working xcode project. All it says is that there is an internal error. I have tried cleaning the project and the build files. The error is listed below. Any idea of how to fix this? I have tried both xcode 7.2 and 7.2.1.
Base.lproj/Main.storyboard: error: Internal error. Please file a bug at bugreport.apple.com and attach "/var/folders/tc/_8l_rs9n055_0zqdny0k89nr0000gp/T/IB-agent-diagnostics_2016-03-01_09-46-22_280000".
The error it shows I am getting is below. How do I find what view it is referring to?
Exception name: NSInvalidArgumentException
Exception reason: Unable to parse constraint format:
Unable to interpret '|' character, because the related view doesn't have a superview
H:|[self]
My guess is that you are using visual constraint language to constrain views.
The error says
Unable to parse constraint format: Unable to interpret '|' character, because the related view doesn't have a superview H:|[self]
which means that you are applying those constraints before you have actually added the view to its superview (the constraint tries to refer to the superview edge (the pipe | symbol)) which is not present because the view you are trying to apply constraints to has not yet been added to its superview.
So here is a scenario that could cause the issue:
let view = UIView()
let subview = UIView()
view.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("|[v]|"))
And how to solve it:
let view = UIView()
let subview = UIView()
view.addSubview(subview) // you have to add it to the superview before applying constraints
view.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("|[v]|"))

Xcode UITesting: label disappears from hierarchy and won't come back

This is using Xcode 7.2.1 and Swift 2.0.
I have a table cell containing a UILabel which is used to display an error message. So at initial load it is blanked using code like this:
cell.errorLabel.alpha = 0.0
cell.errorLabel.text = nil
Then later on when I've detected an error I want to display I do this:
cell.label.text = "to"
cell.errorLabel.alpha = 1.0
cell.errorLabel.text = "Error !!!!"
This works fine when running the app. However when running in a UI Test, I try to test that the error is being displayed like this:
let toCell = XCUIApplication().tables.... // Finds the cell with label 'to'
XCTAssertTrue(toCell.staticTexts["Error !!!!"].exists)
And it fails. I've verified I'm getting the right cell by checking the other ('to') label is present. Which it is. But the UI testing will not see the error label. I've tested this by adding a break point and using the debugger like this:
(lldb) p toCell.staticTexts.count
t = 427.03s Get number of matches for: Descendants matching type StaticText
t = 427.29s Snapshot accessibility hierarchy for enterprise.com.me
t = 427.31s Find: Descendants matching type Table
(UInt) $R2 = 1
t = 427.31s Find: Descendants matching type Cell
t = 427.32s Find: Elements containing elements matching type StaticText with identifier 'to'
t = 427.32s Find: Descendants matching type StaticText
The (UInt) $R2 = 1 indicating that there is one static text present. However looking at the simulator I can clearly see two UILabels.
I've tried a number of things individually to isolate the issue - Using just alpha or setting the text to nil, or using UIView's hidden property. Using any of these options to initially hide the label renders it invisible to UI tests when later made visible, no matter what I try.
I'm quite confused by this and I suspect it's a bug. Anyone have any ideas how to get UI Tests to see the UILabel once I make it visible?
P.S. I've also tried using a wait loop to wait for the label to appear (using expectationForPredicate(...), but the UILabel has not shown up.
Problem turned out to be that I had not set the accessibilityElements property on the cells. Therefore accessibility was having issues trying to figure out what was in each one.
So if you are building custom cells for a table view, ensure you set the accessibilityElements property so that testing can find the contents of the cells.

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.

IBOutlet property returning "Can't unwrap Optional.None" error

I'm getting stuck on some code with the dreaded "Can't unwrap Optional.None" error in my code.
I'm following the Shutterbug code from the iTunes U Stanford university course.
This is the code given in Objective-C for one of the classes.
http://pastebin.com/LG2k3BBW
and what I've come up with in Swift;
http://pastebin.com/pGtSzu6z
After tracing the errors these lines in particular seem to be giving me the problems
self.scrollView.zoomScale = 1.0
and
self.image = nil
Any advice on what's going wrong here?
I had originally put all the setters in the ViewDidLoad function and was receiving the same error.
This line is called when you are preparing for segue:
ivc.imageURL = flickerFetcher.URLforPhoto(photo, format: FlickrFetcher.FlickrPhotoFormat.Large)
Which calls the setter on imageURL:
set {
self.startDownloadingImage()
}
startDownloadingImage() calls the setter on image which is where you get all of your errors:
set{
self.imageView.image = image
self.scrollView.zoomScale = 1.0
self.spinner.stopAnimating()
self.imageView.frame = CGRectMake(0, 0, image!.size.width, image!.size.height)
}
Since all of this is happening in prepareForSegue, the view controller hasn't been loaded at this point and all of the outlets are nil hence the can't unwrap Optional.none.
You need to restructure your program's logic so that it isn't trying to do stuff with outlets before they are loaded.
Check your outlets are connected. Outlets are defined as implicitly unwrapped Optionals, so you'd expect to see that error if you referred to a property that wasn't set (e.g. If the outlet was not connected)
I've downloaded your project and there was a problem with the outlets - the scrollview and spinner were kind of grayed out in Xcode. Here's how the scrollview and spinner showed up for me:
This means that the items are not installed for the currently selected size class. If you go to the attributes inspector for that view, make sure the Installed option is checked for the size classes you care about:
In your project, the top box (representing any size class) was not checked.
However, there are many more problems within the code, too numerous to go into in full detail in this answer. You have several issues which are causing problems, including (I did give up after a while):
Infinite loops in your property accessors - for example, the get closure for imageURL
Implementing set or willSet closures when you actually want didSet - for example, the willSet on the scrollView would be better as a didSet, or you should be using newValue instead of scrollView, because at the point of willSet, scrollView is still nil.
Setting a value of nil to your image property, then accessing it in the setter block for that property
Something odd going on in your downloading logic (at this point, I decided to call it a day, sorry)

Resources