├── .gitignore ├── .swift-version ├── Briggs.podspec ├── Briggs.xcodeproj ├── project.pbxproj ├── project.xcworkspace │ └── contents.xcworkspacedata └── xcshareddata │ └── xcschemes │ └── Briggs.xcscheme ├── Example ├── BriggsDemo.xcodeproj │ ├── project.pbxproj │ └── project.xcworkspace │ │ └── contents.xcworkspacedata └── Source │ ├── AppDelegate.swift │ ├── Assets.xcassets │ └── AppIcon.appiconset │ │ └── Contents.json │ ├── Base.lproj │ └── LaunchScreen.storyboard │ ├── Info.plist │ └── ViewControllers │ ├── BriggsViewController.swift │ ├── NativeViewController.swift │ └── SelectionViewController.swift ├── LICENSE ├── README.md └── Source ├── AdaptiveAttribute.swift ├── AdaptiveAttributeTraitCollectionExtension.swift ├── AdaptiveBehavior.swift ├── AdaptiveConstraintContainer.swift ├── AdaptiveElement.swift ├── AdaptiveInterface.swift ├── AdaptiveViewContainer.swift ├── Briggs.h ├── DisplayGamut.swift ├── ForceTouch.swift ├── Idiom.swift ├── Info.plist ├── LayoutDirection.swift ├── Scale.swift ├── SizeCategory.swift └── SizeClass.swift /.gitignore: -------------------------------------------------------------------------------- 1 | # Mac OS X 2 | .DS_Store 3 | 4 | # Xcode 5 | 6 | ## Build generated 7 | build/ 8 | DerivedData 9 | 10 | ## Various settings 11 | *.pbxuser 12 | !default.pbxuser 13 | *.mode1v3 14 | !default.mode1v3 15 | *.mode2v3 16 | !default.mode2v3 17 | *.perspectivev3 18 | !default.perspectivev3 19 | xcuserdata 20 | 21 | ## Other 22 | *.xccheckout 23 | *.moved-aside 24 | *.xcuserstate 25 | *.xcscmblueprint 26 | 27 | ## Obj-C/Swift specific 28 | *.hmap 29 | *.ipa 30 | 31 | ## Playgrounds 32 | timeline.xctimeline 33 | playground.xcworkspace 34 | 35 | # Swift Package Manager 36 | .build/ 37 | 38 | # Carthage 39 | Carthage/Build 40 | -------------------------------------------------------------------------------- /.swift-version: -------------------------------------------------------------------------------- 1 | 3.0 2 | -------------------------------------------------------------------------------- /Briggs.podspec: -------------------------------------------------------------------------------- 1 | Pod::Spec.new do |s| 2 | s.name = 'Briggs' 3 | s.version = '3.0.0' 4 | s.license = 'MIT' 5 | s.summary = 'A reimagination of UITraitCollection' 6 | s.homepage = 'https://github.com/auswahlaxiom/Briggs' 7 | s.authors = { 'Ada Turner' => 'ada.l.turner@gmail.com' } 8 | s.source = { :git => 'https://github.com/auswahlaxiom/Briggs.git', :tag => s.version } 9 | 10 | s.ios.deployment_target = '10.0' 11 | 12 | s.source_files = 'Source/*.swift' 13 | end 14 | -------------------------------------------------------------------------------- /Briggs.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 6024DFAC1F9FC72B007710C2 /* LayoutDirection.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6024DFAB1F9FC72B007710C2 /* LayoutDirection.swift */; }; 11 | 6024DFAE1F9FC883007710C2 /* SizeCategory.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6024DFAD1F9FC883007710C2 /* SizeCategory.swift */; }; 12 | 6024DFB01F9FCA00007710C2 /* DisplayGamut.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6024DFAF1F9FCA00007710C2 /* DisplayGamut.swift */; }; 13 | 60E2D4A51D5A76A100B4ADE2 /* Briggs.h in Headers */ = {isa = PBXBuildFile; fileRef = 60E2D4A41D5A76A100B4ADE2 /* Briggs.h */; settings = {ATTRIBUTES = (Public, ); }; }; 14 | 60E2D4B51D5A788500B4ADE2 /* AdaptiveAttributeTraitCollectionExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 60E2D4B01D5A788500B4ADE2 /* AdaptiveAttributeTraitCollectionExtension.swift */; }; 15 | 60E2D4B61D5A788500B4ADE2 /* ForceTouch.swift in Sources */ = {isa = PBXBuildFile; fileRef = 60E2D4B11D5A788500B4ADE2 /* ForceTouch.swift */; }; 16 | 60E2D4B71D5A788500B4ADE2 /* Idiom.swift in Sources */ = {isa = PBXBuildFile; fileRef = 60E2D4B21D5A788500B4ADE2 /* Idiom.swift */; }; 17 | 60E2D4B81D5A788500B4ADE2 /* Scale.swift in Sources */ = {isa = PBXBuildFile; fileRef = 60E2D4B31D5A788500B4ADE2 /* Scale.swift */; }; 18 | 60E2D4B91D5A788500B4ADE2 /* SizeClass.swift in Sources */ = {isa = PBXBuildFile; fileRef = 60E2D4B41D5A788500B4ADE2 /* SizeClass.swift */; }; 19 | 60E2D4BD1D5A789400B4ADE2 /* AdaptiveBehavior.swift in Sources */ = {isa = PBXBuildFile; fileRef = 60E2D4BA1D5A789400B4ADE2 /* AdaptiveBehavior.swift */; }; 20 | 60E2D4BE1D5A789400B4ADE2 /* AdaptiveConstraintContainer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 60E2D4BB1D5A789400B4ADE2 /* AdaptiveConstraintContainer.swift */; }; 21 | 60E2D4BF1D5A789400B4ADE2 /* AdaptiveViewContainer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 60E2D4BC1D5A789400B4ADE2 /* AdaptiveViewContainer.swift */; }; 22 | 60E2D4C31D5A789C00B4ADE2 /* AdaptiveAttribute.swift in Sources */ = {isa = PBXBuildFile; fileRef = 60E2D4C01D5A789C00B4ADE2 /* AdaptiveAttribute.swift */; }; 23 | 60E2D4C41D5A789C00B4ADE2 /* AdaptiveElement.swift in Sources */ = {isa = PBXBuildFile; fileRef = 60E2D4C11D5A789C00B4ADE2 /* AdaptiveElement.swift */; }; 24 | 60E2D4C51D5A789C00B4ADE2 /* AdaptiveInterface.swift in Sources */ = {isa = PBXBuildFile; fileRef = 60E2D4C21D5A789C00B4ADE2 /* AdaptiveInterface.swift */; }; 25 | /* End PBXBuildFile section */ 26 | 27 | /* Begin PBXFileReference section */ 28 | 6003FBE31DAEC6CA000BB2FD /* LICENSE */ = {isa = PBXFileReference; lastKnownFileType = text; path = LICENSE; sourceTree = ""; }; 29 | 6003FBE41DAEC6CA000BB2FD /* README.md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; path = README.md; sourceTree = ""; }; 30 | 6003FBE61DAED2FA000BB2FD /* Briggs.podspec */ = {isa = PBXFileReference; lastKnownFileType = text; path = Briggs.podspec; sourceTree = ""; }; 31 | 6024DFAB1F9FC72B007710C2 /* LayoutDirection.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LayoutDirection.swift; sourceTree = ""; }; 32 | 6024DFAD1F9FC883007710C2 /* SizeCategory.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SizeCategory.swift; sourceTree = ""; }; 33 | 6024DFAF1F9FCA00007710C2 /* DisplayGamut.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DisplayGamut.swift; sourceTree = ""; }; 34 | 60E2D4A11D5A76A100B4ADE2 /* Briggs.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Briggs.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 35 | 60E2D4A41D5A76A100B4ADE2 /* Briggs.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = Briggs.h; sourceTree = ""; }; 36 | 60E2D4A61D5A76A100B4ADE2 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 37 | 60E2D4B01D5A788500B4ADE2 /* AdaptiveAttributeTraitCollectionExtension.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AdaptiveAttributeTraitCollectionExtension.swift; sourceTree = ""; }; 38 | 60E2D4B11D5A788500B4ADE2 /* ForceTouch.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ForceTouch.swift; sourceTree = ""; }; 39 | 60E2D4B21D5A788500B4ADE2 /* Idiom.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Idiom.swift; sourceTree = ""; }; 40 | 60E2D4B31D5A788500B4ADE2 /* Scale.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Scale.swift; sourceTree = ""; }; 41 | 60E2D4B41D5A788500B4ADE2 /* SizeClass.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SizeClass.swift; sourceTree = ""; }; 42 | 60E2D4BA1D5A789400B4ADE2 /* AdaptiveBehavior.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AdaptiveBehavior.swift; sourceTree = ""; }; 43 | 60E2D4BB1D5A789400B4ADE2 /* AdaptiveConstraintContainer.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AdaptiveConstraintContainer.swift; sourceTree = ""; }; 44 | 60E2D4BC1D5A789400B4ADE2 /* AdaptiveViewContainer.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AdaptiveViewContainer.swift; sourceTree = ""; }; 45 | 60E2D4C01D5A789C00B4ADE2 /* AdaptiveAttribute.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AdaptiveAttribute.swift; sourceTree = ""; }; 46 | 60E2D4C11D5A789C00B4ADE2 /* AdaptiveElement.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AdaptiveElement.swift; sourceTree = ""; }; 47 | 60E2D4C21D5A789C00B4ADE2 /* AdaptiveInterface.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AdaptiveInterface.swift; sourceTree = ""; }; 48 | /* End PBXFileReference section */ 49 | 50 | /* Begin PBXFrameworksBuildPhase section */ 51 | 60E2D49D1D5A76A100B4ADE2 /* Frameworks */ = { 52 | isa = PBXFrameworksBuildPhase; 53 | buildActionMask = 2147483647; 54 | files = ( 55 | ); 56 | runOnlyForDeploymentPostprocessing = 0; 57 | }; 58 | /* End PBXFrameworksBuildPhase section */ 59 | 60 | /* Begin PBXGroup section */ 61 | 60E2D4971D5A76A100B4ADE2 = { 62 | isa = PBXGroup; 63 | children = ( 64 | 6003FBE31DAEC6CA000BB2FD /* LICENSE */, 65 | 6003FBE41DAEC6CA000BB2FD /* README.md */, 66 | 6003FBE61DAED2FA000BB2FD /* Briggs.podspec */, 67 | 60E2D4A31D5A76A100B4ADE2 /* Source */, 68 | 60E2D4A21D5A76A100B4ADE2 /* Products */, 69 | ); 70 | sourceTree = ""; 71 | }; 72 | 60E2D4A21D5A76A100B4ADE2 /* Products */ = { 73 | isa = PBXGroup; 74 | children = ( 75 | 60E2D4A11D5A76A100B4ADE2 /* Briggs.framework */, 76 | ); 77 | name = Products; 78 | sourceTree = ""; 79 | }; 80 | 60E2D4A31D5A76A100B4ADE2 /* Source */ = { 81 | isa = PBXGroup; 82 | children = ( 83 | 60E2D4AD1D5A785400B4ADE2 /* Adaptive Attributes */, 84 | 60E2D4AE1D5A786300B4ADE2 /* Adaptive Containers */, 85 | 60E2D4AF1D5A786B00B4ADE2 /* Adaptive Protocols */, 86 | 60E2D4AC1D5A781200B4ADE2 /* Supporting Files */, 87 | ); 88 | path = Source; 89 | sourceTree = ""; 90 | }; 91 | 60E2D4AC1D5A781200B4ADE2 /* Supporting Files */ = { 92 | isa = PBXGroup; 93 | children = ( 94 | 60E2D4A41D5A76A100B4ADE2 /* Briggs.h */, 95 | 60E2D4A61D5A76A100B4ADE2 /* Info.plist */, 96 | ); 97 | name = "Supporting Files"; 98 | sourceTree = ""; 99 | }; 100 | 60E2D4AD1D5A785400B4ADE2 /* Adaptive Attributes */ = { 101 | isa = PBXGroup; 102 | children = ( 103 | 60E2D4B01D5A788500B4ADE2 /* AdaptiveAttributeTraitCollectionExtension.swift */, 104 | 60E2D4B11D5A788500B4ADE2 /* ForceTouch.swift */, 105 | 60E2D4B21D5A788500B4ADE2 /* Idiom.swift */, 106 | 60E2D4B31D5A788500B4ADE2 /* Scale.swift */, 107 | 60E2D4B41D5A788500B4ADE2 /* SizeClass.swift */, 108 | 6024DFAB1F9FC72B007710C2 /* LayoutDirection.swift */, 109 | 6024DFAD1F9FC883007710C2 /* SizeCategory.swift */, 110 | 6024DFAF1F9FCA00007710C2 /* DisplayGamut.swift */, 111 | ); 112 | name = "Adaptive Attributes"; 113 | sourceTree = ""; 114 | }; 115 | 60E2D4AE1D5A786300B4ADE2 /* Adaptive Containers */ = { 116 | isa = PBXGroup; 117 | children = ( 118 | 60E2D4BA1D5A789400B4ADE2 /* AdaptiveBehavior.swift */, 119 | 60E2D4BB1D5A789400B4ADE2 /* AdaptiveConstraintContainer.swift */, 120 | 60E2D4BC1D5A789400B4ADE2 /* AdaptiveViewContainer.swift */, 121 | ); 122 | name = "Adaptive Containers"; 123 | sourceTree = ""; 124 | }; 125 | 60E2D4AF1D5A786B00B4ADE2 /* Adaptive Protocols */ = { 126 | isa = PBXGroup; 127 | children = ( 128 | 60E2D4C01D5A789C00B4ADE2 /* AdaptiveAttribute.swift */, 129 | 60E2D4C11D5A789C00B4ADE2 /* AdaptiveElement.swift */, 130 | 60E2D4C21D5A789C00B4ADE2 /* AdaptiveInterface.swift */, 131 | ); 132 | name = "Adaptive Protocols"; 133 | sourceTree = ""; 134 | }; 135 | /* End PBXGroup section */ 136 | 137 | /* Begin PBXHeadersBuildPhase section */ 138 | 60E2D49E1D5A76A100B4ADE2 /* Headers */ = { 139 | isa = PBXHeadersBuildPhase; 140 | buildActionMask = 2147483647; 141 | files = ( 142 | 60E2D4A51D5A76A100B4ADE2 /* Briggs.h in Headers */, 143 | ); 144 | runOnlyForDeploymentPostprocessing = 0; 145 | }; 146 | /* End PBXHeadersBuildPhase section */ 147 | 148 | /* Begin PBXNativeTarget section */ 149 | 60E2D4A01D5A76A100B4ADE2 /* Briggs */ = { 150 | isa = PBXNativeTarget; 151 | buildConfigurationList = 60E2D4A91D5A76A100B4ADE2 /* Build configuration list for PBXNativeTarget "Briggs" */; 152 | buildPhases = ( 153 | 60E2D49C1D5A76A100B4ADE2 /* Sources */, 154 | 60E2D49D1D5A76A100B4ADE2 /* Frameworks */, 155 | 60E2D49E1D5A76A100B4ADE2 /* Headers */, 156 | 60E2D49F1D5A76A100B4ADE2 /* Resources */, 157 | ); 158 | buildRules = ( 159 | ); 160 | dependencies = ( 161 | ); 162 | name = Briggs; 163 | productName = Briggs; 164 | productReference = 60E2D4A11D5A76A100B4ADE2 /* Briggs.framework */; 165 | productType = "com.apple.product-type.framework"; 166 | }; 167 | /* End PBXNativeTarget section */ 168 | 169 | /* Begin PBXProject section */ 170 | 60E2D4981D5A76A100B4ADE2 /* Project object */ = { 171 | isa = PBXProject; 172 | attributes = { 173 | LastUpgradeCheck = 0800; 174 | ORGANIZATIONNAME = Auswahlaxiom; 175 | TargetAttributes = { 176 | 60E2D4A01D5A76A100B4ADE2 = { 177 | CreatedOnToolsVersion = 7.3.1; 178 | LastSwiftMigration = 0900; 179 | }; 180 | }; 181 | }; 182 | buildConfigurationList = 60E2D49B1D5A76A100B4ADE2 /* Build configuration list for PBXProject "Briggs" */; 183 | compatibilityVersion = "Xcode 3.2"; 184 | developmentRegion = English; 185 | hasScannedForEncodings = 0; 186 | knownRegions = ( 187 | en, 188 | ); 189 | mainGroup = 60E2D4971D5A76A100B4ADE2; 190 | productRefGroup = 60E2D4A21D5A76A100B4ADE2 /* Products */; 191 | projectDirPath = ""; 192 | projectRoot = ""; 193 | targets = ( 194 | 60E2D4A01D5A76A100B4ADE2 /* Briggs */, 195 | ); 196 | }; 197 | /* End PBXProject section */ 198 | 199 | /* Begin PBXResourcesBuildPhase section */ 200 | 60E2D49F1D5A76A100B4ADE2 /* Resources */ = { 201 | isa = PBXResourcesBuildPhase; 202 | buildActionMask = 2147483647; 203 | files = ( 204 | ); 205 | runOnlyForDeploymentPostprocessing = 0; 206 | }; 207 | /* End PBXResourcesBuildPhase section */ 208 | 209 | /* Begin PBXSourcesBuildPhase section */ 210 | 60E2D49C1D5A76A100B4ADE2 /* Sources */ = { 211 | isa = PBXSourcesBuildPhase; 212 | buildActionMask = 2147483647; 213 | files = ( 214 | 60E2D4B71D5A788500B4ADE2 /* Idiom.swift in Sources */, 215 | 60E2D4C51D5A789C00B4ADE2 /* AdaptiveInterface.swift in Sources */, 216 | 6024DFAE1F9FC883007710C2 /* SizeCategory.swift in Sources */, 217 | 60E2D4BE1D5A789400B4ADE2 /* AdaptiveConstraintContainer.swift in Sources */, 218 | 60E2D4C31D5A789C00B4ADE2 /* AdaptiveAttribute.swift in Sources */, 219 | 60E2D4BF1D5A789400B4ADE2 /* AdaptiveViewContainer.swift in Sources */, 220 | 60E2D4C41D5A789C00B4ADE2 /* AdaptiveElement.swift in Sources */, 221 | 60E2D4BD1D5A789400B4ADE2 /* AdaptiveBehavior.swift in Sources */, 222 | 60E2D4B91D5A788500B4ADE2 /* SizeClass.swift in Sources */, 223 | 60E2D4B51D5A788500B4ADE2 /* AdaptiveAttributeTraitCollectionExtension.swift in Sources */, 224 | 60E2D4B81D5A788500B4ADE2 /* Scale.swift in Sources */, 225 | 6024DFB01F9FCA00007710C2 /* DisplayGamut.swift in Sources */, 226 | 60E2D4B61D5A788500B4ADE2 /* ForceTouch.swift in Sources */, 227 | 6024DFAC1F9FC72B007710C2 /* LayoutDirection.swift in Sources */, 228 | ); 229 | runOnlyForDeploymentPostprocessing = 0; 230 | }; 231 | /* End PBXSourcesBuildPhase section */ 232 | 233 | /* Begin XCBuildConfiguration section */ 234 | 60E2D4A71D5A76A100B4ADE2 /* Debug */ = { 235 | isa = XCBuildConfiguration; 236 | buildSettings = { 237 | ALWAYS_SEARCH_USER_PATHS = NO; 238 | CLANG_ANALYZER_NONNULL = YES; 239 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 240 | CLANG_CXX_LIBRARY = "libc++"; 241 | CLANG_ENABLE_MODULES = YES; 242 | CLANG_ENABLE_OBJC_ARC = YES; 243 | CLANG_WARN_BOOL_CONVERSION = YES; 244 | CLANG_WARN_CONSTANT_CONVERSION = YES; 245 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 246 | CLANG_WARN_EMPTY_BODY = YES; 247 | CLANG_WARN_ENUM_CONVERSION = YES; 248 | CLANG_WARN_INFINITE_RECURSION = YES; 249 | CLANG_WARN_INT_CONVERSION = YES; 250 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 251 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 252 | CLANG_WARN_UNREACHABLE_CODE = YES; 253 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 254 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 255 | COPY_PHASE_STRIP = NO; 256 | CURRENT_PROJECT_VERSION = 1; 257 | DEBUG_INFORMATION_FORMAT = dwarf; 258 | ENABLE_STRICT_OBJC_MSGSEND = YES; 259 | ENABLE_TESTABILITY = YES; 260 | GCC_C_LANGUAGE_STANDARD = gnu99; 261 | GCC_DYNAMIC_NO_PIC = NO; 262 | GCC_NO_COMMON_BLOCKS = YES; 263 | GCC_OPTIMIZATION_LEVEL = 0; 264 | GCC_PREPROCESSOR_DEFINITIONS = ( 265 | "DEBUG=1", 266 | "$(inherited)", 267 | ); 268 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 269 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 270 | GCC_WARN_UNDECLARED_SELECTOR = YES; 271 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 272 | GCC_WARN_UNUSED_FUNCTION = YES; 273 | GCC_WARN_UNUSED_VARIABLE = YES; 274 | IPHONEOS_DEPLOYMENT_TARGET = 10.0; 275 | MTL_ENABLE_DEBUG_INFO = YES; 276 | ONLY_ACTIVE_ARCH = YES; 277 | SDKROOT = iphoneos; 278 | SWIFT_OPTIMIZATION_LEVEL = "-Onone"; 279 | TARGETED_DEVICE_FAMILY = "1,2"; 280 | VERSIONING_SYSTEM = "apple-generic"; 281 | VERSION_INFO_PREFIX = ""; 282 | }; 283 | name = Debug; 284 | }; 285 | 60E2D4A81D5A76A100B4ADE2 /* Release */ = { 286 | isa = XCBuildConfiguration; 287 | buildSettings = { 288 | ALWAYS_SEARCH_USER_PATHS = NO; 289 | CLANG_ANALYZER_NONNULL = YES; 290 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 291 | CLANG_CXX_LIBRARY = "libc++"; 292 | CLANG_ENABLE_MODULES = YES; 293 | CLANG_ENABLE_OBJC_ARC = YES; 294 | CLANG_WARN_BOOL_CONVERSION = YES; 295 | CLANG_WARN_CONSTANT_CONVERSION = YES; 296 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 297 | CLANG_WARN_EMPTY_BODY = YES; 298 | CLANG_WARN_ENUM_CONVERSION = YES; 299 | CLANG_WARN_INFINITE_RECURSION = YES; 300 | CLANG_WARN_INT_CONVERSION = YES; 301 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 302 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 303 | CLANG_WARN_UNREACHABLE_CODE = YES; 304 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 305 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 306 | COPY_PHASE_STRIP = NO; 307 | CURRENT_PROJECT_VERSION = 1; 308 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 309 | ENABLE_NS_ASSERTIONS = NO; 310 | ENABLE_STRICT_OBJC_MSGSEND = YES; 311 | GCC_C_LANGUAGE_STANDARD = gnu99; 312 | GCC_NO_COMMON_BLOCKS = YES; 313 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 314 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 315 | GCC_WARN_UNDECLARED_SELECTOR = YES; 316 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 317 | GCC_WARN_UNUSED_FUNCTION = YES; 318 | GCC_WARN_UNUSED_VARIABLE = YES; 319 | IPHONEOS_DEPLOYMENT_TARGET = 10.0; 320 | MTL_ENABLE_DEBUG_INFO = NO; 321 | ONLY_ACTIVE_ARCH = NO; 322 | SDKROOT = iphoneos; 323 | SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; 324 | TARGETED_DEVICE_FAMILY = "1,2"; 325 | VALIDATE_PRODUCT = YES; 326 | VERSIONING_SYSTEM = "apple-generic"; 327 | VERSION_INFO_PREFIX = ""; 328 | }; 329 | name = Release; 330 | }; 331 | 60E2D4AA1D5A76A100B4ADE2 /* Debug */ = { 332 | isa = XCBuildConfiguration; 333 | buildSettings = { 334 | APPLICATION_EXTENSION_API_ONLY = YES; 335 | CLANG_ENABLE_MODULES = YES; 336 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; 337 | DEFINES_MODULE = YES; 338 | DYLIB_COMPATIBILITY_VERSION = 1; 339 | DYLIB_CURRENT_VERSION = 1; 340 | DYLIB_INSTALL_NAME_BASE = "@rpath"; 341 | INFOPLIST_FILE = "$(SRCROOT)/Source/Info.plist"; 342 | INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; 343 | IPHONEOS_DEPLOYMENT_TARGET = 10.0; 344 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 345 | PRODUCT_BUNDLE_IDENTIFIER = com.auswahlaxiom.Briggs; 346 | PRODUCT_NAME = "$(TARGET_NAME)"; 347 | SKIP_INSTALL = YES; 348 | SWIFT_OPTIMIZATION_LEVEL = "-Onone"; 349 | SWIFT_SWIFT3_OBJC_INFERENCE = On; 350 | SWIFT_VERSION = 4.0; 351 | }; 352 | name = Debug; 353 | }; 354 | 60E2D4AB1D5A76A100B4ADE2 /* Release */ = { 355 | isa = XCBuildConfiguration; 356 | buildSettings = { 357 | APPLICATION_EXTENSION_API_ONLY = YES; 358 | CLANG_ENABLE_MODULES = YES; 359 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; 360 | DEFINES_MODULE = YES; 361 | DYLIB_COMPATIBILITY_VERSION = 1; 362 | DYLIB_CURRENT_VERSION = 1; 363 | DYLIB_INSTALL_NAME_BASE = "@rpath"; 364 | INFOPLIST_FILE = "$(SRCROOT)/Source/Info.plist"; 365 | INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; 366 | IPHONEOS_DEPLOYMENT_TARGET = 10.0; 367 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 368 | PRODUCT_BUNDLE_IDENTIFIER = com.auswahlaxiom.Briggs; 369 | PRODUCT_NAME = "$(TARGET_NAME)"; 370 | SKIP_INSTALL = YES; 371 | SWIFT_SWIFT3_OBJC_INFERENCE = On; 372 | SWIFT_VERSION = 4.0; 373 | }; 374 | name = Release; 375 | }; 376 | /* End XCBuildConfiguration section */ 377 | 378 | /* Begin XCConfigurationList section */ 379 | 60E2D49B1D5A76A100B4ADE2 /* Build configuration list for PBXProject "Briggs" */ = { 380 | isa = XCConfigurationList; 381 | buildConfigurations = ( 382 | 60E2D4A71D5A76A100B4ADE2 /* Debug */, 383 | 60E2D4A81D5A76A100B4ADE2 /* Release */, 384 | ); 385 | defaultConfigurationIsVisible = 0; 386 | defaultConfigurationName = Release; 387 | }; 388 | 60E2D4A91D5A76A100B4ADE2 /* Build configuration list for PBXNativeTarget "Briggs" */ = { 389 | isa = XCConfigurationList; 390 | buildConfigurations = ( 391 | 60E2D4AA1D5A76A100B4ADE2 /* Debug */, 392 | 60E2D4AB1D5A76A100B4ADE2 /* Release */, 393 | ); 394 | defaultConfigurationIsVisible = 0; 395 | defaultConfigurationName = Release; 396 | }; 397 | /* End XCConfigurationList section */ 398 | }; 399 | rootObject = 60E2D4981D5A76A100B4ADE2 /* Project object */; 400 | } 401 | -------------------------------------------------------------------------------- /Briggs.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /Briggs.xcodeproj/xcshareddata/xcschemes/Briggs.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 32 | 33 | 34 | 35 | 45 | 46 | 52 | 53 | 54 | 55 | 56 | 57 | 63 | 64 | 70 | 71 | 72 | 73 | 75 | 76 | 79 | 80 | 81 | -------------------------------------------------------------------------------- /Example/BriggsDemo.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 6097A52F1D580C4700DAFB98 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6097A52E1D580C4700DAFB98 /* AppDelegate.swift */; }; 11 | 6097A5361D580C4700DAFB98 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 6097A5351D580C4700DAFB98 /* Assets.xcassets */; }; 12 | 6097A5391D580C4700DAFB98 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 6097A5371D580C4700DAFB98 /* LaunchScreen.storyboard */; }; 13 | 6097A55D1D580C9100DAFB98 /* BriggsViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6097A55A1D580C9100DAFB98 /* BriggsViewController.swift */; }; 14 | 6097A55E1D580C9100DAFB98 /* NativeViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6097A55B1D580C9100DAFB98 /* NativeViewController.swift */; }; 15 | 6097A55F1D580C9100DAFB98 /* SelectionViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6097A55C1D580C9100DAFB98 /* SelectionViewController.swift */; }; 16 | 60E2D4E21D5A834A00B4ADE2 /* Briggs.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 60E2D4D91D5A821200B4ADE2 /* Briggs.framework */; }; 17 | 60E2D4E31D5A834A00B4ADE2 /* Briggs.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 60E2D4D91D5A821200B4ADE2 /* Briggs.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; 18 | /* End PBXBuildFile section */ 19 | 20 | /* Begin PBXContainerItemProxy section */ 21 | 60E2D4D81D5A821200B4ADE2 /* PBXContainerItemProxy */ = { 22 | isa = PBXContainerItemProxy; 23 | containerPortal = 60E2D4D41D5A821200B4ADE2 /* Briggs.xcodeproj */; 24 | proxyType = 2; 25 | remoteGlobalIDString = 60E2D4A11D5A76A100B4ADE2; 26 | remoteInfo = Briggs; 27 | }; 28 | 60E2D4E41D5A834A00B4ADE2 /* PBXContainerItemProxy */ = { 29 | isa = PBXContainerItemProxy; 30 | containerPortal = 60E2D4D41D5A821200B4ADE2 /* Briggs.xcodeproj */; 31 | proxyType = 1; 32 | remoteGlobalIDString = 60E2D4A01D5A76A100B4ADE2; 33 | remoteInfo = Briggs; 34 | }; 35 | /* End PBXContainerItemProxy section */ 36 | 37 | /* Begin PBXCopyFilesBuildPhase section */ 38 | 60E2D4E61D5A834A00B4ADE2 /* Embed Frameworks */ = { 39 | isa = PBXCopyFilesBuildPhase; 40 | buildActionMask = 2147483647; 41 | dstPath = ""; 42 | dstSubfolderSpec = 10; 43 | files = ( 44 | 60E2D4E31D5A834A00B4ADE2 /* Briggs.framework in Embed Frameworks */, 45 | ); 46 | name = "Embed Frameworks"; 47 | runOnlyForDeploymentPostprocessing = 0; 48 | }; 49 | /* End PBXCopyFilesBuildPhase section */ 50 | 51 | /* Begin PBXFileReference section */ 52 | 6097A52B1D580C4700DAFB98 /* BriggsDemo.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = BriggsDemo.app; sourceTree = BUILT_PRODUCTS_DIR; }; 53 | 6097A52E1D580C4700DAFB98 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; 54 | 6097A5351D580C4700DAFB98 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 55 | 6097A5381D580C4700DAFB98 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; 56 | 6097A53A1D580C4700DAFB98 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 57 | 6097A55A1D580C9100DAFB98 /* BriggsViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BriggsViewController.swift; sourceTree = ""; }; 58 | 6097A55B1D580C9100DAFB98 /* NativeViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NativeViewController.swift; sourceTree = ""; }; 59 | 6097A55C1D580C9100DAFB98 /* SelectionViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SelectionViewController.swift; sourceTree = ""; }; 60 | 60E2D4D41D5A821200B4ADE2 /* Briggs.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = Briggs.xcodeproj; path = ../Briggs.xcodeproj; sourceTree = ""; }; 61 | /* End PBXFileReference section */ 62 | 63 | /* Begin PBXFrameworksBuildPhase section */ 64 | 6097A5281D580C4700DAFB98 /* Frameworks */ = { 65 | isa = PBXFrameworksBuildPhase; 66 | buildActionMask = 2147483647; 67 | files = ( 68 | 60E2D4E21D5A834A00B4ADE2 /* Briggs.framework in Frameworks */, 69 | ); 70 | runOnlyForDeploymentPostprocessing = 0; 71 | }; 72 | /* End PBXFrameworksBuildPhase section */ 73 | 74 | /* Begin PBXGroup section */ 75 | 6097A5221D580C4700DAFB98 = { 76 | isa = PBXGroup; 77 | children = ( 78 | 6097A52D1D580C4700DAFB98 /* Source */, 79 | 6097A52C1D580C4700DAFB98 /* Products */, 80 | 60E2D4D41D5A821200B4ADE2 /* Briggs.xcodeproj */, 81 | ); 82 | sourceTree = ""; 83 | }; 84 | 6097A52C1D580C4700DAFB98 /* Products */ = { 85 | isa = PBXGroup; 86 | children = ( 87 | 6097A52B1D580C4700DAFB98 /* BriggsDemo.app */, 88 | ); 89 | name = Products; 90 | sourceTree = ""; 91 | }; 92 | 6097A52D1D580C4700DAFB98 /* Source */ = { 93 | isa = PBXGroup; 94 | children = ( 95 | 6097A5591D580C9100DAFB98 /* ViewControllers */, 96 | 6097A52E1D580C4700DAFB98 /* AppDelegate.swift */, 97 | 6097A5351D580C4700DAFB98 /* Assets.xcassets */, 98 | 6097A5371D580C4700DAFB98 /* LaunchScreen.storyboard */, 99 | 6097A53A1D580C4700DAFB98 /* Info.plist */, 100 | ); 101 | path = Source; 102 | sourceTree = ""; 103 | }; 104 | 6097A5591D580C9100DAFB98 /* ViewControllers */ = { 105 | isa = PBXGroup; 106 | children = ( 107 | 6097A55A1D580C9100DAFB98 /* BriggsViewController.swift */, 108 | 6097A55B1D580C9100DAFB98 /* NativeViewController.swift */, 109 | 6097A55C1D580C9100DAFB98 /* SelectionViewController.swift */, 110 | ); 111 | path = ViewControllers; 112 | sourceTree = ""; 113 | }; 114 | 60E2D4D51D5A821200B4ADE2 /* Products */ = { 115 | isa = PBXGroup; 116 | children = ( 117 | 60E2D4D91D5A821200B4ADE2 /* Briggs.framework */, 118 | ); 119 | name = Products; 120 | sourceTree = ""; 121 | }; 122 | /* End PBXGroup section */ 123 | 124 | /* Begin PBXNativeTarget section */ 125 | 6097A52A1D580C4700DAFB98 /* BriggsDemo */ = { 126 | isa = PBXNativeTarget; 127 | buildConfigurationList = 6097A53D1D580C4700DAFB98 /* Build configuration list for PBXNativeTarget "BriggsDemo" */; 128 | buildPhases = ( 129 | 6097A5271D580C4700DAFB98 /* Sources */, 130 | 6097A5281D580C4700DAFB98 /* Frameworks */, 131 | 6097A5291D580C4700DAFB98 /* Resources */, 132 | 60E2D4E61D5A834A00B4ADE2 /* Embed Frameworks */, 133 | ); 134 | buildRules = ( 135 | ); 136 | dependencies = ( 137 | 60E2D4E51D5A834A00B4ADE2 /* PBXTargetDependency */, 138 | ); 139 | name = BriggsDemo; 140 | productName = BriggsDemo; 141 | productReference = 6097A52B1D580C4700DAFB98 /* BriggsDemo.app */; 142 | productType = "com.apple.product-type.application"; 143 | }; 144 | /* End PBXNativeTarget section */ 145 | 146 | /* Begin PBXProject section */ 147 | 6097A5231D580C4700DAFB98 /* Project object */ = { 148 | isa = PBXProject; 149 | attributes = { 150 | LastSwiftUpdateCheck = 0730; 151 | LastUpgradeCheck = 0800; 152 | ORGANIZATIONNAME = AdaTurner; 153 | TargetAttributes = { 154 | 6097A52A1D580C4700DAFB98 = { 155 | CreatedOnToolsVersion = 7.3.1; 156 | LastSwiftMigration = 0900; 157 | }; 158 | }; 159 | }; 160 | buildConfigurationList = 6097A5261D580C4700DAFB98 /* Build configuration list for PBXProject "BriggsDemo" */; 161 | compatibilityVersion = "Xcode 3.2"; 162 | developmentRegion = English; 163 | hasScannedForEncodings = 0; 164 | knownRegions = ( 165 | en, 166 | Base, 167 | ); 168 | mainGroup = 6097A5221D580C4700DAFB98; 169 | productRefGroup = 6097A52C1D580C4700DAFB98 /* Products */; 170 | projectDirPath = ""; 171 | projectReferences = ( 172 | { 173 | ProductGroup = 60E2D4D51D5A821200B4ADE2 /* Products */; 174 | ProjectRef = 60E2D4D41D5A821200B4ADE2 /* Briggs.xcodeproj */; 175 | }, 176 | ); 177 | projectRoot = ""; 178 | targets = ( 179 | 6097A52A1D580C4700DAFB98 /* BriggsDemo */, 180 | ); 181 | }; 182 | /* End PBXProject section */ 183 | 184 | /* Begin PBXReferenceProxy section */ 185 | 60E2D4D91D5A821200B4ADE2 /* Briggs.framework */ = { 186 | isa = PBXReferenceProxy; 187 | fileType = wrapper.framework; 188 | path = Briggs.framework; 189 | remoteRef = 60E2D4D81D5A821200B4ADE2 /* PBXContainerItemProxy */; 190 | sourceTree = BUILT_PRODUCTS_DIR; 191 | }; 192 | /* End PBXReferenceProxy section */ 193 | 194 | /* Begin PBXResourcesBuildPhase section */ 195 | 6097A5291D580C4700DAFB98 /* Resources */ = { 196 | isa = PBXResourcesBuildPhase; 197 | buildActionMask = 2147483647; 198 | files = ( 199 | 6097A5391D580C4700DAFB98 /* LaunchScreen.storyboard in Resources */, 200 | 6097A5361D580C4700DAFB98 /* Assets.xcassets in Resources */, 201 | ); 202 | runOnlyForDeploymentPostprocessing = 0; 203 | }; 204 | /* End PBXResourcesBuildPhase section */ 205 | 206 | /* Begin PBXSourcesBuildPhase section */ 207 | 6097A5271D580C4700DAFB98 /* Sources */ = { 208 | isa = PBXSourcesBuildPhase; 209 | buildActionMask = 2147483647; 210 | files = ( 211 | 6097A55E1D580C9100DAFB98 /* NativeViewController.swift in Sources */, 212 | 6097A55D1D580C9100DAFB98 /* BriggsViewController.swift in Sources */, 213 | 6097A52F1D580C4700DAFB98 /* AppDelegate.swift in Sources */, 214 | 6097A55F1D580C9100DAFB98 /* SelectionViewController.swift in Sources */, 215 | ); 216 | runOnlyForDeploymentPostprocessing = 0; 217 | }; 218 | /* End PBXSourcesBuildPhase section */ 219 | 220 | /* Begin PBXTargetDependency section */ 221 | 60E2D4E51D5A834A00B4ADE2 /* PBXTargetDependency */ = { 222 | isa = PBXTargetDependency; 223 | name = Briggs; 224 | targetProxy = 60E2D4E41D5A834A00B4ADE2 /* PBXContainerItemProxy */; 225 | }; 226 | /* End PBXTargetDependency section */ 227 | 228 | /* Begin PBXVariantGroup section */ 229 | 6097A5371D580C4700DAFB98 /* LaunchScreen.storyboard */ = { 230 | isa = PBXVariantGroup; 231 | children = ( 232 | 6097A5381D580C4700DAFB98 /* Base */, 233 | ); 234 | name = LaunchScreen.storyboard; 235 | sourceTree = ""; 236 | }; 237 | /* End PBXVariantGroup section */ 238 | 239 | /* Begin XCBuildConfiguration section */ 240 | 6097A53B1D580C4700DAFB98 /* Debug */ = { 241 | isa = XCBuildConfiguration; 242 | buildSettings = { 243 | ALWAYS_SEARCH_USER_PATHS = NO; 244 | CLANG_ANALYZER_NONNULL = YES; 245 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 246 | CLANG_CXX_LIBRARY = "libc++"; 247 | CLANG_ENABLE_MODULES = YES; 248 | CLANG_ENABLE_OBJC_ARC = YES; 249 | CLANG_WARN_BOOL_CONVERSION = YES; 250 | CLANG_WARN_CONSTANT_CONVERSION = YES; 251 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 252 | CLANG_WARN_EMPTY_BODY = YES; 253 | CLANG_WARN_ENUM_CONVERSION = YES; 254 | CLANG_WARN_INFINITE_RECURSION = YES; 255 | CLANG_WARN_INT_CONVERSION = YES; 256 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 257 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 258 | CLANG_WARN_UNREACHABLE_CODE = YES; 259 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 260 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 261 | COPY_PHASE_STRIP = NO; 262 | DEBUG_INFORMATION_FORMAT = dwarf; 263 | ENABLE_STRICT_OBJC_MSGSEND = YES; 264 | ENABLE_TESTABILITY = YES; 265 | GCC_C_LANGUAGE_STANDARD = gnu99; 266 | GCC_DYNAMIC_NO_PIC = NO; 267 | GCC_NO_COMMON_BLOCKS = YES; 268 | GCC_OPTIMIZATION_LEVEL = 0; 269 | GCC_PREPROCESSOR_DEFINITIONS = ( 270 | "DEBUG=1", 271 | "$(inherited)", 272 | ); 273 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 274 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 275 | GCC_WARN_UNDECLARED_SELECTOR = YES; 276 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 277 | GCC_WARN_UNUSED_FUNCTION = YES; 278 | GCC_WARN_UNUSED_VARIABLE = YES; 279 | IPHONEOS_DEPLOYMENT_TARGET = 10.0; 280 | MTL_ENABLE_DEBUG_INFO = YES; 281 | ONLY_ACTIVE_ARCH = YES; 282 | SDKROOT = iphoneos; 283 | SWIFT_OPTIMIZATION_LEVEL = "-Onone"; 284 | TARGETED_DEVICE_FAMILY = "1,2"; 285 | }; 286 | name = Debug; 287 | }; 288 | 6097A53C1D580C4700DAFB98 /* Release */ = { 289 | isa = XCBuildConfiguration; 290 | buildSettings = { 291 | ALWAYS_SEARCH_USER_PATHS = NO; 292 | CLANG_ANALYZER_NONNULL = YES; 293 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 294 | CLANG_CXX_LIBRARY = "libc++"; 295 | CLANG_ENABLE_MODULES = YES; 296 | CLANG_ENABLE_OBJC_ARC = YES; 297 | CLANG_WARN_BOOL_CONVERSION = YES; 298 | CLANG_WARN_CONSTANT_CONVERSION = YES; 299 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 300 | CLANG_WARN_EMPTY_BODY = YES; 301 | CLANG_WARN_ENUM_CONVERSION = YES; 302 | CLANG_WARN_INFINITE_RECURSION = YES; 303 | CLANG_WARN_INT_CONVERSION = YES; 304 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 305 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 306 | CLANG_WARN_UNREACHABLE_CODE = YES; 307 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 308 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 309 | COPY_PHASE_STRIP = NO; 310 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 311 | ENABLE_NS_ASSERTIONS = NO; 312 | ENABLE_STRICT_OBJC_MSGSEND = YES; 313 | GCC_C_LANGUAGE_STANDARD = gnu99; 314 | GCC_NO_COMMON_BLOCKS = YES; 315 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 316 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 317 | GCC_WARN_UNDECLARED_SELECTOR = YES; 318 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 319 | GCC_WARN_UNUSED_FUNCTION = YES; 320 | GCC_WARN_UNUSED_VARIABLE = YES; 321 | IPHONEOS_DEPLOYMENT_TARGET = 10.0; 322 | MTL_ENABLE_DEBUG_INFO = NO; 323 | SDKROOT = iphoneos; 324 | SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; 325 | TARGETED_DEVICE_FAMILY = "1,2"; 326 | VALIDATE_PRODUCT = YES; 327 | }; 328 | name = Release; 329 | }; 330 | 6097A53E1D580C4700DAFB98 /* Debug */ = { 331 | isa = XCBuildConfiguration; 332 | buildSettings = { 333 | ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; 334 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 335 | FRAMEWORK_SEARCH_PATHS = ( 336 | "$(inherited)", 337 | "$(PROJECT_DIR)", 338 | ); 339 | INFOPLIST_FILE = "$(SRCROOT)/Source/Info.plist"; 340 | IPHONEOS_DEPLOYMENT_TARGET = 10.0; 341 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 342 | PRODUCT_BUNDLE_IDENTIFIER = ADA.BriggsDemo; 343 | PRODUCT_NAME = "$(TARGET_NAME)"; 344 | SWIFT_SWIFT3_OBJC_INFERENCE = On; 345 | SWIFT_VERSION = 4.0; 346 | }; 347 | name = Debug; 348 | }; 349 | 6097A53F1D580C4700DAFB98 /* Release */ = { 350 | isa = XCBuildConfiguration; 351 | buildSettings = { 352 | ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; 353 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 354 | FRAMEWORK_SEARCH_PATHS = ( 355 | "$(inherited)", 356 | "$(PROJECT_DIR)", 357 | ); 358 | INFOPLIST_FILE = "$(SRCROOT)/Source/Info.plist"; 359 | IPHONEOS_DEPLOYMENT_TARGET = 10.0; 360 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 361 | PRODUCT_BUNDLE_IDENTIFIER = ADA.BriggsDemo; 362 | PRODUCT_NAME = "$(TARGET_NAME)"; 363 | SWIFT_SWIFT3_OBJC_INFERENCE = On; 364 | SWIFT_VERSION = 4.0; 365 | }; 366 | name = Release; 367 | }; 368 | /* End XCBuildConfiguration section */ 369 | 370 | /* Begin XCConfigurationList section */ 371 | 6097A5261D580C4700DAFB98 /* Build configuration list for PBXProject "BriggsDemo" */ = { 372 | isa = XCConfigurationList; 373 | buildConfigurations = ( 374 | 6097A53B1D580C4700DAFB98 /* Debug */, 375 | 6097A53C1D580C4700DAFB98 /* Release */, 376 | ); 377 | defaultConfigurationIsVisible = 0; 378 | defaultConfigurationName = Release; 379 | }; 380 | 6097A53D1D580C4700DAFB98 /* Build configuration list for PBXNativeTarget "BriggsDemo" */ = { 381 | isa = XCConfigurationList; 382 | buildConfigurations = ( 383 | 6097A53E1D580C4700DAFB98 /* Debug */, 384 | 6097A53F1D580C4700DAFB98 /* Release */, 385 | ); 386 | defaultConfigurationIsVisible = 0; 387 | defaultConfigurationName = Release; 388 | }; 389 | /* End XCConfigurationList section */ 390 | }; 391 | rootObject = 6097A5231D580C4700DAFB98 /* Project object */; 392 | } 393 | -------------------------------------------------------------------------------- /Example/BriggsDemo.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /Example/Source/AppDelegate.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.swift 3 | // BriggsDemo 4 | // 5 | // Copyright (c) 2017 Ada Turner (https://github.com/auswahlaxiom) 6 | // 7 | // Permission is hereby granted, free of charge, to any person obtaining a copy 8 | // of this software and associated documentation files (the "Software"), to deal 9 | // in the Software without restriction, including without limitation the rights 10 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | // copies of the Software, and to permit persons to whom the Software is 12 | // furnished to do so, subject to the following conditions:// 13 | // 14 | // The above copyright notice and this permission notice shall be included in 15 | // all copies or substantial portions of the Software.// 16 | // 17 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 23 | // THE SOFTWARE. 24 | // 25 | 26 | import UIKit 27 | 28 | @UIApplicationMain 29 | final class AppDelegate: UIResponder, UIApplicationDelegate { 30 | 31 | // MARK: - UIApplicationDelegate 32 | 33 | var window: UIWindow? 34 | 35 | func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool { 36 | setupRootViewController() 37 | 38 | return true 39 | } 40 | 41 | // MARK: - Internal 42 | 43 | var rootViewController: UINavigationController? 44 | 45 | // MARK: - Private 46 | 47 | private func setupRootViewController() { 48 | let window = UIWindow(frame: UIScreen.main.bounds) 49 | let selectionViewController = SelectionViewController() 50 | let selectionNavigationController = UINavigationController(rootViewController: selectionViewController) 51 | 52 | window.rootViewController = selectionNavigationController 53 | window.makeKeyAndVisible() 54 | 55 | self.rootViewController = selectionNavigationController 56 | self.window = window 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /Example/Source/Assets.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 | } -------------------------------------------------------------------------------- /Example/Source/Base.lproj/LaunchScreen.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /Example/Source/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 | 3.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | $(CURRENT_PROJECT_VERSION) 23 | LSRequiresIPhoneOS 24 | 25 | UILaunchStoryboardName 26 | LaunchScreen 27 | UIRequiredDeviceCapabilities 28 | 29 | armv7 30 | 31 | UISupportedInterfaceOrientations 32 | 33 | UIInterfaceOrientationPortrait 34 | UIInterfaceOrientationLandscapeLeft 35 | UIInterfaceOrientationLandscapeRight 36 | UIInterfaceOrientationPortraitUpsideDown 37 | 38 | UISupportedInterfaceOrientations~ipad 39 | 40 | UIInterfaceOrientationPortrait 41 | UIInterfaceOrientationPortraitUpsideDown 42 | UIInterfaceOrientationLandscapeLeft 43 | UIInterfaceOrientationLandscapeRight 44 | 45 | 46 | 47 | -------------------------------------------------------------------------------- /Example/Source/ViewControllers/BriggsViewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // BriggsViewController.swift 3 | // BriggsDemo 4 | // 5 | // Copyright (c) 2017 Ada Turner (https://github.com/auswahlaxiom) 6 | // 7 | // Permission is hereby granted, free of charge, to any person obtaining a copy 8 | // of this software and associated documentation files (the "Software"), to deal 9 | // in the Software without restriction, including without limitation the rights 10 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | // copies of the Software, and to permit persons to whom the Software is 12 | // furnished to do so, subject to the following conditions:// 13 | // 14 | // The above copyright notice and this permission notice shall be included in 15 | // all copies or substantial portions of the Software.// 16 | // 17 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 23 | // THE SOFTWARE. 24 | // 25 | 26 | import UIKit 27 | import Briggs 28 | 29 | /** 30 | A view controller that uses Briggs Adaptive API to elegantly achieve the following adaptive behaviors: 31 | 1. A label that is red when displayed on @2x scale devices with Force Touch capability, and blue for all other devices 32 | 2. A continue button stretches edge-to-edge in horizontal-compact, and has a fixed width in horizontal-regular 33 | 3. An iPad-exclusive button that is centered at the top of the screen 34 | */ 35 | class BriggsViewController: UIViewController, AdaptiveInterface { 36 | 37 | // MARK: - Static 38 | 39 | struct K { 40 | 41 | static let margin: CGFloat = 12.0 42 | } 43 | 44 | // MARK: - UIViewController 45 | 46 | override func loadView() { 47 | view = UIView() 48 | setupViews() 49 | } 50 | 51 | override func viewDidLoad() { 52 | super.viewDidLoad() 53 | title = "Briggs API" 54 | } 55 | 56 | override func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) { 57 | super.traitCollectionDidChange(previousTraitCollection) 58 | update(for: traitCollection) 59 | } 60 | 61 | // MARK: - AdaptiveInterface 62 | 63 | var adaptiveElements: [AdaptiveElement] = [] 64 | 65 | // MARK: - Interface 66 | 67 | private func setupViews() { 68 | view.backgroundColor = UIColor.white 69 | 70 | let welcomeLabel = createWelcomeLabel() 71 | view.addSubview(welcomeLabel) 72 | 73 | welcomeLabel.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true 74 | welcomeLabel.centerYAnchor.constraint(equalTo: view.centerYAnchor).isActive = true 75 | 76 | // Requirement 1: red text for @2x with force touch, otherwise blue text 77 | addBehavior(for: [Scale.twoX, ForceTouch.available], behavior: { 78 | welcomeLabel.textColor = UIColor.red 79 | }, counterBehavior: { 80 | welcomeLabel.textColor = UIColor.blue 81 | }) 82 | 83 | let continueButton = createContinueButton() 84 | view.addSubview(continueButton) 85 | 86 | bottomLayoutGuide.topAnchor.constraint(equalTo: continueButton.bottomAnchor, constant: K.margin).isActive = true 87 | view.trailingAnchor.constraint(equalTo: continueButton.trailingAnchor, constant: K.margin).isActive = true 88 | continueButton.heightAnchor.constraint(equalToConstant: 45.0).isActive = true 89 | 90 | // Requirement 2: full width in horizontal compact, fixed width in horizontal regular 91 | addConstraints(for: SizeClass.horizontalCompact, constraints: 92 | continueButton.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: K.margin) 93 | ) 94 | 95 | addConstraints(for: SizeClass.horizontalRegular, constraints: 96 | continueButton.widthAnchor.constraint(equalToConstant: 180.0) 97 | ) 98 | 99 | let iPadExclusiveButton = createiPadExclusiveButton() 100 | 101 | // Requirement 3: iPad exclusive button 102 | addView(for: Idiom.pad, view: iPadExclusiveButton, parent: view, constraints: [ 103 | iPadExclusiveButton.centerXAnchor.constraint(equalTo: view.centerXAnchor), 104 | iPadExclusiveButton.topAnchor.constraint(equalTo: topLayoutGuide.bottomAnchor, constant: K.margin) 105 | ]) 106 | } 107 | 108 | private func createWelcomeLabel() -> UILabel { 109 | let welcomeLabel = UILabel() 110 | welcomeLabel.text = "Hello World" 111 | welcomeLabel.translatesAutoresizingMaskIntoConstraints = false 112 | 113 | return welcomeLabel 114 | } 115 | 116 | private func createContinueButton() -> UIButton { 117 | let continueButton = UIButton(type: .system) 118 | continueButton.setTitle("Continue", for: .normal) 119 | continueButton.addTarget(self, action: #selector(continueAction), for: .touchUpInside) 120 | continueButton.backgroundColor = UIColor(red: 0.95, green: 0.95, blue: 1.0, alpha: 1.0) 121 | continueButton.layer.borderColor = UIColor(red: 0.5, green: 0.5, blue: 1.0, alpha: 1.0).cgColor 122 | continueButton.layer.borderWidth = 2.0 123 | continueButton.layer.cornerRadius = 4.0 124 | continueButton.translatesAutoresizingMaskIntoConstraints = false 125 | 126 | return continueButton 127 | } 128 | 129 | private func createiPadExclusiveButton() -> UIButton { 130 | let iPadExclusiveButton = UIButton(type: .system) 131 | iPadExclusiveButton.setTitle("iPad Only!", for: .normal) 132 | iPadExclusiveButton.addTarget(self, action: #selector(iPadExclusiveAction), for: .touchUpInside) 133 | iPadExclusiveButton.translatesAutoresizingMaskIntoConstraints = false 134 | 135 | return iPadExclusiveButton 136 | } 137 | 138 | // MARK: - Actions 139 | 140 | @objc func continueAction(_ sender: UIButton) { 141 | let alert = UIAlertController(title: "Great Success!", message: "You may continue.", preferredStyle: .alert) 142 | let ok = UIAlertAction(title: "Cool", style: .default, handler: nil) 143 | alert.addAction(ok) 144 | present(alert, animated: true, completion: nil) 145 | } 146 | 147 | @objc func iPadExclusiveAction(_ sender: UIButton) { 148 | let alert = UIAlertController(title: "iPad Achieved!", message: "You are holding an iPad.", preferredStyle: .alert) 149 | let ok = UIAlertAction(title: "Nice", style: .default, handler: nil) 150 | alert.addAction(ok) 151 | present(alert, animated: true, completion: nil) 152 | } 153 | } 154 | -------------------------------------------------------------------------------- /Example/Source/ViewControllers/NativeViewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // NativeViewController.swift 3 | // BriggsDemo 4 | // 5 | // Copyright (c) 2017 Ada Turner (https://github.com/auswahlaxiom) 6 | // 7 | // Permission is hereby granted, free of charge, to any person obtaining a copy 8 | // of this software and associated documentation files (the "Software"), to deal 9 | // in the Software without restriction, including without limitation the rights 10 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | // copies of the Software, and to permit persons to whom the Software is 12 | // furnished to do so, subject to the following conditions:// 13 | // 14 | // The above copyright notice and this permission notice shall be included in 15 | // all copies or substantial portions of the Software.// 16 | // 17 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 23 | // THE SOFTWARE. 24 | // 25 | 26 | import UIKit 27 | 28 | /** 29 | A view controller that uses native API to achieve the following adaptive behaviors: 30 | 1. A label that is red when displayed on @2x scale devices with Force Touch capability, and blue for all other devices 31 | 2. A continue button stretches edge-to-edge in horizontal-compact, and has a fixed width in horizontal-regular 32 | 3. An iPad-exclusive button that is centered at the top of the screen 33 | */ 34 | class NativeViewController: UIViewController { 35 | 36 | // MARK: - Static 37 | 38 | struct K { 39 | 40 | static let margin: CGFloat = 12.0 41 | } 42 | 43 | // MARK: - UIViewController 44 | 45 | override func loadView() { 46 | view = UIView() 47 | setupViews() 48 | } 49 | 50 | override func viewDidLoad() { 51 | super.viewDidLoad() 52 | title = "Native API" 53 | } 54 | 55 | override func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) { 56 | super.traitCollectionDidChange(previousTraitCollection) 57 | 58 | // Requirement 1: red text for @2x with force touch, otherwise blue text 59 | let twoX = UITraitCollection(displayScale: 2.0) 60 | let forceTouchAvailable = UITraitCollection(forceTouchCapability: .available) 61 | let forceTouchAvailableAndTwoX = UITraitCollection(traitsFrom: [twoX, forceTouchAvailable]) 62 | 63 | if traitCollection.containsTraits(in: forceTouchAvailableAndTwoX) { 64 | welcomeLabel.textColor = UIColor.red 65 | } else { 66 | welcomeLabel.textColor = UIColor.blue 67 | } 68 | 69 | // Requirement 2: full width in horizontal compact, fixed width in horizontal regular 70 | let horizontalCompact = UITraitCollection(horizontalSizeClass: .compact) 71 | 72 | if traitCollection.containsTraits(in: horizontalCompact) { 73 | continueButtonFixedWidthConstraint.isActive = false 74 | continueButtonFullWidthConstraint.isActive = true 75 | } 76 | 77 | let horizontalRegular = UITraitCollection(horizontalSizeClass: .regular) 78 | 79 | if traitCollection.containsTraits(in: horizontalRegular) { 80 | continueButtonFullWidthConstraint.isActive = false 81 | continueButtonFixedWidthConstraint.isActive = true 82 | } 83 | 84 | // Requirement 3: iPad exclusive button 85 | let idiomPad = UITraitCollection(userInterfaceIdiom: .pad) 86 | 87 | if traitCollection.containsTraits(in: idiomPad) { 88 | if iPadExclusiveButton.superview == nil { 89 | view.addSubview(iPadExclusiveButton) 90 | } 91 | 92 | iPadExclusiveButtonConstraints.forEach { $0.isActive = true } 93 | } else { 94 | iPadExclusiveButtonConstraints.forEach { $0.isActive = false } 95 | iPadExclusiveButton.removeFromSuperview() 96 | } 97 | } 98 | 99 | // MARK: - Interface 100 | 101 | private var welcomeLabel: UILabel! 102 | private var continueButton: UIButton! 103 | private var iPadExclusiveButton: UIButton! 104 | 105 | private var continueButtonFullWidthConstraint: NSLayoutConstraint! 106 | private var continueButtonFixedWidthConstraint: NSLayoutConstraint! 107 | 108 | private var iPadExclusiveButtonConstraints: [NSLayoutConstraint]! 109 | 110 | private func setupViews() { 111 | view.backgroundColor = UIColor.white 112 | 113 | welcomeLabel = createWelcomeLabel() 114 | view.addSubview(welcomeLabel) 115 | 116 | welcomeLabel.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true 117 | welcomeLabel.centerYAnchor.constraint(equalTo: view.centerYAnchor).isActive = true 118 | 119 | continueButton = createContinueButton() 120 | view.addSubview(continueButton) 121 | 122 | bottomLayoutGuide.topAnchor.constraint(equalTo: continueButton.bottomAnchor, constant: K.margin).isActive = true 123 | view.trailingAnchor.constraint(equalTo: continueButton.trailingAnchor, constant: K.margin).isActive = true 124 | continueButton.heightAnchor.constraint(equalToConstant: 45.0).isActive = true 125 | 126 | continueButtonFullWidthConstraint = continueButton.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: K.margin) 127 | continueButtonFixedWidthConstraint = continueButton.widthAnchor.constraint(equalToConstant: 180.0) 128 | 129 | iPadExclusiveButton = createiPadExclusiveButton() 130 | view.addSubview(iPadExclusiveButton) 131 | 132 | iPadExclusiveButtonConstraints = [ 133 | iPadExclusiveButton.centerXAnchor.constraint(equalTo: view.centerXAnchor), 134 | iPadExclusiveButton.topAnchor.constraint(equalTo: topLayoutGuide.bottomAnchor, constant: K.margin) 135 | ] 136 | } 137 | 138 | private func createWelcomeLabel() -> UILabel { 139 | let welcomeLabel = UILabel() 140 | welcomeLabel.text = "Hello World" 141 | welcomeLabel.translatesAutoresizingMaskIntoConstraints = false 142 | 143 | return welcomeLabel 144 | } 145 | 146 | private func createContinueButton() -> UIButton { 147 | let continueButton = UIButton(type: .system) 148 | continueButton.setTitle("Continue", for: .normal) 149 | continueButton.addTarget(self, action: #selector(continueAction), for: .touchUpInside) 150 | continueButton.backgroundColor = UIColor(red: 0.95, green: 0.95, blue: 1.0, alpha: 1.0) 151 | continueButton.layer.borderColor = UIColor(red: 0.5, green: 0.5, blue: 1.0, alpha: 1.0).cgColor 152 | continueButton.layer.borderWidth = 2.0 153 | continueButton.layer.cornerRadius = 4.0 154 | continueButton.translatesAutoresizingMaskIntoConstraints = false 155 | 156 | return continueButton 157 | } 158 | 159 | private func createiPadExclusiveButton() -> UIButton { 160 | let iPadExclusiveButton = UIButton(type: .system) 161 | iPadExclusiveButton.setTitle("iPad Only!", for: .normal) 162 | iPadExclusiveButton.addTarget(self, action: #selector(iPadExclusiveAction), for: .touchUpInside) 163 | iPadExclusiveButton.translatesAutoresizingMaskIntoConstraints = false 164 | 165 | return iPadExclusiveButton 166 | } 167 | 168 | // MARK: - Actions 169 | 170 | @objc func continueAction(_ sender: UIButton) { 171 | let alert = UIAlertController(title: "Great Success!", message: "You may continue.", preferredStyle: .alert) 172 | let ok = UIAlertAction(title: "Cool", style: .default, handler: nil) 173 | alert.addAction(ok) 174 | present(alert, animated: true, completion: nil) 175 | } 176 | 177 | @objc func iPadExclusiveAction(_ sender: UIButton) { 178 | let alert = UIAlertController(title: "iPad Achieved!", message: "You are holding an iPad.", preferredStyle: .alert) 179 | let ok = UIAlertAction(title: "Nice", style: .default, handler: nil) 180 | alert.addAction(ok) 181 | present(alert, animated: true, completion: nil) 182 | } 183 | } 184 | -------------------------------------------------------------------------------- /Example/Source/ViewControllers/SelectionViewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // SelectionViewController.swift 3 | // BriggsDemo 4 | // 5 | // Copyright (c) 2017 Ada Turner (https://github.com/auswahlaxiom) 6 | // 7 | // Permission is hereby granted, free of charge, to any person obtaining a copy 8 | // of this software and associated documentation files (the "Software"), to deal 9 | // in the Software without restriction, including without limitation the rights 10 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | // copies of the Software, and to permit persons to whom the Software is 12 | // furnished to do so, subject to the following conditions:// 13 | // 14 | // The above copyright notice and this permission notice shall be included in 15 | // all copies or substantial portions of the Software.// 16 | // 17 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 23 | // THE SOFTWARE. 24 | // 25 | 26 | import UIKit 27 | 28 | /** 29 | A view controller to select either a Native-implemented demo or a Briggs-implemented demo. 30 | */ 31 | class SelectionViewController: UIViewController, UITableViewDelegate, UITableViewDataSource { 32 | 33 | // MARK: - Types 34 | 35 | enum Option { 36 | 37 | case native 38 | case briggs 39 | 40 | var title: String { 41 | let title: String 42 | 43 | switch self { 44 | case .native: 45 | title = "Native API" 46 | case .briggs: 47 | title = "Briggs API" 48 | } 49 | 50 | return title 51 | } 52 | 53 | func createViewController() -> UIViewController { 54 | let viewController: UIViewController 55 | 56 | switch self { 57 | case .native: 58 | viewController = NativeViewController() 59 | case .briggs: 60 | viewController = BriggsViewController() 61 | } 62 | 63 | return viewController 64 | } 65 | } 66 | 67 | // MARK: - Static 68 | 69 | struct K { 70 | 71 | static let reuseIdentifier = "SelectionReuseIdentifier" 72 | } 73 | 74 | // MARK: - UIViewController 75 | 76 | override func loadView() { 77 | view = UIView() 78 | setupViews() 79 | } 80 | 81 | override func viewDidLoad() { 82 | super.viewDidLoad() 83 | title = "Briggs Demo" 84 | } 85 | 86 | // MARK: - SelectionViewController 87 | 88 | let selections: [Option] = [.native, .briggs] 89 | 90 | // MARK: - UITableViewDataSource 91 | 92 | func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { 93 | let count = selections.count 94 | return count 95 | } 96 | 97 | func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { 98 | let cell = tableView.dequeueReusableCell(withIdentifier: K.reuseIdentifier, for: indexPath) 99 | let selection = selections[indexPath.row] 100 | cell.textLabel?.text = selection.title 101 | 102 | return cell 103 | } 104 | 105 | // MARK: - UITableViewDelegate 106 | 107 | func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { 108 | let selection = selections[indexPath.row] 109 | let viewController = selection.createViewController() 110 | navigationController?.pushViewController(viewController, animated: true) 111 | tableView.deselectRow(at: indexPath, animated: true) 112 | } 113 | 114 | // MARK: - Interface 115 | 116 | private var tableView: UITableView! 117 | 118 | private func setupViews() { 119 | view.backgroundColor = UIColor.white 120 | 121 | tableView = UITableView(frame: CGRect.zero, style: .plain) 122 | tableView.register(UITableViewCell.self, forCellReuseIdentifier: K.reuseIdentifier) 123 | tableView.translatesAutoresizingMaskIntoConstraints = false 124 | tableView.delegate = self 125 | tableView.dataSource = self 126 | view.addSubview(tableView) 127 | 128 | tableView.leadingAnchor.constraint(equalTo: view.leadingAnchor).isActive = true 129 | tableView.topAnchor.constraint(equalTo: view.topAnchor).isActive = true 130 | view.trailingAnchor.constraint(equalTo: tableView.trailingAnchor).isActive = true 131 | view.bottomAnchor.constraint(equalTo: tableView.bottomAnchor).isActive = true 132 | } 133 | } 134 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2017 Ada Turner (https://github.com/auswahlaxiom) 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy 4 | of this software and associated documentation files (the "Software"), to deal 5 | in the Software without restriction, including without limitation the rights 6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | copies of the Software, and to permit persons to whom the Software is 8 | furnished to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in 11 | all copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | THE SOFTWARE. 20 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Briggs 2 | *A reimagination of UITraitCollection* 3 | 4 | [![CocoaPods Compatible](https://img.shields.io/cocoapods/v/Briggs.svg)](https://cocoapods.org/pods/Briggs) 5 | [![Carthage Compatible](https://img.shields.io/badge/carthage-compatible-4BC51D.svg)](https://github.com/Carthage/Carthage) 6 | [![Platform](https://img.shields.io/cocoapods/p/Briggs.svg)](http://cocoadocs.org/docsets/Briggs) 7 | [![Docs](https://img.shields.io/cocoapods/metrics/doc-percent/Briggs.svg)](http://cocoadocs.org/docsets/Briggs) 8 | [![Swift 4.0](https://img.shields.io/badge/Swift-4.0-orange.svg)](https://developer.apple.com/swift/) 9 | [![GitHub license](https://img.shields.io/badge/license-MIT-blue.svg)](https://github.com/auswahlaxiom/Briggs/blob/master/LICENSE) 10 | 11 | As seen on POSSIBLE Mobile Insights! 12 | 13 | - [How UITraitCollection Changed Everything](https://possiblemobile.com/2016/07/adaptive-interfaces-uitraitcollection/) 14 | - [Reimagining UITraitCollection with Briggs](https://possiblemobile.com/2016/08/reimagining-uitraitcollection-with-briggs/) 15 | - [iOS Frameworks Part 2: Build & Ship](https://possiblemobile.com/2016/08/ios-frameworks-part-2-build-and-ship) 16 | 17 | What if setting arbitrary constraints, views, and behaviors for specific trait collections was as easy as: 18 | ```swift 19 | let exclusiveButton = UIButton(type: .system) 20 | let traits: [AdaptiveAttribute] = [ 21 | Idiom.phone, 22 | Scale.twoX, 23 | ForceTouch.available, 24 | SizeClass.verticalRegular, 25 | SizeClass.horizontalCompact, 26 | ] 27 | 28 | addView(for: traits, view: exclusiveButton, parent: view, constraints: [ 29 | exclusiveButton.centerXAnchor.constraintEqualToAnchor(view.centerXAnchor), 30 | exclusiveButton.centerYAnchor.constraintEqualToAnchor(view.centerYAnchor), 31 | ]) 32 | ``` 33 | 34 | ## Abstract 35 | 36 | *UITraitEnvironment is just too cool to be limited to views and view controllers!* 37 | 38 | Briggs seeks to provide a crucial missing component in Apple’s API: `UITraitEnvironment.addChildTraitEnvironment:`, and adds a healthy dose of sugar to `UITraitCollection`. 39 | 40 | ### Components 41 | 42 | - `AdaptiveElement`: The child—receives trait collection information 43 | - `AdaptiveInterface`: The parent—provides trait collection information 44 | - `AdaptiveAttribute`: The trait—describes trait collection information 45 | 46 | ### Containers 47 | 48 | - `AdaptiveBehavior`: Associates a behavior and counter-behavior with a set of traits 49 | 50 | > Behavior is executed if incoming traits match, else counter-behavior is executed. 51 | 52 | - `AdaptiveConstraintContainer`: Associates a set of constraints with a set of traits 53 | 54 | > Constraints are activated if incoming traits match, else they are deactivated. 55 | 56 | - `AdaptiveViewContainer`: Associates a view with a set of traits 57 | 58 | > View is added to hierarchy if traits match, else view is removed. 59 | 60 | ## Requirements 61 | 62 | - iOS 10.0+ 63 | - Xcode 9.0+ 64 | 65 | ## Installation 66 | 67 | ### CocoaPods 68 | 69 | [CocoaPods](http://cocoapods.org) is a dependency manager for Cocoa projects. You can install it with the following command: 70 | 71 | ```bash 72 | $ gem install cocoapods 73 | ``` 74 | 75 | To integrate Briggs into your Xcode project using CocoaPods, specify it in your `Podfile`: 76 | 77 | ```ruby 78 | source 'https://github.com/CocoaPods/Specs.git' 79 | platform :ios, '10.0' 80 | use_frameworks! 81 | 82 | target '' do 83 | pod 'Briggs', '~> 3.0.0' 84 | end 85 | ``` 86 | 87 | Then, run the following command: 88 | 89 | ```bash 90 | $ pod install 91 | ``` 92 | 93 | ### Carthage 94 | 95 | [Carthage](https://github.com/Carthage/Carthage) is a decentralized dependency manager that builds your dependencies and provides you with binary frameworks. 96 | 97 | You can install Carthage with [Homebrew](http://brew.sh/) using the following command: 98 | 99 | ```bash 100 | $ brew update 101 | $ brew install carthage 102 | ``` 103 | 104 | To integrate Briggs into your Xcode project using Carthage, specify it in your `Cartfile`: 105 | 106 | ```ogdl 107 | github "auswahlaxiom/Briggs" ~> 3.0.0 108 | ``` 109 | 110 | Run `carthage update` to build the framework and drag the built `Briggs.framework` into your Xcode project. 111 | 112 | ### Manually 113 | 114 | If you prefer not to use either of the aforementioned dependency managers, you can integrate Briggs into your project manually. 115 | 116 | #### Embedded Framework 117 | 118 | - Open up Terminal, `cd` into your top-level project directory, and run the following command if your project is not initialized as a git repository: 119 | 120 | ```bash 121 | $ git init 122 | ``` 123 | 124 | - Add Briggs as a git [submodule](http://git-scm.com/docs/git-submodule) by running the following command: 125 | 126 | ```bash 127 | $ git submodule add https://github.com/auswahlaxiom/Briggs.git 128 | ``` 129 | 130 | - Open the new `Briggs` folder, and drag the `Briggs.xcodeproj` into the Project Navigator of your application's Xcode project. 131 | 132 | > It should appear nested underneath your application's blue project icon. Whether it is above or below all the other Xcode groups does not matter. 133 | 134 | - Select the `Briggs.xcodeproj` in the Project Navigator and verify the deployment target matches that of your application target. 135 | - Next, select your application project in the Project Navigator (blue project icon) to navigate to the target configuration window and select the application target under the "Targets" heading in the sidebar. 136 | - In the tab bar at the top of that window, open the "General" panel. 137 | - Click on the `+` button under the "Embedded Binaries" section. 138 | - You will see two different `Briggs.xcodeproj` folders. It does not matter which one you select the framework from. 139 | - Select `Briggs.framework` and click `Add`. 140 | 141 | > The `Briggs.framework` is automagically added as a target dependency, linked framework and embedded framework in a copy files build phase which is all you need to build on the simulator and a device. 142 | 143 | - Add `import Briggs` a source file and get coding! 144 | 145 | ## Usage 146 | 147 | For an in-depth dive into Briggs, please visit [Reimagining UITraitCollection with Briggs](https://possiblemobile.com/2016/08/reimagining-uitraitcollection-with-briggs/). 148 | 149 | ## Credits 150 | 151 | Briggs was created by [Ada Turner](https://www.linkedin.com/in/ada-turner-4a663848), an iOS developer at [POSSIBLE Mobile](https://possiblemobile.com/author/ada-turner/). 152 | 153 | ## License 154 | 155 | Briggs is released under the MIT license. See [LICENSE](https://github.com/auswahlaxiom/Briggs/blob/master/LICENSE) for details. 156 | -------------------------------------------------------------------------------- /Source/AdaptiveAttribute.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AdaptiveAttribute.swift 3 | // Briggs 4 | // 5 | // Copyright (c) 2017 Ada Turner (https://github.com/auswahlaxiom) 6 | // 7 | // Permission is hereby granted, free of charge, to any person obtaining a copy 8 | // of this software and associated documentation files (the "Software"), to deal 9 | // in the Software without restriction, including without limitation the rights 10 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | // copies of the Software, and to permit persons to whom the Software is 12 | // furnished to do so, subject to the following conditions:// 13 | // 14 | // The above copyright notice and this permission notice shall be included in 15 | // all copies or substantial portions of the Software.// 16 | // 17 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 23 | // THE SOFTWARE. 24 | // 25 | 26 | import UIKit 27 | 28 | /** 29 | An `AdaptiveAttribute` represents a trait in a `UITraitCollection`. 30 | */ 31 | public protocol AdaptiveAttribute { 32 | 33 | /** 34 | Creates a `UITraitCollection` corresponding to the trait `self` represents 35 | */ 36 | func generateTraitCollection() -> UITraitCollection 37 | } 38 | -------------------------------------------------------------------------------- /Source/AdaptiveAttributeTraitCollectionExtension.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AdaptiveAttributeTraitCollectionExtension.swift 3 | // Briggs 4 | // 5 | // Copyright (c) 2017 Ada Turner (https://github.com/auswahlaxiom) 6 | // 7 | // Permission is hereby granted, free of charge, to any person obtaining a copy 8 | // of this software and associated documentation files (the "Software"), to deal 9 | // in the Software without restriction, including without limitation the rights 10 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | // copies of the Software, and to permit persons to whom the Software is 12 | // furnished to do so, subject to the following conditions:// 13 | // 14 | // The above copyright notice and this permission notice shall be included in 15 | // all copies or substantial portions of the Software.// 16 | // 17 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 23 | // THE SOFTWARE. 24 | // 25 | 26 | import UIKit 27 | 28 | /** 29 | This extension provides a mapping between `AdaptiveAttribute` and `UITraitCollection`. 30 | */ 31 | public extension UITraitCollection { 32 | 33 | /** 34 | Create a `UITraitCollection` from one or more `AdaptiveAttribute`s. 35 | 36 | - parameter attributes: Array of `AdaptiveAttribute` from which a new `UITraitCollection` will be created 37 | - returns: A new `UITraitCollection` containing the traits of each `AdaptiveAttribute` 38 | */ 39 | public static func create(with attributes: [AdaptiveAttribute]) -> UITraitCollection { 40 | let traitCollections = attributes.map { $0.generateTraitCollection() } 41 | return self.init(traitsFrom: traitCollections) 42 | } 43 | 44 | /** 45 | Check if the `UITraitCollection` contains an `AdaptiveAttribute`. 46 | 47 | - parameter attribute: The `AdaptiveAttribute` we want to find in the `UITraitCollection` 48 | - returns: Returns `true` if the `UITraitCollection` contains the `AdaptiveAttribute`, else, `false` 49 | */ 50 | public func contains(_ attribute: AdaptiveAttribute) -> Bool { 51 | return containsTraits(in: attribute.generateTraitCollection()) 52 | } 53 | 54 | /** 55 | Array of `AdaptiveAttribute`s that describe the `self` 56 | */ 57 | public var adaptiveAttributes: [AdaptiveAttribute] { 58 | var attributes: [AdaptiveAttribute] = [] 59 | 60 | switch userInterfaceIdiom { 61 | case .pad: attributes.append(Idiom.pad) 62 | case .phone: attributes.append(Idiom.phone) 63 | case .tv: attributes.append(Idiom.tv) 64 | case .carPlay: attributes.append(Idiom.carPlay) 65 | case .unspecified: break 66 | } 67 | 68 | switch displayScale { 69 | case 1.0: attributes.append(Scale.oneX) 70 | case 2.0: attributes.append(Scale.twoX) 71 | case 3.0: attributes.append(Scale.threeX) 72 | case 4.0: attributes.append(Scale.fourX) 73 | default: break 74 | } 75 | 76 | switch horizontalSizeClass { 77 | case .compact: attributes.append(SizeClass.horizontalCompact) 78 | case .regular: attributes.append(SizeClass.horizontalRegular) 79 | case .unspecified: break 80 | } 81 | 82 | switch verticalSizeClass { 83 | case .compact: attributes.append(SizeClass.verticalCompact) 84 | case .regular: attributes.append(SizeClass.verticalRegular) 85 | case .unspecified: break 86 | } 87 | 88 | switch forceTouchCapability { 89 | case .available: attributes.append(ForceTouch.available) 90 | case .unavailable: attributes.append(ForceTouch.unavailable) 91 | case .unknown: break 92 | } 93 | 94 | switch layoutDirection { 95 | case .leftToRight: attributes.append(LayoutDirection.leftToRight) 96 | case .rightToLeft: attributes.append(LayoutDirection.rightToLeft) 97 | case .unspecified: break 98 | } 99 | 100 | switch preferredContentSizeCategory { 101 | case .extraSmall: attributes.append(SizeCategory.extraSmall) 102 | case .small: attributes.append(SizeCategory.small) 103 | case .medium: attributes.append(SizeCategory.medium) 104 | case .large: attributes.append(SizeCategory.large) 105 | case .extraLarge: attributes.append(SizeCategory.extraLarge) 106 | case .extraExtraLarge: attributes.append(SizeCategory.extraExtraLarge) 107 | case .extraExtraExtraLarge: attributes.append(SizeCategory.extraExtraExtraLarge) 108 | case .accessibilityMedium: attributes.append(SizeCategory.accessibilityMedium) 109 | case .accessibilityLarge: attributes.append(SizeCategory.accessibilityLarge) 110 | case .accessibilityExtraLarge: attributes.append(SizeCategory.accessibilityExtraLarge) 111 | case .accessibilityExtraExtraLarge: attributes.append(SizeCategory.accessibilityExtraExtraLarge) 112 | case .accessibilityExtraExtraExtraLarge: attributes.append(SizeCategory.accessibilityExtraExtraExtraLarge) 113 | default: break 114 | } 115 | 116 | switch displayGamut { 117 | case .SRGB: attributes.append(DisplayGamut.SRGB) 118 | case .P3: attributes.append(DisplayGamut.P3) 119 | case .unspecified: break 120 | } 121 | 122 | return attributes 123 | } 124 | } 125 | -------------------------------------------------------------------------------- /Source/AdaptiveBehavior.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AdaptiveBehavior.swift 3 | // Briggs 4 | // 5 | // Copyright (c) 2017 Ada Turner (https://github.com/auswahlaxiom) 6 | // 7 | // Permission is hereby granted, free of charge, to any person obtaining a copy 8 | // of this software and associated documentation files (the "Software"), to deal 9 | // in the Software without restriction, including without limitation the rights 10 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | // copies of the Software, and to permit persons to whom the Software is 12 | // furnished to do so, subject to the following conditions:// 13 | // 14 | // The above copyright notice and this permission notice shall be included in 15 | // all copies or substantial portions of the Software.// 16 | // 17 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 23 | // THE SOFTWARE. 24 | // 25 | 26 | import UIKit 27 | 28 | /** 29 | A container that relates a `behavior` and `counterBehavior` to a `UITraitCollection`. 30 | 31 | When updating for an incoming `UITraitCollection`, if it contains `self.traitCollection`, `behavior` will be executed, else, `counterBehavior` will be executed if it exists. 32 | */ 33 | public struct AdaptiveBehavior: AdaptiveElement { 34 | 35 | /// A `Behavior` is a closure that takes nothing and returns nothing 36 | public typealias Behavior = () -> Void 37 | 38 | /// `UITraitCollection` associated with `behavior`. 39 | public let traitCollection: UITraitCollection 40 | /// `Behavior` executed in `update(for incomingTraitCollection:)` if `incomingTraitCollection` contains `traitCollection` 41 | public let behavior: Behavior 42 | /// Optional `Behavior` executed in `update(for incomingTraitCollection:)` if `incomingTraitCollection` does *not* contain `traitCollection` 43 | public let counterBehavior: Behavior? 44 | 45 | /** 46 | Update the `AdaptiveBehavior` with a new `UITraitCollection` which executes one of its behaviors. 47 | 48 | When updating for an incoming `UITraitCollection`, if it contains `self.traitCollection`, `behavior` will be executed, else, `counterBehavior` will be executed. 49 | 50 | - parameter incomingTraitCollection: The `UITraitCollection` which determines if we execute `behavior` or `counterBehavior`. 51 | */ 52 | public func update(for incomingTraitCollection: UITraitCollection) { 53 | if incomingTraitCollection.containsTraits(in: traitCollection) { 54 | behavior() 55 | } else { 56 | counterBehavior?() 57 | } 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /Source/AdaptiveConstraintContainer.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AdaptiveConstraintContainer.swift 3 | // Briggs 4 | // 5 | // Copyright (c) 2017 Ada Turner (https://github.com/auswahlaxiom) 6 | // 7 | // Permission is hereby granted, free of charge, to any person obtaining a copy 8 | // of this software and associated documentation files (the "Software"), to deal 9 | // in the Software without restriction, including without limitation the rights 10 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | // copies of the Software, and to permit persons to whom the Software is 12 | // furnished to do so, subject to the following conditions:// 13 | // 14 | // The above copyright notice and this permission notice shall be included in 15 | // all copies or substantial portions of the Software.// 16 | // 17 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 23 | // THE SOFTWARE. 24 | // 25 | 26 | import UIKit 27 | 28 | /** 29 | A container that relates a collection of `NSLayoutConstraint`s to a `UITraitCollection`. 30 | 31 | When updating for an incoming `UITraitCollection`, if it contains `self.traitCollection`, the `constraints` will be activated, else, deactivated. 32 | */ 33 | public struct AdaptiveConstraintContainer: AdaptiveElement { 34 | 35 | /// `UITraitCollection` associated with `constraints`. 36 | public let traitCollection: UITraitCollection 37 | /// Array of `NSLayoutConstraint` activated or deactivated in `update(for incomingTraitCollection:)` if `incomingTraitCollection` does or does not contain `traitCollection`, respectively 38 | public let constraints: [NSLayoutConstraint] 39 | 40 | /** 41 | Update the `AdaptiveConstraintContainer` with a new `UITraitCollection` which activates or deactivates constraints. 42 | 43 | When updating for an incoming `UITraitCollection`, if it contains `self.traitCollection`, the `constraints` will be activated, else, deactivated. 44 | 45 | - parameter incomingTraitCollection: The `UITraitCollection` which determines if we activate or deactivate `constraints`. 46 | */ 47 | public func update(for incomingTraitCollection: UITraitCollection) { 48 | if incomingTraitCollection.containsTraits(in: traitCollection) { 49 | NSLayoutConstraint.activate(constraints) 50 | } else { 51 | NSLayoutConstraint.deactivate(constraints) 52 | } 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /Source/AdaptiveElement.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AdaptiveElement.swift 3 | // Briggs 4 | // 5 | // Copyright (c) 2017 Ada Turner (https://github.com/auswahlaxiom) 6 | // 7 | // Permission is hereby granted, free of charge, to any person obtaining a copy 8 | // of this software and associated documentation files (the "Software"), to deal 9 | // in the Software without restriction, including without limitation the rights 10 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | // copies of the Software, and to permit persons to whom the Software is 12 | // furnished to do so, subject to the following conditions:// 13 | // 14 | // The above copyright notice and this permission notice shall be included in 15 | // all copies or substantial portions of the Software.// 16 | // 17 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 23 | // THE SOFTWARE. 24 | // 25 | 26 | import UIKit 27 | 28 | /** 29 | An `AdaptiveElement` tracks its own `UITraitCollection` and can react to external `UITraitCollection`s. 30 | 31 | `AdaptiveElement` represents the receiving child in an inheritence hierarchy of parent-child relationships passing trait information. 32 | */ 33 | public protocol AdaptiveElement { 34 | 35 | /** 36 | Internal `UITraitCollection` 37 | */ 38 | var traitCollection: UITraitCollection { get } 39 | 40 | /** 41 | Implement to react to external `UITraitCollections`. A reaction could be: 42 | 43 | - To update `self.traitCollection` to match the outside environment 44 | - To compare `self.traitCollection` against `incomingTraitCollection` to enact some behavior 45 | - To simply perform some action using `incomingTraitCollection` 46 | 47 | - parameter incomingTraitCollection: An external `UITraitCollection`. 48 | */ 49 | func update(for incomingTraitCollection: UITraitCollection) 50 | } 51 | -------------------------------------------------------------------------------- /Source/AdaptiveInterface.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AdaptiveInterface.swift 3 | // Briggs 4 | // 5 | // Copyright (c) 2017 Ada Turner (https://github.com/auswahlaxiom) 6 | // 7 | // Permission is hereby granted, free of charge, to any person obtaining a copy 8 | // of this software and associated documentation files (the "Software"), to deal 9 | // in the Software without restriction, including without limitation the rights 10 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | // copies of the Software, and to permit persons to whom the Software is 12 | // furnished to do so, subject to the following conditions:// 13 | // 14 | // The above copyright notice and this permission notice shall be included in 15 | // all copies or substantial portions of the Software.// 16 | // 17 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 23 | // THE SOFTWARE. 24 | // 25 | 26 | import UIKit 27 | 28 | /** 29 | An `AdaptiveInterface` contains a collection of `AdaptiveElement`s and forwards `update(for incomingTraitCollection:)` to each of them. 30 | 31 | `AdaptiveInterface` represents the supplying parent in an inheritence hierarchy of parent-child relationships passing trait information. 32 | 33 | Recommended override for `UITraitEnvironment`s: 34 | ``` 35 | override func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) { 36 | super.traitCollectionDidChange(previousTraitCollection) 37 | update(for: traitCollection) 38 | } 39 | ``` 40 | 41 | Extension methods provide conveniences for adding `Behavior`s, `NSLayoutConstraint`s, and `UIView`s with associated `UITraitCollection`s. These are stored in `AdaptiveElement`-conforming containers which append to `self.adaptiveElements`. 42 | 43 | `AdaptiveInterface` is a class-only protocol to allow for mutating extension methods. 44 | */ 45 | public protocol AdaptiveInterface: class, AdaptiveElement { 46 | 47 | /** 48 | `adaptiveElements` represent `self`'s children. Each element will be forwarded calls to `update(for incomingTraitCollection:)` that `self` recieves. 49 | */ 50 | var adaptiveElements: [AdaptiveElement] { get set } 51 | } 52 | 53 | /** 54 | The default implementation of `update(for incomingTraitCollection:)` forwards `update(for incomingTraitCollection:)` to each item in `self.adaptiveElements`. 55 | */ 56 | public extension AdaptiveInterface { 57 | 58 | /** 59 | Default `AdaptiveInterface` implementation forwards `update(for incomingTraitCollection:)` to each of `self`'s children. 60 | 61 | - note: Child adaptive elements whose `traitCollection` is *not* contained by `incomingTraitCollection` are updated first to avoid conflicting behaviors being active at the same time. 62 | */ 63 | public func update(for incomingTraitCollection: UITraitCollection) { 64 | adaptiveElements.filter { incomingTraitCollection.containsTraits(in: $0.traitCollection) == false }.forEach { $0.update(for: incomingTraitCollection) } 65 | adaptiveElements.filter { incomingTraitCollection.containsTraits(in: $0.traitCollection) == true }.forEach { $0.update(for: incomingTraitCollection) } 66 | } 67 | } 68 | 69 | /** 70 | Convenience methods for adding `AdaptiveBehavior`s, `AdaptiveConstraintContainer`s, and `AdaptiveViewContainer`s. 71 | 72 | Each has a raw form, which takes a `UITraitCollection`, and two wrappers which take one or more `AdaptiveAttribute`s. 73 | */ 74 | public extension AdaptiveInterface { 75 | 76 | // MARK: - Convenience Methods 77 | 78 | // MARK: Add Behavior 79 | 80 | /** 81 | Add a `Behavior` and counter-`Behavior` for a `UITraitCollection` 82 | 83 | Convenience for creating an `AdaptiveBehavior` and adding it to `self.adaptiveElements` 84 | 85 | - parameter traitCollection: `UITraitCollection` for which `behavior` will be executed 86 | - parameter behavior: `Behavior` to be executed if `incomingTraitCollection` contains `traitCollection` when `update(for incomingTraitCollection:)` is called 87 | - parameter counterBehavior: Optional `Behavior` (defaults to `nil`) to be executed if `incomingTraitCollection` does not contain `traitCollection` when `update(for incomingTraitCollection:)` is called 88 | */ 89 | public func addBehavior(for traitCollection: UITraitCollection, behavior: @escaping AdaptiveBehavior.Behavior, counterBehavior: AdaptiveBehavior.Behavior? = nil) { 90 | let adaptiveBehavior = AdaptiveBehavior(traitCollection: traitCollection, behavior: behavior, counterBehavior: counterBehavior) 91 | 92 | adaptiveElements.append(adaptiveBehavior) 93 | } 94 | 95 | /** 96 | Add a `Behavior` and counter-`Behavior` for a set of `AdaptiveAttribute`s 97 | 98 | Convenience for creating an `AdaptiveBehavior` and adding it to `self.adaptiveElements` 99 | 100 | - parameter attributes: Array of `AdaptiveAttribute`s used to create a `UITraitCollection` for which `behavior` will be executed 101 | - parameter behavior: `Behavior` to be executed if `incomingTraitCollection` contains `traitCollection` when `update(for incomingTraitCollection:)` is called 102 | - parameter counterBehavior: Optional `Behavior` (defaults to `nil`) to be executed if `incomingTraitCollection` does not contain `traitCollection` when `update(for incomingTraitCollection:)` is called 103 | */ 104 | public func addBehavior(for attributes: [AdaptiveAttribute], behavior: @escaping AdaptiveBehavior.Behavior, counterBehavior: AdaptiveBehavior.Behavior? = nil) { 105 | let traitCollection = UITraitCollection.create(with: attributes) 106 | addBehavior(for: traitCollection, behavior: behavior, counterBehavior: counterBehavior) 107 | } 108 | 109 | /** 110 | Add a `Behavior` and counter-`Behavior` for a single `AdaptiveAttribute` 111 | 112 | Convenience for creating an `AdaptiveBehavior` and adding it to `self.adaptiveElements` 113 | 114 | - parameter attribute: Single `AdaptiveAttribute` used to create a `UITraitCollection` for which `behavior` will be executed 115 | - parameter behavior: `Behavior` to be executed if `incomingTraitCollection` contains `traitCollection` when `update(for incomingTraitCollection:)` is called 116 | - parameter counterBehavior: Optional `Behavior` (defaults to `nil`) to be executed if `incomingTraitCollection` does not contain `traitCollection` when `update(for incomingTraitCollection:)` is called 117 | */ 118 | public func addBehavior(for attribute: AdaptiveAttribute, behavior: @escaping AdaptiveBehavior.Behavior, counterBehavior: AdaptiveBehavior.Behavior? = nil) { 119 | let traitCollection = UITraitCollection.create(with: [attribute]) 120 | addBehavior(for: traitCollection, behavior: behavior, counterBehavior: counterBehavior) 121 | } 122 | 123 | // MARK: Add NSLayoutConstraints 124 | 125 | /** 126 | Add an array of `NSLayoutConstraint`s for a `UITraitCollection` 127 | 128 | Convenience for creating an `AdaptiveConstraintContainer` and adding it to `self.adaptiveElements` 129 | 130 | - parameter traitCollection: `UITraitCollection` for which `constraints` will be activated 131 | - parameter constraints: Array of `NSLayoutConstraint`s to be activated if `incomingTraitCollection` contains `traitCollection` when `update(for incomingTraitCollection:)` is called 132 | */ 133 | public func addConstraints(for traitCollection: UITraitCollection, constraints: [NSLayoutConstraint]) { 134 | let container = AdaptiveConstraintContainer(traitCollection: traitCollection, constraints: constraints) 135 | 136 | adaptiveElements.append(container) 137 | } 138 | 139 | /** 140 | Add an array of `NSLayoutConstraint`s for a set of `AdaptiveAttribute`s 141 | 142 | Convenience for creating an `AdaptiveConstraintContainer` and adding it to `self.adaptiveElements` 143 | 144 | - parameter attributes: Array of `AdaptiveAttribute`s used to create a `UITraitCollection` for which `constraints` will be activated 145 | - parameter constraints: Variadic array of `NSLayoutConstraint`s to be activated if `incomingTraitCollection` contains `traitCollection` when `update(for incomingTraitCollection:)` is called 146 | */ 147 | public func addConstraints(for attributes: [AdaptiveAttribute], constraints: NSLayoutConstraint...) { 148 | let traitCollection = UITraitCollection.create(with: attributes) 149 | addConstraints(for: traitCollection, constraints: constraints) 150 | } 151 | 152 | /** 153 | Add an array of `NSLayoutConstraint`s for a single `AdaptiveAttribute` 154 | 155 | Convenience for creating an `AdaptiveConstraintContainer` and adding it to `self.adaptiveElements` 156 | 157 | - parameter attribute: Single `AdaptiveAttribute` used to create a `UITraitCollection` for which `constraints` will be activated 158 | - parameter constraints: Variadic array of `NSLayoutConstraint`s to be activated if `incomingTraitCollection` contains `traitCollection` when `update(for incomingTraitCollection:)` is called 159 | */ 160 | public func addConstraints(for attribute: AdaptiveAttribute, constraints: NSLayoutConstraint...) { 161 | let traitCollection = UITraitCollection.create(with: [attribute]) 162 | addConstraints(for: traitCollection, constraints: constraints) 163 | } 164 | 165 | // MARK: Add UIViews 166 | 167 | /** 168 | Add a `UIView` and associated array of `NSLayoutConstraint`s for a `UITraitCollection` 169 | 170 | Convenience for creating an `AdaptiveViewContainer` and optional `AdaptiveConstraintContainer` and adding them to `self.adaptiveElements` 171 | 172 | - parameter traitCollection: `UITraitCollection` for which `view` will be added to `parent` and `constraints` will be activated 173 | - parameter view: `UIView` to be added to `parent` if `incomingTraitCollection` contains `traitCollection` when `update(for incomingTraitCollection:)` is called 174 | - parameter parent: `UIView` to which `view` will be added 175 | - parameter constraints: Optional array of `NSLayoutConstraint`s (defaults to `[]`) used to create an `AdaptiveViewContainer` which will be added alongside the `AdaptiveViewContainer`. Use to specify constraints relating to `view` that will be activated under the same conditions that `view` is added to `parent`. 176 | */ 177 | public func addView(for traitCollection: UITraitCollection, view: UIView, parent: UIView, constraints: @autoclosure () -> [NSLayoutConstraint] = []) { 178 | // Add view to parent, so constraints can be created if they are supplied. Will be removed in updateForTraitCollection if necessary. 179 | parent.addSubview(view) 180 | 181 | let viewContainer = AdaptiveViewContainer(traitCollection: traitCollection, parent: parent, child: view) 182 | adaptiveElements.append(viewContainer) 183 | 184 | // `constraints` is an autoclosure because constraints relating `view` to `parent` or its superviews cannot be instantiated until `view` is in `parent`'s heirarchy 185 | let constructedConstraints = constraints() 186 | 187 | if constructedConstraints.isEmpty == false { 188 | let constraintContainer = AdaptiveConstraintContainer(traitCollection: traitCollection, constraints: constructedConstraints) 189 | adaptiveElements.append(constraintContainer) 190 | } 191 | } 192 | 193 | /** 194 | Add a `UIView` and associated array of `NSLayoutConstraint`s for a set of `AdaptiveAttribute`s 195 | 196 | Convenience for creating an `AdaptiveViewContainer` and optional `AdaptiveConstraintContainer` and adding them to `self.adaptiveElements` 197 | 198 | - parameter attributes: Array of `AdaptiveAttribute`s used to create a `UITraitCollection` for which `view` will be added to `parent` and `constraints` will be activated 199 | - parameter view: `UIView` to be added to `parent` if `incomingTraitCollection` contains `traitCollection` when `update(for incomingTraitCollection:)` is called 200 | - parameter parent: `UIView` to which `view` will be added 201 | - parameter constraints: Optional array of `NSLayoutConstraint`s (defaults to `[]`) used to create an `AdaptiveViewContainer` which will be added alongside the `AdaptiveViewContainer`. Use to specify constraints relating to `view` that will be activated under the same conditions that `view` is added to `parent`. 202 | */ 203 | public func addView(for attributes: [AdaptiveAttribute], view: UIView, parent: UIView, constraints: @autoclosure () -> [NSLayoutConstraint] = []) { 204 | let traitCollection = UITraitCollection.create(with: attributes) 205 | addView(for: traitCollection, view: view, parent: parent, constraints: constraints) 206 | } 207 | 208 | /** 209 | Add a `UIView` and associated array of `NSLayoutConstraint`s for a single `AdaptiveAttribute` 210 | 211 | Convenience for creating an `AdaptiveViewContainer` and optional `AdaptiveConstraintContainer` and adding them to `self.adaptiveElements` 212 | 213 | - parameter attribute: Single `AdaptiveAttribute` used to create a `UITraitCollection` for which `view` will be added to `parent` and `constraints` will be activated 214 | - parameter view: `UIView` to be added to `parent` if `incomingTraitCollection` contains `traitCollection` when `update(for incomingTraitCollection:)` is called 215 | - parameter parent: `UIView` to which `view` will be added 216 | - parameter constraints: Optional array of `NSLayoutConstraint`s (defaults to `[]`) used to create an `AdaptiveViewContainer` which will be added alongside the `AdaptiveViewContainer`. Use to specify constraints relating to `view` that will be activated under the same conditions that `view` is added to `parent`. 217 | */ 218 | public func addView(for attribute: AdaptiveAttribute, view: UIView, parent: UIView, constraints: @autoclosure () -> [NSLayoutConstraint] = []) { 219 | let traitCollection = UITraitCollection.create(with: [attribute]) 220 | addView(for: traitCollection, view: view, parent: parent, constraints: constraints) 221 | } 222 | } 223 | -------------------------------------------------------------------------------- /Source/AdaptiveViewContainer.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AdaptiveViewContainer.swift 3 | // Briggs 4 | // 5 | // Copyright (c) 2017 Ada Turner (https://github.com/auswahlaxiom) 6 | // 7 | // Permission is hereby granted, free of charge, to any person obtaining a copy 8 | // of this software and associated documentation files (the "Software"), to deal 9 | // in the Software without restriction, including without limitation the rights 10 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | // copies of the Software, and to permit persons to whom the Software is 12 | // furnished to do so, subject to the following conditions:// 13 | // 14 | // The above copyright notice and this permission notice shall be included in 15 | // all copies or substantial portions of the Software.// 16 | // 17 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 23 | // THE SOFTWARE. 24 | // 25 | 26 | import UIKit 27 | 28 | /** 29 | A container that relates a `parent` and `child` `UIView` to a `UITraitCollection`. 30 | 31 | When updating for an incoming `UITraitCollection`, if it contains `self.traitCollection`, the `parent` will add the `child` as a subview if it is not already added, else, it will remove the `child` from its `parent`. 32 | */ 33 | public struct AdaptiveViewContainer: AdaptiveElement { 34 | 35 | /// `UITraitCollection` associated with `child`. 36 | public let traitCollection: UITraitCollection 37 | /// `UIView` that will add `child` as a subview in `update(for incomingTraitCollection:)` if `incomingTraitCollection` contains `traitCollection` 38 | public unowned let parent: UIView 39 | /// `UIView` that will be added to `parent` as a subview or removed from its `superview` in `update(for incomingTraitCollection:)` if `incomingTraitCollection` does or does not contain `traitCollection`, respectively 40 | public let child: UIView 41 | 42 | /** 43 | Update the `AdaptiveViewContainer` with a new `UITraitCollection` which adds or removes `child` from `parent`. 44 | 45 | When updating for an incoming `UITraitCollection`, if it contains `self.traitCollection`, the `parent` will add the `child` as a subview if it is not already added, else, it will remove the `child` from its `superview`. 46 | 47 | - parameter incomingTraitCollection: The `UITraitCollection` which determines if we add or remove `child`. 48 | */ 49 | public func update(for incomingTraitCollection: UITraitCollection) { 50 | if incomingTraitCollection.containsTraits(in: traitCollection) { 51 | if child.superview != parent { 52 | parent.addSubview(child) 53 | } 54 | } else { 55 | if child.superview != nil { 56 | child.removeFromSuperview() 57 | } 58 | } 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /Source/Briggs.h: -------------------------------------------------------------------------------- 1 | // 2 | // Briggs.h 3 | // Briggs 4 | // 5 | // Copyright (c) 2017 Ada Turner (https://github.com/auswahlaxiom) 6 | // 7 | // Permission is hereby granted, free of charge, to any person obtaining a copy 8 | // of this software and associated documentation files (the "Software"), to deal 9 | // in the Software without restriction, including without limitation the rights 10 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | // copies of the Software, and to permit persons to whom the Software is 12 | // furnished to do so, subject to the following conditions:// 13 | // 14 | // The above copyright notice and this permission notice shall be included in 15 | // all copies or substantial portions of the Software.// 16 | // 17 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 23 | // THE SOFTWARE. 24 | // 25 | // Created by Ada Turner on 8/9/16. 26 | // Copyright © 2016 Auswahlaxiom. All rights reserved. 27 | // 28 | 29 | #import 30 | 31 | //! Project version number for Briggs. 32 | FOUNDATION_EXPORT double BriggsVersionNumber; 33 | 34 | //! Project version string for Briggs. 35 | FOUNDATION_EXPORT const unsigned char BriggsVersionString[]; 36 | 37 | // In this header, you should import all the public headers of your framework using statements like #import 38 | 39 | 40 | -------------------------------------------------------------------------------- /Source/DisplayGamut.swift: -------------------------------------------------------------------------------- 1 | // 2 | // DisplayGamut.swift 3 | // Briggs 4 | // 5 | // Copyright (c) 2017 Ada Turner (https://github.com/auswahlaxiom) 6 | // 7 | // Permission is hereby granted, free of charge, to any person obtaining a copy 8 | // of this software and associated documentation files (the "Software"), to deal 9 | // in the Software without restriction, including without limitation the rights 10 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | // copies of the Software, and to permit persons to whom the Software is 12 | // furnished to do so, subject to the following conditions:// 13 | // 14 | // The above copyright notice and this permission notice shall be included in 15 | // all copies or substantial portions of the Software.// 16 | // 17 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 23 | // THE SOFTWARE. 24 | // 25 | 26 | import UIKit 27 | 28 | /** 29 | `AdaptiveAttribute` correlating to `init(displayGamut: UIDisplayGamut)` 30 | */ 31 | public enum DisplayGamut: AdaptiveAttribute { 32 | 33 | /// Corelates to `UITraitCollection(displayGamut: .SRGB)` 34 | case SRGB 35 | /// Corelates to `UITraitCollection(displayGamut: .P3)` 36 | case P3 37 | 38 | /** 39 | Creates `UITraitCollection` with correlating `UIUserInterfaceDisplayGamut` 40 | 41 | - returns: New `UITraitCollection` with correlating `displayGamut` 42 | */ 43 | public func generateTraitCollection() -> UITraitCollection { 44 | switch self { 45 | case .SRGB: return UITraitCollection(displayGamut: .SRGB) 46 | case .P3: return UITraitCollection(displayGamut: .P3) 47 | } 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /Source/ForceTouch.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ForceTouch.swift 3 | // Briggs 4 | // 5 | // Copyright (c) 2017 Ada Turner (https://github.com/auswahlaxiom) 6 | // 7 | // Permission is hereby granted, free of charge, to any person obtaining a copy 8 | // of this software and associated documentation files (the "Software"), to deal 9 | // in the Software without restriction, including without limitation the rights 10 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | // copies of the Software, and to permit persons to whom the Software is 12 | // furnished to do so, subject to the following conditions:// 13 | // 14 | // The above copyright notice and this permission notice shall be included in 15 | // all copies or substantial portions of the Software.// 16 | // 17 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 23 | // THE SOFTWARE. 24 | // 25 | 26 | import UIKit 27 | 28 | /** 29 | `AdaptiveAttribute` correlating to `UITraitCollection.init(forceTouchCapability capability: UIForceTouchCapability)` 30 | */ 31 | public enum ForceTouch: AdaptiveAttribute { 32 | 33 | /// Correlates to `UITraitCollection(forceTouchCapability: .unavailable) 34 | case unavailable 35 | /// Corelates to `UITraitCollection(forceTouchCapability: .available) 36 | case available 37 | 38 | /** 39 | Creates `UITraitCollection` with correlating `UIForceTouchCapability` 40 | 41 | - returns: New `UITraitCollection` with correlating `forceTouchCapability` 42 | */ 43 | public func generateTraitCollection() -> UITraitCollection { 44 | switch self { 45 | case .unavailable: return UITraitCollection(forceTouchCapability: .unavailable) 46 | case .available: return UITraitCollection(forceTouchCapability: .available) 47 | } 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /Source/Idiom.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Idiom.swift 3 | // Briggs 4 | // 5 | // Copyright (c) 2017 Ada Turner (https://github.com/auswahlaxiom) 6 | // 7 | // Permission is hereby granted, free of charge, to any person obtaining a copy 8 | // of this software and associated documentation files (the "Software"), to deal 9 | // in the Software without restriction, including without limitation the rights 10 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | // copies of the Software, and to permit persons to whom the Software is 12 | // furnished to do so, subject to the following conditions:// 13 | // 14 | // The above copyright notice and this permission notice shall be included in 15 | // all copies or substantial portions of the Software.// 16 | // 17 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 23 | // THE SOFTWARE. 24 | // 25 | 26 | import UIKit 27 | 28 | /** 29 | `AdaptiveAttribute` correlating to `UITraitCollection.init(userInterfaceIdiom idiom: UIUserInterfaceIdiom)` 30 | */ 31 | public enum Idiom: AdaptiveAttribute { 32 | 33 | /// Corelates to `UITraitCollection(userInterfaceIdiom: .phone)` 34 | case phone 35 | /// Corelates to `UITraitCollection(userInterfaceIdiom: .pad)` 36 | case pad 37 | /// Corelates to `UITraitCollection(userInterfaceIdiom: .tv)` 38 | case tv 39 | /// Corelates to `UITraitCollection(userInterfaceIdiom: .carPlay)` 40 | case carPlay 41 | 42 | /** 43 | Creates `UITraitCollection` with correlating `UIUserInterfaceIdiom` 44 | 45 | - returns: New `UITraitCollection` with correlating `userInterfaceIdiom` 46 | */ 47 | public func generateTraitCollection() -> UITraitCollection { 48 | switch self { 49 | case .phone: return UITraitCollection(userInterfaceIdiom: .phone) 50 | case .pad: return UITraitCollection(userInterfaceIdiom: .pad) 51 | case .tv: return UITraitCollection(userInterfaceIdiom: .tv) 52 | case .carPlay: return UITraitCollection(userInterfaceIdiom: .carPlay) 53 | } 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /Source/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 | 3.0.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | $(CURRENT_PROJECT_VERSION) 23 | NSPrincipalClass 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /Source/LayoutDirection.swift: -------------------------------------------------------------------------------- 1 | // 2 | // LayoutDirection.swift 3 | // Briggs 4 | // 5 | // Copyright (c) 2017 Ada Turner (https://github.com/auswahlaxiom) 6 | // 7 | // Permission is hereby granted, free of charge, to any person obtaining a copy 8 | // of this software and associated documentation files (the "Software"), to deal 9 | // in the Software without restriction, including without limitation the rights 10 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | // copies of the Software, and to permit persons to whom the Software is 12 | // furnished to do so, subject to the following conditions:// 13 | // 14 | // The above copyright notice and this permission notice shall be included in 15 | // all copies or substantial portions of the Software.// 16 | // 17 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 23 | // THE SOFTWARE. 24 | // 25 | 26 | import UIKit 27 | 28 | /** 29 | `AdaptiveAttribute` correlating to `init(layoutDirection: UITraitEnvironmentLayoutDirection)` 30 | */ 31 | public enum LayoutDirection: AdaptiveAttribute { 32 | 33 | /// Corelates to `UITraitCollection(layoutDirection: .leftToRight)` 34 | case leftToRight 35 | /// Corelates to `UITraitCollection(layoutDirection: .rightToLeft)` 36 | case rightToLeft 37 | 38 | /** 39 | Creates `UITraitCollection` with correlating `UIUserInterfaceLayoutDirection` 40 | 41 | - returns: New `UITraitCollection` with correlating `layoutDirection` 42 | */ 43 | public func generateTraitCollection() -> UITraitCollection { 44 | switch self { 45 | case .leftToRight: return UITraitCollection(layoutDirection: .leftToRight) 46 | case .rightToLeft: return UITraitCollection(layoutDirection: .rightToLeft) 47 | } 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /Source/Scale.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Scale.swift 3 | // Briggs 4 | // 5 | // Copyright (c) 2017 Ada Turner (https://github.com/auswahlaxiom) 6 | // 7 | // Permission is hereby granted, free of charge, to any person obtaining a copy 8 | // of this software and associated documentation files (the "Software"), to deal 9 | // in the Software without restriction, including without limitation the rights 10 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | // copies of the Software, and to permit persons to whom the Software is 12 | // furnished to do so, subject to the following conditions:// 13 | // 14 | // The above copyright notice and this permission notice shall be included in 15 | // all copies or substantial portions of the Software.// 16 | // 17 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 23 | // THE SOFTWARE. 24 | // 25 | 26 | import UIKit 27 | 28 | /** 29 | `AdaptiveAttribute` correlating to `UITraitCollection.init(displayScale scale: CGFloat)` 30 | */ 31 | public enum Scale: AdaptiveAttribute { 32 | 33 | /// Corelates to `UITraitCollection(displayScale: 1.0)` 34 | case oneX 35 | /// Corelates to `UITraitCollection(displayScale: 2.0)` 36 | case twoX 37 | /// Corelates to `UITraitCollection(displayScale: 3.0)` 38 | case threeX 39 | /// SO FUTURE!!! Corelates to `UITraitCollection(displayScale: 4.0)` 40 | case fourX 41 | 42 | /** 43 | Creates `UITraitCollection` with correlating `CGFloat` scale 44 | 45 | - returns: New `UITraitCollection` with correlating `displayScale` 46 | */ 47 | public func generateTraitCollection() -> UITraitCollection { 48 | switch self { 49 | case .oneX: return UITraitCollection(displayScale: 1.0) 50 | case .twoX: return UITraitCollection(displayScale: 2.0) 51 | case .threeX: return UITraitCollection(displayScale: 3.0) 52 | case .fourX: return UITraitCollection(displayScale: 4.0) 53 | } 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /Source/SizeCategory.swift: -------------------------------------------------------------------------------- 1 | // 2 | // SizeCategory.swift 3 | // Briggs 4 | // 5 | // Copyright (c) 2017 Ada Turner (https://github.com/auswahlaxiom) 6 | // 7 | // Permission is hereby granted, free of charge, to any person obtaining a copy 8 | // of this software and associated documentation files (the "Software"), to deal 9 | // in the Software without restriction, including without limitation the rights 10 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | // copies of the Software, and to permit persons to whom the Software is 12 | // furnished to do so, subject to the following conditions:// 13 | // 14 | // The above copyright notice and this permission notice shall be included in 15 | // all copies or substantial portions of the Software.// 16 | // 17 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 23 | // THE SOFTWARE. 24 | // 25 | 26 | import UIKit 27 | 28 | /** 29 | `AdaptiveAttribute` correlating to `init(preferredContentSizeCategory: UIContentSizeCategory)` 30 | */ 31 | public enum SizeCategory: AdaptiveAttribute { 32 | 33 | /// Corelates to `UITraitCollection(preferredContentSizeCategory: .extraSmall) 34 | case extraSmall 35 | /// Corelates to `UITraitCollection(preferredContentSizeCategory: .small) 36 | case small 37 | /// Corelates to `UITraitCollection(preferredContentSizeCategory: .medium) 38 | case medium 39 | /// Corelates to `UITraitCollection(preferredContentSizeCategory: .large) 40 | case large 41 | /// Corelates to `UITraitCollection(preferredContentSizeCategory: .extraLarge) 42 | case extraLarge 43 | /// Corelates to `UITraitCollection(preferredContentSizeCategory: .extraExtraLarge) 44 | case extraExtraLarge 45 | /// Corelates to `UITraitCollection(preferredContentSizeCategory: .extraExtraExtraLarge) 46 | case extraExtraExtraLarge 47 | /// Corelates to `UITraitCollection(preferredContentSizeCategory: .accessibilityMedium) 48 | case accessibilityMedium 49 | /// Corelates to `UITraitCollection(preferredContentSizeCategory: .accessibilityLarge) 50 | case accessibilityLarge 51 | /// Corelates to `UITraitCollection(preferredContentSizeCategory: .accessibilityExtraLarge) 52 | case accessibilityExtraLarge 53 | /// Corelates to `UITraitCollection(preferredContentSizeCategory: .accessibilityExtraExtraLarge) 54 | case accessibilityExtraExtraLarge 55 | /// Corelates to `UITraitCollection(preferredContentSizeCategory: .accessibilityExtraExtraExtraLarge) 56 | case accessibilityExtraExtraExtraLarge 57 | 58 | /** 59 | Creates `UITraitCollection` with correlating `UIUserInterfaceSizeCategory` 60 | 61 | - returns: New `UITraitCollection` with correlating `sizeCategory` 62 | */ 63 | public func generateTraitCollection() -> UITraitCollection { 64 | switch self { 65 | case .extraSmall: return UITraitCollection(preferredContentSizeCategory: .extraSmall) 66 | case .small: return UITraitCollection(preferredContentSizeCategory: .small) 67 | case .medium: return UITraitCollection(preferredContentSizeCategory: .medium) 68 | case .large: return UITraitCollection(preferredContentSizeCategory: .large) 69 | case .extraLarge: return UITraitCollection(preferredContentSizeCategory: .extraLarge) 70 | case .extraExtraLarge: return UITraitCollection(preferredContentSizeCategory: .extraExtraLarge) 71 | case .extraExtraExtraLarge: return UITraitCollection(preferredContentSizeCategory: .extraExtraExtraLarge) 72 | case .accessibilityMedium: return UITraitCollection(preferredContentSizeCategory: .accessibilityMedium) 73 | case .accessibilityLarge: return UITraitCollection(preferredContentSizeCategory: .accessibilityLarge) 74 | case .accessibilityExtraLarge: return UITraitCollection(preferredContentSizeCategory: .accessibilityExtraLarge) 75 | case .accessibilityExtraExtraLarge: return UITraitCollection(preferredContentSizeCategory: .accessibilityExtraExtraLarge) 76 | case .accessibilityExtraExtraExtraLarge: return UITraitCollection(preferredContentSizeCategory: .accessibilityExtraExtraExtraLarge) 77 | } 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /Source/SizeClass.swift: -------------------------------------------------------------------------------- 1 | // 2 | // SizeClass.swift 3 | // Briggs 4 | // 5 | // Copyright (c) 2017 Ada Turner (https://github.com/auswahlaxiom) 6 | // 7 | // Permission is hereby granted, free of charge, to any person obtaining a copy 8 | // of this software and associated documentation files (the "Software"), to deal 9 | // in the Software without restriction, including without limitation the rights 10 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | // copies of the Software, and to permit persons to whom the Software is 12 | // furnished to do so, subject to the following conditions:// 13 | // 14 | // The above copyright notice and this permission notice shall be included in 15 | // all copies or substantial portions of the Software.// 16 | // 17 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 23 | // THE SOFTWARE. 24 | // 25 | 26 | import UIKit 27 | 28 | /** 29 | `AdaptiveAttribute` correlating to `UITraitCollection.init(horizontalSizeClass: UIUserInterfaceSizeClass)` and `UITraitCollection.init(verticalSizeClass: UIUserInterfaceSizeClass)` 30 | */ 31 | public enum SizeClass: AdaptiveAttribute { 32 | 33 | /// Corelates to `UITraitCollection(horizontalSizeClass: .compact)` 34 | case horizontalCompact 35 | /// Corelates to `UITraitCollection(horizontalSizeClass: .regular)` 36 | case horizontalRegular 37 | /// Corelates to `UITraitCollection(verticalSizeClass: .compact)` 38 | case verticalCompact 39 | /// Corelates to `UITraitCollection(verticalSizeClass: .regular)` 40 | case verticalRegular 41 | 42 | /** 43 | Creates `UITraitCollection` with correlating `UIUserInterfaceSizeClass` 44 | 45 | - returns: New `UITraitCollection` with correlating `horizontalSizeClass` or `verticalSizeClass` 46 | */ 47 | public func generateTraitCollection() -> UITraitCollection { 48 | switch self { 49 | case .horizontalCompact: return UITraitCollection(horizontalSizeClass: .compact) 50 | case .horizontalRegular: return UITraitCollection(horizontalSizeClass: .regular) 51 | case .verticalCompact: return UITraitCollection(verticalSizeClass: .compact) 52 | case .verticalRegular: return UITraitCollection(verticalSizeClass: .regular) 53 | } 54 | } 55 | } 56 | --------------------------------------------------------------------------------