├── .gitignore ├── LICENSE ├── README.md ├── TinyLayout.xcodeproj ├── project.pbxproj ├── project.xcworkspace │ └── contents.xcworkspacedata └── xcshareddata │ └── xcschemes │ └── TinyLayout.xcscheme ├── TinyLayout ├── Info.plist ├── TinyLayout.h ├── TinyLayout.swift └── UIViewTinyLayout.swift └── TinyLayoutTests ├── Info.plist └── TinyLayoutTests.swift /.gitignore: -------------------------------------------------------------------------------- 1 | # Xcode 2 | # 3 | build/ 4 | *.pbxuser 5 | !default.pbxuser 6 | *.mode1v3 7 | !default.mode1v3 8 | *.mode2v3 9 | !default.mode2v3 10 | *.perspectivev3 11 | !default.perspectivev3 12 | xcuserdata 13 | *.xccheckout 14 | *.moved-aside 15 | DerivedData 16 | *.hmap 17 | *.ipa 18 | *.xcuserstate 19 | 20 | # CocoaPods 21 | # 22 | # We recommend against adding the Pods directory to your .gitignore. However 23 | # you should judge for yourself, the pros and cons are mentioned at: 24 | # http://guides.cocoapods.org/using/using-cocoapods.html#should-i-ignore-the-pods-directory-in-source-control 25 | # 26 | # Pods/ 27 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 Ruben Roques 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # TinyLayout 2 | 3 | 4 | [![License](http://img.shields.io/badge/license-MIT-green.svg?style=flat)](https://github.com/rubenroques/TinyLayout/blob/master/LICENSE) 5 | 6 | A µframework with the purpose to be the most brief and readable way to declare or apply a AutoLayout NSLayoutConstraint in Swift. 7 | 8 | ## What can TinyLayout do for you? 9 | With TinyLayout you can stop doing this: 10 | 11 | ```swift 12 | let superview = self.view 13 | let view = UIView() 14 | view.setTranslatesAutoresizingMaskIntoConstraints(false) 15 | superview.addSubview(view) 16 | 17 | superview.addConstraint(NSLayoutConstraint(item: view, attribute: .Top, relatedBy: .Equal, toItem: superview, attribute: .Top, multiplier: 1, constant:0)) 18 | ``` 19 | 20 | And start doing this: 21 | ```swift 22 | let superview = self.view 23 | let view = UIView() 24 | superview.addSubview(view) 25 | 26 | (view,.Top)|=|(superview,.Top) 27 | ``` 28 | --- 29 | 30 | 31 | ## Integration 32 | 33 | #### Carthage 34 | If you’re using [Carthage](https://github.com/Carthage/Carthage), simply add 35 | TinyLayout to your `Cartfile`: 36 | 37 | ``` 38 | github "rubenroques/TinyLayout" 39 | ``` 40 | 41 | ## Usage 42 | **The simplest version, without multipliers or constraints.** 43 | ```swift 44 | //Add a NSLayoutConstraint to the view.superview 45 | (view,.Top)|=|(superview,.Top) 46 | ``` 47 | ```swift 48 | //Create a NSLayoutConstraint variable 49 | let layoutConstraint = (view,.Top)|=|&(superview,.Top) 50 | ``` 51 | The default values are ```constant = 0``` and ```multiplier = 1```. 52 | 53 | **With a constant value.** 54 | ```swift 55 | //Add a NSLayoutConstraint to the view.superview 56 | (view,.Top)|=|(superview,.Top, 50) 57 | (view,.Left)|=|(superview,.Left, -100) 58 | ``` 59 | ```swift 60 | //Create a NSLayoutConstraint variable 61 | let layoutConstraintTop = (view,.Top)|=|&(superview,.Top, 50) 62 | let layoutConstraintLeft = (view,.Left)|=|&(superview,.Left, -100) 63 | ``` 64 | 65 | 66 | **With a constant value and a multiplier.** 67 | ```swift 68 | //Add a NSLayoutConstraint to the view.superview 69 | (view,.Top)|=|(superview,.Top, 1.2, 50) 70 | (view,.Left)|=|(superview,.Left, 2, -100) 71 | ``` 72 | ```swift 73 | //Create a NSLayoutConstraint variable 74 | let layoutConstraintTop = (view,.Top)|=|&(superview,.Top, 1.2, 50) 75 | let layoutConstraintLeft = (view,.Left)|=|&(superview,.Left, 2, -100) 76 | ``` 77 | 78 | --- 79 | ## Roadmap 80 | 1. Finish [Roadmap](#roadmap) :) 81 | 2. ["You should be testing your library."] (http://guides.cocoapods.org/making/using-pod-lib-create.html#choosing-a-test-framework) 82 | 3. Create a ```typealias``` to avoid repeat the long tuples used in the functions parameter names 83 | 4. Improve demo app 84 | 5. Add support to fallback constrains using an array of UIView ```(view,.Top)|=|([superview, labelA, labelB],.Top)``` 85 | 6. Create func to set the NSLayoutConstraint priority in the declaration 86 | 7. Migrate from UIView to View to add support for AppKit 87 | 88 | 89 | --- 90 | ## Bugs? 91 | If you find any problem with TinyLayout, submit an issue. 92 | 93 | --- 94 | ## Contributing 95 | TinyLayout it's completely open to new ideas and suggestions. Create an issue and lets discuss what you have in mind. 96 | 97 | --- 98 | ## License 99 | This project is licensed under the terms of the MIT license. See the LICENSE file. 100 | -------------------------------------------------------------------------------- /TinyLayout.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 453FAF8A1BC02AFA00F8E7B0 /* TinyLayout.h in Headers */ = {isa = PBXBuildFile; fileRef = 453FAF891BC02AFA00F8E7B0 /* TinyLayout.h */; settings = {ATTRIBUTES = (Public, ); }; }; 11 | 453FAF911BC02AFA00F8E7B0 /* TinyLayout.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 453FAF861BC02AFA00F8E7B0 /* TinyLayout.framework */; settings = {ASSET_TAGS = (); }; }; 12 | 453FAF961BC02AFA00F8E7B0 /* TinyLayoutTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 453FAF951BC02AFA00F8E7B0 /* TinyLayoutTests.swift */; }; 13 | 453FAFA21BC02B0F00F8E7B0 /* TinyLayout.swift in Sources */ = {isa = PBXBuildFile; fileRef = 453FAFA01BC02B0F00F8E7B0 /* TinyLayout.swift */; settings = {ASSET_TAGS = (); }; }; 14 | 453FAFA31BC02B0F00F8E7B0 /* UIViewTinyLayout.swift in Sources */ = {isa = PBXBuildFile; fileRef = 453FAFA11BC02B0F00F8E7B0 /* UIViewTinyLayout.swift */; settings = {ASSET_TAGS = (); }; }; 15 | /* End PBXBuildFile section */ 16 | 17 | /* Begin PBXContainerItemProxy section */ 18 | 453FAF921BC02AFA00F8E7B0 /* PBXContainerItemProxy */ = { 19 | isa = PBXContainerItemProxy; 20 | containerPortal = 453FAF7D1BC02AFA00F8E7B0 /* Project object */; 21 | proxyType = 1; 22 | remoteGlobalIDString = 453FAF851BC02AFA00F8E7B0; 23 | remoteInfo = TinyLayout; 24 | }; 25 | /* End PBXContainerItemProxy section */ 26 | 27 | /* Begin PBXFileReference section */ 28 | 453FAF861BC02AFA00F8E7B0 /* TinyLayout.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = TinyLayout.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 29 | 453FAF891BC02AFA00F8E7B0 /* TinyLayout.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = TinyLayout.h; sourceTree = ""; }; 30 | 453FAF8B1BC02AFA00F8E7B0 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 31 | 453FAF901BC02AFA00F8E7B0 /* TinyLayoutTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = TinyLayoutTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 32 | 453FAF951BC02AFA00F8E7B0 /* TinyLayoutTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TinyLayoutTests.swift; sourceTree = ""; }; 33 | 453FAF971BC02AFA00F8E7B0 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 34 | 453FAFA01BC02B0F00F8E7B0 /* TinyLayout.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TinyLayout.swift; sourceTree = ""; }; 35 | 453FAFA11BC02B0F00F8E7B0 /* UIViewTinyLayout.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = UIViewTinyLayout.swift; sourceTree = ""; }; 36 | /* End PBXFileReference section */ 37 | 38 | /* Begin PBXFrameworksBuildPhase section */ 39 | 453FAF821BC02AFA00F8E7B0 /* Frameworks */ = { 40 | isa = PBXFrameworksBuildPhase; 41 | buildActionMask = 2147483647; 42 | files = ( 43 | ); 44 | runOnlyForDeploymentPostprocessing = 0; 45 | }; 46 | 453FAF8D1BC02AFA00F8E7B0 /* Frameworks */ = { 47 | isa = PBXFrameworksBuildPhase; 48 | buildActionMask = 2147483647; 49 | files = ( 50 | 453FAF911BC02AFA00F8E7B0 /* TinyLayout.framework in Frameworks */, 51 | ); 52 | runOnlyForDeploymentPostprocessing = 0; 53 | }; 54 | /* End PBXFrameworksBuildPhase section */ 55 | 56 | /* Begin PBXGroup section */ 57 | 453FAF7C1BC02AFA00F8E7B0 = { 58 | isa = PBXGroup; 59 | children = ( 60 | 453FAF881BC02AFA00F8E7B0 /* TinyLayout */, 61 | 453FAF941BC02AFA00F8E7B0 /* TinyLayoutTests */, 62 | 453FAF871BC02AFA00F8E7B0 /* Products */, 63 | ); 64 | sourceTree = ""; 65 | }; 66 | 453FAF871BC02AFA00F8E7B0 /* Products */ = { 67 | isa = PBXGroup; 68 | children = ( 69 | 453FAF861BC02AFA00F8E7B0 /* TinyLayout.framework */, 70 | 453FAF901BC02AFA00F8E7B0 /* TinyLayoutTests.xctest */, 71 | ); 72 | name = Products; 73 | sourceTree = ""; 74 | }; 75 | 453FAF881BC02AFA00F8E7B0 /* TinyLayout */ = { 76 | isa = PBXGroup; 77 | children = ( 78 | 453FAFA01BC02B0F00F8E7B0 /* TinyLayout.swift */, 79 | 453FAFA11BC02B0F00F8E7B0 /* UIViewTinyLayout.swift */, 80 | 453FAF891BC02AFA00F8E7B0 /* TinyLayout.h */, 81 | 453FAF8B1BC02AFA00F8E7B0 /* Info.plist */, 82 | ); 83 | path = TinyLayout; 84 | sourceTree = ""; 85 | }; 86 | 453FAF941BC02AFA00F8E7B0 /* TinyLayoutTests */ = { 87 | isa = PBXGroup; 88 | children = ( 89 | 453FAF951BC02AFA00F8E7B0 /* TinyLayoutTests.swift */, 90 | 453FAF971BC02AFA00F8E7B0 /* Info.plist */, 91 | ); 92 | path = TinyLayoutTests; 93 | sourceTree = ""; 94 | }; 95 | /* End PBXGroup section */ 96 | 97 | /* Begin PBXHeadersBuildPhase section */ 98 | 453FAF831BC02AFA00F8E7B0 /* Headers */ = { 99 | isa = PBXHeadersBuildPhase; 100 | buildActionMask = 2147483647; 101 | files = ( 102 | 453FAF8A1BC02AFA00F8E7B0 /* TinyLayout.h in Headers */, 103 | ); 104 | runOnlyForDeploymentPostprocessing = 0; 105 | }; 106 | /* End PBXHeadersBuildPhase section */ 107 | 108 | /* Begin PBXNativeTarget section */ 109 | 453FAF851BC02AFA00F8E7B0 /* TinyLayout */ = { 110 | isa = PBXNativeTarget; 111 | buildConfigurationList = 453FAF9A1BC02AFA00F8E7B0 /* Build configuration list for PBXNativeTarget "TinyLayout" */; 112 | buildPhases = ( 113 | 453FAF811BC02AFA00F8E7B0 /* Sources */, 114 | 453FAF821BC02AFA00F8E7B0 /* Frameworks */, 115 | 453FAF831BC02AFA00F8E7B0 /* Headers */, 116 | 453FAF841BC02AFA00F8E7B0 /* Resources */, 117 | ); 118 | buildRules = ( 119 | ); 120 | dependencies = ( 121 | ); 122 | name = TinyLayout; 123 | productName = TinyLayout; 124 | productReference = 453FAF861BC02AFA00F8E7B0 /* TinyLayout.framework */; 125 | productType = "com.apple.product-type.framework"; 126 | }; 127 | 453FAF8F1BC02AFA00F8E7B0 /* TinyLayoutTests */ = { 128 | isa = PBXNativeTarget; 129 | buildConfigurationList = 453FAF9D1BC02AFA00F8E7B0 /* Build configuration list for PBXNativeTarget "TinyLayoutTests" */; 130 | buildPhases = ( 131 | 453FAF8C1BC02AFA00F8E7B0 /* Sources */, 132 | 453FAF8D1BC02AFA00F8E7B0 /* Frameworks */, 133 | 453FAF8E1BC02AFA00F8E7B0 /* Resources */, 134 | ); 135 | buildRules = ( 136 | ); 137 | dependencies = ( 138 | 453FAF931BC02AFA00F8E7B0 /* PBXTargetDependency */, 139 | ); 140 | name = TinyLayoutTests; 141 | productName = TinyLayoutTests; 142 | productReference = 453FAF901BC02AFA00F8E7B0 /* TinyLayoutTests.xctest */; 143 | productType = "com.apple.product-type.bundle.unit-test"; 144 | }; 145 | /* End PBXNativeTarget section */ 146 | 147 | /* Begin PBXProject section */ 148 | 453FAF7D1BC02AFA00F8E7B0 /* Project object */ = { 149 | isa = PBXProject; 150 | attributes = { 151 | LastSwiftUpdateCheck = 0700; 152 | LastUpgradeCheck = 0700; 153 | ORGANIZATIONNAME = "Ruben Roques"; 154 | TargetAttributes = { 155 | 453FAF851BC02AFA00F8E7B0 = { 156 | CreatedOnToolsVersion = 7.0.1; 157 | }; 158 | 453FAF8F1BC02AFA00F8E7B0 = { 159 | CreatedOnToolsVersion = 7.0.1; 160 | }; 161 | }; 162 | }; 163 | buildConfigurationList = 453FAF801BC02AFA00F8E7B0 /* Build configuration list for PBXProject "TinyLayout" */; 164 | compatibilityVersion = "Xcode 3.2"; 165 | developmentRegion = English; 166 | hasScannedForEncodings = 0; 167 | knownRegions = ( 168 | en, 169 | ); 170 | mainGroup = 453FAF7C1BC02AFA00F8E7B0; 171 | productRefGroup = 453FAF871BC02AFA00F8E7B0 /* Products */; 172 | projectDirPath = ""; 173 | projectRoot = ""; 174 | targets = ( 175 | 453FAF851BC02AFA00F8E7B0 /* TinyLayout */, 176 | 453FAF8F1BC02AFA00F8E7B0 /* TinyLayoutTests */, 177 | ); 178 | }; 179 | /* End PBXProject section */ 180 | 181 | /* Begin PBXResourcesBuildPhase section */ 182 | 453FAF841BC02AFA00F8E7B0 /* Resources */ = { 183 | isa = PBXResourcesBuildPhase; 184 | buildActionMask = 2147483647; 185 | files = ( 186 | ); 187 | runOnlyForDeploymentPostprocessing = 0; 188 | }; 189 | 453FAF8E1BC02AFA00F8E7B0 /* Resources */ = { 190 | isa = PBXResourcesBuildPhase; 191 | buildActionMask = 2147483647; 192 | files = ( 193 | ); 194 | runOnlyForDeploymentPostprocessing = 0; 195 | }; 196 | /* End PBXResourcesBuildPhase section */ 197 | 198 | /* Begin PBXSourcesBuildPhase section */ 199 | 453FAF811BC02AFA00F8E7B0 /* Sources */ = { 200 | isa = PBXSourcesBuildPhase; 201 | buildActionMask = 2147483647; 202 | files = ( 203 | 453FAFA31BC02B0F00F8E7B0 /* UIViewTinyLayout.swift in Sources */, 204 | 453FAFA21BC02B0F00F8E7B0 /* TinyLayout.swift in Sources */, 205 | ); 206 | runOnlyForDeploymentPostprocessing = 0; 207 | }; 208 | 453FAF8C1BC02AFA00F8E7B0 /* Sources */ = { 209 | isa = PBXSourcesBuildPhase; 210 | buildActionMask = 2147483647; 211 | files = ( 212 | 453FAF961BC02AFA00F8E7B0 /* TinyLayoutTests.swift in Sources */, 213 | ); 214 | runOnlyForDeploymentPostprocessing = 0; 215 | }; 216 | /* End PBXSourcesBuildPhase section */ 217 | 218 | /* Begin PBXTargetDependency section */ 219 | 453FAF931BC02AFA00F8E7B0 /* PBXTargetDependency */ = { 220 | isa = PBXTargetDependency; 221 | target = 453FAF851BC02AFA00F8E7B0 /* TinyLayout */; 222 | targetProxy = 453FAF921BC02AFA00F8E7B0 /* PBXContainerItemProxy */; 223 | }; 224 | /* End PBXTargetDependency section */ 225 | 226 | /* Begin XCBuildConfiguration section */ 227 | 453FAF981BC02AFA00F8E7B0 /* Debug */ = { 228 | isa = XCBuildConfiguration; 229 | buildSettings = { 230 | ALWAYS_SEARCH_USER_PATHS = NO; 231 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 232 | CLANG_CXX_LIBRARY = "libc++"; 233 | CLANG_ENABLE_MODULES = YES; 234 | CLANG_ENABLE_OBJC_ARC = YES; 235 | CLANG_WARN_BOOL_CONVERSION = YES; 236 | CLANG_WARN_CONSTANT_CONVERSION = YES; 237 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 238 | CLANG_WARN_EMPTY_BODY = YES; 239 | CLANG_WARN_ENUM_CONVERSION = YES; 240 | CLANG_WARN_INT_CONVERSION = YES; 241 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 242 | CLANG_WARN_UNREACHABLE_CODE = YES; 243 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 244 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 245 | COPY_PHASE_STRIP = NO; 246 | CURRENT_PROJECT_VERSION = 1; 247 | DEBUG_INFORMATION_FORMAT = dwarf; 248 | ENABLE_STRICT_OBJC_MSGSEND = YES; 249 | ENABLE_TESTABILITY = YES; 250 | GCC_C_LANGUAGE_STANDARD = gnu99; 251 | GCC_DYNAMIC_NO_PIC = NO; 252 | GCC_NO_COMMON_BLOCKS = YES; 253 | GCC_OPTIMIZATION_LEVEL = 0; 254 | GCC_PREPROCESSOR_DEFINITIONS = ( 255 | "DEBUG=1", 256 | "$(inherited)", 257 | ); 258 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 259 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 260 | GCC_WARN_UNDECLARED_SELECTOR = YES; 261 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 262 | GCC_WARN_UNUSED_FUNCTION = YES; 263 | GCC_WARN_UNUSED_VARIABLE = YES; 264 | IPHONEOS_DEPLOYMENT_TARGET = 8.0; 265 | MTL_ENABLE_DEBUG_INFO = YES; 266 | ONLY_ACTIVE_ARCH = YES; 267 | SDKROOT = iphoneos; 268 | SWIFT_OPTIMIZATION_LEVEL = "-Onone"; 269 | TARGETED_DEVICE_FAMILY = "1,2"; 270 | VERSIONING_SYSTEM = "apple-generic"; 271 | VERSION_INFO_PREFIX = ""; 272 | }; 273 | name = Debug; 274 | }; 275 | 453FAF991BC02AFA00F8E7B0 /* Release */ = { 276 | isa = XCBuildConfiguration; 277 | buildSettings = { 278 | ALWAYS_SEARCH_USER_PATHS = NO; 279 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 280 | CLANG_CXX_LIBRARY = "libc++"; 281 | CLANG_ENABLE_MODULES = YES; 282 | CLANG_ENABLE_OBJC_ARC = YES; 283 | CLANG_WARN_BOOL_CONVERSION = YES; 284 | CLANG_WARN_CONSTANT_CONVERSION = YES; 285 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 286 | CLANG_WARN_EMPTY_BODY = YES; 287 | CLANG_WARN_ENUM_CONVERSION = YES; 288 | CLANG_WARN_INT_CONVERSION = YES; 289 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 290 | CLANG_WARN_UNREACHABLE_CODE = YES; 291 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 292 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 293 | COPY_PHASE_STRIP = NO; 294 | CURRENT_PROJECT_VERSION = 1; 295 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 296 | ENABLE_NS_ASSERTIONS = NO; 297 | ENABLE_STRICT_OBJC_MSGSEND = YES; 298 | GCC_C_LANGUAGE_STANDARD = gnu99; 299 | GCC_NO_COMMON_BLOCKS = YES; 300 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 301 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 302 | GCC_WARN_UNDECLARED_SELECTOR = YES; 303 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 304 | GCC_WARN_UNUSED_FUNCTION = YES; 305 | GCC_WARN_UNUSED_VARIABLE = YES; 306 | IPHONEOS_DEPLOYMENT_TARGET = 8.0; 307 | MTL_ENABLE_DEBUG_INFO = NO; 308 | SDKROOT = iphoneos; 309 | TARGETED_DEVICE_FAMILY = "1,2"; 310 | VALIDATE_PRODUCT = YES; 311 | VERSIONING_SYSTEM = "apple-generic"; 312 | VERSION_INFO_PREFIX = ""; 313 | }; 314 | name = Release; 315 | }; 316 | 453FAF9B1BC02AFA00F8E7B0 /* Debug */ = { 317 | isa = XCBuildConfiguration; 318 | buildSettings = { 319 | CLANG_ENABLE_MODULES = YES; 320 | DEFINES_MODULE = YES; 321 | DYLIB_COMPATIBILITY_VERSION = 1; 322 | DYLIB_CURRENT_VERSION = 1; 323 | DYLIB_INSTALL_NAME_BASE = "@rpath"; 324 | INFOPLIST_FILE = TinyLayout/Info.plist; 325 | INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; 326 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 327 | PRODUCT_BUNDLE_IDENTIFIER = com.rrocks.TinyLayout; 328 | PRODUCT_NAME = "$(TARGET_NAME)"; 329 | SKIP_INSTALL = YES; 330 | SWIFT_OPTIMIZATION_LEVEL = "-Onone"; 331 | }; 332 | name = Debug; 333 | }; 334 | 453FAF9C1BC02AFA00F8E7B0 /* Release */ = { 335 | isa = XCBuildConfiguration; 336 | buildSettings = { 337 | CLANG_ENABLE_MODULES = YES; 338 | DEFINES_MODULE = YES; 339 | DYLIB_COMPATIBILITY_VERSION = 1; 340 | DYLIB_CURRENT_VERSION = 1; 341 | DYLIB_INSTALL_NAME_BASE = "@rpath"; 342 | INFOPLIST_FILE = TinyLayout/Info.plist; 343 | INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; 344 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 345 | PRODUCT_BUNDLE_IDENTIFIER = com.rrocks.TinyLayout; 346 | PRODUCT_NAME = "$(TARGET_NAME)"; 347 | SKIP_INSTALL = YES; 348 | }; 349 | name = Release; 350 | }; 351 | 453FAF9E1BC02AFA00F8E7B0 /* Debug */ = { 352 | isa = XCBuildConfiguration; 353 | buildSettings = { 354 | INFOPLIST_FILE = TinyLayoutTests/Info.plist; 355 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 356 | PRODUCT_BUNDLE_IDENTIFIER = com.rrocks.TinyLayoutTests; 357 | PRODUCT_NAME = "$(TARGET_NAME)"; 358 | }; 359 | name = Debug; 360 | }; 361 | 453FAF9F1BC02AFA00F8E7B0 /* Release */ = { 362 | isa = XCBuildConfiguration; 363 | buildSettings = { 364 | INFOPLIST_FILE = TinyLayoutTests/Info.plist; 365 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 366 | PRODUCT_BUNDLE_IDENTIFIER = com.rrocks.TinyLayoutTests; 367 | PRODUCT_NAME = "$(TARGET_NAME)"; 368 | }; 369 | name = Release; 370 | }; 371 | /* End XCBuildConfiguration section */ 372 | 373 | /* Begin XCConfigurationList section */ 374 | 453FAF801BC02AFA00F8E7B0 /* Build configuration list for PBXProject "TinyLayout" */ = { 375 | isa = XCConfigurationList; 376 | buildConfigurations = ( 377 | 453FAF981BC02AFA00F8E7B0 /* Debug */, 378 | 453FAF991BC02AFA00F8E7B0 /* Release */, 379 | ); 380 | defaultConfigurationIsVisible = 0; 381 | defaultConfigurationName = Release; 382 | }; 383 | 453FAF9A1BC02AFA00F8E7B0 /* Build configuration list for PBXNativeTarget "TinyLayout" */ = { 384 | isa = XCConfigurationList; 385 | buildConfigurations = ( 386 | 453FAF9B1BC02AFA00F8E7B0 /* Debug */, 387 | 453FAF9C1BC02AFA00F8E7B0 /* Release */, 388 | ); 389 | defaultConfigurationIsVisible = 0; 390 | }; 391 | 453FAF9D1BC02AFA00F8E7B0 /* Build configuration list for PBXNativeTarget "TinyLayoutTests" */ = { 392 | isa = XCConfigurationList; 393 | buildConfigurations = ( 394 | 453FAF9E1BC02AFA00F8E7B0 /* Debug */, 395 | 453FAF9F1BC02AFA00F8E7B0 /* Release */, 396 | ); 397 | defaultConfigurationIsVisible = 0; 398 | }; 399 | /* End XCConfigurationList section */ 400 | }; 401 | rootObject = 453FAF7D1BC02AFA00F8E7B0 /* Project object */; 402 | } 403 | -------------------------------------------------------------------------------- /TinyLayout.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /TinyLayout.xcodeproj/xcshareddata/xcschemes/TinyLayout.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 33 | 39 | 40 | 41 | 42 | 43 | 49 | 50 | 51 | 52 | 53 | 54 | 64 | 65 | 71 | 72 | 73 | 74 | 75 | 76 | 82 | 83 | 89 | 90 | 91 | 92 | 94 | 95 | 98 | 99 | 100 | -------------------------------------------------------------------------------- /TinyLayout/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | FMWK 17 | CFBundleShortVersionString 18 | 0.1 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | $(CURRENT_PROJECT_VERSION) 23 | NSPrincipalClass 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /TinyLayout/TinyLayout.h: -------------------------------------------------------------------------------- 1 | // 2 | // TinyLayout.h 3 | // TinyLayout 4 | // 5 | // Created by Ruben Roques on 03/10/15. 6 | // Copyright © 2015 Ruben Roques. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | //! Project version number for TinyLayout. 12 | FOUNDATION_EXPORT double TinyLayoutVersionNumber; 13 | 14 | //! Project version string for TinyLayout. 15 | FOUNDATION_EXPORT const unsigned char TinyLayoutVersionString[]; 16 | 17 | // In this header, you should import all the public headers of your framework using statements like #import 18 | 19 | 20 | -------------------------------------------------------------------------------- /TinyLayout/TinyLayout.swift: -------------------------------------------------------------------------------- 1 | // 2 | // TinyLayout.swift 3 | // Contra 4 | // 5 | // Created by Ruben Roques on 01/02/15. 6 | // Copyright (c) 2015 RRocks. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | import UIKit 11 | 12 | 13 | infix operator |=| { associativity right precedence 90 } 14 | public func |=| (left:(view:UIView, attri:NSLayoutAttribute), constant: CGFloat) { 15 | (left.view, left.attri) |=| (nil, NSLayoutAttribute.NotAnAttribute, 1,constant) 16 | } 17 | 18 | public func |=| (left:(view:UIView, attri:NSLayoutAttribute), right:(multiplier: CGFloat, constant: CGFloat)) { 19 | (left.view, left.attri) |=| (nil, NSLayoutAttribute.NotAnAttribute, right.multiplier, right.constant) 20 | } 21 | 22 | public func |=| (left:(view:UIView, attri:NSLayoutAttribute), right:(view:UIView?, attri:NSLayoutAttribute)) { 23 | (left.view, left.attri) |=| (right.view, right.attri, 1,0) 24 | } 25 | 26 | public func |=| (left:(view:UIView, attri:NSLayoutAttribute), right:(view:UIView?, attri:NSLayoutAttribute, constant: CGFloat)) { 27 | (left.view, left.attri) |=| (right.view, right.attri, 1,right.constant) 28 | } 29 | 30 | public func |=| (left:(view:UIView, attri:NSLayoutAttribute), right:(view:UIView?, attri:NSLayoutAttribute, multiplier: CGFloat, constant:CGFloat)) { 31 | 32 | if left.view.superview == nil { 33 | fatalError("Left side view does not have a superview") 34 | } 35 | 36 | left.view.translatesAutoresizingMaskIntoConstraints = false 37 | 38 | left.view.superview!.addConstraint(NSLayoutConstraint(item: left.view, attribute: left.attri, relatedBy: .Equal, toItem: right.view, attribute: right.attri, multiplier: right.multiplier, constant: right.constant)) 39 | } 40 | 41 | 42 | infix operator |=|& { associativity right precedence 90 } 43 | public func |=|& (left:(view:UIView, attri:NSLayoutAttribute), constant: CGFloat) -> NSLayoutConstraint? { 44 | return (left.view, left.attri) |=|& (nil, NSLayoutAttribute.NotAnAttribute, 1,constant) 45 | } 46 | 47 | public func |=|& (left:(view:UIView, attri:NSLayoutAttribute), right:(multiplier: CGFloat, constant: CGFloat)) -> NSLayoutConstraint? { 48 | return (left.view, left.attri) |=|& (nil, NSLayoutAttribute.NotAnAttribute, right.multiplier, right.constant) 49 | } 50 | 51 | public func |=|& (left:(view:UIView, attri:NSLayoutAttribute), right:(view:UIView?, attri:NSLayoutAttribute)) -> NSLayoutConstraint? { 52 | return (left.view, left.attri) |=|& (right.view, right.attri, 1,0) 53 | } 54 | 55 | public func |=|& (left:(view:UIView, attri:NSLayoutAttribute), right:(view:UIView?, attri:NSLayoutAttribute, constant: CGFloat)) -> NSLayoutConstraint? { 56 | return (left.view, left.attri) |=|& (right.view, right.attri, 1,right.constant) 57 | } 58 | public func |=|& (left:(view:UIView, attri:NSLayoutAttribute), right:(view:UIView?, attri:NSLayoutAttribute, multiplier: CGFloat, constant:CGFloat)) -> NSLayoutConstraint? { 59 | 60 | if (left.view.superview == nil) { 61 | fatalError("Left side view does not have a superview") 62 | } 63 | 64 | left.view.translatesAutoresizingMaskIntoConstraints = false 65 | 66 | return NSLayoutConstraint(item: left.view, attribute: left.attri, relatedBy: .Equal, toItem: right.view, attribute: right.attri, multiplier: right.multiplier, constant: right.constant) 67 | } 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | infix operator >=| { associativity right precedence 90 } 76 | public func >=| (left:(view:UIView, attri:NSLayoutAttribute), constant: CGFloat) { 77 | (left.view, left.attri) >=| (nil, NSLayoutAttribute.NotAnAttribute, 1,constant) 78 | } 79 | 80 | public func >=| (left:(view:UIView, attri:NSLayoutAttribute), right:(multiplier: CGFloat, constant: CGFloat)) { 81 | (left.view, left.attri) >=| (nil, NSLayoutAttribute.NotAnAttribute, right.multiplier, right.constant) 82 | } 83 | 84 | public func >=| (left:(view:UIView, attri:NSLayoutAttribute), right:(view:UIView?, attri:NSLayoutAttribute)) { 85 | (left.view, left.attri) >=| (right.view, right.attri, 1,0) 86 | } 87 | 88 | public func >=| (left:(view:UIView, attri:NSLayoutAttribute), right:(view:UIView?, attri:NSLayoutAttribute, constant: CGFloat)) { 89 | (left.view, left.attri) >=| (right.view, right.attri, 1,right.constant) 90 | } 91 | 92 | public func >=| (left:(view:UIView, attri:NSLayoutAttribute), right:(view:UIView?, attri:NSLayoutAttribute, multiplier: CGFloat, constant:CGFloat)) { 93 | 94 | if left.view.superview == nil { 95 | fatalError("Left side view does not have a superview") 96 | } 97 | 98 | left.view.translatesAutoresizingMaskIntoConstraints = false 99 | 100 | left.view.superview!.addConstraint(NSLayoutConstraint(item: left.view, attribute: left.attri, relatedBy: .GreaterThanOrEqual, toItem: right.view, attribute: right.attri, multiplier: right.multiplier, constant: right.constant)) 101 | } 102 | 103 | infix operator >=|& { associativity right precedence 90 } 104 | public func >=|& (left:(view:UIView, attri:NSLayoutAttribute), constant: CGFloat) -> NSLayoutConstraint? { 105 | return (left.view, left.attri) >=|& (nil, NSLayoutAttribute.NotAnAttribute, 1,constant) 106 | } 107 | 108 | public func >=|& (left:(view:UIView, attri:NSLayoutAttribute), right:(multiplier: CGFloat, constant: CGFloat)) -> NSLayoutConstraint? { 109 | return (left.view, left.attri) >=|& (nil, NSLayoutAttribute.NotAnAttribute, right.multiplier, right.constant) 110 | } 111 | 112 | public func >=|& (left:(view:UIView, attri:NSLayoutAttribute), right:(view:UIView?, attri:NSLayoutAttribute)) -> NSLayoutConstraint? { 113 | return (left.view, left.attri) >=|& (right.view, right.attri, 1,0) 114 | } 115 | 116 | public func >=|& (left:(view:UIView, attri:NSLayoutAttribute), right:(view:UIView?, attri:NSLayoutAttribute, constant: CGFloat)) -> NSLayoutConstraint? { 117 | return (left.view, left.attri) >=|& (right.view, right.attri, 1,right.constant) 118 | } 119 | public func >=|& (left:(view:UIView, attri:NSLayoutAttribute), right:(view:UIView?, attri:NSLayoutAttribute, multiplier: CGFloat, constant:CGFloat)) -> NSLayoutConstraint? { 120 | 121 | left.view.translatesAutoresizingMaskIntoConstraints = false 122 | 123 | return NSLayoutConstraint(item: left.view, attribute: left.attri, relatedBy: .GreaterThanOrEqual, toItem: right.view, attribute: right.attri, multiplier: right.multiplier, constant: right.constant) 124 | } 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | infix operator <=| { associativity right precedence 90 } 133 | public func <=| (left:(view:UIView, attri:NSLayoutAttribute), constant: CGFloat) { 134 | (left.view, left.attri) <=| (nil, NSLayoutAttribute.NotAnAttribute, 1,constant) 135 | } 136 | 137 | public func <=| (left:(view:UIView, attri:NSLayoutAttribute), right:(multiplier: CGFloat, constant: CGFloat)) { 138 | (left.view, left.attri) >=| (nil, NSLayoutAttribute.NotAnAttribute, right.multiplier, right.constant) 139 | } 140 | 141 | public func <=| (left:(view:UIView, attri:NSLayoutAttribute), right:(view:UIView?, attri:NSLayoutAttribute)) { 142 | (left.view, left.attri) <=| (right.view, right.attri, 1,0) 143 | } 144 | 145 | public func <=| (left:(view:UIView, attri:NSLayoutAttribute), right:(view:UIView?, attri:NSLayoutAttribute, constant: CGFloat)) { 146 | (left.view, left.attri) <=| (right.view, right.attri, 1,right.constant) 147 | } 148 | 149 | public func <=| (left:(view:UIView, attri:NSLayoutAttribute), right:(view:UIView?, attri:NSLayoutAttribute, multiplier: CGFloat, constant:CGFloat)) { 150 | 151 | if left.view.superview == nil { 152 | fatalError("Left side view does not have a superview") 153 | } 154 | 155 | left.view.translatesAutoresizingMaskIntoConstraints = false 156 | 157 | left.view.superview!.addConstraint(NSLayoutConstraint(item: left.view, attribute: left.attri, relatedBy: .LessThanOrEqual, toItem: right.view, attribute: right.attri, multiplier: right.multiplier, constant: right.constant)) 158 | } 159 | 160 | infix operator <=|& { associativity right precedence 90 } 161 | public func <=|& (left:(view:UIView, attri:NSLayoutAttribute), constant: CGFloat) -> NSLayoutConstraint? { 162 | return (left.view, left.attri) <=|& (nil, NSLayoutAttribute.NotAnAttribute, 1,constant) 163 | } 164 | 165 | public func <=|& (left:(view:UIView, attri:NSLayoutAttribute), right:(multiplier: CGFloat, constant: CGFloat)) -> NSLayoutConstraint? { 166 | return (left.view, left.attri) <=|& (nil, NSLayoutAttribute.NotAnAttribute, right.multiplier, right.constant) 167 | } 168 | 169 | public func <=|& (left:(view:UIView, attri:NSLayoutAttribute), right:(view:UIView?, attri:NSLayoutAttribute)) -> NSLayoutConstraint? { 170 | return (left.view, left.attri) <=|& (right.view, right.attri, 1,0) 171 | } 172 | 173 | public func <=|& (left:(view:UIView, attri:NSLayoutAttribute), right:(view:UIView?, attri:NSLayoutAttribute, constant: CGFloat)) -> NSLayoutConstraint? { 174 | return (left.view, left.attri) <=|& (right.view, right.attri, 1,right.constant) 175 | } 176 | public func <=|& (left:(view:UIView, attri:NSLayoutAttribute), right:(view:UIView?, attri:NSLayoutAttribute, multiplier: CGFloat, constant:CGFloat)) -> NSLayoutConstraint? { 177 | 178 | left.view.translatesAutoresizingMaskIntoConstraints = false 179 | 180 | return NSLayoutConstraint(item: left.view, attribute: left.attri, relatedBy: .LessThanOrEqual, toItem: right.view, attribute: right.attri, multiplier: right.multiplier, constant: right.constant) 181 | } 182 | 183 | 184 | 185 | 186 | -------------------------------------------------------------------------------- /TinyLayout/UIViewTinyLayout.swift: -------------------------------------------------------------------------------- 1 | // 2 | // UIViewTinyLayout.swift 3 | // TinyLayoutDemo 4 | // 5 | // Created by Ruben Roques on 01/02/15. 6 | // Copyright (c) 2015 RRocks. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | import UIKit 11 | 12 | extension UIView { 13 | 14 | func tl_constraints(withAttribute attribute:NSLayoutAttribute) -> [NSLayoutConstraint] { 15 | var constraintsArray : [NSLayoutConstraint] = [] 16 | for constraint in self.constraints { 17 | if constraint.firstAttribute == attribute { 18 | constraintsArray.append(constraint) 19 | } 20 | } 21 | return constraintsArray 22 | } 23 | 24 | func tl_constraints(withAttributes attributes:[NSLayoutAttribute]) -> [NSLayoutConstraint] { 25 | var constraintsArray : [NSLayoutConstraint] = [] 26 | for attribute in attributes { 27 | constraintsArray += self.tl_constraints(withAttribute: attribute) 28 | } 29 | return constraintsArray 30 | } 31 | 32 | func tl_setWidth(width: CGFloat) { 33 | self.addConstraint(NSLayoutConstraint(item: self, attribute: .Width, relatedBy: .Equal, toItem: nil, attribute: .NotAnAttribute, multiplier: 1, constant: width)) 34 | } 35 | 36 | func tl_setHeight(height: CGFloat) { 37 | self.addConstraint(NSLayoutConstraint(item: self, attribute: .Height, relatedBy: .Equal, toItem: nil, attribute: .NotAnAttribute, multiplier: 1, constant: height)) 38 | } 39 | 40 | func tl_setSize(size: CGSize) { 41 | self.addConstraint(NSLayoutConstraint(item: self, attribute: .Width, relatedBy: .Equal, toItem: nil, attribute: .NotAnAttribute, multiplier: 1, constant: size.width)) 42 | self.addConstraint(NSLayoutConstraint(item: self, attribute: .Height, relatedBy: .Equal, toItem: nil, attribute: .NotAnAttribute, multiplier: 1, constant: size.height)) 43 | } 44 | } -------------------------------------------------------------------------------- /TinyLayoutTests/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | BNDL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1 23 | 24 | 25 | -------------------------------------------------------------------------------- /TinyLayoutTests/TinyLayoutTests.swift: -------------------------------------------------------------------------------- 1 | // 2 | // TinyLayoutTests.swift 3 | // TinyLayoutTests 4 | // 5 | // Created by Ruben Roques on 03/10/15. 6 | // Copyright © 2015 Ruben Roques. All rights reserved. 7 | // 8 | 9 | import XCTest 10 | @testable import TinyLayout 11 | 12 | class TinyLayoutTests: XCTestCase { 13 | 14 | override func setUp() { 15 | super.setUp() 16 | // Put setup code here. This method is called before the invocation of each test method in the class. 17 | } 18 | 19 | override func tearDown() { 20 | // Put teardown code here. This method is called after the invocation of each test method in the class. 21 | super.tearDown() 22 | } 23 | 24 | func testExample() { 25 | // This is an example of a functional test case. 26 | // Use XCTAssert and related functions to verify your tests produce the correct results. 27 | } 28 | 29 | func testPerformanceExample() { 30 | // This is an example of a performance test case. 31 | self.measureBlock { 32 | // Put the code you want to measure the time of here. 33 | } 34 | } 35 | 36 | } 37 | --------------------------------------------------------------------------------