├── .gitignore ├── .travis.yml ├── Example ├── Example.xcodeproj │ └── project.pbxproj └── Example │ ├── ALAppDelegate.h │ ├── ALAppDelegate.m │ ├── ALViewController.h │ ├── ALViewController.m │ ├── Default-568h@2x.png │ ├── Default.png │ ├── Default@2x.png │ ├── Example-Info.plist │ ├── Example-Prefix.pch │ ├── ar.lproj │ ├── ALViewController.xib │ ├── InfoPlist.strings │ └── Localizable.strings │ ├── en.lproj │ ├── ALViewController.xib │ ├── InfoPlist.strings │ └── Localizable.strings │ └── main.m ├── LICENSE ├── README.md ├── Source ├── UIView+AutoLayout.h └── UIView+AutoLayout.m ├── Tests ├── AutoLayout.xcodeproj │ ├── project.pbxproj │ └── xcshareddata │ │ └── xcschemes │ │ └── AutoLayout.xcscheme ├── AutoLayout │ ├── ALAppDelegate.h │ ├── ALAppDelegate.m │ ├── AutoLayout-Info.plist │ ├── AutoLayout-Prefix.pch │ ├── Images.xcassets │ │ ├── AppIcon.appiconset │ │ │ └── Contents.json │ │ └── LaunchImage.launchimage │ │ │ └── Contents.json │ ├── en.lproj │ │ └── InfoPlist.strings │ └── main.m └── AutoLayoutTests │ ├── AutoLayoutCenteringTests.m │ ├── AutoLayoutInstallationTests.m │ ├── AutoLayoutInstantiationTests.m │ ├── AutoLayoutInternalTests.m │ ├── AutoLayoutPinEdgesTests.m │ ├── AutoLayoutPriorityTests.m │ ├── AutoLayoutRemovalTests.m │ ├── AutoLayoutTestBase.h │ ├── AutoLayoutTestBase.m │ ├── AutoLayoutTests-Info.plist │ ├── UIView+AutoLayoutInternal.h │ └── en.lproj │ └── InfoPlist.strings └── UIView+AutoLayout.podspec /.gitignore: -------------------------------------------------------------------------------- 1 | # Xcode 2 | .DS_Store 3 | build/ 4 | *.pbxuser 5 | !default.pbxuser 6 | *.mode1v3 7 | !default.mode1v3 8 | *.mode2v3 9 | !default.mode2v3 10 | *.perspectivev3 11 | !default.perspectivev3 12 | *.xcworkspace 13 | !default.xcworkspace 14 | xcuserdata 15 | profile 16 | *.moved-aside 17 | DerivedData 18 | .idea/ 19 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: objective-c 2 | xcode_project: Tests/AutoLayout.xcodeproj 3 | xcode_scheme: AutoLayout 4 | xcode_sdk: iphonesimulator 5 | before_install: 6 | - brew update 7 | - brew upgrade xctool 8 | -------------------------------------------------------------------------------- /Example/Example.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 6552AB9817D42AC80073E592 /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = 6552AB9A17D42AC80073E592 /* Localizable.strings */; }; 11 | B12C23DF17C3FDE4001CF667 /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = B12C23DE17C3FDE4001CF667 /* UIKit.framework */; }; 12 | B12C23E117C3FDE4001CF667 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = B12C23E017C3FDE4001CF667 /* Foundation.framework */; }; 13 | B12C23E317C3FDE4001CF667 /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = B12C23E217C3FDE4001CF667 /* CoreGraphics.framework */; }; 14 | B12C23E917C3FDE4001CF667 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = B12C23E717C3FDE4001CF667 /* InfoPlist.strings */; }; 15 | B12C23EB17C3FDE4001CF667 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = B12C23EA17C3FDE4001CF667 /* main.m */; }; 16 | B12C23EF17C3FDE4001CF667 /* ALAppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = B12C23EE17C3FDE4001CF667 /* ALAppDelegate.m */; }; 17 | B12C23F117C3FDE4001CF667 /* Default.png in Resources */ = {isa = PBXBuildFile; fileRef = B12C23F017C3FDE4001CF667 /* Default.png */; }; 18 | B12C23F317C3FDE4001CF667 /* Default@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = B12C23F217C3FDE4001CF667 /* Default@2x.png */; }; 19 | B12C23F517C3FDE4001CF667 /* Default-568h@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = B12C23F417C3FDE4001CF667 /* Default-568h@2x.png */; }; 20 | B12C23F817C3FDE4001CF667 /* ALViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = B12C23F717C3FDE4001CF667 /* ALViewController.m */; }; 21 | B12C23FB17C3FDE4001CF667 /* ALViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = B12C23F917C3FDE4001CF667 /* ALViewController.xib */; }; 22 | B12C240417C3FF84001CF667 /* UIView+AutoLayout.m in Sources */ = {isa = PBXBuildFile; fileRef = B12C240317C3FF84001CF667 /* UIView+AutoLayout.m */; }; 23 | /* End PBXBuildFile section */ 24 | 25 | /* Begin PBXFileReference section */ 26 | 6552AB9417D428A40073E592 /* ar */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = ar; path = ar.lproj/ALViewController.xib; sourceTree = ""; }; 27 | 6552AB9517D428A40073E592 /* ar */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ar; path = ar.lproj/InfoPlist.strings; sourceTree = ""; }; 28 | 6552AB9917D42AC80073E592 /* en */ = {isa = PBXFileReference; lastKnownFileType = file; name = en; path = en.lproj/Localizable.strings; sourceTree = ""; }; 29 | 6552AB9B17D42ADB0073E592 /* ar */ = {isa = PBXFileReference; lastKnownFileType = file; name = ar; path = ar.lproj/Localizable.strings; sourceTree = ""; }; 30 | B12C23DB17C3FDE4001CF667 /* Example.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Example.app; sourceTree = BUILT_PRODUCTS_DIR; }; 31 | B12C23DE17C3FDE4001CF667 /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = System/Library/Frameworks/UIKit.framework; sourceTree = SDKROOT; }; 32 | B12C23E017C3FDE4001CF667 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; }; 33 | B12C23E217C3FDE4001CF667 /* CoreGraphics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreGraphics.framework; path = System/Library/Frameworks/CoreGraphics.framework; sourceTree = SDKROOT; }; 34 | B12C23E617C3FDE4001CF667 /* Example-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "Example-Info.plist"; sourceTree = ""; }; 35 | B12C23E817C3FDE4001CF667 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = ""; }; 36 | B12C23EA17C3FDE4001CF667 /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; 37 | B12C23EC17C3FDE4001CF667 /* Example-Prefix.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Example-Prefix.pch"; sourceTree = ""; }; 38 | B12C23ED17C3FDE4001CF667 /* ALAppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ALAppDelegate.h; sourceTree = ""; }; 39 | B12C23EE17C3FDE4001CF667 /* ALAppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ALAppDelegate.m; sourceTree = ""; }; 40 | B12C23F017C3FDE4001CF667 /* Default.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = Default.png; sourceTree = ""; }; 41 | B12C23F217C3FDE4001CF667 /* Default@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "Default@2x.png"; sourceTree = ""; }; 42 | B12C23F417C3FDE4001CF667 /* Default-568h@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "Default-568h@2x.png"; sourceTree = ""; }; 43 | B12C23F617C3FDE4001CF667 /* ALViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ALViewController.h; sourceTree = ""; }; 44 | B12C23F717C3FDE4001CF667 /* ALViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ALViewController.m; sourceTree = ""; }; 45 | B12C23FA17C3FDE4001CF667 /* en */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = en; path = en.lproj/ALViewController.xib; sourceTree = ""; }; 46 | B12C240217C3FF84001CF667 /* UIView+AutoLayout.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "UIView+AutoLayout.h"; path = "../../Source/UIView+AutoLayout.h"; sourceTree = ""; }; 47 | B12C240317C3FF84001CF667 /* UIView+AutoLayout.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = "UIView+AutoLayout.m"; path = "../../Source/UIView+AutoLayout.m"; sourceTree = ""; }; 48 | /* End PBXFileReference section */ 49 | 50 | /* Begin PBXFrameworksBuildPhase section */ 51 | B12C23D817C3FDE4001CF667 /* Frameworks */ = { 52 | isa = PBXFrameworksBuildPhase; 53 | buildActionMask = 2147483647; 54 | files = ( 55 | B12C23DF17C3FDE4001CF667 /* UIKit.framework in Frameworks */, 56 | B12C23E117C3FDE4001CF667 /* Foundation.framework in Frameworks */, 57 | B12C23E317C3FDE4001CF667 /* CoreGraphics.framework in Frameworks */, 58 | ); 59 | runOnlyForDeploymentPostprocessing = 0; 60 | }; 61 | /* End PBXFrameworksBuildPhase section */ 62 | 63 | /* Begin PBXGroup section */ 64 | B12C23D217C3FDE4001CF667 = { 65 | isa = PBXGroup; 66 | children = ( 67 | B12C23E417C3FDE4001CF667 /* Example */, 68 | B12C23DD17C3FDE4001CF667 /* Frameworks */, 69 | B12C23DC17C3FDE4001CF667 /* Products */, 70 | ); 71 | sourceTree = ""; 72 | }; 73 | B12C23DC17C3FDE4001CF667 /* Products */ = { 74 | isa = PBXGroup; 75 | children = ( 76 | B12C23DB17C3FDE4001CF667 /* Example.app */, 77 | ); 78 | name = Products; 79 | sourceTree = ""; 80 | }; 81 | B12C23DD17C3FDE4001CF667 /* Frameworks */ = { 82 | isa = PBXGroup; 83 | children = ( 84 | B12C23DE17C3FDE4001CF667 /* UIKit.framework */, 85 | B12C23E017C3FDE4001CF667 /* Foundation.framework */, 86 | B12C23E217C3FDE4001CF667 /* CoreGraphics.framework */, 87 | ); 88 | name = Frameworks; 89 | sourceTree = ""; 90 | }; 91 | B12C23E417C3FDE4001CF667 /* Example */ = { 92 | isa = PBXGroup; 93 | children = ( 94 | B12C240117C3FF76001CF667 /* UIView+AutoLayout */, 95 | B12C23ED17C3FDE4001CF667 /* ALAppDelegate.h */, 96 | B12C23EE17C3FDE4001CF667 /* ALAppDelegate.m */, 97 | B12C23F617C3FDE4001CF667 /* ALViewController.h */, 98 | B12C23F717C3FDE4001CF667 /* ALViewController.m */, 99 | B12C23F917C3FDE4001CF667 /* ALViewController.xib */, 100 | B12C23E517C3FDE4001CF667 /* Supporting Files */, 101 | ); 102 | path = Example; 103 | sourceTree = ""; 104 | }; 105 | B12C23E517C3FDE4001CF667 /* Supporting Files */ = { 106 | isa = PBXGroup; 107 | children = ( 108 | B12C23E617C3FDE4001CF667 /* Example-Info.plist */, 109 | B12C23E717C3FDE4001CF667 /* InfoPlist.strings */, 110 | B12C23EA17C3FDE4001CF667 /* main.m */, 111 | B12C23EC17C3FDE4001CF667 /* Example-Prefix.pch */, 112 | B12C23F017C3FDE4001CF667 /* Default.png */, 113 | B12C23F217C3FDE4001CF667 /* Default@2x.png */, 114 | B12C23F417C3FDE4001CF667 /* Default-568h@2x.png */, 115 | 6552AB9A17D42AC80073E592 /* Localizable.strings */, 116 | ); 117 | name = "Supporting Files"; 118 | sourceTree = ""; 119 | }; 120 | B12C240117C3FF76001CF667 /* UIView+AutoLayout */ = { 121 | isa = PBXGroup; 122 | children = ( 123 | B12C240217C3FF84001CF667 /* UIView+AutoLayout.h */, 124 | B12C240317C3FF84001CF667 /* UIView+AutoLayout.m */, 125 | ); 126 | name = "UIView+AutoLayout"; 127 | sourceTree = ""; 128 | }; 129 | /* End PBXGroup section */ 130 | 131 | /* Begin PBXNativeTarget section */ 132 | B12C23DA17C3FDE4001CF667 /* Example */ = { 133 | isa = PBXNativeTarget; 134 | buildConfigurationList = B12C23FE17C3FDE4001CF667 /* Build configuration list for PBXNativeTarget "Example" */; 135 | buildPhases = ( 136 | B12C23D717C3FDE4001CF667 /* Sources */, 137 | B12C23D817C3FDE4001CF667 /* Frameworks */, 138 | B12C23D917C3FDE4001CF667 /* Resources */, 139 | ); 140 | buildRules = ( 141 | ); 142 | dependencies = ( 143 | ); 144 | name = Example; 145 | productName = Example; 146 | productReference = B12C23DB17C3FDE4001CF667 /* Example.app */; 147 | productType = "com.apple.product-type.application"; 148 | }; 149 | /* End PBXNativeTarget section */ 150 | 151 | /* Begin PBXProject section */ 152 | B12C23D317C3FDE4001CF667 /* Project object */ = { 153 | isa = PBXProject; 154 | attributes = { 155 | CLASSPREFIX = AL; 156 | LastUpgradeCheck = 0460; 157 | }; 158 | buildConfigurationList = B12C23D617C3FDE4001CF667 /* Build configuration list for PBXProject "Example" */; 159 | compatibilityVersion = "Xcode 3.2"; 160 | developmentRegion = English; 161 | hasScannedForEncodings = 0; 162 | knownRegions = ( 163 | en, 164 | ar, 165 | ); 166 | mainGroup = B12C23D217C3FDE4001CF667; 167 | productRefGroup = B12C23DC17C3FDE4001CF667 /* Products */; 168 | projectDirPath = ""; 169 | projectRoot = ""; 170 | targets = ( 171 | B12C23DA17C3FDE4001CF667 /* Example */, 172 | ); 173 | }; 174 | /* End PBXProject section */ 175 | 176 | /* Begin PBXResourcesBuildPhase section */ 177 | B12C23D917C3FDE4001CF667 /* Resources */ = { 178 | isa = PBXResourcesBuildPhase; 179 | buildActionMask = 2147483647; 180 | files = ( 181 | B12C23E917C3FDE4001CF667 /* InfoPlist.strings in Resources */, 182 | B12C23F117C3FDE4001CF667 /* Default.png in Resources */, 183 | B12C23F317C3FDE4001CF667 /* Default@2x.png in Resources */, 184 | B12C23F517C3FDE4001CF667 /* Default-568h@2x.png in Resources */, 185 | B12C23FB17C3FDE4001CF667 /* ALViewController.xib in Resources */, 186 | 6552AB9817D42AC80073E592 /* Localizable.strings in Resources */, 187 | ); 188 | runOnlyForDeploymentPostprocessing = 0; 189 | }; 190 | /* End PBXResourcesBuildPhase section */ 191 | 192 | /* Begin PBXSourcesBuildPhase section */ 193 | B12C23D717C3FDE4001CF667 /* Sources */ = { 194 | isa = PBXSourcesBuildPhase; 195 | buildActionMask = 2147483647; 196 | files = ( 197 | B12C23EB17C3FDE4001CF667 /* main.m in Sources */, 198 | B12C23EF17C3FDE4001CF667 /* ALAppDelegate.m in Sources */, 199 | B12C23F817C3FDE4001CF667 /* ALViewController.m in Sources */, 200 | B12C240417C3FF84001CF667 /* UIView+AutoLayout.m in Sources */, 201 | ); 202 | runOnlyForDeploymentPostprocessing = 0; 203 | }; 204 | /* End PBXSourcesBuildPhase section */ 205 | 206 | /* Begin PBXVariantGroup section */ 207 | 6552AB9A17D42AC80073E592 /* Localizable.strings */ = { 208 | isa = PBXVariantGroup; 209 | children = ( 210 | 6552AB9917D42AC80073E592 /* en */, 211 | 6552AB9B17D42ADB0073E592 /* ar */, 212 | ); 213 | name = Localizable.strings; 214 | sourceTree = ""; 215 | }; 216 | B12C23E717C3FDE4001CF667 /* InfoPlist.strings */ = { 217 | isa = PBXVariantGroup; 218 | children = ( 219 | B12C23E817C3FDE4001CF667 /* en */, 220 | 6552AB9517D428A40073E592 /* ar */, 221 | ); 222 | name = InfoPlist.strings; 223 | sourceTree = ""; 224 | }; 225 | B12C23F917C3FDE4001CF667 /* ALViewController.xib */ = { 226 | isa = PBXVariantGroup; 227 | children = ( 228 | B12C23FA17C3FDE4001CF667 /* en */, 229 | 6552AB9417D428A40073E592 /* ar */, 230 | ); 231 | name = ALViewController.xib; 232 | sourceTree = ""; 233 | }; 234 | /* End PBXVariantGroup section */ 235 | 236 | /* Begin XCBuildConfiguration section */ 237 | B12C23FC17C3FDE4001CF667 /* Debug */ = { 238 | isa = XCBuildConfiguration; 239 | buildSettings = { 240 | ALWAYS_SEARCH_USER_PATHS = NO; 241 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 242 | CLANG_CXX_LIBRARY = "libc++"; 243 | CLANG_ENABLE_OBJC_ARC = YES; 244 | CLANG_WARN_CONSTANT_CONVERSION = YES; 245 | CLANG_WARN_EMPTY_BODY = YES; 246 | CLANG_WARN_ENUM_CONVERSION = YES; 247 | CLANG_WARN_INT_CONVERSION = YES; 248 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 249 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 250 | COPY_PHASE_STRIP = NO; 251 | GCC_C_LANGUAGE_STANDARD = gnu99; 252 | GCC_DYNAMIC_NO_PIC = NO; 253 | GCC_OPTIMIZATION_LEVEL = 0; 254 | GCC_PREPROCESSOR_DEFINITIONS = ( 255 | "DEBUG=1", 256 | "$(inherited)", 257 | ); 258 | GCC_SYMBOLS_PRIVATE_EXTERN = NO; 259 | GCC_WARN_ABOUT_RETURN_TYPE = YES; 260 | GCC_WARN_UNINITIALIZED_AUTOS = YES; 261 | GCC_WARN_UNUSED_VARIABLE = YES; 262 | IPHONEOS_DEPLOYMENT_TARGET = 6.1; 263 | ONLY_ACTIVE_ARCH = YES; 264 | SDKROOT = iphoneos; 265 | }; 266 | name = Debug; 267 | }; 268 | B12C23FD17C3FDE4001CF667 /* Release */ = { 269 | isa = XCBuildConfiguration; 270 | buildSettings = { 271 | ALWAYS_SEARCH_USER_PATHS = NO; 272 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 273 | CLANG_CXX_LIBRARY = "libc++"; 274 | CLANG_ENABLE_OBJC_ARC = YES; 275 | CLANG_WARN_CONSTANT_CONVERSION = YES; 276 | CLANG_WARN_EMPTY_BODY = YES; 277 | CLANG_WARN_ENUM_CONVERSION = YES; 278 | CLANG_WARN_INT_CONVERSION = YES; 279 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 280 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 281 | COPY_PHASE_STRIP = YES; 282 | GCC_C_LANGUAGE_STANDARD = gnu99; 283 | GCC_WARN_ABOUT_RETURN_TYPE = YES; 284 | GCC_WARN_UNINITIALIZED_AUTOS = YES; 285 | GCC_WARN_UNUSED_VARIABLE = YES; 286 | IPHONEOS_DEPLOYMENT_TARGET = 6.1; 287 | OTHER_CFLAGS = "-DNS_BLOCK_ASSERTIONS=1"; 288 | SDKROOT = iphoneos; 289 | VALIDATE_PRODUCT = YES; 290 | }; 291 | name = Release; 292 | }; 293 | B12C23FF17C3FDE4001CF667 /* Debug */ = { 294 | isa = XCBuildConfiguration; 295 | buildSettings = { 296 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 297 | GCC_PREFIX_HEADER = "Example/Example-Prefix.pch"; 298 | INFOPLIST_FILE = "Example/Example-Info.plist"; 299 | PRODUCT_NAME = "$(TARGET_NAME)"; 300 | WRAPPER_EXTENSION = app; 301 | }; 302 | name = Debug; 303 | }; 304 | B12C240017C3FDE4001CF667 /* Release */ = { 305 | isa = XCBuildConfiguration; 306 | buildSettings = { 307 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 308 | GCC_PREFIX_HEADER = "Example/Example-Prefix.pch"; 309 | INFOPLIST_FILE = "Example/Example-Info.plist"; 310 | PRODUCT_NAME = "$(TARGET_NAME)"; 311 | WRAPPER_EXTENSION = app; 312 | }; 313 | name = Release; 314 | }; 315 | /* End XCBuildConfiguration section */ 316 | 317 | /* Begin XCConfigurationList section */ 318 | B12C23D617C3FDE4001CF667 /* Build configuration list for PBXProject "Example" */ = { 319 | isa = XCConfigurationList; 320 | buildConfigurations = ( 321 | B12C23FC17C3FDE4001CF667 /* Debug */, 322 | B12C23FD17C3FDE4001CF667 /* Release */, 323 | ); 324 | defaultConfigurationIsVisible = 0; 325 | defaultConfigurationName = Release; 326 | }; 327 | B12C23FE17C3FDE4001CF667 /* Build configuration list for PBXNativeTarget "Example" */ = { 328 | isa = XCConfigurationList; 329 | buildConfigurations = ( 330 | B12C23FF17C3FDE4001CF667 /* Debug */, 331 | B12C240017C3FDE4001CF667 /* Release */, 332 | ); 333 | defaultConfigurationIsVisible = 0; 334 | defaultConfigurationName = Release; 335 | }; 336 | /* End XCConfigurationList section */ 337 | }; 338 | rootObject = B12C23D317C3FDE4001CF667 /* Project object */; 339 | } 340 | -------------------------------------------------------------------------------- /Example/Example/ALAppDelegate.h: -------------------------------------------------------------------------------- 1 | // 2 | // ALAppDelegate.h 3 | // Example 4 | // 5 | // Copyright (c) 2013 Tyler Fox 6 | // https://github.com/smileyborg/UIView-AutoLayout 7 | // 8 | 9 | #import 10 | 11 | @class ALViewController; 12 | 13 | @interface ALAppDelegate : UIResponder 14 | 15 | @property (strong, nonatomic) UIWindow *window; 16 | 17 | @property (strong, nonatomic) ALViewController *viewController; 18 | 19 | @end 20 | -------------------------------------------------------------------------------- /Example/Example/ALAppDelegate.m: -------------------------------------------------------------------------------- 1 | // 2 | // ALAppDelegate.m 3 | // Example 4 | // 5 | // Copyright (c) 2013 Tyler Fox 6 | // https://github.com/smileyborg/UIView-AutoLayout 7 | // 8 | 9 | #import "ALAppDelegate.h" 10 | 11 | #import "ALViewController.h" 12 | 13 | @implementation ALAppDelegate 14 | 15 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions 16 | { 17 | self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]]; 18 | // Override point for customization after application launch. 19 | self.viewController = [[ALViewController alloc] initWithNibName:@"ALViewController" bundle:nil]; 20 | self.window.rootViewController = self.viewController; 21 | [self.window makeKeyAndVisible]; 22 | return YES; 23 | } 24 | 25 | - (void)applicationWillResignActive:(UIApplication *)application 26 | { 27 | // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. 28 | // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game. 29 | } 30 | 31 | - (void)applicationDidEnterBackground:(UIApplication *)application 32 | { 33 | // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. 34 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. 35 | } 36 | 37 | - (void)applicationWillEnterForeground:(UIApplication *)application 38 | { 39 | // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background. 40 | } 41 | 42 | - (void)applicationDidBecomeActive:(UIApplication *)application 43 | { 44 | // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. 45 | } 46 | 47 | - (void)applicationWillTerminate:(UIApplication *)application 48 | { 49 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. 50 | } 51 | 52 | @end 53 | -------------------------------------------------------------------------------- /Example/Example/ALViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // ALViewController.h 3 | // Example 4 | // 5 | // Copyright (c) 2013 Tyler Fox 6 | // https://github.com/smileyborg/UIView-AutoLayout 7 | // 8 | 9 | #import 10 | 11 | @interface ALViewController : UIViewController 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /Example/Example/ALViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // ALViewController.m 3 | // Example 4 | // 5 | // Copyright (c) 2013 Tyler Fox 6 | // https://github.com/smileyborg/UIView-AutoLayout 7 | // 8 | 9 | #import "ALViewController.h" 10 | 11 | typedef NS_ENUM(NSInteger, ExampleConstraintDemo) { 12 | ExampleConstraintDemoReset = 0, 13 | ExampleConstraintDemo1, 14 | ExampleConstraintDemo2, 15 | ExampleConstraintDemo3, 16 | ExampleConstraintDemo4, 17 | ExampleConstraintDemo5, 18 | ExampleConstraintDemo6, 19 | ExampleConstraintDemo7, 20 | ExampleConstraintDemoCount 21 | }; 22 | 23 | @interface ALViewController () 24 | 25 | @property (nonatomic, strong) UIView *containerView; 26 | 27 | @property (nonatomic, strong) UIView *blueView; 28 | @property (nonatomic, strong) UIView *redView; 29 | @property (nonatomic, strong) UIView *yellowView; 30 | @property (nonatomic, strong) UIView *greenView; 31 | @property (nonatomic, strong) UILabel *orangeView; 32 | 33 | @property (nonatomic, assign) ExampleConstraintDemo constraintDemo; 34 | 35 | @property (nonatomic, assign) BOOL isAnimatingDemo3; 36 | @property (nonatomic, strong) NSLayoutConstraint *demo3BlueBottomInset; 37 | @property (nonatomic, strong) NSLayoutConstraint *demo3BlueRightInset; 38 | @property (nonatomic, strong) NSLayoutConstraint *demo3RedSizeConstraint; 39 | @property (nonatomic, strong) NSLayoutConstraint *demo3GreenPinConstraint; 40 | 41 | @end 42 | 43 | @implementation ALViewController 44 | 45 | - (void)viewDidLoad 46 | { 47 | [super viewDidLoad]; 48 | 49 | [self setupViews]; 50 | 51 | // Start off by resetting and advancing to the first demo 52 | self.constraintDemo = ExampleConstraintDemoReset; 53 | [self nextDemo]; 54 | 55 | // Change the demo when the screen is tapped 56 | [self.view addGestureRecognizer:[[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(nextDemo)]]; 57 | } 58 | 59 | - (void)setupViews 60 | { 61 | [self.view addSubview:self.containerView]; 62 | [self.containerView addSubview:self.blueView]; 63 | [self.containerView addSubview:self.redView]; 64 | [self.containerView addSubview:self.yellowView]; 65 | [self.containerView addSubview:self.greenView]; 66 | [self.containerView addSubview:self.orangeView]; 67 | } 68 | 69 | - (void)updateViewConstraints 70 | { 71 | [super updateViewConstraints]; 72 | 73 | [self setupConstraintsForCurrentDemo]; 74 | } 75 | 76 | /** 77 | Demonstrates: 78 | - Setting a view to a fixed width 79 | - Matching the widths of subviews 80 | - Distributing subviews vertically with a fixed height 81 | */ 82 | - (void)setupDemo1 83 | { 84 | NSArray *subviews = @[self.blueView, self.redView, self.yellowView, self.greenView, self.orangeView]; 85 | 86 | [self.blueView autoSetDimension:ALDimensionWidth toSize:80.0f]; 87 | [subviews autoMatchViewsDimension:ALDimensionWidth]; 88 | 89 | [self.orangeView autoAlignAxisToSuperviewAxis:ALAxisVertical]; 90 | 91 | [subviews autoDistributeViewsAlongAxis:ALAxisVertical withFixedSize:30.0f insetSpacing:YES alignment:NSLayoutFormatAlignAllCenterX]; 92 | } 93 | 94 | /** 95 | Demonstrates: 96 | - Matching a view's width to its height 97 | - Matching the heights of subviews 98 | - Distributing subviews horizontally with fixed spacing 99 | */ 100 | - (void)setupDemo2 101 | { 102 | NSArray *subviews = @[self.blueView, self.redView, self.yellowView, self.greenView, self.orangeView]; 103 | 104 | [self.blueView autoMatchDimension:ALDimensionHeight toDimension:ALDimensionWidth ofView:self.blueView]; 105 | [subviews autoMatchViewsDimension:ALDimensionHeight]; 106 | 107 | [self.orangeView autoAlignAxisToSuperviewAxis:ALAxisHorizontal]; 108 | 109 | [subviews autoDistributeViewsAlongAxis:ALAxisHorizontal withFixedSpacing:10.0f insetSpacing:NO alignment:NSLayoutFormatAlignAllCenterY]; 110 | } 111 | 112 | /** 113 | Demonstrates: 114 | - Animation with constraints 115 | - Setting a priority less than required 116 | - Complicated interaction of various constraints 117 | */ 118 | - (void)setupDemo3 119 | { 120 | [self.orangeView autoSetDimensionsToSize:CGSizeZero]; // orange view not used in this demo; this prevents it from taking on its intrinsic content size 121 | 122 | [UIView autoSetPriority:UILayoutPriorityDefaultHigh forConstraints:^{ 123 | [self.blueView autoSetDimensionsToSize:CGSizeMake(60.0f, 80.0f)]; 124 | }]; 125 | 126 | [self.blueView autoPinEdge:ALEdgeLeft toEdge:ALEdgeRight ofView:self.blueView.superview withOffset:-80.0f relation:NSLayoutRelationLessThanOrEqual]; 127 | 128 | self.demo3BlueBottomInset = [self.blueView autoPinEdgeToSuperviewEdge:ALEdgeBottom withInset:50.0f]; 129 | self.demo3BlueRightInset = [self.blueView autoPinEdgeToSuperviewEdge:ALEdgeRight withInset:10.0f]; 130 | 131 | [self.redView autoMatchDimension:ALDimensionWidth toDimension:ALDimensionWidth ofView:self.blueView]; 132 | self.demo3RedSizeConstraint = [self.redView autoMatchDimension:ALDimensionHeight toDimension:ALDimensionHeight ofView:self.blueView withOffset:-40.0f]; 133 | 134 | [self.redView autoAlignAxis:ALAxisHorizontal toSameAxisOfView:self.blueView]; 135 | [self.blueView autoPinEdge:ALEdgeLeft toEdge:ALEdgeRight ofView:self.redView withOffset:30.0f]; 136 | 137 | self.demo3GreenPinConstraint = [self.greenView autoPinEdge:ALEdgeRight toEdge:ALEdgeRight ofView:self.redView]; 138 | [self.greenView autoPinEdge:ALEdgeBottom toEdge:ALEdgeTop ofView:self.redView withOffset:-50.0f]; 139 | [self.greenView autoMatchDimension:ALDimensionWidth toDimension:ALDimensionHeight ofView:self.redView]; 140 | [self.greenView autoMatchDimension:ALDimensionHeight toDimension:ALDimensionWidth ofView:self.blueView]; 141 | 142 | [self.view layoutIfNeeded]; 143 | 144 | if (self.isAnimatingDemo3 == NO) { 145 | // Begin animation on next run loop after initial layout has been calculated 146 | double delayInSeconds = 0.0; 147 | dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(delayInSeconds * NSEC_PER_SEC)); 148 | dispatch_after(popTime, dispatch_get_main_queue(), ^(void){ 149 | self.isAnimatingDemo3 = YES; 150 | [self animateDemo3Constraints]; 151 | }); 152 | } 153 | } 154 | 155 | /** 156 | Runs 1 cycle of the animation for demo 3. 157 | 158 | Notes for animating constraints: 159 | - If modifying the constant of a constraint, just set the existing constraint's constant to the new value 160 | - If modifying any other constraint properties, must remove the old constraint and add a new one with the new values 161 | - Must call layoutIfNeeded at end of animation block 162 | */ 163 | - (void)animateDemo3Constraints 164 | { 165 | [UIView animateWithDuration:1.0 166 | delay:0.0 167 | options:UIViewAnimationOptionCurveEaseInOut 168 | animations:^{ 169 | self.demo3BlueBottomInset.constant = -10.0f; 170 | self.demo3BlueRightInset.constant = -50.0f; 171 | self.demo3RedSizeConstraint.constant = 10.0f; 172 | [self.demo3GreenPinConstraint autoRemove]; 173 | self.demo3GreenPinConstraint = [self.greenView autoPinEdge:ALEdgeRight toEdge:ALEdgeRight ofView:self.blueView]; 174 | [self.view layoutIfNeeded]; 175 | } 176 | completion:^(BOOL finished){ 177 | if (self.constraintDemo != ExampleConstraintDemo3) { 178 | self.isAnimatingDemo3 = NO; 179 | return; 180 | } 181 | [UIView animateWithDuration:1.0 182 | delay:0.0 183 | options:UIViewAnimationOptionCurveEaseInOut 184 | animations:^{ 185 | self.demo3BlueBottomInset.constant = -50.0f; 186 | self.demo3BlueRightInset.constant = -10.0f; 187 | self.demo3RedSizeConstraint.constant = -40.0f; 188 | [self.demo3GreenPinConstraint autoRemove]; 189 | self.demo3GreenPinConstraint = [self.greenView autoPinEdge:ALEdgeRight toEdge:ALEdgeRight ofView:self.redView]; 190 | [self.view layoutIfNeeded]; 191 | } 192 | completion:^(BOOL finished) { 193 | if (self.constraintDemo == ExampleConstraintDemo3) { 194 | // Loop the animation while viewing the same demo 195 | [self animateDemo3Constraints]; 196 | } else { 197 | self.isAnimatingDemo3 = NO; 198 | } 199 | }]; 200 | }]; 201 | } 202 | 203 | /** 204 | Demonstrates: 205 | - Achieving a common layout scenario for content (e.g. an image view, title label, and body text) 206 | - Matching the widths of two views using a multiplier 207 | - Pinning views to each other and to the superview to maintain padding and insets 208 | */ 209 | - (void)setupDemo4 210 | { 211 | [self.redView autoSetDimension:ALDimensionHeight toSize:44.0f]; 212 | [self.blueView autoMatchDimension:ALDimensionHeight toDimension:ALDimensionHeight ofView:self.redView]; 213 | 214 | [self.redView autoPinEdgeToSuperviewEdge:ALEdgeLeft withInset:20.0f]; 215 | [self.redView autoPinEdgeToSuperviewEdge:ALEdgeTop withInset:20.0f]; 216 | 217 | [self.blueView autoPinEdgeToSuperviewEdge:ALEdgeRight withInset:20.0f]; 218 | [self.blueView autoPinEdgeToSuperviewEdge:ALEdgeTop withInset:20.0f]; 219 | 220 | [self.blueView autoPinEdge:ALEdgeLeft toEdge:ALEdgeRight ofView:self.redView withOffset:10.0f]; 221 | [self.blueView autoMatchDimension:ALDimensionWidth toDimension:ALDimensionWidth ofView:self.redView withMultiplier:3.0f]; 222 | 223 | [self.orangeView autoPinEdge:ALEdgeTop toEdge:ALEdgeBottom ofView:self.blueView withOffset:20.0f]; 224 | [self.orangeView autoPinEdge:ALEdgeLeft toEdge:ALEdgeLeft ofView:self.redView]; 225 | [self.orangeView autoPinEdge:ALEdgeRight toEdge:ALEdgeRight ofView:self.blueView]; 226 | [self.orangeView autoPinEdgeToSuperviewEdge:ALEdgeBottom withInset:20.0f]; 227 | } 228 | 229 | /** 230 | Demonstrates: 231 | - Everything from Demo 4, and... 232 | - Using leading/trailing edge attributes instead of left/right 233 | (Change language from English to Arabic to see the difference.) 234 | */ 235 | - (void)setupDemo5 236 | { 237 | [self.redView autoSetDimension:ALDimensionHeight toSize:44.0f]; 238 | [self.blueView autoMatchDimension:ALDimensionHeight toDimension:ALDimensionHeight ofView:self.redView]; 239 | 240 | [self.redView autoPinEdgeToSuperviewEdge:ALEdgeLeading withInset:20.0f]; 241 | [self.redView autoPinEdgeToSuperviewEdge:ALEdgeTop withInset:20.0f]; 242 | 243 | [self.blueView autoPinEdgeToSuperviewEdge:ALEdgeTrailing withInset:20.0f]; 244 | [self.blueView autoPinEdgeToSuperviewEdge:ALEdgeTop withInset:20.0f]; 245 | 246 | [self.blueView autoPinEdge:ALEdgeLeading toEdge:ALEdgeTrailing ofView:self.redView withOffset:10.0f]; 247 | [self.blueView autoMatchDimension:ALDimensionWidth toDimension:ALDimensionWidth ofView:self.redView withMultiplier:3.0f]; 248 | 249 | [self.orangeView autoPinEdge:ALEdgeTop toEdge:ALEdgeBottom ofView:self.blueView withOffset:20.0f]; 250 | [self.orangeView autoPinEdge:ALEdgeLeading toEdge:ALEdgeLeading ofView:self.redView withOffset:20.0]; 251 | [self.orangeView autoPinEdge:ALEdgeTrailing toEdge:ALEdgeTrailing ofView:self.blueView withOffset:-10.0]; 252 | [self.orangeView autoPinEdgeToSuperviewEdge:ALEdgeBottom withInset:20.0f]; 253 | } 254 | 255 | /** 256 | Demonstrates: 257 | - Looping over subviews to apply constraints between them 258 | - Setting a priority less than required for specific constraints 259 | - Specifying an inequality constraint that competes with the lower priority constraints 260 | --> the orange view will maintain at least 10 points of spacing to the bottom of its superview (required constraint), 261 | and this may require reducing its height (breaking the lower priority constraint) 262 | */ 263 | - (void)setupDemo6 264 | { 265 | [self.blueView autoPinEdgeToSuperviewEdge:ALEdgeTop withInset:10.0f]; 266 | [self.blueView autoSetDimensionsToSize:CGSizeMake(25.0f, 10.0f)]; 267 | [self.blueView autoAlignAxisToSuperviewAxis:ALAxisVertical]; 268 | 269 | NSArray *subviews = @[self.blueView, self.redView, self.yellowView, self.greenView, self.orangeView]; 270 | 271 | [subviews autoAlignViewsToAxis:ALAxisVertical]; 272 | 273 | UIView *previousView = nil; 274 | for (UIView *view in subviews) { 275 | if (previousView) { 276 | [view autoPinEdge:ALEdgeTop toEdge:ALEdgeBottom ofView:previousView withOffset:10.0f]; 277 | // The orange view will be allowed to change its size if it conflicts with a required constraint 278 | UILayoutPriority priority = (view == self.orangeView) ? UILayoutPriorityDefaultHigh + 1 : UILayoutPriorityRequired; 279 | [UIView autoSetPriority:priority forConstraints:^{ 280 | [view autoMatchDimension:ALDimensionWidth toDimension:ALDimensionWidth ofView:previousView withMultiplier:1.5f]; 281 | [view autoMatchDimension:ALDimensionHeight toDimension:ALDimensionHeight ofView:previousView withMultiplier:2.0f]; 282 | }]; 283 | } 284 | previousView = view; 285 | } 286 | 287 | [self.orangeView autoPinEdge:ALEdgeBottom toEdge:ALEdgeBottom ofView:self.containerView withOffset:-10.0f relation:NSLayoutRelationLessThanOrEqual]; 288 | } 289 | 290 | /** 291 | Demonstrates: 292 | - Applying a constraint across different types of attributes 293 | */ 294 | - (void)setupDemo7 295 | { 296 | [self.redView autoCenterInSuperview]; 297 | [self.redView autoSetDimensionsToSize:CGSizeMake(100.0f, 250.0f)]; 298 | 299 | [self.orangeView autoSetDimensionsToSize:CGSizeMake(50.0f, 50.0f)]; 300 | [self.orangeView autoConstrainAttribute:ALAxisHorizontal toAttribute:ALEdgeTop ofView:self.redView]; 301 | } 302 | 303 | 304 | #pragma mark Private Helper Methods 305 | 306 | /** 307 | Switches to the next demo in the sequence. 308 | Removes all constraints, then calls the next demo's setup method. 309 | */ 310 | - (void)setupConstraintsForCurrentDemo 311 | { 312 | if (self.constraintDemo >= ExampleConstraintDemoCount) { 313 | // Return to the first demo after the last one 314 | self.constraintDemo = ExampleConstraintDemo1; 315 | } 316 | 317 | // WARNING: Be sure to read the documentation on the below method - it can cause major performance issues! 318 | [self.containerView autoRemoveConstraintsAffectingViewAndSubviews]; 319 | 320 | [self.containerView autoPinToTopLayoutGuideOfViewController:self withInset:10.0f]; 321 | [self.containerView autoPinToBottomLayoutGuideOfViewController:self withInset:10.0f]; 322 | [self.containerView autoPinEdgeToSuperviewEdge:ALEdgeLeft withInset:10.0f]; 323 | [self.containerView autoPinEdgeToSuperviewEdge:ALEdgeRight withInset:10.0f]; 324 | 325 | switch (self.constraintDemo) { 326 | case ExampleConstraintDemo1: 327 | [self setupDemo1]; 328 | break; 329 | case ExampleConstraintDemo2: 330 | [self setupDemo2]; 331 | break; 332 | case ExampleConstraintDemo3: 333 | [self setupDemo3]; 334 | break; 335 | case ExampleConstraintDemo4: 336 | [self setupDemo4]; 337 | break; 338 | case ExampleConstraintDemo5: 339 | [self setupDemo5]; 340 | break; 341 | case ExampleConstraintDemo6: 342 | [self setupDemo6]; 343 | break; 344 | case ExampleConstraintDemo7: 345 | [self setupDemo7]; 346 | break; 347 | default: 348 | self.constraintDemo = ExampleConstraintDemoReset; 349 | break; 350 | } 351 | } 352 | 353 | /** 354 | Advances to the next demo and flags the view for a constraint update. 355 | */ 356 | - (void)nextDemo 357 | { 358 | self.constraintDemo++; 359 | [self.view setNeedsUpdateConstraints]; 360 | } 361 | 362 | #pragma mark Property Accessors 363 | 364 | - (UIView *)containerView 365 | { 366 | if (!_containerView) { 367 | _containerView = [UIView newAutoLayoutView]; 368 | _containerView.backgroundColor = [UIColor blackColor]; 369 | } 370 | return _containerView; 371 | } 372 | 373 | - (UIView *)blueView 374 | { 375 | if (!_blueView) { 376 | _blueView = [[UIView alloc] initForAutoLayout]; 377 | _blueView.backgroundColor = [UIColor blueColor]; 378 | } 379 | return _blueView; 380 | } 381 | 382 | - (UIView *)redView 383 | { 384 | if (!_redView) { 385 | _redView = [[UIView alloc] initForAutoLayout]; 386 | _redView.backgroundColor = [UIColor redColor]; 387 | } 388 | return _redView; 389 | } 390 | 391 | - (UIView *)yellowView 392 | { 393 | if (!_yellowView) { 394 | _yellowView = [[UIView alloc] initForAutoLayout]; 395 | _yellowView.backgroundColor = [UIColor yellowColor]; 396 | } 397 | return _yellowView; 398 | } 399 | 400 | - (UIView *)greenView 401 | { 402 | if (!_greenView) { 403 | _greenView = [[UIView alloc] initForAutoLayout]; 404 | _greenView.backgroundColor = [UIColor greenColor]; 405 | } 406 | return _greenView; 407 | } 408 | 409 | - (UILabel *)orangeView 410 | { 411 | if (!_orangeView) { 412 | _orangeView = [[UILabel alloc] initForAutoLayout]; 413 | _orangeView.backgroundColor = [UIColor orangeColor]; 414 | _orangeView.numberOfLines = 0; 415 | _orangeView.font = [UIFont systemFontOfSize:10.0f]; 416 | _orangeView.textColor = [UIColor whiteColor]; 417 | _orangeView.textAlignment = NSTextAlignmentCenter; 418 | _orangeView.text = NSLocalizedString(@"Lorem ipsum", nil); 419 | } 420 | return _orangeView; 421 | } 422 | 423 | - (NSUInteger)supportedInterfaceOrientations 424 | { 425 | return UIInterfaceOrientationMaskAll; 426 | } 427 | 428 | - (BOOL)prefersStatusBarHidden 429 | { 430 | return NO; 431 | } 432 | 433 | @end 434 | -------------------------------------------------------------------------------- /Example/Example/Default-568h@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/smileyborg/UIView-AutoLayout/a84f6e04189048622507559caa1de45d3944da73/Example/Example/Default-568h@2x.png -------------------------------------------------------------------------------- /Example/Example/Default.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/smileyborg/UIView-AutoLayout/a84f6e04189048622507559caa1de45d3944da73/Example/Example/Default.png -------------------------------------------------------------------------------- /Example/Example/Default@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/smileyborg/UIView-AutoLayout/a84f6e04189048622507559caa1de45d3944da73/Example/Example/Default@2x.png -------------------------------------------------------------------------------- /Example/Example/Example-Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleDisplayName 8 | ${PRODUCT_NAME} 9 | CFBundleExecutable 10 | ${EXECUTABLE_NAME} 11 | CFBundleIdentifier 12 | com.smileyborg.${PRODUCT_NAME:rfc1034identifier} 13 | CFBundleInfoDictionaryVersion 14 | 6.0 15 | CFBundleName 16 | ${PRODUCT_NAME} 17 | CFBundlePackageType 18 | APPL 19 | CFBundleShortVersionString 20 | 1.0 21 | CFBundleSignature 22 | ???? 23 | CFBundleVersion 24 | 1.0 25 | LSRequiresIPhoneOS 26 | 27 | UIRequiredDeviceCapabilities 28 | 29 | armv7 30 | 31 | UIStatusBarHidden 32 | 33 | UISupportedInterfaceOrientations 34 | 35 | UIInterfaceOrientationPortrait 36 | UIInterfaceOrientationLandscapeLeft 37 | UIInterfaceOrientationLandscapeRight 38 | UIInterfaceOrientationPortraitUpsideDown 39 | 40 | 41 | 42 | -------------------------------------------------------------------------------- /Example/Example/Example-Prefix.pch: -------------------------------------------------------------------------------- 1 | // 2 | // Prefix header for all source files of the 'Example' target in the 'Example' project 3 | // 4 | 5 | #import 6 | 7 | #ifndef __IPHONE_4_0 8 | #warning "This project uses features only available in iOS SDK 4.0 and later." 9 | #endif 10 | 11 | #ifdef __OBJC__ 12 | #import 13 | #import 14 | #endif 15 | 16 | #import "UIView+AutoLayout.h" 17 | -------------------------------------------------------------------------------- /Example/Example/ar.lproj/ALViewController.xib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 1552 5 | 12E55 6 | 3084 7 | 1187.39 8 | 626.00 9 | 10 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 11 | 2083 12 | 13 | 14 | IBProxyObject 15 | IBUIView 16 | 17 | 18 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 19 | 20 | 21 | PluginDependencyRecalculationVersion 22 | 23 | 24 | 25 | 26 | IBFilesOwner 27 | IBCocoaTouchFramework 28 | 29 | 30 | IBFirstResponder 31 | IBCocoaTouchFramework 32 | 33 | 34 | 35 | 274 36 | 37 | {{0, 20}, {320, 548}} 38 | 39 | 40 | 41 | 3 42 | MQA 43 | 44 | NO 45 | 46 | 47 | IBUIScreenMetrics 48 | 49 | YES 50 | 51 | 52 | 53 | 54 | 55 | {320, 568} 56 | {568, 320} 57 | 58 | 59 | IBCocoaTouchFramework 60 | Retina 4 Full Screen 61 | 2 62 | 63 | IBCocoaTouchFramework 64 | 65 | 66 | 67 | 68 | 69 | 70 | view 71 | 72 | 73 | 74 | 7 75 | 76 | 77 | 78 | 79 | 80 | 0 81 | 82 | 83 | 84 | 85 | 86 | -1 87 | 88 | 89 | File's Owner 90 | 91 | 92 | -2 93 | 94 | 95 | 96 | 97 | 6 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | ALViewController 106 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 107 | UIResponder 108 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 109 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 110 | 111 | 112 | 113 | 114 | 115 | 49 116 | 117 | 118 | 0 119 | IBCocoaTouchFramework 120 | YES 121 | 3 122 | YES 123 | 2083 124 | 125 | 126 | -------------------------------------------------------------------------------- /Example/Example/ar.lproj/InfoPlist.strings: -------------------------------------------------------------------------------- 1 | /* Localized versions of Info.plist keys */ 2 | 3 | -------------------------------------------------------------------------------- /Example/Example/ar.lproj/Localizable.strings: -------------------------------------------------------------------------------- 1 | /* 2 | Localizable.strings 3 | Example 4 | 5 | Created by David Dancy on 2/09/13. 6 | 7 | */ 8 | 9 | "Lorem ipsum" = "فقد بقصف تغييرات الفرنسية ان. قد ماشاء والجنود مكن. أن بمباركة الإثنان به،. سقط استعملت البشريةً النازية، من, ذات ولكسمبورغ وباستثناء عل. بل بالحرب إستسلاماً فقد, أن أخذ شعار الغازية, وحزبه بتخصيص بحق ان. تاريخ الإمتعاض هذه مع, ان وجزر كنقطة استرجاع قهر. كان للإتحاد ستالينجراد، بـ, الضروري الباهضة لان تم. 10 | 11 | عام عل رجوعهم وتنامت الفرنسية, مهاجمة إستعمل الإنذار، دنو تم. دون وأسرت طوكيو الستار أي, ٣٠ بمحاولة الصينية جوي, الهجوم بالمثل، البريطانيين غير بـ. لم لان أدنى أحدث النمسا. إحتلال البريطانيين وقد من, الحكومة الموسوعة أم على. بزوال لهيمنة أخذ ٣٠. 12 | 13 | حشد تم تنفّس تعداد, قام من قامت طرفاً للأسطول. الخاسر وصافرات الأوضاع بـ قبل, عل حدة الآلاف بتحدّي, كل حول تمهيد لليابان. فسقط وحتى الامم بين ثم, ودول كُلفة الإحتلال بعض ما. عالمية الأوروبية، تحت أن. كان عن تجهيز أثره، انتصارهم, عل أصقاع ونستون الباهضة بلا, دون هو حربية معارضة ديسمبر. الأمور استعملت حتى عل. 14 | 15 | تم خلاف حقول الإيطالية أما. جنوب والإتحاد دون ٣٠. حول الدمج الألمان الجنوبي بـ. و تشرشل النفط دون. هو المواد الإنجليز، قبل, بها اكتوبر النازي كل, أمّا للمجهود مع جُل. 16 | 17 | عصبة قِبل هو غزو. دول عجّل بتطويق مقاومة قد. بقعة الدّفاع عام أن. على أم الغربي شموليةً الكونجرس, فصل كل بيرل أسيا اتفاقية. معركة استسلام أم دنو. 18 | 19 | لكل ٣٠ مرمى الأمامية ماليزيا،. وصغار مهمّات والكساد به، بل, دنو مئات أراض نورماندي و, ان ومن إنطلاق الإمداد الإحتلال. الآخر باستخدام في دار, بـ عدد تصرّف أجزاء, وعلى الجو تكتيكاً ان بين. العظمى الأبرياء أم وضم. فعل أمّا والإتحاد البولندي ثم, انه وتردي الأمور الدّفاع لم. 20 | 21 | حول ستالين مقاطعة ٣٠, إذ أخر اعتداء محاولات, فعل استسلام الجنوبي ٣٠. لها قد وبالرغم الخاصّة بالولايات, بـ دارت ثمّة الإيطالية غزو. ٣٠ هُزم يونيو الألوف قصف. أم وقد تحرّك الأجل. وأسرت يعادل هذا أي. 22 | 23 | طرفاً الثقيل وبولندا لها في. و ضرب وعلى مهانة, مما تم سقطت بلاده نورمبرغ. واُسدل للحكومة عن مكن. جوي حاول أواخر الياباني، من, أي يقوم وانهاء ولاتّساع نفس. بولندا الهزائم الأوروبي ٣٠ قهر. وحلفاؤها ناجازاكي إظهارإخفاء جوي تم, وقامت أسابيع اندلاع كما مع, الحصار الأوروبي في عدد. 24 | 25 | بها إذ جوزيف تشيرشل, الذرية محاولات الدنمارك جعل ثم. مع يونيو الإنزال انه, ان لعملة باستسلام الإنذار، قهر, دون أي الصيني اوروبا. ان أوسع بأضرار بالجانب حدى, ٣٠ الآخر المقيتة الساحلية أضف. أخذ عن ثانية الحاملات, إذ دار والقرى مهمّات. ومن أي بهيئة الإتفاقية الألمانية،. 26 | 27 | كنقطة الآخر لبولندا مكن بل. هذا تم وبحلول الدنمارك, نتيجة والعتاد لمّ عل. كان الحرة تكبّلتها أي. كان الجوي المقيتة من, المؤلّفة الأمريكي دحر تم. 28 | "; -------------------------------------------------------------------------------- /Example/Example/en.lproj/ALViewController.xib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 1552 5 | 12E55 6 | 3084 7 | 1187.39 8 | 626.00 9 | 10 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 11 | 2083 12 | 13 | 14 | IBProxyObject 15 | IBUIView 16 | 17 | 18 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 19 | 20 | 21 | PluginDependencyRecalculationVersion 22 | 23 | 24 | 25 | 26 | IBFilesOwner 27 | IBCocoaTouchFramework 28 | 29 | 30 | IBFirstResponder 31 | IBCocoaTouchFramework 32 | 33 | 34 | 35 | 274 36 | 37 | {{0, 20}, {320, 548}} 38 | 39 | 40 | 41 | 3 42 | MQA 43 | 44 | NO 45 | 46 | 47 | IBUIScreenMetrics 48 | 49 | YES 50 | 51 | 52 | 53 | 54 | 55 | {320, 568} 56 | {568, 320} 57 | 58 | 59 | IBCocoaTouchFramework 60 | Retina 4 Full Screen 61 | 2 62 | 63 | IBCocoaTouchFramework 64 | 65 | 66 | 67 | 68 | 69 | 70 | view 71 | 72 | 73 | 74 | 7 75 | 76 | 77 | 78 | 79 | 80 | 0 81 | 82 | 83 | 84 | 85 | 86 | -1 87 | 88 | 89 | File's Owner 90 | 91 | 92 | -2 93 | 94 | 95 | 96 | 97 | 6 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | ALViewController 106 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 107 | UIResponder 108 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 109 | com.apple.InterfaceBuilder.IBCocoaTouchPlugin 110 | 111 | 112 | 113 | 114 | 115 | 49 116 | 117 | 118 | 0 119 | IBCocoaTouchFramework 120 | YES 121 | 3 122 | YES 123 | 2083 124 | 125 | 126 | -------------------------------------------------------------------------------- /Example/Example/en.lproj/InfoPlist.strings: -------------------------------------------------------------------------------- 1 | /* Localized versions of Info.plist keys */ 2 | 3 | -------------------------------------------------------------------------------- /Example/Example/en.lproj/Localizable.strings: -------------------------------------------------------------------------------- 1 | /* 2 | Localizable.strings 3 | Example 4 | 5 | Created by David Dancy on 2/09/13. 6 | 7 | */ 8 | 9 | "Lorem ipsum" = "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nullam in lacus sit amet tellus feugiat ultricies congue quis eros. Etiam vel laoreet nunc. Cras orci nisl, laoreet eget congue a, convallis vel risus. Integer molestie leo a justo fermentum malesuada. Maecenas aliquet leo nec aliquet sodales. Aenean pretium mollis sapien. Aenean tristique mi ac purus vulputate imperdiet. Sed porta pharetra nisi, nec lobortis massa ullamcorper dignissim. Quisque sem tellus, bibendum vel suscipit ut, commodo in justo. Suspendisse ullamcorper dapibus lectus, nec sollicitudin est porta id. Mauris augue lectus, pharetra ac vulputate ut, dignissim a velit. Phasellus feugiat imperdiet lacus, id vestibulum nibh elementum ornare. Phasellus non enim quis lectus vestibulum convallis ut id nibh. Nam ac est rutrum est dignissim gravida. Curabitur hendrerit iaculis magna, ut rhoncus massa iaculis in. Duis pulvinar mauris eu mauris porttitor hendrerit sed a tellus. Sed lacinia risus vitae est scelerisque, in mattis sem tristique. Fusce malesuada condimentum quam sit amet rhoncus. Praesent lobortis nisi eget lorem condimentum mollis. Sed porta metus elit, vel luctus orci semper sit amet. Fusce laoreet laoreet lectus. Etiam molestie egestas odio vel viverra. Curabitur odio magna, fermentum sit amet arcu a, euismod vestibulum odio. Cras ipsum diam, blandit et sapien vitae, gravida iaculis odio. Pellentesque tincidunt diam ac tincidunt tempus. Cras volutpat adipiscing turpis. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Nam imperdiet urna condimentum quam laoreet, vel semper mi suscipit. Ut scelerisque lacus ac dolor sodales, ac fringilla ipsum tincidunt. Donec sollicitudin aliquam metus, ut congue nisl vestibulum in."; -------------------------------------------------------------------------------- /Example/Example/main.m: -------------------------------------------------------------------------------- 1 | // 2 | // main.m 3 | // Example 4 | // 5 | // Copyright (c) 2013 Tyler Fox 6 | // https://github.com/smileyborg/UIView-AutoLayout 7 | // 8 | 9 | #import 10 | 11 | #import "ALAppDelegate.h" 12 | 13 | int main(int argc, char *argv[]) 14 | { 15 | @autoreleasepool { 16 | return UIApplicationMain(argc, argv, nil, NSStringFromClass([ALAppDelegate class])); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | This code is distributed under the terms and conditions of the MIT license. 2 | 3 | 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: 4 | 5 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 6 | 7 | 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. 8 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Introducing [PureLayout](https://github.com/smileyborg/PureLayout) 2 | ======================== 3 | ### UIView+AutoLayout has been deprecated in favor of [PureLayout](https://github.com/smileyborg/PureLayout), which includes OS X support! 4 | 5 | UIView+AutoLayout [![Build Status](https://travis-ci.org/smileyborg/UIView-AutoLayout.svg?branch=master)](https://travis-ci.org/smileyborg/UIView-AutoLayout) 6 | ================= 7 | 8 | The ultimate API for iOS Auto Layout -- impressively simple, immensely powerful. Comprised of categories on `UIView`, `NSArray`, and `NSLayoutConstraint`. 9 | 10 | UIView+AutoLayout provides a developer-friendly interface for the vast majority of Auto Layout use cases. It is designed for clarity and simplicity, taking inspiration from the Auto Layout UI options available in Interface Builder but delivering far more flexibility and capability. The API is also highly efficient, as it adds only a thin layer of third party code and is engineered for maximum performance (for example, by automatically adding constraints to the nearest ancestor view). 11 | 12 | API Cheat Sheet 13 | --------------- 14 | 15 | This is just a handy overview of the core API methods. Check out the [header file](https://github.com/smileyborg/UIView-AutoLayout/blob/master/Source/UIView%2BAutoLayout.h) for the full API and documentation. A couple notes: 16 | 17 | * *All of the API methods begin with `auto...` for easy autocompletion!* 18 | * *All methods that generate constraints also automatically add the constraint(s) to the correct view, then return the newly created constraint(s) for you to optionally store for later adjustment or removal.* 19 | * *Many methods below also have a variant which includes a `relation:` parameter to make the constraint an inequality.* 20 | 21 | **`UIView`** 22 | 23 | + autoRemoveConstraint(s): 24 | - autoRemoveConstraintsAffectingView(AndSubviews) 25 | + autoSetPriority:forConstraints: 26 | - autoSetContent(CompressionResistance|Hugging)PriorityForAxis: 27 | - autoCenterInSuperview: 28 | - autoAlignAxisToSuperviewAxis: 29 | - autoPinEdgeToSuperviewEdge:withInset: 30 | - autoPinEdgesToSuperviewEdges:withInsets:(excludingEdge:) 31 | - autoPinEdge:toEdge:ofView:(withOffset:) 32 | - autoAlignAxis:toSameAxisOfView:(withOffset:) 33 | - autoMatchDimension:toDimension:ofView:(withOffset:|withMultiplier:) 34 | - autoSetDimension(s)ToSize: 35 | - autoConstrainAttribute:toAttribute:ofView:(withOffset:|withMultiplier:) 36 | - autoPinTo(Top|Bottom)LayoutGuideOfViewController:withInset: 37 | 38 | **`NSArray`** 39 | 40 | - autoAlignViewsToEdge: 41 | - autoAlignViewsToAxis: 42 | - autoMatchViewsDimension: 43 | - autoSetViewsDimension:toSize: 44 | - autoDistributeViewsAlongAxis:withFixedSpacing:(insetSpacing:)alignment: 45 | - autoDistributeViewsAlongAxis:withFixedSize:(insetSpacing:)alignment: 46 | 47 | **`NSLayoutConstraint`** 48 | 49 | - autoInstall 50 | - autoRemove 51 | 52 | Setup 53 | ----- 54 | *Note: you must be developing for iOS 6.0 or later to use Auto Layout.* 55 | 56 | **Using [CocoaPods](http://cocoapods.org)** 57 | 58 | 1. Add the pod `UIView+AutoLayout` to your [Podfile](http://guides.cocoapods.org/using/the-podfile.html). 59 | 60 | pod 'UIView+AutoLayout' 61 | 62 | 2. Run `pod install` from Terminal, then open your app's `.xcworkspace` file to launch Xcode. 63 | 3. `#import "UIView+AutoLayout.h"` wherever you want to use the API. *(Hint: adding the import to your precompiled header (.pch) file once will remove the need to import the .h file everywhere!)* 64 | 65 | That's it - now go write some beautifully simple Auto Layout code! 66 | 67 | **Manually from GitHub** 68 | 69 | 1. Download the `UIView+AutoLayout.h` and `UIView+AutoLayout.m` files in the [Source directory](https://github.com/smileyborg/UIView-AutoLayout/tree/master/Source). 70 | 2. Add both files to your Xcode project. 71 | 3. `#import "UIView+AutoLayout.h"` wherever you want to use the API. *(Hint: adding the import to your precompiled header (.pch) file once will remove the need to import the .h file everywhere!)* 72 | 73 | That's it - now go write some beautifully simple Auto Layout code! 74 | 75 | **Releases** 76 | 77 | 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/UIView-AutoLayout/releases) for each version. 78 | 79 | Usage 80 | ----- 81 | 82 | **Example Project** 83 | 84 | Check out the [example project](https://github.com/smileyborg/UIView-AutoLayout/blob/master/Example/) included in the repository. It contains a few demos of the API in use for various scenarios. While running the app, tap on the screen to cycle through the demos. You can rotate the device to see the constraints in action (as well as toggle the taller in-call status bar in the iOS Simulator). 85 | 86 | **Tips and Tricks** 87 | 88 | Check out some [Tips and Tricks](https://github.com/smileyborg/UIView-AutoLayout/wiki/Tips-and-Tricks) to keep in mind when using the API. 89 | 90 | Limitations 91 | ----------- 92 | 93 | * May need to use the `NSLayoutConstraint` SDK API directly for some extremely uncommon use cases 94 | 95 | UIView+AutoLayout vs. the rest 96 | ------------------------------ 97 | 98 | An overview of the Auto Layout options available, ordered from the lowest- to highest-level of abstraction. 99 | 100 | * Apple [NSLayoutConstraint SDK API](https://developer.apple.com/library/ios/documentation/AppKit/Reference/NSLayoutConstraint_Class/NSLayoutConstraint/NSLayoutConstraint.html#//apple_ref/doc/uid/TP40010628-CH1-SW18) 101 | * Pros: Raw power 102 | * Cons: Extremely verbose, tedious to write, difficult to read 103 | * Apple [Visual Format Language](https://developer.apple.com/library/ios/documentation/UserExperience/Conceptual/AutolayoutPG/VisualFormatLanguage/VisualFormatLanguage.html) 104 | * Pros: Concise, convenient 105 | * Cons: Doesn't support some use cases, incomplete compile-time checks, must learn syntax, hard to debug 106 | * Apple Interface Builder 107 | * Pros: Visual, simple 108 | * Cons: Difficult for complex layouts, cannot dynamically set constraints at runtime, encourages hardcoded magic numbers, not always WYSIWYG 109 | * **UIView+AutoLayout** 110 | * Pros: Simple, efficient, built directly on the iOS SDK, minimal third party code 111 | * Cons: Not the most concise or pure expression of layout code 112 | * High-level layout frameworks ([Masonry](https://github.com/cloudkite/Masonry), [KeepLayout](https://github.com/iMartinKiss/KeepLayout)) 113 | * Pros: Very clean, simple, and convenient 114 | * Cons: Heavy dependency on third party code, cannot mix with SDK APIs, potential compatibility issues with SDK changes, overloaded Objective-C syntax 115 | 116 | Problems, Suggestions, Pull Requests? 117 | ------------------------------------- 118 | 119 | Bring 'em on! :) 120 | 121 | It's always a good idea to reach out before taking on any significant amount of changes or additions to the project. This allows everyone to get onboard with upcoming changes, ensures that changes align with the project's design philosophy, and avoids duplicated work. 122 | 123 | I'm especially interested in hearing about any common use cases that this API does not currently address. Feel free to add feature requests (and view current work in progress) on the [Feature Requests](https://github.com/smileyborg/UIView-AutoLayout/wiki/Feature-Requests) page of the wiki for this project. 124 | 125 | Meta 126 | ---- 127 | 128 | Designed & maintained by Tyler Fox ([@smileyborg](https://twitter.com/smileyborg)). Distributed with the MIT license. 129 | -------------------------------------------------------------------------------- /Source/UIView+AutoLayout.h: -------------------------------------------------------------------------------- 1 | // 2 | // UIView+AutoLayout.h 3 | // v2.0.0 4 | // https://github.com/smileyborg/UIView-AutoLayout 5 | // 6 | // Copyright (c) 2012 Richard Turton 7 | // Copyright (c) 2013 Tyler Fox 8 | // 9 | // This code is distributed under the terms and conditions of the MIT license. 10 | // 11 | // Permission is hereby granted, free of charge, to any person obtaining a copy 12 | // of this software and associated documentation files (the "Software"), to 13 | // deal in the Software without restriction, including without limitation the 14 | // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 15 | // sell copies of the Software, and to permit persons to whom the Software is 16 | // furnished to do so, subject to the following conditions: 17 | // 18 | // The above copyright notice and this permission notice shall be included in 19 | // all copies or substantial portions of the Software. 20 | // 21 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 22 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 23 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 24 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 25 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 26 | // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 27 | // IN THE SOFTWARE. 28 | // 29 | 30 | #import 31 | 32 | #pragma mark ALAttributes 33 | 34 | typedef NS_ENUM(NSInteger, ALEdge) { 35 | ALEdgeLeft = NSLayoutAttributeLeft, // the left edge of the view 36 | ALEdgeRight = NSLayoutAttributeRight, // the right edge of the view 37 | ALEdgeTop = NSLayoutAttributeTop, // the top edge of the view 38 | ALEdgeBottom = NSLayoutAttributeBottom, // the bottom edge of the view 39 | ALEdgeLeading = NSLayoutAttributeLeading, // the leading edge of the view (left edge for left-to-right languages like English, right edge for right-to-left languages like Arabic) 40 | ALEdgeTrailing = NSLayoutAttributeTrailing // the trailing edge of the view (right edge for left-to-right languages like English, left edge for right-to-left languages like Arabic) 41 | }; 42 | 43 | typedef NS_ENUM(NSInteger, ALDimension) { 44 | ALDimensionWidth = NSLayoutAttributeWidth, // the width of the view 45 | ALDimensionHeight = NSLayoutAttributeHeight // the height of the view 46 | }; 47 | 48 | typedef NS_ENUM(NSInteger, ALAxis) { 49 | ALAxisVertical = NSLayoutAttributeCenterX, // a vertical line through the center of the view 50 | ALAxisHorizontal = NSLayoutAttributeCenterY, // a horizontal line through the center of the view 51 | ALAxisBaseline = NSLayoutAttributeBaseline // a horizontal line at the text baseline (not applicable to all views) 52 | }; 53 | 54 | typedef void(^ALConstraintsBlock)(void); // a block of method calls to the UIView+AutoLayout category API 55 | 56 | 57 | #pragma mark - UIView+AutoLayout 58 | 59 | /** 60 | A category on UIView that provides a simple yet powerful interface for creating Auto Layout constraints. 61 | */ 62 | @interface UIView (AutoLayout) 63 | 64 | 65 | #pragma mark Factory & Initializer Methods 66 | 67 | /** Creates and returns a new view that does not convert the autoresizing mask into constraints. */ 68 | + (instancetype)newAutoLayoutView; 69 | 70 | /** Initializes and returns a new view that does not convert the autoresizing mask into constraints. */ 71 | - (instancetype)initForAutoLayout; 72 | 73 | 74 | #pragma mark Set Constraint Priority 75 | 76 | /** Sets the constraint priority to the given value for all constraints created using the UIView+AutoLayout category API within the given constraints block. 77 | NOTE: This method will have no effect (and will NOT set the priority) on constraints created or added using the SDK directly within the block! */ 78 | + (void)autoSetPriority:(UILayoutPriority)priority forConstraints:(ALConstraintsBlock)block; 79 | 80 | 81 | #pragma mark Remove Constraints 82 | 83 | /** Removes the given constraint from the view it has been added to. */ 84 | + (void)autoRemoveConstraint:(NSLayoutConstraint *)constraint; 85 | 86 | /** Removes the given constraints from the views they have been added to. */ 87 | + (void)autoRemoveConstraints:(NSArray *)constraints; 88 | 89 | /** Removes all explicit constraints that affect the view. 90 | WARNING: Apple's constraint solver is not optimized for large-scale constraint removal; you may encounter major performance issues after using this method. 91 | NOTE: This method preserves implicit constraints, such as intrinsic content size constraints, which you usually do not want to remove. */ 92 | - (void)autoRemoveConstraintsAffectingView; 93 | 94 | /** Removes all constraints that affect the view, optionally including implicit constraints. 95 | WARNING: Apple's constraint solver is not optimized for large-scale constraint removal; you may encounter major performance issues after using this method. 96 | NOTE: Implicit constraints are auto-generated lower priority constraints, and you usually do not want to remove these. */ 97 | - (void)autoRemoveConstraintsAffectingViewIncludingImplicitConstraints:(BOOL)shouldRemoveImplicitConstraints; 98 | 99 | /** Recursively removes all explicit constraints that affect the view and its subviews. 100 | WARNING: Apple's constraint solver is not optimized for large-scale constraint removal; you may encounter major performance issues after using this method. 101 | NOTE: This method preserves implicit constraints, such as intrinsic content size constraints, which you usually do not want to remove. */ 102 | - (void)autoRemoveConstraintsAffectingViewAndSubviews; 103 | 104 | /** Recursively removes all constraints from the view and its subviews, optionally including implicit constraints. 105 | WARNING: Apple's constraint solver is not optimized for large-scale constraint removal; you may encounter major performance issues after using this method. 106 | NOTE: Implicit constraints are auto-generated lower priority constraints, and you usually do not want to remove these. */ 107 | - (void)autoRemoveConstraintsAffectingViewAndSubviewsIncludingImplicitConstraints:(BOOL)shouldRemoveImplicitConstraints; 108 | 109 | 110 | #pragma mark Center in Superview 111 | 112 | /** Centers the view in its superview. */ 113 | - (NSArray *)autoCenterInSuperview; 114 | 115 | /** Aligns the view to the same axis of its superview. */ 116 | - (NSLayoutConstraint *)autoAlignAxisToSuperviewAxis:(ALAxis)axis; 117 | 118 | 119 | #pragma mark Pin Edges to Superview 120 | 121 | /** Pins the given edge of the view to the same edge of the superview with an inset. */ 122 | - (NSLayoutConstraint *)autoPinEdgeToSuperviewEdge:(ALEdge)edge withInset:(CGFloat)inset; 123 | 124 | /** Pins the given edge of the view to the same edge of the superview with an inset as a maximum or minimum. */ 125 | - (NSLayoutConstraint *)autoPinEdgeToSuperviewEdge:(ALEdge)edge withInset:(CGFloat)inset relation:(NSLayoutRelation)relation; 126 | 127 | /** Pins the edges of the view to the edges of its superview with the given edge insets. */ 128 | - (NSArray *)autoPinEdgesToSuperviewEdgesWithInsets:(UIEdgeInsets)insets; 129 | 130 | /** Pins 3 of the 4 edges of the view to the edges of its superview with the given edge insets, excluding one edge. */ 131 | - (NSArray *)autoPinEdgesToSuperviewEdgesWithInsets:(UIEdgeInsets)insets excludingEdge:(ALEdge)edge; 132 | 133 | 134 | #pragma mark Pin Edges 135 | 136 | /** Pins an edge of the view to a given edge of another view. */ 137 | - (NSLayoutConstraint *)autoPinEdge:(ALEdge)edge toEdge:(ALEdge)toEdge ofView:(UIView *)peerView; 138 | 139 | /** Pins an edge of the view to a given edge of another view with an offset. */ 140 | - (NSLayoutConstraint *)autoPinEdge:(ALEdge)edge toEdge:(ALEdge)toEdge ofView:(UIView *)peerView withOffset:(CGFloat)offset; 141 | 142 | /** Pins an edge of the view to a given edge of another view with an offset as a maximum or minimum. */ 143 | - (NSLayoutConstraint *)autoPinEdge:(ALEdge)edge toEdge:(ALEdge)toEdge ofView:(UIView *)peerView withOffset:(CGFloat)offset relation:(NSLayoutRelation)relation; 144 | 145 | 146 | #pragma mark Align Axes 147 | 148 | /** Aligns an axis of the view to the same axis of another view. */ 149 | - (NSLayoutConstraint *)autoAlignAxis:(ALAxis)axis toSameAxisOfView:(UIView *)peerView; 150 | 151 | /** Aligns an axis of the view to the same axis of another view with an offset. */ 152 | - (NSLayoutConstraint *)autoAlignAxis:(ALAxis)axis toSameAxisOfView:(UIView *)peerView withOffset:(CGFloat)offset; 153 | 154 | 155 | #pragma mark Match Dimensions 156 | 157 | /** Matches a dimension of the view to a given dimension of another view. */ 158 | - (NSLayoutConstraint *)autoMatchDimension:(ALDimension)dimension toDimension:(ALDimension)toDimension ofView:(UIView *)peerView; 159 | 160 | /** Matches a dimension of the view to a given dimension of another view with an offset. */ 161 | - (NSLayoutConstraint *)autoMatchDimension:(ALDimension)dimension toDimension:(ALDimension)toDimension ofView:(UIView *)peerView withOffset:(CGFloat)offset; 162 | 163 | /** Matches a dimension of the view to a given dimension of another view with an offset as a maximum or minimum. */ 164 | - (NSLayoutConstraint *)autoMatchDimension:(ALDimension)dimension toDimension:(ALDimension)toDimension ofView:(UIView *)peerView withOffset:(CGFloat)offset relation:(NSLayoutRelation)relation; 165 | 166 | /** Matches a dimension of the view to a multiple of a given dimension of another view. */ 167 | - (NSLayoutConstraint *)autoMatchDimension:(ALDimension)dimension toDimension:(ALDimension)toDimension ofView:(UIView *)peerView withMultiplier:(CGFloat)multiplier; 168 | 169 | /** Matches a dimension of the view to a multiple of a given dimension of another view as a maximum or minimum. */ 170 | - (NSLayoutConstraint *)autoMatchDimension:(ALDimension)dimension toDimension:(ALDimension)toDimension ofView:(UIView *)peerView withMultiplier:(CGFloat)multiplier relation:(NSLayoutRelation)relation; 171 | 172 | 173 | #pragma mark Set Dimensions 174 | 175 | /** Sets the view to a specific size. */ 176 | - (NSArray *)autoSetDimensionsToSize:(CGSize)size; 177 | 178 | /** Sets the given dimension of the view to a specific size. */ 179 | - (NSLayoutConstraint *)autoSetDimension:(ALDimension)dimension toSize:(CGFloat)size; 180 | 181 | /** Sets the given dimension of the view to a specific size as a maximum or minimum. */ 182 | - (NSLayoutConstraint *)autoSetDimension:(ALDimension)dimension toSize:(CGFloat)size relation:(NSLayoutRelation)relation; 183 | 184 | 185 | #pragma mark Set Content Compression Resistance & Hugging 186 | 187 | /** Sets the priority of content compression resistance for an axis. 188 | NOTE: This method must only be called from within the block passed into the method +[UIView autoSetPriority:forConstraints:] */ 189 | - (void)autoSetContentCompressionResistancePriorityForAxis:(ALAxis)axis; 190 | 191 | /** Sets the priority of content hugging for an axis. 192 | NOTE: This method must only be called from within the block passed into the method +[UIView autoSetPriority:forConstraints:] */ 193 | - (void)autoSetContentHuggingPriorityForAxis:(ALAxis)axis; 194 | 195 | 196 | #pragma mark Constrain Any Attributes 197 | 198 | /** Constrains an attribute (any ALEdge, ALAxis, or ALDimension) of the view to a given attribute of another view. */ 199 | - (NSLayoutConstraint *)autoConstrainAttribute:(NSInteger)attribute toAttribute:(NSInteger)toAttribute ofView:(UIView *)peerView; 200 | 201 | /** Constrains an attribute (any ALEdge, ALAxis, or ALDimension) of the view to a given attribute of another view with an offset. */ 202 | - (NSLayoutConstraint *)autoConstrainAttribute:(NSInteger)attribute toAttribute:(NSInteger)toAttribute ofView:(UIView *)peerView withOffset:(CGFloat)offset; 203 | 204 | /** Constrains an attribute (any ALEdge, ALAxis, or ALDimension) of the view to a given attribute of another view with an offset as a maximum or minimum. */ 205 | - (NSLayoutConstraint *)autoConstrainAttribute:(NSInteger)attribute toAttribute:(NSInteger)toAttribute ofView:(UIView *)peerView withOffset:(CGFloat)offset relation:(NSLayoutRelation)relation; 206 | 207 | /** Constrains an attribute (any ALEdge, ALAxis, or ALDimension) of the view to a given attribute of another view with a multiplier. */ 208 | - (NSLayoutConstraint *)autoConstrainAttribute:(NSInteger)attribute toAttribute:(NSInteger)toAttribute ofView:(UIView *)peerView withMultiplier:(CGFloat)multiplier; 209 | 210 | /** Constrains an attribute (any ALEdge, ALAxis, or ALDimension) of the view to a given attribute of another view with a multiplier as a maximum or minimum. */ 211 | - (NSLayoutConstraint *)autoConstrainAttribute:(NSInteger)attribute toAttribute:(NSInteger)toAttribute ofView:(UIView *)peerView withMultiplier:(CGFloat)multiplier relation:(NSLayoutRelation)relation; 212 | 213 | 214 | #pragma mark Pin to Layout Guides 215 | 216 | /** Pins the top edge of the view to the top layout guide of the given view controller with an inset. */ 217 | - (NSLayoutConstraint *)autoPinToTopLayoutGuideOfViewController:(UIViewController *)viewController withInset:(CGFloat)inset; 218 | 219 | /** Pins the bottom edge of the view to the bottom layout guide of the given view controller with an inset. */ 220 | - (NSLayoutConstraint *)autoPinToBottomLayoutGuideOfViewController:(UIViewController *)viewController withInset:(CGFloat)inset; 221 | 222 | @end 223 | 224 | 225 | #pragma mark - NSArray+AutoLayout 226 | 227 | /** 228 | A category on NSArray that provides a simple yet powerful interface for applying constraints to groups of views. 229 | */ 230 | @interface NSArray (AutoLayout) 231 | 232 | 233 | #pragma mark Constrain Multiple Views 234 | 235 | /** Aligns views in this array to one another along a given edge. */ 236 | - (NSArray *)autoAlignViewsToEdge:(ALEdge)edge; 237 | 238 | /** Aligns views in this array to one another along a given axis. */ 239 | - (NSArray *)autoAlignViewsToAxis:(ALAxis)axis; 240 | 241 | /** Matches a given dimension of all the views in this array. */ 242 | - (NSArray *)autoMatchViewsDimension:(ALDimension)dimension; 243 | 244 | /** Sets the given dimension of all the views in this array to a given size. */ 245 | - (NSArray *)autoSetViewsDimension:(ALDimension)dimension toSize:(CGFloat)size; 246 | 247 | 248 | #pragma mark Distribute Multiple Views 249 | 250 | /** 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. */ 251 | - (NSArray *)autoDistributeViewsAlongAxis:(ALAxis)axis withFixedSpacing:(CGFloat)spacing alignment:(NSLayoutFormatOptions)alignment; 252 | 253 | /** 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. */ 254 | - (NSArray *)autoDistributeViewsAlongAxis:(ALAxis)axis withFixedSpacing:(CGFloat)spacing insetSpacing:(BOOL)shouldSpaceInsets alignment:(NSLayoutFormatOptions)alignment; 255 | 256 | /** 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. */ 257 | - (NSArray *)autoDistributeViewsAlongAxis:(ALAxis)axis withFixedSize:(CGFloat)size alignment:(NSLayoutFormatOptions)alignment; 258 | 259 | /** 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. */ 260 | - (NSArray *)autoDistributeViewsAlongAxis:(ALAxis)axis withFixedSize:(CGFloat)size insetSpacing:(BOOL)shouldSpaceInsets alignment:(NSLayoutFormatOptions)alignment; 261 | 262 | @end 263 | 264 | 265 | #pragma mark - NSLayoutConstraint+AutoLayout 266 | 267 | /** 268 | A category on NSLayoutConstraint that allows constraints to be easily removed. 269 | */ 270 | @interface NSLayoutConstraint (AutoLayout) 271 | 272 | /** Adds the constraint to the appropriate view. */ 273 | - (void)autoInstall; 274 | 275 | /** Removes the constraint from the view it has been added to. */ 276 | - (void)autoRemove; 277 | 278 | @end 279 | -------------------------------------------------------------------------------- /Tests/AutoLayout.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | A766F3551943D6E200690164 /* AutoLayoutInstallationTests.m in Sources */ = {isa = PBXBuildFile; fileRef = A766F3541943D6E200690164 /* AutoLayoutInstallationTests.m */; }; 11 | A7D5F45A191882BF00B7F344 /* AutoLayoutPinEdgesTests.m in Sources */ = {isa = PBXBuildFile; fileRef = A7D5F459191882BF00B7F344 /* AutoLayoutPinEdgesTests.m */; }; 12 | B15E99CA17C476E600E09E3E /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = B15E99C917C476E600E09E3E /* Foundation.framework */; }; 13 | B15E99CC17C476E600E09E3E /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = B15E99CB17C476E600E09E3E /* CoreGraphics.framework */; }; 14 | B15E99CE17C476E600E09E3E /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = B15E99CD17C476E600E09E3E /* UIKit.framework */; }; 15 | B15E99D417C476E600E09E3E /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = B15E99D217C476E600E09E3E /* InfoPlist.strings */; }; 16 | B15E99D617C476E600E09E3E /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = B15E99D517C476E600E09E3E /* main.m */; }; 17 | B15E99DA17C476E600E09E3E /* ALAppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = B15E99D917C476E600E09E3E /* ALAppDelegate.m */; }; 18 | B15E99DC17C476E600E09E3E /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = B15E99DB17C476E600E09E3E /* Images.xcassets */; }; 19 | B15E99E317C476E600E09E3E /* XCTest.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = B15E99E217C476E600E09E3E /* XCTest.framework */; }; 20 | B15E99E417C476E600E09E3E /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = B15E99C917C476E600E09E3E /* Foundation.framework */; }; 21 | B15E99E517C476E600E09E3E /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = B15E99CD17C476E600E09E3E /* UIKit.framework */; }; 22 | B15E99ED17C476E600E09E3E /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = B15E99EB17C476E600E09E3E /* InfoPlist.strings */; }; 23 | B15E99EF17C476E600E09E3E /* AutoLayoutTestBase.m in Sources */ = {isa = PBXBuildFile; fileRef = B15E99EE17C476E600E09E3E /* AutoLayoutTestBase.m */; }; 24 | B15E99FB17C4772B00E09E3E /* UIView+AutoLayout.m in Sources */ = {isa = PBXBuildFile; fileRef = B15E99FA17C4772B00E09E3E /* UIView+AutoLayout.m */; }; 25 | B15E99FC17C4772B00E09E3E /* UIView+AutoLayout.m in Sources */ = {isa = PBXBuildFile; fileRef = B15E99FA17C4772B00E09E3E /* UIView+AutoLayout.m */; }; 26 | B1C6BDAB191308F700EF2E2D /* AutoLayoutInstantiationTests.m in Sources */ = {isa = PBXBuildFile; fileRef = B1C6BDAA191308F700EF2E2D /* AutoLayoutInstantiationTests.m */; }; 27 | B1C6BDAE191309C500EF2E2D /* AutoLayoutRemovalTests.m in Sources */ = {isa = PBXBuildFile; fileRef = B1C6BDAD191309C500EF2E2D /* AutoLayoutRemovalTests.m */; }; 28 | B1C6BDB019130B8800EF2E2D /* AutoLayoutPriorityTests.m in Sources */ = {isa = PBXBuildFile; fileRef = B1C6BDAF19130B8800EF2E2D /* AutoLayoutPriorityTests.m */; }; 29 | B1C6BDB21913208A00EF2E2D /* AutoLayoutInternalTests.m in Sources */ = {isa = PBXBuildFile; fileRef = B1C6BDB11913208A00EF2E2D /* AutoLayoutInternalTests.m */; }; 30 | B1C6BDB51914643200EF2E2D /* AutoLayoutCenteringTests.m in Sources */ = {isa = PBXBuildFile; fileRef = B1C6BDB41914643200EF2E2D /* AutoLayoutCenteringTests.m */; }; 31 | /* End PBXBuildFile section */ 32 | 33 | /* Begin PBXContainerItemProxy section */ 34 | B15E99E617C476E600E09E3E /* PBXContainerItemProxy */ = { 35 | isa = PBXContainerItemProxy; 36 | containerPortal = B15E99BE17C476E600E09E3E /* Project object */; 37 | proxyType = 1; 38 | remoteGlobalIDString = B15E99C517C476E600E09E3E; 39 | remoteInfo = AutoLayout; 40 | }; 41 | /* End PBXContainerItemProxy section */ 42 | 43 | /* Begin PBXFileReference section */ 44 | A766F3541943D6E200690164 /* AutoLayoutInstallationTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AutoLayoutInstallationTests.m; sourceTree = ""; }; 45 | A7D5F459191882BF00B7F344 /* AutoLayoutPinEdgesTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AutoLayoutPinEdgesTests.m; sourceTree = ""; }; 46 | B15E99C617C476E600E09E3E /* AutoLayout.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = AutoLayout.app; sourceTree = BUILT_PRODUCTS_DIR; }; 47 | B15E99C917C476E600E09E3E /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; }; 48 | B15E99CB17C476E600E09E3E /* CoreGraphics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreGraphics.framework; path = System/Library/Frameworks/CoreGraphics.framework; sourceTree = SDKROOT; }; 49 | B15E99CD17C476E600E09E3E /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = System/Library/Frameworks/UIKit.framework; sourceTree = SDKROOT; }; 50 | B15E99D117C476E600E09E3E /* AutoLayout-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "AutoLayout-Info.plist"; sourceTree = ""; }; 51 | B15E99D317C476E600E09E3E /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = ""; }; 52 | B15E99D517C476E600E09E3E /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; 53 | B15E99D717C476E600E09E3E /* AutoLayout-Prefix.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "AutoLayout-Prefix.pch"; sourceTree = ""; }; 54 | B15E99D817C476E600E09E3E /* ALAppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ALAppDelegate.h; sourceTree = ""; }; 55 | B15E99D917C476E600E09E3E /* ALAppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ALAppDelegate.m; sourceTree = ""; }; 56 | B15E99DB17C476E600E09E3E /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = ""; }; 57 | B15E99E117C476E600E09E3E /* AutoLayoutTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = AutoLayoutTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 58 | B15E99E217C476E600E09E3E /* XCTest.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = XCTest.framework; path = Library/Frameworks/XCTest.framework; sourceTree = DEVELOPER_DIR; }; 59 | B15E99EA17C476E600E09E3E /* AutoLayoutTests-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "AutoLayoutTests-Info.plist"; sourceTree = ""; }; 60 | B15E99EC17C476E600E09E3E /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = ""; }; 61 | B15E99EE17C476E600E09E3E /* AutoLayoutTestBase.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AutoLayoutTestBase.m; sourceTree = ""; }; 62 | B15E99F917C4772B00E09E3E /* UIView+AutoLayout.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "UIView+AutoLayout.h"; path = "../../Source/UIView+AutoLayout.h"; sourceTree = ""; }; 63 | B15E99FA17C4772B00E09E3E /* UIView+AutoLayout.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = "UIView+AutoLayout.m"; path = "../../Source/UIView+AutoLayout.m"; sourceTree = ""; }; 64 | B1C6BDAA191308F700EF2E2D /* AutoLayoutInstantiationTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AutoLayoutInstantiationTests.m; sourceTree = ""; }; 65 | B1C6BDAC1913094700EF2E2D /* AutoLayoutTestBase.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AutoLayoutTestBase.h; sourceTree = ""; }; 66 | B1C6BDAD191309C500EF2E2D /* AutoLayoutRemovalTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AutoLayoutRemovalTests.m; sourceTree = ""; }; 67 | B1C6BDAF19130B8800EF2E2D /* AutoLayoutPriorityTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AutoLayoutPriorityTests.m; sourceTree = ""; }; 68 | B1C6BDB11913208A00EF2E2D /* AutoLayoutInternalTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AutoLayoutInternalTests.m; sourceTree = ""; }; 69 | B1C6BDB3191320E200EF2E2D /* UIView+AutoLayoutInternal.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "UIView+AutoLayoutInternal.h"; sourceTree = ""; }; 70 | B1C6BDB41914643200EF2E2D /* AutoLayoutCenteringTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AutoLayoutCenteringTests.m; sourceTree = ""; }; 71 | /* End PBXFileReference section */ 72 | 73 | /* Begin PBXFrameworksBuildPhase section */ 74 | B15E99C317C476E600E09E3E /* Frameworks */ = { 75 | isa = PBXFrameworksBuildPhase; 76 | buildActionMask = 2147483647; 77 | files = ( 78 | B15E99CC17C476E600E09E3E /* CoreGraphics.framework in Frameworks */, 79 | B15E99CE17C476E600E09E3E /* UIKit.framework in Frameworks */, 80 | B15E99CA17C476E600E09E3E /* Foundation.framework in Frameworks */, 81 | ); 82 | runOnlyForDeploymentPostprocessing = 0; 83 | }; 84 | B15E99DE17C476E600E09E3E /* Frameworks */ = { 85 | isa = PBXFrameworksBuildPhase; 86 | buildActionMask = 2147483647; 87 | files = ( 88 | B15E99E317C476E600E09E3E /* XCTest.framework in Frameworks */, 89 | B15E99E517C476E600E09E3E /* UIKit.framework in Frameworks */, 90 | B15E99E417C476E600E09E3E /* Foundation.framework in Frameworks */, 91 | ); 92 | runOnlyForDeploymentPostprocessing = 0; 93 | }; 94 | /* End PBXFrameworksBuildPhase section */ 95 | 96 | /* Begin PBXGroup section */ 97 | B15E99BD17C476E600E09E3E = { 98 | isa = PBXGroup; 99 | children = ( 100 | B15E99CF17C476E600E09E3E /* AutoLayout */, 101 | B15E99E817C476E600E09E3E /* AutoLayoutTests */, 102 | B15E99C817C476E600E09E3E /* Frameworks */, 103 | B15E99C717C476E600E09E3E /* Products */, 104 | ); 105 | sourceTree = ""; 106 | }; 107 | B15E99C717C476E600E09E3E /* Products */ = { 108 | isa = PBXGroup; 109 | children = ( 110 | B15E99C617C476E600E09E3E /* AutoLayout.app */, 111 | B15E99E117C476E600E09E3E /* AutoLayoutTests.xctest */, 112 | ); 113 | name = Products; 114 | sourceTree = ""; 115 | }; 116 | B15E99C817C476E600E09E3E /* Frameworks */ = { 117 | isa = PBXGroup; 118 | children = ( 119 | B15E99C917C476E600E09E3E /* Foundation.framework */, 120 | B15E99CB17C476E600E09E3E /* CoreGraphics.framework */, 121 | B15E99CD17C476E600E09E3E /* UIKit.framework */, 122 | B15E99E217C476E600E09E3E /* XCTest.framework */, 123 | ); 124 | name = Frameworks; 125 | sourceTree = ""; 126 | }; 127 | B15E99CF17C476E600E09E3E /* AutoLayout */ = { 128 | isa = PBXGroup; 129 | children = ( 130 | B15E99F817C4770F00E09E3E /* UIView+AutoLayout */, 131 | B15E99D817C476E600E09E3E /* ALAppDelegate.h */, 132 | B15E99D917C476E600E09E3E /* ALAppDelegate.m */, 133 | B15E99DB17C476E600E09E3E /* Images.xcassets */, 134 | B15E99D017C476E600E09E3E /* Supporting Files */, 135 | ); 136 | path = AutoLayout; 137 | sourceTree = ""; 138 | }; 139 | B15E99D017C476E600E09E3E /* Supporting Files */ = { 140 | isa = PBXGroup; 141 | children = ( 142 | B15E99D117C476E600E09E3E /* AutoLayout-Info.plist */, 143 | B15E99D217C476E600E09E3E /* InfoPlist.strings */, 144 | B15E99D517C476E600E09E3E /* main.m */, 145 | B15E99D717C476E600E09E3E /* AutoLayout-Prefix.pch */, 146 | ); 147 | name = "Supporting Files"; 148 | sourceTree = ""; 149 | }; 150 | B15E99E817C476E600E09E3E /* AutoLayoutTests */ = { 151 | isa = PBXGroup; 152 | children = ( 153 | B1C6BDB3191320E200EF2E2D /* UIView+AutoLayoutInternal.h */, 154 | B1C6BDAC1913094700EF2E2D /* AutoLayoutTestBase.h */, 155 | B15E99EE17C476E600E09E3E /* AutoLayoutTestBase.m */, 156 | B1C6BDB11913208A00EF2E2D /* AutoLayoutInternalTests.m */, 157 | B1C6BDAA191308F700EF2E2D /* AutoLayoutInstantiationTests.m */, 158 | B1C6BDAF19130B8800EF2E2D /* AutoLayoutPriorityTests.m */, 159 | B1C6BDAD191309C500EF2E2D /* AutoLayoutRemovalTests.m */, 160 | A766F3541943D6E200690164 /* AutoLayoutInstallationTests.m */, 161 | B1C6BDB41914643200EF2E2D /* AutoLayoutCenteringTests.m */, 162 | A7D5F459191882BF00B7F344 /* AutoLayoutPinEdgesTests.m */, 163 | B15E99E917C476E600E09E3E /* Supporting Files */, 164 | ); 165 | path = AutoLayoutTests; 166 | sourceTree = ""; 167 | }; 168 | B15E99E917C476E600E09E3E /* Supporting Files */ = { 169 | isa = PBXGroup; 170 | children = ( 171 | B15E99EA17C476E600E09E3E /* AutoLayoutTests-Info.plist */, 172 | B15E99EB17C476E600E09E3E /* InfoPlist.strings */, 173 | ); 174 | name = "Supporting Files"; 175 | sourceTree = ""; 176 | }; 177 | B15E99F817C4770F00E09E3E /* UIView+AutoLayout */ = { 178 | isa = PBXGroup; 179 | children = ( 180 | B15E99F917C4772B00E09E3E /* UIView+AutoLayout.h */, 181 | B15E99FA17C4772B00E09E3E /* UIView+AutoLayout.m */, 182 | ); 183 | name = "UIView+AutoLayout"; 184 | sourceTree = ""; 185 | }; 186 | /* End PBXGroup section */ 187 | 188 | /* Begin PBXNativeTarget section */ 189 | B15E99C517C476E600E09E3E /* AutoLayout */ = { 190 | isa = PBXNativeTarget; 191 | buildConfigurationList = B15E99F217C476E600E09E3E /* Build configuration list for PBXNativeTarget "AutoLayout" */; 192 | buildPhases = ( 193 | B15E99C217C476E600E09E3E /* Sources */, 194 | B15E99C317C476E600E09E3E /* Frameworks */, 195 | B15E99C417C476E600E09E3E /* Resources */, 196 | ); 197 | buildRules = ( 198 | ); 199 | dependencies = ( 200 | ); 201 | name = AutoLayout; 202 | productName = AutoLayout; 203 | productReference = B15E99C617C476E600E09E3E /* AutoLayout.app */; 204 | productType = "com.apple.product-type.application"; 205 | }; 206 | B15E99E017C476E600E09E3E /* AutoLayoutTests */ = { 207 | isa = PBXNativeTarget; 208 | buildConfigurationList = B15E99F517C476E600E09E3E /* Build configuration list for PBXNativeTarget "AutoLayoutTests" */; 209 | buildPhases = ( 210 | B15E99DD17C476E600E09E3E /* Sources */, 211 | B15E99DE17C476E600E09E3E /* Frameworks */, 212 | B15E99DF17C476E600E09E3E /* Resources */, 213 | ); 214 | buildRules = ( 215 | ); 216 | dependencies = ( 217 | B15E99E717C476E600E09E3E /* PBXTargetDependency */, 218 | ); 219 | name = AutoLayoutTests; 220 | productName = AutoLayoutTests; 221 | productReference = B15E99E117C476E600E09E3E /* AutoLayoutTests.xctest */; 222 | productType = "com.apple.product-type.bundle.unit-test"; 223 | }; 224 | /* End PBXNativeTarget section */ 225 | 226 | /* Begin PBXProject section */ 227 | B15E99BE17C476E600E09E3E /* Project object */ = { 228 | isa = PBXProject; 229 | attributes = { 230 | CLASSPREFIX = AL; 231 | LastUpgradeCheck = 0500; 232 | TargetAttributes = { 233 | B15E99E017C476E600E09E3E = { 234 | TestTargetID = B15E99C517C476E600E09E3E; 235 | }; 236 | }; 237 | }; 238 | buildConfigurationList = B15E99C117C476E600E09E3E /* Build configuration list for PBXProject "AutoLayout" */; 239 | compatibilityVersion = "Xcode 3.2"; 240 | developmentRegion = English; 241 | hasScannedForEncodings = 0; 242 | knownRegions = ( 243 | en, 244 | ); 245 | mainGroup = B15E99BD17C476E600E09E3E; 246 | productRefGroup = B15E99C717C476E600E09E3E /* Products */; 247 | projectDirPath = ""; 248 | projectRoot = ""; 249 | targets = ( 250 | B15E99C517C476E600E09E3E /* AutoLayout */, 251 | B15E99E017C476E600E09E3E /* AutoLayoutTests */, 252 | ); 253 | }; 254 | /* End PBXProject section */ 255 | 256 | /* Begin PBXResourcesBuildPhase section */ 257 | B15E99C417C476E600E09E3E /* Resources */ = { 258 | isa = PBXResourcesBuildPhase; 259 | buildActionMask = 2147483647; 260 | files = ( 261 | B15E99D417C476E600E09E3E /* InfoPlist.strings in Resources */, 262 | B15E99DC17C476E600E09E3E /* Images.xcassets in Resources */, 263 | ); 264 | runOnlyForDeploymentPostprocessing = 0; 265 | }; 266 | B15E99DF17C476E600E09E3E /* Resources */ = { 267 | isa = PBXResourcesBuildPhase; 268 | buildActionMask = 2147483647; 269 | files = ( 270 | B15E99ED17C476E600E09E3E /* InfoPlist.strings in Resources */, 271 | ); 272 | runOnlyForDeploymentPostprocessing = 0; 273 | }; 274 | /* End PBXResourcesBuildPhase section */ 275 | 276 | /* Begin PBXSourcesBuildPhase section */ 277 | B15E99C217C476E600E09E3E /* Sources */ = { 278 | isa = PBXSourcesBuildPhase; 279 | buildActionMask = 2147483647; 280 | files = ( 281 | B15E99D617C476E600E09E3E /* main.m in Sources */, 282 | B15E99FB17C4772B00E09E3E /* UIView+AutoLayout.m in Sources */, 283 | B15E99DA17C476E600E09E3E /* ALAppDelegate.m in Sources */, 284 | ); 285 | runOnlyForDeploymentPostprocessing = 0; 286 | }; 287 | B15E99DD17C476E600E09E3E /* Sources */ = { 288 | isa = PBXSourcesBuildPhase; 289 | buildActionMask = 2147483647; 290 | files = ( 291 | B15E99EF17C476E600E09E3E /* AutoLayoutTestBase.m in Sources */, 292 | B15E99FC17C4772B00E09E3E /* UIView+AutoLayout.m in Sources */, 293 | B1C6BDAB191308F700EF2E2D /* AutoLayoutInstantiationTests.m in Sources */, 294 | B1C6BDB51914643200EF2E2D /* AutoLayoutCenteringTests.m in Sources */, 295 | B1C6BDB019130B8800EF2E2D /* AutoLayoutPriorityTests.m in Sources */, 296 | A7D5F45A191882BF00B7F344 /* AutoLayoutPinEdgesTests.m in Sources */, 297 | B1C6BDB21913208A00EF2E2D /* AutoLayoutInternalTests.m in Sources */, 298 | B1C6BDAE191309C500EF2E2D /* AutoLayoutRemovalTests.m in Sources */, 299 | A766F3551943D6E200690164 /* AutoLayoutInstallationTests.m in Sources */, 300 | ); 301 | runOnlyForDeploymentPostprocessing = 0; 302 | }; 303 | /* End PBXSourcesBuildPhase section */ 304 | 305 | /* Begin PBXTargetDependency section */ 306 | B15E99E717C476E600E09E3E /* PBXTargetDependency */ = { 307 | isa = PBXTargetDependency; 308 | target = B15E99C517C476E600E09E3E /* AutoLayout */; 309 | targetProxy = B15E99E617C476E600E09E3E /* PBXContainerItemProxy */; 310 | }; 311 | /* End PBXTargetDependency section */ 312 | 313 | /* Begin PBXVariantGroup section */ 314 | B15E99D217C476E600E09E3E /* InfoPlist.strings */ = { 315 | isa = PBXVariantGroup; 316 | children = ( 317 | B15E99D317C476E600E09E3E /* en */, 318 | ); 319 | name = InfoPlist.strings; 320 | sourceTree = ""; 321 | }; 322 | B15E99EB17C476E600E09E3E /* InfoPlist.strings */ = { 323 | isa = PBXVariantGroup; 324 | children = ( 325 | B15E99EC17C476E600E09E3E /* en */, 326 | ); 327 | name = InfoPlist.strings; 328 | sourceTree = ""; 329 | }; 330 | /* End PBXVariantGroup section */ 331 | 332 | /* Begin XCBuildConfiguration section */ 333 | B15E99F017C476E600E09E3E /* Debug */ = { 334 | isa = XCBuildConfiguration; 335 | buildSettings = { 336 | ALWAYS_SEARCH_USER_PATHS = NO; 337 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 338 | CLANG_CXX_LIBRARY = "libc++"; 339 | CLANG_ENABLE_MODULES = YES; 340 | CLANG_ENABLE_OBJC_ARC = YES; 341 | CLANG_WARN_BOOL_CONVERSION = YES; 342 | CLANG_WARN_CONSTANT_CONVERSION = YES; 343 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 344 | CLANG_WARN_EMPTY_BODY = YES; 345 | CLANG_WARN_ENUM_CONVERSION = YES; 346 | CLANG_WARN_INT_CONVERSION = YES; 347 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 348 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 349 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 350 | COPY_PHASE_STRIP = NO; 351 | GCC_C_LANGUAGE_STANDARD = gnu99; 352 | GCC_DYNAMIC_NO_PIC = NO; 353 | GCC_OPTIMIZATION_LEVEL = 0; 354 | GCC_PREPROCESSOR_DEFINITIONS = ( 355 | "DEBUG=1", 356 | "$(inherited)", 357 | ); 358 | GCC_SYMBOLS_PRIVATE_EXTERN = NO; 359 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 360 | GCC_WARN_UNDECLARED_SELECTOR = YES; 361 | GCC_WARN_UNINITIALIZED_AUTOS = YES; 362 | GCC_WARN_UNUSED_FUNCTION = YES; 363 | GCC_WARN_UNUSED_VARIABLE = YES; 364 | IPHONEOS_DEPLOYMENT_TARGET = 7.0; 365 | ONLY_ACTIVE_ARCH = YES; 366 | SDKROOT = iphoneos; 367 | }; 368 | name = Debug; 369 | }; 370 | B15E99F117C476E600E09E3E /* Release */ = { 371 | isa = XCBuildConfiguration; 372 | buildSettings = { 373 | ALWAYS_SEARCH_USER_PATHS = NO; 374 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 375 | CLANG_CXX_LIBRARY = "libc++"; 376 | CLANG_ENABLE_MODULES = YES; 377 | CLANG_ENABLE_OBJC_ARC = YES; 378 | CLANG_WARN_BOOL_CONVERSION = YES; 379 | CLANG_WARN_CONSTANT_CONVERSION = YES; 380 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 381 | CLANG_WARN_EMPTY_BODY = YES; 382 | CLANG_WARN_ENUM_CONVERSION = YES; 383 | CLANG_WARN_INT_CONVERSION = YES; 384 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 385 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 386 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 387 | COPY_PHASE_STRIP = YES; 388 | ENABLE_NS_ASSERTIONS = NO; 389 | GCC_C_LANGUAGE_STANDARD = gnu99; 390 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 391 | GCC_WARN_UNDECLARED_SELECTOR = YES; 392 | GCC_WARN_UNINITIALIZED_AUTOS = YES; 393 | GCC_WARN_UNUSED_FUNCTION = YES; 394 | GCC_WARN_UNUSED_VARIABLE = YES; 395 | IPHONEOS_DEPLOYMENT_TARGET = 7.0; 396 | SDKROOT = iphoneos; 397 | VALIDATE_PRODUCT = YES; 398 | }; 399 | name = Release; 400 | }; 401 | B15E99F317C476E600E09E3E /* Debug */ = { 402 | isa = XCBuildConfiguration; 403 | buildSettings = { 404 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 405 | ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = LaunchImage; 406 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 407 | GCC_PREFIX_HEADER = "AutoLayout/AutoLayout-Prefix.pch"; 408 | INFOPLIST_FILE = "AutoLayout/AutoLayout-Info.plist"; 409 | PRODUCT_NAME = "$(TARGET_NAME)"; 410 | WRAPPER_EXTENSION = app; 411 | }; 412 | name = Debug; 413 | }; 414 | B15E99F417C476E600E09E3E /* Release */ = { 415 | isa = XCBuildConfiguration; 416 | buildSettings = { 417 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 418 | ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = LaunchImage; 419 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 420 | GCC_PREFIX_HEADER = "AutoLayout/AutoLayout-Prefix.pch"; 421 | INFOPLIST_FILE = "AutoLayout/AutoLayout-Info.plist"; 422 | PRODUCT_NAME = "$(TARGET_NAME)"; 423 | WRAPPER_EXTENSION = app; 424 | }; 425 | name = Release; 426 | }; 427 | B15E99F617C476E600E09E3E /* Debug */ = { 428 | isa = XCBuildConfiguration; 429 | buildSettings = { 430 | BUNDLE_LOADER = "$(BUILT_PRODUCTS_DIR)/AutoLayout.app/AutoLayout"; 431 | FRAMEWORK_SEARCH_PATHS = ( 432 | "$(SDKROOT)/Developer/Library/Frameworks", 433 | "$(inherited)", 434 | "$(DEVELOPER_FRAMEWORKS_DIR)", 435 | ); 436 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 437 | GCC_PREFIX_HEADER = "AutoLayout/AutoLayout-Prefix.pch"; 438 | GCC_PREPROCESSOR_DEFINITIONS = ( 439 | "DEBUG=1", 440 | "$(inherited)", 441 | ); 442 | INFOPLIST_FILE = "AutoLayoutTests/AutoLayoutTests-Info.plist"; 443 | PRODUCT_NAME = "$(TARGET_NAME)"; 444 | TEST_HOST = "$(BUNDLE_LOADER)"; 445 | WRAPPER_EXTENSION = xctest; 446 | }; 447 | name = Debug; 448 | }; 449 | B15E99F717C476E600E09E3E /* Release */ = { 450 | isa = XCBuildConfiguration; 451 | buildSettings = { 452 | BUNDLE_LOADER = "$(BUILT_PRODUCTS_DIR)/AutoLayout.app/AutoLayout"; 453 | FRAMEWORK_SEARCH_PATHS = ( 454 | "$(SDKROOT)/Developer/Library/Frameworks", 455 | "$(inherited)", 456 | "$(DEVELOPER_FRAMEWORKS_DIR)", 457 | ); 458 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 459 | GCC_PREFIX_HEADER = "AutoLayout/AutoLayout-Prefix.pch"; 460 | INFOPLIST_FILE = "AutoLayoutTests/AutoLayoutTests-Info.plist"; 461 | PRODUCT_NAME = "$(TARGET_NAME)"; 462 | TEST_HOST = "$(BUNDLE_LOADER)"; 463 | WRAPPER_EXTENSION = xctest; 464 | }; 465 | name = Release; 466 | }; 467 | /* End XCBuildConfiguration section */ 468 | 469 | /* Begin XCConfigurationList section */ 470 | B15E99C117C476E600E09E3E /* Build configuration list for PBXProject "AutoLayout" */ = { 471 | isa = XCConfigurationList; 472 | buildConfigurations = ( 473 | B15E99F017C476E600E09E3E /* Debug */, 474 | B15E99F117C476E600E09E3E /* Release */, 475 | ); 476 | defaultConfigurationIsVisible = 0; 477 | defaultConfigurationName = Release; 478 | }; 479 | B15E99F217C476E600E09E3E /* Build configuration list for PBXNativeTarget "AutoLayout" */ = { 480 | isa = XCConfigurationList; 481 | buildConfigurations = ( 482 | B15E99F317C476E600E09E3E /* Debug */, 483 | B15E99F417C476E600E09E3E /* Release */, 484 | ); 485 | defaultConfigurationIsVisible = 0; 486 | defaultConfigurationName = Release; 487 | }; 488 | B15E99F517C476E600E09E3E /* Build configuration list for PBXNativeTarget "AutoLayoutTests" */ = { 489 | isa = XCConfigurationList; 490 | buildConfigurations = ( 491 | B15E99F617C476E600E09E3E /* Debug */, 492 | B15E99F717C476E600E09E3E /* Release */, 493 | ); 494 | defaultConfigurationIsVisible = 0; 495 | defaultConfigurationName = Release; 496 | }; 497 | /* End XCConfigurationList section */ 498 | }; 499 | rootObject = B15E99BE17C476E600E09E3E /* Project object */; 500 | } 501 | -------------------------------------------------------------------------------- /Tests/AutoLayout.xcodeproj/xcshareddata/xcschemes/AutoLayout.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 33 | 39 | 40 | 41 | 42 | 43 | 49 | 50 | 51 | 52 | 61 | 62 | 68 | 69 | 70 | 71 | 72 | 73 | 79 | 80 | 86 | 87 | 88 | 89 | 91 | 92 | 95 | 96 | 97 | -------------------------------------------------------------------------------- /Tests/AutoLayout/ALAppDelegate.h: -------------------------------------------------------------------------------- 1 | // 2 | // ALAppDelegate.h 3 | // AutoLayout 4 | // 5 | // Copyright (c) 2013 Tyler Fox 6 | // https://github.com/smileyborg/UIView-AutoLayout 7 | // 8 | 9 | #import 10 | 11 | @interface ALAppDelegate : UIResponder 12 | 13 | @property (strong, nonatomic) UIWindow *window; 14 | 15 | @end 16 | -------------------------------------------------------------------------------- /Tests/AutoLayout/ALAppDelegate.m: -------------------------------------------------------------------------------- 1 | // 2 | // ALAppDelegate.m 3 | // AutoLayout 4 | // 5 | // Copyright (c) 2013 Tyler Fox 6 | // https://github.com/smileyborg/UIView-AutoLayout 7 | // 8 | 9 | #import "ALAppDelegate.h" 10 | 11 | @implementation ALAppDelegate 12 | 13 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions 14 | { 15 | self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]]; 16 | // Override point for customization after application launch. 17 | self.window.backgroundColor = [UIColor whiteColor]; 18 | [self.window makeKeyAndVisible]; 19 | return YES; 20 | } 21 | 22 | - (void)applicationWillResignActive:(UIApplication *)application 23 | { 24 | // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. 25 | // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game. 26 | } 27 | 28 | - (void)applicationDidEnterBackground:(UIApplication *)application 29 | { 30 | // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. 31 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. 32 | } 33 | 34 | - (void)applicationWillEnterForeground:(UIApplication *)application 35 | { 36 | // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background. 37 | } 38 | 39 | - (void)applicationDidBecomeActive:(UIApplication *)application 40 | { 41 | // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. 42 | } 43 | 44 | - (void)applicationWillTerminate:(UIApplication *)application 45 | { 46 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. 47 | } 48 | 49 | @end 50 | -------------------------------------------------------------------------------- /Tests/AutoLayout/AutoLayout-Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleDisplayName 8 | ${PRODUCT_NAME} 9 | CFBundleExecutable 10 | ${EXECUTABLE_NAME} 11 | CFBundleIdentifier 12 | com.smileyborg.${PRODUCT_NAME:rfc1034identifier} 13 | CFBundleInfoDictionaryVersion 14 | 6.0 15 | CFBundleName 16 | ${PRODUCT_NAME} 17 | CFBundlePackageType 18 | APPL 19 | CFBundleShortVersionString 20 | 1.0 21 | CFBundleSignature 22 | ???? 23 | CFBundleVersion 24 | 1.0 25 | LSRequiresIPhoneOS 26 | 27 | UIRequiredDeviceCapabilities 28 | 29 | armv7 30 | 31 | UISupportedInterfaceOrientations 32 | 33 | UIInterfaceOrientationPortrait 34 | UIInterfaceOrientationLandscapeLeft 35 | UIInterfaceOrientationLandscapeRight 36 | 37 | 38 | 39 | -------------------------------------------------------------------------------- /Tests/AutoLayout/AutoLayout-Prefix.pch: -------------------------------------------------------------------------------- 1 | // 2 | // Prefix header 3 | // 4 | // The contents of this file are implicitly included at the beginning of every source file. 5 | // 6 | 7 | #import 8 | 9 | #ifndef __IPHONE_3_0 10 | #warning "This project uses features only available in iOS SDK 3.0 and later." 11 | #endif 12 | 13 | #ifdef __OBJC__ 14 | #import 15 | #import 16 | #endif 17 | 18 | #import "UIView+AutoLayout.h" 19 | -------------------------------------------------------------------------------- /Tests/AutoLayout/Images.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "iphone", 5 | "size" : "29x29", 6 | "scale" : "2x" 7 | }, 8 | { 9 | "idiom" : "iphone", 10 | "size" : "40x40", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "iphone", 15 | "size" : "60x60", 16 | "scale" : "2x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } -------------------------------------------------------------------------------- /Tests/AutoLayout/Images.xcassets/LaunchImage.launchimage/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "orientation" : "portrait", 5 | "idiom" : "iphone", 6 | "extent" : "full-screen", 7 | "minimum-system-version" : "7.0", 8 | "scale" : "2x" 9 | }, 10 | { 11 | "orientation" : "portrait", 12 | "idiom" : "iphone", 13 | "subtype" : "retina4", 14 | "extent" : "full-screen", 15 | "minimum-system-version" : "7.0", 16 | "scale" : "2x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } -------------------------------------------------------------------------------- /Tests/AutoLayout/en.lproj/InfoPlist.strings: -------------------------------------------------------------------------------- 1 | /* Localized versions of Info.plist keys */ 2 | 3 | -------------------------------------------------------------------------------- /Tests/AutoLayout/main.m: -------------------------------------------------------------------------------- 1 | // 2 | // main.m 3 | // AutoLayout 4 | // 5 | // Copyright (c) 2013 Tyler Fox 6 | // https://github.com/smileyborg/UIView-AutoLayout 7 | // 8 | 9 | #import 10 | 11 | #import "ALAppDelegate.h" 12 | 13 | int main(int argc, char * argv[]) 14 | { 15 | @autoreleasepool { 16 | return UIApplicationMain(argc, argv, nil, NSStringFromClass([ALAppDelegate class])); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /Tests/AutoLayoutTests/AutoLayoutCenteringTests.m: -------------------------------------------------------------------------------- 1 | // 2 | // AutoLayoutCenteringTests.m 3 | // UIView+AutoLayout Tests 4 | // 5 | // Copyright (c) 2014 Tyler Fox 6 | // https://github.com/smileyborg/UIView-AutoLayout 7 | // 8 | 9 | #import "AutoLayoutTestBase.h" 10 | 11 | @interface AutoLayoutCenteringTests : AutoLayoutTestBase 12 | 13 | @end 14 | 15 | @implementation AutoLayoutCenteringTests 16 | 17 | - (void)setUp 18 | { 19 | [super setUp]; 20 | 21 | } 22 | 23 | - (void)tearDown 24 | { 25 | 26 | [super tearDown]; 27 | } 28 | 29 | - (void)testAutoCenterInSuperview 30 | { 31 | [self.viewA autoSetDimensionsToSize:CGSizeMake(100.0, 100.0)]; 32 | [self.viewA autoCenterInSuperview]; 33 | [self evaluateConstraints]; 34 | ALAssertCenterEquals(self.viewA, 500.0, 500.0); 35 | ALAssertFrameEquals(self.viewA, 450.0, 450.0, 100.0, 100.0); 36 | 37 | [self.viewB autoSetDimensionsToSize:CGSizeMake(80.0, 124.0)]; 38 | [self.viewB autoCenterInSuperview]; 39 | [self evaluateConstraints]; 40 | ALAssertCenterEquals(self.viewB, 500.0, 500.0); 41 | ALAssertFrameEquals(self.viewB, 460.0, 438.0, 80.0, 124.0); 42 | } 43 | 44 | - (void)testAutoAlignAxisToSuperviewAxis 45 | { 46 | [self.viewB autoSetDimensionsToSize:CGSizeMake(150.0, 200.0)]; 47 | [self.viewB autoAlignAxisToSuperviewAxis:ALAxisVertical]; 48 | [self evaluateConstraints]; 49 | ALAssertCenterXEquals(self.viewB, 500.0); 50 | 51 | [self.viewB autoAlignAxisToSuperviewAxis:ALAxisHorizontal]; 52 | [self evaluateConstraints]; 53 | ALAssertCenterYEquals(self.viewB, 500.0); 54 | 55 | [self.viewC autoSetDimensionsToSize:CGSizeMake(25.0, 20.0)]; 56 | [self.viewC autoAlignAxisToSuperviewAxis:ALAxisHorizontal]; 57 | [self evaluateConstraints]; 58 | ALAssertCenterYEquals(self.viewC, 500.0); 59 | 60 | [self.viewC autoAlignAxisToSuperviewAxis:ALAxisVertical]; 61 | [self evaluateConstraints]; 62 | ALAssertCenterXEquals(self.viewC, 500.0); 63 | 64 | // viewD and its superview are regular UIViews which have no baseline offset, so the baseline is treated as the bottom edge 65 | [self.viewD autoSetDimensionsToSize:CGSizeMake(400.0, 100.0)]; 66 | [self.viewD autoAlignAxisToSuperviewAxis:ALAxisBaseline]; 67 | [self evaluateConstraints]; 68 | ALAssertMaxYEquals(self.viewD, 1000.0); 69 | } 70 | 71 | @end 72 | -------------------------------------------------------------------------------- /Tests/AutoLayoutTests/AutoLayoutInstallationTests.m: -------------------------------------------------------------------------------- 1 | // 2 | // AutoLayoutInstallationTests.m 3 | // UIView+AutoLayout Tests 4 | // 5 | // Copyright (c) 2014 Tyler Fox 6 | // https://github.com/smileyborg/UIView-AutoLayout 7 | // 8 | 9 | #import "AutoLayoutTestBase.h" 10 | 11 | @interface AutoLayoutInstallationTests : AutoLayoutTestBase 12 | 13 | @end 14 | 15 | @implementation AutoLayoutInstallationTests 16 | 17 | - (void)setUp 18 | { 19 | [super setUp]; 20 | 21 | } 22 | 23 | - (void)tearDown 24 | { 25 | 26 | [super tearDown]; 27 | } 28 | 29 | /** 30 | Test the -[autoInstall] method on NSLayoutConstraint with two nil items. 31 | */ 32 | - (void)testInstallNilItems 33 | { 34 | NSLayoutConstraint *constraint = [NSLayoutConstraint new]; 35 | XCTAssertNil(constraint.firstItem); 36 | XCTAssertNil(constraint.secondItem); 37 | 38 | XCTAssertThrows([constraint autoInstall], @"autoInstall should throw an exception that both items are nil."); 39 | } 40 | 41 | /** 42 | Test the -[autoInstall] method on NSLayoutConstraint with two views as items. 43 | */ 44 | - (void)testInstallTwoItems 45 | { 46 | NSUInteger startingConstraintsCount = [self.containerView.constraints count]; 47 | 48 | NSLayoutConstraint *constraint = [NSLayoutConstraint constraintWithItem:self.viewA attribute:NSLayoutAttributeTop relatedBy:NSLayoutRelationEqual toItem:self.viewB attribute:NSLayoutAttributeBottom multiplier:1.0 constant:0.0]; 49 | 50 | XCTAssert([self.containerView.constraints count] == startingConstraintsCount, @"containerView should have no new constraints added to it yet."); 51 | 52 | [constraint autoInstall]; 53 | 54 | NSUInteger newConstraintsCount = [self.containerView.constraints count]; 55 | XCTAssert(newConstraintsCount == startingConstraintsCount + 1, @"containerView should have one new constraint added to it."); 56 | } 57 | 58 | /** 59 | Test the -[autoInstall] method on NSLayoutConstraint with one view in firstItem. 60 | */ 61 | - (void)testInstallFirstItem 62 | { 63 | NSUInteger startingConstraintsCount = [self.viewC.constraints count]; 64 | 65 | NSLayoutConstraint *constraint = [NSLayoutConstraint constraintWithItem:self.viewC attribute:NSLayoutAttributeWidth relatedBy:NSLayoutRelationEqual toItem:nil attribute:NSLayoutAttributeNotAnAttribute multiplier:1.0 constant:10.0]; 66 | 67 | XCTAssert([self.containerView.constraints count] == startingConstraintsCount, @"viewC should have no new constraints added to it yet."); 68 | 69 | [constraint autoInstall]; 70 | 71 | NSUInteger newConstraintsCount = [self.viewC.constraints count]; 72 | XCTAssert(newConstraintsCount == startingConstraintsCount + 1, @"viewC should have one new constraint added to it."); 73 | } 74 | 75 | @end 76 | -------------------------------------------------------------------------------- /Tests/AutoLayoutTests/AutoLayoutInstantiationTests.m: -------------------------------------------------------------------------------- 1 | // 2 | // AutoLayoutInstantiationTests.m 3 | // UIView+AutoLayout Tests 4 | // 5 | // Copyright (c) 2014 Tyler Fox 6 | // https://github.com/smileyborg/UIView-AutoLayout 7 | // 8 | 9 | #import "AutoLayoutTestBase.h" 10 | 11 | @interface AutoLayoutInstantiationTests : AutoLayoutTestBase 12 | 13 | @end 14 | 15 | @implementation AutoLayoutInstantiationTests 16 | 17 | - (void)setUp 18 | { 19 | [super setUp]; 20 | 21 | } 22 | 23 | - (void)tearDown 24 | { 25 | 26 | [super tearDown]; 27 | } 28 | 29 | /** 30 | Test the +[newAutoLayoutView] method. 31 | */ 32 | - (void)testNewAutoLayoutView 33 | { 34 | UIView *view = [UIView newAutoLayoutView]; 35 | XCTAssertNotNil(view, @"+[UIView newAutoLayoutView] should not return nil."); 36 | XCTAssert([view isKindOfClass:[UIView class]], @"+[UIView newAutoLayoutView] should return an instance of UIView."); 37 | XCTAssert(view.translatesAutoresizingMaskIntoConstraints == NO, @"The view returned from +[UIView newAutoLayoutView] should not translate its autoresizing mask into constraints."); 38 | 39 | view = [UILabel newAutoLayoutView]; 40 | XCTAssertNotNil(view, @"+[UILabel newAutoLayoutView] should not return nil."); 41 | XCTAssert([view isKindOfClass:[UILabel class]], @"+[UILabel newAutoLayoutView] should return an instance of UILabel."); 42 | XCTAssert(view.translatesAutoresizingMaskIntoConstraints == NO, @"The view returned from +[UILabel newAutoLayoutView] should not translate its autoresizing mask into constraints."); 43 | 44 | view = [UIImageView newAutoLayoutView]; 45 | XCTAssertNotNil(view, @"+[UIImageView newAutoLayoutView] should not return nil."); 46 | XCTAssert([view isKindOfClass:[UIImageView class]], @"+[UIImageView newAutoLayoutView] should return an instance of UIImageView."); 47 | XCTAssert(view.translatesAutoresizingMaskIntoConstraints == NO, @"The view returned from +[UIImageView newAutoLayoutView] should not translate its autoresizing mask into constraints."); 48 | } 49 | 50 | /** 51 | Test the -[initForAutoLayout] method. 52 | */ 53 | - (void)testInitForAutoLayout 54 | { 55 | UIView *view = [[UIView alloc] initForAutoLayout]; 56 | XCTAssertNotNil(view, @"-[[UIView alloc] initForAutoLayout] should not return nil."); 57 | XCTAssert([view isKindOfClass:[UIView class]], @"-[[UIView alloc] initForAutoLayout] should return an instance of UIView."); 58 | XCTAssert(view.translatesAutoresizingMaskIntoConstraints == NO, @"The view returned from [[UIView alloc] initForAutoLayout] should not translate its autoresizing mask into constraints."); 59 | 60 | view = [[UILabel alloc] initForAutoLayout]; 61 | XCTAssertNotNil(view, @"-[[UILabel alloc] initForAutoLayout] should not return nil."); 62 | XCTAssert([view isKindOfClass:[UILabel class]], @"-[[UILabel alloc] initForAutoLayout] should return an instance of UILabel."); 63 | XCTAssert(view.translatesAutoresizingMaskIntoConstraints == NO, @"The view returned from [[UILabel alloc] initForAutoLayout] should not translate its autoresizing mask into constraints."); 64 | 65 | view = [[UIImageView alloc] initForAutoLayout]; 66 | XCTAssertNotNil(view, @"-[[UIImageView alloc] initForAutoLayout] should not return nil."); 67 | XCTAssert([view isKindOfClass:[UIImageView class]], @"-[[UIImageView alloc] initForAutoLayout] should return an instance of UIImageView."); 68 | XCTAssert(view.translatesAutoresizingMaskIntoConstraints == NO, @"The view returned from [[UIImageView alloc] initForAutoLayout] should not translate its autoresizing mask into constraints."); 69 | } 70 | 71 | @end 72 | -------------------------------------------------------------------------------- /Tests/AutoLayoutTests/AutoLayoutInternalTests.m: -------------------------------------------------------------------------------- 1 | // 2 | // AutoLayoutInternalTests.m 3 | // UIView+AutoLayout Tests 4 | // 5 | // Copyright (c) 2014 Tyler Fox 6 | // https://github.com/smileyborg/UIView-AutoLayout 7 | // 8 | 9 | #import "AutoLayoutTestBase.h" 10 | 11 | @interface AutoLayoutInternalTests : AutoLayoutTestBase 12 | 13 | @end 14 | 15 | @implementation AutoLayoutInternalTests 16 | 17 | - (void)setUp 18 | { 19 | [super setUp]; 20 | 21 | } 22 | 23 | - (void)tearDown 24 | { 25 | 26 | [super tearDown]; 27 | } 28 | 29 | /** 30 | Test the internal NSLayoutAttribute for ALEdge translation method. 31 | */ 32 | - (void)testAttributeForEdge 33 | { 34 | XCTAssert([UIView al_attributeForEdge:ALEdgeTop] == NSLayoutAttributeTop, @"ALEdgeTop should correspond to NSLayoutAttributeTop."); 35 | XCTAssert([UIView al_attributeForEdge:ALEdgeBottom] == NSLayoutAttributeBottom, @"ALEdgeBottom should correspond to NSLayoutAttributeBottom."); 36 | XCTAssert([UIView al_attributeForEdge:ALEdgeLeft] == NSLayoutAttributeLeft, @"ALEdgeLeft should correspond to NSLayoutAttributeLeft."); 37 | XCTAssert([UIView al_attributeForEdge:ALEdgeRight] == NSLayoutAttributeRight, @"ALEdgeRight should correspond to NSLayoutAttributeRight."); 38 | XCTAssert([UIView al_attributeForEdge:ALEdgeLeading] == NSLayoutAttributeLeading, @"ALEdgeLeading should correspond to NSLayoutAttributeLeading."); 39 | XCTAssert([UIView al_attributeForEdge:ALEdgeTrailing] == NSLayoutAttributeTrailing, @"ALEdgeTrailing should correspond to NSLayoutAttributeTrailing."); 40 | 41 | XCTAssertThrows([UIView al_attributeForEdge:(ALEdge)ALAxisHorizontal], @"Passing an invalid ALEdge should throw an exception."); 42 | XCTAssertThrows([UIView al_attributeForEdge:(ALEdge)ALAxisVertical], @"Passing an invalid ALEdge should throw an exception."); 43 | XCTAssertThrows([UIView al_attributeForEdge:(ALEdge)ALAxisBaseline], @"Passing an invalid ALEdge should throw an exception."); 44 | XCTAssertThrows([UIView al_attributeForEdge:(ALEdge)ALDimensionHeight], @"Passing an invalid ALEdge should throw an exception."); 45 | XCTAssertThrows([UIView al_attributeForEdge:(ALEdge)ALDimensionWidth], @"Passing an invalid ALEdge should throw an exception."); 46 | XCTAssertThrows([UIView al_attributeForEdge:(ALEdge)NSLayoutAttributeNotAnAttribute], @"Passing an invalid ALEdge should throw an exception."); 47 | } 48 | 49 | /** 50 | Test the internal NSLayoutAttribute for ALAxis translation method. 51 | */ 52 | - (void)testAttributeForAxis 53 | { 54 | XCTAssert([UIView al_attributeForAxis:ALAxisHorizontal] == NSLayoutAttributeCenterY, @"ALAxisHorizontal should correspond to NSLayoutAttributeCenterY."); 55 | XCTAssert([UIView al_attributeForAxis:ALAxisVertical] == NSLayoutAttributeCenterX, @"ALAxisVertical should correspond to NSLayoutAttributeCenterX."); 56 | XCTAssert([UIView al_attributeForAxis:ALAxisBaseline] == NSLayoutAttributeBaseline, @"ALAxisBaseline should correspond to NSLayoutAttributeBaseline."); 57 | 58 | XCTAssertThrows([UIView al_attributeForAxis:(ALAxis)ALEdgeTop], @"Passing an invalid ALAxis should throw an exception."); 59 | XCTAssertThrows([UIView al_attributeForAxis:(ALAxis)ALEdgeBottom], @"Passing an invalid ALAxis should throw an exception."); 60 | XCTAssertThrows([UIView al_attributeForAxis:(ALAxis)ALEdgeLeft], @"Passing an invalid ALAxis should throw an exception."); 61 | XCTAssertThrows([UIView al_attributeForAxis:(ALAxis)ALEdgeRight], @"Passing an invalid ALAxis should throw an exception."); 62 | XCTAssertThrows([UIView al_attributeForAxis:(ALAxis)ALEdgeLeading], @"Passing an invalid ALAxis should throw an exception."); 63 | XCTAssertThrows([UIView al_attributeForAxis:(ALAxis)ALEdgeTrailing], @"Passing an invalid ALAxis should throw an exception."); 64 | XCTAssertThrows([UIView al_attributeForAxis:(ALAxis)ALDimensionHeight], @"Passing an invalid ALAxis should throw an exception."); 65 | XCTAssertThrows([UIView al_attributeForAxis:(ALAxis)ALDimensionWidth], @"Passing an invalid ALAxis should throw an exception."); 66 | XCTAssertThrows([UIView al_attributeForAxis:(ALAxis)NSLayoutAttributeNotAnAttribute], @"Passing an invalid ALAxis should throw an exception."); 67 | } 68 | 69 | /** 70 | Test the internal NSLayoutAttribute for ALDimension translation method. 71 | */ 72 | - (void)testAttributeForDimension 73 | { 74 | XCTAssert([UIView al_attributeForDimension:ALDimensionWidth] == NSLayoutAttributeWidth, @"ALDimensionWidth should correspond to NSLayoutAttributeWidth."); 75 | XCTAssert([UIView al_attributeForDimension:ALDimensionHeight] == NSLayoutAttributeHeight, @"ALDimensionHeight should correspond to NSLayoutAttributeHeight."); 76 | 77 | XCTAssertThrows([UIView al_attributeForDimension:(ALDimension)ALEdgeTop], @"Passing an invalid ALDimension should throw an exception."); 78 | XCTAssertThrows([UIView al_attributeForDimension:(ALDimension)ALEdgeBottom], @"Passing an invalid ALDimension should throw an exception."); 79 | XCTAssertThrows([UIView al_attributeForDimension:(ALDimension)ALEdgeLeft], @"Passing an invalid ALDimension should throw an exception."); 80 | XCTAssertThrows([UIView al_attributeForDimension:(ALDimension)ALEdgeRight], @"Passing an invalid ALDimension should throw an exception."); 81 | XCTAssertThrows([UIView al_attributeForDimension:(ALDimension)ALEdgeLeading], @"Passing an invalid ALDimension should throw an exception."); 82 | XCTAssertThrows([UIView al_attributeForDimension:(ALDimension)ALEdgeTrailing], @"Passing an invalid ALDimension should throw an exception."); 83 | XCTAssertThrows([UIView al_attributeForDimension:(ALDimension)ALAxisHorizontal], @"Passing an invalid ALDimension should throw an exception."); 84 | XCTAssertThrows([UIView al_attributeForDimension:(ALDimension)ALAxisVertical], @"Passing an invalid ALDimension should throw an exception."); 85 | XCTAssertThrows([UIView al_attributeForDimension:(ALDimension)ALAxisBaseline], @"Passing an invalid ALDimension should throw an exception."); 86 | XCTAssertThrows([UIView al_attributeForDimension:(ALDimension)NSLayoutAttributeNotAnAttribute], @"Passing an invalid ALDimension should throw an exception."); 87 | } 88 | 89 | /** 90 | Test the internal NSLayoutAttribute for ALAttribute translation method. 91 | */ 92 | - (void)testAttributeForALAttribute 93 | { 94 | XCTAssert([UIView al_attributeForALAttribute:ALEdgeTop] == NSLayoutAttributeTop, @"ALEdgeTop should correspond to NSLayoutAttributeTop."); 95 | XCTAssert([UIView al_attributeForALAttribute:ALEdgeBottom] == NSLayoutAttributeBottom, @"ALEdgeBottom should correspond to NSLayoutAttributeBottom."); 96 | XCTAssert([UIView al_attributeForALAttribute:ALEdgeLeft] == NSLayoutAttributeLeft, @"ALEdgeLeft should correspond to NSLayoutAttributeLeft."); 97 | XCTAssert([UIView al_attributeForALAttribute:ALEdgeRight] == NSLayoutAttributeRight, @"ALEdgeRight should correspond to NSLayoutAttributeRight."); 98 | XCTAssert([UIView al_attributeForALAttribute:ALEdgeLeading] == NSLayoutAttributeLeading, @"ALEdgeLeading should correspond to NSLayoutAttributeLeading."); 99 | XCTAssert([UIView al_attributeForALAttribute:ALEdgeTrailing] == NSLayoutAttributeTrailing, @"ALEdgeTrailing should correspond to NSLayoutAttributeTrailing."); 100 | XCTAssert([UIView al_attributeForALAttribute:ALAxisHorizontal] == NSLayoutAttributeCenterY, @"ALAxisHorizontal should correspond to NSLayoutAttributeCenterY."); 101 | XCTAssert([UIView al_attributeForALAttribute:ALAxisVertical] == NSLayoutAttributeCenterX, @"ALAxisVertical should correspond to NSLayoutAttributeCenterX."); 102 | XCTAssert([UIView al_attributeForALAttribute:ALAxisBaseline] == NSLayoutAttributeBaseline, @"ALAxisBaseline should correspond to NSLayoutAttributeBaseline."); 103 | XCTAssert([UIView al_attributeForALAttribute:ALDimensionWidth] == NSLayoutAttributeWidth, @"ALDimensionWidth should correspond to NSLayoutAttributeWidth."); 104 | XCTAssert([UIView al_attributeForALAttribute:ALDimensionHeight] == NSLayoutAttributeHeight, @"ALDimensionHeight should correspond to NSLayoutAttributeHeight."); 105 | 106 | XCTAssertThrows([UIView al_attributeForALAttribute:NSLayoutAttributeNotAnAttribute], @"Passing an invalid ALAttribute should throw an exception."); 107 | } 108 | 109 | /** 110 | Test the internal NSLayoutConstraintAxis for ALAxis translation method. 111 | */ 112 | - (void)testConstraintAxisForAxis 113 | { 114 | XCTAssert([UIView al_constraintAxisForAxis:ALAxisHorizontal] == UILayoutConstraintAxisHorizontal, @"ALAxisHorizontal should correspond to UILayoutConstraintAxisHorizontal."); 115 | XCTAssert([UIView al_constraintAxisForAxis:ALAxisVertical] == UILayoutConstraintAxisVertical, @"ALAxisHorizontal should correspond to UILayoutConstraintAxisVertical."); 116 | XCTAssert([UIView al_constraintAxisForAxis:ALAxisBaseline] == UILayoutConstraintAxisHorizontal, @"ALAxisBaseline should correspond to UILayoutConstraintAxisHorizontal."); 117 | 118 | XCTAssertThrows([UIView al_attributeForAxis:(ALAxis)ALEdgeTop], @"Passing an invalid ALAxis should throw an exception."); 119 | XCTAssertThrows([UIView al_attributeForAxis:(ALAxis)ALEdgeBottom], @"Passing an invalid ALAxis should throw an exception."); 120 | XCTAssertThrows([UIView al_attributeForAxis:(ALAxis)ALEdgeLeft], @"Passing an invalid ALAxis should throw an exception."); 121 | XCTAssertThrows([UIView al_attributeForAxis:(ALAxis)ALEdgeRight], @"Passing an invalid ALAxis should throw an exception."); 122 | XCTAssertThrows([UIView al_attributeForAxis:(ALAxis)ALEdgeLeading], @"Passing an invalid ALAxis should throw an exception."); 123 | XCTAssertThrows([UIView al_attributeForAxis:(ALAxis)ALEdgeTrailing], @"Passing an invalid ALAxis should throw an exception."); 124 | XCTAssertThrows([UIView al_attributeForAxis:(ALAxis)ALDimensionHeight], @"Passing an invalid ALAxis should throw an exception."); 125 | XCTAssertThrows([UIView al_attributeForAxis:(ALAxis)ALDimensionWidth], @"Passing an invalid ALAxis should throw an exception."); 126 | XCTAssertThrows([UIView al_attributeForAxis:(ALAxis)NSLayoutAttributeNotAnAttribute], @"Passing an invalid ALAxis should throw an exception."); 127 | } 128 | 129 | /** 130 | Test the internal helper method to identify the common superview of two views. 131 | */ 132 | - (void)testCommonSuperviewWithView 133 | { 134 | XCTAssert([self.viewA al_commonSuperviewWithView:self.viewB] == self.containerView, @"The common superview of viewA and viewB should be containerView."); 135 | XCTAssert([self.viewB al_commonSuperviewWithView:self.viewA] == self.containerView, @"The common superview of viewB and viewA should be containerView."); 136 | XCTAssert([self.viewA al_commonSuperviewWithView:self.viewC] == self.containerView, @"The common superview of viewA and viewC should be containerView."); 137 | XCTAssert([self.viewA al_commonSuperviewWithView:self.viewD] == self.containerView, @"The common superview of viewA and viewD should be containerView."); 138 | XCTAssert([self.viewB al_commonSuperviewWithView:self.viewD] == self.containerView, @"The common superview of viewB and viewD should be containerView."); 139 | XCTAssert([self.viewC al_commonSuperviewWithView:self.viewD] == self.containerView, @"The common superview of viewC and viewD should be containerView."); 140 | XCTAssert([self.viewA al_commonSuperviewWithView:self.viewC] == self.containerView, @"The common superview of viewA and viewC should be containerView."); 141 | 142 | XCTAssert([self.viewA al_commonSuperviewWithView:self.viewA_A] == self.viewA, @"The common superview of viewA and viewA_A should be viewA."); 143 | XCTAssert([self.viewA al_commonSuperviewWithView:self.viewA_B] == self.viewA, @"The common superview of viewA and viewA_B should be viewA."); 144 | XCTAssert([self.viewA al_commonSuperviewWithView:self.viewA_A_A] == self.viewA, @"The common superview of viewA and viewA_A_A should be viewA."); 145 | XCTAssert([self.viewA_A al_commonSuperviewWithView:self.viewA] == self.viewA, @"The common superview of viewA_A and viewA should be viewA."); 146 | XCTAssert([self.viewA_B al_commonSuperviewWithView:self.viewA] == self.viewA, @"The common superview of viewA_B and viewA should be viewA."); 147 | XCTAssert([self.viewA_A_A al_commonSuperviewWithView:self.viewA] == self.viewA, @"The common superview of viewA_A_A and viewA should be viewA."); 148 | 149 | XCTAssert([self.viewA_A_A al_commonSuperviewWithView:self.viewA_B_A] == self.viewA, @"The common superview of viewA_A_A and viewA_B_A should be viewA."); 150 | XCTAssert([self.viewA_B_A al_commonSuperviewWithView:self.viewA_A_A] == self.viewA, @"The common superview of viewA_B_A and viewA_A_A should be viewA."); 151 | 152 | XCTAssert([self.viewA_A_A al_commonSuperviewWithView:self.viewD] == self.containerView, @"The common superview of viewA_A_A and viewD should be containerView."); 153 | XCTAssert([self.viewD al_commonSuperviewWithView:self.viewA_A_A] == self.containerView, @"The common superview of viewD and viewA_A_A should be containerView."); 154 | 155 | XCTAssert([self.viewA_A_A al_commonSuperviewWithView:self.viewA_A_B] == self.viewA_A, @"The common superview of viewA_A_A and viewA_A_B should be viewA_A."); 156 | XCTAssert([self.viewA_A_B al_commonSuperviewWithView:self.viewA_A_A] == self.viewA_A, @"The common superview of viewA_A_B and viewA_A_A should be viewA_A."); 157 | 158 | XCTAssert([self.viewA_B al_commonSuperviewWithView:self.viewA_B] == self.viewA_B, @"The common superview of viewA_B and viewA_B should be itself."); 159 | 160 | UIView *orphanView = [UIView newAutoLayoutView]; // has no superview 161 | 162 | XCTAssert([orphanView al_commonSuperviewWithView:orphanView] == orphanView, @"The common superview of orphanView and orphanView should be itself."); 163 | 164 | XCTAssertThrows([orphanView al_commonSuperviewWithView:self.viewA_A_A], @"An exception should be thrown as there is no common superview of orphanView and viewA_A_A."); 165 | XCTAssertThrows([self.viewA_A_A al_commonSuperviewWithView:orphanView], @"An exception should be thrown as there is no common superview of view_A_A_A and orphanView."); 166 | 167 | XCTAssertThrows([orphanView al_commonSuperviewWithView:self.containerView], @"An exception should be thrown as there is no common superview of orphanView and containerView."); 168 | XCTAssertThrows([self.containerView al_commonSuperviewWithView:orphanView], @"An exception should be thrown as there is no common superview of containerView and orphanView."); 169 | } 170 | 171 | /** 172 | Test the internal helper method to identify the common superview of an array of views. 173 | */ 174 | - (void)testCommonSuperviewOfViews 175 | { 176 | NSArray *viewArray = @[self.viewA, self.viewB, self.viewC]; 177 | XCTAssert([viewArray al_commonSuperviewOfViews] == self.containerView, @"The common superview of viewArray should be containerView."); 178 | 179 | viewArray = @[self.viewC, self.viewB, self.viewA_A]; 180 | XCTAssert([viewArray al_commonSuperviewOfViews] == self.containerView, @"The common superview of viewArray should be containerView."); 181 | 182 | viewArray = @[self.viewA_A_B, self.viewA_A_A]; 183 | XCTAssert([viewArray al_commonSuperviewOfViews] == self.viewA_A, @"The common superview of viewArray should be viewA_A."); 184 | 185 | viewArray = @[self.viewA_A_B, self.viewA_A_A, self.viewA]; 186 | XCTAssert([viewArray al_commonSuperviewOfViews] == self.viewA, @"The common superview of viewArray should be viewA."); 187 | 188 | 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]; 189 | XCTAssert([viewArray al_commonSuperviewOfViews] == self.containerView, @"The common superview of viewArray should be containerView."); 190 | 191 | UIView *orphanView = [UIView newAutoLayoutView]; // has no superview 192 | 193 | viewArray = @[orphanView]; 194 | XCTAssert([viewArray al_commonSuperviewOfViews] == orphanView, @"The common superview of viewArray should be orphanView."); 195 | 196 | viewArray = @[orphanView, self.viewC, self.viewB, self.viewA_A]; 197 | XCTAssertThrows([viewArray al_commonSuperviewOfViews], @"An exception should be thrown as there is no common superview of viewArray."); 198 | 199 | viewArray = @[self.viewA_A_B, self.viewB, orphanView]; 200 | XCTAssertThrows([viewArray al_commonSuperviewOfViews], @"An exception should be thrown as there is no common superview of viewArray."); 201 | } 202 | 203 | /** 204 | Test the internal helper method that counts whether an array contains a minimum number of views. 205 | */ 206 | - (void)testContainsMinimumNumberOfViews 207 | { 208 | NSArray *array = @[[NSObject new], [UILabel new], [UIImageView new], [NSString new], [UIView new], [NSDecimalNumber new], [NSLayoutConstraint new]]; 209 | XCTAssert([array al_containsMinimumNumberOfViews:2]); 210 | XCTAssert([array al_containsMinimumNumberOfViews:3]); 211 | XCTAssert([array al_containsMinimumNumberOfViews:4] == NO); 212 | 213 | array = @[[UIView newAutoLayoutView]]; 214 | XCTAssert([array al_containsMinimumNumberOfViews:1]); 215 | XCTAssert([array al_containsMinimumNumberOfViews:2] == NO); 216 | 217 | array = @[]; 218 | XCTAssert([array al_containsMinimumNumberOfViews:0]); 219 | XCTAssert([array al_containsMinimumNumberOfViews:1] == NO); 220 | } 221 | 222 | /** 223 | Test the internal helper method to return a copy of an arbitrary array containing only the views. 224 | */ 225 | - (void)testCopyViewsOnly 226 | { 227 | NSArray *startingArray = @[[NSObject new], [UILabel new], [UIImageView new], [NSString new], [UIView new], [NSDecimalNumber new], [NSLayoutConstraint new]]; 228 | NSArray *viewsOnlyArray = [startingArray al_copyViewsOnly]; 229 | XCTAssert([viewsOnlyArray count] == 3, @"Only 3 objects should remain in the new array."); 230 | 231 | startingArray = @[[UIView newAutoLayoutView]]; 232 | viewsOnlyArray = [startingArray al_copyViewsOnly]; 233 | XCTAssert([viewsOnlyArray count] == 1, @"1 object should remain in the new array."); 234 | XCTAssert(viewsOnlyArray[0] == startingArray[0], @"The one object in both arrays should be identical."); 235 | 236 | startingArray = @[]; 237 | viewsOnlyArray = [startingArray al_copyViewsOnly]; 238 | XCTAssert([viewsOnlyArray count] == 0, @"The new array should be empty."); 239 | } 240 | 241 | @end 242 | -------------------------------------------------------------------------------- /Tests/AutoLayoutTests/AutoLayoutPinEdgesTests.m: -------------------------------------------------------------------------------- 1 | // 2 | // AutoLayoutPinEdgesTests.m 3 | // UIView+AutoLayout Tests 4 | // 5 | // Copyright (c) 2014 Tyler Fox 6 | // https://github.com/smileyborg/UIView-AutoLayout 7 | // 8 | 9 | #import "AutoLayoutTestBase.h" 10 | 11 | @interface AutoLayoutPinEdgesTests : AutoLayoutTestBase 12 | 13 | @end 14 | 15 | @implementation AutoLayoutPinEdgesTests 16 | 17 | - (void)setUp 18 | { 19 | [super setUp]; 20 | 21 | } 22 | 23 | - (void)tearDown 24 | { 25 | 26 | [super tearDown]; 27 | } 28 | 29 | - (void)testAutoPinEdgeToSuperviewEdge 30 | { 31 | [self.viewA autoPinEdgeToSuperviewEdge:ALEdgeTop withInset:10.0]; 32 | [self.viewA autoPinEdgeToSuperviewEdge:ALEdgeLeft withInset:5.0]; 33 | [self evaluateConstraints]; 34 | ALAssertOriginEquals(self.viewA, 5.0, 10.0); 35 | 36 | [self.viewA autoPinEdgeToSuperviewEdge:ALEdgeRight withInset:0.0]; 37 | [self.viewA autoPinEdgeToSuperviewEdge:ALEdgeBottom withInset:-10.0]; 38 | [self evaluateConstraints]; 39 | ALAssertFrameEquals(self.viewA, 5.0, 10.0, kContainerViewWidth - 5.0, kContainerViewHeight); 40 | 41 | [self.viewB autoPinEdgeToSuperviewEdge:ALEdgeTrailing withInset:0.0]; 42 | [self.viewB autoPinEdgeToSuperviewEdge:ALEdgeBottom withInset:-52.0]; 43 | [self evaluateConstraints]; 44 | ALAssertMaxEquals(self.viewB, kContainerViewWidth, kContainerViewHeight + 52.0); 45 | 46 | [self.viewB autoPinEdgeToSuperviewEdge:ALEdgeLeading withInset:500.0]; 47 | [self evaluateConstraints]; 48 | ALAssertOriginXEquals(self.viewB, 500.0); 49 | 50 | [self.viewB autoPinEdgeToSuperviewEdge:ALEdgeTop withInset:0.0]; 51 | [self evaluateConstraints]; 52 | ALAssertFrameEquals(self.viewB, 500.0, 0.0, kContainerViewWidth - 500.0, kContainerViewHeight + 52.0); 53 | } 54 | 55 | @end 56 | -------------------------------------------------------------------------------- /Tests/AutoLayoutTests/AutoLayoutPriorityTests.m: -------------------------------------------------------------------------------- 1 | // 2 | // AutoLayoutPriorityTests.m 3 | // UIView+AutoLayout Tests 4 | // 5 | // Copyright (c) 2014 Tyler Fox 6 | // https://github.com/smileyborg/UIView-AutoLayout 7 | // 8 | 9 | #import "AutoLayoutTestBase.h" 10 | 11 | #define DEFINE_WEAK_SELF __weak __typeof(self) weakSelf = self; 12 | 13 | @interface AutoLayoutPriorityTests : AutoLayoutTestBase 14 | 15 | @end 16 | 17 | @implementation AutoLayoutPriorityTests 18 | 19 | - (void)setUp 20 | { 21 | [super setUp]; 22 | 23 | } 24 | 25 | - (void)tearDown 26 | { 27 | 28 | [super tearDown]; 29 | } 30 | 31 | /** 32 | Returns an array of the default priorities to test. 33 | */ 34 | - (NSArray *)defaultPriorities 35 | { 36 | return @[@(UILayoutPriorityFittingSizeLevel), @(UILayoutPriorityDefaultHigh), @(UILayoutPriorityRequired), @(UILayoutPriorityDefaultLow)]; 37 | } 38 | 39 | /** 40 | A helper method that takes a block containing a call to the UIView+AutoLayout API which adds one constraint, 41 | and calls -[assertConstraint:isAddedWithPriority:] for each of the default priorities. 42 | */ 43 | - (void)assertConstraintIsAddedWithDefaultPriorities:(NSLayoutConstraint *(^)())block 44 | { 45 | for (NSNumber *layoutPriority in [self defaultPriorities]) { 46 | [self assertConstraint:block isAddedWithPriority:[layoutPriority floatValue]]; 47 | } 48 | } 49 | 50 | /** 51 | A helper method that takes a block containing one or more calls to the UIView+AutoLayout API which add multiple 52 | constraints, and calls -[assertConstraints:areAddedWithPriority:] for each of the default priorities. 53 | */ 54 | - (void)assertConstraintsAreAddedWithDefaultPriorities:(NSArray *(^)())block 55 | { 56 | for (NSNumber *layoutPriority in [self defaultPriorities]) { 57 | [self assertConstraints:block areAddedWithPriority:[layoutPriority floatValue]]; 58 | } 59 | } 60 | 61 | /** 62 | A helper method that takes a block containing a call to the UIView+AutoLayout API which adds one constraint, 63 | and verifies that when the +[UIView autoSetPriority:forConstraints:] method is used, this one constraint is 64 | added with the correct priority specified. 65 | */ 66 | - (void)assertConstraint:(NSLayoutConstraint *(^)())block isAddedWithPriority:(UILayoutPriority)priority 67 | { 68 | [self assertConstraints:^NSArray *{ return @[block()]; } areAddedWithPriority:priority]; 69 | } 70 | 71 | /** 72 | A helper method that takes a block containing one or more calls to the UIView+AutoLayout API which add multiple 73 | constraints, and verifies that when the +[UIView autoSetPriority:forConstraints:] method is used, these 74 | constraints are added with the correct priority specified. 75 | */ 76 | - (void)assertConstraints:(NSArray *(^)())block areAddedWithPriority:(UILayoutPriority)priority 77 | { 78 | __block NSArray *constraints; 79 | [UIView autoSetPriority:priority forConstraints:^{ 80 | constraints = block(); 81 | }]; 82 | XCTAssert([constraints count] > 0, @"The array of constraints should not be empty."); 83 | for (NSLayoutConstraint *constraint in constraints) { 84 | XCTAssert(constraint.priority == priority, @"The constraint priority should be equal to the one specified for the constraints block."); 85 | } 86 | } 87 | 88 | /** 89 | Test setting the priority of constraints that center views to their superview. 90 | */ 91 | - (void)testPriorityForCentering 92 | { 93 | DEFINE_WEAK_SELF 94 | 95 | [self assertConstraintsAreAddedWithDefaultPriorities:^NSArray *{ 96 | return [weakSelf.viewA autoCenterInSuperview]; 97 | }]; 98 | 99 | [self assertConstraintIsAddedWithDefaultPriorities:^NSLayoutConstraint *{ 100 | return [weakSelf.viewB autoAlignAxisToSuperviewAxis:ALAxisHorizontal]; 101 | }]; 102 | 103 | [self assertConstraintIsAddedWithDefaultPriorities:^NSLayoutConstraint *{ 104 | return [weakSelf.viewC autoAlignAxisToSuperviewAxis:ALAxisBaseline]; 105 | }]; 106 | 107 | [self assertConstraintIsAddedWithDefaultPriorities:^NSLayoutConstraint *{ 108 | return [weakSelf.viewC autoAlignAxisToSuperviewAxis:ALAxisVertical]; 109 | }]; 110 | } 111 | 112 | /** 113 | Test setting the priority of constraints that pin edges of views to their superview. 114 | */ 115 | - (void)testPriorityForPinningEdgesToSuperview 116 | { 117 | DEFINE_WEAK_SELF 118 | 119 | [self assertConstraintIsAddedWithDefaultPriorities:^NSLayoutConstraint *{ 120 | return [weakSelf.viewA autoPinEdgeToSuperviewEdge:ALEdgeBottom withInset:15.0]; 121 | }]; 122 | 123 | [self assertConstraintIsAddedWithDefaultPriorities:^NSLayoutConstraint *{ 124 | return [weakSelf.viewB autoPinEdgeToSuperviewEdge:ALEdgeRight withInset:0.0 relation:NSLayoutRelationGreaterThanOrEqual]; 125 | }]; 126 | 127 | [self assertConstraintsAreAddedWithDefaultPriorities:^NSArray *{ 128 | return [weakSelf.viewC autoPinEdgesToSuperviewEdgesWithInsets:UIEdgeInsetsZero]; 129 | }]; 130 | 131 | [self assertConstraintsAreAddedWithDefaultPriorities:^NSArray *{ 132 | return [weakSelf.viewD autoPinEdgesToSuperviewEdgesWithInsets:UIEdgeInsetsMake(5.5, -50.0, 42.6, 860.9) excludingEdge:ALEdgeTrailing]; 133 | }]; 134 | } 135 | 136 | /** 137 | Test setting the priority of constraints that pin edges of views. 138 | */ 139 | - (void)testPriorityForPinningEdges 140 | { 141 | DEFINE_WEAK_SELF 142 | 143 | [self assertConstraintIsAddedWithDefaultPriorities:^NSLayoutConstraint *{ 144 | return [weakSelf.viewA autoPinEdge:ALEdgeTop toEdge:ALEdgeBottom ofView:weakSelf.viewB]; 145 | }]; 146 | 147 | [self assertConstraintIsAddedWithDefaultPriorities:^NSLayoutConstraint *{ 148 | return [weakSelf.viewB autoPinEdge:ALEdgeTrailing toEdge:ALEdgeLeft ofView:weakSelf.viewC withOffset:-95.0]; 149 | }]; 150 | 151 | [self assertConstraintIsAddedWithDefaultPriorities:^NSLayoutConstraint *{ 152 | return [weakSelf.viewC autoPinEdge:ALEdgeRight toEdge:ALEdgeBottom ofView:weakSelf.viewD withOffset:555.0]; 153 | }]; 154 | } 155 | 156 | /** 157 | Test setting the priority of constraints that align axes of views. 158 | */ 159 | - (void)testPriorityForAligningAxes 160 | { 161 | DEFINE_WEAK_SELF 162 | 163 | [self assertConstraintIsAddedWithDefaultPriorities:^NSLayoutConstraint *{ 164 | return [weakSelf.viewA autoAlignAxis:ALAxisHorizontal toSameAxisOfView:weakSelf.viewB]; 165 | }]; 166 | 167 | [self assertConstraintIsAddedWithDefaultPriorities:^NSLayoutConstraint *{ 168 | return [weakSelf.viewC autoAlignAxis:ALAxisVertical toSameAxisOfView:weakSelf.viewD]; 169 | }]; 170 | 171 | [self assertConstraintIsAddedWithDefaultPriorities:^NSLayoutConstraint *{ 172 | return [weakSelf.viewB autoAlignAxis:ALAxisBaseline toSameAxisOfView:weakSelf.viewA withOffset:-60.0]; 173 | }]; 174 | } 175 | 176 | /** 177 | Test setting the priority of constraints that match dimensions of views. 178 | */ 179 | - (void)testPriorityForMatchingDimensions 180 | { 181 | DEFINE_WEAK_SELF 182 | 183 | [self assertConstraintsAreAddedWithDefaultPriorities:^NSArray *{ 184 | return [weakSelf.viewA autoSetDimensionsToSize:CGSizeMake(90, 180)]; 185 | }]; 186 | 187 | [self assertConstraintIsAddedWithDefaultPriorities:^NSLayoutConstraint *{ 188 | return [weakSelf.viewB autoSetDimension:ALDimensionHeight toSize:0.0]; 189 | }]; 190 | 191 | [self assertConstraintIsAddedWithDefaultPriorities:^NSLayoutConstraint *{ 192 | return [weakSelf.viewC autoSetDimension:ALDimensionWidth toSize:5.0 relation:NSLayoutRelationLessThanOrEqual]; 193 | }]; 194 | } 195 | 196 | /** 197 | Test setting the priority of the content compression resistance and content hugging implicit constraints. 198 | */ 199 | - (void)testPriorityForContentCompressionResistanceAndContentHugging 200 | { 201 | UILabel *labelA = [UILabel newAutoLayoutView]; // use UILabel since it will have all 4 implicit constraints generated 202 | labelA.text = @"Some text."; 203 | 204 | [UIView autoSetPriority:UILayoutPriorityRequired forConstraints:^{ 205 | [labelA autoSetContentCompressionResistancePriorityForAxis:ALAxisHorizontal]; 206 | }]; 207 | XCTAssert([labelA contentCompressionResistancePriorityForAxis:UILayoutConstraintAxisHorizontal] == UILayoutPriorityRequired, @"The constraint priority should be equal to the one specified for the constraints block."); 208 | 209 | [UIView autoSetPriority:UILayoutPriorityFittingSizeLevel + 1 forConstraints:^{ 210 | [labelA autoSetContentCompressionResistancePriorityForAxis:ALAxisVertical]; 211 | }]; 212 | XCTAssert([labelA contentCompressionResistancePriorityForAxis:UILayoutConstraintAxisVertical] == UILayoutPriorityFittingSizeLevel + 1, @"The constraint priority should be equal to the one specified for the constraints block."); 213 | 214 | [UIView autoSetPriority:UILayoutPriorityRequired forConstraints:^{ 215 | [labelA autoSetContentHuggingPriorityForAxis:ALAxisHorizontal]; 216 | }]; 217 | XCTAssert([labelA contentHuggingPriorityForAxis:UILayoutConstraintAxisHorizontal] == UILayoutPriorityRequired, @"The constraint priority should be equal to the one specified for the constraints block."); 218 | 219 | [UIView autoSetPriority:UILayoutPriorityDefaultHigh - 1 forConstraints:^{ 220 | [labelA autoSetContentHuggingPriorityForAxis:ALAxisVertical]; 221 | }]; 222 | XCTAssert([labelA contentHuggingPriorityForAxis:UILayoutConstraintAxisVertical] == UILayoutPriorityDefaultHigh - 1, @"The constraint priority should be equal to the one specified for the constraints block."); 223 | } 224 | 225 | /** 226 | Test setting the priority of constraints that constrain any attribute of views. 227 | */ 228 | - (void)testPriorityForConstrainingAnyAttribute 229 | { 230 | DEFINE_WEAK_SELF 231 | 232 | [self assertConstraintIsAddedWithDefaultPriorities:^NSLayoutConstraint *{ 233 | return [weakSelf.viewA autoConstrainAttribute:ALAxisVertical toAttribute:ALEdgeBottom ofView:weakSelf.viewB]; 234 | }]; 235 | 236 | [self assertConstraintIsAddedWithDefaultPriorities:^NSLayoutConstraint *{ 237 | return [weakSelf.viewA autoConstrainAttribute:ALEdgeRight toAttribute:ALAxisHorizontal ofView:weakSelf.viewC withOffset:50.0]; 238 | }]; 239 | 240 | [self assertConstraintIsAddedWithDefaultPriorities:^NSLayoutConstraint *{ 241 | return [weakSelf.viewA autoConstrainAttribute:ALDimensionWidth toAttribute:ALDimensionHeight ofView:weakSelf.viewD withOffset:-100.0 relation:NSLayoutRelationLessThanOrEqual]; 242 | }]; 243 | 244 | [self assertConstraintIsAddedWithDefaultPriorities:^NSLayoutConstraint *{ 245 | return [weakSelf.viewD autoConstrainAttribute:ALAxisBaseline toAttribute:ALEdgeTrailing ofView:weakSelf.viewA withMultiplier:-6.0]; 246 | }]; 247 | 248 | [self assertConstraintIsAddedWithDefaultPriorities:^NSLayoutConstraint *{ 249 | return [weakSelf.viewB autoConstrainAttribute:ALEdgeTop toAttribute:ALEdgeLeading ofView:weakSelf.viewA withMultiplier:0.45 relation:NSLayoutRelationGreaterThanOrEqual]; 250 | }]; 251 | } 252 | 253 | /** 254 | Test setting the priority of constraints that pin views to the view controller layout guides. 255 | */ 256 | - (void)testPriorityForPinningToLayoutGuides 257 | { 258 | DEFINE_WEAK_SELF 259 | 260 | UIViewController *viewController = [[UIViewController alloc] initWithNibName:nil bundle:nil]; 261 | [viewController view]; // touch view to load it 262 | 263 | [self assertConstraintIsAddedWithDefaultPriorities:^NSLayoutConstraint *{ 264 | return [weakSelf.viewA autoPinToTopLayoutGuideOfViewController:viewController withInset:50.0]; 265 | }]; 266 | 267 | [self assertConstraintIsAddedWithDefaultPriorities:^NSLayoutConstraint *{ 268 | return [weakSelf.viewA autoPinToTopLayoutGuideOfViewController:viewController withInset:0.0]; 269 | }]; 270 | 271 | [self assertConstraintIsAddedWithDefaultPriorities:^NSLayoutConstraint *{ 272 | return [weakSelf.viewA autoPinToBottomLayoutGuideOfViewController:viewController withInset:-5.0]; 273 | }]; 274 | } 275 | 276 | /** 277 | Test setting the priority of constraints that constrain an array of views. 278 | */ 279 | - (void)testPriorityForConstrainingMultipleViews 280 | { 281 | DEFINE_WEAK_SELF 282 | 283 | [self assertConstraintsAreAddedWithDefaultPriorities:^NSArray *{ 284 | return [weakSelf.viewArray autoAlignViewsToEdge:ALEdgeBottom]; 285 | }]; 286 | 287 | [self assertConstraintsAreAddedWithDefaultPriorities:^NSArray *{ 288 | return [weakSelf.viewArray autoAlignViewsToAxis:ALAxisVertical]; 289 | }]; 290 | 291 | [self assertConstraintsAreAddedWithDefaultPriorities:^NSArray *{ 292 | return [weakSelf.viewArray autoMatchViewsDimension:ALDimensionWidth]; 293 | }]; 294 | 295 | [self assertConstraintsAreAddedWithDefaultPriorities:^NSArray *{ 296 | return [weakSelf.viewArray autoSetViewsDimension:ALDimensionHeight toSize:10.0]; 297 | }]; 298 | } 299 | 300 | /** 301 | Test setting the priority of constraints that distribute an array of views. 302 | */ 303 | - (void)testPriorityForDistributingMultipleViews 304 | { 305 | DEFINE_WEAK_SELF 306 | 307 | [self assertConstraintsAreAddedWithDefaultPriorities:^NSArray *{ 308 | return [weakSelf.viewArray autoDistributeViewsAlongAxis:ALAxisHorizontal withFixedSize:25.0 alignment:NSLayoutFormatAlignAllBottom]; 309 | }]; 310 | 311 | [self assertConstraintsAreAddedWithDefaultPriorities:^NSArray *{ 312 | return [weakSelf.viewArray autoDistributeViewsAlongAxis:ALAxisVertical withFixedSize:5.0 insetSpacing:NO alignment:NSLayoutFormatAlignAllRight]; 313 | }]; 314 | 315 | [self assertConstraintsAreAddedWithDefaultPriorities:^NSArray *{ 316 | return [weakSelf.viewArray autoDistributeViewsAlongAxis:ALAxisVertical withFixedSpacing:0.0 alignment:NSLayoutFormatAlignAllLeading]; 317 | }]; 318 | 319 | [self assertConstraintsAreAddedWithDefaultPriorities:^NSArray *{ 320 | return [weakSelf.viewArray autoDistributeViewsAlongAxis:ALAxisHorizontal withFixedSpacing:899.5 insetSpacing:NO alignment:NSLayoutFormatAlignAllCenterY]; 321 | }]; 322 | } 323 | 324 | @end 325 | -------------------------------------------------------------------------------- /Tests/AutoLayoutTests/AutoLayoutRemovalTests.m: -------------------------------------------------------------------------------- 1 | // 2 | // AutoLayoutRemovalTests.m 3 | // UIView+AutoLayout Tests 4 | // 5 | // Copyright (c) 2014 Tyler Fox 6 | // https://github.com/smileyborg/UIView-AutoLayout 7 | // 8 | 9 | #import "AutoLayoutTestBase.h" 10 | 11 | @interface AutoLayoutRemovalTests : AutoLayoutTestBase 12 | 13 | @end 14 | 15 | @implementation AutoLayoutRemovalTests 16 | 17 | - (void)setUp 18 | { 19 | [super setUp]; 20 | 21 | } 22 | 23 | - (void)tearDown 24 | { 25 | 26 | [super tearDown]; 27 | } 28 | 29 | /** 30 | Test the +[removeConstraint:] method on UIView. 31 | Test the case where we're removing a constraint that was added to the closest common superview of the two views it 32 | constrains. 33 | */ 34 | - (void)testRemoveConstraint 35 | { 36 | [self.viewA autoCenterInSuperview]; 37 | 38 | NSUInteger constraintsCount = [self.viewA.superview.constraints count]; 39 | XCTAssert(constraintsCount > 0, @"viewA's superview should have constraints added to it."); 40 | 41 | [UIView autoRemoveConstraint:self.viewA.superview.constraints[0]]; 42 | NSUInteger newConstraintsCount = [self.viewA.superview.constraints count]; 43 | XCTAssert(constraintsCount - newConstraintsCount == 1, @"viewA's superview should have one less constraint on it."); 44 | 45 | [self.viewB removeFromSuperview]; 46 | [self.viewA addSubview:self.viewB]; 47 | 48 | [self.viewB autoCenterInSuperview]; 49 | } 50 | 51 | /** 52 | Test the +[removeConstraint:] method on UIView. 53 | Test the case where we're removing a constraint that only applies to one view. 54 | */ 55 | - (void)testRemoveConstraintFromSingleView 56 | { 57 | NSLayoutConstraint *constraint = [self.viewA autoSetDimension:ALDimensionWidth toSize:10.0]; 58 | 59 | NSUInteger constraintsCount = [self.viewA.constraints count]; 60 | XCTAssert(constraintsCount > 0, @"viewA should have a constraint added to it."); 61 | 62 | [UIView autoRemoveConstraint:constraint]; 63 | NSUInteger newConstraintsCount = [self.viewA.constraints count]; 64 | XCTAssert(constraintsCount - newConstraintsCount == 1, @"viewA should have one less constraint on it."); 65 | } 66 | 67 | /** 68 | Test the +[removeConstraint:] method on UIView. 69 | Test the case where we're removing a constraint that was added to a view that is not the closest common superview of 70 | the two views it constrains. 71 | */ 72 | - (void)testRemoveConstraintFromNotImmediateSuperview 73 | { 74 | [self.viewC removeFromSuperview]; 75 | [self.viewB removeFromSuperview]; 76 | [self.viewA addSubview:self.viewB]; 77 | [self.viewB addSubview:self.viewC]; 78 | 79 | NSLayoutConstraint *constraint = [self.viewC autoAlignAxisToSuperviewAxis:ALAxisHorizontal]; 80 | [self.viewB removeConstraint:constraint]; 81 | [self.containerView addConstraint:constraint]; 82 | 83 | NSUInteger constraintsCount = [self.containerView.constraints count]; 84 | XCTAssert(constraintsCount > 0, @"containerView should have a constraint added to it."); 85 | 86 | [UIView autoRemoveConstraint:constraint]; 87 | NSUInteger newConstraintsCount = [self.containerView.constraints count]; 88 | XCTAssert(constraintsCount - newConstraintsCount == 1, @"containerView should have one less constraint on it."); 89 | } 90 | 91 | /** 92 | Test the +[removeConstraints:] method on UIView. 93 | */ 94 | - (void)testRemoveConstraints 95 | { 96 | NSArray *constraints = [@[self.viewA, self.viewB, self.viewC, self.viewD] autoDistributeViewsAlongAxis:ALAxisHorizontal withFixedSize:10.0 alignment:NSLayoutFormatAlignAllCenterY]; 97 | 98 | NSUInteger constraintsCount = [self.containerView.constraints count]; 99 | XCTAssert(constraintsCount > 0, @"containerView should have constraints added to it."); 100 | 101 | [UIView autoRemoveConstraints:constraints]; 102 | NSUInteger newConstraintsCount = [self.containerView.constraints count]; 103 | XCTAssert(newConstraintsCount == 0, @"containerView should have no constraints on it."); 104 | } 105 | 106 | /** 107 | Test the -[autoRemove] method on NSLayoutConstraint. 108 | */ 109 | - (void)testRemove 110 | { 111 | NSLayoutConstraint *constraint = [self.containerView autoSetDimension:ALDimensionHeight toSize:0.0]; 112 | 113 | NSUInteger constraintsCount = [self.containerView.constraints count]; 114 | XCTAssert(constraintsCount > 0, @"containerView should have a constraint added to it."); 115 | 116 | [constraint autoRemove]; 117 | NSUInteger newConstraintsCount = [self.containerView.constraints count]; 118 | XCTAssert(constraintsCount - newConstraintsCount == 1, @"containerView should have one less constraint on it."); 119 | } 120 | 121 | @end 122 | -------------------------------------------------------------------------------- /Tests/AutoLayoutTests/AutoLayoutTestBase.h: -------------------------------------------------------------------------------- 1 | // 2 | // AutoLayoutTestBase.h 3 | // UIView+AutoLayout Tests 4 | // 5 | // Copyright (c) 2014 Tyler Fox 6 | // https://github.com/smileyborg/UIView-AutoLayout 7 | // 8 | 9 | #import 10 | #import "UIView+AutoLayoutInternal.h" 11 | 12 | #define ALAssertFrameEquals(view, x, y, w, h) XCTAssert(CGRectEqualToRect(view.frame, CGRectMake(x, y, w, h))) 13 | #define ALAssertOriginEquals(view, x, y) XCTAssert(CGRectGetMinX(view.frame) == x && CGRectGetMinY(view.frame) == y) 14 | #define ALAssertCenterEquals(view, x, y) XCTAssert(CGRectGetMidX(view.frame) == x && CGRectGetMidY(view.frame) == y) 15 | #define ALAssertMaxEquals(view, x, y) XCTAssert(CGRectGetMaxX(view.frame) == x && CGRectGetMaxY(view.frame) == y) 16 | #define ALAssertSizeEquals(view, w, h) XCTAssert(CGRectGetWidth(view.frame) == w && CGRectGetHeight(view.frame) == h) 17 | #define ALAssertOriginXEquals(view, x) XCTAssert(CGRectGetMinX(view.frame) == x) 18 | #define ALAssertOriginYEquals(view, y) XCTAssert(CGRectGetMinY(view.frame) == y) 19 | #define ALAssertCenterXEquals(view, x) XCTAssert(CGRectGetMidX(view.frame) == x) 20 | #define ALAssertCenterYEquals(view, y) XCTAssert(CGRectGetMidY(view.frame) == y) 21 | #define ALAssertMaxXEquals(view, x) XCTAssert(CGRectGetMaxX(view.frame) == x) 22 | #define ALAssertMaxYEquals(view, y) XCTAssert(CGRectGetMaxY(view.frame) == y) 23 | #define ALAssertWidthEquals(view, w) XCTAssert(CGRectGetWidth(view.frame) == w) 24 | #define ALAssertHeightEquals(view, h) XCTAssert(CGRectGetHeight(view.frame) == h) 25 | 26 | static const CGFloat kContainerViewWidth = 1000.0; 27 | static const CGFloat kContainerViewHeight = 1000.0; 28 | 29 | @interface AutoLayoutTestBase : XCTestCase 30 | 31 | // An array of viewA, viewB, viewC, and viewD 32 | @property (nonatomic, readonly) NSArray *viewArray; 33 | 34 | // The indendentation below represents how the view hierarchy is set up 35 | @property (nonatomic, strong) UIView *containerView; 36 | @property (nonatomic, strong) UIView * viewA; 37 | @property (nonatomic, strong) UIView * viewA_A; 38 | @property (nonatomic, strong) UIView * viewA_A_A; 39 | @property (nonatomic, strong) UIView * viewA_A_B; 40 | @property (nonatomic, strong) UIView * viewA_B; 41 | @property (nonatomic, strong) UIView * viewA_B_A; 42 | @property (nonatomic, strong) UIView * viewB; 43 | @property (nonatomic, strong) UIView * viewB_A; 44 | @property (nonatomic, strong) UIView * viewC; 45 | @property (nonatomic, strong) UIView * viewD; 46 | 47 | /** 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. */ 48 | - (void)evaluateConstraints; 49 | 50 | /** Forces the given view to immediately do a layout pass, which will evaluate the constraints and set the frames for the view and any subviews. */ 51 | - (void)evaluateConstraintsForView:(UIView *)view; 52 | 53 | @end 54 | -------------------------------------------------------------------------------- /Tests/AutoLayoutTests/AutoLayoutTestBase.m: -------------------------------------------------------------------------------- 1 | // 2 | // AutoLayoutTestBase.m 3 | // UIView+AutoLayout Tests 4 | // 5 | // Copyright (c) 2014 Tyler Fox 6 | // https://github.com/smileyborg/UIView-AutoLayout 7 | // 8 | 9 | #import "AutoLayoutTestBase.h" 10 | 11 | @implementation AutoLayoutTestBase 12 | 13 | - (NSArray *)viewArray 14 | { 15 | return @[self.viewA, self.viewB, self.viewC, self.viewD]; 16 | } 17 | 18 | - (void)setUp 19 | { 20 | [super setUp]; 21 | 22 | self.containerView = [[UIView alloc] initWithFrame:CGRectMake(0.0, 0.0, kContainerViewWidth, kContainerViewHeight)]; 23 | self.viewA = [UIView newAutoLayoutView]; 24 | self.viewA_A = [UIView newAutoLayoutView]; 25 | self.viewA_A_A = [UIView newAutoLayoutView]; 26 | self.viewA_A_B = [UIView newAutoLayoutView]; 27 | self.viewA_B = [UIView newAutoLayoutView]; 28 | self.viewA_B_A = [UIView newAutoLayoutView]; 29 | self.viewB = [UIView newAutoLayoutView]; 30 | self.viewB_A = [UIView newAutoLayoutView]; 31 | self.viewC = [UIView newAutoLayoutView]; 32 | self.viewD = [UIView newAutoLayoutView]; 33 | 34 | [self.containerView addSubview:self.viewA]; 35 | [self.viewA addSubview:self.viewA_A]; 36 | [self.viewA_A addSubview:self.viewA_A_A]; 37 | [self.viewA_A addSubview:self.viewA_A_B]; 38 | [self.viewA addSubview:self.viewA_B]; 39 | [self.viewA_B addSubview:self.viewA_B_A]; 40 | [self.containerView addSubview:self.viewB]; 41 | [self.viewB addSubview:self.viewB_A]; 42 | [self.containerView addSubview:self.viewC]; 43 | [self.containerView addSubview:self.viewD]; 44 | } 45 | 46 | - (void)tearDown 47 | { 48 | 49 | [super tearDown]; 50 | } 51 | 52 | /** 53 | 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. 54 | */ 55 | - (void)evaluateConstraints 56 | { 57 | [self evaluateConstraintsForView:self.containerView]; 58 | } 59 | 60 | /** 61 | Forces the given view to immediately do a layout pass, which will evaluate the constraints and set the frames for the view and any subviews. 62 | */ 63 | - (void)evaluateConstraintsForView:(UIView *)view 64 | { 65 | [view setNeedsLayout]; 66 | [view layoutIfNeeded]; 67 | } 68 | 69 | /** 70 | Test the view hierarchy to make sure it is correctly established. 71 | */ 72 | - (void)testViewHierarchy 73 | { 74 | XCTAssertNotNil(self.containerView, @"View hierarchy is not setup as expected."); 75 | XCTAssert(self.viewA.superview == self.containerView, @"View hierarchy is not setup as expected."); 76 | XCTAssert(self.viewA_A.superview == self.viewA, @"View hierarchy is not setup as expected."); 77 | XCTAssert(self.viewA_A_A.superview == self.viewA_A, @"View hierarchy is not setup as expected."); 78 | XCTAssert(self.viewA_A_B.superview == self.viewA_A, @"View hierarchy is not setup as expected."); 79 | XCTAssert(self.viewA_B.superview == self.viewA, @"View hierarchy is not setup as expected."); 80 | XCTAssert(self.viewA_B_A.superview == self.viewA_B, @"View hierarchy is not setup as expected."); 81 | XCTAssert(self.viewB.superview == self.containerView, @"View hierarchy is not setup as expected."); 82 | XCTAssert(self.viewB_A.superview == self.viewB, @"View hierarchy is not setup as expected."); 83 | XCTAssert(self.viewC.superview == self.containerView, @"View hierarchy is not setup as expected."); 84 | XCTAssert(self.viewD.superview == self.containerView, @"View hierarchy is not setup as expected."); 85 | } 86 | 87 | @end 88 | -------------------------------------------------------------------------------- /Tests/AutoLayoutTests/AutoLayoutTests-Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | ${EXECUTABLE_NAME} 9 | CFBundleIdentifier 10 | com.smileyborg.${PRODUCT_NAME:rfc1034identifier} 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundlePackageType 14 | BNDL 15 | CFBundleShortVersionString 16 | 1.0 17 | CFBundleSignature 18 | ???? 19 | CFBundleVersion 20 | 1 21 | 22 | 23 | -------------------------------------------------------------------------------- /Tests/AutoLayoutTests/UIView+AutoLayoutInternal.h: -------------------------------------------------------------------------------- 1 | // 2 | // UIView+AutoLayoutInternal.h 3 | // UIView+AutoLayout Tests 4 | // 5 | // Copyright (c) 2014 Tyler Fox 6 | // https://github.com/smileyborg/UIView-AutoLayout 7 | // 8 | 9 | /** 10 | A category that exposes the internal (private) helper methods of the UIView+AutoLayout category for use by unit tests. 11 | */ 12 | @interface UIView (AutoLayoutInternal) 13 | 14 | + (NSLayoutAttribute)al_attributeForEdge:(ALEdge)edge; 15 | + (NSLayoutAttribute)al_attributeForAxis:(ALAxis)axis; 16 | + (NSLayoutAttribute)al_attributeForDimension:(ALDimension)dimension; 17 | + (NSLayoutAttribute)al_attributeForALAttribute:(NSInteger)ALAttribute; 18 | + (UILayoutConstraintAxis)al_constraintAxisForAxis:(ALAxis)axis; 19 | 20 | - (void)al_addConstraintUsingGlobalPriority:(NSLayoutConstraint *)constraint; 21 | - (UIView *)al_commonSuperviewWithView:(UIView *)peerView; 22 | - (NSLayoutConstraint *)al_alignToView:(UIView *)peerView withOption:(NSLayoutFormatOptions)alignment forAxis:(ALAxis)axis; 23 | 24 | @end 25 | 26 | 27 | /** 28 | A category that exposes the internal (private) helper methods of the NSArray+AutoLayout category for use by unit tests. 29 | */ 30 | @interface NSArray (AutoLayoutInternal) 31 | 32 | - (UIView *)al_commonSuperviewOfViews; 33 | - (BOOL)al_containsMinimumNumberOfViews:(NSUInteger)minimumNumberOfViews; 34 | - (NSArray *)al_copyViewsOnly; 35 | 36 | @end 37 | -------------------------------------------------------------------------------- /Tests/AutoLayoutTests/en.lproj/InfoPlist.strings: -------------------------------------------------------------------------------- 1 | /* Localized versions of Info.plist keys */ 2 | 3 | -------------------------------------------------------------------------------- /UIView+AutoLayout.podspec: -------------------------------------------------------------------------------- 1 | Pod::Spec.new do |s| 2 | s.deprecated_in_favor_of = 'PureLayout' 3 | s.name = "UIView+AutoLayout" 4 | s.version = "2.0.1" 5 | s.summary = "The ultimate API for iOS Auto Layout. Deprecated in favor of PureLayout: https://github.com/smileyborg/PureLayout" 6 | 7 | s.description = <<-DESC 8 | Introducing [PureLayout](https://github.com/smileyborg/PureLayout) 9 | ======================== 10 | ### UIView+AutoLayout has been deprecated in favor of [PureLayout](https://github.com/smileyborg/PureLayout), which includes OS X support! 11 | 12 | UIView+AutoLayout 13 | ================= 14 | 15 | The ultimate API for iOS Auto Layout -- impressively simple, immensely powerful. Comprised of categories on `UIView`, `NSArray`, and `NSLayoutConstraint`. 16 | 17 | UIView+AutoLayout provides a developer-friendly interface for the vast majority of Auto Layout use cases. It is designed for clarity and simplicity, taking inspiration from the Auto Layout UI options available in Interface Builder but delivering far more flexibility and capability. The API is also highly efficient, as it adds only a thin layer of third party code and is engineered for maximum performance (for example, by automatically adding constraints to the nearest ancestor view). 18 | 19 | API Cheat Sheet 20 | --------------- 21 | 22 | This is just a handy overview of the core API methods. Check out the [header file](https://github.com/smileyborg/UIView-AutoLayout/blob/master/Source/UIView%2BAutoLayout.h) for the full API and documentation. A couple notes: 23 | 24 | * *All of the API methods begin with `auto...` for easy autocompletion!* 25 | * *All methods that generate constraints also automatically add the constraint(s) to the correct view, then return the newly created constraint(s) for you to optionally store for later adjustment or removal.* 26 | * *Many methods below also have a variant which includes a `relation:` parameter to make the constraint an inequality.* 27 | 28 | **`UIView`** 29 | 30 | + autoRemoveConstraint(s): 31 | - autoRemoveConstraintsAffectingView(AndSubviews) 32 | + autoSetPriority:forConstraints: 33 | - autoSetContent(CompressionResistance|Hugging)PriorityForAxis: 34 | - autoCenterInSuperview: 35 | - autoAlignAxisToSuperviewAxis: 36 | - autoPinEdgeToSuperviewEdge:withInset: 37 | - autoPinEdgesToSuperviewEdges:withInsets:(excludingEdge:) 38 | - autoPinEdge:toEdge:ofView:(withOffset:) 39 | - autoAlignAxis:toSameAxisOfView:(withOffset:) 40 | - autoMatchDimension:toDimension:ofView:(withOffset:|withMultiplier:) 41 | - autoSetDimension(s)ToSize: 42 | - autoConstrainAttribute:toAttribute:ofView:(withOffset:|withMultiplier:) 43 | - autoPinTo(Top|Bottom)LayoutGuideOfViewController:withInset: 44 | 45 | **`NSArray`** 46 | 47 | - autoAlignViewsToEdge: 48 | - autoAlignViewsToAxis: 49 | - autoMatchViewsDimension: 50 | - autoSetViewsDimension:toSize: 51 | - autoDistributeViewsAlongAxis:withFixedSpacing:(insetSpacing:)alignment: 52 | - autoDistributeViewsAlongAxis:withFixedSize:(insetSpacing:)alignment: 53 | 54 | **`NSLayoutConstraint`** 55 | 56 | - autoInstall 57 | - autoRemove 58 | DESC 59 | 60 | s.homepage = "https://github.com/smileyborg/UIView-AutoLayout" 61 | s.license = { :type => 'MIT', :file => 'LICENSE' } 62 | s.author = { "Tyler Fox" => "tfox@smileyborg.com" } 63 | 64 | s.platform = :ios, '6.0' 65 | 66 | s.source = { :git => "https://github.com/smileyborg/UIView-AutoLayout.git", :tag => "v2.0.1" } 67 | s.source_files = 'Source' 68 | s.requires_arc = true 69 | 70 | end 71 | --------------------------------------------------------------------------------