diff --git a/.gitignore b/.gitignore index 87caec8..57eb564 100644 --- a/.gitignore +++ b/.gitignore @@ -14,4 +14,7 @@ DerivedData *.hmap *.ipa *.xcuserstate +*.gcda +*.gcno .DS_Store +.coveralls.yml diff --git a/.slather.yml b/.slather.yml new file mode 100644 index 0000000..d9b2273 --- /dev/null +++ b/.slather.yml @@ -0,0 +1,4 @@ +ci_service: travis_ci +coverage_service: coveralls +xcodeproj: PureLayout/PureLayout.xcodeproj +source_directory: PureLayout/PureLayout diff --git a/.travis.yml b/.travis.yml index 7b92c31..36f9872 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,9 +1,17 @@ sudo: false +osx_image: xcode10 language: objective-c +rvm: + - 2.6.0 xcode_project: PureLayout/PureLayout.xcodeproj -matrix: - include: - - xcode_sdk: iphonesimulator - xcode_scheme: PureLayout_iOS - - xcode_sdk: macosx - xcode_scheme: PureLayout_Mac +before_install: + - rvm install 2.6.0 + - gem install slather --no-document + +script: + - xcodebuild test -project PureLayout/PureLayout.xcodeproj -scheme PureLayout_iOS -destination 'platform=iOS Simulator,name=iPhone X,OS=11.2' + - xcodebuild test -project PureLayout/PureLayout.xcodeproj -scheme PureLayout_iOS -destination 'platform=iOS Simulator,name=iPhone 7,OS=10.2' + - xcodebuild test -project PureLayout/PureLayout.xcodeproj -scheme PureLayout_iOS -destination 'platform=iOS Simulator,name=iPhone 5s,OS=9.0' + - xcodebuild test -project PureLayout/PureLayout.xcodeproj -scheme PureLayout_Mac -destination 'platform=OS X,arch=x86_64' + +after_success: slather diff --git a/Gemfile b/Gemfile new file mode 100644 index 0000000..bea3338 --- /dev/null +++ b/Gemfile @@ -0,0 +1,2 @@ +source 'https://rubygems.org' +gem 'slather' diff --git a/Gemfile.lock b/Gemfile.lock new file mode 100644 index 0000000..427c77f --- /dev/null +++ b/Gemfile.lock @@ -0,0 +1,45 @@ +GEM + remote: https://rubygems.org/ + specs: + CFPropertyList (2.3.6) + activesupport (5.1.5) + concurrent-ruby (~> 1.0, >= 1.0.2) + i18n (~> 0.7) + minitest (~> 5.1) + tzinfo (~> 1.1) + atomos (0.1.2) + claide (1.0.2) + clamp (0.6.5) + colored2 (3.1.2) + concurrent-ruby (1.0.5) + i18n (0.9.5) + concurrent-ruby (~> 1.0) + mini_portile2 (2.3.0) + minitest (5.11.3) + nanaimo (0.2.4) + nokogiri (1.8.2) + mini_portile2 (~> 2.3.0) + slather (2.4.5) + CFPropertyList (~> 2.2) + activesupport (>= 4.0.2) + clamp (~> 0.6) + nokogiri (~> 1.8.2) + xcodeproj (~> 1.4) + thread_safe (0.3.6) + tzinfo (1.2.5) + thread_safe (~> 0.1) + xcodeproj (1.5.7) + CFPropertyList (>= 2.3.3, < 4.0) + atomos (~> 0.1.2) + claide (>= 1.0.2, < 2.0) + colored2 (~> 3.1) + nanaimo (~> 0.2.4) + +PLATFORMS + ruby + +DEPENDENCIES + slather + +BUNDLED WITH + 1.16.1 diff --git a/Images/PureLayout.png b/Images/PureLayout.png index 12ce661..e34c8e3 100644 Binary files a/Images/PureLayout.png and b/Images/PureLayout.png differ diff --git a/Images/XcodeRegexFindReplaceScreenshot.png b/Images/XcodeRegexFindReplaceScreenshot.png new file mode 100644 index 0000000..0d02883 Binary files /dev/null and b/Images/XcodeRegexFindReplaceScreenshot.png differ diff --git a/LICENSE b/LICENSE index ba9ea9e..5396bc0 100755 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ This code is distributed under the terms and conditions of the MIT license. -Copyright (c) 2014 Tyler Fox +Copyright (c) 2014-2015 Tyler Fox Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: diff --git a/Package.swift b/Package.swift new file mode 100644 index 0000000..d386a44 --- /dev/null +++ b/Package.swift @@ -0,0 +1,19 @@ +// swift-tools-version:5.1 + +import PackageDescription + +let package = Package( + name: "PureLayout", + platforms: [.iOS(.v9), .macOS(.v10_10), .tvOS(.v9)], + products: [ + .library( + name: "PureLayout", + targets: ["PureLayout"]) + ], + targets: [ + .target( + name: "PureLayout", + path: "PureLayout/PureLayout", + publicHeadersPath: "include") + ] +) diff --git a/PureLayout.podspec b/PureLayout.podspec index d9620f2..584b9cd 100644 --- a/PureLayout.podspec +++ b/PureLayout.podspec @@ -1,20 +1,19 @@ Pod::Spec.new do |s| - s.name = "PureLayout" - s.version = "2.0.5" - s.homepage = "https://github.com/smileyborg/PureLayout" - s.license = { :type => 'MIT', :file => 'LICENSE' } - s.author = { "Tyler Fox" => "tfox@smileyborg.com" } - s.social_media_url = "https://twitter.com/smileyborg" - s.ios.deployment_target = '6.0' - s.osx.deployment_target = '10.7' - s.source = { :git => "https://github.com/smileyborg/PureLayout.git", :tag => "v2.0.5" } - s.source_files = 'PureLayout/PureLayout' - s.requires_arc = true - s.summary = "The ultimate API for iOS & OS X Auto Layout — impressively simple, immensely powerful. Objective-C and Swift compatible." + s.name = 'PureLayout' + s.version = '3.1.9' + s.homepage = "https://github.com/#{s.name}/#{s.name}" + s.license = { type: 'MIT', file: 'LICENSE' } + s.author = 'Tyler Fox' + s.ios.deployment_target = '9.0' + s.osx.deployment_target = '10.9' + s.tvos.deployment_target = '9.0' + s.source = { git: "#{s.homepage}.git", tag: "v#{s.version}" } + s.source_files = "#{s.name}/#{s.name}", "#{s.name}/#{s.name}/include" + s.summary = 'The ultimate API for iOS & OS X Auto Layout — impressively simple, immensely powerful. Objective-C and Swift compatible.' s.description = <<-DESC - # PureLayout - The ultimate API for iOS & OS X Auto Layout — impressively simple, immensely powerful. PureLayout extends `UIView`/`NSView`, `NSArray`, and `NSLayoutConstraint` with a comprehensive Auto Layout API that is modeled after Apple's own frameworks. PureLayout is an Objective-C library that also works (and looks!) great with Swift using a bridging header. + # PureLayout + The ultimate API for iOS & OS X Auto Layout — impressively simple, immensely powerful. PureLayout extends `UIView`/`NSView`, `NSArray`, and `NSLayoutConstraint` with a comprehensive Auto Layout API that is modeled after Apple's own frameworks. PureLayout is an Objective-C library that also works (and looks!) great with Swift using a bridging header. - Writing Auto Layout code from scratch isn't easy. PureLayout provides a fully capable and developer-friendly interface for Auto Layout. It is designed for clarity and simplicity, and takes inspiration from the AutoLayout UI options available in Interface Builder while delivering far more flexibility. The API is also highly efficient, as it adds only a thin layer of third party code and is engineered for maximum performance. - DESC + Writing Auto Layout code from scratch isn't easy. PureLayout provides a fully capable and developer-friendly interface for Auto Layout. It is designed for clarity and simplicity, and takes inspiration from the AutoLayout UI options available in Interface Builder while delivering far more flexibility. The API is also highly efficient, as it adds only a thin layer of third party code and is engineered for maximum performance. + DESC end diff --git a/PureLayout/3.1.9/PureLayout.podspec b/PureLayout/3.1.9/PureLayout.podspec new file mode 100644 index 0000000..584b9cd --- /dev/null +++ b/PureLayout/3.1.9/PureLayout.podspec @@ -0,0 +1,19 @@ +Pod::Spec.new do |s| + s.name = 'PureLayout' + s.version = '3.1.9' + s.homepage = "https://github.com/#{s.name}/#{s.name}" + s.license = { type: 'MIT', file: 'LICENSE' } + s.author = 'Tyler Fox' + s.ios.deployment_target = '9.0' + s.osx.deployment_target = '10.9' + s.tvos.deployment_target = '9.0' + s.source = { git: "#{s.homepage}.git", tag: "v#{s.version}" } + s.source_files = "#{s.name}/#{s.name}", "#{s.name}/#{s.name}/include" + s.summary = 'The ultimate API for iOS & OS X Auto Layout — impressively simple, immensely powerful. Objective-C and Swift compatible.' + s.description = <<-DESC + # PureLayout + The ultimate API for iOS & OS X Auto Layout — impressively simple, immensely powerful. PureLayout extends `UIView`/`NSView`, `NSArray`, and `NSLayoutConstraint` with a comprehensive Auto Layout API that is modeled after Apple's own frameworks. PureLayout is an Objective-C library that also works (and looks!) great with Swift using a bridging header. + + Writing Auto Layout code from scratch isn't easy. PureLayout provides a fully capable and developer-friendly interface for Auto Layout. It is designed for clarity and simplicity, and takes inspiration from the AutoLayout UI options available in Interface Builder while delivering far more flexibility. The API is also highly efficient, as it adds only a thin layer of third party code and is engineered for maximum performance. + DESC +end diff --git a/PureLayout/Example-Mac/ALMacAppDelegate.h b/PureLayout/Example-Mac/ALMacAppDelegate.h index 3ccc92f..af74698 100644 --- a/PureLayout/Example-Mac/ALMacAppDelegate.h +++ b/PureLayout/Example-Mac/ALMacAppDelegate.h @@ -2,10 +2,12 @@ // ALMacAppDelegate.h // PureLayout Example-Mac // -// Copyright (c) 2014 Tyler Fox -// https://github.com/smileyborg/PureLayout +// Copyright (c) 2014-2015 Tyler Fox +// https://github.com/PureLayout/PureLayout // +#import + @interface ALMacAppDelegate : NSResponder @end diff --git a/PureLayout/Example-Mac/ALMacAppDelegate.m b/PureLayout/Example-Mac/ALMacAppDelegate.m index 1775ca2..41d8ac3 100644 --- a/PureLayout/Example-Mac/ALMacAppDelegate.m +++ b/PureLayout/Example-Mac/ALMacAppDelegate.m @@ -2,8 +2,8 @@ // ALMacAppDelegate.m // PureLayout Example-Mac // -// Copyright (c) 2014 Tyler Fox -// https://github.com/smileyborg/PureLayout +// Copyright (c) 2014-2015 Tyler Fox +// https://github.com/PureLayout/PureLayout // #import "ALMacAppDelegate.h" diff --git a/PureLayout/Example-Mac/ALMacViewController.h b/PureLayout/Example-Mac/ALMacViewController.h index d41ee81..18a4f8f 100644 --- a/PureLayout/Example-Mac/ALMacViewController.h +++ b/PureLayout/Example-Mac/ALMacViewController.h @@ -2,10 +2,12 @@ // ALMacViewController.h // PureLayout Example-Mac // -// Copyright (c) 2014 Tyler Fox -// https://github.com/smileyborg/PureLayout +// Copyright (c) 2014-2015 Tyler Fox +// https://github.com/PureLayout/PureLayout // +#import + @interface ALMacViewController : NSViewController - (void)nextDemo; diff --git a/PureLayout/Example-Mac/ALMacViewController.m b/PureLayout/Example-Mac/ALMacViewController.m index 7e6666c..a1e5357 100644 --- a/PureLayout/Example-Mac/ALMacViewController.m +++ b/PureLayout/Example-Mac/ALMacViewController.m @@ -2,12 +2,12 @@ // ALMacViewController.m // PureLayout Example-Mac // -// Copyright (c) 2014 Tyler Fox -// https://github.com/smileyborg/PureLayout +// Copyright (c) 2014-2015 Tyler Fox +// https://github.com/PureLayout/PureLayout // #import "ALMacViewController.h" -#import "PureLayout.h" +#import typedef NS_ENUM(NSInteger, ExampleConstraintDemo) { ExampleConstraintDemoReset = 0, @@ -164,7 +164,7 @@ - (void)setupDemo4 [view autoPinEdge:ALEdgeTop toEdge:ALEdgeBottom ofView:previousView withOffset:10.0]; // The orange view will be allowed to change its size if it conflicts with a required constraint NSLayoutPriority priority = (view == self.orangeView) ? NSLayoutPriorityDefaultHigh + 1 : NSLayoutPriorityRequired; - [NSView autoSetPriority:priority forConstraints:^{ + [NSLayoutConstraint autoSetPriority:priority forConstraints:^{ [view autoMatchDimension:ALDimensionWidth toDimension:ALDimensionWidth ofView:previousView withMultiplier:1.5]; [view autoMatchDimension:ALDimensionHeight toDimension:ALDimensionHeight ofView:previousView withMultiplier:2.0]; }]; diff --git a/PureLayout/Example-Mac/Example-Mac-Info.plist b/PureLayout/Example-Mac/Example-Mac-Info.plist index 690bd70..ba0e84a 100644 --- a/PureLayout/Example-Mac/Example-Mac-Info.plist +++ b/PureLayout/Example-Mac/Example-Mac-Info.plist @@ -9,7 +9,7 @@ CFBundleIconFile CFBundleIdentifier - com.smileyborg.${PRODUCT_NAME:rfc1034identifier} + $(PRODUCT_BUNDLE_IDENTIFIER) CFBundleInfoDictionaryVersion 6.0 CFBundleName diff --git a/PureLayout/Example-Mac/Example-Mac-Prefix.pch b/PureLayout/Example-Mac/Example-Mac-Prefix.pch deleted file mode 100644 index 02bcfba..0000000 --- a/PureLayout/Example-Mac/Example-Mac-Prefix.pch +++ /dev/null @@ -1,14 +0,0 @@ -// -// Example-Mac-Prefix.pch -// PureLayout Example-Mac -// -// Copyright (c) 2014 Tyler Fox -// https://github.com/smileyborg/PureLayout -// -// Prefix header for all source files of the 'Example-Mac' target in the 'Example' project -// - -#ifdef __OBJC__ - #import - #import -#endif diff --git a/PureLayout/Example-Mac/main.m b/PureLayout/Example-Mac/main.m index 0f8bcde..4403f6b 100644 --- a/PureLayout/Example-Mac/main.m +++ b/PureLayout/Example-Mac/main.m @@ -2,8 +2,8 @@ // main.m // PureLayout Example-Mac // -// Copyright (c) 2014 Tyler Fox -// https://github.com/smileyborg/PureLayout +// Copyright (c) 2014-2015 Tyler Fox +// https://github.com/PureLayout/PureLayout // #import diff --git a/PureLayout/Example-iOS/ALiOSAppDelegate.h b/PureLayout/Example-iOS/ALiOSAppDelegate.h index 500724f..e99a10b 100644 --- a/PureLayout/Example-iOS/ALiOSAppDelegate.h +++ b/PureLayout/Example-iOS/ALiOSAppDelegate.h @@ -2,10 +2,12 @@ // ALiOSAppDelegate.h // PureLayout Example-iOS // -// Copyright (c) 2014 Tyler Fox -// https://github.com/smileyborg/PureLayout +// Copyright (c) 2014-2015 Tyler Fox +// https://github.com/PureLayout/PureLayout // +#import + @interface ALiOSAppDelegate : UIResponder @property (strong, nonatomic) UIWindow *window; diff --git a/PureLayout/Example-iOS/ALiOSAppDelegate.m b/PureLayout/Example-iOS/ALiOSAppDelegate.m index 351fe7c..7dc7716 100644 --- a/PureLayout/Example-iOS/ALiOSAppDelegate.m +++ b/PureLayout/Example-iOS/ALiOSAppDelegate.m @@ -2,8 +2,8 @@ // ALiOSAppDelegate.m // PureLayout Example-iOS // -// Copyright (c) 2014 Tyler Fox -// https://github.com/smileyborg/PureLayout +// Copyright (c) 2014-2015 Tyler Fox +// https://github.com/PureLayout/PureLayout // #import "ALiOSAppDelegate.h" diff --git a/PureLayout/Example-iOS/ALiOSDemoListController.h b/PureLayout/Example-iOS/ALiOSDemoListController.h index 4f47dcc..3399a88 100644 --- a/PureLayout/Example-iOS/ALiOSDemoListController.h +++ b/PureLayout/Example-iOS/ALiOSDemoListController.h @@ -2,8 +2,8 @@ // ALiOSDemoListController.h // PureLayout Example-iOS // -// Copyright (c) 2014 Tyler Fox -// https://github.com/smileyborg/PureLayout +// Copyright (c) 2014-2015 Tyler Fox +// https://github.com/PureLayout/PureLayout // #import diff --git a/PureLayout/Example-iOS/ALiOSDemoListController.m b/PureLayout/Example-iOS/ALiOSDemoListController.m index aba2d14..1457f2a 100644 --- a/PureLayout/Example-iOS/ALiOSDemoListController.m +++ b/PureLayout/Example-iOS/ALiOSDemoListController.m @@ -2,25 +2,69 @@ // ALiOSDemoListController.m // PureLayout Example-iOS // -// Copyright (c) 2014 Tyler Fox -// https://github.com/smileyborg/PureLayout +// Copyright (c) 2014-2015 Tyler Fox +// https://github.com/PureLayout/PureLayout // #import "ALiOSDemoListController.h" +NSString *const kLastUsedDemoTypeUserDefaultsKey = @"PureLayout-iOS-Demos-LastUsedDemoType"; + @interface ALiOSDemoListController () @property (nonatomic, readonly) NSArray *demoTitles; +// Whether to load the Swift (YES) or Objective-C (NO) versions of the demos. +@property (nonatomic, assign) BOOL useSwiftDemos; + @end @implementation ALiOSDemoListController +@synthesize useSwiftDemos = _useSwiftDemos; + +// Recalls and returns the last value of the `useSwiftDemos` flag. ++ (BOOL)recallPreviousUseSwiftDemosValue +{ +#if !USING_XCODE7_SCHEME + return NO; +#endif + + id storedDemoType = [[NSUserDefaults standardUserDefaults] objectForKey:kLastUsedDemoTypeUserDefaultsKey]; + if (storedDemoType) { + NSAssert([storedDemoType isKindOfClass:[NSNumber class]], @"The stored demo type object should be of type NSNumber!"); + return [storedDemoType boolValue]; + } + + // Use the Swift demos by default, if there is no persisted value. + return YES; +} + +- (BOOL)useSwiftDemos +{ +#if !USING_XCODE7_SCHEME + return NO; +#endif + + return _useSwiftDemos; +} + - (void)viewDidLoad { [super viewDidLoad]; self.title = @"PureLayout iOS Demos"; + + self.useSwiftDemos = [[self class] recallPreviousUseSwiftDemosValue]; +} + +- (void)setUseSwiftDemos:(BOOL)useSwiftDemos +{ + _useSwiftDemos = useSwiftDemos; + + // When changing between the Swift and Objective-C demos, persist the last used language type so that the demo app always opens back up to it. + [[NSUserDefaults standardUserDefaults] setObject:@(self.useSwiftDemos) forKey:kLastUsedDemoTypeUserDefaultsKey]; + [[NSUserDefaults standardUserDefaults] synchronize]; } - (NSArray *)demoTitles @@ -35,44 +79,97 @@ - (NSArray *)demoTitles @"Animating Constraints", // Demo 7 @"Constraint Identifiers (iOS 7.0+)", // Demo 8 @"Layout Margins (iOS 8.0+)", // Demo 9 - @"Constraints Without Installing" // Demo 10 + @"Constraints Without Installing", // Demo 10 + @"Basic UIScrollView" // Demo 11 ]; } -- (NSString *)textForDemoAtIndexPath:(NSIndexPath *)indexPath +- (NSString *)textForDemoAtIndex:(NSUInteger)index { - NSString *text = self.demoTitles[indexPath.row]; - text = [NSString stringWithFormat:@"%@. %@", @(indexPath.row + 1), text]; + NSString *text = self.demoTitles[index]; + text = [NSString stringWithFormat:@"%@. %@", @(index + 1), text]; return text; } - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView { - return 1; + return 2; } - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { - return self.demoTitles.count; + if (section == 0) { + return 1; + } else { + return self.demoTitles.count; + } +} + +- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section +{ + if (section == 0) { + return nil; + } else { + NSString *language = self.useSwiftDemos ? @"Swift" : @"Objective-C"; + return [NSString stringWithFormat:@"%@ Demos", language]; + } } - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { UITableViewCell *cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:nil]; // not bothering to reuse cells here - cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator; - cell.textLabel.text = [self textForDemoAtIndexPath:indexPath]; + NSString *text; + if (indexPath.section == 0) { + // The very first section is the option to switch between Objective-C and Swift demo files. +#if USING_XCODE7_SCHEME + cell.textLabel.textColor = [UIColor blueColor]; + cell.textLabel.font = [UIFont preferredFontForTextStyle:UIFontTextStyleHeadline]; + NSString *language = self.useSwiftDemos ? @"Objective-C" : @"Swift"; + text = [NSString stringWithFormat:@"Switch to %@ demo files", language]; +#else + cell.textLabel.font = [UIFont preferredFontForTextStyle:UIFontTextStyleFootnote]; + text = @"Use Example-iOS-Xcode7 scheme to run Swift demos."; +#endif + } else { + // All other rows take you to the actual demos. + cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator; + text = [self textForDemoAtIndex:indexPath.row]; + } + cell.textLabel.text = text; return cell; } - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { - NSString *viewControllerClassName = [NSString stringWithFormat:@"ALiOSDemo%@ViewController", @(indexPath.row + 1)]; + if (indexPath.section == 0) { + // The very first section is the option to switch between Objective-C and Swift demo files. +#if USING_XCODE7_SCHEME + self.useSwiftDemos = !self.useSwiftDemos; + [tableView reloadRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationFade]; + [tableView reloadSections:[NSIndexSet indexSetWithIndex:1] withRowAnimation:UITableViewRowAnimationRight]; +#else + [tableView deselectRowAtIndexPath:indexPath animated:YES]; +#endif + } else { + // All other rows take you to the actual demos. + [self displayDemoAtIndex:indexPath.row]; + } +} + +- (void)displayDemoAtIndex:(NSUInteger)index +{ + NSString *viewControllerClassName; + if (self.useSwiftDemos) { + viewControllerClassName = [NSString stringWithFormat:@"iOSDemo%@ViewController", @(index + 1)]; + } else { + viewControllerClassName = [NSString stringWithFormat:@"ALiOSDemo%@ViewController", @(index + 1)]; + } Class viewControllerKlass = NSClassFromString(viewControllerClassName); NSAssert(viewControllerKlass, @"Class should not be nil!"); NSAssert([viewControllerKlass isSubclassOfClass:[UIViewController class]], @"Class should be a view controller!"); UIViewController *demoViewController = [[viewControllerKlass alloc] initWithNibName:nil bundle:nil]; if (demoViewController) { - demoViewController.title = [self textForDemoAtIndexPath:indexPath]; + demoViewController.title = [self textForDemoAtIndex:index]; [self.navigationController pushViewController:demoViewController animated:YES]; } } diff --git a/PureLayout/Example-iOS/Demos/ALiOSDemo10ViewController.h b/PureLayout/Example-iOS/Demos/ALiOSDemo10ViewController.h index 3dd8d53..7465c44 100644 --- a/PureLayout/Example-iOS/Demos/ALiOSDemo10ViewController.h +++ b/PureLayout/Example-iOS/Demos/ALiOSDemo10ViewController.h @@ -2,8 +2,8 @@ // ALiOSDemo10ViewController.h // PureLayout Example-iOS // -// Copyright (c) 2014 Tyler Fox -// https://github.com/smileyborg/PureLayout +// Copyright (c) 2014-2015 Tyler Fox +// https://github.com/PureLayout/PureLayout // #import diff --git a/PureLayout/Example-iOS/Demos/ALiOSDemo10ViewController.m b/PureLayout/Example-iOS/Demos/ALiOSDemo10ViewController.m index 37e5519..7a444aa 100644 --- a/PureLayout/Example-iOS/Demos/ALiOSDemo10ViewController.m +++ b/PureLayout/Example-iOS/Demos/ALiOSDemo10ViewController.m @@ -2,12 +2,12 @@ // ALiOSDemo10ViewController.m // PureLayout Example-iOS // -// Copyright (c) 2014 Tyler Fox -// https://github.com/smileyborg/PureLayout +// Copyright (c) 2014-2015 Tyler Fox +// https://github.com/PureLayout/PureLayout // #import "ALiOSDemo10ViewController.h" -#import "PureLayout.h" +#import @interface ALiOSDemo10ViewController () @@ -48,24 +48,26 @@ - (void)updateViewConstraints if (!self.didSetupConstraints) { NSArray *views = @[self.redView, self.blueView, self.yellowView, self.greenView]; - // Create the constraints that define the horizontal layout, but don't install any of them - just store them for now - self.horizontalLayoutConstraints = [UIView autoCreateConstraintsWithoutInstalling:^{ + // Start out in the horizontal layout + self.isShowingHorizontalLayout = YES; + + // Create and install the constraints that define the horizontal layout, because this is the one we're starting in. + // Note that we use autoCreateAndInstallConstraints() here in order to easily collect all the constraints into a single array. + self.horizontalLayoutConstraints = [NSLayoutConstraint autoCreateAndInstallConstraints:^{ [views autoSetViewsDimension:ALDimensionHeight toSize:40.0]; [views autoDistributeViewsAlongAxis:ALAxisHorizontal alignedTo:ALAttributeHorizontal withFixedSpacing:10.0 insetSpacing:YES matchedSizes:YES]; [self.redView autoAlignAxisToSuperviewAxis:ALAxisHorizontal]; }]; - // Create the constraints that define the vertical layout, but don't install any of them - just store them for now - self.verticalLayoutConstraints = [UIView autoCreateConstraintsWithoutInstalling:^{ + // Create the constraints that define the vertical layout, but don't install any of them - just store them for now. + // Note that we use autoCreateConstraintsWithoutInstalling() here in order to both prevent the constraints from being installed automatically, + // and to easily collect all the constraints into a single array. + self.verticalLayoutConstraints = [NSLayoutConstraint autoCreateConstraintsWithoutInstalling:^{ [views autoSetViewsDimension:ALDimensionWidth toSize:60.0]; [views autoDistributeViewsAlongAxis:ALAxisVertical alignedTo:ALAttributeVertical withFixedSpacing:70.0 insetSpacing:YES matchedSizes:YES]; [self.redView autoAlignAxisToSuperviewAxis:ALAxisVertical]; }]; - // Start out in the horizontal layout - self.isShowingHorizontalLayout = YES; - [self.horizontalLayoutConstraints autoInstallConstraints]; - [self.toggleConstraintsButton autoPinEdgeToSuperviewEdge:ALEdgeBottom withInset:10.0]; [self.toggleConstraintsButton autoAlignAxisToSuperviewAxis:ALAxisVertical]; diff --git a/PureLayout/Example-iOS/Demos/ALiOSDemo11ViewController.h b/PureLayout/Example-iOS/Demos/ALiOSDemo11ViewController.h new file mode 100644 index 0000000..a560799 --- /dev/null +++ b/PureLayout/Example-iOS/Demos/ALiOSDemo11ViewController.h @@ -0,0 +1,13 @@ +// +// ALiOSDemo11ViewController.h +// PureLayout Example-iOS +// +// Copyright (c) 2014-2015 Spiros Gerokostas +// https://github.com/PureLayout/PureLayout +// + +#import + +@interface ALiOSDemo11ViewController : UIViewController + +@end diff --git a/PureLayout/Example-iOS/Demos/ALiOSDemo11ViewController.m b/PureLayout/Example-iOS/Demos/ALiOSDemo11ViewController.m new file mode 100644 index 0000000..a248408 --- /dev/null +++ b/PureLayout/Example-iOS/Demos/ALiOSDemo11ViewController.m @@ -0,0 +1,88 @@ +// +// ALiOSDemo11ViewController.m +// PureLayout Example-iOS +// +// Copyright (c) 2014-2015 Spiros Gerokostas +// https://github.com/PureLayout/PureLayout +// + +#import "ALiOSDemo11ViewController.h" +#import + +@interface ALiOSDemo11ViewController () + +@property (nonatomic, strong) UILabel *blueLabel; +@property (nonatomic, strong) UIScrollView *scrollView; +@property (nonatomic, strong) UIView *contentView; + +@property (nonatomic, assign) BOOL didSetupConstraints; + +@end + +@implementation ALiOSDemo11ViewController + +- (void)loadView +{ + self.view = [UIView new]; + self.view.backgroundColor = [UIColor colorWithWhite:0.1 alpha:1.0]; + + [self.view addSubview:self.scrollView]; + [self.scrollView addSubview:self.contentView]; + [self.contentView addSubview:self.blueLabel]; + + [self.view setNeedsUpdateConstraints]; // bootstrap Auto Layout +} + +- (void)updateViewConstraints +{ + if (!self.didSetupConstraints) { + + if (@available(iOS 9.0, *)) { + [self.scrollView autoPinEdgesToSuperviewSafeAreaWithInsets:UIEdgeInsetsZero]; + } else { + [self.scrollView autoPinEdgesToSuperviewEdgesWithInsets:UIEdgeInsetsZero]; + } + [self.contentView autoPinEdgesToSuperviewEdgesWithInsets:UIEdgeInsetsZero]; + [self.contentView autoMatchDimension:ALDimensionWidth toDimension:ALDimensionWidth ofView:self.view]; + + [self.blueLabel autoPinEdgeToSuperviewEdge:ALEdgeTop withInset:20.0f]; + [self.blueLabel autoPinEdgeToSuperviewEdge:ALEdgeLeading withInset:20.0f]; + [self.blueLabel autoPinEdgeToSuperviewEdge:ALEdgeTrailing withInset:20.0f]; + [self.blueLabel autoPinEdgeToSuperviewEdge:ALEdgeBottom withInset:20.0f]; + + self.didSetupConstraints = YES; + } + + [super updateViewConstraints]; +} + +- (UIScrollView *)scrollView +{ + if (!_scrollView) { + _scrollView = [UIScrollView newAutoLayoutView]; + } + return _scrollView; +} + +- (UIView *)contentView +{ + if (!_contentView) { + _contentView = [UIView newAutoLayoutView]; + } + return _contentView; +} + +- (UILabel *)blueLabel +{ + if (!_blueLabel) { + _blueLabel = [UILabel newAutoLayoutView]; + _blueLabel.numberOfLines = 0; + _blueLabel.lineBreakMode = NSLineBreakByClipping; + _blueLabel.backgroundColor = [UIColor blueColor]; + _blueLabel.textColor = [UIColor whiteColor]; + _blueLabel.text = NSLocalizedString(@"Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum", nil); + } + return _blueLabel; +} + +@end diff --git a/PureLayout/Example-iOS/Demos/ALiOSDemo1ViewController.h b/PureLayout/Example-iOS/Demos/ALiOSDemo1ViewController.h index 6817e78..903813a 100644 --- a/PureLayout/Example-iOS/Demos/ALiOSDemo1ViewController.h +++ b/PureLayout/Example-iOS/Demos/ALiOSDemo1ViewController.h @@ -2,8 +2,8 @@ // ALiOSDemo1ViewController.h // PureLayout Example-iOS // -// Copyright (c) 2014 Tyler Fox -// https://github.com/smileyborg/PureLayout +// Copyright (c) 2014-2015 Tyler Fox +// https://github.com/PureLayout/PureLayout // #import diff --git a/PureLayout/Example-iOS/Demos/ALiOSDemo1ViewController.m b/PureLayout/Example-iOS/Demos/ALiOSDemo1ViewController.m index 6d80260..f5f67e6 100644 --- a/PureLayout/Example-iOS/Demos/ALiOSDemo1ViewController.m +++ b/PureLayout/Example-iOS/Demos/ALiOSDemo1ViewController.m @@ -2,12 +2,12 @@ // ALiOSDemo1ViewController.m // PureLayout Example-iOS // -// Copyright (c) 2014 Tyler Fox -// https://github.com/smileyborg/PureLayout +// Copyright (c) 2014-2015 Tyler Fox +// https://github.com/PureLayout/PureLayout // #import "ALiOSDemo1ViewController.h" -#import "PureLayout.h" +#import @interface ALiOSDemo1ViewController () diff --git a/PureLayout/Example-iOS/Demos/ALiOSDemo2ViewController.h b/PureLayout/Example-iOS/Demos/ALiOSDemo2ViewController.h index ce0ea5b..0a0b8c9 100644 --- a/PureLayout/Example-iOS/Demos/ALiOSDemo2ViewController.h +++ b/PureLayout/Example-iOS/Demos/ALiOSDemo2ViewController.h @@ -2,8 +2,8 @@ // ALiOSDemo2ViewController.h // PureLayout Example-iOS // -// Copyright (c) 2014 Tyler Fox -// https://github.com/smileyborg/PureLayout +// Copyright (c) 2014-2015 Tyler Fox +// https://github.com/PureLayout/PureLayout // #import diff --git a/PureLayout/Example-iOS/Demos/ALiOSDemo2ViewController.m b/PureLayout/Example-iOS/Demos/ALiOSDemo2ViewController.m index 797c075..6fb5527 100644 --- a/PureLayout/Example-iOS/Demos/ALiOSDemo2ViewController.m +++ b/PureLayout/Example-iOS/Demos/ALiOSDemo2ViewController.m @@ -2,12 +2,12 @@ // ALiOSDemo2ViewController.m // PureLayout Example-iOS // -// Copyright (c) 2014 Tyler Fox -// https://github.com/smileyborg/PureLayout +// Copyright (c) 2014-2015 Tyler Fox +// https://github.com/PureLayout/PureLayout // #import "ALiOSDemo2ViewController.h" -#import "PureLayout.h" +#import @interface ALiOSDemo2ViewController () diff --git a/PureLayout/Example-iOS/Demos/ALiOSDemo3ViewController.h b/PureLayout/Example-iOS/Demos/ALiOSDemo3ViewController.h index c857929..caf5a70 100644 --- a/PureLayout/Example-iOS/Demos/ALiOSDemo3ViewController.h +++ b/PureLayout/Example-iOS/Demos/ALiOSDemo3ViewController.h @@ -2,8 +2,8 @@ // ALiOSDemo3ViewController.h // PureLayout Example-iOS // -// Copyright (c) 2014 Tyler Fox -// https://github.com/smileyborg/PureLayout +// Copyright (c) 2014-2015 Tyler Fox +// https://github.com/PureLayout/PureLayout // #import diff --git a/PureLayout/Example-iOS/Demos/ALiOSDemo3ViewController.m b/PureLayout/Example-iOS/Demos/ALiOSDemo3ViewController.m index 542cda1..79924cf 100644 --- a/PureLayout/Example-iOS/Demos/ALiOSDemo3ViewController.m +++ b/PureLayout/Example-iOS/Demos/ALiOSDemo3ViewController.m @@ -2,12 +2,12 @@ // ALiOSDemo3ViewController.m // PureLayout Example-iOS // -// Copyright (c) 2014 Tyler Fox -// https://github.com/smileyborg/PureLayout +// Copyright (c) 2014-2015 Tyler Fox +// https://github.com/PureLayout/PureLayout // #import "ALiOSDemo3ViewController.h" -#import "PureLayout.h" +#import @interface ALiOSDemo3ViewController () diff --git a/PureLayout/Example-iOS/Demos/ALiOSDemo4ViewController.h b/PureLayout/Example-iOS/Demos/ALiOSDemo4ViewController.h index d8359a4..ae817b9 100644 --- a/PureLayout/Example-iOS/Demos/ALiOSDemo4ViewController.h +++ b/PureLayout/Example-iOS/Demos/ALiOSDemo4ViewController.h @@ -2,8 +2,8 @@ // ALiOSDemo4ViewController.h // PureLayout Example-iOS // -// Copyright (c) 2014 Tyler Fox -// https://github.com/smileyborg/PureLayout +// Copyright (c) 2014-2015 Tyler Fox +// https://github.com/PureLayout/PureLayout // #import diff --git a/PureLayout/Example-iOS/Demos/ALiOSDemo4ViewController.m b/PureLayout/Example-iOS/Demos/ALiOSDemo4ViewController.m index 66df991..5b56cff 100644 --- a/PureLayout/Example-iOS/Demos/ALiOSDemo4ViewController.m +++ b/PureLayout/Example-iOS/Demos/ALiOSDemo4ViewController.m @@ -2,12 +2,12 @@ // ALiOSDemo4ViewController.m // PureLayout Example-iOS // -// Copyright (c) 2014 Tyler Fox -// https://github.com/smileyborg/PureLayout +// Copyright (c) 2014-2015 Tyler Fox +// https://github.com/PureLayout/PureLayout // #import "ALiOSDemo4ViewController.h" -#import "PureLayout.h" +#import @interface ALiOSDemo4ViewController () @@ -64,9 +64,8 @@ - (void)updateViewConstraints [self.redLabel autoPinEdgeToSuperviewEdge:ALEdgeLeading withInset:kSmallPadding]; [self.redLabel autoPinEdgeToSuperviewEdge:ALEdgeBottom withInset:kLargePadding]; - [self.greenView autoPinEdge:ALEdgeLeading toEdge:ALEdgeTrailing ofView:self.redLabel withOffset:kLargePadding]; - // The greenView is positioned below the blueLabel, with its leading edge to the redLabel, and trailing edge to its superview + [self.greenView autoPinEdge:ALEdgeLeading toEdge:ALEdgeTrailing ofView:self.redLabel withOffset:kLargePadding]; [self.greenView autoPinEdge:ALEdgeTop toEdge:ALEdgeBottom ofView:self.blueLabel withOffset:kSmallPadding]; [self.greenView autoPinEdgeToSuperviewEdge:ALEdgeTrailing withInset:kSmallPadding]; diff --git a/PureLayout/Example-iOS/Demos/ALiOSDemo5ViewController.h b/PureLayout/Example-iOS/Demos/ALiOSDemo5ViewController.h index 05c0a9d..f18ceea 100644 --- a/PureLayout/Example-iOS/Demos/ALiOSDemo5ViewController.h +++ b/PureLayout/Example-iOS/Demos/ALiOSDemo5ViewController.h @@ -2,8 +2,8 @@ // ALiOSDemo5ViewController.h // PureLayout Example-iOS // -// Copyright (c) 2014 Tyler Fox -// https://github.com/smileyborg/PureLayout +// Copyright (c) 2014-2015 Tyler Fox +// https://github.com/PureLayout/PureLayout // #import diff --git a/PureLayout/Example-iOS/Demos/ALiOSDemo5ViewController.m b/PureLayout/Example-iOS/Demos/ALiOSDemo5ViewController.m index 3ba9a90..f20b936 100644 --- a/PureLayout/Example-iOS/Demos/ALiOSDemo5ViewController.m +++ b/PureLayout/Example-iOS/Demos/ALiOSDemo5ViewController.m @@ -2,12 +2,12 @@ // ALiOSDemo5ViewController.m // PureLayout Example-iOS // -// Copyright (c) 2014 Tyler Fox -// https://github.com/smileyborg/PureLayout +// Copyright (c) 2014-2015 Tyler Fox +// https://github.com/PureLayout/PureLayout // #import "ALiOSDemo5ViewController.h" -#import "PureLayout.h" +#import @interface ALiOSDemo5ViewController () diff --git a/PureLayout/Example-iOS/Demos/ALiOSDemo6ViewController.h b/PureLayout/Example-iOS/Demos/ALiOSDemo6ViewController.h index e7a9ce5..7d7480f 100644 --- a/PureLayout/Example-iOS/Demos/ALiOSDemo6ViewController.h +++ b/PureLayout/Example-iOS/Demos/ALiOSDemo6ViewController.h @@ -2,8 +2,8 @@ // ALiOSDemo6ViewController.h // PureLayout Example-iOS // -// Copyright (c) 2014 Tyler Fox -// https://github.com/smileyborg/PureLayout +// Copyright (c) 2014-2015 Tyler Fox +// https://github.com/PureLayout/PureLayout // #import diff --git a/PureLayout/Example-iOS/Demos/ALiOSDemo6ViewController.m b/PureLayout/Example-iOS/Demos/ALiOSDemo6ViewController.m index f9e4e6f..a578187 100644 --- a/PureLayout/Example-iOS/Demos/ALiOSDemo6ViewController.m +++ b/PureLayout/Example-iOS/Demos/ALiOSDemo6ViewController.m @@ -2,12 +2,12 @@ // ALiOSDemo6ViewController.m // PureLayout Example-iOS // -// Copyright (c) 2014 Tyler Fox -// https://github.com/smileyborg/PureLayout +// Copyright (c) 2014-2015 Tyler Fox +// https://github.com/PureLayout/PureLayout // #import "ALiOSDemo6ViewController.h" -#import "PureLayout.h" +#import @interface ALiOSDemo6ViewController () @@ -45,7 +45,7 @@ - (void)updateViewConstraints // Add constraints that set the size of the blueView to a ridiculously large size, but set the priority of these constraints // to a lower value than Required. This allows the Auto Layout solver to let these constraints be broken if one or both of // them conflict with higher-priority constraint(s), such as the above 4 edge constraints. - [UIView autoSetPriority:UILayoutPriorityDefaultHigh forConstraints:^{ + [NSLayoutConstraint autoSetPriority:UILayoutPriorityDefaultHigh forConstraints:^{ [self.blueView autoSetDimensionsToSize:CGSizeMake(10000.0, 10000.0)]; }]; diff --git a/PureLayout/Example-iOS/Demos/ALiOSDemo7ViewController.h b/PureLayout/Example-iOS/Demos/ALiOSDemo7ViewController.h index dca999c..46e0461 100644 --- a/PureLayout/Example-iOS/Demos/ALiOSDemo7ViewController.h +++ b/PureLayout/Example-iOS/Demos/ALiOSDemo7ViewController.h @@ -2,8 +2,8 @@ // ALiOSDemo7ViewController.h // PureLayout Example-iOS // -// Copyright (c) 2014 Tyler Fox -// https://github.com/smileyborg/PureLayout +// Copyright (c) 2014-2015 Tyler Fox +// https://github.com/PureLayout/PureLayout // #import diff --git a/PureLayout/Example-iOS/Demos/ALiOSDemo7ViewController.m b/PureLayout/Example-iOS/Demos/ALiOSDemo7ViewController.m index 42f2dc6..ecd7147 100644 --- a/PureLayout/Example-iOS/Demos/ALiOSDemo7ViewController.m +++ b/PureLayout/Example-iOS/Demos/ALiOSDemo7ViewController.m @@ -2,12 +2,12 @@ // ALiOSDemo7ViewController.m // PureLayout Example-iOS // -// Copyright (c) 2014 Tyler Fox -// https://github.com/smileyborg/PureLayout +// Copyright (c) 2014-2015 Tyler Fox +// https://github.com/PureLayout/PureLayout // #import "ALiOSDemo7ViewController.h" -#import "PureLayout.h" +#import @interface ALiOSDemo7ViewController () @@ -110,7 +110,7 @@ - (void)animateLayoutWithSpringAnimation completion:^(BOOL finished) { // Run the animation again in the other direction self.isAnimatingToEndState = !self.isAnimatingToEndState; - if (self.navigationController) { // this will be nil if this view controller is no longer in the navigation stack + if (self.navigationController) { // this will be nil if this view controller is no longer in the navigation stack (stops animation when this view controller is no longer onscreen) [self animateLayoutWithSpringAnimation]; } }]; @@ -134,7 +134,7 @@ - (void)animateLayoutWithRegularAnimation completion:^(BOOL finished) { // Run the animation again in the other direction self.isAnimatingToEndState = !self.isAnimatingToEndState; - if (self.navigationController) { // this will be nil if this view controller is no longer in the navigation stack + if (self.navigationController) { // this will be nil if this view controller is no longer in the navigation stack (stops animation when this view controller is no longer onscreen) [self animateLayoutWithRegularAnimation]; } }]; diff --git a/PureLayout/Example-iOS/Demos/ALiOSDemo8ViewController.h b/PureLayout/Example-iOS/Demos/ALiOSDemo8ViewController.h index 23bd7ac..dcd5374 100644 --- a/PureLayout/Example-iOS/Demos/ALiOSDemo8ViewController.h +++ b/PureLayout/Example-iOS/Demos/ALiOSDemo8ViewController.h @@ -2,8 +2,8 @@ // ALiOSDemo8ViewController.h // PureLayout Example-iOS // -// Copyright (c) 2014 Tyler Fox -// https://github.com/smileyborg/PureLayout +// Copyright (c) 2014-2015 Tyler Fox +// https://github.com/PureLayout/PureLayout // #import diff --git a/PureLayout/Example-iOS/Demos/ALiOSDemo8ViewController.m b/PureLayout/Example-iOS/Demos/ALiOSDemo8ViewController.m index c40bbaf..d3b28ac 100644 --- a/PureLayout/Example-iOS/Demos/ALiOSDemo8ViewController.m +++ b/PureLayout/Example-iOS/Demos/ALiOSDemo8ViewController.m @@ -2,12 +2,12 @@ // ALiOSDemo8ViewController.m // PureLayout Example-iOS // -// Copyright (c) 2014 Tyler Fox -// https://github.com/smileyborg/PureLayout +// Copyright (c) 2014-2015 Tyler Fox +// https://github.com/PureLayout/PureLayout // #import "ALiOSDemo8ViewController.h" -#import "PureLayout.h" +#import @interface ALiOSDemo8ViewController () @@ -47,7 +47,7 @@ - (void)updateViewConstraints it will raise an exception, and you will see these identifiers show up next to the constraint in the console. */ - [UIView autoSetIdentifier:@"Pin Container View Edges" forConstraints:^{ + [NSLayoutConstraint autoSetIdentifier:@"Pin Container View Edges" forConstraints:^{ [self.containerView autoPinToTopLayoutGuideOfViewController:self withInset:10.0]; [self.containerView autoPinEdgesToSuperviewEdgesWithInsets:UIEdgeInsetsMake(0.0, 10.0, 10.0, 10.0) excludingEdge:ALEdgeTop]; }]; @@ -69,12 +69,12 @@ This lets you chain the identifier call right after creating the constraint(s), /** Now, let's add some 'bad' constraints that conflict with one or more of the 'good' constraints above. - Start by uncommenting one of the below constraints, and running the demo. A a constraint exception will be logged + Start by uncommenting one of the below constraints, and running the demo. A constraint exception will be logged to the console, because one or more views was over-constrained, and therefore one or more constraints had to be broken. But because we have provided human-readable identifiers, notice how easy it is to figure out which constraints are conflicting, and which constraint shouldn't be there! */ - [UIView autoSetIdentifier:@"Bad Constraints That Break Things" forConstraints:^{ + [NSLayoutConstraint autoSetIdentifier:@"Bad Constraints That Break Things" forConstraints:^{ // [self.redView autoAlignAxis:ALAxisVertical toSameAxisOfView:self.view withOffset:5.0]; // uncomment me and watch things blow up! // [self.redView autoPinEdgeToSuperviewEdge:ALEdgeLeft]; // uncomment me and watch things blow up! diff --git a/PureLayout/Example-iOS/Demos/ALiOSDemo9ViewController.h b/PureLayout/Example-iOS/Demos/ALiOSDemo9ViewController.h index ed2d3c3..935a254 100644 --- a/PureLayout/Example-iOS/Demos/ALiOSDemo9ViewController.h +++ b/PureLayout/Example-iOS/Demos/ALiOSDemo9ViewController.h @@ -2,8 +2,8 @@ // ALiOSDemo9ViewController.h // PureLayout Example-iOS // -// Copyright (c) 2014 Tyler Fox -// https://github.com/smileyborg/PureLayout +// Copyright (c) 2014-2015 Tyler Fox +// https://github.com/PureLayout/PureLayout // #import diff --git a/PureLayout/Example-iOS/Demos/ALiOSDemo9ViewController.m b/PureLayout/Example-iOS/Demos/ALiOSDemo9ViewController.m index 37da379..5601fea 100644 --- a/PureLayout/Example-iOS/Demos/ALiOSDemo9ViewController.m +++ b/PureLayout/Example-iOS/Demos/ALiOSDemo9ViewController.m @@ -2,12 +2,12 @@ // ALiOSDemo9ViewController.m // PureLayout Example-iOS // -// Copyright (c) 2014 Tyler Fox -// https://github.com/smileyborg/PureLayout +// Copyright (c) 2014-2015 Tyler Fox +// https://github.com/PureLayout/PureLayout // #import "ALiOSDemo9ViewController.h" -#import "PureLayout.h" +#import @interface ALiOSDemo9ViewController () @@ -38,9 +38,9 @@ - (void)loadView - (void)updateViewConstraints { if (!self.didSetupConstraints) { - NSAssert(__PureLayout_MinSysVer_iOS_8_0, @"This demo requires iOS 8.0 or higher to run."); + NSAssert(PL__PureLayout_MinSysVer_iOS_8_0, @"This demo requires iOS 8.0 or higher to run."); - // Before layoutMargins, this is a typical method of giving a subview some padding from its superview edges + // Before layout margins were introduced, this is a typical way of giving a subview some padding from its superview's edges [self.blueView autoPinToTopLayoutGuideOfViewController:self withInset:10.0]; [self.blueView autoPinEdgesToSuperviewEdgesWithInsets:UIEdgeInsetsMake(0, 10.0, 10.0, 10.0) excludingEdge:ALEdgeTop]; @@ -55,7 +55,7 @@ - (void)updateViewConstraints [self.yellowView autoPinEdgeToSuperviewMargin:ALEdgeLeft]; [self.yellowView autoPinEdgeToSuperviewMargin:ALEdgeRight]; - // By aligning the yellowView to its superview's horiztonal margin axis, the yellowView will be positioned with its horizontal axis + // By aligning the yellowView to its superview's horizontal margin axis, the yellowView will be positioned with its horizontal axis // in the middle of the redView's top and bottom margins (causing it to be slightly closer to the top of the redView, since the // redView has a much larger bottom margin than top margin). [self.yellowView autoAlignAxisToSuperviewMarginAxis:ALAxisHorizontal]; diff --git a/PureLayout/Example-iOS/Demos/iOSDemo10ViewController.swift b/PureLayout/Example-iOS/Demos/iOSDemo10ViewController.swift new file mode 100644 index 0000000..9a3f6bb --- /dev/null +++ b/PureLayout/Example-iOS/Demos/iOSDemo10ViewController.swift @@ -0,0 +1,118 @@ +// +// iOSDemo10ViewController.swift +// PureLayout Example-iOS +// +// Copyright (c) 2015 Tyler Fox +// https://github.com/PureLayout/PureLayout +// + +import UIKit +import PureLayout + +@objc(iOSDemo10ViewController) +class iOSDemo10ViewController: UIViewController { + + let blueView: UIView = { + let view = UIView.newAutoLayout() + view.backgroundColor = .blue + return view + }() + let redView: UIView = { + let view = UIView.newAutoLayout() + view.backgroundColor = .red + return view + }() + let yellowView: UIView = { + let view = UIView.newAutoLayout() + view.backgroundColor = .yellow + return view + }() + let greenView: UIView = { + let view = UIView.newAutoLayout() + view.backgroundColor = .green + return view + }() + let toggleConstraintsButton: UIButton = { + let button = UIButton.newAutoLayout() + button.setTitle("Toggle Constraints", for: UIControlState()) + button.setTitleColor(.white, for: UIControlState()) + button.setTitleColor(.gray, for: .highlighted) + return button + }() + + var didSetupConstraints = false + + // Flag that we use to know which layout we're currently in. We start with the horizontal layout. + var isHorizontalLayoutActive = true + + // Properties to store the constraints for each of the two layouts. Only one set of these will be installed at any given time. + var horizontalLayoutConstraints: NSArray? + var verticalLayoutConstraints: NSArray? + + override func loadView() { + view = UIView() + view.backgroundColor = UIColor(white: 0.1, alpha: 1.0) + + view.addSubview(blueView) + view.addSubview(redView) + view.addSubview(yellowView) + view.addSubview(greenView) + + view.addSubview(toggleConstraintsButton) + toggleConstraintsButton.addTarget(self, action: #selector(iOSDemo10ViewController.toggleConstraints(_:)), for: .touchUpInside) + + view.setNeedsUpdateConstraints() // bootstrap Auto Layout + } + + override func updateViewConstraints() { + if (!didSetupConstraints) { + let views: NSArray = [redView, blueView, yellowView, greenView] + + // Create and install the constraints that define the horizontal layout, because this is the one we're starting in. + // Note that we use autoCreateAndInstallConstraints() here in order to easily collect all the constraints into a single array. + horizontalLayoutConstraints = NSLayoutConstraint.autoCreateAndInstallConstraints { + views.autoSetViewsDimension(.height, toSize: 40.0) + views.autoDistributeViews(along: .horizontal, alignedTo: .horizontal, withFixedSpacing: 10.0, insetSpacing: true, matchedSizes: true) + self.redView.autoAlignAxis(toSuperviewAxis: .horizontal) + } as NSArray? + + // Create the constraints that define the vertical layout, but don't install any of them - just store them for now. + // Note that we use autoCreateConstraintsWithoutInstalling() here in order to both prevent the constraints from being installed automatically, + // and to easily collect all the constraints into a single array. + verticalLayoutConstraints = NSLayoutConstraint.autoCreateConstraintsWithoutInstalling { + views.autoSetViewsDimension(.width, toSize: 60.0) + views.autoDistributeViews(along: .vertical, alignedTo: .vertical, withFixedSpacing: 70.0, insetSpacing: true, matchedSizes: true) + self.redView.autoAlignAxis(toSuperviewAxis: .vertical) + } as NSArray? + + toggleConstraintsButton.autoPinEdge(toSuperviewEdge: .bottom, withInset: 10.0) + toggleConstraintsButton.autoAlignAxis(toSuperviewAxis: .vertical) + + didSetupConstraints = true + } + + super.updateViewConstraints() + } + + /** + Callback when the "Toggle Constraints" button is tapped. + */ + func toggleConstraints(_ sender: UIButton) { + isHorizontalLayoutActive = !isHorizontalLayoutActive + + if (isHorizontalLayoutActive) { + verticalLayoutConstraints?.autoRemoveConstraints() + horizontalLayoutConstraints?.autoInstallConstraints() + } else { + horizontalLayoutConstraints?.autoRemoveConstraints() + verticalLayoutConstraints?.autoInstallConstraints() + } + + /** + Uncomment the below code if you want the transitions to be animated! + */ +// UIView.animateWithDuration(0.2) { +// self.view.layoutIfNeeded() +// } + } +} diff --git a/PureLayout/Example-iOS/Demos/iOSDemo11ViewController.swift b/PureLayout/Example-iOS/Demos/iOSDemo11ViewController.swift new file mode 100644 index 0000000..aa9ad05 --- /dev/null +++ b/PureLayout/Example-iOS/Demos/iOSDemo11ViewController.swift @@ -0,0 +1,60 @@ +// +// iOSDemo11ViewController.swift +// PureLayout Example-iOS +// +// Copyright (c) 2015 Spiros Gerokostas +// https://github.com/PureLayout/PureLayout +// + +import UIKit +import PureLayout + +@objc(iOSDemo11ViewController) +class iOSDemo11ViewController: UIViewController { + + let scrollView = UIScrollView.newAutoLayout() + let contentView = UIView.newAutoLayout() + + let blueLabel: UILabel = { + let label = UILabel.newAutoLayout() + label.backgroundColor = .blue + label.numberOfLines = 0 + label.lineBreakMode = .byClipping + label.textColor = .white + label.text = NSLocalizedString("Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum", comment: "") + return label + }() + + var didSetupConstraints = false + + override func loadView() { + view = UIView() + view.backgroundColor = UIColor(white: 0.1, alpha: 1.0) + + view.addSubview(scrollView) + scrollView.addSubview(contentView) + contentView.addSubview(blueLabel) + + view.setNeedsUpdateConstraints() // bootstrap Auto Layout + } + + override func updateViewConstraints() { + + if (!didSetupConstraints) { + + scrollView.autoPinEdgesToSuperviewEdges(with: UIEdgeInsets.zero) + + contentView.autoPinEdgesToSuperviewEdges(with: UIEdgeInsets.zero) + contentView.autoMatch(.width, to: .width, of: view) + + blueLabel.autoPinEdge(toSuperviewEdge: .top, withInset: 20) + blueLabel.autoPinEdge(toSuperviewEdge: .leading, withInset: 20) + blueLabel.autoPinEdge(toSuperviewEdge: .trailing, withInset: 20) + blueLabel.autoPinEdge(toSuperviewEdge: .bottom, withInset: 20) + + didSetupConstraints = true + } + + super.updateViewConstraints() + } +} diff --git a/PureLayout/Example-iOS/Demos/iOSDemo1ViewController.swift b/PureLayout/Example-iOS/Demos/iOSDemo1ViewController.swift new file mode 100644 index 0000000..db956db --- /dev/null +++ b/PureLayout/Example-iOS/Demos/iOSDemo1ViewController.swift @@ -0,0 +1,84 @@ +// +// iOSDemo1ViewController.swift +// PureLayout Example-iOS +// +// Copyright (c) 2015 Tyler Fox +// https://github.com/PureLayout/PureLayout +// + +import UIKit +import PureLayout + +@objc(iOSDemo1ViewController) +class iOSDemo1ViewController: UIViewController { + + let blueView: UIView = { + let view = UIView.newAutoLayout() + view.backgroundColor = .blue + return view + }() + let redView: UIView = { + let view = UIView.newAutoLayout() + view.backgroundColor = .red + return view + }() + let yellowView: UIView = { + let view = UIView.newAutoLayout() + view.backgroundColor = .yellow + return view + }() + let greenView: UIView = { + let view = UIView.newAutoLayout() + view.backgroundColor = .green + return view + }() + + var didSetupConstraints = false + + override func loadView() { + view = UIView() + view.backgroundColor = UIColor(white: 0.1, alpha: 1.0) + + view.addSubview(blueView) + view.addSubview(redView) + view.addSubview(yellowView) + view.addSubview(greenView) + + view.setNeedsUpdateConstraints() // bootstrap Auto Layout + } + + override func updateViewConstraints() { + // Check a flag didSetupConstraints before creating constraints, because this method may be called multiple times, and we + // only want to create these constraints once. Without this check, the same constraints could be added multiple times, + // which can hurt performance and cause other issues. See Demo 7 (Animation) for an example of code that runs every time. + if (!didSetupConstraints) { + // Blue view is centered on screen, with size {50 pt, 50 pt} + blueView.autoCenterInSuperview() + blueView.autoSetDimensions(to: CGSize(width: 50.0, height: 50.0)) + + // Red view is positioned at the bottom right corner of the blue view, with the same width, and a height of 40 pt + redView.autoPinEdge(.top, to: .bottom, of: blueView) + redView.autoPinEdge(.left, to: .right, of: blueView) + redView.autoMatch(.width, to: .width, of: blueView) + redView.autoSetDimension(.height, toSize: 40.0) + + // Yellow view is positioned 10 pt below the red view, extending across the screen with 20 pt insets from the edges, + // and with a fixed height of 25 pt + yellowView.autoPinEdge(.top, to: .bottom, of: redView, withOffset: 10.0) + yellowView.autoSetDimension(.height, toSize: 25.0) + yellowView.autoPinEdge(toSuperviewEdge: .left, withInset: 20.0) + yellowView.autoPinEdge(toSuperviewEdge: .right, withInset: 20.0) + + // Green view is positioned 10 pt below the yellow view, aligned to the vertical axis of its superview, + // with its height twice the height of the yellow view and its width fixed to 150 pt + greenView.autoPinEdge(.top, to: .bottom, of: yellowView, withOffset: 10.0) + greenView.autoAlignAxis(toSuperviewAxis: .vertical) + greenView.autoMatch(.height, to: .height, of: yellowView, withMultiplier: 2.0) + greenView.autoSetDimension(.width, toSize: 150.0) + + didSetupConstraints = true + } + + super.updateViewConstraints() + } +} diff --git a/PureLayout/Example-iOS/Demos/iOSDemo2ViewController.swift b/PureLayout/Example-iOS/Demos/iOSDemo2ViewController.swift new file mode 100644 index 0000000..a906a23 --- /dev/null +++ b/PureLayout/Example-iOS/Demos/iOSDemo2ViewController.swift @@ -0,0 +1,82 @@ +// +// iOSDemo2ViewController.swift +// PureLayout Example-iOS +// +// Copyright (c) 2015 Tyler Fox +// https://github.com/PureLayout/PureLayout +// + +import UIKit +import PureLayout + +@objc(iOSDemo2ViewController) +class iOSDemo2ViewController: UIViewController { + + let blueView: UIView = { + let view = UIView.newAutoLayout() + view.backgroundColor = .blue + return view + }() + let redView: UIView = { + let view = UIView.newAutoLayout() + view.backgroundColor = .red + return view + }() + let yellowView: UIView = { + let view = UIView.newAutoLayout() + view.backgroundColor = .yellow + return view + }() + let greenView: UIView = { + let view = UIView.newAutoLayout() + view.backgroundColor = .green + return view + }() + + var didSetupConstraints = false + + override func loadView() { + view = UIView() + view.backgroundColor = UIColor(white: 0.1, alpha: 1.0) + + view.addSubview(blueView) + view.addSubview(redView) + view.addSubview(yellowView) + view.addSubview(greenView) + + view.setNeedsUpdateConstraints() // bootstrap Auto Layout + } + + override func updateViewConstraints() { + if (!didSetupConstraints) { + // Apply a fixed height of 50 pt to two views at once, and a fixed height of 70 pt to another two views + ([redView, yellowView] as NSArray).autoSetViewsDimension(.height, toSize: 50.0) + ([blueView, greenView] as NSArray).autoSetViewsDimension(.height, toSize: 70.0) + + let views = [redView, blueView, yellowView, greenView] + + // Match the widths of all the views + (views as NSArray).autoMatchViewsDimension(.width) + + // Pin the red view 20 pt from the top layout guide of the view controller + redView.autoPin(toTopLayoutGuideOf: self, withInset: 20.0) + + // Loop over the views, attaching the left edge to the previous view's right edge, + // and the top edge to the previous view's bottom edge + views.first?.autoPinEdge(toSuperviewEdge: .left) + var previousView: UIView? + for view in views { + if let previousView = previousView { + view.autoPinEdge(.left, to: .right, of: previousView) + view.autoPinEdge(.top, to: .bottom, of: previousView) + } + previousView = view + } + views.last?.autoPinEdge(toSuperviewEdge: .right) + + didSetupConstraints = true + } + + super.updateViewConstraints() + } +} diff --git a/PureLayout/Example-iOS/Demos/iOSDemo3ViewController.swift b/PureLayout/Example-iOS/Demos/iOSDemo3ViewController.swift new file mode 100644 index 0000000..ebf5895 --- /dev/null +++ b/PureLayout/Example-iOS/Demos/iOSDemo3ViewController.swift @@ -0,0 +1,70 @@ +// +// iOSDemo3ViewController.swift +// PureLayout Example-iOS +// +// Copyright (c) 2015 Tyler Fox +// https://github.com/PureLayout/PureLayout +// + +import UIKit +import PureLayout + +@objc(iOSDemo3ViewController) +class iOSDemo3ViewController: UIViewController { + + let blueView: UIView = { + let view = UIView.newAutoLayout() + view.backgroundColor = .blue + return view + }() + let redView: UIView = { + let view = UIView.newAutoLayout() + view.backgroundColor = .red + return view + }() + let yellowView: UIView = { + let view = UIView.newAutoLayout() + view.backgroundColor = .yellow + return view + }() + let greenView: UIView = { + let view = UIView.newAutoLayout() + view.backgroundColor = .green + return view + }() + + var didSetupConstraints = false + + override func loadView() { + view = UIView() + view.backgroundColor = UIColor(white: 0.1, alpha: 1.0) + + view.addSubview(blueView) + view.addSubview(redView) + view.addSubview(yellowView) + view.addSubview(greenView) + + view.setNeedsUpdateConstraints() // bootstrap Auto Layout + } + + override func updateViewConstraints() { + if (!didSetupConstraints) { + let views: NSArray = [redView, blueView, yellowView, greenView] + + // Fix all the heights of the views to 40 pt + views.autoSetViewsDimension(.height, toSize: 40.0) + + // Distribute the views horizontally across the screen, aligned to one another's horizontal axis, + // with 10 pt spacing between them and to their superview, and their widths matched equally + views.autoDistributeViews(along: .horizontal, alignedTo: .horizontal, withFixedSpacing: 10.0, insetSpacing: true, matchedSizes: true) + + // Align the red view to the horizontal axis of its superview. + // This will end up affecting all the views, since they are all aligned to one another's horizontal axis. + self.redView.autoAlignAxis(toSuperviewAxis: .horizontal) + + didSetupConstraints = true + } + + super.updateViewConstraints() + } +} diff --git a/PureLayout/Example-iOS/Demos/iOSDemo4ViewController.swift b/PureLayout/Example-iOS/Demos/iOSDemo4ViewController.swift new file mode 100644 index 0000000..ef99e95 --- /dev/null +++ b/PureLayout/Example-iOS/Demos/iOSDemo4ViewController.swift @@ -0,0 +1,94 @@ +// +// iOSDemo4ViewController.swift +// PureLayout Example-iOS +// +// Copyright (c) 2015 Tyler Fox +// https://github.com/PureLayout/PureLayout +// + +import UIKit +import PureLayout + +@objc(iOSDemo4ViewController) +class iOSDemo4ViewController: UIViewController { + + let blueLabel: UILabel = { + let label = UILabel.newAutoLayout() + label.backgroundColor = .blue + label.numberOfLines = 1 + label.lineBreakMode = .byClipping + label.textColor = .white + label.text = NSLocalizedString("Lorem ipsum", comment: "") + return label + }() + let redLabel: UILabel = { + let label = UILabel.newAutoLayout() + label.backgroundColor = .red + label.numberOfLines = 0 + label.textColor = .white + label.text = NSLocalizedString("Lorem ipsum", comment: "") + return label + }() + let greenView: UIView = { + let view = UIView.newAutoLayout() + view.backgroundColor = .green + return view + }() + + var didSetupConstraints = false + + override func loadView() { + view = UIView() + view.backgroundColor = UIColor(white: 0.1, alpha: 1.0) + + view.addSubview(blueLabel) + view.addSubview(redLabel) + view.addSubview(greenView) + + view.setNeedsUpdateConstraints() // bootstrap Auto Layout + } + + override func updateViewConstraints() { + /** + NOTE: To observe the effect of leading & trailing attributes, you need to change the OS language setting from a left-to-right language, + such as English, to a right-to-left language, such as Arabic. + + This demo project includes localized strings for Arabic, so you will see the Lorem Ipsum text in Arabic if the system is set to that language. + + See this method of easily forcing the simulator's language from Xcode: http://stackoverflow.com/questions/8596168/xcode-run-project-with-specified-localization + */ + + let smallPadding: CGFloat = 20.0 + let largePadding: CGFloat = 50.0 + + if (!didSetupConstraints) { + // Prevent the blueLabel from compressing smaller than required to fit its single line of text + blueLabel.setContentCompressionResistancePriority(UILayoutPriorityRequired, for: .vertical) + + // Position the single-line blueLabel at the top of the screen spanning the width, with some small insets + blueLabel.autoPin(toTopLayoutGuideOf: self, withInset: smallPadding) + blueLabel.autoPinEdge(toSuperviewEdge: .leading, withInset: smallPadding) + blueLabel.autoPinEdge(toSuperviewEdge: .trailing, withInset: smallPadding) + + // Make the redLabel 60% of the width of the blueLabel + redLabel.autoMatch(.width, to: .width, of: blueLabel, withMultiplier: 0.6) + + // The redLabel is positioned below the blueLabel, with its leading edge to its superview, and trailing edge to the greenView + redLabel.autoPinEdge(.top, to: .bottom, of: blueLabel, withOffset: smallPadding) + redLabel.autoPinEdge(toSuperviewEdge: .leading, withInset: smallPadding) + redLabel.autoPinEdge(toSuperviewEdge: .bottom, withInset: largePadding) + + // The greenView is positioned below the blueLabel, with its leading edge to the redLabel, and trailing edge to its superview + greenView.autoPinEdge(.leading, to: .trailing, of: redLabel, withOffset: largePadding) + greenView.autoPinEdge(.top, to: .bottom, of: blueLabel, withOffset: smallPadding) + greenView.autoPinEdge(toSuperviewEdge: .trailing, withInset: smallPadding) + + // Match the greenView's height to its width (keeping a consistent aspect ratio) + greenView.autoMatch(.width, to: .height, of: greenView) + + didSetupConstraints = true + } + + super.updateViewConstraints() + } +} diff --git a/PureLayout/Example-iOS/Demos/iOSDemo5ViewController.swift b/PureLayout/Example-iOS/Demos/iOSDemo5ViewController.swift new file mode 100644 index 0000000..520ba26 --- /dev/null +++ b/PureLayout/Example-iOS/Demos/iOSDemo5ViewController.swift @@ -0,0 +1,69 @@ +// +// iOSDemo5ViewController.swift +// PureLayout Example-iOS +// +// Copyright (c) 2015 Tyler Fox +// https://github.com/PureLayout/PureLayout +// + +import UIKit +import PureLayout + +@objc(iOSDemo5ViewController) +class iOSDemo5ViewController: UIViewController { + + let blueView: UIView = { + let view = UIView.newAutoLayout() + view.backgroundColor = .blue + view.layer.borderColor = UIColor.lightGray.cgColor + view.layer.borderWidth = 0.5 + return view + }() + let redView: UIView = { + let view = UIView.newAutoLayout() + view.backgroundColor = .red + return view + }() + let purpleLabel: UILabel = { + let label = UILabel.newAutoLayout() + label.backgroundColor = UIColor(red: 1.0, green: 0, blue: 1.0, alpha: 0.3) // semi-transparent purple + label.textColor = .white + label.text = "The quick brown fox jumps over the lazy dog" + return label + }() + + var didSetupConstraints = false + + override func loadView() { + view = UIView() + view.backgroundColor = UIColor(white: 0.1, alpha: 1.0) + + view.addSubview(blueView) + view.addSubview(redView) + view.addSubview(purpleLabel) + + view.setNeedsUpdateConstraints() // bootstrap Auto Layout + } + + override func updateViewConstraints() { + if (!didSetupConstraints) { + blueView.autoCenterInSuperview() + blueView.autoSetDimensions(to: CGSize(width: 150.0, height: 150.0)) + + // Use a cross-attribute constraint to constrain an ALAxis (Horizontal) to an ALEdge (Bottom) + redView.autoConstrainAttribute(.horizontal, to: .bottom, of: blueView) + + redView.autoAlignAxis(.vertical, toSameAxisOf: blueView) + redView.autoSetDimensions(to: CGSize(width: 50.0, height: 50.0)) + + // Use another cross-attribute constraint to place the purpleLabel's baseline on the blueView's top edge + purpleLabel.autoConstrainAttribute(.baseline, to: .top, of: blueView) + + purpleLabel.autoAlignAxis(.vertical, toSameAxisOf: blueView) + + didSetupConstraints = true + } + + super.updateViewConstraints() + } +} diff --git a/PureLayout/Example-iOS/Demos/iOSDemo6ViewController.swift b/PureLayout/Example-iOS/Demos/iOSDemo6ViewController.swift new file mode 100644 index 0000000..cc49603 --- /dev/null +++ b/PureLayout/Example-iOS/Demos/iOSDemo6ViewController.swift @@ -0,0 +1,56 @@ +// +// iOSDemo6ViewController.swift +// PureLayout Example-iOS +// +// Copyright (c) 2015 Tyler Fox +// https://github.com/PureLayout/PureLayout +// + +import UIKit +import PureLayout + +@objc(iOSDemo6ViewController) +class iOSDemo6ViewController: UIViewController { + + let blueView: UIView = { + let view = UIView.newAutoLayout() + view.backgroundColor = .blue + return view + }() + + var didSetupConstraints = false + + override func loadView() { + view = UIView() + view.backgroundColor = UIColor(white: 0.1, alpha: 1.0) + + view.addSubview(blueView) + + view.setNeedsUpdateConstraints() // bootstrap Auto Layout + } + + override func updateViewConstraints() { + if (!didSetupConstraints) { + // Center the blueView in its superview, and match its width to its height + blueView.autoCenterInSuperview() + blueView.autoMatch(.width, to: .height, of: blueView) + + // Make sure the blueView is always at least 20 pt from any edge + blueView.autoPin(toTopLayoutGuideOf: self, withInset: 20.0, relation: .greaterThanOrEqual) + blueView.autoPin(toBottomLayoutGuideOf: self, withInset: 20.0, relation: .greaterThanOrEqual) + blueView.autoPinEdge(toSuperviewEdge: .left, withInset: 20.0, relation: .greaterThanOrEqual) + blueView.autoPinEdge(toSuperviewEdge: .right, withInset: 20.0, relation: .greaterThanOrEqual) + + // Add constraints that set the size of the blueView to a ridiculously large size, but set the priority of these constraints + // to a lower value than Required. This allows the Auto Layout solver to let these constraints be broken if one or both of + // them conflict with higher-priority constraint(s), such as the above 4 edge constraints. + NSLayoutConstraint.autoSetPriority(UILayoutPriorityDefaultHigh) { + self.blueView.autoSetDimensions(to: CGSize(width: 10000.0, height: 10000.0)) + } + + didSetupConstraints = true + } + + super.updateViewConstraints() + } +} diff --git a/PureLayout/Example-iOS/Demos/iOSDemo7ViewController.swift b/PureLayout/Example-iOS/Demos/iOSDemo7ViewController.swift new file mode 100644 index 0000000..b59294f --- /dev/null +++ b/PureLayout/Example-iOS/Demos/iOSDemo7ViewController.swift @@ -0,0 +1,131 @@ +// +// iOSDemo7ViewController.swift +// PureLayout Example-iOS +// +// Copyright (c) 2015 Tyler Fox +// https://github.com/PureLayout/PureLayout +// + +import UIKit +import PureLayout + +@objc(iOSDemo7ViewController) +class iOSDemo7ViewController: UIViewController { + + let blueView: UIView = { + let view = UIView.newAutoLayout() + view.backgroundColor = .blue + return view + }() + let redView: UIView = { + let view = UIView.newAutoLayout() + view.backgroundColor = .red + return view + }() + + var didSetupConstraints = false + + // Tracks the state of the animation: whether we are animating to the end state (true), or back to the initial state (false) + var isAnimatingToEndState = true + + // Store some constraints that we intend to modify as part of the animation + var blueViewHeightConstraint: NSLayoutConstraint? + var redViewEdgeConstraint: NSLayoutConstraint? + + override func loadView() { + view = UIView() + view.backgroundColor = UIColor(white: 0.1, alpha: 1.0) + + view.addSubview(blueView) + view.addSubview(redView) + + view.setNeedsUpdateConstraints() // bootstrap Auto Layout + } + + override func viewDidAppear(_ animated: Bool) { + super.viewDidAppear(animated) + + /** + Start the animation when the view appears. Note that the first initial constraint setup and layout pass has already occurred at this point. + + To switch between spring animation and regular animation, comment & uncomment the two lines below! + (Don't uncomment both lines, one at a time!) + */ + animateLayoutWithSpringAnimation() // uncomment to use spring animation +// animateLayoutWithRegularAnimation() // uncomment to use regular animation + } + + override func updateViewConstraints() { + let blueViewInitialHeight: CGFloat = 40.0 + let blueViewEndHeight: CGFloat = 100.0 + + // Remember, this code is just the initial constraint setup which only happens the first time this method is called + if (!didSetupConstraints) { + blueView.autoPin(toTopLayoutGuideOf: self, withInset: 20.0) + blueView.autoAlignAxis(toSuperviewAxis: .vertical) + + blueView.autoSetDimension(.width, toSize: 50.0) + blueViewHeightConstraint = blueView.autoSetDimension(.height, toSize: blueViewInitialHeight) + + redView.autoSetDimension(.height, toSize: 50.0) + redView.autoMatch(.width, to: .height, of: blueView, withMultiplier: 1.5) + redView.autoAlignAxis(toSuperviewAxis: .vertical) + + didSetupConstraints = true + } + + // Unlike the code above, this is code that will execute every time this method is called. + // Updating the `constant` property of a constraint is very efficient and can be done without removing/recreating the constraint. + // Any other changes will require you to remove and re-add new constraints. Make sure to remove constraints before you create new ones! + redViewEdgeConstraint?.autoRemove() + if isAnimatingToEndState { + blueViewHeightConstraint?.constant = blueViewEndHeight + redViewEdgeConstraint = redView.autoPinEdge(toSuperviewEdge: .bottom, withInset: 150.0) + } else { + blueViewHeightConstraint?.constant = blueViewInitialHeight + redViewEdgeConstraint = redView.autoPinEdge(.top, to: .bottom, of: blueView, withOffset: 20.0) + } + + super.updateViewConstraints() + } + + /// See the comments in viewDidAppear: above. + func animateLayoutWithSpringAnimation() { + + // These 2 lines will cause updateViewConstraints() to be called again on this view controller, where the constraints will be adjusted to the new state + view.setNeedsUpdateConstraints() + view.updateConstraintsIfNeeded() + + UIView.animate(withDuration: 1.0, delay: 0, usingSpringWithDamping: 0.6, initialSpringVelocity: 0, options: UIViewAnimationOptions(), + animations: { + self.view.layoutIfNeeded() + }, + completion: { (finished: Bool) -> Void in + // Run the animation again in the other direction + self.isAnimatingToEndState = !self.isAnimatingToEndState + if (self.navigationController != nil) { // this will be nil if this view controller is no longer in the navigation stack (stops animation when this view controller is no longer onscreen) + self.animateLayoutWithSpringAnimation() + } + }) + } + + /// See the comments in viewDidAppear: above. + func animateLayoutWithRegularAnimation() { + + // These 2 lines will cause updateViewConstraints() to be called again on this view controller, where the constraints will be adjusted to the new state + view.setNeedsUpdateConstraints() + view.updateConstraintsIfNeeded() + + UIView.animate(withDuration: 1.0, delay: 0, options: UIViewAnimationOptions(), + animations: { + self.view.layoutIfNeeded() + }, + completion: { (finished: Bool) -> Void in + // Run the animation again in the other direction + self.isAnimatingToEndState = !self.isAnimatingToEndState + if (self.navigationController != nil) { // this will be nil if this view controller is no longer in the navigation stack (stops animation when this view controller is no longer onscreen) + self.animateLayoutWithRegularAnimation() + } + }) + } +} diff --git a/PureLayout/Example-iOS/Demos/iOSDemo8ViewController.swift b/PureLayout/Example-iOS/Demos/iOSDemo8ViewController.swift new file mode 100644 index 0000000..50d3312 --- /dev/null +++ b/PureLayout/Example-iOS/Demos/iOSDemo8ViewController.swift @@ -0,0 +1,105 @@ +// +// iOSDemo8ViewController.swift +// PureLayout Example-iOS +// +// Copyright (c) 2015 Tyler Fox +// https://github.com/PureLayout/PureLayout +// + +import UIKit +import PureLayout + +@objc(iOSDemo8ViewController) +class iOSDemo8ViewController: UIViewController { + + let containerView: UIView = { + let view = UIView.newAutoLayout() + view.backgroundColor = .lightGray + return view + }() + let blueView: UIView = { + let view = UIView.newAutoLayout() + view.backgroundColor = .blue + return view + }() + let redView: UIView = { + let view = UIView.newAutoLayout() + view.backgroundColor = .red + return view + }() + let yellowView: UIView = { + let view = UIView.newAutoLayout() + view.backgroundColor = .yellow + return view + }() + let greenView: UIView = { + let view = UIView.newAutoLayout() + view.backgroundColor = .green + return view + }() + + var didSetupConstraints = false + + override func loadView() { + view = UIView() + view.backgroundColor = UIColor(white: 0.1, alpha: 1.0) + + view.addSubview(containerView) + containerView.addSubview(blueView) + containerView.addSubview(redView) + containerView.addSubview(yellowView) + containerView.addSubview(greenView) + + view.setNeedsUpdateConstraints() // bootstrap Auto Layout + } + + override func updateViewConstraints() { + if (!didSetupConstraints) { + + /** + First, we'll set up some 'good' constraints that work correctly. + Note that we identify all of the constraints with a short description of what their purpose is - this is a great feature + to help you document and comment constraints both in the code, and at runtime. If a Required constraint is ever broken, + it will raise an exception, and you will see these identifiers show up next to the constraint in the console. + */ + + NSLayoutConstraint.autoSetIdentifier("Pin Container View Edges") { + self.containerView.autoPin(toTopLayoutGuideOf: self, withInset: 10.0) + self.containerView.autoPinEdgesToSuperviewEdges(with: UIEdgeInsets(top: 0.0, left: 10.0, bottom: 10.0, right: 10.0), excludingEdge: .top) + } + + let views: NSArray = [redView, blueView, yellowView, greenView] + + (views.autoDistributeViews(along: .vertical, alignedTo: .vertical, withFixedSize: 40.0) as NSArray).autoIdentifyConstraints("Distribute Views Vertically") + + /** + Note that the -autoIdentify and -autoIdentifyConstraints methods set the identifier, and then return the constraint(s). + This lets you chain the identifier call right after creating the constraint(s), and still capture a reference to the constraint(s)! + */ + + let constraints = (views.autoSetViewsDimension(.width, toSize: 60.0) as NSArray).autoIdentifyConstraints("Set Width of All Views") + print("Just added \(constraints.count) constraints!") // you can do something with the constraints at this point + let constraint = redView.autoAlignAxis(toSuperviewAxis: .vertical).autoIdentify("Align Red View to Superview Vertical Axis") + print("Just added one constraint with the identifier: \(constraint.identifier)") // you can do something with the constraint at this point + + /** + Now, let's add some 'bad' constraints that conflict with one or more of the 'good' constraints above. + Start by uncommenting one of the below constraints, and running the demo. A constraint exception will be logged + to the console, because one or more views was over-constrained, and therefore one or more constraints had to be broken. + But because we have provided human-readable identifiers, notice how easy it is to figure out which constraints are + conflicting, and which constraint shouldn't be there! + */ + NSLayoutConstraint.autoSetIdentifier("Bad Constraints That Break Things") { +// self.redView.autoAlignAxis(.Vertical, toSameAxisOfView: self.view, withOffset: 5.0) // uncomment me and watch things blow up! + +// self.redView.autoPinEdgeToSuperviewEdge(.Left) // uncomment me and watch things blow up! + +// views.autoSetViewsDimension(.Height, toSize: 50.0) // uncomment me and watch things blow up! + } + + didSetupConstraints = true + } + + super.updateViewConstraints() + } +} diff --git a/PureLayout/Example-iOS/Demos/iOSDemo9ViewController.swift b/PureLayout/Example-iOS/Demos/iOSDemo9ViewController.swift new file mode 100644 index 0000000..89718e3 --- /dev/null +++ b/PureLayout/Example-iOS/Demos/iOSDemo9ViewController.swift @@ -0,0 +1,83 @@ +// +// iOSDemo9ViewController.swift +// PureLayout Example-iOS +// +// Copyright (c) 2015 Tyler Fox +// https://github.com/PureLayout/PureLayout +// + +import UIKit +import PureLayout + +@objc(iOSDemo9ViewController) +class iOSDemo9ViewController: UIViewController { + + let blueView: UIView = { + let view = UIView.newAutoLayout() + view.backgroundColor = .blue + return view + }() + let redView: UIView = { + let view = UIView.newAutoLayout() + view.backgroundColor = .red + return view + }() + let yellowView: UIView = { + let view = UIView.newAutoLayout() + view.backgroundColor = .yellow + return view + }() + let greenView: UIView = { + let view = UIView.newAutoLayout() + view.backgroundColor = .green + return view + }() + + var didSetupConstraints = false + + override func loadView() { + view = UIView() + view.backgroundColor = UIColor(white: 0.1, alpha: 1.0) + + view.addSubview(blueView) + blueView.addSubview(redView) + redView.addSubview(yellowView) + yellowView.addSubview(greenView) + + view.setNeedsUpdateConstraints() // bootstrap Auto Layout + } + + override func updateViewConstraints() { + if (!didSetupConstraints) { + // Before layout margins were introduced, this is a typical way of giving a subview some padding from its superview's edges + blueView.autoPin(toTopLayoutGuideOf: self, withInset: 10.0) + blueView.autoPinEdgesToSuperviewEdges(with: UIEdgeInsets(top: 0, left: 10.0, bottom: 10.0, right: 10.0), excludingEdge: .top) + + // Set the layoutMargins of the blueView, which will have an effect on subviews of the blueView that attach to + // the blueView's margin attributes -- in this case, the redView + blueView.layoutMargins = UIEdgeInsets(top: 10.0, left: 20.0, bottom: 80.0, right: 20.0) + redView.autoPinEdgesToSuperviewMargins() + + // Let the redView inherit the values we just set for the blueView's layoutMargins by setting the below property to YES. + // Then, pin the yellowView's edges to the redView's margins, giving the yellowView the same insets from its superview as the redView. + redView.preservesSuperviewLayoutMargins = true + yellowView.autoPinEdge(toSuperviewMargin: .left) + yellowView.autoPinEdge(toSuperviewMargin: .right) + + // By aligning the yellowView to its superview's horizontal margin axis, the yellowView will be positioned with its horizontal axis + // in the middle of the redView's top and bottom margins (causing it to be slightly closer to the top of the redView, since the + // redView has a much larger bottom margin than top margin). + yellowView.autoAlignAxis(toSuperviewMarginAxis: .horizontal) + yellowView.autoMatch(.height, to: .height, of: redView, withMultiplier: 0.5) + + // Since yellowView.preservesSuperviewLayoutMargins is NO by default, it will not preserve (inherit) its superview's margins, + // and instead will just have the default margins of: {8.0, 8.0, 8.0, 8.0} which will apply to its subviews (greenView) + greenView.autoPinEdges(toSuperviewMarginsExcludingEdge: .bottom) + greenView.autoSetDimension(.height, toSize: 50.0) + + didSetupConstraints = true + } + + super.updateViewConstraints() + } +} diff --git a/PureLayout/Example-iOS/Example-iOS-Bridging-Header.h b/PureLayout/Example-iOS/Example-iOS-Bridging-Header.h new file mode 100644 index 0000000..1b2cb5d --- /dev/null +++ b/PureLayout/Example-iOS/Example-iOS-Bridging-Header.h @@ -0,0 +1,4 @@ +// +// Use this file to import your target's public headers that you would like to expose to Swift. +// + diff --git a/PureLayout/Example-iOS/Example-iOS-Info.plist b/PureLayout/Example-iOS/Example-iOS-Info.plist index e0df185..56e6e61 100644 --- a/PureLayout/Example-iOS/Example-iOS-Info.plist +++ b/PureLayout/Example-iOS/Example-iOS-Info.plist @@ -13,7 +13,7 @@ CFBundleIcons~ipad CFBundleIdentifier - com.smileyborg.${PRODUCT_NAME:rfc1034identifier} + $(PRODUCT_BUNDLE_IDENTIFIER) CFBundleInfoDictionaryVersion 6.0 CFBundleName diff --git a/PureLayout/Example-iOS/Example-iOS-Prefix.pch b/PureLayout/Example-iOS/Example-iOS-Prefix.pch deleted file mode 100644 index a2811e6..0000000 --- a/PureLayout/Example-iOS/Example-iOS-Prefix.pch +++ /dev/null @@ -1,20 +0,0 @@ -// -// Example-iOS-Prefix.pch -// PureLayout Example-iOS -// -// Copyright (c) 2014 Tyler Fox -// https://github.com/smileyborg/PureLayout -// -// Prefix header for all source files of the 'Example-iOS' target in the 'Example' project -// - -#import - -#ifndef __IPHONE_4_0 -#warning "This project uses features only available in iOS SDK 4.0 and later." -#endif - -#ifdef __OBJC__ - #import - #import -#endif diff --git a/PureLayout/Example-iOS/Images-iOS.xcassets/AppIcon.appiconset/Contents.json b/PureLayout/Example-iOS/Images-iOS.xcassets/AppIcon.appiconset/Contents.json index 298e38f..13cb236 100644 --- a/PureLayout/Example-iOS/Images-iOS.xcassets/AppIcon.appiconset/Contents.json +++ b/PureLayout/Example-iOS/Images-iOS.xcassets/AppIcon.appiconset/Contents.json @@ -1,5 +1,15 @@ { "images" : [ + { + "idiom" : "iphone", + "size" : "20x20", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "size" : "20x20", + "scale" : "3x" + }, { "idiom" : "iphone", "size" : "29x29", @@ -45,6 +55,16 @@ "size" : "60x60", "scale" : "3x" }, + { + "idiom" : "ipad", + "size" : "20x20", + "scale" : "1x" + }, + { + "idiom" : "ipad", + "size" : "20x20", + "scale" : "2x" + }, { "idiom" : "ipad", "size" : "29x29", @@ -96,8 +116,13 @@ "scale" : "2x" }, { - "idiom" : "car", - "size" : "120x120", + "idiom" : "ipad", + "size" : "83.5x83.5", + "scale" : "2x" + }, + { + "idiom" : "ios-marketing", + "size" : "1024x1024", "scale" : "1x" } ], diff --git a/PureLayout/Example-iOS/Images-iOS.xcassets/LaunchImage.launchimage/Contents.json b/PureLayout/Example-iOS/Images-iOS.xcassets/LaunchImage.launchimage/Contents.json index 729a5e1..988f966 100644 --- a/PureLayout/Example-iOS/Images-iOS.xcassets/LaunchImage.launchimage/Contents.json +++ b/PureLayout/Example-iOS/Images-iOS.xcassets/LaunchImage.launchimage/Contents.json @@ -1,5 +1,23 @@ { "images" : [ + { + "extent" : "full-screen", + "idiom" : "iphone", + "subtype" : "2436h", + "filename" : "iPhone_X_Portrait.png", + "minimum-system-version" : "11.0", + "orientation" : "portrait", + "scale" : "3x" + }, + { + "extent" : "full-screen", + "idiom" : "iphone", + "subtype" : "2436h", + "filename" : "iPhone_X_Landscape.png", + "minimum-system-version" : "11.0", + "orientation" : "landscape", + "scale" : "3x" + }, { "extent" : "full-screen", "idiom" : "iphone", diff --git a/PureLayout/Example-iOS/Images-iOS.xcassets/LaunchImage.launchimage/iPhone_X_Landscape.png b/PureLayout/Example-iOS/Images-iOS.xcassets/LaunchImage.launchimage/iPhone_X_Landscape.png new file mode 100644 index 0000000..2ba5452 Binary files /dev/null and b/PureLayout/Example-iOS/Images-iOS.xcassets/LaunchImage.launchimage/iPhone_X_Landscape.png differ diff --git a/PureLayout/Example-iOS/Images-iOS.xcassets/LaunchImage.launchimage/iPhone_X_Portrait.png b/PureLayout/Example-iOS/Images-iOS.xcassets/LaunchImage.launchimage/iPhone_X_Portrait.png new file mode 100644 index 0000000..f91fe5d Binary files /dev/null and b/PureLayout/Example-iOS/Images-iOS.xcassets/LaunchImage.launchimage/iPhone_X_Portrait.png differ diff --git a/PureLayout/Example-iOS/main.m b/PureLayout/Example-iOS/main.m index 9dda479..2f71bbe 100644 --- a/PureLayout/Example-iOS/main.m +++ b/PureLayout/Example-iOS/main.m @@ -2,8 +2,8 @@ // main.m // PureLayout Example-iOS // -// Copyright (c) 2014 Tyler Fox -// https://github.com/smileyborg/PureLayout +// Copyright (c) 2014-2015 Tyler Fox +// https://github.com/PureLayout/PureLayout // #import diff --git a/PureLayout/Example-tvOS/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - Large.imagestack/Back.imagestacklayer/Content.imageset/Contents.json b/PureLayout/Example-tvOS/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - Large.imagestack/Back.imagestacklayer/Content.imageset/Contents.json new file mode 100644 index 0000000..0564959 --- /dev/null +++ b/PureLayout/Example-tvOS/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - Large.imagestack/Back.imagestacklayer/Content.imageset/Contents.json @@ -0,0 +1,12 @@ +{ + "images" : [ + { + "idiom" : "tv", + "scale" : "1x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/PureLayout/Example-tvOS/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - Large.imagestack/Back.imagestacklayer/Contents.json b/PureLayout/Example-tvOS/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - Large.imagestack/Back.imagestacklayer/Contents.json new file mode 100644 index 0000000..da4a164 --- /dev/null +++ b/PureLayout/Example-tvOS/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - Large.imagestack/Back.imagestacklayer/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/PureLayout/Example-tvOS/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - Large.imagestack/Contents.json b/PureLayout/Example-tvOS/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - Large.imagestack/Contents.json new file mode 100644 index 0000000..8bf75d9 --- /dev/null +++ b/PureLayout/Example-tvOS/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - Large.imagestack/Contents.json @@ -0,0 +1,17 @@ +{ + "layers" : [ + { + "filename" : "Front.imagestacklayer" + }, + { + "filename" : "Middle.imagestacklayer" + }, + { + "filename" : "Back.imagestacklayer" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} diff --git a/PureLayout/Example-tvOS/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - Large.imagestack/Front.imagestacklayer/Content.imageset/Contents.json b/PureLayout/Example-tvOS/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - Large.imagestack/Front.imagestacklayer/Content.imageset/Contents.json new file mode 100644 index 0000000..0564959 --- /dev/null +++ b/PureLayout/Example-tvOS/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - Large.imagestack/Front.imagestacklayer/Content.imageset/Contents.json @@ -0,0 +1,12 @@ +{ + "images" : [ + { + "idiom" : "tv", + "scale" : "1x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/PureLayout/Example-tvOS/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - Large.imagestack/Front.imagestacklayer/Contents.json b/PureLayout/Example-tvOS/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - Large.imagestack/Front.imagestacklayer/Contents.json new file mode 100644 index 0000000..da4a164 --- /dev/null +++ b/PureLayout/Example-tvOS/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - Large.imagestack/Front.imagestacklayer/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/PureLayout/Example-tvOS/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - Large.imagestack/Middle.imagestacklayer/Content.imageset/Contents.json b/PureLayout/Example-tvOS/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - Large.imagestack/Middle.imagestacklayer/Content.imageset/Contents.json new file mode 100644 index 0000000..0564959 --- /dev/null +++ b/PureLayout/Example-tvOS/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - Large.imagestack/Middle.imagestacklayer/Content.imageset/Contents.json @@ -0,0 +1,12 @@ +{ + "images" : [ + { + "idiom" : "tv", + "scale" : "1x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/PureLayout/Example-tvOS/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - Large.imagestack/Middle.imagestacklayer/Contents.json b/PureLayout/Example-tvOS/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - Large.imagestack/Middle.imagestacklayer/Contents.json new file mode 100644 index 0000000..da4a164 --- /dev/null +++ b/PureLayout/Example-tvOS/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - Large.imagestack/Middle.imagestacklayer/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/PureLayout/Example-tvOS/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - Small.imagestack/Back.imagestacklayer/Content.imageset/Contents.json b/PureLayout/Example-tvOS/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - Small.imagestack/Back.imagestacklayer/Content.imageset/Contents.json new file mode 100644 index 0000000..0564959 --- /dev/null +++ b/PureLayout/Example-tvOS/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - Small.imagestack/Back.imagestacklayer/Content.imageset/Contents.json @@ -0,0 +1,12 @@ +{ + "images" : [ + { + "idiom" : "tv", + "scale" : "1x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/PureLayout/Example-tvOS/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - Small.imagestack/Back.imagestacklayer/Contents.json b/PureLayout/Example-tvOS/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - Small.imagestack/Back.imagestacklayer/Contents.json new file mode 100644 index 0000000..da4a164 --- /dev/null +++ b/PureLayout/Example-tvOS/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - Small.imagestack/Back.imagestacklayer/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/PureLayout/Example-tvOS/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - Small.imagestack/Contents.json b/PureLayout/Example-tvOS/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - Small.imagestack/Contents.json new file mode 100644 index 0000000..8bf75d9 --- /dev/null +++ b/PureLayout/Example-tvOS/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - Small.imagestack/Contents.json @@ -0,0 +1,17 @@ +{ + "layers" : [ + { + "filename" : "Front.imagestacklayer" + }, + { + "filename" : "Middle.imagestacklayer" + }, + { + "filename" : "Back.imagestacklayer" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} diff --git a/PureLayout/Example-tvOS/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - Small.imagestack/Front.imagestacklayer/Content.imageset/Contents.json b/PureLayout/Example-tvOS/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - Small.imagestack/Front.imagestacklayer/Content.imageset/Contents.json new file mode 100644 index 0000000..0564959 --- /dev/null +++ b/PureLayout/Example-tvOS/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - Small.imagestack/Front.imagestacklayer/Content.imageset/Contents.json @@ -0,0 +1,12 @@ +{ + "images" : [ + { + "idiom" : "tv", + "scale" : "1x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/PureLayout/Example-tvOS/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - Small.imagestack/Front.imagestacklayer/Contents.json b/PureLayout/Example-tvOS/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - Small.imagestack/Front.imagestacklayer/Contents.json new file mode 100644 index 0000000..da4a164 --- /dev/null +++ b/PureLayout/Example-tvOS/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - Small.imagestack/Front.imagestacklayer/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/PureLayout/Example-tvOS/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - Small.imagestack/Middle.imagestacklayer/Content.imageset/Contents.json b/PureLayout/Example-tvOS/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - Small.imagestack/Middle.imagestacklayer/Content.imageset/Contents.json new file mode 100644 index 0000000..0564959 --- /dev/null +++ b/PureLayout/Example-tvOS/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - Small.imagestack/Middle.imagestacklayer/Content.imageset/Contents.json @@ -0,0 +1,12 @@ +{ + "images" : [ + { + "idiom" : "tv", + "scale" : "1x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/PureLayout/Example-tvOS/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - Small.imagestack/Middle.imagestacklayer/Contents.json b/PureLayout/Example-tvOS/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - Small.imagestack/Middle.imagestacklayer/Contents.json new file mode 100644 index 0000000..da4a164 --- /dev/null +++ b/PureLayout/Example-tvOS/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - Small.imagestack/Middle.imagestacklayer/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/PureLayout/Example-tvOS/Assets.xcassets/App Icon & Top Shelf Image.brandassets/Contents.json b/PureLayout/Example-tvOS/Assets.xcassets/App Icon & Top Shelf Image.brandassets/Contents.json new file mode 100644 index 0000000..6a3dcfa --- /dev/null +++ b/PureLayout/Example-tvOS/Assets.xcassets/App Icon & Top Shelf Image.brandassets/Contents.json @@ -0,0 +1,26 @@ +{ + "assets" : [ + { + "size" : "1280x768", + "idiom" : "tv", + "filename" : "App Icon - Large.imagestack", + "role" : "primary-app-icon" + }, + { + "size" : "400x240", + "idiom" : "tv", + "filename" : "App Icon - Small.imagestack", + "role" : "primary-app-icon" + }, + { + "size" : "1920x720", + "idiom" : "tv", + "filename" : "Top Shelf Image.imageset", + "role" : "top-shelf-image" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} diff --git a/PureLayout/Example-tvOS/Assets.xcassets/App Icon & Top Shelf Image.brandassets/Top Shelf Image.imageset/Contents.json b/PureLayout/Example-tvOS/Assets.xcassets/App Icon & Top Shelf Image.brandassets/Top Shelf Image.imageset/Contents.json new file mode 100644 index 0000000..0564959 --- /dev/null +++ b/PureLayout/Example-tvOS/Assets.xcassets/App Icon & Top Shelf Image.brandassets/Top Shelf Image.imageset/Contents.json @@ -0,0 +1,12 @@ +{ + "images" : [ + { + "idiom" : "tv", + "scale" : "1x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/PureLayout/Example-tvOS/Assets.xcassets/Contents.json b/PureLayout/Example-tvOS/Assets.xcassets/Contents.json new file mode 100644 index 0000000..da4a164 --- /dev/null +++ b/PureLayout/Example-tvOS/Assets.xcassets/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/PureLayout/Example-tvOS/Assets.xcassets/LaunchImage.launchimage/Contents.json b/PureLayout/Example-tvOS/Assets.xcassets/LaunchImage.launchimage/Contents.json new file mode 100644 index 0000000..29d94c7 --- /dev/null +++ b/PureLayout/Example-tvOS/Assets.xcassets/LaunchImage.launchimage/Contents.json @@ -0,0 +1,15 @@ +{ + "images" : [ + { + "orientation" : "landscape", + "idiom" : "tv", + "extent" : "full-screen", + "minimum-system-version" : "9.0", + "scale" : "1x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/PureLayout/Example-tvOS/Base.lproj/Main.storyboard b/PureLayout/Example-tvOS/Base.lproj/Main.storyboard new file mode 100644 index 0000000..b6a31b8 --- /dev/null +++ b/PureLayout/Example-tvOS/Base.lproj/Main.storyboard @@ -0,0 +1,25 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/PureLayout/Example-tvOS/Info.plist b/PureLayout/Example-tvOS/Info.plist new file mode 100644 index 0000000..4f33860 --- /dev/null +++ b/PureLayout/Example-tvOS/Info.plist @@ -0,0 +1,32 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + APPL + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + 1 + LSRequiresIPhoneOS + + UIMainStoryboardFile + Main + UIRequiredDeviceCapabilities + + arm64 + + + diff --git a/PureLayout/Example-tvOS/TVApp.swift b/PureLayout/Example-tvOS/TVApp.swift new file mode 100644 index 0000000..642ace5 --- /dev/null +++ b/PureLayout/Example-tvOS/TVApp.swift @@ -0,0 +1,45 @@ +// +// TVApp.swift +// Example-tvOS +// +// Copyright (c) 2015 Mickey Reiss Fox +// https://github.com/PureLayout/PureLayout +// +// + +import UIKit +import PureLayout + +class TVViewController: UIViewController { + override func viewDidLoad() { + super.viewDidLoad() + + let views = [UIColor.red, UIColor.green, UIColor.blue] + .map(TVButton.init) + + views.forEach(self.view.addSubview) + + (views as NSArray).autoDistributeViews(along: .horizontal, alignedTo: .horizontal, withFixedSpacing: 50) + views.forEach { view in + view.autoAlignAxis(toSuperviewAxis: .horizontal) + view.autoSetDimension(.height, toSize: 300) + } + } +} + +@UIApplicationMain +class TVAppDelegate: UIResponder, UIApplicationDelegate { + var window: UIWindow? +} + +class TVButton : UIControl { + required init(color: UIColor) { + super.init(frame: CGRect.zero) + self.translatesAutoresizingMaskIntoConstraints = false + self.backgroundColor = color + } + + required init?(coder aDecoder: NSCoder) { + super.init(coder: aDecoder) + } +} diff --git a/PureLayout/PureLayout Frameworks/PureLayout_Mac/PureLayout_Mac.h b/PureLayout/PureLayout Frameworks/PureLayout_Mac/PureLayout_Mac.h deleted file mode 100644 index 12b0532..0000000 --- a/PureLayout/PureLayout Frameworks/PureLayout_Mac/PureLayout_Mac.h +++ /dev/null @@ -1,19 +0,0 @@ -// -// PureLayout_Mac.h -// PureLayout_Mac -// -// Created by Fox, Tyler on 2/1/15. -// -// - -#import - -//! Project version number for PureLayout_Mac. -FOUNDATION_EXPORT double PureLayout_MacVersionNumber; - -//! Project version string for PureLayout_Mac. -FOUNDATION_EXPORT const unsigned char PureLayout_MacVersionString[]; - -// In this header, you should import all the public headers of your framework using statements like #import - -#import diff --git a/PureLayout/PureLayout Frameworks/PureLayout_iOS/PureLayout_iOS.h b/PureLayout/PureLayout Frameworks/PureLayout_iOS/PureLayout_iOS.h deleted file mode 100644 index 61c919a..0000000 --- a/PureLayout/PureLayout Frameworks/PureLayout_iOS/PureLayout_iOS.h +++ /dev/null @@ -1,19 +0,0 @@ -// -// PureLayout_iOS.h -// PureLayout_iOS -// -// Created by Fox, Tyler on 2/1/15. -// -// - -#import - -//! Project version number for PureLayout_iOS. -FOUNDATION_EXPORT double PureLayout_iOSVersionNumber; - -//! Project version string for PureLayout_iOS. -FOUNDATION_EXPORT const unsigned char PureLayout_iOSVersionString[]; - -// In this header, you should import all the public headers of your framework using statements like #import - -#import diff --git a/PureLayout/PureLayout.xcodeproj/project.pbxproj b/PureLayout/PureLayout.xcodeproj/project.pbxproj index 6c647a0..acaa292 100644 --- a/PureLayout/PureLayout.xcodeproj/project.pbxproj +++ b/PureLayout/PureLayout.xcodeproj/project.pbxproj @@ -7,6 +7,57 @@ objects = { /* Begin PBXBuildFile section */ + 164C8B511C0D354E0007A6B1 /* TVApp.swift in Sources */ = {isa = PBXBuildFile; fileRef = 164C8B501C0D354E0007A6B1 /* TVApp.swift */; }; + 164C8B561C0D354E0007A6B1 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 164C8B541C0D354E0007A6B1 /* Main.storyboard */; }; + 164C8B581C0D354F0007A6B1 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 164C8B571C0D354F0007A6B1 /* Assets.xcassets */; }; + 164C8B741C0D36500007A6B1 /* NSArray+PureLayout.m in Sources */ = {isa = PBXBuildFile; fileRef = B1046A871A7F2C700017187F /* NSArray+PureLayout.m */; }; + 164C8B751C0D36500007A6B1 /* ALView+PureLayout.m in Sources */ = {isa = PBXBuildFile; fileRef = B1046A851A7F2C700017187F /* ALView+PureLayout.m */; }; + 164C8B761C0D36500007A6B1 /* NSLayoutConstraint+PureLayout.m in Sources */ = {isa = PBXBuildFile; fileRef = B1046A891A7F2C700017187F /* NSLayoutConstraint+PureLayout.m */; }; + 164C8B791C0D36500007A6B1 /* NSArray+PureLayout.h in Headers */ = {isa = PBXBuildFile; fileRef = B1046A861A7F2C700017187F /* NSArray+PureLayout.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 164C8B7A1C0D36500007A6B1 /* ALView+PureLayout.h in Headers */ = {isa = PBXBuildFile; fileRef = B1046A841A7F2C700017187F /* ALView+PureLayout.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 164C8B7B1C0D36500007A6B1 /* NSLayoutConstraint+PureLayout.h in Headers */ = {isa = PBXBuildFile; fileRef = B1046A881A7F2C700017187F /* NSLayoutConstraint+PureLayout.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 164C8B7C1C0D36500007A6B1 /* PureLayoutDefines.h in Headers */ = {isa = PBXBuildFile; fileRef = B1046A8C1A7F2C700017187F /* PureLayoutDefines.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 164C8B7D1C0D36500007A6B1 /* PureLayout+Internal.h in Headers */ = {isa = PBXBuildFile; fileRef = B1046A8A1A7F2C700017187F /* PureLayout+Internal.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 164C8B7E1C0D36500007A6B1 /* PureLayout.h in Headers */ = {isa = PBXBuildFile; fileRef = B1046A8B1A7F2C700017187F /* PureLayout.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 164C8B8C1C0D37C70007A6B1 /* PureLayout.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 164C8B831C0D36500007A6B1 /* PureLayout.framework */; }; + 164C8B8D1C0D37C70007A6B1 /* PureLayout.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 164C8B831C0D36500007A6B1 /* PureLayout.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; + 567E6C881C4125C60031B78F /* ALiOSDemo11ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 567E6C861C4125C60031B78F /* ALiOSDemo11ViewController.m */; }; + 567E6C891C4126CF0031B78F /* iOSDemo11ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 567E6C831C41240E0031B78F /* iOSDemo11ViewController.swift */; }; + A7371DC31B68792800DB94B6 /* PureLayoutBatchTests.m in Sources */ = {isa = PBXBuildFile; fileRef = A7371DC21B68792800DB94B6 /* PureLayoutBatchTests.m */; }; + A7371DC41B68792800DB94B6 /* PureLayoutBatchTests.m in Sources */ = {isa = PBXBuildFile; fileRef = A7371DC21B68792800DB94B6 /* PureLayoutBatchTests.m */; }; + A7D0FF361B8146370025AF37 /* PureLayoutIdentifierTests.m in Sources */ = {isa = PBXBuildFile; fileRef = A7D0FF351B8146370025AF37 /* PureLayoutIdentifierTests.m */; }; + A7D0FF371B8146370025AF37 /* PureLayoutIdentifierTests.m in Sources */ = {isa = PBXBuildFile; fileRef = A7D0FF351B8146370025AF37 /* PureLayoutIdentifierTests.m */; }; + A7D496591B7B084800A74818 /* ALiOSDemo2ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = B13DFF2319E773D100B26152 /* ALiOSDemo2ViewController.m */; }; + A7D4965A1B7B084800A74818 /* iOSDemo8ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = A7DB5C951B7AEC83000ED37F /* iOSDemo8ViewController.swift */; }; + A7D4965B1B7B084800A74818 /* ALiOSDemo5ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = B162DF6B19E9F6A800D56FEA /* ALiOSDemo5ViewController.m */; }; + A7D4965C1B7B084800A74818 /* iOSDemo4ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = A7DB5C8D1B7AE33C000ED37F /* iOSDemo4ViewController.swift */; }; + A7D4965D1B7B084800A74818 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = B139A5111956334500F33B19 /* main.m */; }; + A7D4965E1B7B084800A74818 /* iOSDemo6ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = A7DB5C911B7AE756000ED37F /* iOSDemo6ViewController.swift */; }; + A7D4965F1B7B084800A74818 /* iOSDemo2ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = A7DB5C891B7ADF7D000ED37F /* iOSDemo2ViewController.swift */; }; + A7D496601B7B084800A74818 /* iOSDemo5ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = A7DB5C8F1B7AE5B9000ED37F /* iOSDemo5ViewController.swift */; }; + A7D496611B7B084800A74818 /* ALiOSDemo10ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = B1B9C68B1A1E6FC200E50B6A /* ALiOSDemo10ViewController.m */; }; + A7D496621B7B084800A74818 /* ALiOSDemo1ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = B1006C6F19E76D4200B92767 /* ALiOSDemo1ViewController.m */; }; + A7D496631B7B084800A74818 /* iOSDemo1ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = A7DB5C861B7AD92B000ED37F /* iOSDemo1ViewController.swift */; }; + A7D496641B7B084800A74818 /* ALiOSDemo6ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = B162DF6E19E9FB2300D56FEA /* ALiOSDemo6ViewController.m */; }; + A7D496651B7B084800A74818 /* ALiOSDemo8ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = B162DF7419EB343000D56FEA /* ALiOSDemo8ViewController.m */; }; + A7D496661B7B084800A74818 /* iOSDemo3ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = A7DB5C8B1B7AE28D000ED37F /* iOSDemo3ViewController.swift */; }; + A7D496671B7B084800A74818 /* ALiOSDemo3ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = B13DFF2519E773D100B26152 /* ALiOSDemo3ViewController.m */; }; + A7D496681B7B084800A74818 /* ALiOSAppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = B139A5011956330800F33B19 /* ALiOSAppDelegate.m */; }; + A7D496691B7B084800A74818 /* ALiOSDemo9ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = B162DF7719EB3A4500D56FEA /* ALiOSDemo9ViewController.m */; }; + A7D4966A1B7B084800A74818 /* iOSDemo9ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = A7D4964F1B7AF1D100A74818 /* iOSDemo9ViewController.swift */; }; + A7D4966B1B7B084800A74818 /* ALiOSDemoListController.m in Sources */ = {isa = PBXBuildFile; fileRef = B1006C6819E7691D00B92767 /* ALiOSDemoListController.m */; }; + A7D4966C1B7B084800A74818 /* iOSDemo10ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = A7D496511B7AF44D00A74818 /* iOSDemo10ViewController.swift */; }; + A7D4966D1B7B084800A74818 /* iOSDemo7ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = A7DB5C931B7AE854000ED37F /* iOSDemo7ViewController.swift */; }; + A7D4966E1B7B084800A74818 /* ALiOSDemo7ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = B162DF7119EB2BAB00D56FEA /* ALiOSDemo7ViewController.m */; }; + A7D4966F1B7B084800A74818 /* ALiOSDemo4ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = B162DF6819E9F0D700D56FEA /* ALiOSDemo4ViewController.m */; }; + A7D496711B7B084800A74818 /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = B12C23DE17C3FDE4001CF667 /* UIKit.framework */; }; + A7D496721B7B084800A74818 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = B12C23E017C3FDE4001CF667 /* Foundation.framework */; }; + A7D496731B7B084800A74818 /* PureLayout.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = B1046AB01A7F32380017187F /* PureLayout.framework */; }; + A7D496741B7B084800A74818 /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = B12C23E217C3FDE4001CF667 /* CoreGraphics.framework */; }; + A7D496761B7B084800A74818 /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = B1089C0A1957767400339027 /* Localizable.strings */; }; + A7D496771B7B084800A74818 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = B139A50D1956333500F33B19 /* InfoPlist.strings */; }; + A7D496781B7B084800A74818 /* Images-iOS.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = B125489319C29D2A00DDD7BF /* Images-iOS.xcassets */; }; + A7D4967A1B7B084800A74818 /* PureLayout.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = B1046AB01A7F32380017187F /* PureLayout.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; B1006C6919E7691D00B92767 /* ALiOSDemoListController.m in Sources */ = {isa = PBXBuildFile; fileRef = B1006C6819E7691D00B92767 /* ALiOSDemoListController.m */; }; B1006C7019E76D4200B92767 /* ALiOSDemo1ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = B1006C6F19E76D4200B92767 /* ALiOSDemo1ViewController.m */; }; B1046A811A7F29F80017187F /* PureLayoutDistributeTests.m in Sources */ = {isa = PBXBuildFile; fileRef = B1046A801A7F29F80017187F /* PureLayoutDistributeTests.m */; }; @@ -15,13 +66,13 @@ B1046AA01A7F2D050017187F /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = B1046A9A1A7F2CDA0017187F /* InfoPlist.strings */; }; B1046AA31A7F2D520017187F /* PureLayoutPriorityTests-iOS.m in Sources */ = {isa = PBXBuildFile; fileRef = B1046AA21A7F2D520017187F /* PureLayoutPriorityTests-iOS.m */; }; B1046AA91A7F2D670017187F /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = B1046AA71A7F2D670017187F /* InfoPlist.strings */; }; - B1046AC71A7F32380017187F /* PureLayout_iOS.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = B1046AB01A7F32380017187F /* PureLayout_iOS.framework */; }; - B1046AC81A7F32380017187F /* PureLayout_iOS.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = B1046AB01A7F32380017187F /* PureLayout_iOS.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; + B1046AC71A7F32380017187F /* PureLayout.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = B1046AB01A7F32380017187F /* PureLayout.framework */; }; + B1046AC81A7F32380017187F /* PureLayout.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = B1046AB01A7F32380017187F /* PureLayout.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; B1046AD01A7F32670017187F /* ALView+PureLayout.m in Sources */ = {isa = PBXBuildFile; fileRef = B1046A851A7F2C700017187F /* ALView+PureLayout.m */; }; B1046AD11A7F32670017187F /* NSArray+PureLayout.m in Sources */ = {isa = PBXBuildFile; fileRef = B1046A871A7F2C700017187F /* NSArray+PureLayout.m */; }; B1046AD21A7F32670017187F /* NSLayoutConstraint+PureLayout.m in Sources */ = {isa = PBXBuildFile; fileRef = B1046A891A7F2C700017187F /* NSLayoutConstraint+PureLayout.m */; }; - B1046AEF1A7F32790017187F /* PureLayout_Mac.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = B1046AD81A7F32790017187F /* PureLayout_Mac.framework */; }; - B1046AF01A7F32790017187F /* PureLayout_Mac.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = B1046AD81A7F32790017187F /* PureLayout_Mac.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; + B1046AEF1A7F32790017187F /* PureLayout.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = B1046AD81A7F32790017187F /* PureLayout.framework */; }; + B1046AF01A7F32790017187F /* PureLayout.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = B1046AD81A7F32790017187F /* PureLayout.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; B1046AF81A7F32890017187F /* ALView+PureLayout.m in Sources */ = {isa = PBXBuildFile; fileRef = B1046A851A7F2C700017187F /* ALView+PureLayout.m */; }; B1046AF91A7F32890017187F /* NSArray+PureLayout.m in Sources */ = {isa = PBXBuildFile; fileRef = B1046A871A7F2C700017187F /* NSArray+PureLayout.m */; }; B1046AFA1A7F32890017187F /* NSLayoutConstraint+PureLayout.m in Sources */ = {isa = PBXBuildFile; fileRef = B1046A891A7F2C700017187F /* NSLayoutConstraint+PureLayout.m */; }; @@ -41,8 +92,6 @@ B1046B0B1A7F38930017187F /* NSLayoutConstraint+PureLayout.m in Sources */ = {isa = PBXBuildFile; fileRef = B1046A891A7F2C700017187F /* NSLayoutConstraint+PureLayout.m */; }; B1046B0D1A7F38930017187F /* NSArray+PureLayout.m in Sources */ = {isa = PBXBuildFile; fileRef = B1046A871A7F2C700017187F /* NSArray+PureLayout.m */; }; B1046B0E1A7F38930017187F /* NSLayoutConstraint+PureLayout.m in Sources */ = {isa = PBXBuildFile; fileRef = B1046A891A7F2C700017187F /* NSLayoutConstraint+PureLayout.m */; }; - B1046B111A7F3A2A0017187F /* PureLayout_iOS.h in Headers */ = {isa = PBXBuildFile; fileRef = B1046B101A7F3A2A0017187F /* PureLayout_iOS.h */; settings = {ATTRIBUTES = (Public, ); }; }; - B1046B151A7F3A3D0017187F /* PureLayout_Mac.h in Headers */ = {isa = PBXBuildFile; fileRef = B1046B141A7F3A3D0017187F /* PureLayout_Mac.h */; settings = {ATTRIBUTES = (Public, ); }; }; B1089C0C1957767400339027 /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = B1089C0A1957767400339027 /* Localizable.strings */; }; B1089C21195787C900339027 /* PureLayoutCenteringTests.m in Sources */ = {isa = PBXBuildFile; fileRef = B1089C1A195787C900339027 /* PureLayoutCenteringTests.m */; }; B1089C22195787C900339027 /* PureLayoutCenteringTests.m in Sources */ = {isa = PBXBuildFile; fileRef = B1089C1A195787C900339027 /* PureLayoutCenteringTests.m */; }; @@ -89,6 +138,27 @@ /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ + 164C8B8E1C0D37C70007A6B1 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = B12C23D317C3FDE4001CF667 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 164C8B721C0D36500007A6B1; + remoteInfo = PureLayout_tvOS; + }; + 6D207E9A1E2E99EB00CCDD7C /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = B12C23D317C3FDE4001CF667 /* Project object */; + proxyType = 1; + remoteGlobalIDString = B1A290DA19562FDA00D4765E; + remoteInfo = "Example-Mac"; + }; + A7D496571B7B084800A74818 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = B12C23D317C3FDE4001CF667 /* Project object */; + proxyType = 1; + remoteGlobalIDString = B1046AAF1A7F32380017187F; + remoteInfo = "PureLayout-iOS"; + }; B1046AC51A7F32380017187F /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = B12C23D317C3FDE4001CF667 /* Project object */; @@ -110,23 +180,38 @@ remoteGlobalIDString = B12C23DA17C3FDE4001CF667; remoteInfo = "Example-iOS"; }; - B1046B1B1A7F4A680017187F /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = B12C23D317C3FDE4001CF667 /* Project object */; - proxyType = 1; - remoteGlobalIDString = B1A290DA19562FDA00D4765E; - remoteInfo = "Example-Mac"; - }; /* End PBXContainerItemProxy section */ /* Begin PBXCopyFilesBuildPhase section */ + 164C8B901C0D37C70007A6B1 /* Embed Frameworks */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = ""; + dstSubfolderSpec = 10; + files = ( + 164C8B8D1C0D37C70007A6B1 /* PureLayout.framework in Embed Frameworks */, + ); + name = "Embed Frameworks"; + runOnlyForDeploymentPostprocessing = 0; + }; + A7D496791B7B084800A74818 /* Embed Frameworks */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = ""; + dstSubfolderSpec = 10; + files = ( + A7D4967A1B7B084800A74818 /* PureLayout.framework in Embed Frameworks */, + ); + name = "Embed Frameworks"; + runOnlyForDeploymentPostprocessing = 0; + }; B1046ACC1A7F32390017187F /* Embed Frameworks */ = { isa = PBXCopyFilesBuildPhase; buildActionMask = 2147483647; dstPath = ""; dstSubfolderSpec = 10; files = ( - B1046AC81A7F32380017187F /* PureLayout_iOS.framework in Embed Frameworks */, + B1046AC81A7F32380017187F /* PureLayout.framework in Embed Frameworks */, ); name = "Embed Frameworks"; runOnlyForDeploymentPostprocessing = 0; @@ -137,7 +222,7 @@ dstPath = ""; dstSubfolderSpec = 10; files = ( - B1046AF01A7F32790017187F /* PureLayout_Mac.framework in Embed Frameworks */, + B1046AF01A7F32790017187F /* PureLayout.framework in Embed Frameworks */, ); name = "Embed Frameworks"; runOnlyForDeploymentPostprocessing = 0; @@ -145,20 +230,46 @@ /* End PBXCopyFilesBuildPhase section */ /* Begin PBXFileReference section */ + 164C8B4E1C0D354E0007A6B1 /* Example-tvOS.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "Example-tvOS.app"; sourceTree = BUILT_PRODUCTS_DIR; }; + 164C8B501C0D354E0007A6B1 /* TVApp.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TVApp.swift; sourceTree = ""; }; + 164C8B551C0D354E0007A6B1 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; + 164C8B571C0D354F0007A6B1 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; + 164C8B591C0D354F0007A6B1 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 164C8B831C0D36500007A6B1 /* PureLayout.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = PureLayout.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 164C8B921C0D380E0007A6B1 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 567E6C831C41240E0031B78F /* iOSDemo11ViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = iOSDemo11ViewController.swift; path = "Example-iOS/Demos/iOSDemo11ViewController.swift"; sourceTree = SOURCE_ROOT; }; + 567E6C851C4125C60031B78F /* ALiOSDemo11ViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ALiOSDemo11ViewController.h; path = "Example-iOS/Demos/ALiOSDemo11ViewController.h"; sourceTree = SOURCE_ROOT; }; + 567E6C861C4125C60031B78F /* ALiOSDemo11ViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = ALiOSDemo11ViewController.m; path = "Example-iOS/Demos/ALiOSDemo11ViewController.m"; sourceTree = SOURCE_ROOT; }; + A7371DC21B68792800DB94B6 /* PureLayoutBatchTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = PureLayoutBatchTests.m; path = PureLayoutTests/PureLayoutBatchTests.m; sourceTree = ""; }; + A7D0FF351B8146370025AF37 /* PureLayoutIdentifierTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = PureLayoutIdentifierTests.m; path = PureLayoutTests/PureLayoutIdentifierTests.m; sourceTree = ""; }; + A7D4964F1B7AF1D100A74818 /* iOSDemo9ViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = iOSDemo9ViewController.swift; path = "Example-iOS/Demos/iOSDemo9ViewController.swift"; sourceTree = SOURCE_ROOT; }; + A7D496511B7AF44D00A74818 /* iOSDemo10ViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = iOSDemo10ViewController.swift; path = "Example-iOS/Demos/iOSDemo10ViewController.swift"; sourceTree = SOURCE_ROOT; }; + A7D4967E1B7B084800A74818 /* Example-iOS-Xcode7.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "Example-iOS-Xcode7.app"; sourceTree = BUILT_PRODUCTS_DIR; }; + A7DB5C821B7AD612000ED37F /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + A7DB5C841B7AD612000ED37F /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + A7DB5C861B7AD92B000ED37F /* iOSDemo1ViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = iOSDemo1ViewController.swift; path = "Example-iOS/Demos/iOSDemo1ViewController.swift"; sourceTree = SOURCE_ROOT; }; + A7DB5C881B7AD982000ED37F /* Example-iOS-Bridging-Header.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "Example-iOS-Bridging-Header.h"; path = "Example-iOS/Example-iOS-Bridging-Header.h"; sourceTree = SOURCE_ROOT; }; + A7DB5C891B7ADF7D000ED37F /* iOSDemo2ViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = iOSDemo2ViewController.swift; path = "Example-iOS/Demos/iOSDemo2ViewController.swift"; sourceTree = SOURCE_ROOT; }; + A7DB5C8B1B7AE28D000ED37F /* iOSDemo3ViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = iOSDemo3ViewController.swift; path = "Example-iOS/Demos/iOSDemo3ViewController.swift"; sourceTree = SOURCE_ROOT; }; + A7DB5C8D1B7AE33C000ED37F /* iOSDemo4ViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = iOSDemo4ViewController.swift; path = "Example-iOS/Demos/iOSDemo4ViewController.swift"; sourceTree = SOURCE_ROOT; }; + A7DB5C8F1B7AE5B9000ED37F /* iOSDemo5ViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = iOSDemo5ViewController.swift; path = "Example-iOS/Demos/iOSDemo5ViewController.swift"; sourceTree = SOURCE_ROOT; }; + A7DB5C911B7AE756000ED37F /* iOSDemo6ViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = iOSDemo6ViewController.swift; path = "Example-iOS/Demos/iOSDemo6ViewController.swift"; sourceTree = SOURCE_ROOT; }; + A7DB5C931B7AE854000ED37F /* iOSDemo7ViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = iOSDemo7ViewController.swift; path = "Example-iOS/Demos/iOSDemo7ViewController.swift"; sourceTree = SOURCE_ROOT; }; + A7DB5C951B7AEC83000ED37F /* iOSDemo8ViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = iOSDemo8ViewController.swift; path = "Example-iOS/Demos/iOSDemo8ViewController.swift"; sourceTree = SOURCE_ROOT; }; B1006C6719E7691D00B92767 /* ALiOSDemoListController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ALiOSDemoListController.h; path = "Example-iOS/ALiOSDemoListController.h"; sourceTree = SOURCE_ROOT; }; B1006C6819E7691D00B92767 /* ALiOSDemoListController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = ALiOSDemoListController.m; path = "Example-iOS/ALiOSDemoListController.m"; sourceTree = SOURCE_ROOT; }; B1006C6E19E76D4200B92767 /* ALiOSDemo1ViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ALiOSDemo1ViewController.h; path = "Example-iOS/Demos/ALiOSDemo1ViewController.h"; sourceTree = SOURCE_ROOT; }; B1006C6F19E76D4200B92767 /* ALiOSDemo1ViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = ALiOSDemo1ViewController.m; path = "Example-iOS/Demos/ALiOSDemo1ViewController.m"; sourceTree = SOURCE_ROOT; }; B1046A801A7F29F80017187F /* PureLayoutDistributeTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = PureLayoutDistributeTests.m; path = PureLayoutTests/PureLayoutDistributeTests.m; sourceTree = ""; }; - B1046A841A7F2C700017187F /* ALView+PureLayout.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "ALView+PureLayout.h"; path = "PureLayout/ALView+PureLayout.h"; sourceTree = ""; }; + B1046A841A7F2C700017187F /* ALView+PureLayout.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "ALView+PureLayout.h"; path = "PureLayout/include/ALView+PureLayout.h"; sourceTree = ""; }; B1046A851A7F2C700017187F /* ALView+PureLayout.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = "ALView+PureLayout.m"; path = "PureLayout/ALView+PureLayout.m"; sourceTree = ""; }; - B1046A861A7F2C700017187F /* NSArray+PureLayout.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "NSArray+PureLayout.h"; path = "PureLayout/NSArray+PureLayout.h"; sourceTree = ""; }; + B1046A861A7F2C700017187F /* NSArray+PureLayout.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "NSArray+PureLayout.h"; path = "PureLayout/include/NSArray+PureLayout.h"; sourceTree = ""; }; B1046A871A7F2C700017187F /* NSArray+PureLayout.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = "NSArray+PureLayout.m"; path = "PureLayout/NSArray+PureLayout.m"; sourceTree = ""; }; - B1046A881A7F2C700017187F /* NSLayoutConstraint+PureLayout.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "NSLayoutConstraint+PureLayout.h"; path = "PureLayout/NSLayoutConstraint+PureLayout.h"; sourceTree = ""; }; + B1046A881A7F2C700017187F /* NSLayoutConstraint+PureLayout.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "NSLayoutConstraint+PureLayout.h"; path = "PureLayout/include/NSLayoutConstraint+PureLayout.h"; sourceTree = ""; }; B1046A891A7F2C700017187F /* NSLayoutConstraint+PureLayout.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = "NSLayoutConstraint+PureLayout.m"; path = "PureLayout/NSLayoutConstraint+PureLayout.m"; sourceTree = ""; }; B1046A8A1A7F2C700017187F /* PureLayout+Internal.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "PureLayout+Internal.h"; path = "PureLayout/PureLayout+Internal.h"; sourceTree = ""; }; - B1046A8B1A7F2C700017187F /* PureLayout.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PureLayout.h; path = PureLayout/PureLayout.h; sourceTree = ""; }; - B1046A8C1A7F2C700017187F /* PureLayoutDefines.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PureLayoutDefines.h; path = PureLayout/PureLayoutDefines.h; sourceTree = ""; }; + B1046A8B1A7F2C700017187F /* PureLayout.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PureLayout.h; path = PureLayout/include/PureLayout.h; sourceTree = ""; }; + B1046A8C1A7F2C700017187F /* PureLayoutDefines.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PureLayoutDefines.h; path = PureLayout/include/PureLayoutDefines.h; sourceTree = ""; }; B1046A9B1A7F2CDA0017187F /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = InfoPlist.strings; sourceTree = ""; }; B1046A9D1A7F2CE80017187F /* PureLayoutTests-Mac-Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = "PureLayoutTests-Mac-Info.plist"; path = "PureLayoutTests/PureLayoutTests-Mac/PureLayoutTests-Mac-Info.plist"; sourceTree = SOURCE_ROOT; }; B1046AA11A7F2D1B0017187F /* PureLayoutTests-Mac-Prefix.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "PureLayoutTests-Mac-Prefix.pch"; path = "PureLayoutTests/PureLayoutTests-Mac/PureLayoutTests-Mac-Prefix.pch"; sourceTree = SOURCE_ROOT; }; @@ -166,12 +277,8 @@ B1046AA41A7F2D5C0017187F /* PureLayoutTests-iOS-Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = "PureLayoutTests-iOS-Info.plist"; path = "PureLayoutTests/PureLayoutTests-iOS/PureLayoutTests-iOS-Info.plist"; sourceTree = SOURCE_ROOT; }; B1046AA81A7F2D670017187F /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = InfoPlist.strings; sourceTree = ""; }; B1046AAA1A7F2D720017187F /* PureLayoutTests-iOS-Prefix.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "PureLayoutTests-iOS-Prefix.pch"; path = "PureLayoutTests/PureLayoutTests-iOS/PureLayoutTests-iOS-Prefix.pch"; sourceTree = SOURCE_ROOT; }; - B1046AB01A7F32380017187F /* PureLayout_iOS.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = PureLayout_iOS.framework; sourceTree = BUILT_PRODUCTS_DIR; }; - B1046AD81A7F32790017187F /* PureLayout_Mac.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = PureLayout_Mac.framework; sourceTree = BUILT_PRODUCTS_DIR; }; - B1046B101A7F3A2A0017187F /* PureLayout_iOS.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PureLayout_iOS.h; path = "PureLayout Frameworks/PureLayout_iOS/PureLayout_iOS.h"; sourceTree = SOURCE_ROOT; }; - B1046B121A7F3A330017187F /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = Info.plist; path = "PureLayout Frameworks/PureLayout_iOS/Info.plist"; sourceTree = SOURCE_ROOT; }; - B1046B141A7F3A3D0017187F /* PureLayout_Mac.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PureLayout_Mac.h; path = "PureLayout Frameworks/PureLayout_Mac/PureLayout_Mac.h"; sourceTree = SOURCE_ROOT; }; - B1046B161A7F3A440017187F /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = Info.plist; path = "PureLayout Frameworks/PureLayout_Mac/Info.plist"; sourceTree = SOURCE_ROOT; }; + B1046AB01A7F32380017187F /* PureLayout.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = PureLayout.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + B1046AD81A7F32790017187F /* PureLayout.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = PureLayout.framework; sourceTree = BUILT_PRODUCTS_DIR; }; B1089C0B1957767400339027 /* ar */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ar; path = "Example-iOS/ar.lproj/Localizable.strings"; sourceTree = SOURCE_ROOT; }; B1089C0D1957767D00339027 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = "Example-iOS/en.lproj/Localizable.strings"; sourceTree = SOURCE_ROOT; }; B1089C1A195787C900339027 /* PureLayoutCenteringTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = PureLayoutCenteringTests.m; path = PureLayoutTests/PureLayoutCenteringTests.m; sourceTree = ""; }; @@ -192,7 +299,6 @@ B139A50E1956333500F33B19 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = "Example-iOS/en.lproj/InfoPlist.strings"; sourceTree = SOURCE_ROOT; }; B139A5101956333C00F33B19 /* ar */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ar; path = "Example-iOS/ar.lproj/InfoPlist.strings"; sourceTree = SOURCE_ROOT; }; B139A5111956334500F33B19 /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = main.m; path = "Example-iOS/main.m"; sourceTree = SOURCE_ROOT; }; - B139A5131956334E00F33B19 /* Example-iOS-Prefix.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "Example-iOS-Prefix.pch"; path = "Example-iOS/Example-iOS-Prefix.pch"; sourceTree = SOURCE_ROOT; }; B13DFF2219E773D100B26152 /* ALiOSDemo2ViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ALiOSDemo2ViewController.h; path = "Example-iOS/Demos/ALiOSDemo2ViewController.h"; sourceTree = SOURCE_ROOT; }; B13DFF2319E773D100B26152 /* ALiOSDemo2ViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = ALiOSDemo2ViewController.m; path = "Example-iOS/Demos/ALiOSDemo2ViewController.m"; sourceTree = SOURCE_ROOT; }; B13DFF2419E773D100B26152 /* ALiOSDemo3ViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ALiOSDemo3ViewController.h; path = "Example-iOS/Demos/ALiOSDemo3ViewController.h"; sourceTree = SOURCE_ROOT; }; @@ -222,7 +328,6 @@ B1A290E219562FDA00D4765E /* ALMacAppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ALMacAppDelegate.m; sourceTree = ""; }; B1A290E419562FDA00D4765E /* Images-Mac.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = "Images-Mac.xcassets"; sourceTree = ""; }; B1A290E719562FDA00D4765E /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/MainMenu.xib; sourceTree = ""; }; - B1A291041956326300D4765E /* Example-Mac-Prefix.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Example-Mac-Prefix.pch"; sourceTree = ""; }; B1B9C68A1A1E6FC200E50B6A /* ALiOSDemo10ViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ALiOSDemo10ViewController.h; path = "Example-iOS/Demos/ALiOSDemo10ViewController.h"; sourceTree = SOURCE_ROOT; }; B1B9C68B1A1E6FC200E50B6A /* ALiOSDemo10ViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = ALiOSDemo10ViewController.m; path = "Example-iOS/Demos/ALiOSDemo10ViewController.m"; sourceTree = SOURCE_ROOT; }; B1EC855D195662790099293C /* PureLayoutTests-iOS.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "PureLayoutTests-iOS.xctest"; sourceTree = BUILT_PRODUCTS_DIR; }; @@ -231,6 +336,32 @@ /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ + 164C8B4B1C0D354E0007A6B1 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 164C8B8C1C0D37C70007A6B1 /* PureLayout.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 164C8B771C0D36500007A6B1 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + A7D496701B7B084800A74818 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + A7D496711B7B084800A74818 /* UIKit.framework in Frameworks */, + A7D496721B7B084800A74818 /* Foundation.framework in Frameworks */, + A7D496731B7B084800A74818 /* PureLayout.framework in Frameworks */, + A7D496741B7B084800A74818 /* CoreGraphics.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; B1046AAC1A7F32380017187F /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; @@ -251,7 +382,7 @@ files = ( B12C23DF17C3FDE4001CF667 /* UIKit.framework in Frameworks */, B12C23E117C3FDE4001CF667 /* Foundation.framework in Frameworks */, - B1046AC71A7F32380017187F /* PureLayout_iOS.framework in Frameworks */, + B1046AC71A7F32380017187F /* PureLayout.framework in Frameworks */, B12C23E317C3FDE4001CF667 /* CoreGraphics.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; @@ -260,7 +391,7 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( - B1046AEF1A7F32790017187F /* PureLayout_Mac.framework in Frameworks */, + B1046AEF1A7F32790017187F /* PureLayout.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -285,7 +416,44 @@ /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ - B1006C6A19E76B8700B92767 /* Demos */ = { + 164C8B4F1C0D354E0007A6B1 /* Example-tvOS */ = { + isa = PBXGroup; + children = ( + 164C8B501C0D354E0007A6B1 /* TVApp.swift */, + 164C8B541C0D354E0007A6B1 /* Main.storyboard */, + 164C8B571C0D354F0007A6B1 /* Assets.xcassets */, + 164C8B591C0D354F0007A6B1 /* Info.plist */, + ); + path = "Example-tvOS"; + sourceTree = ""; + }; + 164C8B911C0D380E0007A6B1 /* PureLayout_tvOS */ = { + isa = PBXGroup; + children = ( + 164C8B921C0D380E0007A6B1 /* Info.plist */, + ); + path = PureLayout_tvOS; + sourceTree = ""; + }; + A7D496531B7AF95E00A74818 /* Swift */ = { + isa = PBXGroup; + children = ( + A7DB5C861B7AD92B000ED37F /* iOSDemo1ViewController.swift */, + A7DB5C891B7ADF7D000ED37F /* iOSDemo2ViewController.swift */, + A7DB5C8B1B7AE28D000ED37F /* iOSDemo3ViewController.swift */, + A7DB5C8D1B7AE33C000ED37F /* iOSDemo4ViewController.swift */, + A7DB5C8F1B7AE5B9000ED37F /* iOSDemo5ViewController.swift */, + A7DB5C911B7AE756000ED37F /* iOSDemo6ViewController.swift */, + A7DB5C931B7AE854000ED37F /* iOSDemo7ViewController.swift */, + A7DB5C951B7AEC83000ED37F /* iOSDemo8ViewController.swift */, + A7D4964F1B7AF1D100A74818 /* iOSDemo9ViewController.swift */, + A7D496511B7AF44D00A74818 /* iOSDemo10ViewController.swift */, + 567E6C831C41240E0031B78F /* iOSDemo11ViewController.swift */, + ); + name = Swift; + sourceTree = ""; + }; + A7D496541B7AF97A00A74818 /* Objective-C */ = { isa = PBXGroup; children = ( B1006C6E19E76D4200B92767 /* ALiOSDemo1ViewController.h */, @@ -308,63 +476,64 @@ B162DF7719EB3A4500D56FEA /* ALiOSDemo9ViewController.m */, B1B9C68A1A1E6FC200E50B6A /* ALiOSDemo10ViewController.h */, B1B9C68B1A1E6FC200E50B6A /* ALiOSDemo10ViewController.m */, + 567E6C851C4125C60031B78F /* ALiOSDemo11ViewController.h */, + 567E6C861C4125C60031B78F /* ALiOSDemo11ViewController.m */, ); - name = Demos; + name = "Objective-C"; sourceTree = ""; }; - B1046A991A7F2CDA0017187F /* en.lproj */ = { + A7DB5C801B7AD612000ED37F /* Supporting Files */ = { isa = PBXGroup; children = ( - B1046A9A1A7F2CDA0017187F /* InfoPlist.strings */, + A7DB5C811B7AD612000ED37F /* PureLayout_iOS */, + A7DB5C831B7AD612000ED37F /* PureLayout_Mac */, + 164C8B911C0D380E0007A6B1 /* PureLayout_tvOS */, ); - name = en.lproj; - path = "PureLayoutTests/PureLayoutTests-Mac/en.lproj"; - sourceTree = SOURCE_ROOT; + path = "Supporting Files"; + sourceTree = ""; }; - B1046AA61A7F2D670017187F /* en.lproj */ = { + A7DB5C811B7AD612000ED37F /* PureLayout_iOS */ = { isa = PBXGroup; children = ( - B1046AA71A7F2D670017187F /* InfoPlist.strings */, + A7DB5C821B7AD612000ED37F /* Info.plist */, ); - name = en.lproj; - path = "PureLayoutTests/PureLayoutTests-iOS/en.lproj"; - sourceTree = SOURCE_ROOT; + path = PureLayout_iOS; + sourceTree = ""; }; - B1046AB11A7F32380017187F /* PureLayout_iOS */ = { + A7DB5C831B7AD612000ED37F /* PureLayout_Mac */ = { isa = PBXGroup; children = ( - B1046B101A7F3A2A0017187F /* PureLayout_iOS.h */, - B1046AB21A7F32380017187F /* Supporting Files */, + A7DB5C841B7AD612000ED37F /* Info.plist */, ); - name = PureLayout_iOS; - path = "PureLayout-iOS"; + path = PureLayout_Mac; sourceTree = ""; }; - B1046AB21A7F32380017187F /* Supporting Files */ = { + B1006C6A19E76B8700B92767 /* Demos */ = { isa = PBXGroup; children = ( - B1046B121A7F3A330017187F /* Info.plist */, + A7D496531B7AF95E00A74818 /* Swift */, + A7D496541B7AF97A00A74818 /* Objective-C */, ); - name = "Supporting Files"; + name = Demos; sourceTree = ""; }; - B1046AD91A7F32790017187F /* PureLayout_Mac */ = { + B1046A991A7F2CDA0017187F /* en.lproj */ = { isa = PBXGroup; children = ( - B1046B141A7F3A3D0017187F /* PureLayout_Mac.h */, - B1046ADA1A7F32790017187F /* Supporting Files */, + B1046A9A1A7F2CDA0017187F /* InfoPlist.strings */, ); - name = PureLayout_Mac; - path = "PureLayout-Mac"; - sourceTree = ""; + name = en.lproj; + path = "PureLayoutTests/PureLayoutTests-Mac/en.lproj"; + sourceTree = SOURCE_ROOT; }; - B1046ADA1A7F32790017187F /* Supporting Files */ = { + B1046AA61A7F2D670017187F /* en.lproj */ = { isa = PBXGroup; children = ( - B1046B161A7F3A440017187F /* Info.plist */, + B1046AA71A7F2D670017187F /* InfoPlist.strings */, ); - name = "Supporting Files"; - sourceTree = ""; + name = en.lproj; + path = "PureLayoutTests/PureLayoutTests-iOS/en.lproj"; + sourceTree = SOURCE_ROOT; }; B1046AFC1A7F33110017187F /* PureLayout */ = { isa = PBXGroup; @@ -382,23 +551,15 @@ name = PureLayout; sourceTree = ""; }; - B1046B0F1A7F3A0F0017187F /* PureLayout Frameworks */ = { - isa = PBXGroup; - children = ( - B1046AB11A7F32380017187F /* PureLayout_iOS */, - B1046AD91A7F32790017187F /* PureLayout_Mac */, - ); - name = "PureLayout Frameworks"; - sourceTree = ""; - }; B12C23D217C3FDE4001CF667 = { isa = PBXGroup; children = ( B1046AFC1A7F33110017187F /* PureLayout */, - B1046B0F1A7F3A0F0017187F /* PureLayout Frameworks */, B1EC853F1956620F0099293C /* PureLayoutTests */, B12C23E417C3FDE4001CF667 /* Example-iOS */, B1A290DC19562FDA00D4765E /* Example-Mac */, + 164C8B4F1C0D354E0007A6B1 /* Example-tvOS */, + A7DB5C801B7AD612000ED37F /* Supporting Files */, B12C23DD17C3FDE4001CF667 /* Frameworks */, B12C23DC17C3FDE4001CF667 /* Products */, ); @@ -411,8 +572,11 @@ B1A290DB19562FDA00D4765E /* Example-Mac.app */, B1EC855D195662790099293C /* PureLayoutTests-iOS.xctest */, B1EC857C195662B40099293C /* PureLayoutTests-Mac.xctest */, - B1046AB01A7F32380017187F /* PureLayout_iOS.framework */, - B1046AD81A7F32790017187F /* PureLayout_Mac.framework */, + B1046AB01A7F32380017187F /* PureLayout.framework */, + B1046AD81A7F32790017187F /* PureLayout.framework */, + A7D4967E1B7B084800A74818 /* Example-iOS-Xcode7.app */, + 164C8B4E1C0D354E0007A6B1 /* Example-tvOS.app */, + 164C8B831C0D36500007A6B1 /* PureLayout.framework */, ); name = Products; sourceTree = ""; @@ -439,17 +603,16 @@ B125489319C29D2A00DDD7BF /* Images-iOS.xcassets */, B12C23E517C3FDE4001CF667 /* Supporting Files */, ); - name = "Example-iOS"; - path = Example; + path = "Example-iOS"; sourceTree = ""; }; B12C23E517C3FDE4001CF667 /* Supporting Files */ = { isa = PBXGroup; children = ( + A7DB5C881B7AD982000ED37F /* Example-iOS-Bridging-Header.h */, B139A50B1956332D00F33B19 /* Example-iOS-Info.plist */, B139A50D1956333500F33B19 /* InfoPlist.strings */, B139A5111956334500F33B19 /* main.m */, - B139A5131956334E00F33B19 /* Example-iOS-Prefix.pch */, B1089C0A1957767400339027 /* Localizable.strings */, ); name = "Supporting Files"; @@ -474,7 +637,6 @@ children = ( B1A290DE19562FDA00D4765E /* Example-Mac-Info.plist */, B1A290DF19562FDA00D4765E /* main.m */, - B1A291041956326300D4765E /* Example-Mac-Prefix.pch */, B17D24CD1957763300F2FD4B /* Localizable.strings */, ); name = "Supporting Files"; @@ -485,7 +647,9 @@ children = ( B17D24C81956648700F2FD4B /* PureLayoutTestBase.h */, B17D24C91956648700F2FD4B /* PureLayoutTestBase.m */, + A7371DC21B68792800DB94B6 /* PureLayoutBatchTests.m */, B1089C1A195787C900339027 /* PureLayoutCenteringTests.m */, + A7D0FF351B8146370025AF37 /* PureLayoutIdentifierTests.m */, B1089C1B195787C900339027 /* PureLayoutInstallationTests.m */, B1089C1C195787C900339027 /* PureLayoutInstantiationTests.m */, B1089C1D195787C900339027 /* PureLayoutInternalTests.m */, @@ -505,7 +669,8 @@ B1046AA21A7F2D520017187F /* PureLayoutPriorityTests-iOS.m */, B1EC8563195662790099293C /* Supporting Files */, ); - path = "PureLayoutTests-iOS"; + name = "PureLayoutTests-iOS"; + path = "PureLayoutTests/PureLayoutTests-iOS"; sourceTree = ""; }; B1EC8563195662790099293C /* Supporting Files */ = { @@ -523,7 +688,8 @@ children = ( B1EC857F195662B40099293C /* Supporting Files */, ); - path = "PureLayoutTests-Mac"; + name = "PureLayoutTests-Mac"; + path = "PureLayoutTests/PureLayoutTests-Mac"; sourceTree = ""; }; B1EC857F195662B40099293C /* Supporting Files */ = { @@ -539,11 +705,23 @@ /* End PBXGroup section */ /* Begin PBXHeadersBuildPhase section */ + 164C8B781C0D36500007A6B1 /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + 164C8B791C0D36500007A6B1 /* NSArray+PureLayout.h in Headers */, + 164C8B7A1C0D36500007A6B1 /* ALView+PureLayout.h in Headers */, + 164C8B7B1C0D36500007A6B1 /* NSLayoutConstraint+PureLayout.h in Headers */, + 164C8B7C1C0D36500007A6B1 /* PureLayoutDefines.h in Headers */, + 164C8B7D1C0D36500007A6B1 /* PureLayout+Internal.h in Headers */, + 164C8B7E1C0D36500007A6B1 /* PureLayout.h in Headers */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; B1046AAD1A7F32380017187F /* Headers */ = { isa = PBXHeadersBuildPhase; buildActionMask = 2147483647; files = ( - B1046B111A7F3A2A0017187F /* PureLayout_iOS.h in Headers */, B1046AFF1A7F37100017187F /* NSArray+PureLayout.h in Headers */, B1046AFD1A7F37060017187F /* ALView+PureLayout.h in Headers */, B1046B001A7F37100017187F /* NSLayoutConstraint+PureLayout.h in Headers */, @@ -562,7 +740,6 @@ B1046B051A7F37110017187F /* NSLayoutConstraint+PureLayout.h in Headers */, B1046B081A7F37110017187F /* PureLayoutDefines.h in Headers */, B1046B061A7F37110017187F /* PureLayout+Internal.h in Headers */, - B1046B151A7F3A3D0017187F /* PureLayout_Mac.h in Headers */, B1046B071A7F37110017187F /* PureLayout.h in Headers */, ); runOnlyForDeploymentPostprocessing = 0; @@ -570,6 +747,62 @@ /* End PBXHeadersBuildPhase section */ /* Begin PBXNativeTarget section */ + 164C8B4D1C0D354E0007A6B1 /* Example-tvOS */ = { + isa = PBXNativeTarget; + buildConfigurationList = 164C8B5C1C0D354F0007A6B1 /* Build configuration list for PBXNativeTarget "Example-tvOS" */; + buildPhases = ( + 164C8B4A1C0D354E0007A6B1 /* Sources */, + 164C8B4B1C0D354E0007A6B1 /* Frameworks */, + 164C8B4C1C0D354E0007A6B1 /* Resources */, + 164C8B901C0D37C70007A6B1 /* Embed Frameworks */, + ); + buildRules = ( + ); + dependencies = ( + 164C8B8F1C0D37C70007A6B1 /* PBXTargetDependency */, + ); + name = "Example-tvOS"; + productName = "Example-tvOS"; + productReference = 164C8B4E1C0D354E0007A6B1 /* Example-tvOS.app */; + productType = "com.apple.product-type.application"; + }; + 164C8B721C0D36500007A6B1 /* PureLayout_tvOS */ = { + isa = PBXNativeTarget; + buildConfigurationList = 164C8B801C0D36500007A6B1 /* Build configuration list for PBXNativeTarget "PureLayout_tvOS" */; + buildPhases = ( + 164C8B731C0D36500007A6B1 /* Sources */, + 164C8B771C0D36500007A6B1 /* Frameworks */, + 164C8B781C0D36500007A6B1 /* Headers */, + 164C8B7F1C0D36500007A6B1 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = PureLayout_tvOS; + productName = "PureLayout-iOS"; + productReference = 164C8B831C0D36500007A6B1 /* PureLayout.framework */; + productType = "com.apple.product-type.framework"; + }; + A7D496551B7B084800A74818 /* Example-iOS-Xcode7 */ = { + isa = PBXNativeTarget; + buildConfigurationList = A7D4967B1B7B084800A74818 /* Build configuration list for PBXNativeTarget "Example-iOS-Xcode7" */; + buildPhases = ( + A7D496581B7B084800A74818 /* Sources */, + A7D496701B7B084800A74818 /* Frameworks */, + A7D496751B7B084800A74818 /* Resources */, + A7D496791B7B084800A74818 /* Embed Frameworks */, + ); + buildRules = ( + ); + dependencies = ( + A7D496561B7B084800A74818 /* PBXTargetDependency */, + ); + name = "Example-iOS-Xcode7"; + productName = Example; + productReference = A7D4967E1B7B084800A74818 /* Example-iOS-Xcode7.app */; + productType = "com.apple.product-type.application"; + }; B1046AAF1A7F32380017187F /* PureLayout_iOS */ = { isa = PBXNativeTarget; buildConfigurationList = B1046AC91A7F32390017187F /* Build configuration list for PBXNativeTarget "PureLayout_iOS" */; @@ -585,7 +818,7 @@ ); name = PureLayout_iOS; productName = "PureLayout-iOS"; - productReference = B1046AB01A7F32380017187F /* PureLayout_iOS.framework */; + productReference = B1046AB01A7F32380017187F /* PureLayout.framework */; productType = "com.apple.product-type.framework"; }; B1046AD71A7F32790017187F /* PureLayout_Mac */ = { @@ -603,7 +836,7 @@ ); name = PureLayout_Mac; productName = "PureLayout-Mac"; - productReference = B1046AD81A7F32790017187F /* PureLayout_Mac.framework */; + productReference = B1046AD81A7F32790017187F /* PureLayout.framework */; productType = "com.apple.product-type.framework"; }; B12C23DA17C3FDE4001CF667 /* Example-iOS */ = { @@ -673,7 +906,7 @@ buildRules = ( ); dependencies = ( - B1046B1C1A7F4A680017187F /* PBXTargetDependency */, + 6D207E9B1E2E99EB00CCDD7C /* PBXTargetDependency */, ); name = "PureLayoutTests-Mac"; productName = "PureLayoutTests-Mac"; @@ -687,21 +920,44 @@ isa = PBXProject; attributes = { CLASSPREFIX = AL; - LastUpgradeCheck = 0600; + LastSwiftUpdateCheck = 0720; + LastUpgradeCheck = 1000; TargetAttributes = { + 164C8B4D1C0D354E0007A6B1 = { + CreatedOnToolsVersion = 7.1; + LastSwiftMigration = 0800; + ProvisioningStyle = Manual; + }; + 164C8B721C0D36500007A6B1 = { + LastSwiftMigration = 0800; + ProvisioningStyle = Manual; + }; + A7D496551B7B084800A74818 = { + LastSwiftMigration = 0800; + ProvisioningStyle = Manual; + }; B1046AAF1A7F32380017187F = { CreatedOnToolsVersion = 6.1.1; + LastSwiftMigration = 0800; + ProvisioningStyle = Manual; }; B1046AD71A7F32790017187F = { CreatedOnToolsVersion = 6.1.1; }; + B12C23DA17C3FDE4001CF667 = { + LastSwiftMigration = 0800; + ProvisioningStyle = Manual; + }; B1A290DA19562FDA00D4765E = { CreatedOnToolsVersion = 6.0; }; B1EC855C195662790099293C = { + LastSwiftMigration = 0800; + ProvisioningStyle = Manual; TestTargetID = B12C23DA17C3FDE4001CF667; }; B1EC857B195662B40099293C = { + ProvisioningStyle = Manual; TestTargetID = B1A290DA19562FDA00D4765E; }; }; @@ -711,6 +967,7 @@ developmentRegion = English; hasScannedForEncodings = 0; knownRegions = ( + English, en, ar, Base, @@ -722,8 +979,11 @@ targets = ( B1046AAF1A7F32380017187F /* PureLayout_iOS */, B1046AD71A7F32790017187F /* PureLayout_Mac */, + 164C8B721C0D36500007A6B1 /* PureLayout_tvOS */, B12C23DA17C3FDE4001CF667 /* Example-iOS */, + A7D496551B7B084800A74818 /* Example-iOS-Xcode7 */, B1A290DA19562FDA00D4765E /* Example-Mac */, + 164C8B4D1C0D354E0007A6B1 /* Example-tvOS */, B1EC855C195662790099293C /* PureLayoutTests-iOS */, B1EC857B195662B40099293C /* PureLayoutTests-Mac */, ); @@ -731,6 +991,32 @@ /* End PBXProject section */ /* Begin PBXResourcesBuildPhase section */ + 164C8B4C1C0D354E0007A6B1 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 164C8B581C0D354F0007A6B1 /* Assets.xcassets in Resources */, + 164C8B561C0D354E0007A6B1 /* Main.storyboard in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 164C8B7F1C0D36500007A6B1 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + A7D496751B7B084800A74818 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + A7D496761B7B084800A74818 /* Localizable.strings in Resources */, + A7D496771B7B084800A74818 /* InfoPlist.strings in Resources */, + A7D496781B7B084800A74818 /* Images-iOS.xcassets in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; B1046AAE1A7F32380017187F /* Resources */ = { isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; @@ -785,10 +1071,60 @@ /* End PBXResourcesBuildPhase section */ /* Begin PBXSourcesBuildPhase section */ + 164C8B4A1C0D354E0007A6B1 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 164C8B511C0D354E0007A6B1 /* TVApp.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 164C8B731C0D36500007A6B1 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 164C8B741C0D36500007A6B1 /* NSArray+PureLayout.m in Sources */, + 164C8B751C0D36500007A6B1 /* ALView+PureLayout.m in Sources */, + 164C8B761C0D36500007A6B1 /* NSLayoutConstraint+PureLayout.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + A7D496581B7B084800A74818 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 567E6C891C4126CF0031B78F /* iOSDemo11ViewController.swift in Sources */, + A7D496591B7B084800A74818 /* ALiOSDemo2ViewController.m in Sources */, + A7D4965A1B7B084800A74818 /* iOSDemo8ViewController.swift in Sources */, + A7D4965B1B7B084800A74818 /* ALiOSDemo5ViewController.m in Sources */, + A7D4965C1B7B084800A74818 /* iOSDemo4ViewController.swift in Sources */, + A7D4965D1B7B084800A74818 /* main.m in Sources */, + A7D4965E1B7B084800A74818 /* iOSDemo6ViewController.swift in Sources */, + A7D4965F1B7B084800A74818 /* iOSDemo2ViewController.swift in Sources */, + A7D496601B7B084800A74818 /* iOSDemo5ViewController.swift in Sources */, + A7D496611B7B084800A74818 /* ALiOSDemo10ViewController.m in Sources */, + A7D496621B7B084800A74818 /* ALiOSDemo1ViewController.m in Sources */, + A7D496631B7B084800A74818 /* iOSDemo1ViewController.swift in Sources */, + A7D496641B7B084800A74818 /* ALiOSDemo6ViewController.m in Sources */, + A7D496651B7B084800A74818 /* ALiOSDemo8ViewController.m in Sources */, + A7D496661B7B084800A74818 /* iOSDemo3ViewController.swift in Sources */, + A7D496671B7B084800A74818 /* ALiOSDemo3ViewController.m in Sources */, + A7D496681B7B084800A74818 /* ALiOSAppDelegate.m in Sources */, + A7D496691B7B084800A74818 /* ALiOSDemo9ViewController.m in Sources */, + A7D4966A1B7B084800A74818 /* iOSDemo9ViewController.swift in Sources */, + A7D4966B1B7B084800A74818 /* ALiOSDemoListController.m in Sources */, + A7D4966C1B7B084800A74818 /* iOSDemo10ViewController.swift in Sources */, + A7D4966D1B7B084800A74818 /* iOSDemo7ViewController.swift in Sources */, + A7D4966E1B7B084800A74818 /* ALiOSDemo7ViewController.m in Sources */, + A7D4966F1B7B084800A74818 /* ALiOSDemo4ViewController.m in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; B1046AAB1A7F32380017187F /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( + 567E6C881C4125C60031B78F /* ALiOSDemo11ViewController.m in Sources */, B1046AD11A7F32670017187F /* NSArray+PureLayout.m in Sources */, B1046AD01A7F32670017187F /* ALView+PureLayout.m in Sources */, B1046AD21A7F32670017187F /* NSLayoutConstraint+PureLayout.m in Sources */, @@ -841,6 +1177,7 @@ files = ( B1089C29195787C900339027 /* PureLayoutPinEdgesTests.m in Sources */, B1089C23195787C900339027 /* PureLayoutInstallationTests.m in Sources */, + A7D0FF361B8146370025AF37 /* PureLayoutIdentifierTests.m in Sources */, B1046B0B1A7F38930017187F /* NSLayoutConstraint+PureLayout.m in Sources */, B1089C27195787C900339027 /* PureLayoutInternalTests.m in Sources */, B1046A811A7F29F80017187F /* PureLayoutDistributeTests.m in Sources */, @@ -851,6 +1188,7 @@ B1089C25195787C900339027 /* PureLayoutInstantiationTests.m in Sources */, B1089C2D195787C900339027 /* PureLayoutRemovalTests.m in Sources */, B1089C2B195787C900339027 /* PureLayoutPriorityTests.m in Sources */, + A7371DC31B68792800DB94B6 /* PureLayoutBatchTests.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -858,6 +1196,7 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( + A7371DC41B68792800DB94B6 /* PureLayoutBatchTests.m in Sources */, B1089C2A195787C900339027 /* PureLayoutPinEdgesTests.m in Sources */, B1089C24195787C900339027 /* PureLayoutInstallationTests.m in Sources */, B1089C28195787C900339027 /* PureLayoutInternalTests.m in Sources */, @@ -865,6 +1204,7 @@ B1089C22195787C900339027 /* PureLayoutCenteringTests.m in Sources */, B1046B0D1A7F38930017187F /* NSArray+PureLayout.m in Sources */, B1089C26195787C900339027 /* PureLayoutInstantiationTests.m in Sources */, + A7D0FF371B8146370025AF37 /* PureLayoutIdentifierTests.m in Sources */, B1089C2E195787C900339027 /* PureLayoutRemovalTests.m in Sources */, B1046A821A7F29F80017187F /* PureLayoutDistributeTests.m in Sources */, B1089C2C195787C900339027 /* PureLayoutPriorityTests.m in Sources */, @@ -875,6 +1215,21 @@ /* End PBXSourcesBuildPhase section */ /* Begin PBXTargetDependency section */ + 164C8B8F1C0D37C70007A6B1 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 164C8B721C0D36500007A6B1 /* PureLayout_tvOS */; + targetProxy = 164C8B8E1C0D37C70007A6B1 /* PBXContainerItemProxy */; + }; + 6D207E9B1E2E99EB00CCDD7C /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = B1A290DA19562FDA00D4765E /* Example-Mac */; + targetProxy = 6D207E9A1E2E99EB00CCDD7C /* PBXContainerItemProxy */; + }; + A7D496561B7B084800A74818 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = B1046AAF1A7F32380017187F /* PureLayout_iOS */; + targetProxy = A7D496571B7B084800A74818 /* PBXContainerItemProxy */; + }; B1046AC61A7F32380017187F /* PBXTargetDependency */ = { isa = PBXTargetDependency; target = B1046AAF1A7F32380017187F /* PureLayout_iOS */; @@ -890,14 +1245,17 @@ target = B12C23DA17C3FDE4001CF667 /* Example-iOS */; targetProxy = B1046B191A7F4A640017187F /* PBXContainerItemProxy */; }; - B1046B1C1A7F4A680017187F /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - target = B1A290DA19562FDA00D4765E /* Example-Mac */; - targetProxy = B1046B1B1A7F4A680017187F /* PBXContainerItemProxy */; - }; /* End PBXTargetDependency section */ /* Begin PBXVariantGroup section */ + 164C8B541C0D354E0007A6B1 /* Main.storyboard */ = { + isa = PBXVariantGroup; + children = ( + 164C8B551C0D354E0007A6B1 /* Base */, + ); + name = Main.storyboard; + sourceTree = ""; + }; B1046A9A1A7F2CDA0017187F /* InfoPlist.strings */ = { isa = PBXVariantGroup; children = ( @@ -952,7 +1310,70 @@ /* End PBXVariantGroup section */ /* Begin XCBuildConfiguration section */ - B1046ACA1A7F32390017187F /* Debug */ = { + 164C8B5A1C0D354F0007A6B1 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = "App Icon & Top Shelf Image"; + ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = LaunchImage; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_UNREACHABLE_CODE = YES; + DEBUG_INFORMATION_FORMAT = dwarf; + DEVELOPMENT_TEAM = ""; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + INFOPLIST_FILE = "Example-tvOS/Info.plist"; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + MTL_ENABLE_DEBUG_INFO = YES; + PRODUCT_BUNDLE_IDENTIFIER = "com.PureLayout.Example-tvOS"; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = appletvos; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_VERSION = 3.0; + TARGETED_DEVICE_FAMILY = 3; + TVOS_DEPLOYMENT_TARGET = 9.0; + }; + name = Debug; + }; + 164C8B5B1C0D354F0007A6B1 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = "App Icon & Top Shelf Image"; + ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = LaunchImage; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_UNREACHABLE_CODE = YES; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + DEVELOPMENT_TEAM = ""; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + INFOPLIST_FILE = "Example-tvOS/Info.plist"; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + MTL_ENABLE_DEBUG_INFO = NO; + PRODUCT_BUNDLE_IDENTIFIER = "com.PureLayout.Example-tvOS"; + PRODUCT_NAME = "$(TARGET_NAME)"; + SDKROOT = appletvos; + SWIFT_VERSION = 3.0; + TARGETED_DEVICE_FAMILY = 3; + TVOS_DEPLOYMENT_TARGET = 9.0; + }; + name = Release; + }; + 164C8B811C0D36500007A6B1 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { CLANG_ENABLE_MODULES = YES; @@ -960,8 +1381,11 @@ CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_UNREACHABLE_CODE = YES; + "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; CURRENT_PROJECT_VERSION = 1; DEFINES_MODULE = YES; + DEVELOPMENT_TEAM = ""; DYLIB_COMPATIBILITY_VERSION = 1; DYLIB_CURRENT_VERSION = 1; DYLIB_INSTALL_NAME_BASE = "@rpath"; @@ -975,13 +1399,144 @@ GCC_WARN_UNDECLARED_SELECTOR = YES; GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; - INFOPLIST_FILE = "PureLayout Frameworks/PureLayout_iOS/Info.plist"; + INFOPLIST_FILE = "Supporting Files/PureLayout_tvOS/Info.plist"; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; - IPHONEOS_DEPLOYMENT_TARGET = 8.1; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; MTL_ENABLE_DEBUG_INFO = YES; + PRODUCT_BUNDLE_IDENTIFIER = "com.PureLayout.$(PRODUCT_NAME:rfc1034identifier)"; + PRODUCT_NAME = PureLayout; + SDKROOT = appletvos; + SKIP_INSTALL = YES; + SWIFT_VERSION = 3.0; + TARGETED_DEVICE_FAMILY = 3; + TVOS_DEPLOYMENT_TARGET = 9.0; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Debug; + }; + 164C8B821C0D36500007A6B1 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + CLANG_ENABLE_MODULES = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_UNREACHABLE_CODE = YES; + "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DEVELOPMENT_TEAM = ""; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + INFOPLIST_FILE = "Supporting Files/PureLayout_tvOS/Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + MTL_ENABLE_DEBUG_INFO = NO; + PRODUCT_BUNDLE_IDENTIFIER = "com.PureLayout.$(PRODUCT_NAME:rfc1034identifier)"; + PRODUCT_NAME = PureLayout; + SDKROOT = appletvos; + SKIP_INSTALL = YES; + SWIFT_VERSION = 3.0; + TARGETED_DEVICE_FAMILY = 3; + TVOS_DEPLOYMENT_TARGET = 9.0; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Release; + }; + A7D4967C1B7B084800A74818 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = LaunchImage; + CLANG_ENABLE_MODULES = YES; + DEVELOPMENT_TEAM = ""; + GCC_PREPROCESSOR_DEFINITIONS = ( + "$(inherited)", + "USING_XCODE7_SCHEME=1", + ); + INFOPLIST_FILE = "Example-iOS/Example-iOS-Info.plist"; + INFOPLIST_OUTPUT_FORMAT = "same-as-input"; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + PRODUCT_BUNDLE_IDENTIFIER = "com.PureLayout.${PRODUCT_NAME:rfc1034identifier}"; PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_OBJC_BRIDGING_HEADER = "Example-iOS/Example-iOS-Bridging-Header.h"; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_VERSION = 3.0; + TARGETED_DEVICE_FAMILY = "1,2"; + WRAPPER_EXTENSION = app; + }; + name = Debug; + }; + A7D4967D1B7B084800A74818 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = LaunchImage; + CLANG_ENABLE_MODULES = YES; + DEVELOPMENT_TEAM = ""; + GCC_PREPROCESSOR_DEFINITIONS = ( + "$(inherited)", + "USING_XCODE7_SCHEME=1", + ); + INFOPLIST_FILE = "Example-iOS/Example-iOS-Info.plist"; + INFOPLIST_OUTPUT_FORMAT = "same-as-input"; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + PRODUCT_BUNDLE_IDENTIFIER = "com.PureLayout.${PRODUCT_NAME:rfc1034identifier}"; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_OBJC_BRIDGING_HEADER = "Example-iOS/Example-iOS-Bridging-Header.h"; + SWIFT_VERSION = 3.0; + TARGETED_DEVICE_FAMILY = "1,2"; + WRAPPER_EXTENSION = app; + }; + name = Release; + }; + B1046ACA1A7F32390017187F /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + APPLICATION_EXTENSION_API_ONLY = YES; + CLANG_ENABLE_MODULES = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DEVELOPMENT_TEAM = ""; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + INFOPLIST_FILE = "Supporting Files/PureLayout_iOS/Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + MTL_ENABLE_DEBUG_INFO = YES; + PRODUCT_BUNDLE_IDENTIFIER = "com.PureLayout.$(PRODUCT_NAME:rfc1034identifier)"; + PRODUCT_NAME = PureLayout; SKIP_INSTALL = YES; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_VERSION = 3.0; TARGETED_DEVICE_FAMILY = "1,2"; VERSIONING_SYSTEM = "apple-generic"; VERSION_INFO_PREFIX = ""; @@ -991,13 +1546,17 @@ B1046ACB1A7F32390017187F /* Release */ = { isa = XCBuildConfiguration; buildSettings = { + APPLICATION_EXTENSION_API_ONLY = YES; CLANG_ENABLE_MODULES = YES; CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; CLANG_WARN_UNREACHABLE_CODE = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; CURRENT_PROJECT_VERSION = 1; DEFINES_MODULE = YES; + DEVELOPMENT_TEAM = ""; DYLIB_COMPATIBILITY_VERSION = 1; DYLIB_CURRENT_VERSION = 1; DYLIB_INSTALL_NAME_BASE = "@rpath"; @@ -1008,13 +1567,14 @@ GCC_WARN_UNDECLARED_SELECTOR = YES; GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; - INFOPLIST_FILE = "PureLayout Frameworks/PureLayout_iOS/Info.plist"; + INFOPLIST_FILE = "Supporting Files/PureLayout_iOS/Info.plist"; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; - IPHONEOS_DEPLOYMENT_TARGET = 8.1; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; MTL_ENABLE_DEBUG_INFO = NO; - PRODUCT_NAME = "$(TARGET_NAME)"; + PRODUCT_BUNDLE_IDENTIFIER = "com.PureLayout.$(PRODUCT_NAME:rfc1034identifier)"; + PRODUCT_NAME = PureLayout; SKIP_INSTALL = YES; + SWIFT_VERSION = 3.0; TARGETED_DEVICE_FAMILY = "1,2"; VERSIONING_SYSTEM = "apple-generic"; VERSION_INFO_PREFIX = ""; @@ -1029,7 +1589,6 @@ CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_UNREACHABLE_CODE = YES; - CODE_SIGN_IDENTITY = "-"; COMBINE_HIDPI_IMAGES = YES; CURRENT_PROJECT_VERSION = 1; DEFINES_MODULE = YES; @@ -1047,12 +1606,14 @@ GCC_WARN_UNDECLARED_SELECTOR = YES; GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; - INFOPLIST_FILE = "PureLayout Frameworks/PureLayout_Mac/Info.plist"; + INFOPLIST_FILE = "Supporting Files/PureLayout_Mac/Info.plist"; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/Frameworks"; - MACOSX_DEPLOYMENT_TARGET = 10.10; MTL_ENABLE_DEBUG_INFO = YES; - PRODUCT_NAME = "$(TARGET_NAME)"; + PRODUCT_BUNDLE_IDENTIFIER = "com.PureLayout.$(PRODUCT_NAME:rfc1034identifier)"; + PRODUCT_NAME = PureLayout; + PROVISIONING_PROFILE = None; + PROVISIONING_PROFILE_SPECIFIER = None; SDKROOT = macosx; SKIP_INSTALL = YES; VERSIONING_SYSTEM = "apple-generic"; @@ -1068,7 +1629,6 @@ CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_UNREACHABLE_CODE = YES; - CODE_SIGN_IDENTITY = "-"; COMBINE_HIDPI_IMAGES = YES; CURRENT_PROJECT_VERSION = 1; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; @@ -1084,12 +1644,14 @@ GCC_WARN_UNDECLARED_SELECTOR = YES; GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; - INFOPLIST_FILE = "PureLayout Frameworks/PureLayout_Mac/Info.plist"; + INFOPLIST_FILE = "Supporting Files/PureLayout_Mac/Info.plist"; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/Frameworks"; - MACOSX_DEPLOYMENT_TARGET = 10.10; MTL_ENABLE_DEBUG_INFO = NO; - PRODUCT_NAME = "$(TARGET_NAME)"; + PRODUCT_BUNDLE_IDENTIFIER = "com.PureLayout.$(PRODUCT_NAME:rfc1034identifier)"; + PRODUCT_NAME = PureLayout; + PROVISIONING_PROFILE = None; + PROVISIONING_PROFILE_SPECIFIER = None; SDKROOT = macosx; SKIP_INSTALL = YES; VERSIONING_SYSTEM = "apple-generic"; @@ -1101,32 +1663,55 @@ isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES; CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; COPY_PHASE_STRIP = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; GCC_C_LANGUAGE_STANDARD = gnu99; GCC_DYNAMIC_NO_PIC = NO; + GCC_GENERATE_TEST_COVERAGE_FILES = YES; + GCC_INSTRUMENT_PROGRAM_FLOW_ARCS = YES; + GCC_NO_COMMON_BLOCKS = YES; GCC_OPTIMIZATION_LEVEL = 0; GCC_PREPROCESSOR_DEFINITIONS = ( "DEBUG=1", "$(inherited)", ); GCC_SYMBOLS_PRIVATE_EXTERN = NO; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES; + GCC_WARN_UNDECLARED_SELECTOR = YES; GCC_WARN_UNINITIALIZED_AUTOS = YES; + GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 8.0; - MACOSX_DEPLOYMENT_TARGET = 10.7; + IPHONEOS_DEPLOYMENT_TARGET = 9.0; + MACOSX_DEPLOYMENT_TARGET = 10.9; ONLY_ACTIVE_ARCH = YES; SDKROOT = iphoneos; + WARNING_CFLAGS = "-Wreserved-id-macro"; }; name = Debug; }; @@ -1134,26 +1719,47 @@ isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES; CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; COPY_PHASE_STRIP = YES; + ENABLE_STRICT_OBJC_MSGSEND = YES; GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES; + GCC_WARN_UNDECLARED_SELECTOR = YES; GCC_WARN_UNINITIALIZED_AUTOS = YES; + GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 8.0; - MACOSX_DEPLOYMENT_TARGET = 10.7; + IPHONEOS_DEPLOYMENT_TARGET = 9.0; + MACOSX_DEPLOYMENT_TARGET = 10.9; OTHER_CFLAGS = "-DNS_BLOCK_ASSERTIONS=1"; SDKROOT = iphoneos; + SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; VALIDATE_PRODUCT = YES; + WARNING_CFLAGS = "-Wreserved-id-macro"; }; name = Release; }; @@ -1162,12 +1768,16 @@ buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = LaunchImage; - GCC_PRECOMPILE_PREFIX_HEADER = YES; - GCC_PREFIX_HEADER = "Example-iOS/Example-iOS-Prefix.pch"; + CLANG_ENABLE_MODULES = YES; + DEVELOPMENT_TEAM = ""; INFOPLIST_FILE = "Example-iOS/Example-iOS-Info.plist"; INFOPLIST_OUTPUT_FORMAT = "same-as-input"; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + PRODUCT_BUNDLE_IDENTIFIER = "com.PureLayout.${PRODUCT_NAME:rfc1034identifier}"; PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_OBJC_BRIDGING_HEADER = "Example-iOS/Example-iOS-Bridging-Header.h"; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_VERSION = 3.0; TARGETED_DEVICE_FAMILY = "1,2"; WRAPPER_EXTENSION = app; }; @@ -1178,12 +1788,15 @@ buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = LaunchImage; - GCC_PRECOMPILE_PREFIX_HEADER = YES; - GCC_PREFIX_HEADER = "Example-iOS/Example-iOS-Prefix.pch"; + CLANG_ENABLE_MODULES = YES; + DEVELOPMENT_TEAM = ""; INFOPLIST_FILE = "Example-iOS/Example-iOS-Info.plist"; INFOPLIST_OUTPUT_FORMAT = "same-as-input"; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + PRODUCT_BUNDLE_IDENTIFIER = "com.PureLayout.${PRODUCT_NAME:rfc1034identifier}"; PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_OBJC_BRIDGING_HEADER = "Example-iOS/Example-iOS-Bridging-Header.h"; + SWIFT_VERSION = 3.0; TARGETED_DEVICE_FAMILY = "1,2"; WRAPPER_EXTENSION = app; }; @@ -1198,10 +1811,8 @@ CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_UNREACHABLE_CODE = YES; - CODE_SIGN_IDENTITY = "-"; COMBINE_HIDPI_IMAGES = YES; ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_PREFIX_HEADER = "Example-Mac/Example-Mac-Prefix.pch"; GCC_PREPROCESSOR_DEFINITIONS = ( "DEBUG=1", "$(inherited)", @@ -1214,7 +1825,10 @@ INFOPLIST_FILE = "Example-Mac/Example-Mac-Info.plist"; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks"; METAL_ENABLE_DEBUG_INFO = YES; + PRODUCT_BUNDLE_IDENTIFIER = "com.PureLayout.${PRODUCT_NAME:rfc1034identifier}"; PRODUCT_NAME = "$(TARGET_NAME)"; + PROVISIONING_PROFILE = None; + PROVISIONING_PROFILE_SPECIFIER = None; SDKROOT = macosx; }; name = Debug; @@ -1228,12 +1842,10 @@ CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_UNREACHABLE_CODE = YES; - CODE_SIGN_IDENTITY = "-"; COMBINE_HIDPI_IMAGES = YES; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; ENABLE_NS_ASSERTIONS = NO; ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_PREFIX_HEADER = "Example-Mac/Example-Mac-Prefix.pch"; GCC_WARN_64_TO_32_BIT_CONVERSION = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; GCC_WARN_UNDECLARED_SELECTOR = YES; @@ -1242,7 +1854,10 @@ INFOPLIST_FILE = "Example-Mac/Example-Mac-Info.plist"; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks"; METAL_ENABLE_DEBUG_INFO = NO; + PRODUCT_BUNDLE_IDENTIFIER = "com.PureLayout.${PRODUCT_NAME:rfc1034identifier}"; PRODUCT_NAME = "$(TARGET_NAME)"; + PROVISIONING_PROFILE = None; + PROVISIONING_PROFILE_SPECIFIER = None; SDKROOT = macosx; }; name = Release; @@ -1254,8 +1869,9 @@ CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + DEVELOPMENT_TEAM = ""; FRAMEWORK_SEARCH_PATHS = ( - "$(SDKROOT)/Developer/Library/Frameworks", "$(inherited)", "$(DEVELOPER_FRAMEWORKS_DIR)", ); @@ -1271,8 +1887,11 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; INFOPLIST_FILE = "PureLayoutTests/PureLayoutTests-iOS/PureLayoutTests-iOS-Info.plist"; + PRODUCT_BUNDLE_IDENTIFIER = "com.PureLayout.${PRODUCT_NAME:rfc1034identifier}"; PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 3.0; TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Example-iOS.app/Example-iOS"; + WARNING_CFLAGS = ""; WRAPPER_EXTENSION = xctest; }; name = Debug; @@ -1284,9 +1903,10 @@ CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + DEVELOPMENT_TEAM = ""; ENABLE_NS_ASSERTIONS = NO; FRAMEWORK_SEARCH_PATHS = ( - "$(SDKROOT)/Developer/Library/Frameworks", "$(inherited)", "$(DEVELOPER_FRAMEWORKS_DIR)", ); @@ -1298,8 +1918,11 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; INFOPLIST_FILE = "PureLayoutTests/PureLayoutTests-iOS/PureLayoutTests-iOS-Info.plist"; + PRODUCT_BUNDLE_IDENTIFIER = "com.PureLayout.${PRODUCT_NAME:rfc1034identifier}"; PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 3.0; TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Example-iOS.app/Example-iOS"; + WARNING_CFLAGS = ""; WRAPPER_EXTENSION = xctest; }; name = Release; @@ -1311,7 +1934,9 @@ CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CODE_SIGN_IDENTITY = ""; COMBINE_HIDPI_IMAGES = YES; + DEVELOPMENT_TEAM = ""; FRAMEWORK_SEARCH_PATHS = ( "$(DEVELOPER_FRAMEWORKS_DIR)", "$(inherited)", @@ -1329,9 +1954,12 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; INFOPLIST_FILE = "PureLayoutTests/PureLayoutTests-Mac/PureLayoutTests-Mac-Info.plist"; + PRODUCT_BUNDLE_IDENTIFIER = "com.PureLayout.${PRODUCT_NAME:rfc1034identifier}"; PRODUCT_NAME = "$(TARGET_NAME)"; SDKROOT = macosx; + SUPPORTED_PLATFORMS = macosx; TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Example-Mac.app/Contents/MacOS/Example-Mac"; + WARNING_CFLAGS = ""; WRAPPER_EXTENSION = xctest; }; name = Debug; @@ -1343,8 +1971,10 @@ CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CODE_SIGN_IDENTITY = ""; COMBINE_HIDPI_IMAGES = YES; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + DEVELOPMENT_TEAM = ""; ENABLE_NS_ASSERTIONS = NO; FRAMEWORK_SEARCH_PATHS = ( "$(DEVELOPER_FRAMEWORKS_DIR)", @@ -1359,9 +1989,12 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; INFOPLIST_FILE = "PureLayoutTests/PureLayoutTests-Mac/PureLayoutTests-Mac-Info.plist"; + PRODUCT_BUNDLE_IDENTIFIER = "com.PureLayout.${PRODUCT_NAME:rfc1034identifier}"; PRODUCT_NAME = "$(TARGET_NAME)"; SDKROOT = macosx; + SUPPORTED_PLATFORMS = macosx; TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Example-Mac.app/Contents/MacOS/Example-Mac"; + WARNING_CFLAGS = ""; WRAPPER_EXTENSION = xctest; }; name = Release; @@ -1369,6 +2002,33 @@ /* End XCBuildConfiguration section */ /* Begin XCConfigurationList section */ + 164C8B5C1C0D354F0007A6B1 /* Build configuration list for PBXNativeTarget "Example-tvOS" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 164C8B5A1C0D354F0007A6B1 /* Debug */, + 164C8B5B1C0D354F0007A6B1 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 164C8B801C0D36500007A6B1 /* Build configuration list for PBXNativeTarget "PureLayout_tvOS" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 164C8B811C0D36500007A6B1 /* Debug */, + 164C8B821C0D36500007A6B1 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + A7D4967B1B7B084800A74818 /* Build configuration list for PBXNativeTarget "Example-iOS-Xcode7" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + A7D4967C1B7B084800A74818 /* Debug */, + A7D4967D1B7B084800A74818 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; B1046AC91A7F32390017187F /* Build configuration list for PBXNativeTarget "PureLayout_iOS" */ = { isa = XCConfigurationList; buildConfigurations = ( diff --git a/PureLayout/PureLayout.xcodeproj/xcshareddata/xcschemes/Example-Mac.xcscheme b/PureLayout/PureLayout.xcodeproj/xcshareddata/xcschemes/Example-Mac.xcscheme index 17eb747..0523542 100644 --- a/PureLayout/PureLayout.xcodeproj/xcshareddata/xcschemes/Example-Mac.xcscheme +++ b/PureLayout/PureLayout.xcodeproj/xcshareddata/xcschemes/Example-Mac.xcscheme @@ -1,6 +1,6 @@ + codeCoverageEnabled = "YES" + shouldUseLaunchSchemeArgsEnv = "YES"> @@ -48,17 +49,21 @@ ReferencedContainer = "container:PureLayout.xcodeproj"> + + - + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/PureLayout/PureLayout.xcodeproj/xcshareddata/xcschemes/Example-iOS.xcscheme b/PureLayout/PureLayout.xcodeproj/xcshareddata/xcschemes/Example-iOS.xcscheme index 067b094..d32cfb5 100644 --- a/PureLayout/PureLayout.xcodeproj/xcshareddata/xcschemes/Example-iOS.xcscheme +++ b/PureLayout/PureLayout.xcodeproj/xcshareddata/xcschemes/Example-iOS.xcscheme @@ -1,6 +1,6 @@ + codeCoverageEnabled = "YES" + shouldUseLaunchSchemeArgsEnv = "YES"> @@ -62,17 +63,21 @@ ReferencedContainer = "container:PureLayout.xcodeproj"> + + - + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/PureLayout/PureLayout.xcodeproj/xcshareddata/xcschemes/PureLayout_Mac.xcscheme b/PureLayout/PureLayout.xcodeproj/xcshareddata/xcschemes/PureLayout_Mac.xcscheme index 4b58c7f..9d1f458 100644 --- a/PureLayout/PureLayout.xcodeproj/xcshareddata/xcschemes/PureLayout_Mac.xcscheme +++ b/PureLayout/PureLayout.xcodeproj/xcshareddata/xcschemes/PureLayout_Mac.xcscheme @@ -1,6 +1,6 @@ @@ -23,10 +23,11 @@ + codeCoverageEnabled = "YES" + shouldUseLaunchSchemeArgsEnv = "YES"> @@ -43,26 +44,29 @@ + + @@ -71,16 +75,16 @@ diff --git a/PureLayout/PureLayout.xcodeproj/xcshareddata/xcschemes/PureLayout_iOS.xcscheme b/PureLayout/PureLayout.xcodeproj/xcshareddata/xcschemes/PureLayout_iOS.xcscheme index a0d5c91..d60f3f1 100644 --- a/PureLayout/PureLayout.xcodeproj/xcshareddata/xcschemes/PureLayout_iOS.xcscheme +++ b/PureLayout/PureLayout.xcodeproj/xcshareddata/xcschemes/PureLayout_iOS.xcscheme @@ -1,6 +1,6 @@ @@ -23,10 +23,11 @@ + codeCoverageEnabled = "YES" + shouldUseLaunchSchemeArgsEnv = "YES"> @@ -43,26 +44,29 @@ + + @@ -71,16 +75,16 @@ diff --git a/PureLayout/PureLayout.xcodeproj/xcshareddata/xcschemes/PureLayout_tvOS.xcscheme b/PureLayout/PureLayout.xcodeproj/xcshareddata/xcschemes/PureLayout_tvOS.xcscheme new file mode 100644 index 0000000..a239914 --- /dev/null +++ b/PureLayout/PureLayout.xcodeproj/xcshareddata/xcschemes/PureLayout_tvOS.xcscheme @@ -0,0 +1,81 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/PureLayout/PureLayout/ALView+PureLayout.m b/PureLayout/PureLayout/ALView+PureLayout.m index 47edebd..3ec32e2 100755 --- a/PureLayout/PureLayout/ALView+PureLayout.m +++ b/PureLayout/PureLayout/ALView+PureLayout.m @@ -1,7 +1,6 @@ // // ALView+PureLayout.m -// v2.0.5 -// https://github.com/smileyborg/PureLayout +// https://github.com/PureLayout/PureLayout // // Copyright (c) 2012 Richard Turton // Copyright (c) 2013-2015 Tyler Fox @@ -62,261 +61,305 @@ - (instancetype)initForAutoLayout return self; } - -#pragma mark Create Constraints Without Installing - /** - A global variable that stores a stack of arrays of constraints created without being immediately installed. - When executing a constraints block passed into the +[autoCreateConstraintsWithoutInstalling:] method, a new - mutable array is pushed onto this stack, and all constraints created with PureLayout in the block are added - to this array. When the block finishes executing, the array is popped off this stack. Automatic constraint - installation is prevented if this stack contains at least 1 array. - - NOTE: Access to this variable is not synchronized (and should only be done on the main thread). + Configures an existing view to not convert the autoresizing mask into constraints and returns the view. */ -static NSMutableArray *_al_arraysOfCreatedConstraints = nil; - -/** - Accessor for the global state that stores arrays of constraints created without being installed. - */ -+ (NSMutableArray *)al_arraysOfCreatedConstraints +- (instancetype)configureForAutoLayout { - if (!_al_arraysOfCreatedConstraints) { - _al_arraysOfCreatedConstraints = [NSMutableArray new]; - } - return _al_arraysOfCreatedConstraints; + self.translatesAutoresizingMaskIntoConstraints = NO; + return self; } -/** - Accessor for the current mutable array of constraints created without being immediately installed. - */ -+ (NSMutableArray *)al_currentArrayOfCreatedConstraints -{ - return [[self al_arraysOfCreatedConstraints] lastObject]; -} -/** - Accessor for the global state that determines whether automatic constraint installation should be prevented. - */ -+ (BOOL)al_preventAutomaticConstraintInstallation -{ - return [[self al_arraysOfCreatedConstraints] count] > 0; -} +#pragma mark Center in Superview -/** - Prevents constraints created in the given constraints block from being automatically installed (activated). - The constraints created from calls to the PureLayout API in the block are returned in a single array. +/** + Centers the view in its superview. - @param block A block of method calls to the PureLayout API that create constraints. - @return An array of the constraints that were created from calls to the PureLayout API inside the block. + @return An array of constraints added. */ -+ (NSArray *)autoCreateConstraintsWithoutInstalling:(ALConstraintsBlock)block +- (PL__NSArray_of(NSLayoutConstraint *) *)autoCenterInSuperview { - NSAssert(block, @"The constraints block cannot be nil."); - NSArray *createdConstraints = nil; - if (block) { - [[self al_arraysOfCreatedConstraints] addObject:[NSMutableArray new]]; - block(); - createdConstraints = [self al_currentArrayOfCreatedConstraints]; - [[self al_arraysOfCreatedConstraints] removeLastObject]; - } - return createdConstraints; + PL__NSMutableArray_of(NSLayoutConstraint *) *constraints = [NSMutableArray new]; + [constraints addObject:[self autoAlignAxisToSuperviewAxis:ALAxisHorizontal]]; + [constraints addObject:[self autoAlignAxisToSuperviewAxis:ALAxisVertical]]; + return constraints; } - -#pragma mark Set Priority For Constraints - -/** - A global variable that stores a stack of layout priorities to set on constraints. - When executing a constraints block passed into the +[autoSetPriority:forConstraints:] method, the priority for - that call is pushed onto this stack, and when the block finishes executing, that priority is popped off this - stack. If this stack contains at least 1 priority, the priority at the top of the stack will be set for all - constraints created by this library (even if automatic constraint installation is being prevented). - NOTE: Access to this variable is not synchronized (and should only be done on the main thread). - */ -static NSMutableArray *_al_globalConstraintPriorities = nil; - /** - Accessor for the global stack of layout priorities. + Aligns the view to the same axis of its superview. + + @param axis The axis of this view and of its superview to align. + @return The constraint added. */ -+ (NSMutableArray *)al_globalConstraintPriorities +- (NSLayoutConstraint *)autoAlignAxisToSuperviewAxis:(ALAxis)axis { - if (!_al_globalConstraintPriorities) { - _al_globalConstraintPriorities = [NSMutableArray new]; - } - return _al_globalConstraintPriorities; + self.translatesAutoresizingMaskIntoConstraints = NO; + ALView *superview = self.superview; + NSAssert(superview, @"View's superview must not be nil.\nView: %@", self); + return [self autoConstrainAttribute:(ALAttribute)axis toAttribute:(ALAttribute)axis ofView:superview]; } -/** - Returns the current layout priority to use for constraints. - When executing a constraints block passed into +[autoSetPriority:forConstraints:], this will return - the priority for the current block. Otherwise, the default Required priority is returned. - */ -+ (ALLayoutPriority)al_currentGlobalConstraintPriority -{ - NSMutableArray *globalConstraintPriorities = [self al_globalConstraintPriorities]; - if ([globalConstraintPriorities count] == 0) { - return ALLayoutPriorityRequired; - } - return [[globalConstraintPriorities lastObject] floatValue]; -} +#if PL__PureLayout_MinBaseSDK_iOS_8_0 /** - Accessor for the global state that determines if we're currently in the scope of a priority constraints block. + Centers the view in its superview, taking into account the layout margins of both the view and its superview. + + @return An array of constraints added. */ -+ (BOOL)al_isExecutingPriorityConstraintsBlock +- (PL__NSArray_of(NSLayoutConstraint *) *)autoCenterInSuperviewMargins { - return [[self al_globalConstraintPriorities] count] > 0; + PL__NSMutableArray_of(NSLayoutConstraint *) *constraints = [NSMutableArray new]; + [constraints addObject:[self autoAlignAxisToSuperviewMarginAxis:ALAxisHorizontal]]; + [constraints addObject:[self autoAlignAxisToSuperviewMarginAxis:ALAxisVertical]]; + return constraints; } /** - Sets the constraint priority to the given value for all constraints created using the PureLayout - API within the given constraints block. - - NOTE: This method will have no effect (and will NOT set the priority) on constraints created or added - without using the PureLayout API! + Aligns the view to the corresponding margin axis of its superview. - @param priority The layout priority to be set on all constraints created in the constraints block. - @param block A block of method calls to the PureLayout API that create and install constraints. + @param axis The axis of this view to align to the corresponding margin axis of its superview. + @return The constraint added. */ -+ (void)autoSetPriority:(ALLayoutPriority)priority forConstraints:(ALConstraintsBlock)block +- (NSLayoutConstraint *)autoAlignAxisToSuperviewMarginAxis:(ALAxis)axis { - NSAssert(block, @"The constraints block cannot be nil."); - if (block) { - [[self al_globalConstraintPriorities] addObject:@(priority)]; - block(); - [[self al_globalConstraintPriorities] removeLastObject]; - } + self.translatesAutoresizingMaskIntoConstraints = NO; + ALView *superview = self.superview; + NSAssert(superview, @"View's superview must not be nil.\nView: %@", self); + ALMarginAxis marginAxis = [NSLayoutConstraint al_marginAxisForAxis:axis]; + return [self autoConstrainAttribute:(ALAttribute)axis toAttribute:(ALAttribute)marginAxis ofView:superview]; } +#endif /* PL__PureLayout_MinBaseSDK_iOS_8_0 */ -#pragma mark Set Identifier For Constraints -#if __PureLayout_MinBaseSDK_iOS_8_0 +#pragma mark Pin Edges to SafeArea -/** - A global variable that stores a stack of identifier strings to set on constraints. - When executing a constraints block passed into the +[autoSetIdentifier:forConstraints:] method, the identifier for - that call is pushed onto this stack, and when the block finishes executing, that identifier is popped off this - stack. If this stack contains at least 1 identifier, the identifier at the top of the stack will be set for all - constraints created by this library (even if automatic constraint installation is being prevented). - NOTE: Access to this variable is not synchronized (and should only be done on the main thread). - */ -static NSMutableArray *_al_globalConstraintIdentifiers = nil; +#if TARGET_OS_IPHONE /** - Accessor for the global state of constraint identifiers. + Pins the given edge of the view to the same edge of its superview anchor. + + @param edge The edge of this view and its superview to pin. + @return The constraint added. */ -+ (NSMutableArray *)al_globalConstraintIdentifiers +- (NSLayoutConstraint *)autoPinEdgeToSuperviewSafeArea:(ALEdge)edge { - if (!_al_globalConstraintIdentifiers) { - _al_globalConstraintIdentifiers = [NSMutableArray new]; - } - return _al_globalConstraintIdentifiers; + return [self autoPinEdgeToSuperviewSafeArea:edge withInset:0.0]; } /** - Returns the current identifier string to use for constraints. - When executing a constraints block passed into +[autoSetIdentifier:forConstraints:], this will return - the identifier for the current block. Otherwise, nil is returned. - */ -+ (NSString *)al_currentGlobalConstraintIdentifier -{ - NSMutableArray *globalConstraintIdentifiers = [self al_globalConstraintIdentifiers]; - if ([globalConstraintIdentifiers count] == 0) { - return nil; - } - return [globalConstraintIdentifiers lastObject]; -} + Pins the given edge of the view to the same edge of its superview anchor with an inset. -/** - Sets the identifier for all constraints created using the PureLayout API within the given constraints block. - - NOTE: This method will have no effect (and will NOT set the identifier) on constraints created or added - without using the PureLayout API! - - @param identifier A string used to identify all constraints created in the constraints block. - @param block A block of method calls to the PureLayout API that create and install constraints. + @param edge The edge of this view and its superview to pin. + @param inset The amount to inset this view's edge from the superview's edge. + @return The constraint added. */ -+ (void)autoSetIdentifier:(NSString *)identifier forConstraints:(ALConstraintsBlock)block +- (NSLayoutConstraint *)autoPinEdgeToSuperviewSafeArea:(ALEdge)edge withInset:(CGFloat)inset { - NSAssert(block, @"The constraints block cannot be nil."); - NSAssert(identifier, @"The identifier string cannot be nil."); - if (block) { - if (identifier) { - [[self al_globalConstraintIdentifiers] addObject:identifier]; - } - block(); - if (identifier) { - [[self al_globalConstraintIdentifiers] removeLastObject]; - } - } + return [self autoPinEdgeToSuperviewSafeArea:edge withInset:inset relation:NSLayoutRelationEqual]; } -#endif /* __PureLayout_MinBaseSDK_iOS_8_0 */ - - -#pragma mark Center in Superview - /** - Centers the view in its superview. - - @return An array of constraints added. - */ -- (NSArray *)autoCenterInSuperview -{ - NSMutableArray *constraints = [NSMutableArray new]; - [constraints addObject:[self autoAlignAxisToSuperviewAxis:ALAxisHorizontal]]; - [constraints addObject:[self autoAlignAxisToSuperviewAxis:ALAxisVertical]]; - return constraints; -} + Pins the given edge of the view to the same edge of its superview anchor/edge with an inset as a maximum or minimum. -/** - Aligns the view to the same axis of its superview. - - @param axis The axis of this view and of its superview to align. + @param edge The edge of this view and its superview to pin. + @param inset The amount to inset this view's edge from the superview's edge. + @param relation Whether the inset should be at least, at most, or exactly equal to the given value. @return The constraint added. */ -- (NSLayoutConstraint *)autoAlignAxisToSuperviewAxis:(ALAxis)axis +- (NSLayoutConstraint *)autoPinEdgeToSuperviewSafeArea:(ALEdge)edge withInset:(CGFloat)inset relation:(NSLayoutRelation)relation { +#if PL__PureLayout_MinBaseSDK_iOS_9_0 self.translatesAutoresizingMaskIntoConstraints = NO; + ALView *superview = self.superview; NSAssert(superview, @"View's superview must not be nil.\nView: %@", self); - return [self autoConstrainAttribute:(ALAttribute)axis toAttribute:(ALAttribute)axis ofView:superview]; + NSLayoutConstraint *constraint = nil; + NSLayoutYAxisAnchor *topAnchor; + NSLayoutYAxisAnchor *bottomAnchor; + NSLayoutXAxisAnchor *leftAnchor; + NSLayoutXAxisAnchor *rightAnchor; + NSLayoutXAxisAnchor *leadingAnchor; + NSLayoutXAxisAnchor *trailingAnchor; + +#if PL__PureLayout_MinBaseSDK_iOS_11_0 // only iOS/tvOS SDK 11.0 has @available syntax introduced + if (@available(iOS 11.0, tvOS 11.0, *)) { + topAnchor = superview.safeAreaLayoutGuide.topAnchor; + bottomAnchor = superview.safeAreaLayoutGuide.bottomAnchor; + leftAnchor = superview.safeAreaLayoutGuide.leftAnchor; + rightAnchor = superview.safeAreaLayoutGuide.rightAnchor; + leadingAnchor = superview.safeAreaLayoutGuide.leadingAnchor; + trailingAnchor = superview.safeAreaLayoutGuide.trailingAnchor; + } else if (@available(iOS 9.0, *)) { + topAnchor = superview.topAnchor; + bottomAnchor = superview.bottomAnchor; + leftAnchor = superview.leftAnchor; + rightAnchor = superview.rightAnchor; + leadingAnchor = superview.leadingAnchor; + trailingAnchor = superview.trailingAnchor; + } else { // for targeting iOS 8 or below without anchor system + return [self autoPinEdgeToSuperviewEdge:edge withInset:inset relation:relation]; + } +#elif PL__PureLayout_MinBaseSDK_iOS_9_0 // fallback to older SDKs, when using Xcode 8.0, which only has iOS SDK 10.0 + if (PL__PureLayout_MinSysVer_iOS_9_0) { + topAnchor = superview.topAnchor; + bottomAnchor = superview.bottomAnchor; + leftAnchor = superview.leftAnchor; + rightAnchor = superview.rightAnchor; + leadingAnchor = superview.leadingAnchor; + trailingAnchor = superview.trailingAnchor; + } else { // for targeting iOS 8 or below without anchor system + return [self autoPinEdgeToSuperviewEdge:edge withInset:inset relation:relation]; + } +#endif + if (edge == ALEdgeBottom || edge == ALEdgeRight || edge == ALEdgeTrailing) { + // The bottom, right, and trailing insets (and relations, if an inequality) are inverted to become offsets + inset = -inset; + } + switch (edge) { + case ALEdgeLeft: + switch (relation) { + case NSLayoutRelationEqual: + constraint = [[self leftAnchor] constraintEqualToAnchor:leftAnchor constant:inset]; + break; + case NSLayoutRelationLessThanOrEqual: + constraint = [[self leftAnchor] constraintLessThanOrEqualToAnchor:leftAnchor constant:inset]; + break; + case NSLayoutRelationGreaterThanOrEqual: + constraint = [[self leftAnchor] constraintGreaterThanOrEqualToAnchor:leftAnchor constant:inset]; + break; + } + break; + case ALEdgeRight: + switch (relation) { + case NSLayoutRelationEqual: + constraint = [[self rightAnchor] constraintEqualToAnchor:rightAnchor constant:inset]; + break; + case NSLayoutRelationLessThanOrEqual: + constraint = [[self rightAnchor] constraintGreaterThanOrEqualToAnchor:rightAnchor constant:inset]; + break; + case NSLayoutRelationGreaterThanOrEqual: + constraint = [[self rightAnchor] constraintLessThanOrEqualToAnchor:rightAnchor constant:inset]; + break; + } + break; + case ALEdgeTop: + switch (relation) { + case NSLayoutRelationEqual: + constraint = [[self topAnchor] constraintEqualToAnchor:topAnchor constant:inset]; + break; + case NSLayoutRelationLessThanOrEqual: + constraint = [[self topAnchor] constraintLessThanOrEqualToAnchor:topAnchor constant:inset]; + break; + case NSLayoutRelationGreaterThanOrEqual: + constraint = [[self topAnchor] constraintGreaterThanOrEqualToAnchor:topAnchor constant:inset]; + break; + } + break; + case ALEdgeBottom: + switch (relation) { + case NSLayoutRelationEqual: + constraint = [[self bottomAnchor] constraintEqualToAnchor:bottomAnchor constant:inset]; + break; + case NSLayoutRelationLessThanOrEqual: + constraint = [[self bottomAnchor] constraintGreaterThanOrEqualToAnchor:bottomAnchor constant:inset]; + break; + case NSLayoutRelationGreaterThanOrEqual: + constraint = [[self bottomAnchor] constraintLessThanOrEqualToAnchor:bottomAnchor constant:inset]; + break; + } + break; + case ALEdgeLeading: + switch (relation) { + case NSLayoutRelationEqual: + constraint = [[self leadingAnchor] constraintEqualToAnchor:leadingAnchor constant:inset]; + break; + case NSLayoutRelationLessThanOrEqual: + constraint = [[self leadingAnchor] constraintLessThanOrEqualToAnchor:leadingAnchor constant:inset]; + break; + case NSLayoutRelationGreaterThanOrEqual: + constraint = [[self leadingAnchor] constraintGreaterThanOrEqualToAnchor:leadingAnchor constant:inset]; + break; + } + break; + case ALEdgeTrailing: + switch (relation) { + case NSLayoutRelationEqual: + constraint = [[self trailingAnchor] constraintEqualToAnchor:trailingAnchor constant:inset]; + break; + case NSLayoutRelationLessThanOrEqual: + constraint = [[self trailingAnchor] constraintGreaterThanOrEqualToAnchor:trailingAnchor constant:inset]; + break; + case NSLayoutRelationGreaterThanOrEqual: + constraint = [[self trailingAnchor] constraintLessThanOrEqualToAnchor:trailingAnchor constant:inset]; + break; + } + break; + } + [constraint autoInstall]; + return constraint; +#else + return [self autoPinEdgeToSuperviewEdge:edge withInset:inset relation:relation]; +#endif /* PL__PureLayout_MinBaseSDK_iOS_9_0 */ } -#if __PureLayout_MinBaseSDK_iOS_8_0 +/** + Pins the edges of the view to the edges of its superview anchor. + + @return An array of constraints added, ordered counterclockwise from top. + */ +- (PL__NSArray_of(NSLayoutConstraint *) *)autoPinEdgesToSuperviewSafeArea +{ + return [self autoPinEdgesToSuperviewSafeAreaWithInsets:ALEdgeInsetsZero]; +} /** - Centers the view in its superview, taking into account the layout margins of both the view and its superview. - - @return An array of constraints added. + Pins the edges of the view to the edges of its superview anchor with the given edge insets. + The insets.left corresponds to a leading edge constraint, and insets.right corresponds to a trailing edge constraint. + + @param insets The insets for this view's edges from its superview's edges. + @return An array of constraints added, ordered counterclockwise from top. */ -- (NSArray *)autoCenterInSuperviewMargins +- (PL__NSArray_of(NSLayoutConstraint *) *)autoPinEdgesToSuperviewSafeAreaWithInsets:(ALEdgeInsets)insets { - NSMutableArray *constraints = [NSMutableArray new]; - [constraints addObject:[self autoAlignAxisToSuperviewMarginAxis:ALAxisHorizontal]]; - [constraints addObject:[self autoAlignAxisToSuperviewMarginAxis:ALAxisVertical]]; + PL__NSMutableArray_of(NSLayoutConstraint *) *constraints = [NSMutableArray new]; + [constraints addObject:[self autoPinEdgeToSuperviewSafeArea:ALEdgeTop withInset:insets.top]]; + [constraints addObject:[self autoPinEdgeToSuperviewSafeArea:ALEdgeLeading withInset:insets.left]]; + [constraints addObject:[self autoPinEdgeToSuperviewSafeArea:ALEdgeBottom withInset:insets.bottom]]; + [constraints addObject:[self autoPinEdgeToSuperviewSafeArea:ALEdgeTrailing withInset:insets.right]]; return constraints; } /** - Aligns the view to the corresponding margin axis of its superview. - - @param axis The axis of this view to align to the corresponding margin axis of its superview. - @return The constraint added. + Pins 3 of the 4 edges of the view to the edges of its superview anchor with the given edge insets, excluding one edge. + The insets.left corresponds to a leading edge constraint, and insets.right corresponds to a trailing edge constraint. + + @param insets The insets for this view's edges from its superview's edges. The inset corresponding to the excluded edge + will be ignored. + @param edge The edge of this view to exclude in pinning to its superview anchor; this method will not apply any constraint to it. + @return An array of constraints added, ordered counterclockwise from top. */ -- (NSLayoutConstraint *)autoAlignAxisToSuperviewMarginAxis:(ALAxis)axis +- (PL__NSArray_of(NSLayoutConstraint *) *)autoPinEdgesToSuperviewSafeAreaWithInsets:(ALEdgeInsets)insets excludingEdge:(ALEdge)edge { - self.translatesAutoresizingMaskIntoConstraints = NO; - ALView *superview = self.superview; - NSAssert(superview, @"View's superview must not be nil.\nView: %@", self); - ALMarginAxis marginAxis = [NSLayoutConstraint al_marginAxisForAxis:axis]; - return [self autoConstrainAttribute:(ALAttribute)axis toAttribute:(ALAttribute)marginAxis ofView:superview]; -} + PL__NSMutableArray_of(NSLayoutConstraint *) *constraints = [NSMutableArray new]; -#endif /* __PureLayout_MinBaseSDK_iOS_8_0 */ + if (edge != ALEdgeTop) { + [constraints addObject:[self autoPinEdgeToSuperviewSafeArea:ALEdgeTop withInset:insets.top]]; + } + if (edge != ALEdgeLeading && edge != ALEdgeLeft) { + [constraints addObject:[self autoPinEdgeToSuperviewSafeArea:ALEdgeLeading withInset:insets.left]]; + } + if (edge != ALEdgeBottom) { + [constraints addObject:[self autoPinEdgeToSuperviewSafeArea:ALEdgeBottom withInset:insets.bottom]]; + } + if (edge != ALEdgeTrailing && edge != ALEdgeRight) { + [constraints addObject:[self autoPinEdgeToSuperviewSafeArea:ALEdgeTrailing withInset:insets.right]]; + } + return constraints; +} +#endif /* TARGET_OS_IPHONE */ #pragma mark Pin Edges to Superview @@ -368,16 +411,26 @@ - (NSLayoutConstraint *)autoPinEdgeToSuperviewEdge:(ALEdge)edge withInset:(CGFlo return [self autoPinEdge:edge toEdge:edge ofView:superview withOffset:inset relation:relation]; } +/** + Pins the edges of the view to the edges of its superview. + + @return An array of constraints added, ordered counterclockwise from top. + */ +- (PL__NSArray_of(NSLayoutConstraint *) *)autoPinEdgesToSuperviewEdges +{ + return [self autoPinEdgesToSuperviewEdgesWithInsets:ALEdgeInsetsZero]; +} + /** Pins the edges of the view to the edges of its superview with the given edge insets. The insets.left corresponds to a leading edge constraint, and insets.right corresponds to a trailing edge constraint. @param insets The insets for this view's edges from its superview's edges. - @return An array of constraints added. + @return An array of constraints added, ordered counterclockwise from top. */ -- (NSArray *)autoPinEdgesToSuperviewEdgesWithInsets:(ALEdgeInsets)insets +- (PL__NSArray_of(NSLayoutConstraint *) *)autoPinEdgesToSuperviewEdgesWithInsets:(ALEdgeInsets)insets { - NSMutableArray *constraints = [NSMutableArray new]; + PL__NSMutableArray_of(NSLayoutConstraint *) *constraints = [NSMutableArray new]; [constraints addObject:[self autoPinEdgeToSuperviewEdge:ALEdgeTop withInset:insets.top]]; [constraints addObject:[self autoPinEdgeToSuperviewEdge:ALEdgeLeading withInset:insets.left]]; [constraints addObject:[self autoPinEdgeToSuperviewEdge:ALEdgeBottom withInset:insets.bottom]]; @@ -392,27 +445,47 @@ - (NSArray *)autoPinEdgesToSuperviewEdgesWithInsets:(ALEdgeInsets)insets @param insets The insets for this view's edges from its superview's edges. The inset corresponding to the excluded edge will be ignored. @param edge The edge of this view to exclude in pinning to its superview; this method will not apply any constraint to it. - @return An array of constraints added. + @return An array of constraints added, ordered counterclockwise from top. */ -- (NSArray *)autoPinEdgesToSuperviewEdgesWithInsets:(ALEdgeInsets)insets excludingEdge:(ALEdge)edge +- (PL__NSArray_of(NSLayoutConstraint *) *)autoPinEdgesToSuperviewEdgesWithInsets:(ALEdgeInsets)insets excludingEdge:(ALEdge)edge { - NSMutableArray *constraints = [NSMutableArray new]; - if (edge != ALEdgeTop) { - [constraints addObject:[self autoPinEdgeToSuperviewEdge:ALEdgeTop withInset:insets.top]]; - } - if (edge != ALEdgeLeading && edge != ALEdgeLeft) { - [constraints addObject:[self autoPinEdgeToSuperviewEdge:ALEdgeLeading withInset:insets.left]]; - } - if (edge != ALEdgeBottom) { - [constraints addObject:[self autoPinEdgeToSuperviewEdge:ALEdgeBottom withInset:insets.bottom]]; - } - if (edge != ALEdgeTrailing && edge != ALEdgeRight) { - [constraints addObject:[self autoPinEdgeToSuperviewEdge:ALEdgeTrailing withInset:insets.right]]; + PL__NSMutableArray_of(NSLayoutConstraint *) *constraints = [NSMutableArray new]; + switch (edge) { + case ALEdgeLeft: + [constraints addObject:[self autoPinEdgeToSuperviewEdge:ALEdgeTop withInset:insets.top]]; + [constraints addObject:[self autoPinEdgeToSuperviewEdge:ALEdgeBottom withInset:insets.bottom]]; + [constraints addObject:[self autoPinEdgeToSuperviewEdge:ALEdgeRight withInset:insets.right]]; + break; + case ALEdgeRight: + [constraints addObject:[self autoPinEdgeToSuperviewEdge:ALEdgeTop withInset:insets.top]]; + [constraints addObject:[self autoPinEdgeToSuperviewEdge:ALEdgeLeft withInset:insets.left]]; + [constraints addObject:[self autoPinEdgeToSuperviewEdge:ALEdgeBottom withInset:insets.bottom]]; + break; + case ALEdgeTop: + [constraints addObject:[self autoPinEdgeToSuperviewEdge:ALEdgeLeading withInset:insets.left]]; + [constraints addObject:[self autoPinEdgeToSuperviewEdge:ALEdgeBottom withInset:insets.bottom]]; + [constraints addObject:[self autoPinEdgeToSuperviewEdge:ALEdgeTrailing withInset:insets.right]]; + break; + case ALEdgeBottom: + [constraints addObject:[self autoPinEdgeToSuperviewEdge:ALEdgeTop withInset:insets.top]]; + [constraints addObject:[self autoPinEdgeToSuperviewEdge:ALEdgeLeading withInset:insets.left]]; + [constraints addObject:[self autoPinEdgeToSuperviewEdge:ALEdgeTrailing withInset:insets.right]]; + break; + case ALEdgeLeading: + [constraints addObject:[self autoPinEdgeToSuperviewEdge:ALEdgeTop withInset:insets.top]]; + [constraints addObject:[self autoPinEdgeToSuperviewEdge:ALEdgeBottom withInset:insets.bottom]]; + [constraints addObject:[self autoPinEdgeToSuperviewEdge:ALEdgeTrailing withInset:insets.right]]; + break; + case ALEdgeTrailing: + [constraints addObject:[self autoPinEdgeToSuperviewEdge:ALEdgeTop withInset:insets.top]]; + [constraints addObject:[self autoPinEdgeToSuperviewEdge:ALEdgeLeading withInset:insets.left]]; + [constraints addObject:[self autoPinEdgeToSuperviewEdge:ALEdgeBottom withInset:insets.bottom]]; + break; } return constraints; } -#if __PureLayout_MinBaseSDK_iOS_8_0 +#if PL__PureLayout_MinBaseSDK_iOS_8_0 /** Pins the given edge of the view to the corresponding margin of its superview. @@ -425,6 +498,26 @@ - (NSLayoutConstraint *)autoPinEdgeToSuperviewMargin:(ALEdge)edge return [self autoPinEdgeToSuperviewMargin:edge relation:NSLayoutRelationEqual]; } +/** + Pins the given edge of the view to the corresponding margin of its superview with an inset. + + @param edge The edge of this view to pin to the corresponding margin of its superview. + @param inset The amount to inset this view's edge from the corresponding margin of its superview edge. + @return The constraint added. + */ +- (NSLayoutConstraint *)autoPinEdgeToSuperviewMargin:(ALEdge)edge withInset:(CGFloat)inset +{ + self.translatesAutoresizingMaskIntoConstraints = NO; + ALView *superview = self.superview; + NSAssert(superview, @"View's superview must not be nil.\nView: %@", self); + if (edge == ALEdgeBottom || edge == ALEdgeRight || edge == ALEdgeTrailing) { + // The bottom, right, and trailing insets (and relations, if an inequality) are inverted to become offsets + inset = -inset; + } + ALMargin margin = [NSLayoutConstraint al_marginForEdge:edge]; + return [self autoConstrainAttribute:(ALAttribute)edge toAttribute:(ALAttribute)margin ofView:superview withOffset:inset]; +} + /** Pins the given edge of the view to the corresponding margin of its superview as a maximum or minimum. @@ -448,19 +541,31 @@ - (NSLayoutConstraint *)autoPinEdgeToSuperviewMargin:(ALEdge)edge relation:(NSLa ALMargin margin = [NSLayoutConstraint al_marginForEdge:edge]; return [self autoConstrainAttribute:(ALAttribute)edge toAttribute:(ALAttribute)margin ofView:superview withOffset:0.0 relation:relation]; } - + /** Pins the edges of the view to the margins of its superview. - @return An array of constraints added. + @return An array of constraints added, ordered counterclockwise from top. + */ +- (PL__NSArray_of(NSLayoutConstraint *) *)autoPinEdgesToSuperviewMargins +{ + return [self autoPinEdgesToSuperviewMarginsWithInsets:ALEdgeInsetsZero]; +} + +/** + Pins the edges of the view to the edges of its corresponding margins of its superview with the given edge insets. + The insets.left corresponds to a leading edge constraint, and insets.right corresponds to a trailing edge constraint. + + @param insets The insets for this view's edges from its corresponding margin of its superview. + @return An array of constraints added, ordered counterclockwise from top. */ -- (NSArray *)autoPinEdgesToSuperviewMargins +- (PL__NSArray_of(NSLayoutConstraint *) *)autoPinEdgesToSuperviewMarginsWithInsets:(ALEdgeInsets)insets { - NSMutableArray *constraints = [NSMutableArray new]; - [constraints addObject:[self autoPinEdgeToSuperviewMargin:ALEdgeTop]]; - [constraints addObject:[self autoPinEdgeToSuperviewMargin:ALEdgeLeading]]; - [constraints addObject:[self autoPinEdgeToSuperviewMargin:ALEdgeBottom]]; - [constraints addObject:[self autoPinEdgeToSuperviewMargin:ALEdgeTrailing]]; + PL__NSMutableArray_of(NSLayoutConstraint *) *constraints = [NSMutableArray new]; + [constraints addObject:[self autoPinEdgeToSuperviewMargin:ALEdgeTop withInset:insets.top]]; + [constraints addObject:[self autoPinEdgeToSuperviewMargin:ALEdgeLeading withInset:insets.left]]; + [constraints addObject:[self autoPinEdgeToSuperviewMargin:ALEdgeBottom withInset:insets.bottom]]; + [constraints addObject:[self autoPinEdgeToSuperviewMargin:ALEdgeTrailing withInset:insets.right]]; return constraints; } @@ -468,27 +573,47 @@ - (NSArray *)autoPinEdgesToSuperviewMargins Pins 3 of the 4 edges of the view to the margins of its superview, excluding one edge. @param edge The edge of this view to exclude in pinning to its superview; this method will not apply any constraint to it. - @return An array of constraints added. + @return An array of constraints added, ordered counterclockwise from top. */ -- (NSArray *)autoPinEdgesToSuperviewMarginsExcludingEdge:(ALEdge)edge +- (PL__NSArray_of(NSLayoutConstraint *) *)autoPinEdgesToSuperviewMarginsExcludingEdge:(ALEdge)edge { - NSMutableArray *constraints = [NSMutableArray new]; - if (edge != ALEdgeTop) { - [constraints addObject:[self autoPinEdgeToSuperviewMargin:ALEdgeTop]]; - } - if (edge != ALEdgeLeading && edge != ALEdgeLeft) { - [constraints addObject:[self autoPinEdgeToSuperviewMargin:ALEdgeLeading]]; - } - if (edge != ALEdgeBottom) { - [constraints addObject:[self autoPinEdgeToSuperviewMargin:ALEdgeBottom]]; - } - if (edge != ALEdgeTrailing && edge != ALEdgeRight) { - [constraints addObject:[self autoPinEdgeToSuperviewMargin:ALEdgeTrailing]]; + PL__NSMutableArray_of(NSLayoutConstraint *) *constraints = [NSMutableArray new]; + switch (edge) { + case ALEdgeLeft: + [constraints addObject:[self autoPinEdgeToSuperviewMargin:ALEdgeTop]]; + [constraints addObject:[self autoPinEdgeToSuperviewMargin:ALEdgeBottom]]; + [constraints addObject:[self autoPinEdgeToSuperviewMargin:ALEdgeRight]]; + break; + case ALEdgeRight: + [constraints addObject:[self autoPinEdgeToSuperviewMargin:ALEdgeTop]]; + [constraints addObject:[self autoPinEdgeToSuperviewMargin:ALEdgeLeft]]; + [constraints addObject:[self autoPinEdgeToSuperviewMargin:ALEdgeBottom]]; + break; + case ALEdgeTop: + [constraints addObject:[self autoPinEdgeToSuperviewMargin:ALEdgeLeading]]; + [constraints addObject:[self autoPinEdgeToSuperviewMargin:ALEdgeBottom]]; + [constraints addObject:[self autoPinEdgeToSuperviewMargin:ALEdgeTrailing]]; + break; + case ALEdgeBottom: + [constraints addObject:[self autoPinEdgeToSuperviewMargin:ALEdgeTop]]; + [constraints addObject:[self autoPinEdgeToSuperviewMargin:ALEdgeLeading]]; + [constraints addObject:[self autoPinEdgeToSuperviewMargin:ALEdgeTrailing]]; + break; + case ALEdgeLeading: + [constraints addObject:[self autoPinEdgeToSuperviewMargin:ALEdgeTop]]; + [constraints addObject:[self autoPinEdgeToSuperviewMargin:ALEdgeBottom]]; + [constraints addObject:[self autoPinEdgeToSuperviewMargin:ALEdgeTrailing]]; + break; + case ALEdgeTrailing: + [constraints addObject:[self autoPinEdgeToSuperviewMargin:ALEdgeTop]]; + [constraints addObject:[self autoPinEdgeToSuperviewMargin:ALEdgeLeading]]; + [constraints addObject:[self autoPinEdgeToSuperviewMargin:ALEdgeBottom]]; + break; } return constraints; } -#endif /* __PureLayout_MinBaseSDK_iOS_8_0 */ +#endif /* PL__PureLayout_MinBaseSDK_iOS_8_0 */ #pragma mark Pin Edges @@ -535,7 +660,6 @@ - (NSLayoutConstraint *)autoPinEdge:(ALEdge)edge toEdge:(ALEdge)toEdge ofView:(A return [self autoConstrainAttribute:(ALAttribute)edge toAttribute:(ALAttribute)toEdge ofView:otherView withOffset:offset relation:relation]; } - #pragma mark Align Axes /** @@ -563,6 +687,19 @@ - (NSLayoutConstraint *)autoAlignAxis:(ALAxis)axis toSameAxisOfView:(ALView *)ot return [self autoConstrainAttribute:(ALAttribute)axis toAttribute:(ALAttribute)axis ofView:otherView withOffset:offset]; } +/** + Aligns an axis of the view to the same axis of another view with a multiplier. + + @param axis The axis of this view and the other view to align. + @param otherView The other view to align to. Must be in the same view hierarchy as this view. + @param multiplier The multiplier between the axis of this view and the axis of the other view. + @return The constraint added. + */ +- (NSLayoutConstraint *)autoAlignAxis:(ALAxis)axis toSameAxisOfView:(ALView *)otherView withMultiplier:(CGFloat)multiplier +{ + return [self autoConstrainAttribute:(ALAttribute)axis toAttribute:(ALAttribute)axis ofView:otherView withMultiplier:multiplier]; +} + #pragma mark Match Dimensions @@ -646,9 +783,9 @@ - (NSLayoutConstraint *)autoMatchDimension:(ALDimension)dimension toDimension:(A @param size The size to set this view's dimensions to. @return An array of constraints added. */ -- (NSArray *)autoSetDimensionsToSize:(CGSize)size +- (PL__NSArray_of(NSLayoutConstraint *) *)autoSetDimensionsToSize:(CGSize)size { - NSMutableArray *constraints = [NSMutableArray new]; + PL__NSMutableArray_of(NSLayoutConstraint *) *constraints = [NSMutableArray new]; [constraints addObject:[self autoSetDimension:ALDimensionWidth toSize:size.width]]; [constraints addObject:[self autoSetDimension:ALDimensionHeight toSize:size.height]]; return constraints; @@ -694,14 +831,14 @@ - (NSLayoutConstraint *)autoSetDimension:(ALDimension)dimension toSize:(CGFloat) */ - (void)autoSetContentCompressionResistancePriorityForAxis:(ALAxis)axis { - NSAssert([ALView al_isExecutingPriorityConstraintsBlock], @"%@ should only be called from within the block passed into the method +[autoSetPriority:forConstraints:]", NSStringFromSelector(_cmd)); - if ([ALView al_isExecutingPriorityConstraintsBlock]) { + NSAssert([NSLayoutConstraint al_isExecutingPriorityConstraintsBlock], @"%@ should only be called from within the block passed into the method +[autoSetPriority:forConstraints:]", NSStringFromSelector(_cmd)); + if ([NSLayoutConstraint al_isExecutingPriorityConstraintsBlock]) { self.translatesAutoresizingMaskIntoConstraints = NO; ALLayoutConstraintAxis constraintAxis = [NSLayoutConstraint al_constraintAxisForAxis:axis]; #if TARGET_OS_IPHONE - [self setContentCompressionResistancePriority:[ALView al_currentGlobalConstraintPriority] forAxis:constraintAxis]; + [self setContentCompressionResistancePriority:[NSLayoutConstraint al_currentGlobalConstraintPriority] forAxis:constraintAxis]; #else - [self setContentCompressionResistancePriority:[ALView al_currentGlobalConstraintPriority] forOrientation:constraintAxis]; + [self setContentCompressionResistancePriority:[NSLayoutConstraint al_currentGlobalConstraintPriority] forOrientation:constraintAxis]; #endif /* TARGET_OS_IPHONE */ } } @@ -714,14 +851,14 @@ - (void)autoSetContentCompressionResistancePriorityForAxis:(ALAxis)axis */ - (void)autoSetContentHuggingPriorityForAxis:(ALAxis)axis { - NSAssert([ALView al_isExecutingPriorityConstraintsBlock], @"%@ should only be called from within the block passed into the method +[autoSetPriority:forConstraints:]", NSStringFromSelector(_cmd)); - if ([ALView al_isExecutingPriorityConstraintsBlock]) { + NSAssert([NSLayoutConstraint al_isExecutingPriorityConstraintsBlock], @"%@ should only be called from within the block passed into the method +[autoSetPriority:forConstraints:]", NSStringFromSelector(_cmd)); + if ([NSLayoutConstraint al_isExecutingPriorityConstraintsBlock]) { self.translatesAutoresizingMaskIntoConstraints = NO; ALLayoutConstraintAxis constraintAxis = [NSLayoutConstraint al_constraintAxisForAxis:axis]; #if TARGET_OS_IPHONE - [self setContentHuggingPriority:[ALView al_currentGlobalConstraintPriority] forAxis:constraintAxis]; + [self setContentHuggingPriority:[NSLayoutConstraint al_currentGlobalConstraintPriority] forAxis:constraintAxis]; #else - [self setContentHuggingPriority:[ALView al_currentGlobalConstraintPriority] forOrientation:constraintAxis]; + [self setContentHuggingPriority:[NSLayoutConstraint al_currentGlobalConstraintPriority] forOrientation:constraintAxis]; #endif /* TARGET_OS_IPHONE */ } } @@ -819,7 +956,7 @@ - (NSLayoutConstraint *)autoConstrainAttribute:(ALAttribute)attribute toAttribut #pragma mark Pin to Layout Guides #if TARGET_OS_IPHONE - +#if __IPHONE_OS_VERSION_MIN_REQUIRED < __IPHONE_11_0 // Top and bottom layout guides were deprecated in iOS 11 /** Pins the top edge of the view to the top layout guide of the given view controller with an inset. For compatibility with iOS 6 (where layout guides do not exist), this method will simply pin the top edge of @@ -836,7 +973,7 @@ - (NSLayoutConstraint *)autoPinToTopLayoutGuideOfViewController:(UIViewControlle - (NSLayoutConstraint *)autoPinToTopLayoutGuideOfViewController:(UIViewController *)viewController withInset:(CGFloat)inset relation:(NSLayoutRelation)relation { - if (__PureLayout_MinSysVer_iOS_7_0) { + if (PL__PureLayout_MinSysVer_iOS_7_0) { self.translatesAutoresizingMaskIntoConstraints = NO; NSLayoutConstraint *constraint = [NSLayoutConstraint constraintWithItem:self attribute:NSLayoutAttributeTop relatedBy:relation toItem:viewController.topLayoutGuide attribute:NSLayoutAttributeBottom multiplier:1.0 constant:inset]; [viewController.view al_addConstraint:constraint]; // Can't use autoInstall because the layout guide is not a view @@ -870,7 +1007,7 @@ - (NSLayoutConstraint *)autoPinToBottomLayoutGuideOfViewController:(UIViewContro } else if (relation == NSLayoutRelationGreaterThanOrEqual) { relation = NSLayoutRelationLessThanOrEqual; } - if (__PureLayout_MinSysVer_iOS_7_0) { + if (PL__PureLayout_MinSysVer_iOS_7_0) { self.translatesAutoresizingMaskIntoConstraints = NO; NSLayoutConstraint *constraint = [NSLayoutConstraint constraintWithItem:self attribute:NSLayoutAttributeBottom relatedBy:relation toItem:viewController.bottomLayoutGuide attribute:NSLayoutAttributeTop multiplier:1.0 constant:inset]; [viewController.view al_addConstraint:constraint]; // Can't use autoInstall because the layout guide is not a view @@ -881,103 +1018,11 @@ - (NSLayoutConstraint *)autoPinToBottomLayoutGuideOfViewController:(UIViewContro } } +#endif /* __IPHONE_OS_VERSION_MIN_REQUIRED */ #endif /* TARGET_OS_IPHONE */ - -#pragma mark Deprecated Methods - -/** - DEPRECATED as of PureLayout v2.0.0. Retain a reference to and remove specific constraints instead, or recreate the view(s) entirely to remove all constraints. - Removes all explicit constraints that affect the view. - WARNING: Apple's constraint solver is not optimized for large-scale constraint removal; you may encounter major performance issues after using this method. - It is not recommended to use this method to "reset" a view for reuse in a different way with new constraints. Create a new view instead. - NOTE: This method preserves implicit constraints, such as intrinsic content size constraints, which you usually do not want to remove. - */ -- (void)autoRemoveConstraintsAffectingView -{ - [self autoRemoveConstraintsAffectingViewIncludingImplicitConstraints:NO]; -} - -/** - DEPRECATED as of PureLayout v2.0.0. Retain a reference to and remove specific constraints instead, or recreate the view(s) entirely to remove all constraints. - Removes all constraints that affect the view, optionally including implicit constraints. - WARNING: Apple's constraint solver is not optimized for large-scale constraint removal; you may encounter major performance issues after using this method. - It is not recommended to use this method to "reset" a view for reuse in a different way with new constraints. Create a new view instead. - NOTE: Implicit constraints are auto-generated lower priority constraints (such as those that attempt to keep a view at - its intrinsic content size by hugging its content & resisting compression), and you usually do not want to remove these. - - @param shouldRemoveImplicitConstraints Whether implicit constraints should be removed or skipped. - */ -- (void)autoRemoveConstraintsAffectingViewIncludingImplicitConstraints:(BOOL)shouldRemoveImplicitConstraints -{ - NSMutableArray *constraintsToRemove = [NSMutableArray new]; - ALView *startView = self; - do { - for (NSLayoutConstraint *constraint in startView.constraints) { - BOOL isImplicitConstraint = [NSStringFromClass([constraint class]) isEqualToString:@"NSContentSizeLayoutConstraint"]; - if (shouldRemoveImplicitConstraints || !isImplicitConstraint) { - if (constraint.firstItem == self || constraint.secondItem == self) { - [constraintsToRemove addObject:constraint]; - } - } - } - startView = startView.superview; - } while (startView); - [constraintsToRemove autoRemoveConstraints]; -} - -/** - DEPRECATED as of PureLayout v2.0.0. Retain a reference to and remove specific constraints instead, or recreate the view(s) entirely to remove all constraints. - Recursively removes all explicit constraints that affect the view and its subviews. - WARNING: Apple's constraint solver is not optimized for large-scale constraint removal; you may encounter major performance issues after using this method. - It is not recommended to use this method to "reset" views for reuse in a different way with new constraints. Create a new view instead. - NOTE: This method preserves implicit constraints, such as intrinsic content size constraints, which you usually do not want to remove. - */ -- (void)autoRemoveConstraintsAffectingViewAndSubviews -{ - [self autoRemoveConstraintsAffectingViewAndSubviewsIncludingImplicitConstraints:NO]; -} - -/** - DEPRECATED as of PureLayout v2.0.0. Retain a reference to and remove specific constraints instead, or recreate the view(s) entirely to remove all constraints. - Recursively removes all constraints that affect the view and its subviews, optionally including implicit constraints. - WARNING: Apple's constraint solver is not optimized for large-scale constraint removal; you may encounter major performance issues after using this method. - It is not recommended to use this method to "reset" views for reuse in a different way with new constraints. Create a new view instead. - NOTE: Implicit constraints are auto-generated lower priority constraints (such as those that attempt to keep a view at - its intrinsic content size by hugging its content & resisting compression), and you usually do not want to remove these. - - @param shouldRemoveImplicitConstraints Whether implicit constraints should be removed or skipped. - */ -- (void)autoRemoveConstraintsAffectingViewAndSubviewsIncludingImplicitConstraints:(BOOL)shouldRemoveImplicitConstraints -{ - [self autoRemoveConstraintsAffectingViewIncludingImplicitConstraints:shouldRemoveImplicitConstraints]; - for (ALView *subview in self.subviews) { - [subview autoRemoveConstraintsAffectingViewAndSubviewsIncludingImplicitConstraints:shouldRemoveImplicitConstraints]; - } -} - - #pragma mark Internal Methods -/** - Applies the global constraint priority and identifier to the given constraint. - This should be done before installing all constraints. - - @param constraint The constraint to set the global priority and identifier on. - */ -+ (void)al_applyGlobalStateToConstraint:(NSLayoutConstraint *)constraint -{ - if ([ALView al_isExecutingPriorityConstraintsBlock]) { - constraint.priority = [ALView al_currentGlobalConstraintPriority]; - } -#if __PureLayout_MinBaseSDK_iOS_8_0 - NSString *globalConstraintIdentifier = [ALView al_currentGlobalConstraintIdentifier]; - if (globalConstraintIdentifier) { - [constraint autoIdentify:globalConstraintIdentifier]; - } -#endif /* __PureLayout_MinBaseSDK_iOS_8_0 */ -} - /** Adds the given constraint to this view after applying the global state to the constraint. NOTE: This method is compatible with all versions of iOS, and should be used for older versions before the active @@ -989,9 +1034,9 @@ + (void)al_applyGlobalStateToConstraint:(NSLayoutConstraint *)constraint */ - (void)al_addConstraint:(NSLayoutConstraint *)constraint { - [ALView al_applyGlobalStateToConstraint:constraint]; - if ([ALView al_preventAutomaticConstraintInstallation]) { - [[ALView al_currentArrayOfCreatedConstraints] addObject:constraint]; + [NSLayoutConstraint al_applyGlobalStateToConstraint:constraint]; + if ([NSLayoutConstraint al_preventAutomaticConstraintInstallation]) { + [[NSLayoutConstraint al_currentArrayOfCreatedConstraints] addObject:constraint]; } else { [self addConstraint:constraint]; } @@ -1047,13 +1092,13 @@ - (NSLayoutConstraint *)al_alignAttribute:(ALAttribute)attribute toView:(ALView NSAssert(axis != ALAxisVertical, @"Cannot align views that are distributed vertically with ALAttributeBaseline."); constraint = [self autoAlignAxis:ALAxisBaseline toSameAxisOfView:otherView]; break; -#if __PureLayout_MinBaseSDK_iOS_8_0 +#if PL__PureLayout_MinBaseSDK_iOS_8_0 case ALAttributeFirstBaseline: - NSAssert(__PureLayout_MinSysVer_iOS_8_0, @"ALAttributeFirstBaseline is only supported on iOS 8.0 or higher."); + NSAssert(PL__PureLayout_MinSysVer_iOS_8_0, @"ALAttributeFirstBaseline is only supported on iOS 8.0 or higher."); NSAssert(axis != ALAxisVertical, @"Cannot align views that are distributed vertically with ALAttributeFirstBaseline."); constraint = [self autoAlignAxis:ALAxisFirstBaseline toSameAxisOfView:otherView]; break; -#endif /* __PureLayout_MinBaseSDK_iOS_8_0 */ +#endif /* PL__PureLayout_MinBaseSDK_iOS_8_0 */ case ALAttributeTop: NSAssert(axis != ALAxisVertical, @"Cannot align views that are distributed vertically with ALAttributeTop."); constraint = [self autoPinEdge:ALEdgeTop toEdge:ALEdgeTop ofView:otherView]; @@ -1078,8 +1123,22 @@ - (NSLayoutConstraint *)al_alignAttribute:(ALAttribute)attribute toView:(ALView NSAssert(axis == ALAxisVertical, @"Cannot align views that are distributed horizontally with ALAttributeTrailing."); constraint = [self autoPinEdge:ALEdgeTrailing toEdge:ALEdgeTrailing ofView:otherView]; break; + + // All of the below attributes are invalid as alignment options. Listing them explicitly (even though they just fall through to the default case) to avoid an incomplete switch statement warning from the compiler. + case ALAttributeWidth: + case ALAttributeHeight: +#if PL__PureLayout_MinBaseSDK_iOS_8_0 + case ALAttributeMarginLeft: + case ALAttributeMarginRight: + case ALAttributeMarginTop: + case ALAttributeMarginBottom: + case ALAttributeMarginLeading: + case ALAttributeMarginTrailing: + case ALAttributeMarginAxisVertical: + case ALAttributeMarginAxisHorizontal: +#endif /* PL__PureLayout_MinBaseSDK_iOS_8_0 */ default: - NSAssert(nil, @"Unsupported alignment option."); + NSAssert(nil, @"Unsupported attribute for alignment."); break; } return constraint; diff --git a/PureLayout/PureLayout/NSArray+PureLayout.h b/PureLayout/PureLayout/NSArray+PureLayout.h deleted file mode 100755 index 10ece57..0000000 --- a/PureLayout/PureLayout/NSArray+PureLayout.h +++ /dev/null @@ -1,107 +0,0 @@ -// -// NSArray+PureLayout.h -// v2.0.5 -// https://github.com/smileyborg/PureLayout -// -// Copyright (c) 2012 Richard Turton -// Copyright (c) 2013-2015 Tyler Fox -// -// This code is distributed under the terms and conditions of the MIT license. -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to -// deal in the Software without restriction, including without limitation the -// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or -// sell copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -// IN THE SOFTWARE. -// - -#import "PureLayoutDefines.h" - - -#pragma mark - NSArray+PureLayout - -/** - A category on NSArray that provides a simple yet powerful interface to: - - Manage an array of Auto Layout constraints - - Apply constraints to an array of views - */ -@interface NSArray (PureLayout) - - -#pragma mark Array of Constraints - -/** Activates the constraints in this array. */ -- (void)autoInstallConstraints; - -/** Deactivates the constraints in this array. */ -- (void)autoRemoveConstraints; - -#if __PureLayout_MinBaseSDK_iOS_8_0 - -/** Sets the string as the identifier for the constraints in this array. Available in iOS 7.0 and OS X 10.9 and later. */ -- (instancetype)autoIdentifyConstraints:(NSString *)identifier; - -#endif /* __PureLayout_MinBaseSDK_iOS_8_0 */ - - -#pragma mark Array of Views - -/** Aligns views in this array to one another along a given edge. */ -- (NSArray *)autoAlignViewsToEdge:(ALEdge)edge; - -/** Aligns views in this array to one another along a given axis. */ -- (NSArray *)autoAlignViewsToAxis:(ALAxis)axis; - -/** Matches a given dimension of all the views in this array. */ -- (NSArray *)autoMatchViewsDimension:(ALDimension)dimension; - -/** Sets the given dimension of all the views in this array to a given size. */ -- (NSArray *)autoSetViewsDimension:(ALDimension)dimension toSize:(CGFloat)size; - -/** Sets all of the views in this array to a given size. */ -- (NSArray *)autoSetViewsDimensionsToSize:(CGSize)size; - - -/** Distributes the views in this array equally along the selected axis in their superview. Views will be the same size (variable) in the dimension along the axis and will have spacing (fixed) between them. */ -- (NSArray *)autoDistributeViewsAlongAxis:(ALAxis)axis - alignedTo:(ALAttribute)alignment - withFixedSpacing:(CGFloat)spacing; - -/** Distributes the views in this array equally along the selected axis in their superview. Views will be the same size (variable) in the dimension along the axis and will have spacing (fixed) between them, with optional insets from the first and last views to their superview. */ -- (NSArray *)autoDistributeViewsAlongAxis:(ALAxis)axis - alignedTo:(ALAttribute)alignment - withFixedSpacing:(CGFloat)spacing - insetSpacing:(BOOL)shouldSpaceInsets; - -/** Distributes the views in this array equally along the selected axis in their superview. Views will have spacing (fixed) between them, with optional insets from the first and last views to their superview, and optionally constrained to the same size in the dimension along the axis. */ -- (NSArray *)autoDistributeViewsAlongAxis:(ALAxis)axis - alignedTo:(ALAttribute)alignment - withFixedSpacing:(CGFloat)spacing - insetSpacing:(BOOL)shouldSpaceInsets - matchedSizes:(BOOL)shouldMatchSizes; - - -/** Distributes the views in this array equally along the selected axis in their superview. Views will be the same size (fixed) in the dimension along the axis and will have spacing (variable) between them. */ -- (NSArray *)autoDistributeViewsAlongAxis:(ALAxis)axis - alignedTo:(ALAttribute)alignment - withFixedSize:(CGFloat)size; - -/** Distributes the views in this array equally along the selected axis in their superview. Views will be the same size (fixed) in the dimension along the axis and will have spacing (variable) between them, with optional insets from the first and last views to their superview. */ -- (NSArray *)autoDistributeViewsAlongAxis:(ALAxis)axis - alignedTo:(ALAttribute)alignment - withFixedSize:(CGFloat)size - insetSpacing:(BOOL)shouldSpaceInsets; - -@end diff --git a/PureLayout/PureLayout/NSArray+PureLayout.m b/PureLayout/PureLayout/NSArray+PureLayout.m index 81c0fb5..a66f05e 100755 --- a/PureLayout/PureLayout/NSArray+PureLayout.m +++ b/PureLayout/PureLayout/NSArray+PureLayout.m @@ -1,7 +1,6 @@ // // NSArray+PureLayout.m -// v2.0.5 -// https://github.com/smileyborg/PureLayout +// https://github.com/PureLayout/PureLayout // // Copyright (c) 2012 Richard Turton // Copyright (c) 2013-2015 Tyler Fox @@ -45,21 +44,21 @@ @implementation NSArray (PureLayout) */ - (void)autoInstallConstraints { -#if __PureLayout_MinBaseSDK_iOS_8_0 || __PureLayout_MinBaseSDK_OSX_10_10 +#if PL__PureLayout_MinBaseSDK_iOS_8_0 || PL__PureLayout_MinBaseSDK_OSX_10_10 if ([NSLayoutConstraint respondsToSelector:@selector(activateConstraints:)]) { for (id object in self) { if ([object isKindOfClass:[NSLayoutConstraint class]]) { - [ALView al_applyGlobalStateToConstraint:object]; + [NSLayoutConstraint al_applyGlobalStateToConstraint:object]; } } - if ([ALView al_preventAutomaticConstraintInstallation]) { - [[ALView al_currentArrayOfCreatedConstraints] addObjectsFromArray:self]; + if ([NSLayoutConstraint al_preventAutomaticConstraintInstallation]) { + [[NSLayoutConstraint al_currentArrayOfCreatedConstraints] addObjectsFromArray:self]; } else { [NSLayoutConstraint activateConstraints:self]; } return; } -#endif /* __PureLayout_MinBaseSDK_iOS_8_0 || __PureLayout_MinBaseSDK_OSX_10_10 */ +#endif /* PL__PureLayout_MinBaseSDK_iOS_8_0 || PL__PureLayout_MinBaseSDK_OSX_10_10 */ for (id object in self) { if ([object isKindOfClass:[NSLayoutConstraint class]]) { @@ -73,12 +72,12 @@ - (void)autoInstallConstraints */ - (void)autoRemoveConstraints { -#if __PureLayout_MinBaseSDK_iOS_8_0 || __PureLayout_MinBaseSDK_OSX_10_10 +#if PL__PureLayout_MinBaseSDK_iOS_8_0 || PL__PureLayout_MinBaseSDK_OSX_10_10 if ([NSLayoutConstraint respondsToSelector:@selector(deactivateConstraints:)]) { [NSLayoutConstraint deactivateConstraints:self]; return; } -#endif /* __PureLayout_MinBaseSDK_iOS_8_0 || __PureLayout_MinBaseSDK_OSX_10_10 */ +#endif /* PL__PureLayout_MinBaseSDK_iOS_8_0 || PL__PureLayout_MinBaseSDK_OSX_10_10 */ for (id object in self) { if ([object isKindOfClass:[NSLayoutConstraint class]]) { @@ -87,7 +86,7 @@ - (void)autoRemoveConstraints } } -#if __PureLayout_MinBaseSDK_iOS_8_0 +#if PL__PureLayout_MinBaseSDK_iOS_8_0 || PL__PureLayout_MinBaseSDK_OSX_10_10 /** Sets the string as the identifier for the constraints in this array. Available in iOS 7.0 and OS X 10.9 and later. @@ -107,7 +106,7 @@ - (instancetype)autoIdentifyConstraints:(NSString *)identifier return self; } -#endif /* __PureLayout_MinBaseSDK_iOS_8_0 */ +#endif /* PL__PureLayout_MinBaseSDK_iOS_8_0 || PL__PureLayout_MinBaseSDK_OSX_10_10 */ #pragma mark Array of Views @@ -119,10 +118,10 @@ - (instancetype)autoIdentifyConstraints:(NSString *)identifier @param edge The edge to which the views will be aligned. @return An array of constraints added. */ -- (NSArray *)autoAlignViewsToEdge:(ALEdge)edge +- (PL__NSArray_of(NSLayoutConstraint *) *)autoAlignViewsToEdge:(ALEdge)edge { NSAssert([self al_containsMinimumNumberOfViews:2], @"This array must contain at least 2 views."); - NSMutableArray *constraints = [NSMutableArray new]; + PL__NSMutableArray_of(NSLayoutConstraint *) *constraints = [NSMutableArray new]; ALView *previousView = nil; for (id object in self) { if ([object isKindOfClass:[ALView class]]) { @@ -144,10 +143,10 @@ - (NSArray *)autoAlignViewsToEdge:(ALEdge)edge @param axis The axis to which the views will be aligned. @return An array of constraints added. */ -- (NSArray *)autoAlignViewsToAxis:(ALAxis)axis +- (PL__NSArray_of(NSLayoutConstraint *) *)autoAlignViewsToAxis:(ALAxis)axis { NSAssert([self al_containsMinimumNumberOfViews:2], @"This array must contain at least 2 views."); - NSMutableArray *constraints = [NSMutableArray new]; + PL__NSMutableArray_of(NSLayoutConstraint *) *constraints = [NSMutableArray new]; ALView *previousView = nil; for (id object in self) { if ([object isKindOfClass:[ALView class]]) { @@ -169,10 +168,10 @@ - (NSArray *)autoAlignViewsToAxis:(ALAxis)axis @param dimension The dimension to match for all of the views. @return An array of constraints added. */ -- (NSArray *)autoMatchViewsDimension:(ALDimension)dimension +- (PL__NSArray_of(NSLayoutConstraint *) *)autoMatchViewsDimension:(ALDimension)dimension { NSAssert([self al_containsMinimumNumberOfViews:2], @"This array must contain at least 2 views."); - NSMutableArray *constraints = [NSMutableArray new]; + PL__NSMutableArray_of(NSLayoutConstraint *) *constraints = [NSMutableArray new]; ALView *previousView = nil; for (id object in self) { if ([object isKindOfClass:[ALView class]]) { @@ -195,10 +194,10 @@ - (NSArray *)autoMatchViewsDimension:(ALDimension)dimension @param size The size to set the given dimension of each view to. @return An array of constraints added. */ -- (NSArray *)autoSetViewsDimension:(ALDimension)dimension toSize:(CGFloat)size +- (PL__NSArray_of(NSLayoutConstraint *) *)autoSetViewsDimension:(ALDimension)dimension toSize:(CGFloat)size { NSAssert([self al_containsMinimumNumberOfViews:1], @"This array must contain at least 1 view."); - NSMutableArray *constraints = [NSMutableArray new]; + PL__NSMutableArray_of(NSLayoutConstraint *) *constraints = [NSMutableArray new]; for (id object in self) { if ([object isKindOfClass:[ALView class]]) { ALView *view = (ALView *)object; @@ -216,9 +215,9 @@ - (NSArray *)autoSetViewsDimension:(ALDimension)dimension toSize:(CGFloat)size @param size The size to set each view's dimensions to. @return An array of constraints added. */ -- (NSArray *)autoSetViewsDimensionsToSize:(CGSize)size +- (PL__NSArray_of(NSLayoutConstraint *) *)autoSetViewsDimensionsToSize:(CGSize)size { - NSMutableArray *constraints = [NSMutableArray new]; + PL__NSMutableArray_of(NSLayoutConstraint *) *constraints = [NSMutableArray new]; [constraints addObjectsFromArray:[self autoSetViewsDimension:ALDimensionWidth toSize:size.width]]; [constraints addObjectsFromArray:[self autoSetViewsDimension:ALDimensionHeight toSize:size.height]]; return constraints; @@ -235,9 +234,9 @@ Views will be the same size (variable) in the dimension along the axis and will @param spacing The fixed amount of spacing between each view. @return An array of constraints added. */ -- (NSArray *)autoDistributeViewsAlongAxis:(ALAxis)axis - alignedTo:(ALAttribute)alignment - withFixedSpacing:(CGFloat)spacing +- (PL__NSArray_of(NSLayoutConstraint *) *)autoDistributeViewsAlongAxis:(ALAxis)axis + alignedTo:(ALAttribute)alignment + withFixedSpacing:(CGFloat)spacing { return [self autoDistributeViewsAlongAxis:axis alignedTo:alignment @@ -256,10 +255,10 @@ Views will be the same size (variable) in the dimension along the axis and will @param shouldSpaceInsets Whether the first and last views should be equally inset from their superview. @return An array of constraints added. */ -- (NSArray *)autoDistributeViewsAlongAxis:(ALAxis)axis - alignedTo:(ALAttribute)alignment - withFixedSpacing:(CGFloat)spacing - insetSpacing:(BOOL)shouldSpaceInsets +- (PL__NSArray_of(NSLayoutConstraint *) *)autoDistributeViewsAlongAxis:(ALAxis)axis + alignedTo:(ALAttribute)alignment + withFixedSpacing:(CGFloat)spacing + insetSpacing:(BOOL)shouldSpaceInsets { return [self autoDistributeViewsAlongAxis:axis alignedTo:alignment @@ -281,21 +280,21 @@ - (NSArray *)autoDistributeViewsAlongAxis:(ALAxis)axis NOTE: All views must specify an intrinsic content size if passing NO, otherwise the layout will be ambiguous! @return An array of constraints added. */ -- (NSArray *)autoDistributeViewsAlongAxis:(ALAxis)axis - alignedTo:(ALAttribute)alignment - withFixedSpacing:(CGFloat)spacing - insetSpacing:(BOOL)shouldSpaceInsets - matchedSizes:(BOOL)shouldMatchSizes +- (PL__NSArray_of(NSLayoutConstraint *) *)autoDistributeViewsAlongAxis:(ALAxis)axis + alignedTo:(ALAttribute)alignment + withFixedSpacing:(CGFloat)spacing + insetSpacing:(BOOL)shouldSpaceInsets + matchedSizes:(BOOL)shouldMatchSizes { - NSAssert([self al_containsMinimumNumberOfViews:2], @"This array must contain at least 2 views to distribute."); + NSAssert([self al_containsMinimumNumberOfViews:1], @"This array must contain at least 1 view to distribute."); ALDimension matchedDimension; ALEdge firstEdge, lastEdge; switch (axis) { case ALAxisHorizontal: case ALAxisBaseline: // same value as ALAxisLastBaseline -#if __PureLayout_MinBaseSDK_iOS_8_0 +#if PL__PureLayout_MinBaseSDK_iOS_8_0 case ALAxisFirstBaseline: -#endif /* __PureLayout_MinBaseSDK_iOS_8_0 */ +#endif /* PL__PureLayout_MinBaseSDK_iOS_8_0 */ matchedDimension = ALDimensionWidth; firstEdge = ALEdgeLeading; lastEdge = ALEdgeTrailing; @@ -312,7 +311,7 @@ - (NSArray *)autoDistributeViewsAlongAxis:(ALAxis)axis CGFloat leadingSpacing = shouldSpaceInsets ? spacing : 0.0; CGFloat trailingSpacing = shouldSpaceInsets ? spacing : 0.0; - NSMutableArray *constraints = [NSMutableArray new]; + PL__NSMutableArray_of(NSLayoutConstraint *) *constraints = [NSMutableArray new]; ALView *previousView = nil; for (id object in self) { if ([object isKindOfClass:[ALView class]]) { @@ -350,9 +349,9 @@ Views will be the same size (fixed) in the dimension along the axis and will hav @param size The fixed size of each view in the dimension along the given axis. @return An array of constraints added. */ -- (NSArray *)autoDistributeViewsAlongAxis:(ALAxis)axis - alignedTo:(ALAttribute)alignment - withFixedSize:(CGFloat)size +- (PL__NSArray_of(NSLayoutConstraint *) *)autoDistributeViewsAlongAxis:(ALAxis)axis + alignedTo:(ALAttribute)alignment + withFixedSize:(CGFloat)size { return [self autoDistributeViewsAlongAxis:axis alignedTo:alignment @@ -371,20 +370,20 @@ Views will be the same size (fixed) in the dimension along the axis and will hav @param shouldSpaceInsets Whether the first and last views should be equally inset from their superview. @return An array of constraints added. */ -- (NSArray *)autoDistributeViewsAlongAxis:(ALAxis)axis - alignedTo:(ALAttribute)alignment - withFixedSize:(CGFloat)size - insetSpacing:(BOOL)shouldSpaceInsets +- (PL__NSArray_of(NSLayoutConstraint *) *)autoDistributeViewsAlongAxis:(ALAxis)axis + alignedTo:(ALAttribute)alignment + withFixedSize:(CGFloat)size + insetSpacing:(BOOL)shouldSpaceInsets { - NSAssert([self al_containsMinimumNumberOfViews:2], @"This array must contain at least 2 views to distribute."); + NSAssert([self al_containsMinimumNumberOfViews:1], @"This array must contain at least 1 view to distribute."); ALDimension fixedDimension; NSLayoutAttribute attribute; switch (axis) { case ALAxisHorizontal: case ALAxisBaseline: // same value as ALAxisLastBaseline -#if __PureLayout_MinBaseSDK_iOS_8_0 +#if PL__PureLayout_MinBaseSDK_iOS_8_0 case ALAxisFirstBaseline: -#endif /* __PureLayout_MinBaseSDK_iOS_8_0 */ +#endif /* PL__PureLayout_MinBaseSDK_iOS_8_0 */ fixedDimension = ALDimensionWidth; attribute = NSLayoutAttributeCenterX; break; @@ -397,19 +396,21 @@ - (NSArray *)autoDistributeViewsAlongAxis:(ALAxis)axis return nil; } #if TARGET_OS_IPHONE -# if !defined(PURELAYOUT_APP_EXTENSIONS) - BOOL isRightToLeftLayout = [[UIApplication sharedApplication] userInterfaceLayoutDirection] == UIUserInterfaceLayoutDirectionRightToLeft; -# else - // App Extensions may not access -[UIApplication sharedApplication]; fall back to checking the bundle's preferred localization character direction - BOOL isRightToLeftLayout = [NSLocale characterDirectionForLanguage:[[NSBundle mainBundle] preferredLocalizations][0]] == NSLocaleLanguageDirectionRightToLeft; -# endif /* !defined(PURELAYOUT_APP_EXTENSIONS) */ + BOOL isRightToLeftLayout; + if ([[[[NSBundle mainBundle] bundlePath] pathExtension] isEqualToString:@"appex"]) { + // App Extensions may not access -[UIApplication sharedApplication]; fall back to checking the bundle's preferred localization character direction + isRightToLeftLayout = [NSLocale characterDirectionForLanguage:[[NSBundle mainBundle] preferredLocalizations][0]] == NSLocaleLanguageDirectionRightToLeft; + } else { + // Use dynamic call to sharedApplication to workaround compilation error when building against app extensions + isRightToLeftLayout = [[UIApplication performSelector:@selector(sharedApplication)] userInterfaceLayoutDirection] == UIUserInterfaceLayoutDirectionRightToLeft; + } #else BOOL isRightToLeftLayout = [[NSApplication sharedApplication] userInterfaceLayoutDirection] == NSUserInterfaceLayoutDirectionRightToLeft; #endif /* TARGET_OS_IPHONE */ BOOL shouldFlipOrder = isRightToLeftLayout && (axis != ALAxisVertical); // imitate the effect of leading/trailing when distributing horizontally - NSMutableArray *constraints = [NSMutableArray new]; - NSArray *views = [self al_copyViewsOnly]; + PL__NSMutableArray_of(NSLayoutConstraint *) *constraints = [NSMutableArray new]; + PL__NSArray_of(ALView *) *views = [self al_copyViewsOnly]; NSUInteger numberOfViews = [views count]; ALView *commonSuperview = [views al_commonSuperviewOfViews]; ALView *previousView = nil; @@ -443,7 +444,7 @@ - (NSArray *)autoDistributeViewsAlongAxis:(ALAxis)axis #pragma mark Internal Helper Methods /** - Returns the common superview for the views in this array. + Returns the common superview for the views in this array. If there is only one view in the array, its superview will be returned. Raises an exception if the views in this array do not share a common superview. @return The common superview for the views in this array. @@ -458,7 +459,7 @@ - (ALView *)al_commonSuperviewOfViews if (previousView) { commonSuperview = [view al_commonSuperviewWithView:commonSuperview]; } else { - commonSuperview = view; + commonSuperview = view.superview; } previousView = view; } @@ -492,9 +493,9 @@ - (BOOL)al_containsMinimumNumberOfViews:(NSUInteger)minimumNumberOfViews @return A new array containing only the views that are in this array. */ -- (NSArray *)al_copyViewsOnly +- (PL__NSArray_of(ALView *) *)al_copyViewsOnly { - NSMutableArray *viewsOnlyArray = [NSMutableArray arrayWithCapacity:[self count]]; + PL__NSMutableArray_of(ALView *) *viewsOnlyArray = [NSMutableArray arrayWithCapacity:[self count]]; for (id object in self) { if ([object isKindOfClass:[ALView class]]) { [viewsOnlyArray addObject:object]; diff --git a/PureLayout/PureLayout/NSLayoutConstraint+PureLayout.h b/PureLayout/PureLayout/NSLayoutConstraint+PureLayout.h deleted file mode 100755 index 87797f6..0000000 --- a/PureLayout/PureLayout/NSLayoutConstraint+PureLayout.h +++ /dev/null @@ -1,58 +0,0 @@ -// -// NSLayoutConstraint+PureLayout.h -// v2.0.5 -// https://github.com/smileyborg/PureLayout -// -// Copyright (c) 2013-2015 Tyler Fox -// -// This code is distributed under the terms and conditions of the MIT license. -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to -// deal in the Software without restriction, including without limitation the -// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or -// sell copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -// IN THE SOFTWARE. -// - -#import "PureLayoutDefines.h" - - -#pragma mark - NSLayoutConstraint+PureLayout - -/** - A category on NSLayoutConstraint that allows constraints to be easily installed & removed. - */ -@interface NSLayoutConstraint (PureLayout) - - -#pragma mark Install & Remove Constraints - -/** Activates the the constraint. */ -- (void)autoInstall; - -/** Deactivates the constraint. */ -- (void)autoRemove; - - -#pragma mark Identify Constraints - -#if __PureLayout_MinBaseSDK_iOS_8_0 || __PureLayout_MinBaseSDK_OSX_10_10 - -/** Sets the string as the identifier for this constraint. Available in iOS 7.0 and OS X 10.9 and later. */ -- (instancetype)autoIdentify:(NSString *)identifier; - -#endif /* __PureLayout_MinBaseSDK_iOS_8_0 || __PureLayout_MinBaseSDK_OSX_10_10 */ - -@end diff --git a/PureLayout/PureLayout/NSLayoutConstraint+PureLayout.m b/PureLayout/PureLayout/NSLayoutConstraint+PureLayout.m index 1a290b5..4ee751d 100755 --- a/PureLayout/PureLayout/NSLayoutConstraint+PureLayout.m +++ b/PureLayout/PureLayout/NSLayoutConstraint+PureLayout.m @@ -1,7 +1,6 @@ // // NSLayoutConstraint+PureLayout.m -// v2.0.5 -// https://github.com/smileyborg/PureLayout +// https://github.com/PureLayout/PureLayout // // Copyright (c) 2013-2015 Tyler Fox // @@ -28,6 +27,7 @@ #import "NSLayoutConstraint+PureLayout.h" #import "ALView+PureLayout.h" +#import "NSArray+PureLayout.h" #import "PureLayout+Internal.h" @@ -35,25 +35,267 @@ @implementation NSLayoutConstraint (PureLayout) +#pragma mark Batch Constraint Creation -#pragma mark Installing & Removing Constraints +/** + A global variable that stores a stack of arrays of constraints created without being immediately installed. + When executing a constraints block passed into the +[autoCreateConstraintsWithoutInstalling:] method, a new + mutable array is pushed onto this stack, and all constraints created with PureLayout in the block are added + to this array. When the block finishes executing, the array is popped off this stack. Automatic constraint + installation is prevented if this stack contains at least 1 array. + + NOTE: Access to this variable is not synchronized (and should only be done on the main thread). + */ +static PL__NSMutableArray_of(PL__NSMutableArray_of(NSLayoutConstraint *) *) *_al_arraysOfCreatedConstraints = nil; + +/** + A global variable that is set to YES when installing a batch of constraints collected from a call to +[autoCreateAndInstallConstraints]. + When this flag is YES, constraints are installed immediately without checking for or adding to the +[al_currentArrayOfCreatedConstraints]. + This is necessary to properly handle nested calls to +[autoCreateAndInstallConstraints], where calls whose block contains other call(s) + should not return constraints from within the blocks of nested call(s). + */ +static BOOL _al_isInstallingCreatedConstraints = NO; + +/** + Accessor for the global state that stores arrays of constraints created without being installed. + */ ++ (PL__NSMutableArray_of(PL__NSMutableArray_of(NSLayoutConstraint *) *) *)al_arraysOfCreatedConstraints +{ + NSAssert([NSThread isMainThread], @"PureLayout is not thread safe, and must be used exclusively from the main thread."); + if (!_al_arraysOfCreatedConstraints) { + _al_arraysOfCreatedConstraints = [NSMutableArray new]; + } + return _al_arraysOfCreatedConstraints; +} + +/** + Accessor for the current mutable array of constraints created without being immediately installed. + */ ++ (PL__NSMutableArray_of(NSLayoutConstraint *) *)al_currentArrayOfCreatedConstraints +{ + return [[self al_arraysOfCreatedConstraints] lastObject]; +} + +/** + Accessor for the global state that determines whether automatic constraint installation should be prevented. + */ ++ (BOOL)al_preventAutomaticConstraintInstallation +{ + return (_al_isInstallingCreatedConstraints == NO) && ([[self al_arraysOfCreatedConstraints] count] > 0); +} + +/** + Creates all of the constraints in the block, then installs (activates) them all at once. + All constraints created from calls to the PureLayout API in the block are returned in a single array. + This may be more efficient than installing (activating) each constraint one-by-one. + + Note: calls to this method may be nested. The constraints returned from a call will NOT include constraints + created in nested calls; constraints are only returned from the inner-most call they are created within. + + @param block A block of method calls to the PureLayout API that create constraints. + @return An array of the constraints that were created from calls to the PureLayout API inside the block. + */ ++ (PL__NSArray_of(NSLayoutConstraint *) *)autoCreateAndInstallConstraints:(__attribute__((noescape)) ALConstraintsBlock)block +{ + NSArray *createdConstraints = [self autoCreateConstraintsWithoutInstalling:block]; + _al_isInstallingCreatedConstraints = YES; + [createdConstraints autoInstallConstraints]; + _al_isInstallingCreatedConstraints = NO; + return createdConstraints; +} + +/** + Creates all of the constraints in the block but prevents them from being automatically installed (activated). + All constraints created from calls to the PureLayout API in the block are returned in a single array. + + Note: calls to this method may be nested. The constraints returned from a call will NOT include constraints + created in nested calls; constraints are only returned from the inner-most call they are created within. + + @param block A block of method calls to the PureLayout API that create constraints. + @return An array of the constraints that were created from calls to the PureLayout API inside the block. + */ ++ (PL__NSArray_of(NSLayoutConstraint *) *)autoCreateConstraintsWithoutInstalling:(__attribute__((noescape)) ALConstraintsBlock)block +{ + NSAssert(block, @"The constraints block cannot be nil."); + NSArray *createdConstraints = nil; + if (block) { + [[self al_arraysOfCreatedConstraints] addObject:[NSMutableArray new]]; + block(); + createdConstraints = [self al_currentArrayOfCreatedConstraints]; + [[self al_arraysOfCreatedConstraints] removeLastObject]; + } + return createdConstraints; +} + + +#pragma mark Set Priority For Constraints + +/** + A global variable that stores a stack of layout priorities to set on constraints. + When executing a constraints block passed into the +[autoSetPriority:forConstraints:] method, the priority for + that call is pushed onto this stack, and when the block finishes executing, that priority is popped off this + stack. If this stack contains at least 1 priority, the priority at the top of the stack will be set for all + constraints created by this library (even if automatic constraint installation is being prevented). + NOTE: Access to this variable is not synchronized (and should only be done on the main thread). + */ +static PL__NSMutableArray_of(NSNumber *) *_al_globalConstraintPriorities = nil; + +/** + Accessor for the global stack of layout priorities. + */ ++ (PL__NSMutableArray_of(NSNumber *) *)al_globalConstraintPriorities +{ + NSAssert([NSThread isMainThread], @"PureLayout is not thread safe, and must be used exclusively from the main thread."); + if (!_al_globalConstraintPriorities) { + _al_globalConstraintPriorities = [NSMutableArray new]; + } + return _al_globalConstraintPriorities; +} + +/** + Returns the current layout priority to use for constraints. + When executing a constraints block passed into +[autoSetPriority:forConstraints:], this will return + the priority for the current block. Otherwise, the default Required priority is returned. + */ ++ (ALLayoutPriority)al_currentGlobalConstraintPriority +{ + PL__NSMutableArray_of(NSNumber *) *globalConstraintPriorities = [self al_globalConstraintPriorities]; + if ([globalConstraintPriorities count] == 0) { + return ALLayoutPriorityRequired; + } + return [[globalConstraintPriorities lastObject] floatValue]; +} + +/** + Accessor for the global state that determines if we're currently in the scope of a priority constraints block. + */ ++ (BOOL)al_isExecutingPriorityConstraintsBlock +{ + return [[self al_globalConstraintPriorities] count] > 0; +} + +/** + Sets the constraint priority to the given value for all constraints created using the PureLayout + API within the given constraints block. + + NOTE: This method will have no effect (and will NOT set the priority) on constraints created or added + without using the PureLayout API! + + @param priority The layout priority to be set on all constraints created in the constraints block. + @param block A block of method calls to the PureLayout API that create and install constraints. + */ ++ (void)autoSetPriority:(ALLayoutPriority)priority forConstraints:(__attribute__((noescape)) ALConstraintsBlock)block +{ + NSAssert(block, @"The constraints block cannot be nil."); + if (block) { + [[self al_globalConstraintPriorities] addObject:@(priority)]; + block(); + [[self al_globalConstraintPriorities] removeLastObject]; + } +} + + +#pragma mark Identify Constraints + +#if PL__PureLayout_MinBaseSDK_iOS_8_0 || PL__PureLayout_MinBaseSDK_OSX_10_10 + +/** + A global variable that stores a stack of identifier strings to set on constraints. + When executing a constraints block passed into the +[autoSetIdentifier:forConstraints:] method, the identifier for + that call is pushed onto this stack, and when the block finishes executing, that identifier is popped off this + stack. If this stack contains at least 1 identifier, the identifier at the top of the stack will be set for all + constraints created by this library (even if automatic constraint installation is being prevented). + NOTE: Access to this variable is not synchronized (and should only be done on the main thread). + */ +static PL__NSMutableArray_of(NSString *) *_al_globalConstraintIdentifiers = nil; + +/** + Accessor for the global state of constraint identifiers. + */ ++ (PL__NSMutableArray_of(NSString *) *)al_globalConstraintIdentifiers +{ + NSAssert([NSThread isMainThread], @"PureLayout is not thread safe, and must be used exclusively from the main thread."); + if (!_al_globalConstraintIdentifiers) { + _al_globalConstraintIdentifiers = [NSMutableArray new]; + } + return _al_globalConstraintIdentifiers; +} + +/** + Returns the current identifier string to use for constraints. + When executing a constraints block passed into +[autoSetIdentifier:forConstraints:], this will return + the identifier for the current block. Otherwise, nil is returned. + */ ++ (NSString *)al_currentGlobalConstraintIdentifier +{ + PL__NSMutableArray_of(NSString *) *globalConstraintIdentifiers = [self al_globalConstraintIdentifiers]; + if ([globalConstraintIdentifiers count] == 0) { + return nil; + } + return [globalConstraintIdentifiers lastObject]; +} + +/** + Sets the identifier for all constraints created using the PureLayout API within the given constraints block. + + NOTE: This method will have no effect (and will NOT set the identifier) on constraints created or added + without using the PureLayout API! + + @param identifier A string used to identify all constraints created in the constraints block. + @param block A block of method calls to the PureLayout API that create and install constraints. + */ ++ (void)autoSetIdentifier:(NSString *)identifier forConstraints:(__attribute__((noescape)) ALConstraintsBlock)block +{ + NSAssert(block, @"The constraints block cannot be nil."); + NSAssert(identifier, @"The identifier string cannot be nil."); + if (block) { + if (identifier) { + [[self al_globalConstraintIdentifiers] addObject:identifier]; + } + block(); + if (identifier) { + [[self al_globalConstraintIdentifiers] removeLastObject]; + } + } +} + +/** + Sets the string as the identifier for this constraint. Available in iOS 7.0 and OS X 10.9 and later. + The identifier will be printed along with the constraint's description. + This is helpful to document a constraint's purpose and aid in debugging. + + @param identifier A string used to identify this constraint. + @return This constraint. + */ +- (instancetype)autoIdentify:(NSString *)identifier +{ + if ([self respondsToSelector:@selector(setIdentifier:)]) { + self.identifier = identifier; + } + return self; +} + +#endif /* PL__PureLayout_MinBaseSDK_iOS_8_0 || PL__PureLayout_MinBaseSDK_OSX_10_10 */ + + +#pragma mark Install & Remove Constraints /** Activates the constraint. */ - (void)autoInstall { -#if __PureLayout_MinBaseSDK_iOS_8_0 || __PureLayout_MinBaseSDK_OSX_10_10 +#if PL__PureLayout_MinBaseSDK_iOS_8_0 || PL__PureLayout_MinBaseSDK_OSX_10_10 if ([self respondsToSelector:@selector(setActive:)]) { - [ALView al_applyGlobalStateToConstraint:self]; - if ([ALView al_preventAutomaticConstraintInstallation]) { - [[ALView al_currentArrayOfCreatedConstraints] addObject:self]; + [NSLayoutConstraint al_applyGlobalStateToConstraint:self]; + if ([NSLayoutConstraint al_preventAutomaticConstraintInstallation]) { + [[NSLayoutConstraint al_currentArrayOfCreatedConstraints] addObject:self]; } else { self.active = YES; } return; } -#endif /* __PureLayout_MinBaseSDK_iOS_8_0 || __PureLayout_MinBaseSDK_OSX_10_10 */ +#endif /* PL__PureLayout_MinBaseSDK_iOS_8_0 || PL__PureLayout_MinBaseSDK_OSX_10_10 */ NSAssert(self.firstItem || self.secondItem, @"Can't install a constraint with nil firstItem and secondItem."); if (self.firstItem) { @@ -76,12 +318,12 @@ - (void)autoInstall */ - (void)autoRemove { -#if __PureLayout_MinBaseSDK_iOS_8_0 || __PureLayout_MinBaseSDK_OSX_10_10 +#if PL__PureLayout_MinBaseSDK_iOS_8_0 || PL__PureLayout_MinBaseSDK_OSX_10_10 if ([self respondsToSelector:@selector(setActive:)]) { self.active = NO; return; } -#endif /* __PureLayout_MinBaseSDK_iOS_8_0 || __PureLayout_MinBaseSDK_OSX_10_10 */ +#endif /* PL__PureLayout_MinBaseSDK_iOS_8_0 || PL__PureLayout_MinBaseSDK_OSX_10_10 */ if (self.secondItem) { ALView *commonSuperview = [self.firstItem al_commonSuperviewWithView:self.secondItem]; @@ -101,31 +343,27 @@ - (void)autoRemove } -#pragma mark Identify Constraints - -#if __PureLayout_MinBaseSDK_iOS_8_0 || __PureLayout_MinBaseSDK_OSX_10_10 +#pragma mark Internal Methods /** - Sets the string as the identifier for this constraint. Available in iOS 7.0 and OS X 10.9 and later. - The identifier will be printed along with the constraint's description. - This is helpful to document a constraint's purpose and aid in debugging. + Applies the global constraint priority and identifier to the given constraint. + This should be done before installing all constraints. - @param identifier A string used to identify this constraint. - @return This constraint. + @param constraint The constraint to set the global priority and identifier on. */ -- (instancetype)autoIdentify:(NSString *)identifier ++ (void)al_applyGlobalStateToConstraint:(NSLayoutConstraint *)constraint { - if ([self respondsToSelector:@selector(setIdentifier:)]) { - self.identifier = identifier; + if ([NSLayoutConstraint al_isExecutingPriorityConstraintsBlock]) { + constraint.priority = [NSLayoutConstraint al_currentGlobalConstraintPriority]; } - return self; +#if PL__PureLayout_MinBaseSDK_iOS_8_0 || PL__PureLayout_MinBaseSDK_OSX_10_10 + NSString *globalConstraintIdentifier = [NSLayoutConstraint al_currentGlobalConstraintIdentifier]; + if (globalConstraintIdentifier) { + [constraint autoIdentify:globalConstraintIdentifier]; + } +#endif /* PL__PureLayout_MinBaseSDK_iOS_8_0 || PL__PureLayout_MinBaseSDK_OSX_10_10 */ } -#endif /* __PureLayout_MinBaseSDK_iOS_8_0 || __PureLayout_MinBaseSDK_OSX_10_10 */ - - -#pragma mark Internal Methods - /** Returns the corresponding NSLayoutAttribute for the given ALAttribute. @@ -135,77 +373,77 @@ + (NSLayoutAttribute)al_layoutAttributeForAttribute:(ALAttribute)attribute { NSLayoutAttribute layoutAttribute = NSLayoutAttributeNotAnAttribute; switch (attribute) { - case ALEdgeLeft: + case ALAttributeLeft: layoutAttribute = NSLayoutAttributeLeft; break; - case ALEdgeRight: + case ALAttributeRight: layoutAttribute = NSLayoutAttributeRight; break; - case ALEdgeTop: + case ALAttributeTop: layoutAttribute = NSLayoutAttributeTop; break; - case ALEdgeBottom: + case ALAttributeBottom: layoutAttribute = NSLayoutAttributeBottom; break; - case ALEdgeLeading: + case ALAttributeLeading: layoutAttribute = NSLayoutAttributeLeading; break; - case ALEdgeTrailing: + case ALAttributeTrailing: layoutAttribute = NSLayoutAttributeTrailing; break; - case ALDimensionWidth: + case ALAttributeWidth: layoutAttribute = NSLayoutAttributeWidth; break; - case ALDimensionHeight: + case ALAttributeHeight: layoutAttribute = NSLayoutAttributeHeight; break; - case ALAxisVertical: + case ALAttributeVertical: layoutAttribute = NSLayoutAttributeCenterX; break; - case ALAxisHorizontal: + case ALAttributeHorizontal: layoutAttribute = NSLayoutAttributeCenterY; break; - case ALAxisBaseline: // same value as ALAxisLastBaseline + case ALAttributeBaseline: // same value as ALAxisLastBaseline layoutAttribute = NSLayoutAttributeBaseline; break; -#if __PureLayout_MinBaseSDK_iOS_8_0 - case ALAxisFirstBaseline: - NSAssert(__PureLayout_MinSysVer_iOS_8_0, @"ALAxisFirstBaseline is only supported on iOS 8.0 or higher."); +#if PL__PureLayout_MinBaseSDK_iOS_8_0 + case ALAttributeFirstBaseline: + NSAssert(PL__PureLayout_MinSysVer_iOS_8_0, @"ALAxisFirstBaseline is only supported on iOS 8.0 or higher."); layoutAttribute = NSLayoutAttributeFirstBaseline; break; - case ALMarginLeft: - NSAssert(__PureLayout_MinSysVer_iOS_8_0, @"ALEdgeLeftMargin is only supported on iOS 8.0 or higher."); + case ALAttributeMarginLeft: + NSAssert(PL__PureLayout_MinSysVer_iOS_8_0, @"ALEdgeLeftMargin is only supported on iOS 8.0 or higher."); layoutAttribute = NSLayoutAttributeLeftMargin; break; - case ALMarginRight: - NSAssert(__PureLayout_MinSysVer_iOS_8_0, @"ALEdgeRightMargin is only supported on iOS 8.0 or higher."); + case ALAttributeMarginRight: + NSAssert(PL__PureLayout_MinSysVer_iOS_8_0, @"ALEdgeRightMargin is only supported on iOS 8.0 or higher."); layoutAttribute = NSLayoutAttributeRightMargin; break; - case ALMarginTop: - NSAssert(__PureLayout_MinSysVer_iOS_8_0, @"ALEdgeTopMargin is only supported on iOS 8.0 or higher."); + case ALAttributeMarginTop: + NSAssert(PL__PureLayout_MinSysVer_iOS_8_0, @"ALEdgeTopMargin is only supported on iOS 8.0 or higher."); layoutAttribute = NSLayoutAttributeTopMargin; break; - case ALMarginBottom: - NSAssert(__PureLayout_MinSysVer_iOS_8_0, @"ALEdgeBottomMargin is only supported on iOS 8.0 or higher."); + case ALAttributeMarginBottom: + NSAssert(PL__PureLayout_MinSysVer_iOS_8_0, @"ALEdgeBottomMargin is only supported on iOS 8.0 or higher."); layoutAttribute = NSLayoutAttributeBottomMargin; break; - case ALMarginLeading: - NSAssert(__PureLayout_MinSysVer_iOS_8_0, @"ALEdgeLeadingMargin is only supported on iOS 8.0 or higher."); + case ALAttributeMarginLeading: + NSAssert(PL__PureLayout_MinSysVer_iOS_8_0, @"ALEdgeLeadingMargin is only supported on iOS 8.0 or higher."); layoutAttribute = NSLayoutAttributeLeadingMargin; break; - case ALMarginTrailing: - NSAssert(__PureLayout_MinSysVer_iOS_8_0, @"ALEdgeTrailingMargin is only supported on iOS 8.0 or higher."); + case ALAttributeMarginTrailing: + NSAssert(PL__PureLayout_MinSysVer_iOS_8_0, @"ALEdgeTrailingMargin is only supported on iOS 8.0 or higher."); layoutAttribute = NSLayoutAttributeTrailingMargin; break; - case ALMarginAxisVertical: - NSAssert(__PureLayout_MinSysVer_iOS_8_0, @"ALAxisVerticalMargin is only supported on iOS 8.0 or higher."); + case ALAttributeMarginAxisVertical: + NSAssert(PL__PureLayout_MinSysVer_iOS_8_0, @"ALAxisVerticalMargin is only supported on iOS 8.0 or higher."); layoutAttribute = NSLayoutAttributeCenterXWithinMargins; break; - case ALMarginAxisHorizontal: - NSAssert(__PureLayout_MinSysVer_iOS_8_0, @"ALAxisHorizontalMargin is only supported on iOS 8.0 or higher."); + case ALAttributeMarginAxisHorizontal: + NSAssert(PL__PureLayout_MinSysVer_iOS_8_0, @"ALAxisHorizontalMargin is only supported on iOS 8.0 or higher."); layoutAttribute = NSLayoutAttributeCenterYWithinMargins; break; -#endif /* __PureLayout_MinBaseSDK_iOS_8_0 */ +#endif /* PL__PureLayout_MinBaseSDK_iOS_8_0 */ default: NSAssert(nil, @"Not a valid ALAttribute."); break; @@ -227,20 +465,20 @@ + (ALLayoutConstraintAxis)al_constraintAxisForAxis:(ALAxis)axis break; case ALAxisHorizontal: case ALAxisBaseline: // same value as ALAxisLastBaseline -#if __PureLayout_MinBaseSDK_iOS_8_0 +#if PL__PureLayout_MinBaseSDK_iOS_8_0 case ALAxisFirstBaseline: -#endif /* __PureLayout_MinBaseSDK_iOS_8_0 */ +#endif /* PL__PureLayout_MinBaseSDK_iOS_8_0 */ constraintAxis = ALLayoutConstraintAxisHorizontal; break; default: NSAssert(nil, @"Not a valid ALAxis."); - constraintAxis = ALLayoutConstraintAxisHorizontal; // default to a random value to satisfy the compiler + constraintAxis = ALLayoutConstraintAxisHorizontal; // default to an arbitrary value to satisfy the compiler break; } return constraintAxis; } -#if __PureLayout_MinBaseSDK_iOS_8_0 +#if PL__PureLayout_MinBaseSDK_iOS_8_0 /** Returns the corresponding margin for the given edge. @@ -250,7 +488,7 @@ + (ALLayoutConstraintAxis)al_constraintAxisForAxis:(ALAxis)axis */ + (ALMargin)al_marginForEdge:(ALEdge)edge { - NSAssert(__PureLayout_MinSysVer_iOS_8_0, @"Margin attributes are only supported on iOS 8.0 or higher."); + NSAssert(PL__PureLayout_MinSysVer_iOS_8_0, @"Margin attributes are only supported on iOS 8.0 or higher."); ALMargin margin; switch (edge) { case ALEdgeLeft: @@ -273,7 +511,7 @@ + (ALMargin)al_marginForEdge:(ALEdge)edge break; default: NSAssert(nil, @"Not a valid ALEdge."); - margin = ALMarginLeft; // default to a random value to satisfy the compiler + margin = ALMarginLeft; // default to an arbitrary value to satisfy the compiler break; } return margin; @@ -287,7 +525,7 @@ + (ALMargin)al_marginForEdge:(ALEdge)edge */ + (ALMarginAxis)al_marginAxisForAxis:(ALAxis)axis { - NSAssert(__PureLayout_MinSysVer_iOS_8_0, @"Margin attributes are only supported on iOS 8.0 or higher."); + NSAssert(PL__PureLayout_MinSysVer_iOS_8_0, @"Margin attributes are only supported on iOS 8.0 or higher."); ALMarginAxis marginAxis; switch (axis) { case ALAxisVertical: @@ -299,16 +537,16 @@ + (ALMarginAxis)al_marginAxisForAxis:(ALAxis)axis case ALAxisBaseline: case ALAxisFirstBaseline: NSAssert(nil, @"The baseline axis attributes do not have corresponding margin axis attributes."); - marginAxis = ALMarginAxisVertical; // default to a random value to satisfy the compiler + marginAxis = ALMarginAxisVertical; // default to an arbitrary value to satisfy the compiler break; default: NSAssert(nil, @"Not a valid ALAxis."); - marginAxis = ALMarginAxisVertical; // default to a random value to satisfy the compiler + marginAxis = ALMarginAxisVertical; // default to an arbitrary value to satisfy the compiler break; } return marginAxis; } -#endif /* __PureLayout_MinBaseSDK_iOS_8_0 */ +#endif /* PL__PureLayout_MinBaseSDK_iOS_8_0 */ @end diff --git a/PureLayout/PureLayout/PureLayout+Internal.h b/PureLayout/PureLayout/PureLayout+Internal.h index 28fbfcf..15c2eeb 100644 --- a/PureLayout/PureLayout/PureLayout+Internal.h +++ b/PureLayout/PureLayout/PureLayout+Internal.h @@ -1,7 +1,6 @@ // // PureLayout+Internal.h -// v2.0.5 -// https://github.com/smileyborg/PureLayout +// https://github.com/PureLayout/PureLayout // // Copyright (c) 2014-2015 Tyler Fox // @@ -28,9 +27,15 @@ #import "PureLayoutDefines.h" + +// Using generics with NSMutableArray is so common in the internal implementation of PureLayout that it gets a dedicated preprocessor macro for better readability. +#define PL__NSMutableArray_of(type) PL__GENERICS(NSMutableArray, type) + +PL__ASSUME_NONNULL_BEGIN + /** A constant that represents the smallest valid positive value for the multiplier of a constraint, since a value of 0 will cause the second item to be lost in the internal auto layout engine. */ -static const CGFloat kMULTIPLIER_MIN_VALUE = 0.00001; // very small floating point numbers (e.g. CGFLOAT_MIN) can cause problems +static const CGFloat kMULTIPLIER_MIN_VALUE = (CGFloat)0.00001; // very small floating point numbers (e.g. CGFLOAT_MIN) can cause problems /** @@ -38,12 +43,6 @@ static const CGFloat kMULTIPLIER_MIN_VALUE = 0.00001; // very small floating poi */ @interface ALView (PureLayoutInternal) -+ (BOOL)al_preventAutomaticConstraintInstallation; -+ (NSMutableArray *)al_currentArrayOfCreatedConstraints; -+ (BOOL)al_isExecutingPriorityConstraintsBlock; -+ (ALLayoutPriority)al_currentGlobalConstraintPriority; -+ (NSString *)al_currentGlobalConstraintIdentifier; -+ (void)al_applyGlobalStateToConstraint:(NSLayoutConstraint *)constraint; - (void)al_addConstraint:(NSLayoutConstraint *)constraint; - (ALView *)al_commonSuperviewWithView:(ALView *)otherView; - (NSLayoutConstraint *)al_alignAttribute:(ALAttribute)attribute toView:(ALView *)otherView forAxis:(ALAxis)axis; @@ -58,7 +57,7 @@ static const CGFloat kMULTIPLIER_MIN_VALUE = 0.00001; // very small floating poi - (ALView *)al_commonSuperviewOfViews; - (BOOL)al_containsMinimumNumberOfViews:(NSUInteger)minimumNumberOfViews; -- (NSArray *)al_copyViewsOnly; +- (PL__NSArray_of(ALView *) *)al_copyViewsOnly; @end @@ -68,11 +67,21 @@ static const CGFloat kMULTIPLIER_MIN_VALUE = 0.00001; // very small floating poi */ @interface NSLayoutConstraint (PureLayoutInternal) ++ (BOOL)al_preventAutomaticConstraintInstallation; ++ (PL__NSMutableArray_of(NSLayoutConstraint *) *)al_currentArrayOfCreatedConstraints; ++ (BOOL)al_isExecutingPriorityConstraintsBlock; ++ (ALLayoutPriority)al_currentGlobalConstraintPriority; +#if PL__PureLayout_MinBaseSDK_iOS_8_0 || PL__PureLayout_MinBaseSDK_OSX_10_10 ++ (nullable NSString *)al_currentGlobalConstraintIdentifier; +#endif /* PL__PureLayout_MinBaseSDK_iOS_8_0 || PL__PureLayout_MinBaseSDK_OSX_10_10 */ ++ (void)al_applyGlobalStateToConstraint:(NSLayoutConstraint *)constraint; + (NSLayoutAttribute)al_layoutAttributeForAttribute:(ALAttribute)attribute; + (ALLayoutConstraintAxis)al_constraintAxisForAxis:(ALAxis)axis; -#if __PureLayout_MinBaseSDK_iOS_8_0 +#if PL__PureLayout_MinBaseSDK_iOS_8_0 + (ALMargin)al_marginForEdge:(ALEdge)edge; + (ALMarginAxis)al_marginAxisForAxis:(ALAxis)axis; -#endif /* __PureLayout_MinBaseSDK_iOS_8_0 */ +#endif /* PL__PureLayout_MinBaseSDK_iOS_8_0 */ @end + +PL__ASSUME_NONNULL_END diff --git a/PureLayout/PureLayout/ALView+PureLayout.h b/PureLayout/PureLayout/include/ALView+PureLayout.h similarity index 67% rename from PureLayout/PureLayout/ALView+PureLayout.h rename to PureLayout/PureLayout/include/ALView+PureLayout.h index ae74922..ced5859 100755 --- a/PureLayout/PureLayout/ALView+PureLayout.h +++ b/PureLayout/PureLayout/include/ALView+PureLayout.h @@ -1,7 +1,6 @@ // // ALView+PureLayout.h -// v2.0.5 -// https://github.com/smileyborg/PureLayout +// https://github.com/PureLayout/PureLayout // // Copyright (c) 2012 Richard Turton // Copyright (c) 2013-2015 Tyler Fox @@ -30,7 +29,9 @@ #import "PureLayoutDefines.h" -#pragma mark - ALView+PureLayout +PL__ASSUME_NONNULL_BEGIN + +#pragma mark ALView+PureLayout /** A category on UIView/NSView that provides a simple yet powerful interface for creating Auto Layout constraints. @@ -46,50 +47,51 @@ /** Initializes and returns a new view that does not convert the autoresizing mask into constraints. */ - (instancetype)initForAutoLayout; +/** Configures an existing view to not convert the autoresizing mask into constraints and returns the view. */ +- (instancetype)configureForAutoLayout; -#pragma mark Create Constraints Without Installing - -/** Prevents constraints created in the given constraints block from being automatically installed (activated). - The constraints created from calls to the PureLayout API in the block are returned in a single array. */ -+ (NSArray *)autoCreateConstraintsWithoutInstalling:(ALConstraintsBlock)block; +#pragma mark Center & Align in Superview -#pragma mark Set Priority For Constraints - -/** Sets the constraint priority to the given value for all constraints created using the PureLayout API within the given constraints block. - NOTE: This method will have no effect (and will NOT set the priority) on constraints created or added without using the PureLayout API! */ -+ (void)autoSetPriority:(ALLayoutPriority)priority forConstraints:(ALConstraintsBlock)block; +/** Centers the view in its superview. */ +- (PL__NSArray_of(NSLayoutConstraint *) *)autoCenterInSuperview; +/** Aligns the view to the same axis of its superview. */ +- (NSLayoutConstraint *)autoAlignAxisToSuperviewAxis:(ALAxis)axis; -#pragma mark Set Identifier For Constraints +#if PL__PureLayout_MinBaseSDK_iOS_8_0 -#if __PureLayout_MinBaseSDK_iOS_8_0 +/** Centers the view in its superview's margins. Available in iOS 8.0 and later. */ +- (PL__NSArray_of(NSLayoutConstraint *) *)autoCenterInSuperviewMargins; -/** Sets the identifier for all constraints created using the PureLayout API within the given constraints block. - NOTE: This method will have no effect (and will NOT set the identifier) on constraints created or added without using the PureLayout API! */ -+ (void)autoSetIdentifier:(NSString *)identifier forConstraints:(ALConstraintsBlock)block; +/** Aligns the view to the corresponding margin axis of its superview. Available in iOS 8.0 and later. */ +- (NSLayoutConstraint *)autoAlignAxisToSuperviewMarginAxis:(ALAxis)axis; -#endif /* __PureLayout_MinBaseSDK_iOS_8_0 */ +#endif /* PL__PureLayout_MinBaseSDK_iOS_8_0 */ +#if TARGET_OS_IPHONE -#pragma mark Center & Align in Superview +#pragma mark Pin Edges to SafeArea -/** Centers the view in its superview. */ -- (NSArray *)autoCenterInSuperview; +/** Pins the given edge of the view to the same edge of its superview anchor/edge. */ +- (NSLayoutConstraint *)API_AVAILABLE(ios(9.0), tvos(9.0))autoPinEdgeToSuperviewSafeArea:(ALEdge)edge; -/** Aligns the view to the same axis of its superview. */ -- (NSLayoutConstraint *)autoAlignAxisToSuperviewAxis:(ALAxis)axis; +/** Pins the given edge of the view to the same edge of its superview anchor/edge with an inset. */ +- (NSLayoutConstraint *)API_AVAILABLE(ios(9.0), tvos(9.0))autoPinEdgeToSuperviewSafeArea:(ALEdge)edge withInset:(CGFloat)inset; -#if __PureLayout_MinBaseSDK_iOS_8_0 +/** Pins the given edge of the view to the same edge of its superview anchor/edge with an inset as a maximum or minimum. */ +- (NSLayoutConstraint *)API_AVAILABLE(ios(9.0), tvos(9.0))autoPinEdgeToSuperviewSafeArea:(ALEdge)edge withInset:(CGFloat)inset relation:(NSLayoutRelation)relation; -/** Centers the view in its superview's margins. Available in iOS 8.0 and later. */ -- (NSArray *)autoCenterInSuperviewMargins; +/** Pins the edges of the view to the edges of its superview anchors/edge. */ +- (PL__NSArray_of(NSLayoutConstraint *) *)API_AVAILABLE(ios(9.0), tvos(9.0))autoPinEdgesToSuperviewSafeArea; -/** Aligns the view to the corresponding margin axis of its superview. Available in iOS 8.0 and later. */ -- (NSLayoutConstraint *)autoAlignAxisToSuperviewMarginAxis:(ALAxis)axis; +/** Pins the edges of the view to the edges of its superview anchors/edges with the given edge insets. */ +- (PL__NSArray_of(NSLayoutConstraint *) *)API_AVAILABLE(ios(9.0), tvos(9.0))autoPinEdgesToSuperviewSafeAreaWithInsets:(ALEdgeInsets)insets; -#endif /* __PureLayout_MinBaseSDK_iOS_8_0 */ +/** Pins 3 of the 4 edges of the view to the edges of its superview anchor/edge with the given edge insets, excluding one edge. */ +- (PL__NSArray_of(NSLayoutConstraint *) *)API_AVAILABLE(ios(9.0), tvos(9.0))autoPinEdgesToSuperviewSafeAreaWithInsets:(ALEdgeInsets)insets excludingEdge:(ALEdge)edge; +#endif /* TARGET_OS_IPHONE */ #pragma mark Pin Edges to Superview @@ -102,27 +104,36 @@ /** Pins the given edge of the view to the same edge of its superview with an inset as a maximum or minimum. */ - (NSLayoutConstraint *)autoPinEdgeToSuperviewEdge:(ALEdge)edge withInset:(CGFloat)inset relation:(NSLayoutRelation)relation; +/** Pins the edges of the view to the edges of its superview. */ +- (PL__NSArray_of(NSLayoutConstraint *) *)autoPinEdgesToSuperviewEdges; + /** Pins the edges of the view to the edges of its superview with the given edge insets. */ -- (NSArray *)autoPinEdgesToSuperviewEdgesWithInsets:(ALEdgeInsets)insets; +- (PL__NSArray_of(NSLayoutConstraint *) *)autoPinEdgesToSuperviewEdgesWithInsets:(ALEdgeInsets)insets; /** Pins 3 of the 4 edges of the view to the edges of its superview with the given edge insets, excluding one edge. */ -- (NSArray *)autoPinEdgesToSuperviewEdgesWithInsets:(ALEdgeInsets)insets excludingEdge:(ALEdge)edge; +- (PL__NSArray_of(NSLayoutConstraint *) *)autoPinEdgesToSuperviewEdgesWithInsets:(ALEdgeInsets)insets excludingEdge:(ALEdge)edge; -#if __PureLayout_MinBaseSDK_iOS_8_0 +#if PL__PureLayout_MinBaseSDK_iOS_8_0 /** Pins the given edge of the view to the corresponding margin of its superview. Available in iOS 8.0 and later. */ - (NSLayoutConstraint *)autoPinEdgeToSuperviewMargin:(ALEdge)edge; +/** Pins the given edge of a view to the corresponding margin of its superview with an inset.*/ +- (NSLayoutConstraint *)autoPinEdgeToSuperviewMargin:(ALEdge)edge withInset:(CGFloat)inset; + /** Pins the given edge of the view to the corresponding margin of its superview as a maximum or minimum. Available in iOS 8.0 and later. */ - (NSLayoutConstraint *)autoPinEdgeToSuperviewMargin:(ALEdge)edge relation:(NSLayoutRelation)relation; /** Pins the edges of the view to the margins of its superview. Available in iOS 8.0 and later. */ -- (NSArray *)autoPinEdgesToSuperviewMargins; +- (PL__NSArray_of(NSLayoutConstraint *) *)autoPinEdgesToSuperviewMargins; + +/** Pins the edges of the view to the margins of its superview with the given edge insets. Available in iOS 8.0 and later.*/ +- (PL__NSArray_of(NSLayoutConstraint *) *)autoPinEdgesToSuperviewMarginsWithInsets:(ALEdgeInsets)insets; /** Pins 3 of the 4 edges of the view to the margins of its superview excluding one edge. Available in iOS 8.0 and later. */ -- (NSArray *)autoPinEdgesToSuperviewMarginsExcludingEdge:(ALEdge)edge; +- (PL__NSArray_of(NSLayoutConstraint *) *)autoPinEdgesToSuperviewMarginsExcludingEdge:(ALEdge)edge; -#endif /* __PureLayout_MinBaseSDK_iOS_8_0 */ +#endif /* PL__PureLayout_MinBaseSDK_iOS_8_0 */ #pragma mark Pin Edges @@ -145,6 +156,9 @@ /** Aligns an axis of the view to the same axis of another view with an offset. */ - (NSLayoutConstraint *)autoAlignAxis:(ALAxis)axis toSameAxisOfView:(ALView *)otherView withOffset:(CGFloat)offset; +/** Aligns an axis of the view to the same axis of another view with a multiplier. */ +- (NSLayoutConstraint *)autoAlignAxis:(ALAxis)axis toSameAxisOfView:(ALView *)otherView withMultiplier:(CGFloat)multiplier; + #pragma mark Match Dimensions @@ -167,7 +181,7 @@ #pragma mark Set Dimensions /** Sets the view to a specific size. */ -- (NSArray *)autoSetDimensionsToSize:(CGSize)size; +- (PL__NSArray_of(NSLayoutConstraint *) *)autoSetDimensionsToSize:(CGSize)size; /** Sets the given dimension of the view to a specific size. */ - (NSLayoutConstraint *)autoSetDimension:(ALDimension)dimension toSize:(CGFloat)size; @@ -179,11 +193,11 @@ #pragma mark Set Content Compression Resistance & Hugging /** Sets the priority of content compression resistance for an axis. - NOTE: This method must be called from within the block passed into the method +[UIView autoSetPriority:forConstraints:] */ + NOTE: This method must be called from within the block passed into the method +[NSLayoutConstraint autoSetPriority:forConstraints:] */ - (void)autoSetContentCompressionResistancePriorityForAxis:(ALAxis)axis; /** Sets the priority of content hugging for an axis. - NOTE: This method must be called from within the block passed into the method +[UIView autoSetPriority:forConstraints:] */ + NOTE: This method must be called from within the block passed into the method +[NSLayoutConstraint autoSetPriority:forConstraints:] */ - (void)autoSetContentHuggingPriorityForAxis:(ALAxis)axis; @@ -208,6 +222,7 @@ #pragma mark Pin to Layout Guides (iOS only) #if TARGET_OS_IPHONE +#if __IPHONE_OS_VERSION_MIN_REQUIRED < __IPHONE_11_0 // Top and bottom layout guides were deprecated in iOS 11 /** Pins the top edge of the view to the top layout guide of the given view controller with an inset. Available on iOS only. */ - (NSLayoutConstraint *)autoPinToTopLayoutGuideOfViewController:(UIViewController *)viewController withInset:(CGFloat)inset; @@ -221,33 +236,9 @@ /** Pins the bottom edge of the view to the bottom layout guide of the given view controller with an inset as a maximum or minimum. Available on iOS only. */ - (NSLayoutConstraint *)autoPinToBottomLayoutGuideOfViewController:(UIViewController *)viewController withInset:(CGFloat)inset relation:(NSLayoutRelation)relation; +#endif /* __IPHONE_OS_VERSION_MIN_REQUIRED */ #endif /* TARGET_OS_IPHONE */ - -#pragma mark Deprecated Methods - -/** DEPRECATED as of PureLayout v2.0.0. Retain a reference to and remove specific constraints instead, or recreate the view(s) entirely to remove all constraints. - Removes all explicit constraints that affect the view. - WARNING: Apple's constraint solver is not optimized for large-scale constraint removal; you may encounter major performance issues after using this method. - NOTE: This method preserves implicit constraints, such as intrinsic content size constraints, which you usually do not want to remove. */ -- (void)autoRemoveConstraintsAffectingView __attribute__((deprecated)); - -/** DEPRECATED as of PureLayout v2.0.0. Retain a reference to and remove specific constraints instead, or recreate the view(s) entirely to remove all constraints. - Removes all constraints that affect the view, optionally including implicit constraints. - WARNING: Apple's constraint solver is not optimized for large-scale constraint removal; you may encounter major performance issues after using this method. - NOTE: Implicit constraints are auto-generated lower priority constraints, and you usually do not want to remove these. */ -- (void)autoRemoveConstraintsAffectingViewIncludingImplicitConstraints:(BOOL)shouldRemoveImplicitConstraints __attribute__((deprecated)); - -/** DEPRECATED as of PureLayout v2.0.0. Retain a reference to and remove specific constraints instead, or recreate the view(s) entirely to remove all constraints. - Recursively removes all explicit constraints that affect the view and its subviews. - WARNING: Apple's constraint solver is not optimized for large-scale constraint removal; you may encounter major performance issues after using this method. - NOTE: This method preserves implicit constraints, such as intrinsic content size constraints, which you usually do not want to remove. */ -- (void)autoRemoveConstraintsAffectingViewAndSubviews __attribute__((deprecated)); - -/** DEPRECATED as of PureLayout v2.0.0. Retain a reference to and remove specific constraints instead, or recreate the view(s) entirely to remove all constraints. - Recursively removes all constraints from the view and its subviews, optionally including implicit constraints. - WARNING: Apple's constraint solver is not optimized for large-scale constraint removal; you may encounter major performance issues after using this method. - NOTE: Implicit constraints are auto-generated lower priority constraints, and you usually do not want to remove these. */ -- (void)autoRemoveConstraintsAffectingViewAndSubviewsIncludingImplicitConstraints:(BOOL)shouldRemoveImplicitConstraints __attribute__((deprecated)); - @end + +PL__ASSUME_NONNULL_END diff --git a/PureLayout/PureLayout/include/NSArray+PureLayout.h b/PureLayout/PureLayout/include/NSArray+PureLayout.h new file mode 100755 index 0000000..682ef1b --- /dev/null +++ b/PureLayout/PureLayout/include/NSArray+PureLayout.h @@ -0,0 +1,115 @@ +// +// NSArray+PureLayout.h +// https://github.com/PureLayout/PureLayout +// +// Copyright (c) 2012 Richard Turton +// Copyright (c) 2013-2015 Tyler Fox +// +// This code is distributed under the terms and conditions of the MIT license. +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +// + +#import "PureLayoutDefines.h" + + +PL__ASSUME_NONNULL_BEGIN + +#pragma mark NSArray+PureLayout + +/** + A category on NSArray that provides a simple yet powerful interface to: + - Manage an array of Auto Layout constraints + - Apply constraints to an array of views + */ +@interface NSArray (PureLayout) + + +#pragma mark Array of Constraints + +/** Activates the constraints in this array. */ +- (void)autoInstallConstraints; + +/** Deactivates the constraints in this array. */ +- (void)autoRemoveConstraints; + +#if PL__PureLayout_MinBaseSDK_iOS_8_0 || PL__PureLayout_MinBaseSDK_OSX_10_10 + +/** Sets the string as the identifier for the constraints in this array. Available in iOS 7.0 and OS X 10.9 and later. */ +- (instancetype)autoIdentifyConstraints:(NSString *)identifier; + +#endif /* PL__PureLayout_MinBaseSDK_iOS_8_0 || PL__PureLayout_MinBaseSDK_OSX_10_10 */ + + +#pragma mark Array of Views + +/** Aligns views in this array to one another along a given edge. */ +- (PL__NSArray_of(NSLayoutConstraint *) *)autoAlignViewsToEdge:(ALEdge)edge; + +/** Aligns views in this array to one another along a given axis. */ +- (PL__NSArray_of(NSLayoutConstraint *) *)autoAlignViewsToAxis:(ALAxis)axis; + +/** Matches a given dimension of all the views in this array. */ +- (PL__NSArray_of(NSLayoutConstraint *) *)autoMatchViewsDimension:(ALDimension)dimension; + +/** Sets the given dimension of all the views in this array to a given size. */ +- (PL__NSArray_of(NSLayoutConstraint *) *)autoSetViewsDimension:(ALDimension)dimension toSize:(CGFloat)size; + +/** Sets all of the views in this array to a given size. */ +- (PL__NSArray_of(NSLayoutConstraint *) *)autoSetViewsDimensionsToSize:(CGSize)size; + + +/** Distributes the views in this array equally along the selected axis in their superview. + Views will be the same size (variable) in the dimension along the axis and will have spacing (fixed) between them. */ +- (PL__NSArray_of(NSLayoutConstraint *) *)autoDistributeViewsAlongAxis:(ALAxis)axis + alignedTo:(ALAttribute)alignment + withFixedSpacing:(CGFloat)spacing; + +/** Distributes the views in this array equally along the selected axis in their superview. + Views will be the same size (variable) in the dimension along the axis and will have spacing (fixed) between them, with optional insets from the first and last views to their superview. */ +- (PL__NSArray_of(NSLayoutConstraint *) *)autoDistributeViewsAlongAxis:(ALAxis)axis + alignedTo:(ALAttribute)alignment + withFixedSpacing:(CGFloat)spacing + insetSpacing:(BOOL)shouldSpaceInsets; + +/** Distributes the views in this array equally along the selected axis in their superview. + Views will have spacing (fixed) between them, with optional insets from the first and last views to their superview, and optionally constrained to the same size in the dimension along the axis. */ +- (PL__NSArray_of(NSLayoutConstraint *) *)autoDistributeViewsAlongAxis:(ALAxis)axis + alignedTo:(ALAttribute)alignment + withFixedSpacing:(CGFloat)spacing + insetSpacing:(BOOL)shouldSpaceInsets + matchedSizes:(BOOL)shouldMatchSizes; + + +/** Distributes the views in this array equally along the selected axis in their superview. + Views will be the same size (fixed) in the dimension along the axis and will have spacing (variable) between them. */ +- (PL__NSArray_of(NSLayoutConstraint *) *)autoDistributeViewsAlongAxis:(ALAxis)axis + alignedTo:(ALAttribute)alignment + withFixedSize:(CGFloat)size; + +/** Distributes the views in this array equally along the selected axis in their superview. + Views will be the same size (fixed) in the dimension along the axis and will have spacing (variable) between them, with optional insets from the first and last views to their superview. */ +- (PL__NSArray_of(NSLayoutConstraint *) *)autoDistributeViewsAlongAxis:(ALAxis)axis + alignedTo:(ALAttribute)alignment + withFixedSize:(CGFloat)size + insetSpacing:(BOOL)shouldSpaceInsets; + +@end + +PL__ASSUME_NONNULL_END diff --git a/PureLayout/PureLayout/include/NSLayoutConstraint+PureLayout.h b/PureLayout/PureLayout/include/NSLayoutConstraint+PureLayout.h new file mode 100755 index 0000000..ae48ca0 --- /dev/null +++ b/PureLayout/PureLayout/include/NSLayoutConstraint+PureLayout.h @@ -0,0 +1,84 @@ +// +// NSLayoutConstraint+PureLayout.h +// https://github.com/PureLayout/PureLayout +// +// Copyright (c) 2013-2015 Tyler Fox +// +// This code is distributed under the terms and conditions of the MIT license. +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. +// + +#import "PureLayoutDefines.h" + + +PL__ASSUME_NONNULL_BEGIN + +#pragma mark NSLayoutConstraint+PureLayout + +/** + A category on NSLayoutConstraint that allows constraints to be easily installed & removed. + */ +@interface NSLayoutConstraint (PureLayout) + + +#pragma mark Batch Constraint Creation + +/** Creates all of the constraints in the block, then installs (activates) them all at once. + All constraints created from calls to the PureLayout API in the block are returned in a single array. + This may be more efficient than installing (activating) each constraint one-by-one. */ ++ (PL__NSArray_of(NSLayoutConstraint *) *)autoCreateAndInstallConstraints:(__attribute__((noescape)) ALConstraintsBlock)block; + +/** Creates all of the constraints in the block but prevents them from being automatically installed (activated). + All constraints created from calls to the PureLayout API in the block are returned in a single array. */ ++ (PL__NSArray_of(NSLayoutConstraint *) *)autoCreateConstraintsWithoutInstalling:(__attribute__((noescape)) ALConstraintsBlock)block; + + +#pragma mark Set Priority For Constraints + +/** Sets the constraint priority to the given value for all constraints created using the PureLayout API within the given constraints block. + NOTE: This method will have no effect (and will NOT set the priority) on constraints created or added without using the PureLayout API! */ ++ (void)autoSetPriority:(ALLayoutPriority)priority forConstraints:(__attribute__((noescape)) ALConstraintsBlock)block; + + +#pragma mark Identify Constraints + +#if PL__PureLayout_MinBaseSDK_iOS_8_0 || PL__PureLayout_MinBaseSDK_OSX_10_10 + +/** Sets the identifier for all constraints created using the PureLayout API within the given constraints block. + NOTE: This method will have no effect (and will NOT set the identifier) on constraints created or added without using the PureLayout API! */ ++ (void)autoSetIdentifier:(NSString *)identifier forConstraints:(__attribute__((noescape)) ALConstraintsBlock)block; + +/** Sets the string as the identifier for this constraint. Available in iOS 7.0 and OS X 10.9 and later. */ +- (instancetype)autoIdentify:(NSString *)identifier; + +#endif /* PL__PureLayout_MinBaseSDK_iOS_8_0 || PL__PureLayout_MinBaseSDK_OSX_10_10 */ + + +#pragma mark Install & Remove Constraints + +/** Activates the the constraint. */ +- (void)autoInstall; + +/** Deactivates the constraint. */ +- (void)autoRemove; + +@end + +PL__ASSUME_NONNULL_END diff --git a/PureLayout/PureLayout/PureLayout.h b/PureLayout/PureLayout/include/PureLayout.h similarity index 83% rename from PureLayout/PureLayout/PureLayout.h rename to PureLayout/PureLayout/include/PureLayout.h index 8c47775..ab615d3 100755 --- a/PureLayout/PureLayout/PureLayout.h +++ b/PureLayout/PureLayout/include/PureLayout.h @@ -1,7 +1,6 @@ // // PureLayout.h -// v2.0.5 -// https://github.com/smileyborg/PureLayout +// https://github.com/PureLayout/PureLayout // // Copyright (c) 2014-2015 Tyler Fox // @@ -29,6 +28,14 @@ #ifndef PureLayout_h #define PureLayout_h +#import + +//! Project version number for PureLayout. +FOUNDATION_EXPORT double PureLayoutVersionNumber; + +//! Project version string for PureLayout. +FOUNDATION_EXPORT const unsigned char PureLayoutVersionString[]; + #import "ALView+PureLayout.h" #import "NSArray+PureLayout.h" #import "NSLayoutConstraint+PureLayout.h" diff --git a/PureLayout/PureLayout/PureLayoutDefines.h b/PureLayout/PureLayout/include/PureLayoutDefines.h similarity index 72% rename from PureLayout/PureLayout/PureLayoutDefines.h rename to PureLayout/PureLayout/include/PureLayoutDefines.h index 2f10152..56bd197 100755 --- a/PureLayout/PureLayout/PureLayoutDefines.h +++ b/PureLayout/PureLayout/include/PureLayoutDefines.h @@ -1,7 +1,6 @@ // // PureLayoutDefines.h -// v2.0.5 -// https://github.com/smileyborg/PureLayout +// https://github.com/PureLayout/PureLayout // // Copyright (c) 2014-2015 Tyler Fox // @@ -30,17 +29,42 @@ #define PureLayoutDefines_h #import +// check the code in - +// Define some preprocessor macros to check for a minimum Base SDK. These are used to prevent compile-time errors in older versions of Xcode. +#define PL__PureLayout_MinBaseSDK_iOS_8_0 (TARGET_OS_IPHONE && __IPHONE_OS_VERSION_MAX_ALLOWED > __IPHONE_7_1) +#define PL__PureLayout_MinBaseSDK_iOS_9_0 (TARGET_OS_IPHONE && __IPHONE_OS_VERSION_MAX_ALLOWED > __IPHONE_8_4) +#define PL__PureLayout_MinBaseSDK_iOS_11_0 (TARGET_OS_IPHONE && __IPHONE_OS_VERSION_MAX_ALLOWED > __IPHONE_10_3) +#define PL__PureLayout_MinBaseSDK_OSX_10_10 (!TARGET_OS_IPHONE && __MAC_OS_X_VERSION_MAX_ALLOWED > __MAC_10_9) + +// Define some preprocessor macros to check for a minimum System Version. These are used to prevent runtime crashes on older versions of iOS/OS X. +#define PL__PureLayout_MinSysVer_iOS_7_0 (TARGET_OS_IPHONE && floor(NSFoundationVersionNumber) > NSFoundationVersionNumber_iOS_6_1) +#define PL__PureLayout_MinSysVer_iOS_8_0 (TARGET_OS_IPHONE && floor(NSFoundationVersionNumber) > NSFoundationVersionNumber_iOS_7_1) +#define PL__PureLayout_MinSysVer_iOS_9_0 (TARGET_OS_IPHONE && floor(NSFoundationVersionNumber) > NSFoundationVersionNumber_iOS_8_x_Max) +#define PL__PureLayout_MinSysVer_iOS_10_0 (TARGET_OS_IPHONE && floor(NSFoundationVersionNumber) > NSFoundationVersionNumber_iOS_9_x_Max) +#define PL__PureLayout_MinSysVer_OSX_10_9 (!TARGET_OS_IPHONE && floor(NSFoundationVersionNumber) > NSFoundationVersionNumber10_8_4) + +// Define some preprocessor macros that allow nullability annotations to be adopted in a backwards-compatible manner. +#if __has_feature(nullability) +# define PL__ASSUME_NONNULL_BEGIN NS_ASSUME_NONNULL_BEGIN +# define PL__ASSUME_NONNULL_END NS_ASSUME_NONNULL_END +#else +# define PL__ASSUME_NONNULL_BEGIN +# define PL__ASSUME_NONNULL_END +#endif -#define __PureLayout_MinBaseSDK_iOS_8_0 TARGET_OS_IPHONE && __IPHONE_OS_VERSION_MAX_ALLOWED > __IPHONE_7_1 -#define __PureLayout_MinSysVer_iOS_7_0 TARGET_OS_IPHONE && floor(NSFoundationVersionNumber) > NSFoundationVersionNumber_iOS_6_1 -#define __PureLayout_MinSysVer_iOS_8_0 TARGET_OS_IPHONE && floor(NSFoundationVersionNumber) > NSFoundationVersionNumber_iOS_7_1 +// Define some preprocessor macros that allow generics to be adopted in a backwards-compatible manner. +#if __has_feature(objc_generics) +# define PL__GENERICS(class, ...) class<__VA_ARGS__> +#else +# define PL__GENERICS(class, ...) class +#endif -#define __PureLayout_MinBaseSDK_OSX_10_10 !TARGET_OS_IPHONE && __MAC_OS_X_VERSION_MAX_ALLOWED > __MAC_10_9 -#define __PureLayout_MinSysVer_OSX_10_9 !TARGET_OS_IPHONE && floor(NSFoundationVersionNumber) > NSFoundationVersionNumber10_8_4 +// Using generics with NSArray is so common in PureLayout that it gets a dedicated preprocessor macro for better readability. +#define PL__NSArray_of(type) PL__GENERICS(NSArray, type) -#if TARGET_OS_IPHONE +// Define generic AL-prefixed macros for the types/constants/etc that have slight naming variations across iOS and OS X, which allows the same code to be platform-independent. +#if TARGET_OS_IPHONE || TARGET_OS_TV # import - # define ALView UIView # define ALEdgeInsets UIEdgeInsets # define ALEdgeInsetsZero UIEdgeInsetsZero @@ -59,7 +83,6 @@ # define ALLayoutPriorityFittingSizeCompression ALLayoutPriorityFittingSizeLevel #else # import - # define ALView NSView # define ALEdgeInsets NSEdgeInsets # define ALEdgeInsetsZero NSEdgeInsetsMake(0, 0, 0, 0) @@ -82,7 +105,7 @@ #pragma mark PureLayout Attributes /** Constants that represent edges of a view. */ -typedef NS_ENUM(NSInteger, ALEdge) { +typedef NS_CLOSED_ENUM(NSInteger, ALEdge) { /** The left edge of the view. */ ALEdgeLeft = NSLayoutAttributeLeft, /** The right edge of the view. */ @@ -98,7 +121,7 @@ typedef NS_ENUM(NSInteger, ALEdge) { }; /** Constants that represent dimensions of a view. */ -typedef NS_ENUM(NSInteger, ALDimension) { +typedef NS_CLOSED_ENUM(NSInteger, ALDimension) { /** The width of the view. */ ALDimensionWidth = NSLayoutAttributeWidth, /** The height of the view. */ @@ -106,26 +129,26 @@ typedef NS_ENUM(NSInteger, ALDimension) { }; /** Constants that represent axes of a view. */ -typedef NS_ENUM(NSInteger, ALAxis) { - /** A vertical line through the middle of the view's left and right edges. */ +typedef NS_CLOSED_ENUM(NSInteger, ALAxis) { + /** A vertical line equidistant from the view's left and right edges. */ ALAxisVertical = NSLayoutAttributeCenterX, - /** A horizontal line through the middle of the view's top and bottom edges. */ + /** A horizontal line equidistant from the view's top and bottom edges. */ ALAxisHorizontal = NSLayoutAttributeCenterY, /** A horizontal line at the baseline of the last line of text in the view. (For views that do not draw text, will be equivalent to ALEdgeBottom.) Same as ALAxisLastBaseline. */ ALAxisBaseline = NSLayoutAttributeBaseline, /** A horizontal line at the baseline of the last line of text in the view. (For views that do not draw text, will be equivalent to ALEdgeBottom.) */ ALAxisLastBaseline = ALAxisBaseline, - #if __PureLayout_MinBaseSDK_iOS_8_0 + #if PL__PureLayout_MinBaseSDK_iOS_8_0 /** A horizontal line at the baseline of the first line of text in a view. (For views that do not draw text, will be equivalent to ALEdgeTop.) Available in iOS 8.0 and later. */ ALAxisFirstBaseline = NSLayoutAttributeFirstBaseline - #endif /* __PureLayout_MinBaseSDK_iOS_8_0 */ + #endif /* PL__PureLayout_MinBaseSDK_iOS_8_0 */ }; -#if __PureLayout_MinBaseSDK_iOS_8_0 +#if PL__PureLayout_MinBaseSDK_iOS_8_0 /** Constants that represent layout margins of a view. Available in iOS 8.0 and later. */ -typedef NS_ENUM(NSInteger, ALMargin) { +typedef NS_CLOSED_ENUM(NSInteger, ALMargin) { /** The left margin of the view, based on the view's layoutMargins left inset. */ ALMarginLeft = NSLayoutAttributeLeftMargin, /** The right margin of the view, based on the view's layoutMargins right inset. */ @@ -141,18 +164,18 @@ typedef NS_ENUM(NSInteger, ALMargin) { }; /** Constants that represent axes of the layout margins of a view. Available in iOS 8.0 and later. */ -typedef NS_ENUM(NSInteger, ALMarginAxis) { - /** A vertical line through the middle of the view's left and right margins. */ +typedef NS_CLOSED_ENUM(NSInteger, ALMarginAxis) { + /** A vertical line equidistant from the view's left and right margins. */ ALMarginAxisVertical = NSLayoutAttributeCenterXWithinMargins, - /** A horizontal line through the middle of the view's top and bottom margins. */ + /** A horizontal line equidistant from the view's top and bottom margins. */ ALMarginAxisHorizontal = NSLayoutAttributeCenterYWithinMargins }; -#endif /* __PureLayout_MinBaseSDK_iOS_8_0 */ +#endif /* PL__PureLayout_MinBaseSDK_iOS_8_0 */ /** An attribute of a view that can be used in auto layout constraints. These constants are identical to the more specific enum types: ALEdge, ALAxis, ALDimension, ALMargin, ALMarginAxis. It is safe to cast a more specific enum type to the ALAttribute type. */ -typedef NS_ENUM(NSInteger, ALAttribute) { +typedef NS_CLOSED_ENUM(NSInteger, ALAttribute) { /** The left edge of the view. */ ALAttributeLeft = ALEdgeLeft, /** The right edge of the view. */ @@ -169,15 +192,15 @@ typedef NS_ENUM(NSInteger, ALAttribute) { ALAttributeWidth = ALDimensionWidth, /** The height of the view. */ ALAttributeHeight = ALDimensionHeight, - /** A vertical line through the middle of the view's left and right edges. */ + /** A vertical line equidistant from the view's left and right edges. */ ALAttributeVertical = ALAxisVertical, - /** A horizontal line through the middle of the view's top and bottom edges. */ + /** A horizontal line equidistant from the view's top and bottom edges. */ ALAttributeHorizontal = ALAxisHorizontal, /** A horizontal line at the baseline of the last line of text in the view. (For views that do not draw text, will be equivalent to ALEdgeBottom.) Same as ALAxisLastBaseline. */ ALAttributeBaseline = ALAxisBaseline, /** A horizontal line at the baseline of the last line of text in the view. (For views that do not draw text, will be equivalent to ALEdgeBottom.) */ ALAttributeLastBaseline = ALAxisLastBaseline, -#if __PureLayout_MinBaseSDK_iOS_8_0 +#if PL__PureLayout_MinBaseSDK_iOS_8_0 /** A horizontal line at the baseline of the first line of text in a view. (For views that do not draw text, will be equivalent to ALEdgeTop.) Available in iOS 8.0 and later. */ ALAttributeFirstBaseline = ALAxisFirstBaseline, /** The left margin of the view, based on the view's layoutMargins left inset. */ @@ -192,11 +215,11 @@ typedef NS_ENUM(NSInteger, ALAttribute) { ALAttributeMarginLeading = ALMarginLeading, /** The trailing margin of the view, based on the view's layoutMargins left/right (depending on language direction) inset. */ ALAttributeMarginTrailing = ALMarginTrailing, - /** A vertical line through the middle of the view's left and right margins. */ + /** A vertical line equidistant from the view's left and right margins. */ ALAttributeMarginAxisVertical = ALMarginAxisVertical, - /** A horizontal line through the middle of the view's top and bottom margins. */ + /** A horizontal line equidistant from the view's top and bottom margins. */ ALAttributeMarginAxisHorizontal = ALMarginAxisHorizontal -#endif /* __PureLayout_MinBaseSDK_iOS_8_0 */ +#endif /* PL__PureLayout_MinBaseSDK_iOS_8_0 */ }; /** A block containing method calls to the PureLayout API. Takes no arguments and has no return value. */ diff --git a/PureLayout/PureLayoutTests/PureLayoutBatchTests.m b/PureLayout/PureLayoutTests/PureLayoutBatchTests.m new file mode 100644 index 0000000..8f8b37b --- /dev/null +++ b/PureLayout/PureLayoutTests/PureLayoutBatchTests.m @@ -0,0 +1,255 @@ +// +// PureLayoutBatchTests.m +// PureLayout Tests +// +// Copyright (c) 2015 Tyler Fox +// https://github.com/PureLayout/PureLayout +// + +#import "PureLayoutTestBase.h" + +@interface PureLayoutBatchTests : PureLayoutTestBase + +@end + +@implementation PureLayoutBatchTests + +/** Returns YES if the constraint is active. */ +- (BOOL)isConstraintActive:(NSLayoutConstraint *)constraint +{ +#if PL__PureLayout_MinBaseSDK_iOS_8_0 || PL__PureLayout_MinBaseSDK_OSX_10_10 + if ([constraint respondsToSelector:@selector(isActive)]) { + return constraint.isActive; + } +#endif + + // Same as the `isActive` property, but backwards-compatible with iOS and OS X versions before that property was introduced. + if (constraint.secondItem) { + ALView *commonSuperview = [constraint.firstItem al_commonSuperviewWithView:constraint.secondItem]; + while (commonSuperview) { + if ([commonSuperview.constraints containsObject:constraint]) { + return YES; + } + commonSuperview = commonSuperview.superview; + } + } + else { + if ([((ALView *)constraint.firstItem).constraints containsObject:constraint]) { + return YES; + } + } + return NO; +} + +/** Returns YES if all the constraints in the array are active. */ +- (BOOL)allConstraintsAreActivated:(PL__NSArray_of(NSLayoutConstraint *) *)constraints +{ + BOOL allConstraintsActivated = YES; + for (NSLayoutConstraint *constraint in constraints) { + allConstraintsActivated &= [self isConstraintActive:constraint]; + } + return allConstraintsActivated; +} + +/** Returns YES if none of the constraints in the array are active. */ +- (BOOL)noConstraintsAreActivated:(PL__NSArray_of(NSLayoutConstraint *) *)constraints +{ + BOOL anyConstraintActivated = NO; + for (NSLayoutConstraint *constraint in constraints) { + anyConstraintActivated |= [self isConstraintActive:constraint]; + } + return !anyConstraintActivated; +} + +/** + Test the +[NSLayoutConstraint autoCreateAndInstallConstraints:] method. + */ +- (void)testCreateAndInstallConstraints +{ + PL__NSMutableArray_of(NSLayoutConstraint *) *createdConstraints = [NSMutableArray array]; + PL__NSArray_of(NSLayoutConstraint *) *returnedConstraints = [NSLayoutConstraint autoCreateAndInstallConstraints:^{ + [createdConstraints addObjectsFromArray:[self.viewA autoPinEdgesToSuperviewEdges]]; + [createdConstraints addObject:[self.viewA_A autoAlignAxis:ALAxisHorizontal toSameAxisOfView:self.viewA_A.superview]]; + [createdConstraints addObject:[self.viewA_A autoAlignAxis:ALAxisVertical toSameAxisOfView:self.viewA_A.superview withOffset:10.0]]; + [createdConstraints addObjectsFromArray:[self.viewA_A autoSetDimensionsToSize:CGSizeMake(50.0, 50.0)]]; + [createdConstraints addObjectsFromArray:[self.viewA_B autoCenterInSuperview]]; + [createdConstraints addObject:[self.viewA_B autoMatchDimension:ALDimensionHeight toDimension:ALDimensionWidth ofView:self.viewA_A]]; + [createdConstraints addObject:[self.viewB autoConstrainAttribute:ALAttributeLeading toAttribute:ALAttributeVertical ofView:self.viewA]]; + }]; + XCTAssertEqualObjects(createdConstraints, returnedConstraints, @"The array returned by +[autoCreateAndInstallConstraints:] should contain every constraint created."); + XCTAssert([self allConstraintsAreActivated:returnedConstraints], @"All constraints created inside of +[autoCreateAndInstallConstraints:] should be activated."); +} + +/** + Test nested calls to the +[NSLayoutConstraint autoCreateAndInstallConstraints:] method. + - Constraints should be returned ONLY by the call that provided the immediate enclosing block. + - Calls whose block contains other call(s) should not return constraints from within the blocks of nested call(s). + - Constraints should be active when they are returned. + */ +- (void)testCreateAndInstallConstraintsNested +{ + __block PL__NSArray_of(NSLayoutConstraint *) *returnedConstraints1_1 = nil; + __block PL__NSArray_of(NSLayoutConstraint *) *returnedConstraints1_1_1 = nil; + __block PL__NSArray_of(NSLayoutConstraint *) *returnedConstraints1_2 = nil; + + PL__NSArray_of(NSLayoutConstraint *) *returnedConstraints1 = [NSLayoutConstraint autoCreateAndInstallConstraints:^{ + [self.viewA autoPinEdgeToSuperviewEdge:ALEdgeTop]; + + returnedConstraints1_1 = [NSLayoutConstraint autoCreateAndInstallConstraints:^{ + [self.viewB autoSetDimension:ALDimensionWidth toSize:100.0]; + [self.viewC autoSetDimension:ALDimensionHeight toSize:100.0]; + + returnedConstraints1_1_1 = [NSLayoutConstraint autoCreateAndInstallConstraints:^{ + [self.viewD autoConstrainAttribute:ALAttributeHeight toAttribute:ALAttributeWidth ofView:self.viewC withMultiplier:2.0]; + }]; + XCTAssertEqual(returnedConstraints1_1_1.count, 1); + XCTAssert([self allConstraintsAreActivated:returnedConstraints1_1_1]); + + [self.viewB autoSetDimension:ALDimensionHeight toSize:100.0]; + [self.viewC autoSetDimension:ALDimensionWidth toSize:100.0]; + }]; + XCTAssertEqual(returnedConstraints1_1.count, 4); + XCTAssert([self allConstraintsAreActivated:returnedConstraints1_1]); + + [self.viewA autoPinEdgeToSuperviewEdge:ALEdgeLeading]; + + returnedConstraints1_2 = [NSLayoutConstraint autoCreateAndInstallConstraints:^{ + [self.viewA autoPinEdgeToSuperviewEdge:ALEdgeBottom]; + [self.viewA autoAlignAxisToSuperviewAxis:ALAxisVertical]; + }]; + XCTAssertEqual(returnedConstraints1_2.count, 2); + XCTAssert([self allConstraintsAreActivated:returnedConstraints1_2]); + + [self.viewA autoPinEdgeToSuperviewEdge:ALEdgeTrailing]; + }]; + XCTAssertEqual(returnedConstraints1.count, 3); + XCTAssert([self allConstraintsAreActivated:returnedConstraints1]); + XCTAssertEqual(returnedConstraints1_1.count, 4); + XCTAssert([self allConstraintsAreActivated:returnedConstraints1_1]); + XCTAssertEqual(returnedConstraints1_1_1.count, 1); + XCTAssert([self allConstraintsAreActivated:returnedConstraints1_1_1]); + XCTAssertEqual(returnedConstraints1_2.count, 2); + XCTAssert([self allConstraintsAreActivated:returnedConstraints1_2]); +} + +/** + Test the +[NSLayoutConstraint autoCreateConstraintsWithoutInstalling:] method. + */ +- (void)testCreateConstraintsWithoutInstalling +{ + PL__NSMutableArray_of(NSLayoutConstraint *) *createdConstraints = [NSMutableArray array]; + PL__NSArray_of(NSLayoutConstraint *) *returnedConstraints = [NSLayoutConstraint autoCreateConstraintsWithoutInstalling:^{ + [createdConstraints addObjectsFromArray:[self.viewA autoPinEdgesToSuperviewEdgesWithInsets:ALEdgeInsetsMake(10.0, 10.0, 10.0, 10.0) excludingEdge:ALEdgeBottom]]; + [createdConstraints addObject:[self.viewA_A autoAlignAxis:ALAxisVertical toSameAxisOfView:self.viewA_A.superview]]; + [createdConstraints addObject:[self.viewA_A autoAlignAxis:ALAxisBaseline toSameAxisOfView:self.viewA_A.superview withOffset:-10.0]]; + [createdConstraints addObjectsFromArray:[self.viewA_A autoSetDimensionsToSize:CGSizeMake(20.0, 80.0)]]; + [createdConstraints addObjectsFromArray:[self.viewA_B autoCenterInSuperview]]; + [createdConstraints addObject:[self.viewA_B autoMatchDimension:ALDimensionWidth toDimension:ALDimensionWidth ofView:self.viewA_A]]; + [createdConstraints addObject:[self.viewB autoConstrainAttribute:ALAttributeHorizontal toAttribute:ALAttributeTop ofView:self.viewA]]; + }]; + XCTAssertEqualObjects(createdConstraints, returnedConstraints, @"The array returned by +[autoCreateAndInstallConstraints:] should contain every constraint created."); + XCTAssert([self noConstraintsAreActivated:returnedConstraints], @"All constraints created inside of +[autoCreateAndInstallConstraints:] should not be activated."); +} + +/** + Test nested calls to the +[NSLayoutConstraint autoCreateConstraintsWithoutInstalling:] method. + - Constraints should be returned ONLY by the call that provided the immediate enclosing block. + - Calls whose block contains other call(s) should not return constraints from within the blocks of nested call(s). + - Constraints should never be active. + */ +- (void)testCreateConstraintsWithoutInstallingNested +{ + __block PL__NSArray_of(NSLayoutConstraint *) *returnedConstraints1_1 = nil; + __block PL__NSArray_of(NSLayoutConstraint *) *returnedConstraints1_1_1 = nil; + __block PL__NSArray_of(NSLayoutConstraint *) *returnedConstraints1_2 = nil; + + PL__NSArray_of(NSLayoutConstraint *) *returnedConstraints1 = [NSLayoutConstraint autoCreateConstraintsWithoutInstalling:^{ + [self.viewA autoPinEdgeToSuperviewEdge:ALEdgeTop]; + + returnedConstraints1_1 = [NSLayoutConstraint autoCreateConstraintsWithoutInstalling:^{ + [self.viewB autoSetDimension:ALDimensionWidth toSize:100.0]; + [self.viewC autoSetDimension:ALDimensionHeight toSize:100.0]; + + returnedConstraints1_1_1 = [NSLayoutConstraint autoCreateConstraintsWithoutInstalling:^{ + [self.viewD autoConstrainAttribute:ALAttributeHeight toAttribute:ALAttributeWidth ofView:self.viewC withMultiplier:2.0]; + }]; + XCTAssertEqual(returnedConstraints1_1_1.count, 1); + XCTAssert([self noConstraintsAreActivated:returnedConstraints1_1_1]); + + [self.viewB autoSetDimension:ALDimensionHeight toSize:100.0]; + [self.viewC autoSetDimension:ALDimensionWidth toSize:100.0]; + }]; + XCTAssertEqual(returnedConstraints1_1.count, 4); + XCTAssert([self noConstraintsAreActivated:returnedConstraints1_1]); + + [self.viewA autoPinEdgeToSuperviewEdge:ALEdgeLeading]; + + returnedConstraints1_2 = [NSLayoutConstraint autoCreateConstraintsWithoutInstalling:^{ + [self.viewA autoPinEdgeToSuperviewEdge:ALEdgeBottom]; + [self.viewA autoAlignAxisToSuperviewAxis:ALAxisVertical]; + }]; + XCTAssertEqual(returnedConstraints1_2.count, 2); + XCTAssert([self noConstraintsAreActivated:returnedConstraints1_2]); + + [self.viewA autoPinEdgeToSuperviewEdge:ALEdgeTrailing]; + }]; + XCTAssertEqual(returnedConstraints1.count, 3); + XCTAssert([self noConstraintsAreActivated:returnedConstraints1]); + XCTAssertEqual(returnedConstraints1_1.count, 4); + XCTAssert([self noConstraintsAreActivated:returnedConstraints1_1]); + XCTAssertEqual(returnedConstraints1_1_1.count, 1); + XCTAssert([self noConstraintsAreActivated:returnedConstraints1_1_1]); + XCTAssertEqual(returnedConstraints1_2.count, 2); + XCTAssert([self noConstraintsAreActivated:returnedConstraints1_2]); +} + +/** + Test nested calls to both +[NSLayoutConstraint autoCreateAndInstallConstraints:] and +[NSLayoutConstraint autoCreateConstraintsWithoutInstalling:] methods. + */ +- (void)testBothBatchCreateMethodsNested +{ + __block PL__NSArray_of(NSLayoutConstraint *) *returnedConstraints1_1 = nil; + __block PL__NSArray_of(NSLayoutConstraint *) *returnedConstraints1_1_1 = nil; + __block PL__NSArray_of(NSLayoutConstraint *) *returnedConstraints1_2 = nil; + + PL__NSArray_of(NSLayoutConstraint *) *returnedConstraints1 = [NSLayoutConstraint autoCreateConstraintsWithoutInstalling:^{ + [self.viewA autoPinEdgeToSuperviewEdge:ALEdgeTop]; + + returnedConstraints1_1 = [NSLayoutConstraint autoCreateAndInstallConstraints:^{ + [self.viewB autoSetDimension:ALDimensionWidth toSize:100.0]; + [self.viewC autoSetDimension:ALDimensionHeight toSize:100.0]; + + returnedConstraints1_1_1 = [NSLayoutConstraint autoCreateConstraintsWithoutInstalling:^{ + [self.viewD autoConstrainAttribute:ALAttributeHeight toAttribute:ALAttributeWidth ofView:self.viewC withMultiplier:2.0]; + }]; + XCTAssertEqual(returnedConstraints1_1_1.count, 1); + XCTAssert([self noConstraintsAreActivated:returnedConstraints1_1_1]); + + [self.viewB autoSetDimension:ALDimensionHeight toSize:100.0]; + [self.viewC autoSetDimension:ALDimensionWidth toSize:100.0]; + }]; + XCTAssertEqual(returnedConstraints1_1.count, 4); + XCTAssert([self allConstraintsAreActivated:returnedConstraints1_1]); + + [self.viewA autoPinEdgeToSuperviewEdge:ALEdgeLeading]; + + returnedConstraints1_2 = [NSLayoutConstraint autoCreateAndInstallConstraints:^{ + [self.viewA autoPinEdgeToSuperviewEdge:ALEdgeBottom]; + [self.viewA autoAlignAxisToSuperviewAxis:ALAxisVertical]; + }]; + XCTAssertEqual(returnedConstraints1_2.count, 2); + XCTAssert([self allConstraintsAreActivated:returnedConstraints1_2]); + + [self.viewA autoPinEdgeToSuperviewEdge:ALEdgeTrailing]; + }]; + XCTAssertEqual(returnedConstraints1.count, 3); + XCTAssert([self noConstraintsAreActivated:returnedConstraints1]); + XCTAssertEqual(returnedConstraints1_1.count, 4); + XCTAssert([self allConstraintsAreActivated:returnedConstraints1_1]); + XCTAssertEqual(returnedConstraints1_1_1.count, 1); + XCTAssert([self noConstraintsAreActivated:returnedConstraints1_1_1]); + XCTAssertEqual(returnedConstraints1_2.count, 2); + XCTAssert([self allConstraintsAreActivated:returnedConstraints1_2]); +} + +@end diff --git a/PureLayout/PureLayoutTests/PureLayoutCenteringTests.m b/PureLayout/PureLayoutTests/PureLayoutCenteringTests.m index 036c944..c1ec19f 100644 --- a/PureLayout/PureLayoutTests/PureLayoutCenteringTests.m +++ b/PureLayout/PureLayoutTests/PureLayoutCenteringTests.m @@ -2,8 +2,8 @@ // PureLayoutCenteringTests.m // PureLayout Tests // -// Copyright (c) 2014 Tyler Fox -// https://github.com/smileyborg/PureLayout +// Copyright (c) 2014-2015 Tyler Fox +// https://github.com/PureLayout/PureLayout // #import "PureLayoutTestBase.h" @@ -14,18 +14,6 @@ @interface PureLayoutCenteringTests : PureLayoutTestBase @implementation PureLayoutCenteringTests -- (void)setUp -{ - [super setUp]; - -} - -- (void)tearDown -{ - - [super tearDown]; -} - - (void)testAutoCenterInSuperview { [self.viewA autoSetDimensionsToSize:CGSizeMake(100.0, 100.0)]; diff --git a/PureLayout/PureLayoutTests/PureLayoutDistributeTests.m b/PureLayout/PureLayoutTests/PureLayoutDistributeTests.m index 7971c08..8b95551 100644 --- a/PureLayout/PureLayoutTests/PureLayoutDistributeTests.m +++ b/PureLayout/PureLayoutTests/PureLayoutDistributeTests.m @@ -3,30 +3,23 @@ // PureLayout Tests // // Copyright (c) 2014 Vytis Šibonis -// https://github.com/smileyborg/PureLayout +// Copyright (c) 2015 Tyler Fox +// https://github.com/PureLayout/PureLayout // #import "PureLayoutTestBase.h" +#pragma mark - Multiple View Distribution Tests + @interface PureLayoutDistributeTests : PureLayoutTestBase @end @implementation PureLayoutDistributeTests -- (void)setUp -{ - [super setUp]; -} - -- (void)tearDown -{ - [super tearDown]; -} - - (void)testAutoDistributeViewsHorizontallyWithFixedSpacing { - NSArray *constraints = nil; + PL__NSArray_of(NSLayoutConstraint *) *constraints = nil; constraints = [self.viewArray autoDistributeViewsAlongAxis:ALAxisHorizontal alignedTo:ALAttributeTop withFixedSpacing:20]; [self evaluateConstraints]; @@ -46,7 +39,7 @@ - (void)testAutoDistributeViewsHorizontallyWithFixedSpacing - (void)testAutoDistributeViewsVerticallyWithFixedSpacing { - NSArray *constraints = nil; + PL__NSArray_of(NSLayoutConstraint *) *constraints = nil; constraints = [self.viewArray autoDistributeViewsAlongAxis:ALAxisVertical alignedTo:ALAttributeRight withFixedSpacing:20]; [self evaluateConstraints]; @@ -66,7 +59,7 @@ - (void)testAutoDistributeViewsVerticallyWithFixedSpacing - (void)testAutoDistributeViewsHorizontallyWithFixedSize { - NSArray *constraints = nil; + PL__NSArray_of(NSLayoutConstraint *) *constraints = nil; constraints = [self.viewArray autoDistributeViewsAlongAxis:ALAxisHorizontal alignedTo:ALAttributeTop withFixedSize:20]; [self evaluateConstraints]; @@ -86,7 +79,7 @@ - (void)testAutoDistributeViewsHorizontallyWithFixedSize - (void)testAutoDistributeViewsVerticallyWithFixedSize { - NSArray *constraints = nil; + PL__NSArray_of(NSLayoutConstraint *) *constraints = nil; constraints = [self.viewArray autoDistributeViewsAlongAxis:ALAxisVertical alignedTo:ALAttributeLeft withFixedSize:20]; [self evaluateConstraints]; @@ -104,35 +97,35 @@ - (void)testAutoDistributeViewsVerticallyWithFixedSize [constraints autoRemoveConstraints]; } -- (void)assertViews:(NSArray *)views areDistributedHorizontallyWithSpacing:(CGFloat)spacing +- (void)assertViews:(PL__NSArray_of(ALView *) *)views areDistributedHorizontallyWithSpacing:(CGFloat)spacing { CGFloat totalSpacing = (views.count + 1) * spacing; CGFloat singleViewWidth = (kContainerViewWidth - totalSpacing) / views.count; [self assertViews:views areDistributedHorizontallyWithWidth:singleViewWidth andSpacing:spacing]; } -- (void)assertViews:(NSArray *)views areDistributedHorizontallyWithWidth:(CGFloat)width +- (void)assertViews:(PL__NSArray_of(ALView *) *)views areDistributedHorizontallyWithWidth:(CGFloat)width { CGFloat totalSpacing = kContainerViewWidth - views.count * width; CGFloat singleSpace = totalSpacing / (views.count + 1); [self assertViews:views areDistributedHorizontallyWithWidth:width andSpacing:singleSpace]; } -- (void)assertViews:(NSArray *)views areDistributedVerticallyWithSpacing:(CGFloat)singleSpace +- (void)assertViews:(PL__NSArray_of(ALView *) *)views areDistributedVerticallyWithSpacing:(CGFloat)singleSpace { CGFloat totalSpacing = (views.count + 1) * singleSpace; CGFloat singleViewHeight = (kContainerViewHeight - totalSpacing) / views.count; [self assertViews:views areDistributedVerticallyWithHeight:singleViewHeight andSpacing:singleSpace]; } -- (void)assertViews:(NSArray *)views areDistributedVerticallyWithHeight:(CGFloat)height +- (void)assertViews:(PL__NSArray_of(ALView *) *)views areDistributedVerticallyWithHeight:(CGFloat)height { CGFloat totalSpacing = kContainerViewHeight - views.count * height; CGFloat singleSpace = totalSpacing / (views.count + 1); [self assertViews:views areDistributedVerticallyWithHeight:height andSpacing:singleSpace]; } -- (void)assertViews:(NSArray *)views areDistributedHorizontallyWithWidth:(CGFloat)width andSpacing:(CGFloat)spacing +- (void)assertViews:(PL__NSArray_of(ALView *) *)views areDistributedHorizontallyWithWidth:(CGFloat)width andSpacing:(CGFloat)spacing { ALView *previousView = nil; for (ALView *view in views) { @@ -142,7 +135,7 @@ - (void)assertViews:(NSArray *)views areDistributedHorizontallyWithWidth:(CGFloa } } -- (void)assertViews:(NSArray *)views areDistributedVerticallyWithHeight:(CGFloat)height andSpacing:(CGFloat)spacing +- (void)assertViews:(PL__NSArray_of(ALView *) *)views areDistributedVerticallyWithHeight:(CGFloat)height andSpacing:(CGFloat)spacing { // Y-axis is inverted on Mac, reverse view array to compensate #if !TARGET_OS_IPHONE @@ -158,3 +151,58 @@ - (void)assertViews:(NSArray *)views areDistributedVerticallyWithHeight:(CGFloat } @end + + + +#pragma mark - Single View Distribution Tests + +@interface PureLayoutSingleViewDistributeTests : PureLayoutDistributeTests + +@property ALView *singleView; + +@end + +@implementation PureLayoutSingleViewDistributeTests + +// Set up a modified view hierarchy for this test (without calling super). +- (void)setupViewHierarchy +{ + self.singleView = [ALView newAutoLayoutView]; + + [self.containerView addSubview:self.singleView]; +} + +// Override the testViewHierarchy method to test our modified view hierarchy. +- (void)testViewHierarchy +{ + XCTAssertNotNil(self.containerView, @"View hierarchy is not setup as expected."); + XCTAssert(self.singleView.superview == self.containerView, @"View hierarchy is not setup as expected."); +} + +// Override the viewArray accessor to always just return an array of the one view used for this test. +- (PL__NSArray_of(ALView *) *)viewArray +{ + return @[self.singleView]; +} + +- (void)testAutoDistributeViewsHorizontallyWithFixedSpacing +{ + [super testAutoDistributeViewsHorizontallyWithFixedSpacing]; +} + +- (void)testAutoDistributeViewsVerticallyWithFixedSpacing +{ + [super testAutoDistributeViewsVerticallyWithFixedSpacing]; +} + +- (void)testAutoDistributeViewsHorizontallyWithFixedSize +{ + [super testAutoDistributeViewsHorizontallyWithFixedSize]; +} + +- (void)testAutoDistributeViewsVerticallyWithFixedSize +{ + [super testAutoDistributeViewsVerticallyWithFixedSize]; +} + +@end diff --git a/PureLayout/PureLayoutTests/PureLayoutIdentifierTests.m b/PureLayout/PureLayoutTests/PureLayoutIdentifierTests.m new file mode 100644 index 0000000..e8c5464 --- /dev/null +++ b/PureLayout/PureLayoutTests/PureLayoutIdentifierTests.m @@ -0,0 +1,111 @@ +// +// PureLayoutIdentifierTests.m +// PureLayout Tests +// +// Copyright (c) 2015 Tyler Fox +// https://github.com/PureLayout/PureLayout +// + +#import "PureLayoutTestBase.h" + +@interface PureLayoutIdentifierTests : PureLayoutTestBase + +@end + +@implementation PureLayoutIdentifierTests + +/** Test the -[autoIdentify:] method on NSLayoutConstraint. */ +- (void)testIdentify +{ + NSLayoutConstraint *c1 = [[self.viewA autoPinEdge:ALEdgeLeading toEdge:ALEdgeTrailing ofView:self.viewB] autoIdentify:@"Identify1"]; + XCTAssertEqualObjects(c1.identifier, @"Identify1"); + + NSLayoutConstraint *c2 = [self.viewD autoSetDimension:ALDimensionHeight toSize:25.0]; + [c2 autoIdentify:@"Identify2"]; + XCTAssertEqualObjects(c2.identifier, @"Identify2"); +} + +/** Test the -[autoIdentifyConstraints:] method on NSArray. */ +- (void)testIdentifyConstraints +{ + PL__NSArray_of(NSLayoutConstraint *) *constraints = [[self.viewC autoCenterInSuperview] autoIdentifyConstraints:@"IdentifyConstraints1"]; + for (NSLayoutConstraint *constraint in constraints) { + XCTAssertEqualObjects(constraint.identifier, @"IdentifyConstraints1"); + } + + constraints = [@[self.viewA_A_A, self.viewA_A_B] autoDistributeViewsAlongAxis:ALAxisHorizontal alignedTo:ALAttributeHorizontal withFixedSize:10.0]; + [constraints autoIdentifyConstraints:@"IdentifyConstraints2"]; + for (NSLayoutConstraint *constraint in constraints) { + XCTAssertEqualObjects(constraint.identifier, @"IdentifyConstraints2"); + } +} + +/** Test setting identifiers within a block that prevents automatic constraint installation. */ +- (void)testIdentifyConstraintsCreatedWithoutInstalling +{ + __block NSLayoutConstraint *c1, *c2, *c3; + __block PL__NSArray_of(NSLayoutConstraint *) *c4s; + PL__NSArray_of(NSLayoutConstraint *) *constraints = [NSLayoutConstraint autoCreateConstraintsWithoutInstalling:^{ + c1 = [self.viewA autoMatchDimension:ALDimensionWidth toDimension:ALDimensionHeight ofView:self.viewB]; + c2 = [[self.viewC autoMatchDimension:ALDimensionWidth toDimension:ALDimensionHeight ofView:self.viewD] autoIdentify:@"Identifier1"]; + [NSLayoutConstraint autoSetIdentifier:@"Identifier2" forConstraints:^{ + c3 = [self.viewA_B autoPinEdgeToSuperviewEdge:ALEdgeBottom]; + c4s = [self.viewA_A autoPinEdgesToSuperviewEdges]; + }]; + XCTAssertNil(c1.identifier); + XCTAssertEqualObjects(c2.identifier, @"Identifier1"); + XCTAssertEqualObjects(c3.identifier, @"Identifier2"); + for (NSLayoutConstraint *constraint in c4s) { + XCTAssertEqualObjects(constraint.identifier, @"Identifier2"); + } + }]; + XCTAssertNil(c1.identifier); + XCTAssertEqualObjects(c2.identifier, @"Identifier1"); + XCTAssertEqualObjects(c3.identifier, @"Identifier2"); + for (NSLayoutConstraint *constraint in c4s) { + XCTAssertEqualObjects(constraint.identifier, @"Identifier2"); + } + [constraints autoInstallConstraints]; + XCTAssertNil(c1.identifier); + XCTAssertEqualObjects(c2.identifier, @"Identifier1"); + XCTAssertEqualObjects(c3.identifier, @"Identifier2"); + for (NSLayoutConstraint *constraint in c4s) { + XCTAssertEqualObjects(constraint.identifier, @"Identifier2"); + } +} + +/** Test the +[NSLayoutConstraint autoSetIdentifier:forConstraints:] method. */ +- (void)testSetIdentifierForConstraints +{ + __block NSLayoutConstraint *c1; + __block PL__NSArray_of(NSLayoutConstraint *) *c2s; + [NSLayoutConstraint autoSetIdentifier:@"Identifier1" forConstraints:^{ + c1 = [self.viewA_A_A autoSetDimension:ALDimensionHeight toSize:50.0]; + c2s = [@[self.viewA, self.viewB, self.viewC] autoDistributeViewsAlongAxis:ALAxisVertical alignedTo:ALAttributeVertical withFixedSpacing:15.0]; + }]; + XCTAssertEqualObjects(c1.identifier, @"Identifier1"); + for (NSLayoutConstraint *constraint in c2s) { + XCTAssertEqualObjects(constraint.identifier, @"Identifier1"); + } +} + +/** Test nested calls to the +[NSLayoutConstraint autoSetIdentifier:forConstraints:] method. */ +- (void)testSetIdentifierForConstraintsNested +{ + __block NSLayoutConstraint *c1, *c2, *c3; + [NSLayoutConstraint autoSetIdentifier:@"IdentifierA" forConstraints:^{ + c1 = [self.viewA_A_A autoSetDimension:ALDimensionHeight toSize:50.0]; + + [NSLayoutConstraint autoSetIdentifier:@"IdentifierB" forConstraints:^{ + c2 = [self.viewA_A_A autoSetDimension:ALDimensionHeight toSize:50.0]; + }]; + XCTAssertEqualObjects(c2.identifier, @"IdentifierB"); + + c3 = [self.viewA_A_A autoSetDimension:ALDimensionHeight toSize:50.0]; + }]; + XCTAssertEqualObjects(c1.identifier, @"IdentifierA"); + XCTAssertEqualObjects(c2.identifier, @"IdentifierB"); + XCTAssertEqualObjects(c3.identifier, @"IdentifierA"); +} + +@end diff --git a/PureLayout/PureLayoutTests/PureLayoutInstallationTests.m b/PureLayout/PureLayoutTests/PureLayoutInstallationTests.m index a54738d..e2841fa 100644 --- a/PureLayout/PureLayoutTests/PureLayoutInstallationTests.m +++ b/PureLayout/PureLayoutTests/PureLayoutInstallationTests.m @@ -2,8 +2,8 @@ // PureLayoutInstallationTests.m // PureLayout Tests // -// Copyright (c) 2014 Tyler Fox -// https://github.com/smileyborg/PureLayout +// Copyright (c) 2014-2015 Tyler Fox +// https://github.com/PureLayout/PureLayout // #import "PureLayoutTestBase.h" @@ -14,18 +14,6 @@ @interface PureLayoutInstallationTests : PureLayoutTestBase @implementation PureLayoutInstallationTests -- (void)setUp -{ - [super setUp]; - -} - -- (void)tearDown -{ - - [super tearDown]; -} - /** Test the -[autoInstall] method on NSLayoutConstraint with two nil items. */ diff --git a/PureLayout/PureLayoutTests/PureLayoutInstantiationTests.m b/PureLayout/PureLayoutTests/PureLayoutInstantiationTests.m index 8386781..9cea9ca 100644 --- a/PureLayout/PureLayoutTests/PureLayoutInstantiationTests.m +++ b/PureLayout/PureLayoutTests/PureLayoutInstantiationTests.m @@ -2,8 +2,8 @@ // PureLayoutInstantiationTests.m // PureLayout Tests // -// Copyright (c) 2014 Tyler Fox -// https://github.com/smileyborg/PureLayout +// Copyright (c) 2014-2015 Tyler Fox +// https://github.com/PureLayout/PureLayout // #import "PureLayoutTestBase.h" @@ -14,18 +14,6 @@ @interface PureLayoutInstantiationTests : PureLayoutTestBase @implementation PureLayoutInstantiationTests -- (void)setUp -{ - [super setUp]; - -} - -- (void)tearDown -{ - - [super tearDown]; -} - /** Test the +[newAutoLayoutView] method. */ @@ -68,4 +56,28 @@ - (void)testInitForAutoLayout XCTAssert(view.translatesAutoresizingMaskIntoConstraints == NO, @"The view returned from [[ALImageView alloc] initForAutoLayout] should not translate its autoresizing mask into constraints."); } +/** + Test the -[configureForAutoLayout] method. + */ +- (void)testConfigureForAutoLayout +{ + ALView *view = [[ALView alloc] init]; + XCTAssert(view.translatesAutoresizingMaskIntoConstraints, @"By default, initialized views should translate their autoresizing mask into constraints."); + ALView *returnedView = [view configureForAutoLayout]; + XCTAssert(view == returnedView, @"Calling -[view configureForAutoLayout] should return an identical reference to the same view."); + XCTAssert(returnedView.translatesAutoresizingMaskIntoConstraints == NO, @"The view returned from [view configureForAutoLayout] should not translate its autoresizing mask into constraints."); + + view = [[ALLabel alloc] init]; + XCTAssert(view.translatesAutoresizingMaskIntoConstraints, @"By default, initialized views should translate their autoresizing mask into constraints."); + returnedView = [view configureForAutoLayout]; + XCTAssert(view == returnedView, @"Calling -[view configureForAutoLayout] should return an identical reference to the same view."); + XCTAssert(returnedView.translatesAutoresizingMaskIntoConstraints == NO, @"The view returned from [view configureForAutoLayout] should not translate its autoresizing mask into constraints."); + + view = [[ALImageView alloc] init]; + XCTAssert(view.translatesAutoresizingMaskIntoConstraints, @"By default, initialized views should translate their autoresizing mask into constraints."); + returnedView = [view configureForAutoLayout]; + XCTAssert(view == returnedView, @"Calling -[view configureForAutoLayout] should return an identical reference to the same view."); + XCTAssert(returnedView.translatesAutoresizingMaskIntoConstraints == NO, @"The view returned from [view configureForAutoLayout] should not translate its autoresizing mask into constraints."); +} + @end diff --git a/PureLayout/PureLayoutTests/PureLayoutInternalTests.m b/PureLayout/PureLayoutTests/PureLayoutInternalTests.m index 64774e0..c6dc996 100644 --- a/PureLayout/PureLayoutTests/PureLayoutInternalTests.m +++ b/PureLayout/PureLayoutTests/PureLayoutInternalTests.m @@ -2,8 +2,8 @@ // PureLayoutInternalTests.m // PureLayout Tests // -// Copyright (c) 2014 Tyler Fox -// https://github.com/smileyborg/PureLayout +// Copyright (c) 2014-2015 Tyler Fox +// https://github.com/PureLayout/PureLayout // #import "PureLayoutTestBase.h" @@ -14,18 +14,6 @@ @interface PureLayoutInternalTests : PureLayoutTestBase @implementation PureLayoutInternalTests -- (void)setUp -{ - [super setUp]; - -} - -- (void)tearDown -{ - - [super tearDown]; -} - /** Test that ALAttributes translate directly to the specific enum types. */ @@ -43,7 +31,7 @@ - (void)testAttributeEnums XCTAssert(ALAttributeHorizontal == ALAxisHorizontal); XCTAssert(ALAttributeBaseline == ALAxisBaseline); XCTAssert(ALAttributeLastBaseline == ALAxisLastBaseline); -#if __PureLayout_MinBaseSDK_iOS_8_0 +#if PL__PureLayout_MinBaseSDK_iOS_8_0 XCTAssert(ALAttributeFirstBaseline == ALAxisFirstBaseline); XCTAssert(ALAttributeMarginLeft == ALMarginLeft); XCTAssert(ALAttributeMarginRight == ALMarginRight); @@ -53,7 +41,7 @@ - (void)testAttributeEnums XCTAssert(ALAttributeMarginTrailing == ALMarginTrailing); XCTAssert(ALAttributeMarginAxisVertical == ALMarginAxisVertical); XCTAssert(ALAttributeMarginAxisHorizontal == ALMarginAxisHorizontal); -#endif /* __PureLayout_MinBaseSDK_iOS_8_0 */ +#endif /* PL__PureLayout_MinBaseSDK_iOS_8_0 */ } /** @@ -73,8 +61,8 @@ - (void)testLayoutAttributeForAttribute XCTAssert([NSLayoutConstraint al_layoutAttributeForAttribute:(ALAttribute)ALDimensionWidth] == NSLayoutAttributeWidth, @"ALDimensionWidth should correspond to NSLayoutAttributeWidth."); XCTAssert([NSLayoutConstraint al_layoutAttributeForAttribute:(ALAttribute)ALDimensionHeight] == NSLayoutAttributeHeight, @"ALDimensionHeight should correspond to NSLayoutAttributeHeight."); -#if __PureLayout_MinBaseSDK_iOS_8_0 - if (__PureLayout_MinSysVer_iOS_8_0) { +#if PL__PureLayout_MinBaseSDK_iOS_8_0 + if (PL__PureLayout_MinSysVer_iOS_8_0) { XCTAssert([NSLayoutConstraint al_layoutAttributeForAttribute:(ALAttribute)ALMarginLeft] == NSLayoutAttributeLeftMargin, @"ALMarginLeft should correspond to NSLayoutAttributeLeftMargin."); XCTAssert([NSLayoutConstraint al_layoutAttributeForAttribute:(ALAttribute)ALMarginRight] == NSLayoutAttributeRightMargin, @"ALMarginRight should correspond to NSLayoutAttributeRightMargin."); XCTAssert([NSLayoutConstraint al_layoutAttributeForAttribute:(ALAttribute)ALMarginTop] == NSLayoutAttributeTopMargin, @"ALMarginTop should correspond to NSLayoutAttributeTopMargin."); @@ -98,19 +86,19 @@ - (void)testLayoutAttributeForAttribute XCTAssertNoThrow([NSLayoutConstraint al_layoutAttributeForAttribute:(ALAttribute)ALAxisLastBaseline], @"ALAxisLastBaseline should not throw an exception on iOS 6 or 7."); XCTAssert([NSLayoutConstraint al_layoutAttributeForAttribute:(ALAttribute)ALAxisLastBaseline] == NSLayoutAttributeLastBaseline, @"ALAxisLastBaseline should correspond to NSLayoutAttributeLastBaseline."); } -#endif /* __PureLayout_MinBaseSDK_iOS_8_0 */ +#endif /* PL__PureLayout_MinBaseSDK_iOS_8_0 */ XCTAssertThrows([NSLayoutConstraint al_layoutAttributeForAttribute:(ALAttribute)NSLayoutAttributeNotAnAttribute], @"Passing an invalid ALAttribute should throw an exception."); } -#if __PureLayout_MinBaseSDK_iOS_8_0 +#if PL__PureLayout_MinBaseSDK_iOS_8_0 /** Test the internal edge <-> margin translation method. */ - (void)testMarginForEdge { - if (__PureLayout_MinSysVer_iOS_8_0) { + if (PL__PureLayout_MinSysVer_iOS_8_0) { XCTAssert([NSLayoutConstraint al_marginForEdge:ALEdgeLeft] == ALMarginLeft); XCTAssert([NSLayoutConstraint al_marginForEdge:ALEdgeRight] == ALMarginRight); XCTAssert([NSLayoutConstraint al_marginForEdge:ALEdgeTop] == ALMarginTop); @@ -132,7 +120,7 @@ - (void)testMarginForEdge */ - (void)testMarginAxisforAxis { - if (__PureLayout_MinSysVer_iOS_8_0) { + if (PL__PureLayout_MinSysVer_iOS_8_0) { XCTAssert([NSLayoutConstraint al_marginAxisForAxis:ALAxisVertical] == ALMarginAxisVertical); XCTAssert([NSLayoutConstraint al_marginAxisForAxis:ALAxisHorizontal] == ALMarginAxisHorizontal); } else { @@ -143,7 +131,7 @@ - (void)testMarginAxisforAxis XCTAssertThrows([NSLayoutConstraint al_marginAxisForAxis:ALAxisFirstBaseline]); } -#endif /* __PureLayout_MinBaseSDK_iOS_8_0 */ +#endif /* PL__PureLayout_MinBaseSDK_iOS_8_0 */ /** Test the internal NSLayoutConstraintAxis for ALAxis translation method. @@ -202,7 +190,12 @@ - (void)testCommonSuperviewWithView */ - (void)testCommonSuperviewOfViews { - NSArray *viewArray = @[self.viewA, self.viewB, self.viewC]; + PL__NSArray_of(ALView *) *viewArray; + + viewArray = @[self.viewA, self.viewB, self.viewC]; + XCTAssert([viewArray al_commonSuperviewOfViews] == self.containerView, @"The common superview of viewArray should be containerView."); + + viewArray = @[self.viewA_A, self.viewB_A]; XCTAssert([viewArray al_commonSuperviewOfViews] == self.containerView, @"The common superview of viewArray should be containerView."); viewArray = @[self.viewC, self.viewB, self.viewA_A]; @@ -216,12 +209,16 @@ - (void)testCommonSuperviewOfViews viewArray = @[self.viewA_A_B, self.viewA_A_A, self.viewA, self.viewB, self.viewC, self.viewA_B, self.viewA_B_A, self.viewB, self.viewB_A]; XCTAssert([viewArray al_commonSuperviewOfViews] == self.containerView, @"The common superview of viewArray should be containerView."); + + viewArray = @[self.viewA]; + XCTAssert([viewArray al_commonSuperviewOfViews] == self.containerView, @"The common superview of viewArray should be containerView."); - ALView *orphanView = [ALView newAutoLayoutView]; // has no superview + ALView *orphanView = [ALView newAutoLayoutView]; // has no superview + viewArray = @[orphanView]; - XCTAssert([viewArray al_commonSuperviewOfViews] == orphanView, @"The common superview of viewArray should be orphanView."); - + XCTAssertThrows([viewArray al_commonSuperviewOfViews], @"An exception should be thrown as there is no common superview of viewArray."); + viewArray = @[orphanView, self.viewC, self.viewB, self.viewA_A]; XCTAssertThrows([viewArray al_commonSuperviewOfViews], @"An exception should be thrown as there is no common superview of viewArray."); @@ -254,7 +251,7 @@ - (void)testContainsMinimumNumberOfViews - (void)testCopyViewsOnly { NSArray *startingArray = @[[NSObject new], [ALLabel new], [ALImageView new], [NSString new], [ALView new], [NSDecimalNumber new], [NSLayoutConstraint new]]; - NSArray *viewsOnlyArray = [startingArray al_copyViewsOnly]; + PL__NSArray_of(ALView *) *viewsOnlyArray = [startingArray al_copyViewsOnly]; XCTAssert([viewsOnlyArray count] == 3, @"Only 3 objects should remain in the new array."); startingArray = @[[ALView newAutoLayoutView]]; diff --git a/PureLayout/PureLayoutTests/PureLayoutPinEdgesTests.m b/PureLayout/PureLayoutTests/PureLayoutPinEdgesTests.m index 6b334a3..d11f38d 100644 --- a/PureLayout/PureLayoutTests/PureLayoutPinEdgesTests.m +++ b/PureLayout/PureLayoutTests/PureLayoutPinEdgesTests.m @@ -2,8 +2,8 @@ // PureLayoutPinEdgesTests.m // PureLayout Tests // -// Copyright (c) 2014 Tyler Fox -// https://github.com/smileyborg/PureLayout +// Copyright (c) 2014-2015 Tyler Fox +// https://github.com/PureLayout/PureLayout // #import "PureLayoutTestBase.h" @@ -14,18 +14,6 @@ @interface PureLayoutPinEdgesTests : PureLayoutTestBase @implementation PureLayoutPinEdgesTests -- (void)setUp -{ - [super setUp]; - -} - -- (void)tearDown -{ - - [super tearDown]; -} - - (void)testAutoPinEdgeToSuperviewEdge { [self.viewA autoPinEdgeToSuperviewEdge:ALEdgeTop withInset:10.0]; @@ -52,4 +40,106 @@ - (void)testAutoPinEdgeToSuperviewEdge ALAssertFrameEquals(self.viewB, 500.0, VALUES(0.0, -52.0), kContainerViewWidth - 500.0, kContainerViewHeight + 52.0); } +-(void)testAutoPinEdgesReturnsConstraintsCounterclockwiseFromTop +{ + PL__NSArray_of(NSLayoutConstraint *) *constraints = [self.viewA autoPinEdgesToSuperviewEdges]; + + XCTAssertEqual([[constraints objectAtIndex:0] firstAttribute], NSLayoutAttributeTop); + XCTAssertEqual([[constraints objectAtIndex:1] firstAttribute], NSLayoutAttributeLeading); + XCTAssertEqual([[constraints objectAtIndex:2] firstAttribute], NSLayoutAttributeBottom); + XCTAssertEqual([[constraints objectAtIndex:3] firstAttribute], NSLayoutAttributeTrailing); +} + +-(void)testAutoPinEdgesExcludingEdgeRetainsRelativeConstraintOrdering +{ + PL__NSArray_of(NSLayoutConstraint *) *constraints = [self.viewA autoPinEdgesToSuperviewEdgesWithInsets:ALEdgeInsetsZero excludingEdge:ALEdgeLeading]; + + XCTAssertEqual([[constraints objectAtIndex:0] firstAttribute], NSLayoutAttributeTop); + XCTAssertEqual([[constraints objectAtIndex:1] firstAttribute], NSLayoutAttributeBottom); + XCTAssertEqual([[constraints objectAtIndex:2] firstAttribute], NSLayoutAttributeTrailing); +} + +-(void)testAutoPinEdgesExcludingLeftEdgeDoesNotUseTrailing +{ + PL__NSArray_of(NSLayoutConstraint *) *excludingLeft = [self.viewA autoPinEdgesToSuperviewEdgesWithInsets:ALEdgeInsetsZero excludingEdge:ALEdgeLeft]; + + XCTAssertEqual([[excludingLeft objectAtIndex:0] firstAttribute], NSLayoutAttributeTop); + XCTAssertEqual([[excludingLeft objectAtIndex:1] firstAttribute], NSLayoutAttributeBottom); + XCTAssertEqual([[excludingLeft objectAtIndex:2] firstAttribute], NSLayoutAttributeRight); + + PL__NSArray_of(NSLayoutConstraint *) *excludingLeading = [self.viewA autoPinEdgesToSuperviewEdgesWithInsets:ALEdgeInsetsZero excludingEdge:ALEdgeLeading]; + + XCTAssertEqual([[excludingLeading objectAtIndex:0] firstAttribute], NSLayoutAttributeTop); + XCTAssertEqual([[excludingLeading objectAtIndex:1] firstAttribute], NSLayoutAttributeBottom); + XCTAssertEqual([[excludingLeading objectAtIndex:2] firstAttribute], NSLayoutAttributeTrailing); +} + +-(void)testAutoPinEdgesExcludingRightEdgeDoesNotUseLeading +{ + PL__NSArray_of(NSLayoutConstraint *) *excludingRight = [self.viewA autoPinEdgesToSuperviewEdgesWithInsets:ALEdgeInsetsZero excludingEdge:ALEdgeRight]; + + XCTAssertEqual([[excludingRight objectAtIndex:0] firstAttribute], NSLayoutAttributeTop); + XCTAssertEqual([[excludingRight objectAtIndex:1] firstAttribute], NSLayoutAttributeLeft); + XCTAssertEqual([[excludingRight objectAtIndex:2] firstAttribute], NSLayoutAttributeBottom); + + PL__NSArray_of(NSLayoutConstraint *) *excludingTrailing = [self.viewA autoPinEdgesToSuperviewEdgesWithInsets:ALEdgeInsetsZero excludingEdge:ALEdgeTrailing]; + + XCTAssertEqual([[excludingTrailing objectAtIndex:0] firstAttribute], NSLayoutAttributeTop); + XCTAssertEqual([[excludingTrailing objectAtIndex:1] firstAttribute], NSLayoutAttributeLeading); + XCTAssertEqual([[excludingTrailing objectAtIndex:2] firstAttribute], NSLayoutAttributeBottom); +} + +#if PL__PureLayout_MinBaseSDK_iOS_8_0 + +-(void)testAutoPinEdgesSuperViewMarginsReturnsConstraintsCounterclockwiseFromTop +{ + PL__NSArray_of(NSLayoutConstraint *)*constraints = [self.viewA autoPinEdgesToSuperviewMarginsWithInsets:(ALEdgeInsetsZero)]; + + XCTAssertEqual([[constraints objectAtIndex:0] firstAttribute], NSLayoutAttributeTop); + XCTAssertEqual([[constraints objectAtIndex:1] firstAttribute], NSLayoutAttributeLeading); + XCTAssertEqual([[constraints objectAtIndex:2] firstAttribute], NSLayoutAttributeBottom); + XCTAssertEqual([[constraints objectAtIndex:3] firstAttribute], NSLayoutAttributeTrailing); +} + +-(void)testAutoPinEdgesToSuperviewMarginsExcludingEdgeRetainsRelativeConstraintOrdering +{ + PL__NSArray_of(NSLayoutConstraint *)*constraints = [self.viewA autoPinEdgesToSuperviewMarginsExcludingEdge:ALEdgeLeading]; + + XCTAssertEqual([[constraints objectAtIndex:0] firstAttribute], NSLayoutAttributeTop); + XCTAssertEqual([[constraints objectAtIndex:1] firstAttribute], NSLayoutAttributeBottom); + XCTAssertEqual([[constraints objectAtIndex:2] firstAttribute], NSLayoutAttributeTrailing); +} + +-(void)testAutoPinMarginsExcludingLeftEdgeDoesNotUseTrailing +{ + PL__NSArray_of(NSLayoutConstraint *) *excludingLeft = [self.viewA autoPinEdgesToSuperviewMarginsExcludingEdge:ALEdgeLeft]; + + XCTAssertEqual([[excludingLeft objectAtIndex:0] firstAttribute], NSLayoutAttributeTop); + XCTAssertEqual([[excludingLeft objectAtIndex:1] firstAttribute], NSLayoutAttributeBottom); + XCTAssertEqual([[excludingLeft objectAtIndex:2] firstAttribute], NSLayoutAttributeRight); + + PL__NSArray_of(NSLayoutConstraint *) *excludingLeading = [self.viewA autoPinEdgesToSuperviewMarginsExcludingEdge:ALEdgeLeading]; + + XCTAssertEqual([[excludingLeading objectAtIndex:0] firstAttribute], NSLayoutAttributeTop); + XCTAssertEqual([[excludingLeading objectAtIndex:1] firstAttribute], NSLayoutAttributeBottom); + XCTAssertEqual([[excludingLeading objectAtIndex:2] firstAttribute], NSLayoutAttributeTrailing); +} + +-(void)testAutoPinMarginsExcludingRightEdgeDoesNotUseLeading +{ + PL__NSArray_of(NSLayoutConstraint *) *excludingRight = [self.viewA autoPinEdgesToSuperviewMarginsExcludingEdge:ALEdgeRight]; + + XCTAssertEqual([[excludingRight objectAtIndex:0] firstAttribute], NSLayoutAttributeTop); + XCTAssertEqual([[excludingRight objectAtIndex:1] firstAttribute], NSLayoutAttributeLeft); + XCTAssertEqual([[excludingRight objectAtIndex:2] firstAttribute], NSLayoutAttributeBottom); + + PL__NSArray_of(NSLayoutConstraint *) *excludingTrailing = [self.viewA autoPinEdgesToSuperviewMarginsExcludingEdge:ALEdgeTrailing]; + + XCTAssertEqual([[excludingTrailing objectAtIndex:0] firstAttribute], NSLayoutAttributeTop); + XCTAssertEqual([[excludingTrailing objectAtIndex:1] firstAttribute], NSLayoutAttributeLeading); + XCTAssertEqual([[excludingTrailing objectAtIndex:2] firstAttribute], NSLayoutAttributeBottom); +} + +#endif /* PL__PureLayout_MinBaseSDK_iOS_8_0 */ + @end diff --git a/PureLayout/PureLayoutTests/PureLayoutPriorityTests.m b/PureLayout/PureLayoutTests/PureLayoutPriorityTests.m index d0df2db..1437ea6 100644 --- a/PureLayout/PureLayoutTests/PureLayoutPriorityTests.m +++ b/PureLayout/PureLayoutTests/PureLayoutPriorityTests.m @@ -2,36 +2,22 @@ // PureLayoutPriorityTests.m // PureLayout Tests // -// Copyright (c) 2014 Tyler Fox -// https://github.com/smileyborg/PureLayout +// Copyright (c) 2014-2015 Tyler Fox +// https://github.com/PureLayout/PureLayout // #import "PureLayoutTestBase.h" -#define DEFINE_WEAK_SELF __typeof(self) __weak weakSelf = self; - @interface PureLayoutPriorityTests : PureLayoutTestBase @end @implementation PureLayoutPriorityTests -- (void)setUp -{ - [super setUp]; - -} - -- (void)tearDown -{ - - [super tearDown]; -} - /** Returns an array of the default priorities to test. */ -- (NSArray *)defaultPriorities +- (PL__NSArray_of(NSNumber *) *)defaultPriorities { return @[@(ALLayoutPriorityFittingSizeLevel), @(ALLayoutPriorityDefaultHigh), @(ALLayoutPriorityRequired), @(ALLayoutPriorityDefaultLow)]; } @@ -40,7 +26,7 @@ - (NSArray *)defaultPriorities A helper method that takes a block containing a call to the PureLayout API which adds one constraint, and calls -[assertConstraint:isAddedWithPriority:] for each of the default priorities. */ -- (void)assertConstraintIsAddedWithDefaultPriorities:(NSLayoutConstraint *(^)())block +- (void)assertConstraintIsAddedWithDefaultPriorities:(NSLayoutConstraint *(^)(void))block { for (NSNumber *layoutPriority in [self defaultPriorities]) { [self assertConstraint:block isAddedWithPriority:[layoutPriority floatValue]]; @@ -51,7 +37,7 @@ - (void)assertConstraintIsAddedWithDefaultPriorities:(NSLayoutConstraint *(^)()) A helper method that takes a block containing one or more calls to the PureLayout API which add multiple constraints, and calls -[assertConstraints:areAddedWithPriority:] for each of the default priorities. */ -- (void)assertConstraintsAreAddedWithDefaultPriorities:(NSArray *(^)())block +- (void)assertConstraintsAreAddedWithDefaultPriorities:(NSArray *(^)(void))block { for (NSNumber *layoutPriority in [self defaultPriorities]) { [self assertConstraints:block areAddedWithPriority:[layoutPriority floatValue]]; @@ -60,23 +46,23 @@ - (void)assertConstraintsAreAddedWithDefaultPriorities:(NSArray *(^)())block /** A helper method that takes a block containing a call to the PureLayout API which adds one constraint, - and verifies that when the +[UIView autoSetPriority:forConstraints:] method is used, this one constraint is + and verifies that when the +[NSLayoutConstraint autoSetPriority:forConstraints:] method is used, this one constraint is added with the correct priority specified. */ -- (void)assertConstraint:(NSLayoutConstraint *(^)())block isAddedWithPriority:(ALLayoutPriority)priority +- (void)assertConstraint:(NSLayoutConstraint *(^)(void))block isAddedWithPriority:(ALLayoutPriority)priority { - [self assertConstraints:^NSArray *{ return @[block()]; } areAddedWithPriority:priority]; + [self assertConstraints:^PL__NSArray_of(NSLayoutConstraint *) *{ return @[block()]; } areAddedWithPriority:priority]; } /** A helper method that takes a block containing one or more calls to the PureLayout API which add multiple - constraints, and verifies that when the +[UIView autoSetPriority:forConstraints:] method is used, these - constraints are added with the correct priority specified. + constraints, and verifies that when the +[NSLayoutConstraint autoSetPriority:forConstraints:] method is used, + these constraints are added with the correct priority specified. */ -- (void)assertConstraints:(NSArray *(^)())block areAddedWithPriority:(ALLayoutPriority)priority +- (void)assertConstraints:(PL__NSArray_of(NSLayoutConstraint *) *(^)(void))block areAddedWithPriority:(ALLayoutPriority)priority { - __block NSArray *constraints; - [ALView autoSetPriority:priority forConstraints:^{ + __block PL__NSArray_of(NSLayoutConstraint *) *constraints; + [NSLayoutConstraint autoSetPriority:priority forConstraints:^{ constraints = block(); }]; XCTAssert([constraints count] > 0, @"The array of constraints should not be empty."); @@ -90,22 +76,20 @@ - (void)assertConstraints:(NSArray *(^)())block areAddedWithPriority:(ALLayoutPr */ - (void)testPriorityForCentering { - DEFINE_WEAK_SELF - - [self assertConstraintsAreAddedWithDefaultPriorities:^NSArray *{ - return [weakSelf.viewA autoCenterInSuperview]; + [self assertConstraintsAreAddedWithDefaultPriorities:^PL__NSArray_of(NSLayoutConstraint *) *{ + return [self.viewA autoCenterInSuperview]; }]; [self assertConstraintIsAddedWithDefaultPriorities:^NSLayoutConstraint *{ - return [weakSelf.viewB autoAlignAxisToSuperviewAxis:ALAxisHorizontal]; + return [self.viewB autoAlignAxisToSuperviewAxis:ALAxisHorizontal]; }]; [self assertConstraintIsAddedWithDefaultPriorities:^NSLayoutConstraint *{ - return [weakSelf.viewC autoAlignAxisToSuperviewAxis:ALAxisBaseline]; + return [self.viewC autoAlignAxisToSuperviewAxis:ALAxisBaseline]; }]; [self assertConstraintIsAddedWithDefaultPriorities:^NSLayoutConstraint *{ - return [weakSelf.viewC autoAlignAxisToSuperviewAxis:ALAxisVertical]; + return [self.viewC autoAlignAxisToSuperviewAxis:ALAxisVertical]; }]; } @@ -114,22 +98,20 @@ - (void)testPriorityForCentering */ - (void)testPriorityForPinningEdgesToSuperview { - DEFINE_WEAK_SELF - [self assertConstraintIsAddedWithDefaultPriorities:^NSLayoutConstraint *{ - return [weakSelf.viewA autoPinEdgeToSuperviewEdge:ALEdgeBottom withInset:15.0]; + return [self.viewA autoPinEdgeToSuperviewEdge:ALEdgeBottom withInset:15.0]; }]; [self assertConstraintIsAddedWithDefaultPriorities:^NSLayoutConstraint *{ - return [weakSelf.viewB autoPinEdgeToSuperviewEdge:ALEdgeRight withInset:0.0 relation:NSLayoutRelationGreaterThanOrEqual]; + return [self.viewB autoPinEdgeToSuperviewEdge:ALEdgeRight withInset:0.0 relation:NSLayoutRelationGreaterThanOrEqual]; }]; - [self assertConstraintsAreAddedWithDefaultPriorities:^NSArray *{ - return [weakSelf.viewC autoPinEdgesToSuperviewEdgesWithInsets:ALEdgeInsetsZero]; + [self assertConstraintsAreAddedWithDefaultPriorities:^PL__NSArray_of(NSLayoutConstraint *) *{ + return [self.viewC autoPinEdgesToSuperviewEdgesWithInsets:ALEdgeInsetsZero]; }]; - [self assertConstraintsAreAddedWithDefaultPriorities:^NSArray *{ - return [weakSelf.viewD autoPinEdgesToSuperviewEdgesWithInsets:ALEdgeInsetsMake(5.5, -50.0, 42.6, 860.9) excludingEdge:ALEdgeTrailing]; + [self assertConstraintsAreAddedWithDefaultPriorities:^PL__NSArray_of(NSLayoutConstraint *) *{ + return [self.viewD autoPinEdgesToSuperviewEdgesWithInsets:ALEdgeInsetsMake(5.5, -50.0, 42.6, 860.9) excludingEdge:ALEdgeTrailing]; }]; } @@ -138,18 +120,16 @@ - (void)testPriorityForPinningEdgesToSuperview */ - (void)testPriorityForPinningEdges { - DEFINE_WEAK_SELF - [self assertConstraintIsAddedWithDefaultPriorities:^NSLayoutConstraint *{ - return [weakSelf.viewA autoPinEdge:ALEdgeTop toEdge:ALEdgeBottom ofView:weakSelf.viewB]; + return [self.viewA autoPinEdge:ALEdgeTop toEdge:ALEdgeBottom ofView:self.viewB]; }]; [self assertConstraintIsAddedWithDefaultPriorities:^NSLayoutConstraint *{ - return [weakSelf.viewB autoPinEdge:ALEdgeTrailing toEdge:ALEdgeLeading ofView:weakSelf.viewC withOffset:-95.0]; + return [self.viewB autoPinEdge:ALEdgeTrailing toEdge:ALEdgeLeading ofView:self.viewC withOffset:-95.0]; }]; [self assertConstraintIsAddedWithDefaultPriorities:^NSLayoutConstraint *{ - return [weakSelf.viewC autoPinEdge:ALEdgeRight toEdge:ALEdgeBottom ofView:weakSelf.viewD withOffset:555.0]; + return [self.viewC autoPinEdge:ALEdgeRight toEdge:ALEdgeBottom ofView:self.viewD withOffset:555.0]; }]; } @@ -158,18 +138,16 @@ - (void)testPriorityForPinningEdges */ - (void)testPriorityForAligningAxes { - DEFINE_WEAK_SELF - [self assertConstraintIsAddedWithDefaultPriorities:^NSLayoutConstraint *{ - return [weakSelf.viewA autoAlignAxis:ALAxisHorizontal toSameAxisOfView:weakSelf.viewB]; + return [self.viewA autoAlignAxis:ALAxisHorizontal toSameAxisOfView:self.viewB]; }]; [self assertConstraintIsAddedWithDefaultPriorities:^NSLayoutConstraint *{ - return [weakSelf.viewC autoAlignAxis:ALAxisVertical toSameAxisOfView:weakSelf.viewD]; + return [self.viewC autoAlignAxis:ALAxisVertical toSameAxisOfView:self.viewD]; }]; [self assertConstraintIsAddedWithDefaultPriorities:^NSLayoutConstraint *{ - return [weakSelf.viewB autoAlignAxis:ALAxisBaseline toSameAxisOfView:weakSelf.viewA withOffset:-60.0]; + return [self.viewB autoAlignAxis:ALAxisBaseline toSameAxisOfView:self.viewA withOffset:-60.0]; }]; } @@ -178,18 +156,16 @@ - (void)testPriorityForAligningAxes */ - (void)testPriorityForMatchingDimensions { - DEFINE_WEAK_SELF - - [self assertConstraintsAreAddedWithDefaultPriorities:^NSArray *{ - return [weakSelf.viewA autoSetDimensionsToSize:CGSizeMake(90, 180)]; + [self assertConstraintsAreAddedWithDefaultPriorities:^PL__NSArray_of(NSLayoutConstraint *) *{ + return [self.viewA autoSetDimensionsToSize:CGSizeMake(90, 180)]; }]; [self assertConstraintIsAddedWithDefaultPriorities:^NSLayoutConstraint *{ - return [weakSelf.viewB autoSetDimension:ALDimensionHeight toSize:0.0]; + return [self.viewB autoSetDimension:ALDimensionHeight toSize:0.0]; }]; [self assertConstraintIsAddedWithDefaultPriorities:^NSLayoutConstraint *{ - return [weakSelf.viewC autoSetDimension:ALDimensionWidth toSize:5.0 relation:NSLayoutRelationLessThanOrEqual]; + return [self.viewC autoSetDimension:ALDimensionWidth toSize:5.0 relation:NSLayoutRelationLessThanOrEqual]; }]; } @@ -198,26 +174,24 @@ - (void)testPriorityForMatchingDimensions */ - (void)testPriorityForConstrainingAnyAttribute { - DEFINE_WEAK_SELF - [self assertConstraintIsAddedWithDefaultPriorities:^NSLayoutConstraint *{ - return [weakSelf.viewA autoConstrainAttribute:ALAttributeVertical toAttribute:ALAttributeBottom ofView:weakSelf.viewB]; + return [self.viewA autoConstrainAttribute:ALAttributeVertical toAttribute:ALAttributeBottom ofView:self.viewB]; }]; [self assertConstraintIsAddedWithDefaultPriorities:^NSLayoutConstraint *{ - return [weakSelf.viewA autoConstrainAttribute:ALAttributeRight toAttribute:ALAttributeHorizontal ofView:weakSelf.viewC withOffset:50.0]; + return [self.viewA autoConstrainAttribute:ALAttributeRight toAttribute:ALAttributeHorizontal ofView:self.viewC withOffset:50.0]; }]; [self assertConstraintIsAddedWithDefaultPriorities:^NSLayoutConstraint *{ - return [weakSelf.viewA autoConstrainAttribute:ALAttributeWidth toAttribute:ALAttributeHeight ofView:weakSelf.viewD withOffset:-100.0 relation:NSLayoutRelationLessThanOrEqual]; + return [self.viewA autoConstrainAttribute:ALAttributeWidth toAttribute:ALAttributeHeight ofView:self.viewD withOffset:-100.0 relation:NSLayoutRelationLessThanOrEqual]; }]; [self assertConstraintIsAddedWithDefaultPriorities:^NSLayoutConstraint *{ - return [weakSelf.viewD autoConstrainAttribute:ALAttributeBaseline toAttribute:ALAttributeTrailing ofView:weakSelf.viewA withMultiplier:-6.0]; + return [self.viewD autoConstrainAttribute:ALAttributeBaseline toAttribute:ALAttributeTrailing ofView:self.viewA withMultiplier:-6.0]; }]; [self assertConstraintIsAddedWithDefaultPriorities:^NSLayoutConstraint *{ - return [weakSelf.viewB autoConstrainAttribute:ALAttributeTop toAttribute:ALAttributeLeading ofView:weakSelf.viewA withMultiplier:0.45 relation:NSLayoutRelationGreaterThanOrEqual]; + return [self.viewB autoConstrainAttribute:ALAttributeTop toAttribute:ALAttributeLeading ofView:self.viewA withMultiplier:0.45 relation:NSLayoutRelationGreaterThanOrEqual]; }]; } @@ -226,22 +200,20 @@ - (void)testPriorityForConstrainingAnyAttribute */ - (void)testPriorityForConstrainingMultipleViews { - DEFINE_WEAK_SELF - - [self assertConstraintsAreAddedWithDefaultPriorities:^NSArray *{ - return [weakSelf.viewArray autoAlignViewsToEdge:ALEdgeBottom]; + [self assertConstraintsAreAddedWithDefaultPriorities:^PL__NSArray_of(NSLayoutConstraint *) *{ + return [self.viewArray autoAlignViewsToEdge:ALEdgeBottom]; }]; - [self assertConstraintsAreAddedWithDefaultPriorities:^NSArray *{ - return [weakSelf.viewArray autoAlignViewsToAxis:ALAxisVertical]; + [self assertConstraintsAreAddedWithDefaultPriorities:^PL__NSArray_of(NSLayoutConstraint *) *{ + return [self.viewArray autoAlignViewsToAxis:ALAxisVertical]; }]; - [self assertConstraintsAreAddedWithDefaultPriorities:^NSArray *{ - return [weakSelf.viewArray autoMatchViewsDimension:ALDimensionWidth]; + [self assertConstraintsAreAddedWithDefaultPriorities:^PL__NSArray_of(NSLayoutConstraint *) *{ + return [self.viewArray autoMatchViewsDimension:ALDimensionWidth]; }]; - [self assertConstraintsAreAddedWithDefaultPriorities:^NSArray *{ - return [weakSelf.viewArray autoSetViewsDimension:ALDimensionHeight toSize:10.0]; + [self assertConstraintsAreAddedWithDefaultPriorities:^PL__NSArray_of(NSLayoutConstraint *) *{ + return [self.viewArray autoSetViewsDimension:ALDimensionHeight toSize:10.0]; }]; } @@ -250,22 +222,20 @@ - (void)testPriorityForConstrainingMultipleViews */ - (void)testPriorityForDistributingMultipleViews { - DEFINE_WEAK_SELF - - [self assertConstraintsAreAddedWithDefaultPriorities:^NSArray *{ - return [weakSelf.viewArray autoDistributeViewsAlongAxis:ALAxisHorizontal alignedTo:ALAttributeBottom withFixedSize:25.0]; + [self assertConstraintsAreAddedWithDefaultPriorities:^PL__NSArray_of(NSLayoutConstraint *) *{ + return [self.viewArray autoDistributeViewsAlongAxis:ALAxisHorizontal alignedTo:ALAttributeBottom withFixedSize:25.0]; }]; - [self assertConstraintsAreAddedWithDefaultPriorities:^NSArray *{ - return [weakSelf.viewArray autoDistributeViewsAlongAxis:ALAxisVertical alignedTo:ALAttributeRight withFixedSize:5.0 insetSpacing:NO]; + [self assertConstraintsAreAddedWithDefaultPriorities:^PL__NSArray_of(NSLayoutConstraint *) *{ + return [self.viewArray autoDistributeViewsAlongAxis:ALAxisVertical alignedTo:ALAttributeRight withFixedSize:5.0 insetSpacing:NO]; }]; - [self assertConstraintsAreAddedWithDefaultPriorities:^NSArray *{ - return [weakSelf.viewArray autoDistributeViewsAlongAxis:ALAxisVertical alignedTo:ALAttributeLeading withFixedSpacing:0.0]; + [self assertConstraintsAreAddedWithDefaultPriorities:^PL__NSArray_of(NSLayoutConstraint *) *{ + return [self.viewArray autoDistributeViewsAlongAxis:ALAxisVertical alignedTo:ALAttributeLeading withFixedSpacing:0.0]; }]; - [self assertConstraintsAreAddedWithDefaultPriorities:^NSArray *{ - return [weakSelf.viewArray autoDistributeViewsAlongAxis:ALAxisHorizontal alignedTo:ALAttributeHorizontal withFixedSpacing:899.5 insetSpacing:NO]; + [self assertConstraintsAreAddedWithDefaultPriorities:^PL__NSArray_of(NSLayoutConstraint *) *{ + return [self.viewArray autoDistributeViewsAlongAxis:ALAxisHorizontal alignedTo:ALAttributeHorizontal withFixedSpacing:899.5 insetSpacing:NO]; }]; } @@ -274,21 +244,19 @@ - (void)testPriorityForDistributingMultipleViews */ - (void)testNestingPriorityConstraintBlocks { - DEFINE_WEAK_SELF - - NSLayoutConstraint *constraint0 = [weakSelf.viewD autoAlignAxisToSuperviewAxis:ALAxisVertical]; + NSLayoutConstraint *constraint0 = [self.viewD autoAlignAxisToSuperviewAxis:ALAxisVertical]; XCTAssertEqual(constraint0.priority, ALLayoutPriorityRequired); - [ALView autoSetPriority:ALLayoutPriorityDefaultLow forConstraints:^{ - NSLayoutConstraint *constraint1 = [weakSelf.viewA autoAlignAxisToSuperviewAxis:ALAxisVertical]; + [NSLayoutConstraint autoSetPriority:ALLayoutPriorityDefaultLow forConstraints:^{ + NSLayoutConstraint *constraint1 = [self.viewA autoAlignAxisToSuperviewAxis:ALAxisVertical]; XCTAssertEqual(constraint1.priority, ALLayoutPriorityDefaultLow); - [ALView autoSetPriority:ALLayoutPriorityDefaultHigh forConstraints:^{ - NSLayoutConstraint *constraint2 = [weakSelf.viewB autoAlignAxisToSuperviewAxis:ALAxisVertical]; + [NSLayoutConstraint autoSetPriority:ALLayoutPriorityDefaultHigh forConstraints:^{ + NSLayoutConstraint *constraint2 = [self.viewB autoAlignAxisToSuperviewAxis:ALAxisVertical]; XCTAssertEqual(constraint2.priority, ALLayoutPriorityDefaultHigh); }]; - NSLayoutConstraint *constraint3 = [weakSelf.viewC autoAlignAxisToSuperviewAxis:ALAxisVertical]; + NSLayoutConstraint *constraint3 = [self.viewC autoAlignAxisToSuperviewAxis:ALAxisVertical]; XCTAssertEqual(constraint3.priority, ALLayoutPriorityDefaultLow); }]; - NSLayoutConstraint *constraint4 = [weakSelf.viewD autoAlignAxisToSuperviewAxis:ALAxisHorizontal]; + NSLayoutConstraint *constraint4 = [self.viewD autoAlignAxisToSuperviewAxis:ALAxisHorizontal]; XCTAssertEqual(constraint4.priority, ALLayoutPriorityRequired); } @@ -297,26 +265,24 @@ - (void)testNestingPriorityConstraintBlocks */ - (void)testInstallingConstraintsOutsidePriorityBlock { - DEFINE_WEAK_SELF - - __block NSLayoutConstraint *constraint0; - [ALView autoCreateConstraintsWithoutInstalling:^{ - constraint0 = [weakSelf.viewD autoAlignAxisToSuperviewAxis:ALAxisVertical]; + __block NSLayoutConstraint *constraint; + [NSLayoutConstraint autoCreateConstraintsWithoutInstalling:^{ + constraint = [self.viewD autoAlignAxisToSuperviewAxis:ALAxisVertical]; }]; - XCTAssertEqual(constraint0.priority, ALLayoutPriorityRequired); - constraint0.priority = ALLayoutPriorityDefaultLow; - XCTAssertEqual(constraint0.priority, ALLayoutPriorityDefaultLow); + XCTAssertEqual(constraint.priority, ALLayoutPriorityRequired); + constraint.priority = ALLayoutPriorityDefaultLow; + XCTAssertEqual(constraint.priority, ALLayoutPriorityDefaultLow); // Install the constraint and check that its priority was not affected - [constraint0 autoInstall]; - XCTAssertEqual(constraint0.priority, ALLayoutPriorityDefaultLow); + [constraint autoInstall]; + XCTAssertEqual(constraint.priority, ALLayoutPriorityDefaultLow); // Remove the constraint, then re-add it but this time inside of a constraints block - [constraint0 autoRemove]; - XCTAssertEqual(constraint0.priority, ALLayoutPriorityDefaultLow); - [ALView autoSetPriority:ALLayoutPriorityDefaultHigh forConstraints:^{ - [constraint0 autoInstall]; - XCTAssertEqual(constraint0.priority, ALLayoutPriorityDefaultHigh); + [constraint autoRemove]; + XCTAssertEqual(constraint.priority, ALLayoutPriorityDefaultLow); + [NSLayoutConstraint autoSetPriority:ALLayoutPriorityDefaultHigh forConstraints:^{ + [constraint autoInstall]; + XCTAssertEqual(constraint.priority, ALLayoutPriorityDefaultHigh); }]; } diff --git a/PureLayout/PureLayoutTests/PureLayoutRemovalTests.m b/PureLayout/PureLayoutTests/PureLayoutRemovalTests.m index 469acd0..50cecae 100644 --- a/PureLayout/PureLayoutTests/PureLayoutRemovalTests.m +++ b/PureLayout/PureLayoutTests/PureLayoutRemovalTests.m @@ -2,8 +2,8 @@ // PureLayoutRemovalTests.m // PureLayout Tests // -// Copyright (c) 2014 Tyler Fox -// https://github.com/smileyborg/PureLayout +// Copyright (c) 2014-2015 Tyler Fox +// https://github.com/PureLayout/PureLayout // #import "PureLayoutTestBase.h" @@ -14,18 +14,6 @@ @interface PureLayoutRemovalTests : PureLayoutTestBase @implementation PureLayoutRemovalTests -- (void)setUp -{ - [super setUp]; - -} - -- (void)tearDown -{ - - [super tearDown]; -} - /** Test the +[removeConstraint:] method on UIView. Test the case where we're removing a constraint that was added to the closest common superview of the two views it @@ -41,15 +29,10 @@ - (void)testRemoveConstraint [self.viewA.superview.constraints[0] autoRemove]; NSUInteger newConstraintsCount = [self.viewA.superview.constraints count]; XCTAssert(constraintsCount - newConstraintsCount == 1, @"viewA's superview should have one less constraint on it."); - - [self.viewB removeFromSuperview]; - [self.viewA addSubview:self.viewB]; - - [self.viewB autoCenterInSuperview]; } /** - Test the +[removeConstraint:] method on UIView. + Test the -[autoRemove] method on NSLayoutConstraint. Test the case where we're removing a constraint that only applies to one view. */ - (void)testRemoveConstraintFromSingleView @@ -65,7 +48,7 @@ - (void)testRemoveConstraintFromSingleView } /** - Test the +[removeConstraint:] method on UIView. + Test the -[autoRemove] method on NSLayoutConstraint. Test the case where we're removing a constraint that was added to a view that is not the closest common superview of the two views it constrains. */ @@ -89,11 +72,11 @@ - (void)testRemoveConstraintFromNotImmediateSuperview } /** - Test the +[removeConstraints:] method on UIView. + Test the -[autoRemoveConstraints] method on NSArray. */ - (void)testRemoveConstraints { - NSArray *constraints = [@[self.viewA, self.viewB, self.viewC, self.viewD] autoDistributeViewsAlongAxis:ALAxisHorizontal alignedTo:ALAttributeHorizontal withFixedSize:10.0]; + PL__NSArray_of(NSLayoutConstraint *) *constraints = [@[self.viewA, self.viewB, self.viewC, self.viewD] autoDistributeViewsAlongAxis:ALAxisHorizontal alignedTo:ALAttributeHorizontal withFixedSize:10.0]; NSUInteger constraintsCount = [self.containerView.constraints count]; XCTAssert(constraintsCount > 0, @"containerView should have constraints added to it."); diff --git a/PureLayout/PureLayoutTests/PureLayoutTestBase.h b/PureLayout/PureLayoutTests/PureLayoutTestBase.h index 5729ac2..fb975c0 100644 --- a/PureLayout/PureLayoutTests/PureLayoutTestBase.h +++ b/PureLayout/PureLayoutTests/PureLayoutTestBase.h @@ -2,8 +2,8 @@ // PureLayoutTestBase.h // PureLayout Tests // -// Copyright (c) 2014 Tyler Fox -// https://github.com/smileyborg/PureLayout +// Copyright (c) 2014-2015 Tyler Fox +// https://github.com/PureLayout/PureLayout // #import @@ -12,17 +12,13 @@ #if TARGET_OS_IPHONE - - #define VALUES(iOS, OSX) (iOS) // a macro that takes a value for each platform, and substitutes the value for the current platform - #define ALLabel UILabel - #define ALImageView UIImageView - +# define VALUES(iOS, OSX) (iOS) // a macro that takes a value for each platform, and substitutes the value for the current platform +# define ALLabel UILabel +# define ALImageView UIImageView #else - - #define VALUES(iOS, OSX) (OSX) // a macro that takes a value for each platform, and substitutes the value for the current platform - #define ALLabel NSTextView - #define ALImageView NSImageView - +# define VALUES(iOS, OSX) (OSX) // a macro that takes a value for each platform, and substitutes the value for the current platform +# define ALLabel NSTextView +# define ALImageView NSImageView #endif /* TARGET_OS_IPHONE */ @@ -51,7 +47,7 @@ static const CGFloat kContainerViewHeight = 1000.0; @interface PureLayoutTestBase : XCTestCase // An array of viewA, viewB, viewC, and viewD -@property (nonatomic, readonly) NSArray *viewArray; +@property (nonatomic, readonly) PL__NSArray_of(ALView *) *viewArray; // The indendentation below represents how the view hierarchy is set up @property (nonatomic, strong) ALView *containerView; @@ -66,6 +62,11 @@ static const CGFloat kContainerViewHeight = 1000.0; @property (nonatomic, strong) ALView * viewC; @property (nonatomic, strong) ALView * viewD; +/** Sets up the default view hierarchy for tests. Test subclasses may override this method to customize the view hierarchy set up. */ +- (void)setupViewHierarchy; +/** Test subclasses should override this method with updated tests if the -[setupViewHierarchy] method is overridden. */ +- (void)testViewHierarchy; + /** Forces the container view to immediately do a layout pass, which will evaluate the constraints and set the frames for the container view and subviews. */ - (void)evaluateConstraints; diff --git a/PureLayout/PureLayoutTests/PureLayoutTestBase.m b/PureLayout/PureLayoutTests/PureLayoutTestBase.m index 1ee83f2..3934930 100644 --- a/PureLayout/PureLayoutTests/PureLayoutTestBase.m +++ b/PureLayout/PureLayoutTests/PureLayoutTestBase.m @@ -2,15 +2,15 @@ // PureLayoutTestBase.m // PureLayout Tests // -// Copyright (c) 2014 Tyler Fox -// https://github.com/smileyborg/PureLayout +// Copyright (c) 2014-2015 Tyler Fox +// https://github.com/PureLayout/PureLayout // #import "PureLayoutTestBase.h" @implementation PureLayoutTestBase -- (NSArray *)viewArray +- (PL__NSArray_of(ALView *) *)viewArray { return @[self.viewA, self.viewB, self.viewC, self.viewD]; } @@ -20,6 +20,15 @@ - (void)setUp [super setUp]; self.containerView = [[ALView alloc] initWithFrame:CGRectMake(0.0, 0.0, kContainerViewWidth, kContainerViewHeight)]; + + [self setupViewHierarchy]; +} + +/** + Sets up the default view hierarchy for tests. Test subclasses may override this method to customize the view hierarchy set up. + */ +- (void)setupViewHierarchy +{ self.viewA = [ALView newAutoLayoutView]; self.viewA_A = [ALView newAutoLayoutView]; self.viewA_A_A = [ALView newAutoLayoutView]; @@ -43,10 +52,22 @@ - (void)setUp [self.containerView addSubview:self.viewD]; } -- (void)tearDown +/** + Test the default view hierarchy to make sure it is correctly established. + */ +- (void)testViewHierarchy { - - [super tearDown]; + XCTAssertNotNil(self.containerView, @"View hierarchy is not setup as expected."); + XCTAssert(self.viewA.superview == self.containerView, @"View hierarchy is not setup as expected."); + XCTAssert(self.viewA_A.superview == self.viewA, @"View hierarchy is not setup as expected."); + XCTAssert(self.viewA_A_A.superview == self.viewA_A, @"View hierarchy is not setup as expected."); + XCTAssert(self.viewA_A_B.superview == self.viewA_A, @"View hierarchy is not setup as expected."); + XCTAssert(self.viewA_B.superview == self.viewA, @"View hierarchy is not setup as expected."); + XCTAssert(self.viewA_B_A.superview == self.viewA_B, @"View hierarchy is not setup as expected."); + XCTAssert(self.viewB.superview == self.containerView, @"View hierarchy is not setup as expected."); + XCTAssert(self.viewB_A.superview == self.viewB, @"View hierarchy is not setup as expected."); + XCTAssert(self.viewC.superview == self.containerView, @"View hierarchy is not setup as expected."); + XCTAssert(self.viewD.superview == self.containerView, @"View hierarchy is not setup as expected."); } /** @@ -74,22 +95,4 @@ - (void)evaluateConstraintsForView:(ALView *)view #endif /* TARGET_OS_IPHONE */ } -/** - Test the view hierarchy to make sure it is correctly established. - */ -- (void)testViewHierarchy -{ - XCTAssertNotNil(self.containerView, @"View hierarchy is not setup as expected."); - XCTAssert(self.viewA.superview == self.containerView, @"View hierarchy is not setup as expected."); - XCTAssert(self.viewA_A.superview == self.viewA, @"View hierarchy is not setup as expected."); - XCTAssert(self.viewA_A_A.superview == self.viewA_A, @"View hierarchy is not setup as expected."); - XCTAssert(self.viewA_A_B.superview == self.viewA_A, @"View hierarchy is not setup as expected."); - XCTAssert(self.viewA_B.superview == self.viewA, @"View hierarchy is not setup as expected."); - XCTAssert(self.viewA_B_A.superview == self.viewA_B, @"View hierarchy is not setup as expected."); - XCTAssert(self.viewB.superview == self.containerView, @"View hierarchy is not setup as expected."); - XCTAssert(self.viewB_A.superview == self.viewB, @"View hierarchy is not setup as expected."); - XCTAssert(self.viewC.superview == self.containerView, @"View hierarchy is not setup as expected."); - XCTAssert(self.viewD.superview == self.containerView, @"View hierarchy is not setup as expected."); -} - @end diff --git a/PureLayout/PureLayoutTests/PureLayoutTests-Mac/PureLayoutTests-Mac-Info.plist b/PureLayout/PureLayoutTests/PureLayoutTests-Mac/PureLayoutTests-Mac-Info.plist index 1dde7a2..169b6f7 100644 --- a/PureLayout/PureLayoutTests/PureLayoutTests-Mac/PureLayoutTests-Mac-Info.plist +++ b/PureLayout/PureLayoutTests/PureLayoutTests-Mac/PureLayoutTests-Mac-Info.plist @@ -7,7 +7,7 @@ CFBundleExecutable ${EXECUTABLE_NAME} CFBundleIdentifier - com.smileyborg.${PRODUCT_NAME:rfc1034identifier} + $(PRODUCT_BUNDLE_IDENTIFIER) CFBundleInfoDictionaryVersion 6.0 CFBundlePackageType diff --git a/PureLayout/PureLayoutTests/PureLayoutTests-iOS/PureLayoutPriorityTests-iOS.m b/PureLayout/PureLayoutTests/PureLayoutTests-iOS/PureLayoutPriorityTests-iOS.m index e2937ec..3876897 100644 --- a/PureLayout/PureLayoutTests/PureLayoutTests-iOS/PureLayoutPriorityTests-iOS.m +++ b/PureLayout/PureLayoutTests/PureLayoutTests-iOS/PureLayoutPriorityTests-iOS.m @@ -2,14 +2,12 @@ // PureLayoutPriorityTests-iOS.m // PureLayout Tests // -// Copyright (c) 2014 Tyler Fox -// https://github.com/smileyborg/PureLayout +// Copyright (c) 2014-2015 Tyler Fox +// https://github.com/PureLayout/PureLayout // #import "PureLayoutTestBase.h" -#define DEFINE_WEAK_SELF __typeof(self) __weak weakSelf = self; - @interface PureLayoutPriorityTestsiOS : PureLayoutTestBase @property (nonatomic, strong) UIWindow *window; @@ -33,7 +31,7 @@ - (void)tearDown /** Returns an array of the default priorities to test. */ -- (NSArray *)defaultPriorities +- (PL__NSArray_of(NSNumber *) *)defaultPriorities { return @[@(ALLayoutPriorityFittingSizeLevel), @(ALLayoutPriorityDefaultHigh), @(ALLayoutPriorityRequired), @(ALLayoutPriorityDefaultLow)]; } @@ -42,7 +40,7 @@ - (NSArray *)defaultPriorities A helper method that takes a block containing a call to the PureLayout API which adds one constraint, and calls -[assertConstraint:isAddedWithPriority:] for each of the default priorities. */ -- (void)assertConstraintIsAddedWithDefaultPriorities:(NSLayoutConstraint *(^)())block +- (void)assertConstraintIsAddedWithDefaultPriorities:(NSLayoutConstraint *(^)(void))block { for (NSNumber *layoutPriority in [self defaultPriorities]) { [self assertConstraint:block isAddedWithPriority:[layoutPriority floatValue]]; @@ -53,7 +51,7 @@ - (void)assertConstraintIsAddedWithDefaultPriorities:(NSLayoutConstraint *(^)()) A helper method that takes a block containing one or more calls to the PureLayout API which add multiple constraints, and calls -[assertConstraints:areAddedWithPriority:] for each of the default priorities. */ -- (void)assertConstraintsAreAddedWithDefaultPriorities:(NSArray *(^)())block +- (void)assertConstraintsAreAddedWithDefaultPriorities:(PL__NSArray_of(NSLayoutConstraint *) *(^)(void))block { for (NSNumber *layoutPriority in [self defaultPriorities]) { [self assertConstraints:block areAddedWithPriority:[layoutPriority floatValue]]; @@ -62,23 +60,23 @@ - (void)assertConstraintsAreAddedWithDefaultPriorities:(NSArray *(^)())block /** A helper method that takes a block containing a call to the PureLayout API which adds one constraint, - and verifies that when the +[UIView autoSetPriority:forConstraints:] method is used, this one constraint is + and verifies that when the +[NSLayoutConstraint autoSetPriority:forConstraints:] method is used, this one constraint is added with the correct priority specified. */ -- (void)assertConstraint:(NSLayoutConstraint *(^)())block isAddedWithPriority:(ALLayoutPriority)priority +- (void)assertConstraint:(NSLayoutConstraint *(^)(void))block isAddedWithPriority:(ALLayoutPriority)priority { - [self assertConstraints:^NSArray *{ return @[block()]; } areAddedWithPriority:priority]; + [self assertConstraints:^PL__NSArray_of(NSLayoutConstraint *) *{ return @[block()]; } areAddedWithPriority:priority]; } /** A helper method that takes a block containing one or more calls to the PureLayout API which add multiple - constraints, and verifies that when the +[UIView autoSetPriority:forConstraints:] method is used, these - constraints are added with the correct priority specified. + constraints, and verifies that when the +[NSLayoutConstraint autoSetPriority:forConstraints:] method is used, + these constraints are added with the correct priority specified. */ -- (void)assertConstraints:(NSArray *(^)())block areAddedWithPriority:(ALLayoutPriority)priority +- (void)assertConstraints:(PL__NSArray_of(NSLayoutConstraint *) *(^)(void))block areAddedWithPriority:(ALLayoutPriority)priority { - __block NSArray *constraints; - [ALView autoSetPriority:priority forConstraints:^{ + __block PL__NSArray_of(NSLayoutConstraint *) *constraints; + [NSLayoutConstraint autoSetPriority:priority forConstraints:^{ constraints = block(); }]; XCTAssert([constraints count] > 0, @"The array of constraints should not be empty."); @@ -95,54 +93,52 @@ - (void)testPriorityForContentCompressionResistanceAndContentHugging ALLabel *labelA = [ALLabel newAutoLayoutView]; // use ALLabel since it will have all 4 implicit constraints generated labelA.text = @"Some text."; - [ALView autoSetPriority:ALLayoutPriorityRequired forConstraints:^{ + [NSLayoutConstraint autoSetPriority:ALLayoutPriorityRequired forConstraints:^{ [labelA autoSetContentCompressionResistancePriorityForAxis:ALAxisHorizontal]; }]; - XCTAssert([labelA contentCompressionResistancePriorityForAxis:UILayoutConstraintAxisHorizontal] == ALLayoutPriorityRequired, @"The constraint priority should be equal to the one specified for the constraints block."); + XCTAssert([labelA contentCompressionResistancePriorityForAxis:ALLayoutConstraintAxisHorizontal] == ALLayoutPriorityRequired, @"The constraint priority should be equal to the one specified for the constraints block."); - [ALView autoSetPriority:ALLayoutPriorityFittingSizeLevel + 1 forConstraints:^{ + [NSLayoutConstraint autoSetPriority:ALLayoutPriorityFittingSizeLevel + 1 forConstraints:^{ [labelA autoSetContentCompressionResistancePriorityForAxis:ALAxisVertical]; }]; - XCTAssert([labelA contentCompressionResistancePriorityForAxis:UILayoutConstraintAxisVertical] == ALLayoutPriorityFittingSizeLevel + 1, @"The constraint priority should be equal to the one specified for the constraints block."); + XCTAssert([labelA contentCompressionResistancePriorityForAxis:ALLayoutConstraintAxisVertical] == ALLayoutPriorityFittingSizeLevel + 1, @"The constraint priority should be equal to the one specified for the constraints block."); - [ALView autoSetPriority:ALLayoutPriorityRequired forConstraints:^{ + [NSLayoutConstraint autoSetPriority:ALLayoutPriorityRequired forConstraints:^{ [labelA autoSetContentHuggingPriorityForAxis:ALAxisHorizontal]; }]; XCTAssert([labelA contentHuggingPriorityForAxis:ALLayoutConstraintAxisHorizontal] == ALLayoutPriorityRequired, @"The constraint priority should be equal to the one specified for the constraints block."); - [ALView autoSetPriority:ALLayoutPriorityDefaultHigh - 1 forConstraints:^{ + [NSLayoutConstraint autoSetPriority:ALLayoutPriorityDefaultHigh - 1 forConstraints:^{ [labelA autoSetContentHuggingPriorityForAxis:ALAxisVertical]; }]; - XCTAssert([labelA contentHuggingPriorityForAxis:UILayoutConstraintAxisVertical] == ALLayoutPriorityDefaultHigh - 1, @"The constraint priority should be equal to the one specified for the constraints block."); + XCTAssert([labelA contentHuggingPriorityForAxis:ALLayoutConstraintAxisVertical] == ALLayoutPriorityDefaultHigh - 1, @"The constraint priority should be equal to the one specified for the constraints block."); } /** Test setting the priority of constraints that pin views to the view controller layout guides. */ -- (void)testPriorityForPinningToLayoutGuides -{ - DEFINE_WEAK_SELF - - UIViewController *viewController = [[UIViewController alloc] initWithNibName:nil bundle:nil]; - self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]]; - self.window.rootViewController = viewController; - [self.window makeKeyAndVisible]; - - // Wait until the next run loop to run the actual tests, after the window & view controller have a chance to - // get into a state where the view hierarchy is prepared to accept constraints to the layout guides - dispatch_async(dispatch_get_main_queue(), ^{ - [self assertConstraintIsAddedWithDefaultPriorities:^NSLayoutConstraint *{ - return [weakSelf.viewA autoPinToTopLayoutGuideOfViewController:viewController withInset:50.0]; - }]; - - [self assertConstraintIsAddedWithDefaultPriorities:^NSLayoutConstraint *{ - return [weakSelf.viewA autoPinToTopLayoutGuideOfViewController:viewController withInset:0.0]; - }]; - - [self assertConstraintIsAddedWithDefaultPriorities:^NSLayoutConstraint *{ - return [weakSelf.viewA autoPinToBottomLayoutGuideOfViewController:viewController withInset:-5.0]; - }]; - }); -} +//- (void)testPriorityForPinningToLayoutGuides +//{ +// UIViewController *viewController = [[UIViewController alloc] initWithNibName:nil bundle:nil]; +// self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]]; +// self.window.rootViewController = viewController; +// [self.window makeKeyAndVisible]; +// +// // Wait until the next run loop to run the actual tests, after the window & view controller have a chance to +// // get into a state where the view hierarchy is prepared to accept constraints to the layout guides +// dispatch_async(dispatch_get_main_queue(), ^{ +// [self assertConstraintIsAddedWithDefaultPriorities:^NSLayoutConstraint *{ +// return [self.viewA autoPinToTopLayoutGuideOfViewController:viewController withInset:50.0]; +// }]; +// +// [self assertConstraintIsAddedWithDefaultPriorities:^NSLayoutConstraint *{ +// return [self.viewA autoPinToTopLayoutGuideOfViewController:viewController withInset:0.0]; +// }]; +// +// [self assertConstraintIsAddedWithDefaultPriorities:^NSLayoutConstraint *{ +// return [self.viewA autoPinToBottomLayoutGuideOfViewController:viewController withInset:-5.0]; +// }]; +// }); +//} @end diff --git a/PureLayout/PureLayoutTests/PureLayoutTests-iOS/PureLayoutTests-iOS-Info.plist b/PureLayout/PureLayoutTests/PureLayoutTests-iOS/PureLayoutTests-iOS-Info.plist index 1dde7a2..169b6f7 100644 --- a/PureLayout/PureLayoutTests/PureLayoutTests-iOS/PureLayoutTests-iOS-Info.plist +++ b/PureLayout/PureLayoutTests/PureLayoutTests-iOS/PureLayoutTests-iOS-Info.plist @@ -7,7 +7,7 @@ CFBundleExecutable ${EXECUTABLE_NAME} CFBundleIdentifier - com.smileyborg.${PRODUCT_NAME:rfc1034identifier} + $(PRODUCT_BUNDLE_IDENTIFIER) CFBundleInfoDictionaryVersion 6.0 CFBundlePackageType diff --git a/PureLayout/PureLayout Frameworks/PureLayout_iOS/Info.plist b/PureLayout/Supporting Files/PureLayout_Mac/Info.plist similarity index 89% rename from PureLayout/PureLayout Frameworks/PureLayout_iOS/Info.plist rename to PureLayout/Supporting Files/PureLayout_Mac/Info.plist index 8d44ad9..19c1e8d 100644 --- a/PureLayout/PureLayout Frameworks/PureLayout_iOS/Info.plist +++ b/PureLayout/Supporting Files/PureLayout_Mac/Info.plist @@ -7,7 +7,7 @@ CFBundleExecutable $(EXECUTABLE_NAME) CFBundleIdentifier - com.smileyborg.$(PRODUCT_NAME:rfc1034identifier) + $(PRODUCT_BUNDLE_IDENTIFIER) CFBundleInfoDictionaryVersion 6.0 CFBundleName @@ -15,7 +15,7 @@ CFBundlePackageType FMWK CFBundleShortVersionString - 1.0 + 3.1 CFBundleSignature ???? CFBundleVersion diff --git a/PureLayout/PureLayout Frameworks/PureLayout_Mac/Info.plist b/PureLayout/Supporting Files/PureLayout_iOS/Info.plist similarity index 89% rename from PureLayout/PureLayout Frameworks/PureLayout_Mac/Info.plist rename to PureLayout/Supporting Files/PureLayout_iOS/Info.plist index 8d44ad9..19c1e8d 100644 --- a/PureLayout/PureLayout Frameworks/PureLayout_Mac/Info.plist +++ b/PureLayout/Supporting Files/PureLayout_iOS/Info.plist @@ -7,7 +7,7 @@ CFBundleExecutable $(EXECUTABLE_NAME) CFBundleIdentifier - com.smileyborg.$(PRODUCT_NAME:rfc1034identifier) + $(PRODUCT_BUNDLE_IDENTIFIER) CFBundleInfoDictionaryVersion 6.0 CFBundleName @@ -15,7 +15,7 @@ CFBundlePackageType FMWK CFBundleShortVersionString - 1.0 + 3.1 CFBundleSignature ???? CFBundleVersion diff --git a/PureLayout/Supporting Files/PureLayout_tvOS/Info.plist b/PureLayout/Supporting Files/PureLayout_tvOS/Info.plist new file mode 100644 index 0000000..19c1e8d --- /dev/null +++ b/PureLayout/Supporting Files/PureLayout_tvOS/Info.plist @@ -0,0 +1,26 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + FMWK + CFBundleShortVersionString + 3.1 + CFBundleSignature + ???? + CFBundleVersion + $(CURRENT_PROJECT_VERSION) + NSPrincipalClass + + + diff --git a/README.md b/README.md index d55bce3..4638d03 100644 --- a/README.md +++ b/README.md @@ -1,16 +1,87 @@ -# [![PureLayout](https://github.com/smileyborg/PureLayout/blob/master/Images/PureLayout.png?raw=true)](#) -[![Build Status](http://img.shields.io/travis/smileyborg/PureLayout.svg?style=flat)](https://travis-ci.org/smileyborg/PureLayout) [![Version](http://img.shields.io/cocoapods/v/PureLayout.svg?style=flat)](http://cocoapods.org/?q=PureLayout) [![Platform](http://img.shields.io/cocoapods/p/PureLayout.svg?style=flat)](http://cocoapods.org/?q=PureLayout) [![License](http://img.shields.io/cocoapods/l/PureLayout.svg?style=flat)](LICENSE) +# [![PureLayout](https://github.com/PureLayout/PureLayout/blob/master/Images/PureLayout.png?raw=true)](#) +[![Build Status](https://travis-ci.org/PureLayout/PureLayout.svg?branch=master)](https://travis-ci.org/PureLayout/PureLayout) [![Version](http://img.shields.io/cocoapods/v/PureLayout.svg?style=flat)](http://cocoapods.org/pods/PureLayout) [![Platform](http://img.shields.io/cocoapods/p/PureLayout.svg?style=flat)](http://cocoapods.org/pods/PureLayout) [![License](http://img.shields.io/cocoapods/l/PureLayout.svg?style=flat)](LICENSE) -The ultimate API for iOS & OS X Auto Layout — impressively simple, immensely powerful. PureLayout extends `UIView`/`NSView`, `NSArray`, and `NSLayoutConstraint` with a comprehensive Auto Layout API that is modeled after Apple's own frameworks. PureLayout is an Objective-C library that also works (and looks!) great with Swift using a bridging header. +The ultimate API for iOS & OS X Auto Layout — impressively simple, immensely powerful. PureLayout extends `UIView`/`NSView`, `NSArray`, and `NSLayoutConstraint` with a comprehensive Auto Layout API that is modeled after Apple's own frameworks. PureLayout is a cross-platform Objective-C library that works (and looks!) great in Swift. It is fully backwards-compatible with all versions of iOS and OS X that support Auto Layout. Writing Auto Layout code from scratch isn't easy. PureLayout provides a fully capable and developer-friendly interface for Auto Layout. It is designed for clarity and simplicity, and takes inspiration from the AutoLayout UI options available in Interface Builder while delivering far more flexibility. The API is also highly efficient, as it adds only a thin layer of third party code and is engineered for maximum performance. +### Table of Contents + 1. [Setup](#setup) + 1. [API Cheat Sheet](#api-cheat-sheet) + 1. [Usage](#usage) + * [Sample Code](#sample-code-swift) + * [Example Apps](#example-apps) + 1. [PureLayout vs. the rest](#purelayout-vs-the-rest) + 1. [Problems, Suggestions, Pull Requests?](#problems-suggestions-pull-requests) + +## Setup +### Compatibility +The current release of PureLayout supports all versions of iOS and OS X since the introduction of Auto Layout on each platform, in both Swift and Objective-C, with a single codebase! + +* Xcode + * Language Support: **Swift** *(any version)*, **Objective-C** + * Fully Compatible With: **Xcode 7.0** + * Minimum Supported Version: **Xcode 5.0** +* iOS + * Fully Compatible With: **iOS 9.0** + * Minimum Deployment Target: **iOS 6.0** +* OS X + * Fully Compatible With: **OS X 10.11** + * Minimum Deployment Target: **OS X 10.7** + +### Using [CocoaPods](http://cocoapods.org) +1. Add the pod `PureLayout` to your [Podfile](http://guides.cocoapods.org/using/the-podfile.html). + + ```ruby + pod 'PureLayout' + ``` + +1. Run `pod install` from Terminal, then open your app's `.xcworkspace` file to launch Xcode. +1. Import the `PureLayout.h` umbrella header. + * With `use_frameworks!` in your Podfile + * Swift: `import PureLayout` + * Objective-C: `#import ` (or with Modules enabled: `@import PureLayout;`) + * Without `use_frameworks!` in your Podfile + * Swift: Add `#import "PureLayout.h"` to your bridging header. + * Objective-C: `#import "PureLayout.h"` + +That's it - now go write some beautiful Auto Layout code! + +### Using [Carthage](https://github.com/Carthage/Carthage) +1. Add the `PureLayout/PureLayout` project to your [Cartfile](https://github.com/Carthage/Carthage/blob/master/Documentation/Artifacts.md#cartfile). + + ```ogdl + github "PureLayout/PureLayout" + ``` + +1. Run `carthage update`, then follow the [additional steps required](https://github.com/Carthage/Carthage#adding-frameworks-to-an-application) to add the framework into your project. +1. Import the PureLayout framework/module. + * Swift: `import PureLayout` + * Objective-C: `#import ` (or with Modules enabled: `@import PureLayout;`) + +That's it - now go write some beautiful Auto Layout code! + +### Manually from GitHub +1. Download the source files in the [PureLayout subdirectory](PureLayout/PureLayout). +1. Add the source files to your Xcode project. +1. Import the `PureLayout.h` header. + * Swift: Add `#import "PureLayout.h"` to your bridging header. + * Objective-C: `#import "PureLayout.h"` + +That's it - now go write some beautiful Auto Layout code! + +### App Extensions +To use PureLayout in an App Extension, you need to do a bit of extra configuration to prevent usage of unavailable APIs. [Click here](https://github.com/PureLayout/PureLayout/wiki/App-Extensions) for more info. + +### Releases +Releases are tagged in the git commit history using [semantic versioning](http://semver.org). Check out the [releases and release notes](https://github.com/PureLayout/PureLayout/releases) for each version. + ## API Cheat Sheet This is just a handy overview of the core API methods. Explore the [header files](PureLayout/PureLayout) for the full API, and find the complete documentation above the implementation of each method in the corresponding .m file. A couple of notes: -* All of the public API methods are namespaced with the prefix `auto...`, which also makes it easy for Xcode to autocomplete as you type. -* Methods that create constraints also automatically install (activate) the constraint(s), then return the new constraint(s) for you to optionally store for later adjustment or removal. -* Many methods below also have a variant which includes a `relation:` parameter to make the constraint an inequality. +* All of the public API methods are namespaced with the prefix `auto...`, which also makes it easy for Xcode to autocomplete as you type. +* Methods that create constraints also automatically install (activate) the constraint(s), then return the new constraint(s) for you to optionally store for later adjustment or removal. +* Many methods below also have a variant which includes a `relation:` parameter to make the constraint an inequality. ### Attributes @@ -26,123 +97,143 @@ There are 5 specific attribute types, which are used throughout most of the API: Additionally, there is one generic attribute type, `ALAttribute`, which is effectively a union of all the specific types. You can think of this as the "supertype" of all of the specific attribute types, which means that it is always safe to cast a specific type to the generic `ALAttribute` type. (Note that the reverse is not true -- casting a generic ALAttribute to a specific attribute type is unsafe!) -### [`UIView`/`NSView`](PureLayout/PureLayout/ALView%2BPureLayout.h) - - + autoCreateConstraintsWithoutInstalling: - + autoSetPriority:forConstraints: - + autoSetIdentifier:forConstraints: // iOS 7.0+, OS X 10.9+ only - - autoSetContent(CompressionResistance|Hugging)PriorityForAxis: - - autoCenterInSuperview: - - autoAlignAxisToSuperviewAxis: - - autoCenterInSuperviewMargins: // iOS 8.0+ only - - autoAlignAxisToSuperviewMarginAxis: // iOS 8.0+ only - - autoPinEdgeToSuperviewEdge:(withInset:) - - autoPinEdgesToSuperviewEdgesWithInsets:(excludingEdge:) - - autoPinEdgeToSuperviewMargin: // iOS 8.0+ only - - autoPinEdgesToSuperviewMargins(ExcludingEdge:) // iOS 8.0+ only - - autoPinEdge:toEdge:ofView:(withOffset:) - - autoAlignAxis:toSameAxisOfView:(withOffset:) - - autoMatchDimension:toDimension:ofView:(withOffset:|withMultiplier:) - - autoSetDimension(s)ToSize: - - autoConstrainAttribute:toAttribute:ofView:(withOffset:|withMultiplier:) - - autoPinTo(Top|Bottom)LayoutGuideOfViewController:withInset: // iOS only - -### [`NSArray`](PureLayout/PureLayout/NSArray%2BPureLayout.h) - - // Arrays of Constraints - - autoInstallConstraints - - autoRemoveConstraints - - autoIdentifyConstraints: // iOS 7.0+, OS X 10.9+ only - - // Arrays of Views - - autoAlignViewsToEdge: - - autoAlignViewsToAxis: - - autoMatchViewsDimension: - - autoSetViewsDimension:toSize: - - autoSetViewsDimensionsToSize: - - autoDistributeViewsAlongAxis:alignedTo:withFixedSpacing:(insetSpacing:)(matchedSizes:) - - autoDistributeViewsAlongAxis:alignedTo:withFixedSize:(insetSpacing:) +### [`UIView`/`NSView`](PureLayout/PureLayout/include/ALView%2BPureLayout.h) +``` +- autoSetContent(CompressionResistance|Hugging)PriorityForAxis: +- autoCenterInSuperview(Margins) // Margins variant iOS 8.0+ only +- autoAlignAxisToSuperview(Margin)Axis: // Margin variant iOS 8.0+ only +- autoPinEdgeToSuperview(Edge:|Margin:)(withInset:) // Margin variant iOS 8.0+ only +- autoPinEdgesToSuperview(Edges|Margins)(WithInsets:)(excludingEdge:) // Margins variant iOS 8.0+ only +- autoPinEdge:toEdge:ofView:(withOffset:) +- autoAlignAxis:toSameAxisOfView:(withOffset:|withMultiplier:) +- autoMatchDimension:toDimension:ofView:(withOffset:|withMultiplier:) +- autoSetDimension(s)ToSize: +- autoConstrainAttribute:toAttribute:ofView:(withOffset:|withMultiplier:) +- autoPinTo(Top|Bottom)LayoutGuideOfViewController:withInset: // iOS only +- autoPinEdgeToSuperviewSafeArea: // iOS 11.0+ only +- autoPinEdgeToSuperviewSafeArea:withInset: // iOS 11.0+ only +``` + +### [`NSArray`](PureLayout/PureLayout/include/NSArray%2BPureLayout.h) +``` +// Arrays of Constraints +- autoInstallConstraints +- autoRemoveConstraints +- autoIdentifyConstraints: // iOS 7.0+, OS X 10.9+ only + +// Arrays of Views +- autoAlignViewsToEdge: +- autoAlignViewsToAxis: +- autoMatchViewsDimension: +- autoSetViewsDimension:toSize: +- autoSetViewsDimensionsToSize: +- autoDistributeViewsAlongAxis:alignedTo:withFixedSpacing:(insetSpacing:)(matchedSizes:) +- autoDistributeViewsAlongAxis:alignedTo:withFixedSize:(insetSpacing:) +``` + +### [`NSLayoutConstraint`](PureLayout/PureLayout/include/NSLayoutConstraint%2BPureLayout.h) +``` ++ autoCreateAndInstallConstraints: ++ autoCreateConstraintsWithoutInstalling: ++ autoSetPriority:forConstraints: ++ autoSetIdentifier:forConstraints: // iOS 7.0+, OS X 10.9+ only +- autoIdentify: // iOS 7.0+, OS X 10.9+ only +- autoInstall +- autoRemove +``` -### [`NSLayoutConstraint`](PureLayout/PureLayout/NSLayoutConstraint%2BPureLayout.h) +## Usage +### Sample Code (Swift) +PureLayout dramatically simplifies writing Auto Layout code. Let's take a quick look at some examples, using PureLayout from Swift. - - autoInstall - - autoRemove - - autoIdentify: // iOS 7.0+, OS X 10.9+ only +Initialize the view using PureLayout initializer: -## Setup -*Note: PureLayout requires a minimum deployment target of iOS 6.0 or OS X 10.7* +```swift +let view1 = UIView(forAutoLayout: ()) +``` -### Using [CocoaPods](http://cocoapods.org) -1. Add the pod `PureLayout` to your [Podfile](http://guides.cocoapods.org/using/the-podfile.html). +If you need to use a different initializer (e.g. in `UIView` subclass), you can also use `configureForAutoLayout`: - pod 'PureLayout' +``` +view1.configureForAutoLayout() // alternative to UIView.init(forAutoLayout: ()) +``` -2. Run `pod install` from Terminal, then open your app's `.xcworkspace` file to launch Xcode. -3. Import the `PureLayout.h` header. Typically, this should be written as `#import ` +Here's a constraint between two views created (and automatically activated) using PureLayout: -That's it - now go write some beautiful Auto Layout code! +```swift +view1.autoPinEdge(.top, toEdge: .bottom, ofView: view2) +``` -### Using [Carthage](https://github.com/Carthage/Carthage) -1. Add the `smileyborg/PureLayout` project to your [Cartfile](https://github.com/Carthage/Carthage/blob/master/Documentation/Artifacts.md#cartfile). +Without PureLayout, here's the equivalent code you'd have to write using Apple's Foundation API directly: - github "smileyborg/PureLayout" +```swift +NSLayoutConstraint(item: view1, attribute: .top, relatedBy: .equal, toItem: view2, attribute: .bottom, multiplier: 1.0, constant: 0.0).active = true +``` -2. Run `carthage update`, then follow the [additional steps required](https://github.com/Carthage/Carthage#adding-frameworks-to-an-application) to add the iOS and/or Mac frameworks into your project. -3. Import the PureLayout framework/module (with the appropriate name for the platform you're using it on). - * Using Modules: `@import PureLayout_iOS` or `@import PureLayout_Mac` - * Without Modules: `#import ` or `#import ` +Many APIs of PureLayout create multiple constraints for you under the hood, letting you write highly readable layout code: -That's it - now go write some beautiful Auto Layout code! +```swift +// 2 constraints created & activated in one line! +logoImageView.autoCenterInSuperview() -### Manually from GitHub -1. Download the source files in the [PureLayout subdirectory](PureLayout/PureLayout). -2. Add the source files to your Xcode project. -3. Import the `PureLayout.h` header. +// 4 constraints created & activated in one line! +textContentView.autoPinEdgesToSuperviewEdges(with insets: UIEdgeInsets(top: 20.0, left: 5.0, bottom: 10.0, right: 5.0)) +``` -That's it - now go write some beautiful Auto Layout code! +PureLayout always returns the constraints it creates so you have full control: -### App Extensions -To use PureLayout in an App Extension, you need to do a bit of extra configuration to prevent usage of unavailable APIs. [Click here](https://github.com/smileyborg/PureLayout/wiki/App-Extensions) for more info. +```swift +let constraint = skinnyView.autoMatchDimension(.height, toDimension: .width, ofView: tallView) +``` -### Releases -Releases are tagged in the git commit history using [semantic versioning](http://semver.org). Check out the [releases and release notes](https://github.com/smileyborg/PureLayout/releases) for each version. +PureLayout supports safearea with iOS 11.0+: -## Usage -### Example Project -Open the project included in the repository (requires Xcode 6 or higher). It contains [iOS](PureLayout/Example-iOS) (`Example-iOS` scheme) and [OS X](PureLayout/Example-Mac) (`Example-Mac` scheme) demos of the library being used in various scenarios. +```swift +view2.autoPinEdge(toSuperviewSafeArea: .top) +``` + +PureLayout supports all Auto Layout features including inequalities, priorities, layout margins, identifiers, and much more. It's a comprehensive, developer-friendly way to use Auto Layout. + +Check out the example apps below for many more demos of PureLayout in use. + +### Example Apps +Open the project included in the repository (requires Xcode 6 or higher). It contains [iOS](PureLayout/Example-iOS) (`Example-iOS` scheme) and [OS X](PureLayout/Example-Mac) (`Example-Mac` scheme) demos of the library being used in various scenarios. The demos in the iOS example app make a great introductory tutorial to PureLayout -- run each demo, review the code used to implement it, then practice by making some changes of your own to the demo code. -On iOS, you can use different device simulators and rotate the device to see the constraints in action (as well as toggle the taller in-call status bar in the iOS Simulator). +Each demo in the iOS example app has a Swift and Objective-C version. **To compile & run the Swift demos, you must use Xcode 7.0 or higher (Swift 2.0) and choose the `Example-iOS-Xcode7` scheme.** When you run the example app, you can easily switch between using the Swift and Objective-C versions of the demos. To see the constraints in action while running the iOS demos, try using different device simulators, rotating the device to different orientations, as well as toggling the taller in-call status bar in the iOS Simulator. On OS X, while running the app, press any key to cycle through the demos. You can resize the window to see the constraints in action. ### Tips and Tricks -Check out some [Tips and Tricks](https://github.com/smileyborg/PureLayout/wiki/Tips-and-Tricks) to keep in mind when using the API. +Check out some [Tips and Tricks](https://github.com/PureLayout/PureLayout/wiki/Tips-and-Tricks) to keep in mind when using the API. ## PureLayout vs. the rest -An overview of the Auto Layout options available, ordered from the lowest- to highest-level of abstraction. - -* Apple [NSLayoutConstraint SDK API](https://developer.apple.com/library/ios/documentation/AppKit/Reference/NSLayoutConstraint_Class/index.html#//apple_ref/occ/clm/NSLayoutConstraint/constraintWithItem:attribute:relatedBy:toItem:attribute:multiplier:constant:) - * Pros: Raw power - * Cons: Extremely verbose, tedious to write, difficult to read -* Apple [Visual Format Language](https://developer.apple.com/library/ios/documentation/UserExperience/Conceptual/AutolayoutPG/VisualFormatLanguage/VisualFormatLanguage.html) - * Pros: Concise, convenient - * Cons: Doesn't support some use cases, incomplete compile-time checks, must learn syntax, hard to debug -* Apple Interface Builder - * Pros: Visual, simple - * Cons: Difficult for complex layouts, cannot dynamically set constraints at runtime, encourages hardcoded magic numbers, not always WYSIWYG -* **PureLayout** - * Pros: Simple, efficient, minimal third party code, consistent with Cocoa API style, compatible with Objective-C and Swift codebases - * Cons: Not the most concise expression of layout code -* High-level Auto Layout Libraries/DSLs ([Cartography](https://github.com/robb/Cartography), [Masonry](https://github.com/Masonry/Masonry), [KeepLayout](https://github.com/iMartinKiss/KeepLayout)) - * Pros: Very clean, concise, and convenient - * Cons: Unique API style is foreign to Cocoa APIs, mixed compatibility with Objective-C & Swift, greater dependency on third party code +There are quite a few different ways to implement Auto Layout. Here is a quick overview of the available options: + +* Apple [NSLayoutConstraint SDK API](https://developer.apple.com/library/ios/documentation/AppKit/Reference/NSLayoutConstraint_Class/index.html#//apple_ref/occ/clm/NSLayoutConstraint/constraintWithItem:attribute:relatedBy:toItem:attribute:multiplier:constant:) + * Pros: Raw power + * Cons: Extremely verbose; tedious to write; difficult to read +* Apple [Visual Format Language](https://developer.apple.com/library/ios/documentation/UserExperience/Conceptual/AutolayoutPG/VisualFormatLanguage.html) + * Pros: Concise; convenient + * Cons: Doesn't support some use cases; lacks compile-time checking and safety; must learn syntax; hard to debug +* Apple Interface Builder + * Pros: Visual; interactive; provides compile-time layout checking + * Cons: Difficult for complex layouts; cannot dynamically set constraints at runtime; encourages hardcoded magic numbers; not always WYSIWYG +* Apple [NSLayoutAnchor SDK API](https://developer.apple.com/library/prerelease/ios/documentation/AppKit/Reference/NSLayoutAnchor_ClassReference/index.html) + * Pros: Clean, readable, and type-safe API for creating individual constraints + * Cons: Only available in iOS 9.0 and OS X 10.11 and higher; requires manually activating each constraint; no API for creating multiple constraints at once +* **PureLayout** + * Pros: Compatible with Objective-C and Swift codebases; consistent with Cocoa API style; cross-platform API and implementation shared across iOS and OS X; fully backwards-compatible to iOS 6 & OS X 10.7; easy to use; type-safe; efficient + * Cons: Not the most concise expression of layout code +* High-level Auto Layout Libraries/DSLs ([Cartography](https://github.com/robb/Cartography), [SnapKit](https://github.com/SnapKit/SnapKit), [KeepLayout](https://github.com/iMartinKiss/KeepLayout)) + * Pros: Very clean, concise, and convenient + * Cons: Unique API style is foreign to Apple's APIs; mixed compatibility with Objective-C & Swift; greater dependency on third party code PureLayout takes a balanced approach to Auto Layout that makes it well suited for any project. ## Problems, Suggestions, Pull Requests? -Please open a [new Issue here](https://github.com/smileyborg/PureLayout/issues/new) if you run into an issue, have a feature request, or want to share a comment. Note that general Auto Layout questions should be asked on [Stack Overflow](http://stackoverflow.com). +Please open a [new Issue here](https://github.com/PureLayout/PureLayout/issues/new) if you run into a problem specific to PureLayout, have a feature request, or want to share a comment. Note that general Auto Layout questions should be asked on [Stack Overflow](http://stackoverflow.com). -If you're considering taking on significant changes or additions to the project, please communicate in advance by opening a new Issue. This allows everyone to get onboard with upcoming changes, ensures that changes align with the project's design philosophy, and avoids duplicated work. +Pull requests are encouraged and greatly appreciated! Please try to maintain consistency with the existing code style. If you're considering taking on significant changes or additions to the project, please communicate in advance by opening a new Issue. This allows everyone to get onboard with upcoming changes, ensures that changes align with the project's design philosophy, and avoids duplicated work. ## Meta -Designed & maintained by Tyler Fox ([@smileyborg](https://twitter.com/smileyborg)). Distributed with the MIT license. +Originally designed & built by Tyler Fox ([@smileyborg](https://github.com/smileyborg)). Currently maintained by Mickey Reiss ([@mickeyreiss](https://github.com/mickeyreiss)). Distributed with the MIT license.