├── .gitignore ├── .ruby-version ├── .swift-version ├── .travis.yml ├── Gemfile ├── Gemfile.lock ├── LICENSE ├── ManualLayout.podspec ├── ManualLayout.xcodeproj ├── project.pbxproj ├── project.xcworkspace │ ├── contents.xcworkspacedata │ └── xcshareddata │ │ └── ManualLayout.xccheckout └── xcshareddata │ └── xcschemes │ ├── ManualLayout-tvOS.xcscheme │ └── ManualLayout.xcscheme ├── ManualLayout ├── CALayer+ManualLayout.swift ├── CGRect+ManualLayout.swift ├── HelperFunctions.swift ├── Info-tvOS.plist ├── Info.plist ├── ManualLayout.h ├── SmartAssign.swift ├── UIScrollView+ManualLayout.swift ├── UIView+ManualLayout.swift └── UIViewController+ManualLayout.swift ├── ManualLayoutTests ├── HelperFunctionTests.swift ├── Info.plist ├── SmartAssignTests.swift ├── UIScrollViewManualLayoutTests.swift └── UIViewManualLayoutTests.swift ├── README.md ├── SimpleExample ├── AppDelegate.swift ├── Base.lproj │ └── LaunchScreen.xib ├── ExampleViewController.swift ├── Images.xcassets │ └── AppIcon.appiconset │ │ └── Contents.json └── Info.plist └── SimpleExampleTests ├── Info.plist └── SimpleExampleTests.swift /.gitignore: -------------------------------------------------------------------------------- 1 | # General 2 | # 3 | *.swp 4 | 5 | # OSX 6 | # 7 | .DS_Store 8 | Iconr 9 | Icon? 10 | 11 | ## Windows 12 | # 13 | desktop.ini 14 | 15 | # Xcode 16 | # 17 | build/ 18 | *.pbxuser 19 | !default.pbxuser 20 | *.mode1v3 21 | !default.mode1v3 22 | *.mode2v3 23 | !default.mode2v3 24 | *.perspectivev3 25 | !default.perspectivev3 26 | xcuserdata 27 | *.xccheckout 28 | *.moved-aside 29 | DerivedData 30 | *.hmap 31 | *.ipa 32 | *.xcuserstate 33 | project.xcworkspace 34 | 35 | # iOS package manager files 36 | # 37 | Pods/ 38 | Carthage/ 39 | 40 | # bundler 41 | .bundle 42 | vendor/bundle/ 43 | vendor/ruby/ 44 | -------------------------------------------------------------------------------- /.ruby-version: -------------------------------------------------------------------------------- 1 | 2.2.2 2 | -------------------------------------------------------------------------------- /.swift-version: -------------------------------------------------------------------------------- 1 | 4.0 2 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: objective-c 2 | osx_image: xcode8 3 | -------------------------------------------------------------------------------- /Gemfile: -------------------------------------------------------------------------------- 1 | source 'https://rubygems.org' 2 | 3 | gem 'cocoapods', :github => 'CocoaPods', :ref => 'a5a409a85f99d8500af2d9da8d038106657525c6' 4 | -------------------------------------------------------------------------------- /Gemfile.lock: -------------------------------------------------------------------------------- 1 | GIT 2 | remote: git://github.com/CocoaPods/CocoaPods.git 3 | revision: a5a409a85f99d8500af2d9da8d038106657525c6 4 | ref: a5a409a85f99d8500af2d9da8d038106657525c6 5 | specs: 6 | cocoapods (1.1.0.rc.2) 7 | activesupport (>= 4.0.2, < 5) 8 | claide (>= 1.0.0, < 2.0) 9 | cocoapods-core (= 1.1.0.rc.2) 10 | cocoapods-deintegrate (>= 1.0.1, < 2.0) 11 | cocoapods-downloader (>= 1.1.1, < 2.0) 12 | cocoapods-plugins (>= 1.0.0, < 2.0) 13 | cocoapods-search (>= 1.0.0, < 2.0) 14 | cocoapods-stats (>= 1.0.0, < 2.0) 15 | cocoapods-trunk (>= 1.0.0, < 2.0) 16 | cocoapods-try (>= 1.1.0, < 2.0) 17 | colored (~> 1.2) 18 | escape (~> 0.0.4) 19 | fourflusher (~> 1.0.1) 20 | gh_inspector (~> 1.0) 21 | molinillo (~> 0.5.1) 22 | nap (~> 1.0) 23 | xcodeproj (>= 1.3.1, < 2.0) 24 | 25 | GEM 26 | remote: https://rubygems.org/ 27 | specs: 28 | activesupport (4.2.7.1) 29 | i18n (~> 0.7) 30 | json (~> 1.7, >= 1.7.7) 31 | minitest (~> 5.1) 32 | thread_safe (~> 0.3, >= 0.3.4) 33 | tzinfo (~> 1.1) 34 | claide (1.0.0) 35 | cocoapods-core (1.1.0.rc.2) 36 | activesupport (>= 4.0.2, < 5) 37 | fuzzy_match (~> 2.0.4) 38 | nap (~> 1.0) 39 | cocoapods-deintegrate (1.0.1) 40 | cocoapods-downloader (1.1.1) 41 | cocoapods-plugins (1.0.0) 42 | nap 43 | cocoapods-search (1.0.0) 44 | cocoapods-stats (1.0.0) 45 | cocoapods-trunk (1.0.0) 46 | nap (>= 0.8, < 2.0) 47 | netrc (= 0.7.8) 48 | cocoapods-try (1.1.0) 49 | colored (1.2) 50 | escape (0.0.4) 51 | fourflusher (1.0.1) 52 | fuzzy_match (2.0.4) 53 | gh_inspector (1.0.2) 54 | i18n (0.7.0) 55 | json (1.8.3) 56 | minitest (5.9.1) 57 | molinillo (0.5.1) 58 | nap (1.1.0) 59 | netrc (0.7.8) 60 | thread_safe (0.3.5) 61 | tzinfo (1.2.2) 62 | thread_safe (~> 0.1) 63 | xcodeproj (1.3.1) 64 | activesupport (>= 3) 65 | claide (>= 1.0.0, < 2.0) 66 | colored (~> 1.2) 67 | 68 | PLATFORMS 69 | ruby 70 | 71 | DEPENDENCIES 72 | cocoapods! 73 | 74 | BUNDLED WITH 75 | 1.12.1 76 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 Barış Şencan 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 | -------------------------------------------------------------------------------- /ManualLayout.podspec: -------------------------------------------------------------------------------- 1 | Pod::Spec.new do |s| 2 | s.name = 'ManualLayout' 3 | s.version = '1.3.0' 4 | s.license = { :type => 'MIT', :file => 'LICENSE' } 5 | s.summary = 'Easy to use and flexible AutoLayout alternative for iOS 8+. Supports AsyncDisplayKit.' 6 | 7 | s.homepage = 'https://github.com/isair/ManualLayout' 8 | s.author = { 'Baris Sencan' => 'baris.sncn@gmail.com' } 9 | s.social_media_url = 'https://twitter.com/IsairAndMorty' 10 | 11 | s.ios.deployment_target = '8.0' 12 | s.tvos.deployment_target = '9.0' 13 | s.source = { :git => 'https://github.com/isair/ManualLayout.git', :tag => s.version } 14 | s.source_files = 'ManualLayout' 15 | s.frameworks = 'UIKit' 16 | s.requires_arc = true 17 | end 18 | -------------------------------------------------------------------------------- /ManualLayout.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 5F3026921AAA3C6B00F65A20 /* UIScrollView+ManualLayout.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5F3026911AAA3C6B00F65A20 /* UIScrollView+ManualLayout.swift */; }; 11 | 5F3026941AAA460E00F65A20 /* UIScrollViewManualLayoutTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5F3026931AAA460E00F65A20 /* UIScrollViewManualLayoutTests.swift */; }; 12 | 5F67BC0A1A9D43FE00347483 /* UIViewManualLayoutTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5F67BC091A9D43FE00347483 /* UIViewManualLayoutTests.swift */; }; 13 | 5F67BC3F1A9E970300347483 /* UIViewController+ManualLayout.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5F67BC3E1A9E970300347483 /* UIViewController+ManualLayout.swift */; }; 14 | 5F67BC4C1A9FAB4B00347483 /* SmartAssign.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5F67BC4B1A9FAB4B00347483 /* SmartAssign.swift */; }; 15 | 5F67BC4E1A9FB1A600347483 /* SmartAssignTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5F67BC4D1A9FB1A600347483 /* SmartAssignTests.swift */; }; 16 | 5F67BC501A9FDDD900347483 /* HelperFunctions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5F67BC4F1A9FDDD900347483 /* HelperFunctions.swift */; }; 17 | 5F67BC521A9FE35C00347483 /* HelperFunctionTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5F67BC511A9FE35C00347483 /* HelperFunctionTests.swift */; }; 18 | 5F875C691A9BE99F003CACDD /* CALayer+ManualLayout.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5F875C681A9BE99F003CACDD /* CALayer+ManualLayout.swift */; }; 19 | 5F875C6D1A9BFC7E003CACDD /* UIView+ManualLayout.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5F875C6C1A9BFC7E003CACDD /* UIView+ManualLayout.swift */; }; 20 | 5F9134781AC9E0830001DBF8 /* CGRect+ManualLayout.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5F9134771AC9E0830001DBF8 /* CGRect+ManualLayout.swift */; }; 21 | 5F9134821AC9E1640001DBF8 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5F9134811AC9E1640001DBF8 /* AppDelegate.swift */; }; 22 | 5F9134841AC9E1640001DBF8 /* ExampleViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5F9134831AC9E1640001DBF8 /* ExampleViewController.swift */; }; 23 | 5F9134891AC9E1640001DBF8 /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 5F9134881AC9E1640001DBF8 /* Images.xcassets */; }; 24 | 5F91348C1AC9E1640001DBF8 /* LaunchScreen.xib in Resources */ = {isa = PBXBuildFile; fileRef = 5F91348A1AC9E1640001DBF8 /* LaunchScreen.xib */; }; 25 | 5F9134981AC9E1640001DBF8 /* SimpleExampleTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5F9134971AC9E1640001DBF8 /* SimpleExampleTests.swift */; }; 26 | 5F9134A11AC9E3A00001DBF8 /* ManualLayout.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 5FB4CBE91A9BBE7500C2FB4F /* ManualLayout.framework */; }; 27 | 5FB4CBEF1A9BBE7500C2FB4F /* ManualLayout.h in Headers */ = {isa = PBXBuildFile; fileRef = 5FB4CBEE1A9BBE7500C2FB4F /* ManualLayout.h */; settings = {ATTRIBUTES = (Public, ); }; }; 28 | 5FB4CBF51A9BBE7500C2FB4F /* ManualLayout.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 5FB4CBE91A9BBE7500C2FB4F /* ManualLayout.framework */; }; 29 | FE4500621BF12E5F0005E270 /* CGRect+ManualLayout.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5F9134771AC9E0830001DBF8 /* CGRect+ManualLayout.swift */; }; 30 | FE4500631BF12E5F0005E270 /* CALayer+ManualLayout.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5F875C681A9BE99F003CACDD /* CALayer+ManualLayout.swift */; }; 31 | FE4500641BF12E5F0005E270 /* UIViewController+ManualLayout.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5F67BC3E1A9E970300347483 /* UIViewController+ManualLayout.swift */; }; 32 | FE4500651BF12E5F0005E270 /* HelperFunctions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5F67BC4F1A9FDDD900347483 /* HelperFunctions.swift */; }; 33 | FE4500661BF12E5F0005E270 /* UIView+ManualLayout.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5F875C6C1A9BFC7E003CACDD /* UIView+ManualLayout.swift */; }; 34 | FE4500671BF12E5F0005E270 /* SmartAssign.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5F67BC4B1A9FAB4B00347483 /* SmartAssign.swift */; }; 35 | FE4500681BF12E5F0005E270 /* UIScrollView+ManualLayout.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5F3026911AAA3C6B00F65A20 /* UIScrollView+ManualLayout.swift */; }; 36 | FE45006B1BF12E5F0005E270 /* ManualLayout.h in Headers */ = {isa = PBXBuildFile; fileRef = 5FB4CBEE1A9BBE7500C2FB4F /* ManualLayout.h */; settings = {ATTRIBUTES = (Public, ); }; }; 37 | /* End PBXBuildFile section */ 38 | 39 | /* Begin PBXContainerItemProxy section */ 40 | 5F9134921AC9E1640001DBF8 /* PBXContainerItemProxy */ = { 41 | isa = PBXContainerItemProxy; 42 | containerPortal = 5FB4CBE01A9BBE7500C2FB4F /* Project object */; 43 | proxyType = 1; 44 | remoteGlobalIDString = 5F91347C1AC9E1630001DBF8; 45 | remoteInfo = SimpleExample; 46 | }; 47 | 5F91349F1AC9E3980001DBF8 /* PBXContainerItemProxy */ = { 48 | isa = PBXContainerItemProxy; 49 | containerPortal = 5FB4CBE01A9BBE7500C2FB4F /* Project object */; 50 | proxyType = 1; 51 | remoteGlobalIDString = 5FB4CBE81A9BBE7500C2FB4F; 52 | remoteInfo = ManualLayout; 53 | }; 54 | 5FB4CBF61A9BBE7500C2FB4F /* PBXContainerItemProxy */ = { 55 | isa = PBXContainerItemProxy; 56 | containerPortal = 5FB4CBE01A9BBE7500C2FB4F /* Project object */; 57 | proxyType = 1; 58 | remoteGlobalIDString = 5FB4CBE81A9BBE7500C2FB4F; 59 | remoteInfo = ManualLayout; 60 | }; 61 | /* End PBXContainerItemProxy section */ 62 | 63 | /* Begin PBXFileReference section */ 64 | 5F3026911AAA3C6B00F65A20 /* UIScrollView+ManualLayout.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "UIScrollView+ManualLayout.swift"; sourceTree = ""; }; 65 | 5F3026931AAA460E00F65A20 /* UIScrollViewManualLayoutTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = UIScrollViewManualLayoutTests.swift; sourceTree = ""; }; 66 | 5F67BC091A9D43FE00347483 /* UIViewManualLayoutTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = UIViewManualLayoutTests.swift; sourceTree = ""; }; 67 | 5F67BC3E1A9E970300347483 /* UIViewController+ManualLayout.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "UIViewController+ManualLayout.swift"; sourceTree = ""; }; 68 | 5F67BC4B1A9FAB4B00347483 /* SmartAssign.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SmartAssign.swift; sourceTree = ""; }; 69 | 5F67BC4D1A9FB1A600347483 /* SmartAssignTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SmartAssignTests.swift; sourceTree = ""; }; 70 | 5F67BC4F1A9FDDD900347483 /* HelperFunctions.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = HelperFunctions.swift; sourceTree = ""; }; 71 | 5F67BC511A9FE35C00347483 /* HelperFunctionTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = HelperFunctionTests.swift; sourceTree = ""; }; 72 | 5F875C681A9BE99F003CACDD /* CALayer+ManualLayout.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "CALayer+ManualLayout.swift"; sourceTree = ""; }; 73 | 5F875C6C1A9BFC7E003CACDD /* UIView+ManualLayout.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "UIView+ManualLayout.swift"; sourceTree = ""; }; 74 | 5F9134771AC9E0830001DBF8 /* CGRect+ManualLayout.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "CGRect+ManualLayout.swift"; sourceTree = ""; }; 75 | 5F91347D1AC9E1630001DBF8 /* SimpleExample.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = SimpleExample.app; sourceTree = BUILT_PRODUCTS_DIR; }; 76 | 5F9134801AC9E1630001DBF8 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 77 | 5F9134811AC9E1640001DBF8 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; 78 | 5F9134831AC9E1640001DBF8 /* ExampleViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ExampleViewController.swift; sourceTree = ""; }; 79 | 5F9134881AC9E1640001DBF8 /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = ""; }; 80 | 5F91348B1AC9E1640001DBF8 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/LaunchScreen.xib; sourceTree = ""; }; 81 | 5F9134911AC9E1640001DBF8 /* SimpleExampleTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = SimpleExampleTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 82 | 5F9134961AC9E1640001DBF8 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 83 | 5F9134971AC9E1640001DBF8 /* SimpleExampleTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SimpleExampleTests.swift; sourceTree = ""; }; 84 | 5FB4CBE91A9BBE7500C2FB4F /* ManualLayout.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = ManualLayout.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 85 | 5FB4CBED1A9BBE7500C2FB4F /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 86 | 5FB4CBEE1A9BBE7500C2FB4F /* ManualLayout.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ManualLayout.h; sourceTree = ""; }; 87 | 5FB4CBF41A9BBE7500C2FB4F /* ManualLayoutTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = ManualLayoutTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 88 | 5FB4CBFA1A9BBE7500C2FB4F /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 89 | 5FE3334E1C028A8F00EF50C4 /* Info-tvOS.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = "Info-tvOS.plist"; sourceTree = ""; }; 90 | FE4500701BF12E5F0005E270 /* ManualLayout.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = ManualLayout.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 91 | /* End PBXFileReference section */ 92 | 93 | /* Begin PBXFrameworksBuildPhase section */ 94 | 5F91347A1AC9E1630001DBF8 /* Frameworks */ = { 95 | isa = PBXFrameworksBuildPhase; 96 | buildActionMask = 2147483647; 97 | files = ( 98 | 5F9134A11AC9E3A00001DBF8 /* ManualLayout.framework in Frameworks */, 99 | ); 100 | runOnlyForDeploymentPostprocessing = 0; 101 | }; 102 | 5F91348E1AC9E1640001DBF8 /* Frameworks */ = { 103 | isa = PBXFrameworksBuildPhase; 104 | buildActionMask = 2147483647; 105 | files = ( 106 | ); 107 | runOnlyForDeploymentPostprocessing = 0; 108 | }; 109 | 5FB4CBE51A9BBE7500C2FB4F /* Frameworks */ = { 110 | isa = PBXFrameworksBuildPhase; 111 | buildActionMask = 2147483647; 112 | files = ( 113 | ); 114 | runOnlyForDeploymentPostprocessing = 0; 115 | }; 116 | 5FB4CBF11A9BBE7500C2FB4F /* Frameworks */ = { 117 | isa = PBXFrameworksBuildPhase; 118 | buildActionMask = 2147483647; 119 | files = ( 120 | 5FB4CBF51A9BBE7500C2FB4F /* ManualLayout.framework in Frameworks */, 121 | ); 122 | runOnlyForDeploymentPostprocessing = 0; 123 | }; 124 | FE4500691BF12E5F0005E270 /* Frameworks */ = { 125 | isa = PBXFrameworksBuildPhase; 126 | buildActionMask = 2147483647; 127 | files = ( 128 | ); 129 | runOnlyForDeploymentPostprocessing = 0; 130 | }; 131 | /* End PBXFrameworksBuildPhase section */ 132 | 133 | /* Begin PBXGroup section */ 134 | 5F91347E1AC9E1630001DBF8 /* SimpleExample */ = { 135 | isa = PBXGroup; 136 | children = ( 137 | 5F9134811AC9E1640001DBF8 /* AppDelegate.swift */, 138 | 5F9134831AC9E1640001DBF8 /* ExampleViewController.swift */, 139 | 5F9134881AC9E1640001DBF8 /* Images.xcassets */, 140 | 5F91348A1AC9E1640001DBF8 /* LaunchScreen.xib */, 141 | 5F91347F1AC9E1630001DBF8 /* Supporting Files */, 142 | ); 143 | path = SimpleExample; 144 | sourceTree = ""; 145 | }; 146 | 5F91347F1AC9E1630001DBF8 /* Supporting Files */ = { 147 | isa = PBXGroup; 148 | children = ( 149 | 5F9134801AC9E1630001DBF8 /* Info.plist */, 150 | ); 151 | name = "Supporting Files"; 152 | sourceTree = ""; 153 | }; 154 | 5F9134941AC9E1640001DBF8 /* SimpleExampleTests */ = { 155 | isa = PBXGroup; 156 | children = ( 157 | 5F9134971AC9E1640001DBF8 /* SimpleExampleTests.swift */, 158 | 5F9134951AC9E1640001DBF8 /* Supporting Files */, 159 | ); 160 | path = SimpleExampleTests; 161 | sourceTree = ""; 162 | }; 163 | 5F9134951AC9E1640001DBF8 /* Supporting Files */ = { 164 | isa = PBXGroup; 165 | children = ( 166 | 5F9134961AC9E1640001DBF8 /* Info.plist */, 167 | ); 168 | name = "Supporting Files"; 169 | sourceTree = ""; 170 | }; 171 | 5FB4CBDF1A9BBE7500C2FB4F = { 172 | isa = PBXGroup; 173 | children = ( 174 | 5FB4CBEB1A9BBE7500C2FB4F /* ManualLayout */, 175 | 5FB4CBF81A9BBE7500C2FB4F /* ManualLayoutTests */, 176 | 5F91347E1AC9E1630001DBF8 /* SimpleExample */, 177 | 5F9134941AC9E1640001DBF8 /* SimpleExampleTests */, 178 | 5FB4CBEA1A9BBE7500C2FB4F /* Products */, 179 | ); 180 | sourceTree = ""; 181 | }; 182 | 5FB4CBEA1A9BBE7500C2FB4F /* Products */ = { 183 | isa = PBXGroup; 184 | children = ( 185 | 5FB4CBE91A9BBE7500C2FB4F /* ManualLayout.framework */, 186 | 5FB4CBF41A9BBE7500C2FB4F /* ManualLayoutTests.xctest */, 187 | 5F91347D1AC9E1630001DBF8 /* SimpleExample.app */, 188 | 5F9134911AC9E1640001DBF8 /* SimpleExampleTests.xctest */, 189 | FE4500701BF12E5F0005E270 /* ManualLayout.framework */, 190 | ); 191 | name = Products; 192 | sourceTree = ""; 193 | }; 194 | 5FB4CBEB1A9BBE7500C2FB4F /* ManualLayout */ = { 195 | isa = PBXGroup; 196 | children = ( 197 | 5FB4CBEE1A9BBE7500C2FB4F /* ManualLayout.h */, 198 | 5F67BC4B1A9FAB4B00347483 /* SmartAssign.swift */, 199 | 5F67BC4F1A9FDDD900347483 /* HelperFunctions.swift */, 200 | 5F9134771AC9E0830001DBF8 /* CGRect+ManualLayout.swift */, 201 | 5F875C681A9BE99F003CACDD /* CALayer+ManualLayout.swift */, 202 | 5F875C6C1A9BFC7E003CACDD /* UIView+ManualLayout.swift */, 203 | 5F3026911AAA3C6B00F65A20 /* UIScrollView+ManualLayout.swift */, 204 | 5F67BC3E1A9E970300347483 /* UIViewController+ManualLayout.swift */, 205 | 5FB4CBEC1A9BBE7500C2FB4F /* Supporting Files */, 206 | ); 207 | path = ManualLayout; 208 | sourceTree = ""; 209 | }; 210 | 5FB4CBEC1A9BBE7500C2FB4F /* Supporting Files */ = { 211 | isa = PBXGroup; 212 | children = ( 213 | 5FB4CBED1A9BBE7500C2FB4F /* Info.plist */, 214 | 5FE3334E1C028A8F00EF50C4 /* Info-tvOS.plist */, 215 | ); 216 | name = "Supporting Files"; 217 | sourceTree = ""; 218 | }; 219 | 5FB4CBF81A9BBE7500C2FB4F /* ManualLayoutTests */ = { 220 | isa = PBXGroup; 221 | children = ( 222 | 5F67BC4D1A9FB1A600347483 /* SmartAssignTests.swift */, 223 | 5F67BC511A9FE35C00347483 /* HelperFunctionTests.swift */, 224 | 5F67BC091A9D43FE00347483 /* UIViewManualLayoutTests.swift */, 225 | 5F3026931AAA460E00F65A20 /* UIScrollViewManualLayoutTests.swift */, 226 | 5FB4CBF91A9BBE7500C2FB4F /* Supporting Files */, 227 | ); 228 | path = ManualLayoutTests; 229 | sourceTree = ""; 230 | }; 231 | 5FB4CBF91A9BBE7500C2FB4F /* Supporting Files */ = { 232 | isa = PBXGroup; 233 | children = ( 234 | 5FB4CBFA1A9BBE7500C2FB4F /* Info.plist */, 235 | ); 236 | name = "Supporting Files"; 237 | sourceTree = ""; 238 | }; 239 | /* End PBXGroup section */ 240 | 241 | /* Begin PBXHeadersBuildPhase section */ 242 | 5FB4CBE61A9BBE7500C2FB4F /* Headers */ = { 243 | isa = PBXHeadersBuildPhase; 244 | buildActionMask = 2147483647; 245 | files = ( 246 | 5FB4CBEF1A9BBE7500C2FB4F /* ManualLayout.h in Headers */, 247 | ); 248 | runOnlyForDeploymentPostprocessing = 0; 249 | }; 250 | FE45006A1BF12E5F0005E270 /* Headers */ = { 251 | isa = PBXHeadersBuildPhase; 252 | buildActionMask = 2147483647; 253 | files = ( 254 | FE45006B1BF12E5F0005E270 /* ManualLayout.h in Headers */, 255 | ); 256 | runOnlyForDeploymentPostprocessing = 0; 257 | }; 258 | /* End PBXHeadersBuildPhase section */ 259 | 260 | /* Begin PBXNativeTarget section */ 261 | 5F91347C1AC9E1630001DBF8 /* SimpleExample */ = { 262 | isa = PBXNativeTarget; 263 | buildConfigurationList = 5F9134991AC9E1640001DBF8 /* Build configuration list for PBXNativeTarget "SimpleExample" */; 264 | buildPhases = ( 265 | 5F9134791AC9E1630001DBF8 /* Sources */, 266 | 5F91347A1AC9E1630001DBF8 /* Frameworks */, 267 | 5F91347B1AC9E1630001DBF8 /* Resources */, 268 | ); 269 | buildRules = ( 270 | ); 271 | dependencies = ( 272 | 5F9134A01AC9E3980001DBF8 /* PBXTargetDependency */, 273 | ); 274 | name = SimpleExample; 275 | productName = SimpleExample; 276 | productReference = 5F91347D1AC9E1630001DBF8 /* SimpleExample.app */; 277 | productType = "com.apple.product-type.application"; 278 | }; 279 | 5F9134901AC9E1640001DBF8 /* SimpleExampleTests */ = { 280 | isa = PBXNativeTarget; 281 | buildConfigurationList = 5F91349C1AC9E1640001DBF8 /* Build configuration list for PBXNativeTarget "SimpleExampleTests" */; 282 | buildPhases = ( 283 | 5F91348D1AC9E1640001DBF8 /* Sources */, 284 | 5F91348E1AC9E1640001DBF8 /* Frameworks */, 285 | 5F91348F1AC9E1640001DBF8 /* Resources */, 286 | ); 287 | buildRules = ( 288 | ); 289 | dependencies = ( 290 | 5F9134931AC9E1640001DBF8 /* PBXTargetDependency */, 291 | ); 292 | name = SimpleExampleTests; 293 | productName = SimpleExampleTests; 294 | productReference = 5F9134911AC9E1640001DBF8 /* SimpleExampleTests.xctest */; 295 | productType = "com.apple.product-type.bundle.unit-test"; 296 | }; 297 | 5FB4CBE81A9BBE7500C2FB4F /* ManualLayout */ = { 298 | isa = PBXNativeTarget; 299 | buildConfigurationList = 5FB4CBFF1A9BBE7500C2FB4F /* Build configuration list for PBXNativeTarget "ManualLayout" */; 300 | buildPhases = ( 301 | 5FB4CBE41A9BBE7500C2FB4F /* Sources */, 302 | 5FB4CBE51A9BBE7500C2FB4F /* Frameworks */, 303 | 5FB4CBE61A9BBE7500C2FB4F /* Headers */, 304 | 5FB4CBE71A9BBE7500C2FB4F /* Resources */, 305 | ); 306 | buildRules = ( 307 | ); 308 | dependencies = ( 309 | ); 310 | name = ManualLayout; 311 | productName = ManualLayout; 312 | productReference = 5FB4CBE91A9BBE7500C2FB4F /* ManualLayout.framework */; 313 | productType = "com.apple.product-type.framework"; 314 | }; 315 | 5FB4CBF31A9BBE7500C2FB4F /* ManualLayoutTests */ = { 316 | isa = PBXNativeTarget; 317 | buildConfigurationList = 5FB4CC021A9BBE7500C2FB4F /* Build configuration list for PBXNativeTarget "ManualLayoutTests" */; 318 | buildPhases = ( 319 | 5FB4CBF01A9BBE7500C2FB4F /* Sources */, 320 | 5FB4CBF11A9BBE7500C2FB4F /* Frameworks */, 321 | 5FB4CBF21A9BBE7500C2FB4F /* Resources */, 322 | ); 323 | buildRules = ( 324 | ); 325 | dependencies = ( 326 | 5FB4CBF71A9BBE7500C2FB4F /* PBXTargetDependency */, 327 | ); 328 | name = ManualLayoutTests; 329 | productName = ManualLayoutTests; 330 | productReference = 5FB4CBF41A9BBE7500C2FB4F /* ManualLayoutTests.xctest */; 331 | productType = "com.apple.product-type.bundle.unit-test"; 332 | }; 333 | FE4500601BF12E5F0005E270 /* ManualLayout-tvOS */ = { 334 | isa = PBXNativeTarget; 335 | buildConfigurationList = FE45006D1BF12E5F0005E270 /* Build configuration list for PBXNativeTarget "ManualLayout-tvOS" */; 336 | buildPhases = ( 337 | FE4500611BF12E5F0005E270 /* Sources */, 338 | FE4500691BF12E5F0005E270 /* Frameworks */, 339 | FE45006A1BF12E5F0005E270 /* Headers */, 340 | FE45006C1BF12E5F0005E270 /* Resources */, 341 | ); 342 | buildRules = ( 343 | ); 344 | dependencies = ( 345 | ); 346 | name = "ManualLayout-tvOS"; 347 | productName = ManualLayout; 348 | productReference = FE4500701BF12E5F0005E270 /* ManualLayout.framework */; 349 | productType = "com.apple.product-type.framework"; 350 | }; 351 | /* End PBXNativeTarget section */ 352 | 353 | /* Begin PBXProject section */ 354 | 5FB4CBE01A9BBE7500C2FB4F /* Project object */ = { 355 | isa = PBXProject; 356 | attributes = { 357 | LastSwiftUpdateCheck = 0700; 358 | LastUpgradeCheck = 0900; 359 | ORGANIZATIONNAME = "Baris Sencan"; 360 | TargetAttributes = { 361 | 5F91347C1AC9E1630001DBF8 = { 362 | CreatedOnToolsVersion = 6.2; 363 | LastSwiftMigration = 0800; 364 | }; 365 | 5F9134901AC9E1640001DBF8 = { 366 | CreatedOnToolsVersion = 6.2; 367 | LastSwiftMigration = 0800; 368 | TestTargetID = 5F91347C1AC9E1630001DBF8; 369 | }; 370 | 5FB4CBE81A9BBE7500C2FB4F = { 371 | CreatedOnToolsVersion = 6.1.1; 372 | LastSwiftMigration = 0900; 373 | ProvisioningStyle = Automatic; 374 | }; 375 | 5FB4CBF31A9BBE7500C2FB4F = { 376 | CreatedOnToolsVersion = 6.1.1; 377 | LastSwiftMigration = 0900; 378 | }; 379 | FE4500601BF12E5F0005E270 = { 380 | ProvisioningStyle = Automatic; 381 | }; 382 | }; 383 | }; 384 | buildConfigurationList = 5FB4CBE31A9BBE7500C2FB4F /* Build configuration list for PBXProject "ManualLayout" */; 385 | compatibilityVersion = "Xcode 3.2"; 386 | developmentRegion = English; 387 | hasScannedForEncodings = 0; 388 | knownRegions = ( 389 | en, 390 | Base, 391 | ); 392 | mainGroup = 5FB4CBDF1A9BBE7500C2FB4F; 393 | productRefGroup = 5FB4CBEA1A9BBE7500C2FB4F /* Products */; 394 | projectDirPath = ""; 395 | projectRoot = ""; 396 | targets = ( 397 | 5FB4CBE81A9BBE7500C2FB4F /* ManualLayout */, 398 | FE4500601BF12E5F0005E270 /* ManualLayout-tvOS */, 399 | 5FB4CBF31A9BBE7500C2FB4F /* ManualLayoutTests */, 400 | 5F91347C1AC9E1630001DBF8 /* SimpleExample */, 401 | 5F9134901AC9E1640001DBF8 /* SimpleExampleTests */, 402 | ); 403 | }; 404 | /* End PBXProject section */ 405 | 406 | /* Begin PBXResourcesBuildPhase section */ 407 | 5F91347B1AC9E1630001DBF8 /* Resources */ = { 408 | isa = PBXResourcesBuildPhase; 409 | buildActionMask = 2147483647; 410 | files = ( 411 | 5F91348C1AC9E1640001DBF8 /* LaunchScreen.xib in Resources */, 412 | 5F9134891AC9E1640001DBF8 /* Images.xcassets in Resources */, 413 | ); 414 | runOnlyForDeploymentPostprocessing = 0; 415 | }; 416 | 5F91348F1AC9E1640001DBF8 /* Resources */ = { 417 | isa = PBXResourcesBuildPhase; 418 | buildActionMask = 2147483647; 419 | files = ( 420 | ); 421 | runOnlyForDeploymentPostprocessing = 0; 422 | }; 423 | 5FB4CBE71A9BBE7500C2FB4F /* Resources */ = { 424 | isa = PBXResourcesBuildPhase; 425 | buildActionMask = 2147483647; 426 | files = ( 427 | ); 428 | runOnlyForDeploymentPostprocessing = 0; 429 | }; 430 | 5FB4CBF21A9BBE7500C2FB4F /* Resources */ = { 431 | isa = PBXResourcesBuildPhase; 432 | buildActionMask = 2147483647; 433 | files = ( 434 | ); 435 | runOnlyForDeploymentPostprocessing = 0; 436 | }; 437 | FE45006C1BF12E5F0005E270 /* Resources */ = { 438 | isa = PBXResourcesBuildPhase; 439 | buildActionMask = 2147483647; 440 | files = ( 441 | ); 442 | runOnlyForDeploymentPostprocessing = 0; 443 | }; 444 | /* End PBXResourcesBuildPhase section */ 445 | 446 | /* Begin PBXSourcesBuildPhase section */ 447 | 5F9134791AC9E1630001DBF8 /* Sources */ = { 448 | isa = PBXSourcesBuildPhase; 449 | buildActionMask = 2147483647; 450 | files = ( 451 | 5F9134841AC9E1640001DBF8 /* ExampleViewController.swift in Sources */, 452 | 5F9134821AC9E1640001DBF8 /* AppDelegate.swift in Sources */, 453 | ); 454 | runOnlyForDeploymentPostprocessing = 0; 455 | }; 456 | 5F91348D1AC9E1640001DBF8 /* Sources */ = { 457 | isa = PBXSourcesBuildPhase; 458 | buildActionMask = 2147483647; 459 | files = ( 460 | 5F9134981AC9E1640001DBF8 /* SimpleExampleTests.swift in Sources */, 461 | ); 462 | runOnlyForDeploymentPostprocessing = 0; 463 | }; 464 | 5FB4CBE41A9BBE7500C2FB4F /* Sources */ = { 465 | isa = PBXSourcesBuildPhase; 466 | buildActionMask = 2147483647; 467 | files = ( 468 | 5F9134781AC9E0830001DBF8 /* CGRect+ManualLayout.swift in Sources */, 469 | 5F875C691A9BE99F003CACDD /* CALayer+ManualLayout.swift in Sources */, 470 | 5F67BC3F1A9E970300347483 /* UIViewController+ManualLayout.swift in Sources */, 471 | 5F67BC501A9FDDD900347483 /* HelperFunctions.swift in Sources */, 472 | 5F875C6D1A9BFC7E003CACDD /* UIView+ManualLayout.swift in Sources */, 473 | 5F67BC4C1A9FAB4B00347483 /* SmartAssign.swift in Sources */, 474 | 5F3026921AAA3C6B00F65A20 /* UIScrollView+ManualLayout.swift in Sources */, 475 | ); 476 | runOnlyForDeploymentPostprocessing = 0; 477 | }; 478 | 5FB4CBF01A9BBE7500C2FB4F /* Sources */ = { 479 | isa = PBXSourcesBuildPhase; 480 | buildActionMask = 2147483647; 481 | files = ( 482 | 5F67BC521A9FE35C00347483 /* HelperFunctionTests.swift in Sources */, 483 | 5F3026941AAA460E00F65A20 /* UIScrollViewManualLayoutTests.swift in Sources */, 484 | 5F67BC4E1A9FB1A600347483 /* SmartAssignTests.swift in Sources */, 485 | 5F67BC0A1A9D43FE00347483 /* UIViewManualLayoutTests.swift in Sources */, 486 | ); 487 | runOnlyForDeploymentPostprocessing = 0; 488 | }; 489 | FE4500611BF12E5F0005E270 /* Sources */ = { 490 | isa = PBXSourcesBuildPhase; 491 | buildActionMask = 2147483647; 492 | files = ( 493 | FE4500621BF12E5F0005E270 /* CGRect+ManualLayout.swift in Sources */, 494 | FE4500631BF12E5F0005E270 /* CALayer+ManualLayout.swift in Sources */, 495 | FE4500641BF12E5F0005E270 /* UIViewController+ManualLayout.swift in Sources */, 496 | FE4500651BF12E5F0005E270 /* HelperFunctions.swift in Sources */, 497 | FE4500661BF12E5F0005E270 /* UIView+ManualLayout.swift in Sources */, 498 | FE4500671BF12E5F0005E270 /* SmartAssign.swift in Sources */, 499 | FE4500681BF12E5F0005E270 /* UIScrollView+ManualLayout.swift in Sources */, 500 | ); 501 | runOnlyForDeploymentPostprocessing = 0; 502 | }; 503 | /* End PBXSourcesBuildPhase section */ 504 | 505 | /* Begin PBXTargetDependency section */ 506 | 5F9134931AC9E1640001DBF8 /* PBXTargetDependency */ = { 507 | isa = PBXTargetDependency; 508 | target = 5F91347C1AC9E1630001DBF8 /* SimpleExample */; 509 | targetProxy = 5F9134921AC9E1640001DBF8 /* PBXContainerItemProxy */; 510 | }; 511 | 5F9134A01AC9E3980001DBF8 /* PBXTargetDependency */ = { 512 | isa = PBXTargetDependency; 513 | target = 5FB4CBE81A9BBE7500C2FB4F /* ManualLayout */; 514 | targetProxy = 5F91349F1AC9E3980001DBF8 /* PBXContainerItemProxy */; 515 | }; 516 | 5FB4CBF71A9BBE7500C2FB4F /* PBXTargetDependency */ = { 517 | isa = PBXTargetDependency; 518 | target = 5FB4CBE81A9BBE7500C2FB4F /* ManualLayout */; 519 | targetProxy = 5FB4CBF61A9BBE7500C2FB4F /* PBXContainerItemProxy */; 520 | }; 521 | /* End PBXTargetDependency section */ 522 | 523 | /* Begin PBXVariantGroup section */ 524 | 5F91348A1AC9E1640001DBF8 /* LaunchScreen.xib */ = { 525 | isa = PBXVariantGroup; 526 | children = ( 527 | 5F91348B1AC9E1640001DBF8 /* Base */, 528 | ); 529 | name = LaunchScreen.xib; 530 | sourceTree = ""; 531 | }; 532 | /* End PBXVariantGroup section */ 533 | 534 | /* Begin XCBuildConfiguration section */ 535 | 5F91349A1AC9E1640001DBF8 /* Debug */ = { 536 | isa = XCBuildConfiguration; 537 | buildSettings = { 538 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 539 | GCC_PREPROCESSOR_DEFINITIONS = ( 540 | "DEBUG=1", 541 | "$(inherited)", 542 | ); 543 | INFOPLIST_FILE = SimpleExample/Info.plist; 544 | IPHONEOS_DEPLOYMENT_TARGET = 8.0; 545 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 546 | PRODUCT_BUNDLE_IDENTIFIER = "com.bsencan.ManualLayout.SimpleExample.$(PRODUCT_NAME:rfc1034identifier)"; 547 | PRODUCT_NAME = "$(TARGET_NAME)"; 548 | SWIFT_VERSION = 3.0; 549 | }; 550 | name = Debug; 551 | }; 552 | 5F91349B1AC9E1640001DBF8 /* Release */ = { 553 | isa = XCBuildConfiguration; 554 | buildSettings = { 555 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 556 | COPY_PHASE_STRIP = NO; 557 | INFOPLIST_FILE = SimpleExample/Info.plist; 558 | IPHONEOS_DEPLOYMENT_TARGET = 8.0; 559 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 560 | PRODUCT_BUNDLE_IDENTIFIER = "com.bsencan.ManualLayout.SimpleExample.$(PRODUCT_NAME:rfc1034identifier)"; 561 | PRODUCT_NAME = "$(TARGET_NAME)"; 562 | SWIFT_VERSION = 3.0; 563 | }; 564 | name = Release; 565 | }; 566 | 5F91349D1AC9E1640001DBF8 /* Debug */ = { 567 | isa = XCBuildConfiguration; 568 | buildSettings = { 569 | BUNDLE_LOADER = "$(TEST_HOST)"; 570 | FRAMEWORK_SEARCH_PATHS = ( 571 | "$(SDKROOT)/Developer/Library/Frameworks", 572 | "$(inherited)", 573 | ); 574 | GCC_PREPROCESSOR_DEFINITIONS = ( 575 | "DEBUG=1", 576 | "$(inherited)", 577 | ); 578 | INFOPLIST_FILE = SimpleExampleTests/Info.plist; 579 | IPHONEOS_DEPLOYMENT_TARGET = 8.2; 580 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 581 | PRODUCT_BUNDLE_IDENTIFIER = "com.bsencan.ManualLayout.SimpleExample.$(PRODUCT_NAME:rfc1034identifier)"; 582 | PRODUCT_NAME = "$(TARGET_NAME)"; 583 | SWIFT_VERSION = 3.0; 584 | TEST_HOST = "$(BUILT_PRODUCTS_DIR)/SimpleExample.app/SimpleExample"; 585 | }; 586 | name = Debug; 587 | }; 588 | 5F91349E1AC9E1640001DBF8 /* Release */ = { 589 | isa = XCBuildConfiguration; 590 | buildSettings = { 591 | BUNDLE_LOADER = "$(TEST_HOST)"; 592 | COPY_PHASE_STRIP = NO; 593 | FRAMEWORK_SEARCH_PATHS = ( 594 | "$(SDKROOT)/Developer/Library/Frameworks", 595 | "$(inherited)", 596 | ); 597 | INFOPLIST_FILE = SimpleExampleTests/Info.plist; 598 | IPHONEOS_DEPLOYMENT_TARGET = 8.2; 599 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 600 | PRODUCT_BUNDLE_IDENTIFIER = "com.bsencan.ManualLayout.SimpleExample.$(PRODUCT_NAME:rfc1034identifier)"; 601 | PRODUCT_NAME = "$(TARGET_NAME)"; 602 | SWIFT_VERSION = 3.0; 603 | TEST_HOST = "$(BUILT_PRODUCTS_DIR)/SimpleExample.app/SimpleExample"; 604 | }; 605 | name = Release; 606 | }; 607 | 5FB4CBFD1A9BBE7500C2FB4F /* Debug */ = { 608 | isa = XCBuildConfiguration; 609 | buildSettings = { 610 | ALWAYS_SEARCH_USER_PATHS = NO; 611 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 612 | CLANG_CXX_LIBRARY = "libc++"; 613 | CLANG_ENABLE_MODULES = YES; 614 | CLANG_ENABLE_OBJC_ARC = YES; 615 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 616 | CLANG_WARN_BOOL_CONVERSION = YES; 617 | CLANG_WARN_COMMA = YES; 618 | CLANG_WARN_CONSTANT_CONVERSION = YES; 619 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 620 | CLANG_WARN_EMPTY_BODY = YES; 621 | CLANG_WARN_ENUM_CONVERSION = YES; 622 | CLANG_WARN_INFINITE_RECURSION = YES; 623 | CLANG_WARN_INT_CONVERSION = YES; 624 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 625 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 626 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 627 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 628 | CLANG_WARN_STRICT_PROTOTYPES = YES; 629 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 630 | CLANG_WARN_UNREACHABLE_CODE = YES; 631 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 632 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 633 | COPY_PHASE_STRIP = NO; 634 | CURRENT_PROJECT_VERSION = 2; 635 | ENABLE_STRICT_OBJC_MSGSEND = YES; 636 | ENABLE_TESTABILITY = YES; 637 | GCC_C_LANGUAGE_STANDARD = gnu99; 638 | GCC_DYNAMIC_NO_PIC = NO; 639 | GCC_NO_COMMON_BLOCKS = YES; 640 | GCC_OPTIMIZATION_LEVEL = 0; 641 | GCC_PREPROCESSOR_DEFINITIONS = ( 642 | "DEBUG=1", 643 | "$(inherited)", 644 | ); 645 | GCC_SYMBOLS_PRIVATE_EXTERN = NO; 646 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 647 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 648 | GCC_WARN_UNDECLARED_SELECTOR = YES; 649 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 650 | GCC_WARN_UNUSED_FUNCTION = YES; 651 | GCC_WARN_UNUSED_VARIABLE = YES; 652 | IPHONEOS_DEPLOYMENT_TARGET = 8.1; 653 | MTL_ENABLE_DEBUG_INFO = YES; 654 | ONLY_ACTIVE_ARCH = YES; 655 | SDKROOT = iphoneos; 656 | SWIFT_OPTIMIZATION_LEVEL = "-Onone"; 657 | TARGETED_DEVICE_FAMILY = "1,2"; 658 | VERSIONING_SYSTEM = "apple-generic"; 659 | VERSION_INFO_PREFIX = ""; 660 | }; 661 | name = Debug; 662 | }; 663 | 5FB4CBFE1A9BBE7500C2FB4F /* Release */ = { 664 | isa = XCBuildConfiguration; 665 | buildSettings = { 666 | ALWAYS_SEARCH_USER_PATHS = NO; 667 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 668 | CLANG_CXX_LIBRARY = "libc++"; 669 | CLANG_ENABLE_MODULES = YES; 670 | CLANG_ENABLE_OBJC_ARC = YES; 671 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 672 | CLANG_WARN_BOOL_CONVERSION = YES; 673 | CLANG_WARN_COMMA = YES; 674 | CLANG_WARN_CONSTANT_CONVERSION = YES; 675 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 676 | CLANG_WARN_EMPTY_BODY = YES; 677 | CLANG_WARN_ENUM_CONVERSION = YES; 678 | CLANG_WARN_INFINITE_RECURSION = YES; 679 | CLANG_WARN_INT_CONVERSION = YES; 680 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 681 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 682 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 683 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 684 | CLANG_WARN_STRICT_PROTOTYPES = YES; 685 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 686 | CLANG_WARN_UNREACHABLE_CODE = YES; 687 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 688 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Distribution"; 689 | COPY_PHASE_STRIP = YES; 690 | CURRENT_PROJECT_VERSION = 2; 691 | ENABLE_NS_ASSERTIONS = NO; 692 | ENABLE_STRICT_OBJC_MSGSEND = YES; 693 | GCC_C_LANGUAGE_STANDARD = gnu99; 694 | GCC_NO_COMMON_BLOCKS = YES; 695 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 696 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 697 | GCC_WARN_UNDECLARED_SELECTOR = YES; 698 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 699 | GCC_WARN_UNUSED_FUNCTION = YES; 700 | GCC_WARN_UNUSED_VARIABLE = YES; 701 | IPHONEOS_DEPLOYMENT_TARGET = 8.1; 702 | MTL_ENABLE_DEBUG_INFO = NO; 703 | SDKROOT = iphoneos; 704 | SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; 705 | TARGETED_DEVICE_FAMILY = "1,2"; 706 | VALIDATE_PRODUCT = YES; 707 | VERSIONING_SYSTEM = "apple-generic"; 708 | VERSION_INFO_PREFIX = ""; 709 | }; 710 | name = Release; 711 | }; 712 | 5FB4CC001A9BBE7500C2FB4F /* Debug */ = { 713 | isa = XCBuildConfiguration; 714 | buildSettings = { 715 | CLANG_ENABLE_MODULES = YES; 716 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; 717 | DEFINES_MODULE = YES; 718 | DYLIB_COMPATIBILITY_VERSION = 1; 719 | DYLIB_CURRENT_VERSION = 1; 720 | DYLIB_INSTALL_NAME_BASE = "@rpath"; 721 | INFOPLIST_FILE = ManualLayout/Info.plist; 722 | INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; 723 | IPHONEOS_DEPLOYMENT_TARGET = 8.0; 724 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 725 | PRODUCT_BUNDLE_IDENTIFIER = "com.bsencan.$(PRODUCT_NAME:rfc1034identifier)"; 726 | PRODUCT_NAME = "$(TARGET_NAME)"; 727 | SKIP_INSTALL = YES; 728 | SWIFT_OPTIMIZATION_LEVEL = "-Onone"; 729 | SWIFT_VERSION = 4.0; 730 | }; 731 | name = Debug; 732 | }; 733 | 5FB4CC011A9BBE7500C2FB4F /* Release */ = { 734 | isa = XCBuildConfiguration; 735 | buildSettings = { 736 | CLANG_ENABLE_MODULES = YES; 737 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; 738 | DEFINES_MODULE = YES; 739 | DYLIB_COMPATIBILITY_VERSION = 1; 740 | DYLIB_CURRENT_VERSION = 1; 741 | DYLIB_INSTALL_NAME_BASE = "@rpath"; 742 | INFOPLIST_FILE = ManualLayout/Info.plist; 743 | INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; 744 | IPHONEOS_DEPLOYMENT_TARGET = 8.0; 745 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 746 | PRODUCT_BUNDLE_IDENTIFIER = "com.bsencan.$(PRODUCT_NAME:rfc1034identifier)"; 747 | PRODUCT_NAME = "$(TARGET_NAME)"; 748 | SKIP_INSTALL = YES; 749 | SWIFT_VERSION = 4.0; 750 | }; 751 | name = Release; 752 | }; 753 | 5FB4CC031A9BBE7500C2FB4F /* Debug */ = { 754 | isa = XCBuildConfiguration; 755 | buildSettings = { 756 | FRAMEWORK_SEARCH_PATHS = ( 757 | "$(SDKROOT)/Developer/Library/Frameworks", 758 | "$(inherited)", 759 | ); 760 | GCC_PREPROCESSOR_DEFINITIONS = ( 761 | "DEBUG=1", 762 | "$(inherited)", 763 | ); 764 | INFOPLIST_FILE = ManualLayoutTests/Info.plist; 765 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 766 | PRODUCT_BUNDLE_IDENTIFIER = "com.bsencan.$(PRODUCT_NAME:rfc1034identifier)"; 767 | PRODUCT_NAME = "$(TARGET_NAME)"; 768 | SWIFT_VERSION = 4.0; 769 | }; 770 | name = Debug; 771 | }; 772 | 5FB4CC041A9BBE7500C2FB4F /* Release */ = { 773 | isa = XCBuildConfiguration; 774 | buildSettings = { 775 | FRAMEWORK_SEARCH_PATHS = ( 776 | "$(SDKROOT)/Developer/Library/Frameworks", 777 | "$(inherited)", 778 | ); 779 | INFOPLIST_FILE = ManualLayoutTests/Info.plist; 780 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 781 | PRODUCT_BUNDLE_IDENTIFIER = "com.bsencan.$(PRODUCT_NAME:rfc1034identifier)"; 782 | PRODUCT_NAME = "$(TARGET_NAME)"; 783 | SWIFT_VERSION = 4.0; 784 | }; 785 | name = Release; 786 | }; 787 | FE45006E1BF12E5F0005E270 /* Debug */ = { 788 | isa = XCBuildConfiguration; 789 | buildSettings = { 790 | BITCODE_GENERATION_MODE = bitcode; 791 | CLANG_ENABLE_MODULES = YES; 792 | "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; 793 | DEFINES_MODULE = YES; 794 | DYLIB_COMPATIBILITY_VERSION = 1; 795 | DYLIB_CURRENT_VERSION = 1; 796 | DYLIB_INSTALL_NAME_BASE = "@rpath"; 797 | INFOPLIST_FILE = "ManualLayout/Info-tvOS.plist"; 798 | INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; 799 | IPHONEOS_DEPLOYMENT_TARGET = 8.0; 800 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 801 | PRODUCT_BUNDLE_IDENTIFIER = com.bsencan.ManualLayout; 802 | PRODUCT_NAME = ManualLayout; 803 | SDKROOT = appletvos; 804 | SKIP_INSTALL = YES; 805 | SWIFT_OPTIMIZATION_LEVEL = "-Onone"; 806 | TARGETED_DEVICE_FAMILY = 3; 807 | TVOS_DEPLOYMENT_TARGET = 9.0; 808 | }; 809 | name = Debug; 810 | }; 811 | FE45006F1BF12E5F0005E270 /* Release */ = { 812 | isa = XCBuildConfiguration; 813 | buildSettings = { 814 | BITCODE_GENERATION_MODE = bitcode; 815 | CLANG_ENABLE_MODULES = YES; 816 | "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; 817 | DEFINES_MODULE = YES; 818 | DYLIB_COMPATIBILITY_VERSION = 1; 819 | DYLIB_CURRENT_VERSION = 1; 820 | DYLIB_INSTALL_NAME_BASE = "@rpath"; 821 | INFOPLIST_FILE = "ManualLayout/Info-tvOS.plist"; 822 | INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; 823 | IPHONEOS_DEPLOYMENT_TARGET = 8.0; 824 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 825 | PRODUCT_BUNDLE_IDENTIFIER = com.bsencan.ManualLayout; 826 | PRODUCT_NAME = ManualLayout; 827 | SDKROOT = appletvos; 828 | SKIP_INSTALL = YES; 829 | TARGETED_DEVICE_FAMILY = 3; 830 | TVOS_DEPLOYMENT_TARGET = 9.0; 831 | }; 832 | name = Release; 833 | }; 834 | /* End XCBuildConfiguration section */ 835 | 836 | /* Begin XCConfigurationList section */ 837 | 5F9134991AC9E1640001DBF8 /* Build configuration list for PBXNativeTarget "SimpleExample" */ = { 838 | isa = XCConfigurationList; 839 | buildConfigurations = ( 840 | 5F91349A1AC9E1640001DBF8 /* Debug */, 841 | 5F91349B1AC9E1640001DBF8 /* Release */, 842 | ); 843 | defaultConfigurationIsVisible = 0; 844 | defaultConfigurationName = Release; 845 | }; 846 | 5F91349C1AC9E1640001DBF8 /* Build configuration list for PBXNativeTarget "SimpleExampleTests" */ = { 847 | isa = XCConfigurationList; 848 | buildConfigurations = ( 849 | 5F91349D1AC9E1640001DBF8 /* Debug */, 850 | 5F91349E1AC9E1640001DBF8 /* Release */, 851 | ); 852 | defaultConfigurationIsVisible = 0; 853 | defaultConfigurationName = Release; 854 | }; 855 | 5FB4CBE31A9BBE7500C2FB4F /* Build configuration list for PBXProject "ManualLayout" */ = { 856 | isa = XCConfigurationList; 857 | buildConfigurations = ( 858 | 5FB4CBFD1A9BBE7500C2FB4F /* Debug */, 859 | 5FB4CBFE1A9BBE7500C2FB4F /* Release */, 860 | ); 861 | defaultConfigurationIsVisible = 0; 862 | defaultConfigurationName = Release; 863 | }; 864 | 5FB4CBFF1A9BBE7500C2FB4F /* Build configuration list for PBXNativeTarget "ManualLayout" */ = { 865 | isa = XCConfigurationList; 866 | buildConfigurations = ( 867 | 5FB4CC001A9BBE7500C2FB4F /* Debug */, 868 | 5FB4CC011A9BBE7500C2FB4F /* Release */, 869 | ); 870 | defaultConfigurationIsVisible = 0; 871 | defaultConfigurationName = Release; 872 | }; 873 | 5FB4CC021A9BBE7500C2FB4F /* Build configuration list for PBXNativeTarget "ManualLayoutTests" */ = { 874 | isa = XCConfigurationList; 875 | buildConfigurations = ( 876 | 5FB4CC031A9BBE7500C2FB4F /* Debug */, 877 | 5FB4CC041A9BBE7500C2FB4F /* Release */, 878 | ); 879 | defaultConfigurationIsVisible = 0; 880 | defaultConfigurationName = Release; 881 | }; 882 | FE45006D1BF12E5F0005E270 /* Build configuration list for PBXNativeTarget "ManualLayout-tvOS" */ = { 883 | isa = XCConfigurationList; 884 | buildConfigurations = ( 885 | FE45006E1BF12E5F0005E270 /* Debug */, 886 | FE45006F1BF12E5F0005E270 /* Release */, 887 | ); 888 | defaultConfigurationIsVisible = 0; 889 | defaultConfigurationName = Release; 890 | }; 891 | /* End XCConfigurationList section */ 892 | }; 893 | rootObject = 5FB4CBE01A9BBE7500C2FB4F /* Project object */; 894 | } 895 | -------------------------------------------------------------------------------- /ManualLayout.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /ManualLayout.xcodeproj/project.xcworkspace/xcshareddata/ManualLayout.xccheckout: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDESourceControlProjectFavoriteDictionaryKey 6 | 7 | IDESourceControlProjectIdentifier 8 | 40BBFAAD-121E-4919-A427-B1BAD98E7C45 9 | IDESourceControlProjectName 10 | ManualLayout 11 | IDESourceControlProjectOriginsDictionary 12 | 13 | 9A55608E5CD4363CECFDC3A8DD4BF9A298F03725 14 | https://github.com/isair/ManualLayout.git 15 | 16 | IDESourceControlProjectPath 17 | ManualLayout.xcodeproj 18 | IDESourceControlProjectRelativeInstallPathDictionary 19 | 20 | 9A55608E5CD4363CECFDC3A8DD4BF9A298F03725 21 | ../.. 22 | 23 | IDESourceControlProjectURL 24 | https://github.com/isair/ManualLayout.git 25 | IDESourceControlProjectVersion 26 | 111 27 | IDESourceControlProjectWCCIdentifier 28 | 9A55608E5CD4363CECFDC3A8DD4BF9A298F03725 29 | IDESourceControlProjectWCConfigurations 30 | 31 | 32 | IDESourceControlRepositoryExtensionIdentifierKey 33 | public.vcs.git 34 | IDESourceControlWCCIdentifierKey 35 | 9A55608E5CD4363CECFDC3A8DD4BF9A298F03725 36 | IDESourceControlWCCName 37 | ManualLayout 38 | 39 | 40 | 41 | 42 | -------------------------------------------------------------------------------- /ManualLayout.xcodeproj/xcshareddata/xcschemes/ManualLayout-tvOS.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 31 | 32 | 33 | 34 | 35 | 36 | 47 | 48 | 54 | 55 | 56 | 57 | 58 | 59 | 65 | 66 | 72 | 73 | 74 | 75 | 77 | 78 | 81 | 82 | 83 | -------------------------------------------------------------------------------- /ManualLayout.xcodeproj/xcshareddata/xcschemes/ManualLayout.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 29 | 35 | 36 | 37 | 38 | 39 | 45 | 46 | 48 | 54 | 55 | 56 | 57 | 58 | 64 | 65 | 66 | 67 | 68 | 69 | 80 | 81 | 87 | 88 | 89 | 90 | 91 | 92 | 98 | 99 | 105 | 106 | 107 | 108 | 110 | 111 | 114 | 115 | 116 | -------------------------------------------------------------------------------- /ManualLayout/CALayer+ManualLayout.swift: -------------------------------------------------------------------------------- 1 | // 2 | // CALayer+ManualLayout.swift 3 | // ManualLayout 4 | // 5 | // Created by Baris Sencan on 23/02/15. 6 | // Copyright (c) 2015 Baris Sencan. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | public extension CALayer { 12 | 13 | // MARK: - Position 14 | 15 | public var origin: CGPoint { 16 | get { 17 | return frame.origin 18 | } 19 | set { 20 | x = newValue.x 21 | y = newValue.y 22 | } 23 | } 24 | 25 | public var x: CGFloat { 26 | get { return frame.x } 27 | set { frame.x = newValue } 28 | } 29 | 30 | public var y: CGFloat { 31 | get { return frame.y } 32 | set { frame.y = newValue } 33 | } 34 | 35 | public var center: CGPoint { 36 | get { return frame.center } 37 | set { frame.center = newValue } 38 | } 39 | 40 | public var centerX: CGFloat { 41 | get { return frame.centerX } 42 | set { frame.centerX = newValue } 43 | } 44 | 45 | public var centerY: CGFloat { 46 | get { return frame.centerY } 47 | set { frame.centerY = newValue } 48 | } 49 | 50 | // MARK: - Size 51 | 52 | public var size: CGSize { 53 | get { 54 | return frame.size 55 | } 56 | set { 57 | width = newValue.width 58 | height = newValue.height 59 | } 60 | } 61 | 62 | public var width: CGFloat { 63 | get { 64 | return frame.size.width 65 | } 66 | set { 67 | frame.size.width = snapToPixel(pointCoordinate: newValue) 68 | } 69 | } 70 | 71 | public var height: CGFloat { 72 | get { 73 | return frame.size.height 74 | } 75 | set { 76 | frame.size.height = snapToPixel(pointCoordinate: newValue) 77 | } 78 | } 79 | 80 | // MARK: - Edges 81 | 82 | public var top: CGFloat { 83 | get { return frame.top } 84 | set { frame.top = newValue } 85 | } 86 | 87 | public var right: CGFloat { 88 | get { return frame.right } 89 | set { frame.right = newValue } 90 | } 91 | 92 | public var bottom: CGFloat { 93 | get { return frame.bottom } 94 | set { frame.bottom = newValue } 95 | } 96 | 97 | public var left: CGFloat { 98 | get { return frame.left } 99 | set { frame.left = newValue } 100 | } 101 | 102 | // MARK: - Alternative Edges 103 | 104 | public var top2: CGFloat { 105 | get { return frame.top2 } 106 | set { frame.top2 = newValue } 107 | } 108 | 109 | public var right2: CGFloat { 110 | get { return frame.right2 } 111 | set { frame.right2 = newValue } 112 | } 113 | 114 | public var bottom2: CGFloat { 115 | get { return frame.bottom2 } 116 | set { frame.bottom2 = newValue } 117 | } 118 | 119 | public var left2: CGFloat { 120 | get { return frame.left2 } 121 | set { frame.left2 = newValue } 122 | } 123 | } 124 | -------------------------------------------------------------------------------- /ManualLayout/CGRect+ManualLayout.swift: -------------------------------------------------------------------------------- 1 | // 2 | // CGRect+ManualLayout.swift 3 | // ManualLayout 4 | // 5 | // Created by Baris Sencan on 30/03/15. 6 | // Copyright (c) 2015 Baris Sencan. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | public extension CGRect { 12 | 13 | // MARK: - Position 14 | 15 | public var x: CGFloat { 16 | get { 17 | return origin.x 18 | } 19 | set { 20 | origin.x = snapToPixel(pointCoordinate: newValue) 21 | } 22 | } 23 | 24 | public var y: CGFloat { 25 | get { 26 | return origin.y 27 | } 28 | set { 29 | origin.y = snapToPixel(pointCoordinate: newValue) 30 | } 31 | } 32 | 33 | public var center: CGPoint { 34 | get { 35 | return CGPoint(x: centerX, y: centerY) 36 | } 37 | set { 38 | centerX = newValue.x 39 | centerY = newValue.y 40 | } 41 | } 42 | 43 | public var centerX: CGFloat { 44 | get { 45 | return origin.x + size.width / 2 46 | } 47 | set { 48 | x = newValue - size.width / 2 49 | } 50 | } 51 | 52 | public var centerY: CGFloat { 53 | get { 54 | return origin.y + size.height / 2 55 | } 56 | set { 57 | y = newValue - size.height / 2 58 | } 59 | } 60 | 61 | // MARK: - Edges 62 | 63 | public var top: CGFloat { 64 | get { 65 | return origin.y 66 | } 67 | set { 68 | y = newValue 69 | } 70 | } 71 | 72 | public var right: CGFloat { 73 | get { 74 | return origin.x + size.width 75 | } 76 | set { 77 | x = newValue - size.width 78 | } 79 | } 80 | 81 | public var bottom: CGFloat { 82 | get { 83 | return origin.y + size.height 84 | } 85 | set { 86 | y = newValue - size.height 87 | } 88 | } 89 | 90 | public var left: CGFloat { 91 | get { 92 | return origin.x 93 | } 94 | set { 95 | x = newValue 96 | } 97 | } 98 | 99 | // MARK: - Alternative Edges 100 | 101 | public var top2: CGFloat { 102 | get { 103 | return origin.y 104 | } 105 | set { 106 | if newValue <= bottom { 107 | size.height += snapToPixel(pointCoordinate: top - newValue) 108 | y = newValue 109 | } else { 110 | // Swap top with bottom. 111 | let newTop = bottom 112 | size.height = snapToPixel(pointCoordinate: newValue - newTop) 113 | y = newTop 114 | } 115 | } 116 | } 117 | 118 | public var right2: CGFloat { 119 | get { 120 | return origin.x + size.width 121 | } 122 | set { 123 | if newValue >= left { 124 | size.width += snapToPixel(pointCoordinate: newValue - right) 125 | } else { 126 | // Swap left with right. 127 | let newRight = left 128 | size.width = snapToPixel(pointCoordinate: newRight - newValue) 129 | x = newValue 130 | } 131 | } 132 | } 133 | 134 | public var bottom2: CGFloat { 135 | get { 136 | return origin.y + size.height 137 | } 138 | set { 139 | if newValue >= top { 140 | size.height += snapToPixel(pointCoordinate: newValue - bottom) 141 | } else { 142 | // Swap bottom with top. 143 | let newBottom = top 144 | size.height = snapToPixel(pointCoordinate: newBottom - newValue) 145 | y = newValue 146 | } 147 | } 148 | } 149 | 150 | public var left2: CGFloat { 151 | get { 152 | return origin.x 153 | } 154 | set { 155 | if newValue <= right { 156 | size.width += snapToPixel(pointCoordinate: left - newValue) 157 | x = newValue 158 | } else { 159 | // Swap right with left. 160 | let newLeft = right 161 | size.width = snapToPixel(pointCoordinate: newValue - newLeft) 162 | x = newLeft 163 | } 164 | } 165 | } 166 | } 167 | -------------------------------------------------------------------------------- /ManualLayout/HelperFunctions.swift: -------------------------------------------------------------------------------- 1 | // 2 | // HelperFunctions.swift 3 | // ManualLayout 4 | // 5 | // Created by Baris Sencan on 26/02/15. 6 | // Copyright (c) 2015 Baris Sencan. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | internal func snapToPixel(pointCoordinate coordinate: CGFloat) -> CGFloat { 12 | let screenScale = UIScreen.main.scale 13 | return round(coordinate * screenScale) / screenScale 14 | } 15 | 16 | //MARK: - Insetting 17 | 18 | public func inset(_ view: UIView, amount: CGFloat) -> CGRect { 19 | return inset(view.frame, amount: amount) 20 | } 21 | 22 | public func inset(_ layer: CALayer, amount: CGFloat) -> CGRect { 23 | return inset(layer.frame, amount: amount) 24 | } 25 | 26 | public func inset(_ rect: CGRect, amount: CGFloat) -> CGRect { 27 | return rect.insetBy(dx: amount, dy: amount) 28 | } 29 | 30 | public func inset(_ view: UIView, dx: CGFloat, dy: CGFloat) -> CGRect { 31 | return inset(view.frame, dx: dx, dy: dy) 32 | } 33 | 34 | public func inset(_ layer: CALayer, dx: CGFloat, dy: CGFloat) -> CGRect { 35 | return inset(layer.frame, dx: dx, dy: dy) 36 | } 37 | 38 | public func inset(_ rect: CGRect, dx: CGFloat, dy: CGFloat) -> CGRect { 39 | return rect.insetBy(dx: dx, dy: dy) 40 | } 41 | 42 | public func inset(_ view: UIView, top: CGFloat, left: CGFloat, bottom: CGFloat, right: CGFloat) -> CGRect { 43 | return inset(view.frame, top: top, left: left, bottom: bottom, right: right) 44 | } 45 | 46 | public func inset(_ layer: CALayer, top: CGFloat, left: CGFloat, bottom: CGFloat, right: CGFloat) -> CGRect { 47 | return inset(layer.frame, top: top, left: left, bottom: bottom, right: right) 48 | } 49 | 50 | public func inset(_ rect: CGRect, top: CGFloat, left: CGFloat, bottom: CGFloat, right: CGFloat) -> CGRect { 51 | return CGRect( 52 | origin: offset(rect.origin, dx: left, dy: top), 53 | size: inset(rect.size, top: top, left: left, bottom: bottom, right: right)) 54 | } 55 | 56 | public func inset(_ size: CGSize, amount: CGFloat) -> CGSize { 57 | return inset(size, dx: amount, dy: amount) 58 | } 59 | 60 | public func inset(_ size: CGSize, dx: CGFloat, dy: CGFloat) -> CGSize { 61 | return inset(size, top: dy, left: dx, bottom: dy, right: dx) 62 | } 63 | 64 | public func inset(_ size: CGSize, top: CGFloat, left: CGFloat, bottom: CGFloat, right: CGFloat) -> CGSize { 65 | return CGSize( 66 | width: size.width - left - right, 67 | height: size.height - top - bottom) 68 | } 69 | 70 | // MARK: - Offsetting 71 | 72 | public func offset(_ view: UIView, amount: CGFloat) -> CGRect { 73 | return offset(view.frame, amount: amount) 74 | } 75 | 76 | public func offset(_ layer: CALayer, amount: CGFloat) -> CGRect { 77 | return offset(layer.frame, amount: amount) 78 | } 79 | 80 | public func offset(_ rect: CGRect, amount: CGFloat) -> CGRect { 81 | return rect.offsetBy(dx: amount, dy: amount) 82 | } 83 | 84 | public func offset(_ view: UIView, dx: CGFloat, dy: CGFloat) -> CGRect { 85 | return offset(view.frame, dx: dx, dy: dy) 86 | } 87 | 88 | public func offset(_ layer: CALayer, dx: CGFloat, dy: CGFloat) -> CGRect { 89 | return offset(layer.frame, dx: dx, dy: dy) 90 | } 91 | 92 | public func offset(_ rect: CGRect, dx: CGFloat, dy: CGFloat) -> CGRect { 93 | return rect.offsetBy(dx: dx, dy: dy) 94 | } 95 | 96 | public func offset(_ point: CGPoint, amount: CGFloat) -> CGPoint { 97 | return offset(point, dx: amount, dy: amount) 98 | } 99 | 100 | public func offset(_ point: CGPoint, dx: CGFloat, dy: CGFloat) -> CGPoint { 101 | return CGPoint(x: point.x + dx, y: point.y + dy) 102 | } 103 | -------------------------------------------------------------------------------- /ManualLayout/Info-tvOS.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 | 1.3.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | $(CURRENT_PROJECT_VERSION) 23 | NSPrincipalClass 24 | 25 | UIRequiredDeviceCapabilities 26 | 27 | arm64 28 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /ManualLayout/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 | 1.3.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | $(CURRENT_PROJECT_VERSION) 23 | NSPrincipalClass 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /ManualLayout/ManualLayout.h: -------------------------------------------------------------------------------- 1 | // 2 | // ManualLayout.h 3 | // ManualLayout 4 | // 5 | // Created by Baris Sencan on 23/02/15. 6 | // Copyright (c) 2015 Baris Sencan. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | //! Project version number for ManualLayout. 12 | FOUNDATION_EXPORT double ManualLayoutVersionNumber; 13 | 14 | //! Project version string for ManualLayout. 15 | FOUNDATION_EXPORT const unsigned char ManualLayoutVersionString[]; -------------------------------------------------------------------------------- /ManualLayout/SmartAssign.swift: -------------------------------------------------------------------------------- 1 | // 2 | // SmartAssign.swift 3 | // ManualLayout 4 | // 5 | // Created by Baris Sencan on 26/02/15. 6 | // Copyright (c) 2015 Baris Sencan. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | precedencegroup SmartAssignment { 12 | assignment: true 13 | } 14 | 15 | infix operator =~ : SmartAssignment 16 | 17 | @discardableResult 18 | public func =~ (point: inout CGPoint, pointTuple: (CGFloat, CGFloat)) -> CGPoint { 19 | point = CGPoint(x: pointTuple.0, y: pointTuple.1) 20 | return point 21 | } 22 | 23 | @discardableResult 24 | public func =~ (size: inout CGSize, sizeTuple: (CGFloat, CGFloat)) -> CGSize { 25 | size = CGSize(width: sizeTuple.0, height: sizeTuple.1) 26 | return size 27 | } 28 | 29 | @discardableResult 30 | public func =~ (rect: inout CGRect, rectTuple: (CGFloat, CGFloat, CGFloat, CGFloat)) -> CGRect { 31 | rect = CGRect(x: rectTuple.0, y: rectTuple.1, width: rectTuple.2, height: rectTuple.3) 32 | return rect 33 | } 34 | -------------------------------------------------------------------------------- /ManualLayout/UIScrollView+ManualLayout.swift: -------------------------------------------------------------------------------- 1 | // 2 | // UIScrollView+ManualLayout.swift 3 | // ManualLayout 4 | // 5 | // Created by Baris Sencan on 06/03/15. 6 | // Copyright (c) 2015 Baris Sencan. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | public extension UIScrollView { 12 | 13 | // MARK: - Content Size 14 | 15 | public var contentWidth: CGFloat { 16 | get { 17 | return contentSize.width 18 | } 19 | set { 20 | contentSize.width = snapToPixel(pointCoordinate: newValue) 21 | } 22 | } 23 | 24 | public var contentHeight: CGFloat { 25 | get { 26 | return contentSize.height 27 | } 28 | set { 29 | contentSize.height = snapToPixel(pointCoordinate: newValue) 30 | } 31 | } 32 | 33 | // MARK: - Content Edges (For Convenience) 34 | 35 | public var contentTop: CGFloat { 36 | return 0 37 | } 38 | 39 | public var contentLeft: CGFloat { 40 | return 0 41 | } 42 | 43 | public var contentBottom: CGFloat { 44 | get { 45 | return contentHeight 46 | } 47 | set { 48 | contentHeight = newValue 49 | } 50 | } 51 | 52 | public var contentRight: CGFloat { 53 | get { 54 | return contentWidth 55 | } 56 | set { 57 | contentWidth = newValue 58 | } 59 | } 60 | 61 | // MARK: - Viewport Edges 62 | 63 | public var viewportTop: CGFloat { 64 | get { 65 | return contentOffset.y 66 | } 67 | set { 68 | contentOffset.y = snapToPixel(pointCoordinate: newValue) 69 | } 70 | } 71 | 72 | public var viewportLeft: CGFloat { 73 | get { 74 | return contentOffset.x 75 | } 76 | set { 77 | contentOffset.x = snapToPixel(pointCoordinate: newValue) 78 | } 79 | } 80 | 81 | public var viewportBottom: CGFloat { 82 | get { 83 | return contentOffset.y + height 84 | } 85 | set { 86 | contentOffset.y = snapToPixel(pointCoordinate: newValue - height) 87 | } 88 | } 89 | 90 | public var viewportRight: CGFloat { 91 | get { 92 | return contentOffset.x + width 93 | } 94 | set { 95 | contentOffset.x = snapToPixel(pointCoordinate: newValue - width) 96 | } 97 | } 98 | } 99 | -------------------------------------------------------------------------------- /ManualLayout/UIView+ManualLayout.swift: -------------------------------------------------------------------------------- 1 | // 2 | // UIView+ManualLayout.swift 3 | // ManualLayout 4 | // 5 | // Created by Baris Sencan on 23/02/15. 6 | // Copyright (c) 2015 Baris Sencan. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | // I wish there was an easier way to do this in Swift. 12 | public extension UIView { 13 | 14 | // MARK: - Position 15 | 16 | public var origin: CGPoint { 17 | get { return layer.origin } 18 | set { layer.origin = newValue } 19 | } 20 | 21 | public var x: CGFloat { 22 | get { return layer.x } 23 | set { layer.x = newValue } 24 | } 25 | 26 | public var y: CGFloat { 27 | get { return layer.y } 28 | set { layer.y = newValue } 29 | } 30 | 31 | public var centerX: CGFloat { 32 | get { return layer.centerX } 33 | set { layer.centerX = newValue } 34 | } 35 | 36 | public var centerY: CGFloat { 37 | get { return layer.centerY } 38 | set { layer.centerY = newValue } 39 | } 40 | 41 | // MARK: - Size 42 | 43 | public var size: CGSize { 44 | get { return layer.size } 45 | set { layer.size = newValue } 46 | } 47 | 48 | public var width: CGFloat { 49 | get { return layer.width } 50 | set { layer.width = newValue } 51 | } 52 | 53 | public var height: CGFloat { 54 | get { return layer.height } 55 | set { layer.height = newValue } 56 | } 57 | 58 | // MARK: - Edges 59 | 60 | public var top: CGFloat { 61 | get { return layer.top } 62 | set { layer.top = newValue } 63 | } 64 | 65 | public var right: CGFloat { 66 | get { return layer.right } 67 | set { layer.right = newValue } 68 | } 69 | 70 | public var bottom: CGFloat { 71 | get { return layer.bottom } 72 | set { layer.bottom = newValue } 73 | } 74 | 75 | public var left: CGFloat { 76 | get { return layer.left } 77 | set { layer.left = newValue } 78 | } 79 | 80 | // MARK: - Alternative Edges 81 | 82 | public var top2: CGFloat { 83 | get { return layer.top2 } 84 | set { layer.top2 = newValue } 85 | } 86 | 87 | public var right2: CGFloat { 88 | get { return layer.right2 } 89 | set { layer.right2 = newValue } 90 | } 91 | 92 | public var bottom2: CGFloat { 93 | get { return layer.bottom2 } 94 | set { layer.bottom2 = newValue } 95 | } 96 | 97 | public var left2: CGFloat { 98 | get { return layer.left2 } 99 | set { layer.left2 = newValue } 100 | } 101 | 102 | // MARK: - Automatic Sizing 103 | 104 | @discardableResult 105 | public func sizeToFit(_ width: CGFloat, _ height: CGFloat) -> CGSize { 106 | return sizeToFit(CGSize(width: width, height: height)) 107 | } 108 | 109 | @discardableResult 110 | public func sizeToFit(_ constrainedSize: CGSize) -> CGSize { 111 | var newSize = sizeThatFits(constrainedSize) 112 | newSize.width = min(newSize.width, constrainedSize.width) 113 | newSize.height = min(newSize.height, constrainedSize.height) 114 | size = newSize 115 | return newSize 116 | } 117 | } 118 | -------------------------------------------------------------------------------- /ManualLayout/UIViewController+ManualLayout.swift: -------------------------------------------------------------------------------- 1 | // 2 | // UIViewController+ManualLayout.swift 3 | // ManualLayout 4 | // 5 | // Created by Baris Sencan on 25/02/15. 6 | // Copyright (c) 2015 Baris Sencan. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | public extension UIViewController { 12 | 13 | public var bounds: CGRect { 14 | return view.bounds 15 | } 16 | 17 | // MARK: - Center 18 | 19 | public var center: CGPoint { 20 | return view.center 21 | } 22 | 23 | public var centerX: CGFloat { 24 | return view.centerX 25 | } 26 | 27 | public var centerY: CGFloat { 28 | return view.centerY 29 | } 30 | 31 | // MARK: - Size 32 | 33 | public var size: CGSize { 34 | return view.size 35 | } 36 | 37 | public var width: CGFloat { 38 | return view.width 39 | } 40 | 41 | public var height: CGFloat { 42 | return view.height 43 | } 44 | 45 | // MARK: - Edges 46 | 47 | public var top: CGFloat { 48 | return topLayoutGuide.length 49 | } 50 | 51 | public var right: CGFloat { 52 | return view.width 53 | } 54 | 55 | public var bottom: CGFloat { 56 | return view.height - bottomLayoutGuide.length 57 | } 58 | 59 | public var left: CGFloat { 60 | return 0 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /ManualLayoutTests/HelperFunctionTests.swift: -------------------------------------------------------------------------------- 1 | // 2 | // HelperFunctionTests.swift 3 | // ManualLayout 4 | // 5 | // Created by Baris Sencan on 26/02/15. 6 | // Copyright (c) 2015 Baris Sencan. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | import XCTest 11 | import ManualLayout 12 | 13 | class HelperFunctionTests: XCTestCase { 14 | var view = UIView(frame: .zero) 15 | let defaultFrame = CGRect(x: 1, y: 3, width: 6, height: 8) 16 | 17 | override func setUp() { 18 | view.frame = defaultFrame 19 | } 20 | 21 | func testInsetRectSingleArg() { 22 | view.frame = inset(view, amount: 1) 23 | XCTAssertEqual( 24 | view.frame, 25 | CGRect(x: 2, y: 4, width: 4, height: 6), 26 | "insetting with amount should inset correctly") 27 | } 28 | 29 | func testInsetRectTwoArg() { 30 | view.frame = inset(view, dx: 1, dy: 2) 31 | XCTAssertEqual( 32 | view.frame, 33 | CGRect(x: 2, y: 5, width: 4, height: 4), 34 | "insetting with dx and dy should inset correctly") 35 | } 36 | 37 | func testInsetRectFourArg() { 38 | view.frame = inset(view, top: 1, left: 2, bottom: 3, right: 4) 39 | XCTAssertEqual( 40 | view.frame, 41 | CGRect(x: 3, y: 4, width: 0, height: 4), 42 | "insetting with four arguments should inset correctly") 43 | } 44 | 45 | func testInsetSizeSingleArg() { 46 | let size = inset(view.frame.size, amount: 1) 47 | XCTAssertEqual( 48 | size, 49 | CGSize(width: 4, height: 6), 50 | "insetting size with amount should inset correctly") 51 | } 52 | 53 | func testInsetSizeTwoArg() { 54 | let size = inset(view.frame.size, dx: 1, dy: 2) 55 | XCTAssertEqual( 56 | size, 57 | CGSize(width: 4, height: 4), 58 | "insetting size with two arguments should inset correctly") 59 | } 60 | 61 | func testInsetSizeFourArg() { 62 | let size = inset(view.frame.size, top: 1, left: 2, bottom: 3, right: 4) 63 | XCTAssertEqual( 64 | size, 65 | CGSize(width: 0, height: 4), 66 | "insetting size with four arguments should inset correctly") 67 | } 68 | 69 | func testOffsetSingleArg() { 70 | view.frame = offset(view, amount: 1) 71 | XCTAssertEqual( 72 | view.frame, 73 | CGRect(x: 2, y: 4, width: 6, height: 8), 74 | "offsetting with amount should offset correctly") 75 | } 76 | 77 | func testOffsetTwoArg() { 78 | view.frame = offset(view, dx: 1, dy: 2) 79 | XCTAssertEqual( 80 | view.frame, 81 | CGRect(x: 2, y: 5, width: 6, height: 8), 82 | "offsetting with dx and dy should offset correctly") 83 | } 84 | 85 | func testOffsetPointSingleArg() { 86 | let origin = offset(view.frame.origin, amount: 1) 87 | XCTAssertEqual( 88 | origin, 89 | CGPoint(x: 2, y: 4), 90 | "offsetting origin with amount should offset correctly") 91 | } 92 | 93 | func testOffsetPointTwoArg() { 94 | let origin = offset(view.frame.origin, dx: 1, dy: 2) 95 | XCTAssertEqual( 96 | origin, 97 | CGPoint(x: 2, y: 5), 98 | "offsetting origin with dx and dy should offset correctly") 99 | } 100 | } -------------------------------------------------------------------------------- /ManualLayoutTests/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 | -------------------------------------------------------------------------------- /ManualLayoutTests/SmartAssignTests.swift: -------------------------------------------------------------------------------- 1 | // 2 | // SmartAssignTests.swift 3 | // ManualLayout 4 | // 5 | // Created by Baris Sencan on 26/02/15. 6 | // Copyright (c) 2015 Baris Sencan. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | import XCTest 11 | import ManualLayout 12 | 13 | class SmartAssignTests: XCTestCase { 14 | var view = UIView(frame: .zero) 15 | 16 | override func setUp() { 17 | view.frame = .zero 18 | } 19 | 20 | func testPointAssignment() { 21 | view.origin =~ (1, 3) 22 | XCTAssertEqual(view.origin, CGPoint(x: 1, y: 3), "origin should be at (1, 3)") 23 | } 24 | 25 | func testSizeAssignment() { 26 | view.size =~ (5, 7) 27 | XCTAssertEqual(view.size, CGSize(width: 5, height: 7), "size should be (5, 7)") 28 | } 29 | 30 | func testRectAssignment() { 31 | view.frame =~ (1, 3, 5, 7) 32 | XCTAssertEqual( 33 | view.frame, 34 | CGRect(x: 1, y: 3, width: 5, height: 7), 35 | "frame should be at (1, 3) and of size (5, 7)") 36 | } 37 | } -------------------------------------------------------------------------------- /ManualLayoutTests/UIScrollViewManualLayoutTests.swift: -------------------------------------------------------------------------------- 1 | // 2 | // UIScrollViewManualLayoutTests.swift 3 | // ManualLayout 4 | // 5 | // Created by Baris Sencan on 06/03/15. 6 | // Copyright (c) 2015 Baris Sencan. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | import XCTest 11 | import ManualLayout 12 | 13 | internal final class UIScrollViewManualLayoutTests: XCTestCase { 14 | let defaultContentSize = CGSize(width: 20, height: 20) 15 | let defaultContentOffset = CGPoint(x: 10, y: 10) 16 | let scrollView = UIScrollView(frame: CGRect(x: 0, y: 0, width: 10, height: 10)) 17 | 18 | override func setUp() { 19 | scrollView.contentSize = defaultContentSize 20 | scrollView.contentOffset = defaultContentOffset 21 | } 22 | 23 | func testContentWidth() { 24 | XCTAssertEqual( 25 | scrollView.contentWidth, 26 | scrollView.contentSize.width, 27 | "contentWidth should be equal to contentSize.width") 28 | scrollView.contentWidth = 30 29 | XCTAssertEqual( 30 | scrollView.contentSize, 31 | CGSize(width: 30, height: defaultContentSize.height), 32 | "Setting contentWidth should modify contentSize correctly") 33 | } 34 | 35 | func testContentHeight() { 36 | XCTAssertEqual( 37 | scrollView.contentHeight, 38 | scrollView.contentSize.height, 39 | "contentHeight should be equal to contentSize.height") 40 | scrollView.contentHeight = 30 41 | XCTAssertEqual( 42 | scrollView.contentSize, 43 | CGSize(width: defaultContentSize.width, height: 30), 44 | "Setting contentHeight should modify contentSize correctly") 45 | } 46 | 47 | func testContentTop() { 48 | XCTAssert( 49 | scrollView.contentTop == 0, 50 | "contentTop should be equal to 0") 51 | } 52 | 53 | func testContentLeft() { 54 | XCTAssert( 55 | scrollView.contentLeft == 0, 56 | "contentLeft should be equal to 0") 57 | } 58 | 59 | func testContentBottom() { 60 | XCTAssertEqual( 61 | scrollView.contentBottom, 62 | scrollView.contentSize.height, 63 | "contentBottom should be equal to contentSize.height") 64 | scrollView.contentBottom = 30 65 | XCTAssertEqual( 66 | scrollView.contentSize, 67 | CGSize(width: defaultContentSize.width, height: 30), 68 | "Setting contentBottom should modify contentSize correctly") 69 | } 70 | 71 | func testContentRight() { 72 | XCTAssertEqual( 73 | scrollView.contentRight, 74 | scrollView.contentSize.width, 75 | "contentRight should be equal to contentSize.width") 76 | scrollView.contentRight = 30 77 | XCTAssertEqual( 78 | scrollView.contentSize, 79 | CGSize(width: 30, height: defaultContentSize.height), 80 | "Setting contentRight should modify contentSize correctly") 81 | } 82 | 83 | func testViewportTop() { 84 | XCTAssertEqual( 85 | scrollView.viewportTop, 86 | scrollView.contentOffset.y, 87 | "viewportTop should be equal to contentOffset.y") 88 | scrollView.viewportTop = 0 89 | XCTAssertEqual( 90 | scrollView.contentOffset, 91 | CGPoint(x: defaultContentOffset.x, y: 0), 92 | "Setting viewportTop should modify contentOffset correctly") 93 | } 94 | 95 | func testViewportLeft() { 96 | XCTAssertEqual( 97 | scrollView.viewportLeft, 98 | scrollView.contentOffset.x, 99 | "viewportLeft should be equal to contentOffset.x") 100 | scrollView.viewportLeft = 0 101 | XCTAssertEqual( 102 | scrollView.contentOffset, 103 | CGPoint(x: 0, y: defaultContentOffset.y), 104 | "Setting viewportLeft should modify contentOffset correctly") 105 | } 106 | 107 | func testViewportBottom() { 108 | XCTAssertEqual( 109 | scrollView.viewportBottom, 110 | scrollView.contentOffset.y + scrollView.frame.size.height, 111 | "viewportBottom should be equal to contentOffset.y + height") 112 | scrollView.viewportBottom = 10 113 | XCTAssertEqual( 114 | scrollView.contentOffset, 115 | CGPoint(x: defaultContentOffset.x, y: 0), 116 | "Setting viewportBottom should modify contentOffset correctly") 117 | } 118 | 119 | func testViewportRight() { 120 | XCTAssertEqual( 121 | scrollView.viewportRight, 122 | scrollView.contentOffset.x + scrollView.frame.size.width, 123 | "viewportRight should be equal to contentOffset.x + width") 124 | scrollView.viewportRight = 10 125 | XCTAssertEqual( 126 | scrollView.contentOffset, 127 | CGPoint(x: 0, y: defaultContentOffset.y), 128 | "Setting viewportRight should modify contentOffset correctly") 129 | } 130 | } -------------------------------------------------------------------------------- /ManualLayoutTests/UIViewManualLayoutTests.swift: -------------------------------------------------------------------------------- 1 | // 2 | // UIViewManualLayoutTests.swift 3 | // ManualLayout 4 | // 5 | // Created by Baris Sencan on 24/02/15. 6 | // Copyright (c) 2015 Baris Sencan. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | import XCTest 11 | import ManualLayout 12 | 13 | class UIViewManualLayoutTests: XCTestCase { 14 | let view = UIView(frame: .zero) 15 | let defaultFrame = CGRect(x: 1, y: 3, width: 6, height: 8) 16 | 17 | override func setUp() { 18 | view.frame = defaultFrame 19 | } 20 | 21 | func testOrigin() { 22 | let newOrigin = CGPoint(x: 10, y: 10) 23 | view.origin = newOrigin 24 | XCTAssertEqual( 25 | view.frame.origin, 26 | newOrigin, 27 | "origin changes should modify frame origin") 28 | XCTAssertEqual( 29 | view.frame.size, 30 | defaultFrame.size, 31 | "origin changes should not modify frame size") 32 | } 33 | 34 | func testX() { 35 | view.x = 10 36 | XCTAssertEqual( 37 | view.frame.origin, 38 | CGPoint(x: 10, y: defaultFrame.origin.y), 39 | "x changes should just modify frame x") 40 | XCTAssertEqual( 41 | view.frame.size, 42 | defaultFrame.size, 43 | "x changes should not modify frame size") 44 | } 45 | 46 | func testY() { 47 | view.y = 10 48 | XCTAssertEqual( 49 | view.frame.origin, 50 | CGPoint(x: defaultFrame.origin.x, y: 10), 51 | "y changes should just modify frame y") 52 | XCTAssertEqual( 53 | view.frame.size, 54 | defaultFrame.size, 55 | "y changes should not modify frame size") 56 | } 57 | 58 | func testCenter() { 59 | view.layer.center = CGPoint(x: 10, y: 10) 60 | XCTAssertEqual( 61 | view.frame.origin, 62 | CGPoint(x: 7, y: 6), 63 | "center changes should center frame") 64 | XCTAssertEqual( 65 | view.frame.size, 66 | defaultFrame.size, 67 | "center changes should not modify frame size") 68 | } 69 | 70 | func testCenterX() { 71 | view.centerX = 10 72 | XCTAssertEqual( 73 | view.frame.origin, 74 | CGPoint(x: 7, y: defaultFrame.origin.y), 75 | "centerX changes should center frame") 76 | XCTAssertEqual( 77 | view.frame.size, 78 | defaultFrame.size, 79 | "centerX changes should not modify frame size") 80 | } 81 | 82 | func testCenterY() { 83 | view.centerY = 10 84 | XCTAssertEqual( 85 | view.frame.origin, 86 | CGPoint(x: defaultFrame.origin.x, y: 6), 87 | "centerY changes should center frame") 88 | XCTAssertEqual( 89 | view.frame.size, 90 | defaultFrame.size, 91 | "centerY changes should not modify frame size") 92 | } 93 | 94 | func testSize() { 95 | view.size = .zero 96 | XCTAssertEqual( 97 | view.frame.origin, 98 | defaultFrame.origin, 99 | "size changes should not modify frame origin") 100 | XCTAssertEqual( 101 | view.frame.size, 102 | .zero, 103 | "size changes should modify frame size") 104 | } 105 | 106 | func testWidth() { 107 | view.width = 10 108 | XCTAssertEqual( 109 | view.frame.origin, 110 | defaultFrame.origin, 111 | "width changes should not modify frame origin") 112 | XCTAssertEqual( 113 | view.frame.size, 114 | CGSize(width: 10, height: defaultFrame.size.height), 115 | "width changes should just modify frame width") 116 | } 117 | 118 | func testHeight() { 119 | view.height = 10 120 | XCTAssertEqual( 121 | view.frame.origin, 122 | defaultFrame.origin, 123 | "height changes should not modify frame origin") 124 | XCTAssertEqual( 125 | view.frame.size, 126 | CGSize(width: defaultFrame.size.width, height: 10), 127 | "height changes should just modify frame height") 128 | } 129 | 130 | func testTop() { 131 | view.top = 10 132 | XCTAssertEqual( 133 | view.frame.origin, 134 | CGPoint(x: defaultFrame.origin.x, y: 10), 135 | "top changes should just modify frame y") 136 | XCTAssertEqual( 137 | view.frame.size, 138 | defaultFrame.size, 139 | "top changes should not modify frame size") 140 | } 141 | 142 | func testRight() { 143 | view.right = 10 144 | XCTAssertEqual( 145 | view.frame.origin, 146 | CGPoint(x: 10 - defaultFrame.size.width, y: defaultFrame.origin.y), 147 | "right changes should just modify frame x") 148 | XCTAssertEqual( 149 | view.frame.size, 150 | defaultFrame.size, 151 | "right changes should not modify frame size") 152 | } 153 | 154 | func testBottom() { 155 | view.bottom = 10 156 | XCTAssertEqual( 157 | view.frame.origin, 158 | CGPoint(x: defaultFrame.origin.x, y: 10 - defaultFrame.size.height), 159 | "bottom changes should just modify frame y") 160 | XCTAssertEqual( 161 | view.frame.size, 162 | defaultFrame.size, 163 | "bottom changes should not modify frame size") 164 | } 165 | 166 | func testLeft() { 167 | view.left = 10 168 | XCTAssertEqual( 169 | view.frame.origin, 170 | CGPoint(x: 10, y: defaultFrame.origin.y), 171 | "left changes should just modify frame x") 172 | XCTAssertEqual( 173 | view.frame.size, 174 | defaultFrame.size, 175 | "left changes should not modify frame size") 176 | } 177 | 178 | func testTop2() { 179 | view.top2 = 5 180 | XCTAssertEqual( 181 | view.frame.origin, 182 | CGPoint(x: defaultFrame.origin.x, y: 5), 183 | "top2 changes without a swap should just modify frame y") 184 | XCTAssertEqual( 185 | view.frame.size, 186 | CGSize(width: defaultFrame.size.width, height: 6), 187 | "top2 changes without a swap should modify frame size") 188 | // TODO: Test swap behavior. 189 | } 190 | 191 | func testRight2() { 192 | view.right2 = 5 193 | XCTAssertEqual( 194 | view.frame.origin, 195 | defaultFrame.origin, 196 | "right2 changes without a swap should not modify frame origin") 197 | XCTAssertEqual( 198 | view.frame.size, 199 | CGSize(width: 4, height: defaultFrame.size.height), 200 | "right2 changes without a swap should modify frame size") 201 | // TODO: Test swap behavior. 202 | } 203 | 204 | func testBottom2() { 205 | view.bottom2 = 5 206 | XCTAssertEqual( 207 | view.frame.origin, 208 | defaultFrame.origin, 209 | "bottom2 changes without a swap should not modify frame origin") 210 | XCTAssertEqual( 211 | view.frame.size, 212 | CGSize(width: defaultFrame.size.width, height: 2), 213 | "bottom2 changes without a swap should modify frame size") 214 | // TODO: Test swap behavior. 215 | } 216 | 217 | func testLeft2() { 218 | view.left2 = 5 219 | XCTAssertEqual( 220 | view.frame.origin, 221 | CGPoint(x: 5, y: defaultFrame.origin.y), 222 | "left2 changes without a swap should just modify frame x") 223 | XCTAssertEqual( 224 | view.frame.size, 225 | CGSize(width: 2, height: defaultFrame.size.height), 226 | "left2 changes without a swap should modify frame size") 227 | // TODO: Test swap behavior. 228 | } 229 | 230 | func testSizeToFit() { 231 | let containerView = UIView(frame: CGRect(x: 0, y: 0, width: 20, height: 200)) 232 | let label = UILabel(frame: .zero) 233 | label.text = "lorem ipsum dolor sit amet" 234 | label.numberOfLines = 5 235 | containerView.addSubview(label) 236 | label.sizeToFit(containerView.frame.size) 237 | XCTAssert( 238 | label.frame.size.height > 20 && label.frame.size.width <= 20, 239 | "sizeToFit should size the view to fit given constrained size") 240 | label.numberOfLines = 1 241 | label.sizeToFit(containerView.frame.size) 242 | XCTAssert( 243 | label.frame.size.height > 20 && label.frame.size.width <= 20, 244 | "sizeToFit should size the view to fit given constrained size") 245 | } 246 | } 247 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ManualLayout [![CocoaPods](https://img.shields.io/cocoapods/l/ManualLayout.svg)](https://github.com/isair/ManualLayout/blob/master/LICENSE) ![CocoaPods](https://img.shields.io/cocoapods/p/ManualLayout.svg) 2 | ----- 3 | 4 | [![Build Status](https://travis-ci.org/isair/ManualLayout.svg)](https://travis-ci.org/isair/ManualLayout) 5 | [![CocoaPods](https://img.shields.io/cocoapods/v/ManualLayout.svg)](https://cocoapods.org/pods/ManualLayout) 6 | [![Gitter](https://badges.gitter.im/JOINCHAT.svg)](https://gitter.im/isair/ManualLayout?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) 7 | 8 | 9 | Sponsor 10 | 11 | 12 | # Table of Contents 13 | 14 | 1. [Installation](#installation) 15 | 2. [Usage](#usage) 16 | 3. [API Cheat Sheet](#api-cheat-sheet) 17 | 18 | # Installation 19 | 20 | ### [Carthage](https://github.com/Carthage/Carthage#installing-carthage) 21 | 22 | Add the following line to your [Cartfile](https://github.com/Carthage/Carthage/blob/master/Documentation/Artifacts.md#cartfile). 23 | 24 | ``` 25 | github "isair/ManualLayout" 26 | ``` 27 | 28 | Then do `carthage update`. After that, add the framework to your project. 29 | 30 | ### [CocoaPods](https://github.com/CocoaPods/CocoaPods) 31 | 32 | Add the following line in your `Podfile`. 33 | 34 | ``` 35 | pod "ManualLayout" 36 | ``` 37 | 38 | # Usage 39 | 40 | Just `import ManualLayout` in your code and use the methods and properties provided by the library to layout your views. You can check out the cheat sheet below for a compact list of everything. There are also [example projects](https://github.com/isair/ManualLayout/tree/master/Examples) to get you started. 41 | 42 | 43 | # API Cheat Sheet 44 | 45 | ### Smart Assign Operator 46 | 47 | The smart assign operator `=~` has only one job; to make your life easier. 48 | 49 | ```swift 50 | someView.origin =~ (0, 20) 51 | anotherView.size =~ (100, 100) 52 | yetAnotherView.frame =~ (0, 120, view.width, 100) 53 | ``` 54 | 55 | ### CGRect/CALayer/UIView Properties 56 | 57 | ```swift 58 | // For fast positioning. 59 | var origin: CGPoint 60 | var x: CGFloat 61 | var y: CGFloat 62 | var center: CGPoint 63 | var centerX: CGFloat 64 | var centerY: CGFloat 65 | var top: CGFloat 66 | var right: CGFloat 67 | var bottom: CGFloat 68 | var left: CGFloat 69 | 70 | // For fast sizing. 71 | var size: CGSize 72 | var width: CGFloat 73 | var height: CGFloat 74 | 75 | // Alternate edges. Their names may change in the near future. 76 | var top2: CGFloat 77 | var right2: CGFloat 78 | var bottom2: CGFloat 79 | var left2: CGFloat 80 | ``` 81 | 82 | The difference between alternate edges and normal edges require a bit of explaining. Imagine we have a view at position (0, 0) of size (100, 100) named *myView*. If we do `myView.right = 200`, then its position is now (100, 0) and its size remains unchaged. However, back when our view was located at (0, 0), if we had done `myView.right2 = 200`, then *myView* would have still been at (0, 0) but would have had a size of (200, 100). 83 | 84 | So basically, *setting a normal edge's position drags the whole view along with that edge but setting an alternative edge's position drags just that edge*. And don't worry if you, for example, try to drag a left edge past its view's right edge. Edge swapping is done automatically so you don't have to worry about it. 85 | 86 | ### UIView Methods 87 | 88 | Just one method with two variants for now, and those are used for easy size calculations. 89 | 90 | ```swift 91 | func sizeToFit(width: CGFloat, height: CGFloat) -> CGSize 92 | func sizeToFit(constrainedSize: CGSize) -> CGSize 93 | ``` 94 | 95 | So let's say that you have a label inside a view and you want to lay it out with an inset of 4 points on all sides, you could easily do the following: 96 | 97 | ```swift 98 | myLabel.sizeToFit(inset(myView.size, 4)) 99 | myLabel.origin =~ (4, 4) 100 | ``` 101 | 102 | Done! 103 | 104 | ### UIScrollView Properties 105 | 106 | ```swift 107 | var contentWidth: CGFloat 108 | var contentHeight: CGFloat 109 | 110 | var contentTop: CGFloat // Always equal to 0. Read-only. 111 | var contentLeft: CGFloat // Always equal to 0. Read-only. 112 | var contentBottom: CGFloat // contentHeight alias. 113 | var contentRight: CGFloat // contentWidth alias. 114 | 115 | var viewportTop: CGFloat // contentOffset.y alias. 116 | var viewportLeft: CGFloat // contentOffset.x alias. 117 | var viewportBottom: CGFloat // conentOffset.y + view height 118 | var viewportRight: CGFloat // contentOffset.x + view width 119 | ``` 120 | 121 | ### UIViewController Properties 122 | 123 | All UIViewController properties are read only. They offer easy read access to a controller's view's properties. 124 | 125 | ```swift 126 | var bounds: CGRect 127 | 128 | var center: CGPoint 129 | var centerX: CGFloat 130 | var centerY: CGFloat 131 | 132 | var size: CGSize 133 | var width: CGFloat 134 | var height: CGFloat 135 | 136 | var top: CGFloat // Top layout guide y coordinate. 137 | var right: CGFloat // Equal to the width of the controller's view. 138 | var bottom: CGFloat // Bottom layout guide y coordinate. 139 | var left: CGFloat // Always equal to 0. 140 | ``` 141 | 142 | ### Helper Methods 143 | 144 | These functions never modify the view/layer/rectangle/etc they are passed. 145 | 146 | ```swift 147 | func inset(view: UIView, amount: CGFloat) -> CGRect 148 | func inset(layer: CALayer, amount: CGFloat) -> CGRect 149 | func inset(rect: CGRect, amount: CGFloat) -> CGRect 150 | 151 | func inset(view: UIView, dx: CGFloat, dy: CGFloat) -> CGRect 152 | func inset(layer: CALayer, dx: CGFloat, dy: CGFloat) -> CGRect 153 | func inset(rect: CGRect, dx: CGFloat, dy: CGFloat) -> CGRect 154 | 155 | func inset(view: UIView, top: CGFloat, left: CGFloat, bottom: CGFloat, right: CGFloat) -> CGRect 156 | func inset(layer: CALayer, top: CGFloat, left: CGFloat, bottom: CGFloat, right: CGFloat) -> CGRect 157 | func inset(rect: CGRect, top: CGFloat, left: CGFloat, bottom: CGFloat, right: CGFloat) -> CGRect 158 | 159 | func inset(size: CGSize, amount: CGFloat) -> CGSize 160 | func inset(size: CGSize, dx: CGFloat, dy: CGFloat) -> CGSize 161 | func inset(size: CGSize, top: CGFloat, left: CGFloat, bottom: CGFloat, right: CGFloat) -> CGSize 162 | ``` 163 | 164 | ```swift 165 | func offset(view: UIView, amount: CGFloat) -> CGRect 166 | func offset(layer: CALayer, amount: CGFloat) -> CGRect 167 | func offset(rect: CGRect, amount: CGFloat) -> CGRect 168 | 169 | func offset(view: UIView, dx: CGFloat, dy: CGFloat) -> CGRect 170 | func offset(layer: CALayer, dx: CGFloat, dy: CGFloat) -> CGRect 171 | func offset(rect: CGRect, dx: CGFloat, dy: CGFloat) -> CGRect 172 | 173 | func offset(point: CGPoint, amount: CGFloat) -> CGPoint 174 | func offset(point: CGPoint, dx: CGFloat, dy: CGFloat) -> CGPoint 175 | ``` 176 | -------------------------------------------------------------------------------- /SimpleExample/AppDelegate.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.swift 3 | // SimpleExample 4 | // 5 | // Created by Baris Sencan on 30/03/15. 6 | // Copyright (c) 2015 Baris Sencan. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | @UIApplicationMain 12 | class AppDelegate: UIResponder, UIApplicationDelegate { 13 | var window: UIWindow? 14 | 15 | func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool { 16 | let window = UIWindow(frame: UIScreen.main.bounds) 17 | window.backgroundColor = UIColor.white 18 | window.rootViewController = ExampleViewController() 19 | window.makeKeyAndVisible() 20 | self.window = window 21 | return true 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /SimpleExample/Base.lproj/LaunchScreen.xib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | -------------------------------------------------------------------------------- /SimpleExample/ExampleViewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ExampleViewController.swift 3 | // SimpleExample 4 | // 5 | // Created by Baris Sencan on 30/03/15. 6 | // Copyright (c) 2015 Baris Sencan. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | import ManualLayout 11 | 12 | internal final class ExampleViewController: UIViewController { 13 | let titleLabel = UILabel(frame: .zero) 14 | let subtitleLabel = UILabel(frame: .zero) 15 | let yinView = UIView(frame: .zero) 16 | 17 | init() { 18 | super.init(nibName: nil, bundle: nil) 19 | titleLabel.attributedText = NSAttributedString( 20 | string: "Hello World!", 21 | attributes: generateTextStyle()) 22 | subtitleLabel.attributedText = NSAttributedString( 23 | string: "Lorem ipsum dolor sit amet, pro eu epicurei oportere similique, everti postulant repudiandae ei nam.", 24 | attributes: generateTextStyle(smaller: true)) 25 | subtitleLabel.textAlignment = .center 26 | subtitleLabel.numberOfLines = 3 27 | yinView.backgroundColor = UIColor.black 28 | } 29 | 30 | required init(coder aDecoder: NSCoder) { 31 | fatalError("storyboards are incompatible with truth and beauty") 32 | } 33 | 34 | override func viewDidLoad() { 35 | super.viewDidLoad() 36 | view.backgroundColor = UIColor.white 37 | view.addSubview(titleLabel) 38 | view.addSubview(subtitleLabel) 39 | view.addSubview(yinView) 40 | } 41 | 42 | override func viewWillLayoutSubviews() { 43 | titleLabel.sizeToFit() 44 | titleLabel.top = top + 20 45 | titleLabel.centerX = centerX 46 | subtitleLabel.sizeToFit(width - 40, height / 2 - titleLabel.bottom - 16) 47 | subtitleLabel.top = titleLabel.bottom + 8 48 | subtitleLabel.centerX = centerX 49 | yinView.top = height / 2 50 | yinView.right2 = right 51 | yinView.bottom2 = bottom 52 | } 53 | 54 | fileprivate func generateTextStyle(smaller: Bool = false) -> [String: AnyObject] { 55 | return [ 56 | NSFontAttributeName: UIFont.systemFont(ofSize: smaller ? 14 : 18), 57 | NSForegroundColorAttributeName: UIColor.black 58 | ] 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /SimpleExample/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" : "29x29", 11 | "scale" : "3x" 12 | }, 13 | { 14 | "idiom" : "iphone", 15 | "size" : "40x40", 16 | "scale" : "2x" 17 | }, 18 | { 19 | "idiom" : "iphone", 20 | "size" : "40x40", 21 | "scale" : "3x" 22 | }, 23 | { 24 | "idiom" : "iphone", 25 | "size" : "60x60", 26 | "scale" : "2x" 27 | }, 28 | { 29 | "idiom" : "iphone", 30 | "size" : "60x60", 31 | "scale" : "3x" 32 | }, 33 | { 34 | "idiom" : "ipad", 35 | "size" : "29x29", 36 | "scale" : "1x" 37 | }, 38 | { 39 | "idiom" : "ipad", 40 | "size" : "29x29", 41 | "scale" : "2x" 42 | }, 43 | { 44 | "idiom" : "ipad", 45 | "size" : "40x40", 46 | "scale" : "1x" 47 | }, 48 | { 49 | "idiom" : "ipad", 50 | "size" : "40x40", 51 | "scale" : "2x" 52 | }, 53 | { 54 | "idiom" : "ipad", 55 | "size" : "76x76", 56 | "scale" : "1x" 57 | }, 58 | { 59 | "idiom" : "ipad", 60 | "size" : "76x76", 61 | "scale" : "2x" 62 | } 63 | ], 64 | "info" : { 65 | "version" : 1, 66 | "author" : "xcode" 67 | } 68 | } -------------------------------------------------------------------------------- /SimpleExample/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 | APPL 17 | CFBundleShortVersionString 18 | 1.2.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 4 23 | LSRequiresIPhoneOS 24 | 25 | UILaunchStoryboardName 26 | LaunchScreen 27 | UIRequiredDeviceCapabilities 28 | 29 | armv7 30 | 31 | UISupportedInterfaceOrientations 32 | 33 | UIInterfaceOrientationPortrait 34 | UIInterfaceOrientationLandscapeLeft 35 | UIInterfaceOrientationLandscapeRight 36 | 37 | UISupportedInterfaceOrientations~ipad 38 | 39 | UIInterfaceOrientationPortrait 40 | UIInterfaceOrientationPortraitUpsideDown 41 | UIInterfaceOrientationLandscapeLeft 42 | UIInterfaceOrientationLandscapeRight 43 | 44 | 45 | 46 | -------------------------------------------------------------------------------- /SimpleExampleTests/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 | -------------------------------------------------------------------------------- /SimpleExampleTests/SimpleExampleTests.swift: -------------------------------------------------------------------------------- 1 | // 2 | // SimpleExampleTests.swift 3 | // SimpleExampleTests 4 | // 5 | // Created by Baris Sencan on 30/03/15. 6 | // Copyright (c) 2015 Baris Sencan. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | import XCTest 11 | 12 | class SimpleExampleTests: 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 | XCTAssert(true, "Pass") 27 | } 28 | 29 | func testPerformanceExample() { 30 | // This is an example of a performance test case. 31 | self.measure() { 32 | // Put the code you want to measure the time of here. 33 | } 34 | } 35 | 36 | } 37 | --------------------------------------------------------------------------------