constraint
constraint,即约束,用来定义两个UI对象之间relationship,constraint本质是线性方程式,线性方程式格式:item1.attribute1 relationship multiplier * item2.attribute2 + constant
create
/* Create constraints explicitly. Constraints are of the form "view1.attr1 = view2.attr2 * multiplier + constant"
If your equation does not have a second view and attribute, use nil and NSLayoutAttributeNotAnAttribute.
*/
+(instancetype)constraintWithItem:(id)view1 attribute:(NSLayoutAttribute)attr1 relatedBy:(NSLayoutRelation)relation toItem:(nullable id)view2 attribute:(NSLayoutAttribute)attr2 multiplier:(CGFloat)multiplier constant:(CGFloat)c;
/* accessors
firstItem.firstAttribute {==,<=,>=} secondItem.secondAttribute * multiplier + constant
*/
@property (readonly, assign) id firstItem;
@property (readonly) NSLayoutAttribute firstAttribute;
@property (readonly) NSLayoutRelation relation;
@property (nullable, readonly, assign) id secondItem;
@property (readonly) NSLayoutAttribute secondAttribute;
@property (readonly) CGFloat multiplier;
/* Unlike the other properties, the constant may be modified after constraint creation. Setting the constant on an existing constraint performs much better than removing the constraint and adding a new one that's just like the old but for having a new constant.
*/
@property CGFloat constant;
辅助数据类型:
typedef NS_ENUM(NSInteger, NSLayoutRelation) {
NSLayoutRelationLessThanOrEqual = -1,
NSLayoutRelationEqual = 0,
NSLayoutRelationGreaterThanOrEqual = 1,
};
typedef NS_ENUM(NSInteger, NSLayoutAttribute) {
NSLayoutAttributeLeft = 1,
NSLayoutAttributeRight,
NSLayoutAttributeTop,
NSLayoutAttributeBottom,
NSLayoutAttributeLeading,
NSLayoutAttributeTrailing,
NSLayoutAttributeWidth,
NSLayoutAttributeHeight,
NSLayoutAttributeCenterX,
NSLayoutAttributeCenterY,
NSLayoutAttributeBaseline,
NSLayoutAttributeLastBaseline = NSLayoutAttributeBaseline,
NSLayoutAttributeFirstBaseline NS_ENUM_AVAILABLE_IOS(8_0),
NSLayoutAttributeLeftMargin NS_ENUM_AVAILABLE_IOS(8_0),
NSLayoutAttributeRightMargin NS_ENUM_AVAILABLE_IOS(8_0),
NSLayoutAttributeTopMargin NS_ENUM_AVAILABLE_IOS(8_0),
NSLayoutAttributeBottomMargin NS_ENUM_AVAILABLE_IOS(8_0),
NSLayoutAttributeLeadingMargin NS_ENUM_AVAILABLE_IOS(8_0),
NSLayoutAttributeTrailingMargin NS_ENUM_AVAILABLE_IOS(8_0),
NSLayoutAttributeCenterXWithinMargins NS_ENUM_AVAILABLE_IOS(8_0),
NSLayoutAttributeCenterYWithinMargins NS_ENUM_AVAILABLE_IOS(8_0),
NSLayoutAttributeNotAnAttribute = 0
};
解释:
- view1不可为空
- view2可为空,view2如果为空,view2传nil,attr2传NSLayoutAttributeNotAnAttribute,multiplier传0.0,线性方程式简化为view1.attr1 relation constant
- constant为readwrite,其余为readonly
- 如果创建了invalid constraint,throw NSInvalidArgumentException
- 如果使用代码创建constraint,建议使用layout anchor创建,layout anchor API包含类型信息,可在编译期捕获很多invalid constraint
activating&deactivating
/* The receiver may be activated or deactivated by manipulating this property. Only active constraints affect the calculated layout. Attempting to activate a constraint whose items have no common ancestor will cause an exception to be thrown. Defaults to NO for newly created constraints. */
@property (getter=isActive) BOOL active NS_AVAILABLE(10_10, 8_0);
/* Convenience method that activates each constraint in the contained array, in the same manner as setting active=YES. This is often more efficient than activating each constraint individually. */
+ (void)activateConstraints:(NSArray<NSLayoutConstraint *> *)constraints NS_AVAILABLE(10_10, 8_0);
/* Convenience method that deactivates each constraint in the contained array, in the same manner as setting active=NO. This is often more efficient than deactivating each constraint individually. */
+ (void)deactivateConstraints:(NSArray<NSLayoutConstraint *> *)constraints NS_AVAILABLE(10_10, 8_0);
解释:
- constraint通常关联着两个UI对象,假设两个UI对象closest common ancestor为ancestor,activating constraint(设置active为YES)等同调用ancestor的addConstraint,deactivating constraint(设置active为NO)等同调用ancestor的removeConstraint,显然ancestor是constraint拥有者
- active默认为NO,active为NO时constraint不属于任何view,此时constraint对layout不产生任何影响,只有active为YES,constraint add到view中,constraint对layout才会影响
- 如果两个UI对象无common ancestor,则在activating constraint(设置active为YES)时,throw exception,constraint不知道add到哪个view中
- 建议通过设置active属性代替调用addConstraint和removeConstraint
priority
/* If a constraint's priority level is less than UILayoutPriorityRequired, then it is optional. Higher priority constraints are met before lower priority constraints.
Constraint satisfaction is not all or nothing. If a constraint 'a == b' is optional, that means we will attempt to minimize 'abs(a-b)'.
This property may only be modified as part of initial set up. An exception will be thrown if it is set after a constraint has been added to a view.
*/
@property UILayoutPriority priority;
辅助数据类型:
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.
static const UILayoutPriority UILayoutPriorityFittingSizeLevel NS_AVAILABLE_IOS(6_0) = 50; // When you send -[UIView systemLayoutSizeFittingSize:], the size fitting most closely to the target size (the argument) is computed. UILayoutPriorityFittingSizeLevel is the priority level with which the view wants to conform to the target size in that computation. It's quite low. It is generally not appropriate to make a constraint at exactly this priority. You want to be higher or lower.
解释:
- required priority:ios = UILayoutPriorityRequired,os x = NSLayoutPriorityRequired,constraint priority默认为required
- 如果constraint已add到view,required priority to optional priority或optional priority to required priority throw exception
- 不管constraint是否已add到view,optional priority to optional priority允许
identifier
@interface NSLayoutConstraint (NSIdentifier)
/* For ease in debugging, name a constraint by setting its identifier, which will be printed in the constraint's description.
Identifiers starting with UI and NS are reserved by the system.
*/
@property (nullable, copy) NSString *identifier NS_AVAILABLE_IOS(7_0);
@end
解释:
- 方便调试,NS开头identifier为系统所保留
shouldBeArchived
/* When a view is archived, it archives some but not all constraints in its -constraints array. The value of shouldBeArchived informs UIView if a particular constraint should be archived by UIView.
If a constraint is created at runtime in response to the state of the object, it isn't appropriate to archive the constraint - rather you archive the state that gives rise to the constraint. Since the majority of constraints that should be archived are created in Interface Builder (which is smart enough to set this prop to YES), the default value for this property is NO.
*/
@property BOOL shouldBeArchived;
解释:
- view归档时,constraint是否归档标志,默认为NO
- 运行时依据对象状态创建的constraint不适合归档,但产生constraint的对象状态可归档