NSLayoutConstraint+PureLayout.m 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553
  1. //
  2. // NSLayoutConstraint+PureLayout.m
  3. // https://github.com/PureLayout/PureLayout
  4. //
  5. // Copyright (c) 2013-2015 Tyler Fox
  6. //
  7. // This code is distributed under the terms and conditions of the MIT license.
  8. //
  9. // Permission is hereby granted, free of charge, to any person obtaining a copy
  10. // of this software and associated documentation files (the "Software"), to
  11. // deal in the Software without restriction, including without limitation the
  12. // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
  13. // sell copies of the Software, and to permit persons to whom the Software is
  14. // furnished to do so, subject to the following conditions:
  15. //
  16. // The above copyright notice and this permission notice shall be included in
  17. // all copies or substantial portions of the Software.
  18. //
  19. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  20. // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  21. // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  22. // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  23. // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  24. // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
  25. // IN THE SOFTWARE.
  26. //
  27. #import "NSLayoutConstraint+PureLayout.h"
  28. #import "ALView+PureLayout.h"
  29. #import "NSArray+PureLayout.h"
  30. #import "PureLayout+Internal.h"
  31. #pragma mark - NSLayoutConstraint+PureLayout
  32. @implementation NSLayoutConstraint (PureLayout)
  33. #pragma mark Batch Constraint Creation
  34. /**
  35. A global variable that stores a stack of arrays of constraints created without being immediately installed.
  36. When executing a constraints block passed into the +[autoCreateConstraintsWithoutInstalling:] method, a new
  37. mutable array is pushed onto this stack, and all constraints created with PureLayout in the block are added
  38. to this array. When the block finishes executing, the array is popped off this stack. Automatic constraint
  39. installation is prevented if this stack contains at least 1 array.
  40. NOTE: Access to this variable is not synchronized (and should only be done on the main thread).
  41. */
  42. static PL__NSMutableArray_of(PL__NSMutableArray_of(NSLayoutConstraint *) *) *_al_arraysOfCreatedConstraints = nil;
  43. /**
  44. A global variable that is set to YES when installing a batch of constraints collected from a call to +[autoCreateAndInstallConstraints].
  45. When this flag is YES, constraints are installed immediately without checking for or adding to the +[al_currentArrayOfCreatedConstraints].
  46. This is necessary to properly handle nested calls to +[autoCreateAndInstallConstraints], where calls whose block contains other call(s)
  47. should not return constraints from within the blocks of nested call(s).
  48. */
  49. static BOOL _al_isInstallingCreatedConstraints = NO;
  50. /**
  51. Accessor for the global state that stores arrays of constraints created without being installed.
  52. */
  53. + (PL__NSMutableArray_of(PL__NSMutableArray_of(NSLayoutConstraint *) *) *)al_arraysOfCreatedConstraints
  54. {
  55. NSAssert([NSThread isMainThread], @"PureLayout is not thread safe, and must be used exclusively from the main thread.");
  56. if (!_al_arraysOfCreatedConstraints) {
  57. _al_arraysOfCreatedConstraints = [NSMutableArray new];
  58. }
  59. return _al_arraysOfCreatedConstraints;
  60. }
  61. /**
  62. Accessor for the current mutable array of constraints created without being immediately installed.
  63. */
  64. + (PL__NSMutableArray_of(NSLayoutConstraint *) *)al_currentArrayOfCreatedConstraints
  65. {
  66. return [[self al_arraysOfCreatedConstraints] lastObject];
  67. }
  68. /**
  69. Accessor for the global state that determines whether automatic constraint installation should be prevented.
  70. */
  71. + (BOOL)al_preventAutomaticConstraintInstallation
  72. {
  73. return (_al_isInstallingCreatedConstraints == NO) && ([[self al_arraysOfCreatedConstraints] count] > 0);
  74. }
  75. /**
  76. Creates all of the constraints in the block, then installs (activates) them all at once.
  77. All constraints created from calls to the PureLayout API in the block are returned in a single array.
  78. This may be more efficient than installing (activating) each constraint one-by-one.
  79. Note: calls to this method may be nested. The constraints returned from a call will NOT include constraints
  80. created in nested calls; constraints are only returned from the inner-most call they are created within.
  81. @param block A block of method calls to the PureLayout API that create constraints.
  82. @return An array of the constraints that were created from calls to the PureLayout API inside the block.
  83. */
  84. + (PL__NSArray_of(NSLayoutConstraint *) *)autoCreateAndInstallConstraints:(__attribute__((noescape)) ALConstraintsBlock)block
  85. {
  86. NSArray *createdConstraints = [self autoCreateConstraintsWithoutInstalling:block];
  87. _al_isInstallingCreatedConstraints = YES;
  88. [createdConstraints autoInstallConstraints];
  89. _al_isInstallingCreatedConstraints = NO;
  90. return createdConstraints;
  91. }
  92. /**
  93. Creates all of the constraints in the block but prevents them from being automatically installed (activated).
  94. All constraints created from calls to the PureLayout API in the block are returned in a single array.
  95. Note: calls to this method may be nested. The constraints returned from a call will NOT include constraints
  96. created in nested calls; constraints are only returned from the inner-most call they are created within.
  97. @param block A block of method calls to the PureLayout API that create constraints.
  98. @return An array of the constraints that were created from calls to the PureLayout API inside the block.
  99. */
  100. + (PL__NSArray_of(NSLayoutConstraint *) *)autoCreateConstraintsWithoutInstalling:(__attribute__((noescape)) ALConstraintsBlock)block
  101. {
  102. NSAssert(block, @"The constraints block cannot be nil.");
  103. NSArray *createdConstraints = nil;
  104. if (block) {
  105. [[self al_arraysOfCreatedConstraints] addObject:[NSMutableArray new]];
  106. block();
  107. createdConstraints = [self al_currentArrayOfCreatedConstraints];
  108. [[self al_arraysOfCreatedConstraints] removeLastObject];
  109. }
  110. return createdConstraints;
  111. }
  112. #pragma mark Set Priority For Constraints
  113. /**
  114. A global variable that stores a stack of layout priorities to set on constraints.
  115. When executing a constraints block passed into the +[autoSetPriority:forConstraints:] method, the priority for
  116. that call is pushed onto this stack, and when the block finishes executing, that priority is popped off this
  117. stack. If this stack contains at least 1 priority, the priority at the top of the stack will be set for all
  118. constraints created by this library (even if automatic constraint installation is being prevented).
  119. NOTE: Access to this variable is not synchronized (and should only be done on the main thread).
  120. */
  121. static PL__NSMutableArray_of(NSNumber *) *_al_globalConstraintPriorities = nil;
  122. /**
  123. Accessor for the global stack of layout priorities.
  124. */
  125. + (PL__NSMutableArray_of(NSNumber *) *)al_globalConstraintPriorities
  126. {
  127. NSAssert([NSThread isMainThread], @"PureLayout is not thread safe, and must be used exclusively from the main thread.");
  128. if (!_al_globalConstraintPriorities) {
  129. _al_globalConstraintPriorities = [NSMutableArray new];
  130. }
  131. return _al_globalConstraintPriorities;
  132. }
  133. /**
  134. Returns the current layout priority to use for constraints.
  135. When executing a constraints block passed into +[autoSetPriority:forConstraints:], this will return
  136. the priority for the current block. Otherwise, the default Required priority is returned.
  137. */
  138. + (ALLayoutPriority)al_currentGlobalConstraintPriority
  139. {
  140. PL__NSMutableArray_of(NSNumber *) *globalConstraintPriorities = [self al_globalConstraintPriorities];
  141. if ([globalConstraintPriorities count] == 0) {
  142. return ALLayoutPriorityRequired;
  143. }
  144. return [[globalConstraintPriorities lastObject] floatValue];
  145. }
  146. /**
  147. Accessor for the global state that determines if we're currently in the scope of a priority constraints block.
  148. */
  149. + (BOOL)al_isExecutingPriorityConstraintsBlock
  150. {
  151. return [[self al_globalConstraintPriorities] count] > 0;
  152. }
  153. /**
  154. Sets the constraint priority to the given value for all constraints created using the PureLayout
  155. API within the given constraints block.
  156. NOTE: This method will have no effect (and will NOT set the priority) on constraints created or added
  157. without using the PureLayout API!
  158. @param priority The layout priority to be set on all constraints created in the constraints block.
  159. @param block A block of method calls to the PureLayout API that create and install constraints.
  160. */
  161. + (void)autoSetPriority:(ALLayoutPriority)priority forConstraints:(__attribute__((noescape)) ALConstraintsBlock)block
  162. {
  163. NSAssert(block, @"The constraints block cannot be nil.");
  164. if (block) {
  165. [[self al_globalConstraintPriorities] addObject:@(priority)];
  166. block();
  167. [[self al_globalConstraintPriorities] removeLastObject];
  168. }
  169. }
  170. #pragma mark Identify Constraints
  171. #if PL__PureLayout_MinBaseSDK_iOS_8_0 || PL__PureLayout_MinBaseSDK_OSX_10_10
  172. /**
  173. A global variable that stores a stack of identifier strings to set on constraints.
  174. When executing a constraints block passed into the +[autoSetIdentifier:forConstraints:] method, the identifier for
  175. that call is pushed onto this stack, and when the block finishes executing, that identifier is popped off this
  176. stack. If this stack contains at least 1 identifier, the identifier at the top of the stack will be set for all
  177. constraints created by this library (even if automatic constraint installation is being prevented).
  178. NOTE: Access to this variable is not synchronized (and should only be done on the main thread).
  179. */
  180. static PL__NSMutableArray_of(NSString *) *_al_globalConstraintIdentifiers = nil;
  181. /**
  182. Accessor for the global state of constraint identifiers.
  183. */
  184. + (PL__NSMutableArray_of(NSString *) *)al_globalConstraintIdentifiers
  185. {
  186. NSAssert([NSThread isMainThread], @"PureLayout is not thread safe, and must be used exclusively from the main thread.");
  187. if (!_al_globalConstraintIdentifiers) {
  188. _al_globalConstraintIdentifiers = [NSMutableArray new];
  189. }
  190. return _al_globalConstraintIdentifiers;
  191. }
  192. /**
  193. Returns the current identifier string to use for constraints.
  194. When executing a constraints block passed into +[autoSetIdentifier:forConstraints:], this will return
  195. the identifier for the current block. Otherwise, nil is returned.
  196. */
  197. + (NSString *)al_currentGlobalConstraintIdentifier
  198. {
  199. PL__NSMutableArray_of(NSString *) *globalConstraintIdentifiers = [self al_globalConstraintIdentifiers];
  200. if ([globalConstraintIdentifiers count] == 0) {
  201. return nil;
  202. }
  203. return [globalConstraintIdentifiers lastObject];
  204. }
  205. /**
  206. Sets the identifier for all constraints created using the PureLayout API within the given constraints block.
  207. NOTE: This method will have no effect (and will NOT set the identifier) on constraints created or added
  208. without using the PureLayout API!
  209. @param identifier A string used to identify all constraints created in the constraints block.
  210. @param block A block of method calls to the PureLayout API that create and install constraints.
  211. */
  212. + (void)autoSetIdentifier:(NSString *)identifier forConstraints:(__attribute__((noescape)) ALConstraintsBlock)block
  213. {
  214. NSAssert(block, @"The constraints block cannot be nil.");
  215. NSAssert(identifier, @"The identifier string cannot be nil.");
  216. if (block) {
  217. if (identifier) {
  218. [[self al_globalConstraintIdentifiers] addObject:identifier];
  219. }
  220. block();
  221. if (identifier) {
  222. [[self al_globalConstraintIdentifiers] removeLastObject];
  223. }
  224. }
  225. }
  226. /**
  227. Sets the string as the identifier for this constraint. Available in iOS 7.0 and OS X 10.9 and later.
  228. The identifier will be printed along with the constraint's description.
  229. This is helpful to document a constraint's purpose and aid in debugging.
  230. @param identifier A string used to identify this constraint.
  231. @return This constraint.
  232. */
  233. - (instancetype)autoIdentify:(NSString *)identifier
  234. {
  235. if ([self respondsToSelector:@selector(setIdentifier:)]) {
  236. self.identifier = identifier;
  237. }
  238. return self;
  239. }
  240. #endif /* PL__PureLayout_MinBaseSDK_iOS_8_0 || PL__PureLayout_MinBaseSDK_OSX_10_10 */
  241. #pragma mark Install & Remove Constraints
  242. /**
  243. Activates the constraint.
  244. */
  245. - (void)autoInstall
  246. {
  247. #if PL__PureLayout_MinBaseSDK_iOS_8_0 || PL__PureLayout_MinBaseSDK_OSX_10_10
  248. if ([self respondsToSelector:@selector(setActive:)]) {
  249. [NSLayoutConstraint al_applyGlobalStateToConstraint:self];
  250. if ([NSLayoutConstraint al_preventAutomaticConstraintInstallation]) {
  251. [[NSLayoutConstraint al_currentArrayOfCreatedConstraints] addObject:self];
  252. } else {
  253. self.active = YES;
  254. }
  255. return;
  256. }
  257. #endif /* PL__PureLayout_MinBaseSDK_iOS_8_0 || PL__PureLayout_MinBaseSDK_OSX_10_10 */
  258. NSAssert(self.firstItem || self.secondItem, @"Can't install a constraint with nil firstItem and secondItem.");
  259. if (self.firstItem) {
  260. if (self.secondItem) {
  261. NSAssert([self.firstItem isKindOfClass:[ALView class]] && [self.secondItem isKindOfClass:[ALView class]], @"Can only automatically install a constraint if both items are views.");
  262. ALView *commonSuperview = [self.firstItem al_commonSuperviewWithView:self.secondItem];
  263. [commonSuperview al_addConstraint:self];
  264. } else {
  265. NSAssert([self.firstItem isKindOfClass:[ALView class]], @"Can only automatically install a constraint if the item is a view.");
  266. [self.firstItem al_addConstraint:self];
  267. }
  268. } else {
  269. NSAssert([self.secondItem isKindOfClass:[ALView class]], @"Can only automatically install a constraint if the item is a view.");
  270. [self.secondItem al_addConstraint:self];
  271. }
  272. }
  273. /**
  274. Deactivates the constraint.
  275. */
  276. - (void)autoRemove
  277. {
  278. #if PL__PureLayout_MinBaseSDK_iOS_8_0 || PL__PureLayout_MinBaseSDK_OSX_10_10
  279. if ([self respondsToSelector:@selector(setActive:)]) {
  280. self.active = NO;
  281. return;
  282. }
  283. #endif /* PL__PureLayout_MinBaseSDK_iOS_8_0 || PL__PureLayout_MinBaseSDK_OSX_10_10 */
  284. if (self.secondItem) {
  285. ALView *commonSuperview = [self.firstItem al_commonSuperviewWithView:self.secondItem];
  286. while (commonSuperview) {
  287. if ([commonSuperview.constraints containsObject:self]) {
  288. [commonSuperview removeConstraint:self];
  289. return;
  290. }
  291. commonSuperview = commonSuperview.superview;
  292. }
  293. }
  294. else {
  295. [self.firstItem removeConstraint:self];
  296. return;
  297. }
  298. NSAssert(nil, @"Failed to remove constraint: %@", self);
  299. }
  300. #pragma mark Internal Methods
  301. /**
  302. Applies the global constraint priority and identifier to the given constraint.
  303. This should be done before installing all constraints.
  304. @param constraint The constraint to set the global priority and identifier on.
  305. */
  306. + (void)al_applyGlobalStateToConstraint:(NSLayoutConstraint *)constraint
  307. {
  308. if ([NSLayoutConstraint al_isExecutingPriorityConstraintsBlock]) {
  309. constraint.priority = [NSLayoutConstraint al_currentGlobalConstraintPriority];
  310. }
  311. #if PL__PureLayout_MinBaseSDK_iOS_8_0 || PL__PureLayout_MinBaseSDK_OSX_10_10
  312. NSString *globalConstraintIdentifier = [NSLayoutConstraint al_currentGlobalConstraintIdentifier];
  313. if (globalConstraintIdentifier) {
  314. [constraint autoIdentify:globalConstraintIdentifier];
  315. }
  316. #endif /* PL__PureLayout_MinBaseSDK_iOS_8_0 || PL__PureLayout_MinBaseSDK_OSX_10_10 */
  317. }
  318. /**
  319. Returns the corresponding NSLayoutAttribute for the given ALAttribute.
  320. @return The layout attribute for the given ALAttribute.
  321. */
  322. + (NSLayoutAttribute)al_layoutAttributeForAttribute:(ALAttribute)attribute
  323. {
  324. NSLayoutAttribute layoutAttribute = NSLayoutAttributeNotAnAttribute;
  325. switch (attribute) {
  326. case ALEdgeLeft:
  327. layoutAttribute = NSLayoutAttributeLeft;
  328. break;
  329. case ALEdgeRight:
  330. layoutAttribute = NSLayoutAttributeRight;
  331. break;
  332. case ALEdgeTop:
  333. layoutAttribute = NSLayoutAttributeTop;
  334. break;
  335. case ALEdgeBottom:
  336. layoutAttribute = NSLayoutAttributeBottom;
  337. break;
  338. case ALEdgeLeading:
  339. layoutAttribute = NSLayoutAttributeLeading;
  340. break;
  341. case ALEdgeTrailing:
  342. layoutAttribute = NSLayoutAttributeTrailing;
  343. break;
  344. case ALDimensionWidth:
  345. layoutAttribute = NSLayoutAttributeWidth;
  346. break;
  347. case ALDimensionHeight:
  348. layoutAttribute = NSLayoutAttributeHeight;
  349. break;
  350. case ALAxisVertical:
  351. layoutAttribute = NSLayoutAttributeCenterX;
  352. break;
  353. case ALAxisHorizontal:
  354. layoutAttribute = NSLayoutAttributeCenterY;
  355. break;
  356. case ALAxisBaseline: // same value as ALAxisLastBaseline
  357. layoutAttribute = NSLayoutAttributeBaseline;
  358. break;
  359. #if PL__PureLayout_MinBaseSDK_iOS_8_0
  360. case ALAxisFirstBaseline:
  361. NSAssert(PL__PureLayout_MinSysVer_iOS_8_0, @"ALAxisFirstBaseline is only supported on iOS 8.0 or higher.");
  362. layoutAttribute = NSLayoutAttributeFirstBaseline;
  363. break;
  364. case ALMarginLeft:
  365. NSAssert(PL__PureLayout_MinSysVer_iOS_8_0, @"ALEdgeLeftMargin is only supported on iOS 8.0 or higher.");
  366. layoutAttribute = NSLayoutAttributeLeftMargin;
  367. break;
  368. case ALMarginRight:
  369. NSAssert(PL__PureLayout_MinSysVer_iOS_8_0, @"ALEdgeRightMargin is only supported on iOS 8.0 or higher.");
  370. layoutAttribute = NSLayoutAttributeRightMargin;
  371. break;
  372. case ALMarginTop:
  373. NSAssert(PL__PureLayout_MinSysVer_iOS_8_0, @"ALEdgeTopMargin is only supported on iOS 8.0 or higher.");
  374. layoutAttribute = NSLayoutAttributeTopMargin;
  375. break;
  376. case ALMarginBottom:
  377. NSAssert(PL__PureLayout_MinSysVer_iOS_8_0, @"ALEdgeBottomMargin is only supported on iOS 8.0 or higher.");
  378. layoutAttribute = NSLayoutAttributeBottomMargin;
  379. break;
  380. case ALMarginLeading:
  381. NSAssert(PL__PureLayout_MinSysVer_iOS_8_0, @"ALEdgeLeadingMargin is only supported on iOS 8.0 or higher.");
  382. layoutAttribute = NSLayoutAttributeLeadingMargin;
  383. break;
  384. case ALMarginTrailing:
  385. NSAssert(PL__PureLayout_MinSysVer_iOS_8_0, @"ALEdgeTrailingMargin is only supported on iOS 8.0 or higher.");
  386. layoutAttribute = NSLayoutAttributeTrailingMargin;
  387. break;
  388. case ALMarginAxisVertical:
  389. NSAssert(PL__PureLayout_MinSysVer_iOS_8_0, @"ALAxisVerticalMargin is only supported on iOS 8.0 or higher.");
  390. layoutAttribute = NSLayoutAttributeCenterXWithinMargins;
  391. break;
  392. case ALMarginAxisHorizontal:
  393. NSAssert(PL__PureLayout_MinSysVer_iOS_8_0, @"ALAxisHorizontalMargin is only supported on iOS 8.0 or higher.");
  394. layoutAttribute = NSLayoutAttributeCenterYWithinMargins;
  395. break;
  396. #endif /* PL__PureLayout_MinBaseSDK_iOS_8_0 */
  397. default:
  398. NSAssert(nil, @"Not a valid ALAttribute.");
  399. break;
  400. }
  401. return layoutAttribute;
  402. }
  403. /**
  404. Returns the corresponding ALLayoutConstraintAxis for the given ALAxis.
  405. @return The constraint axis for the given axis.
  406. */
  407. + (ALLayoutConstraintAxis)al_constraintAxisForAxis:(ALAxis)axis
  408. {
  409. ALLayoutConstraintAxis constraintAxis;
  410. switch (axis) {
  411. case ALAxisVertical:
  412. constraintAxis = ALLayoutConstraintAxisVertical;
  413. break;
  414. case ALAxisHorizontal:
  415. case ALAxisBaseline: // same value as ALAxisLastBaseline
  416. #if PL__PureLayout_MinBaseSDK_iOS_8_0
  417. case ALAxisFirstBaseline:
  418. #endif /* PL__PureLayout_MinBaseSDK_iOS_8_0 */
  419. constraintAxis = ALLayoutConstraintAxisHorizontal;
  420. break;
  421. default:
  422. NSAssert(nil, @"Not a valid ALAxis.");
  423. constraintAxis = ALLayoutConstraintAxisHorizontal; // default to an arbitrary value to satisfy the compiler
  424. break;
  425. }
  426. return constraintAxis;
  427. }
  428. #if PL__PureLayout_MinBaseSDK_iOS_8_0
  429. /**
  430. Returns the corresponding margin for the given edge.
  431. @param edge The edge to convert to the corresponding margin.
  432. @return The margin for the given edge.
  433. */
  434. + (ALMargin)al_marginForEdge:(ALEdge)edge
  435. {
  436. NSAssert(PL__PureLayout_MinSysVer_iOS_8_0, @"Margin attributes are only supported on iOS 8.0 or higher.");
  437. ALMargin margin;
  438. switch (edge) {
  439. case ALEdgeLeft:
  440. margin = ALMarginLeft;
  441. break;
  442. case ALEdgeRight:
  443. margin = ALMarginRight;
  444. break;
  445. case ALEdgeTop:
  446. margin = ALMarginTop;
  447. break;
  448. case ALEdgeBottom:
  449. margin = ALMarginBottom;
  450. break;
  451. case ALEdgeLeading:
  452. margin = ALMarginLeading;
  453. break;
  454. case ALEdgeTrailing:
  455. margin = ALMarginTrailing;
  456. break;
  457. default:
  458. NSAssert(nil, @"Not a valid ALEdge.");
  459. margin = ALMarginLeft; // default to an arbitrary value to satisfy the compiler
  460. break;
  461. }
  462. return margin;
  463. }
  464. /**
  465. Returns the corresponding margin axis for the given axis.
  466. @param axis The axis to convert to the corresponding margin axis.
  467. @return The margin axis for the given axis.
  468. */
  469. + (ALMarginAxis)al_marginAxisForAxis:(ALAxis)axis
  470. {
  471. NSAssert(PL__PureLayout_MinSysVer_iOS_8_0, @"Margin attributes are only supported on iOS 8.0 or higher.");
  472. ALMarginAxis marginAxis;
  473. switch (axis) {
  474. case ALAxisVertical:
  475. marginAxis = ALMarginAxisVertical;
  476. break;
  477. case ALAxisHorizontal:
  478. marginAxis = ALMarginAxisHorizontal;
  479. break;
  480. case ALAxisBaseline:
  481. case ALAxisFirstBaseline:
  482. NSAssert(nil, @"The baseline axis attributes do not have corresponding margin axis attributes.");
  483. marginAxis = ALMarginAxisVertical; // default to an arbitrary value to satisfy the compiler
  484. break;
  485. default:
  486. NSAssert(nil, @"Not a valid ALAxis.");
  487. marginAxis = ALMarginAxisVertical; // default to an arbitrary value to satisfy the compiler
  488. break;
  489. }
  490. return marginAxis;
  491. }
  492. #endif /* PL__PureLayout_MinBaseSDK_iOS_8_0 */
  493. @end