Using Swift again, am I missing something?
I have this line:
self.itemDescription?.setContentCompressionResistancePriority(UILayoutPriorityRequired, forAxis: UILayoutConstraintAxis.Vertical);
But Xcode is giving me an error:
Undefined symbols for architecture i386: "_UILayoutPriorityRequired"
Another one of Swift's quirks?
And the Content Compression Resistance is, how much a view "resists" getting smaller The View with higher resistance priority value is the one that will resist compression.
The content-hugging priority represents the resistance a view has to grow larger than its intrinsic content size. Conversely, the compression-resistance priority represents the resistance a view has to shrink beyond its intrinsic content size.
The Content Hugging Priority resolves this confusion. Setting any one of the labels Content Hugging Priority to greater than the other does the trick, and the one with higher priority hugs its content more and make the other expand more than its intinsic content. we get to see this, Makes sense right?
The priority really come in to play only if two different constraints conflict. The system will give importance to the one with higher priority. So, Priority is the tie-breaker in the autolayout world.
Solution: replace UILayoutPriorityRequired
with 1000
self.itemDescription?.setContentCompressionResistancePriority(1000, forAxis: UILayoutConstraintAxis.Vertical);
This is not a bug. It is a misunderstanding of how Objective-C libraries are imported into Swift. It should be understood how Swift imports code (even from the Apple UIKIt Libraries) from Objective-C into Swift.
UILayoutPriority is a float. In Objective-C, a couple of values have been pre-defined for us. The pre-defined values appear to be an enum. We might expect that the same enums would be available to us in Swift.
The documentation does seem to imply an enum:
SWIFT (Documentation)
typealias UILayoutPriority = Float
OBJECTIVE-C (Documentation)
enum { UILayoutPriorityRequired = 1000, UILayoutPriorityDefaultHigh = 750, UILayoutPriorityDefaultLow = 250, UILayoutPriorityFittingSizeLevel = 50, }; typedef float UILayoutPriority;
But in Xcode, if you ask to see the defintion of one of these enum values (UILayoutPriorityRequired, for example), you will see that they are actually defined in the header file as constant floats.
OBJECTIVE-C (Header file)
typedef float UILayoutPriority; static const UILayoutPriority UILayoutPriorityRequired NS_AVAILABLE_IOS(6_0) = 1000; // A required constraint. Do not exceed this. static const UILayoutPriority UILayoutPriorityDefaultHigh NS_AVAILABLE_IOS(6_0) = 750; // This is the priority level with which a button resists compressing its content. static const UILayoutPriority UILayoutPriorityDefaultLow NS_AVAILABLE_IOS(6_0) = 250; // This is the priority level at which a button hugs its contents horizontally.
So although we may like to think of the pre-defined layout priorities as enum values (as the documentation suggests) the layout priorities are not really defined as enums; they are defined as constant floats.
A hint that there is a mis-match -- for anyone that knows the C programming language -- is that a C enum may only contain int
values. The following is legal and will compile:
enum myEnum { JGCEnum_one = 1, // this is O.K. JGCEnum_two, JGCEnum_three } JGCEnum;
But we can not define floats as values for C enums. The following will not compile:
enum myEnum { JGCEnum_one = 1.5, // compile error JGCEnum_two, JGCEnum_three } JGCEnum;
Objective-C enums are the same as C enums (Swift enums are different). It is important to know if we are dealing with actual integers or floats. Because integers can be defined using the NS_ENUM macro, which can then be imported to Swift as a Swift enum.
The iBook says
Swift imports as a Swift enumeration any C-style enumeration marked with the NS_ENUM macro. This means that the prefixes to enumeration value names are truncated when they are imported into Swift, whether they’re defined in system frameworks or in custom code.
Excerpt From: Apple Inc. “Using Swift with Cocoa and Objective-C.” iBooks
That means that if UILayoutPriority had been defined as an integer using the NS_ENUM macro, it would have been imported into Swift as Swift enum. This is the case for UILayoutConstraintAxis.
SWIFT (Documentation)
enum UILayoutConstraintAxis : Int { case Horizontal case Vertical }
OBJECTIVE-C (Documentation)
enum { UILayoutConstraintAxisHorizontal = 0, UILayoutConstraintAxisVertical = 1 }; typedef NSInteger UILayoutConstraintAxis;
Looking at the Objective-C header file confirms what the documentation says.
OBJECTIVE-C (Header File)
// // UIView Constraint-based Layout Support // typedef NS_ENUM(NSInteger, UILayoutConstraintAxis) { UILayoutConstraintAxisHorizontal = 0, UILayoutConstraintAxisVertical = 1 };
So there are at least two ways to know if a pre-defined value you are used to using in Objective-C is available in Swift:
There is one more way to see if a typedef you are used to using is a constant or an enum. In code, test to see if the address of the constant exists. Constants have a memory address, while enums do not. See the code below.
// this line will compile and run just fine. // UILayoutPriorityDefaultHigh is a constant and has a memory address // the value will be true if the device is running iOS 6.0 or later // and false otherwise BOOL predefinedValueIsAvailable = (NULL != &UILayoutPriorityDefaultHigh); // this line will not compile // UILayoutConstraintAxisHorizontal is an enum (NOT a constant) // and does not have a memory address predefinedValueIsAvailable = (NULL != &UILayoutConstraintAxisHorizontal);
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With