├── .github └── workflows │ └── driftwood_ci.yaml ├── .gitignore ├── .swiftpm └── xcode │ └── package.xcworkspace │ └── contents.xcworkspacedata ├── Demo ├── Driftwood_iOS │ ├── Driftwood_iOS.xcodeproj │ │ ├── project.pbxproj │ │ ├── project.xcworkspace │ │ │ ├── contents.xcworkspacedata │ │ │ └── xcshareddata │ │ │ │ └── IDEWorkspaceChecks.plist │ │ └── xcshareddata │ │ │ └── xcschemes │ │ │ └── Driftwood_iOS.xcscheme │ ├── Driftwood_iOS.xcworkspace │ │ ├── contents.xcworkspacedata │ │ └── xcshareddata │ │ │ └── IDEWorkspaceChecks.plist │ ├── Driftwood_iOS │ │ ├── AppDelegate.swift │ │ ├── Assets.xcassets │ │ │ ├── AppIcon.appiconset │ │ │ │ └── Contents.json │ │ │ └── Contents.json │ │ ├── Base.lproj │ │ │ ├── LaunchScreen.storyboard │ │ │ └── Main.storyboard │ │ ├── Info.plist │ │ ├── Utils.swift │ │ └── ViewController.swift │ ├── Podfile │ ├── Podfile.lock │ └── Pods │ │ ├── Headers │ │ └── Public │ │ │ └── Driftwood │ │ │ ├── Driftwood-umbrella.h │ │ │ └── Driftwood.modulemap │ │ ├── Local Podspecs │ │ └── Driftwood.podspec.json │ │ ├── Manifest.lock │ │ ├── Pods.xcodeproj │ │ └── project.pbxproj │ │ └── Target Support Files │ │ ├── Driftwood │ │ ├── Driftwood-dummy.m │ │ ├── Driftwood-prefix.pch │ │ ├── Driftwood-umbrella.h │ │ ├── Driftwood.debug.xcconfig │ │ ├── Driftwood.modulemap │ │ ├── Driftwood.release.xcconfig │ │ ├── Driftwood.xcconfig │ │ └── Info.plist │ │ └── Pods-Driftwood_iOS │ │ ├── Info.plist │ │ ├── Pods-Driftwood_iOS-acknowledgements.markdown │ │ ├── Pods-Driftwood_iOS-acknowledgements.plist │ │ ├── Pods-Driftwood_iOS-dummy.m │ │ ├── Pods-Driftwood_iOS-frameworks.sh │ │ ├── Pods-Driftwood_iOS-resources.sh │ │ ├── Pods-Driftwood_iOS-umbrella.h │ │ ├── Pods-Driftwood_iOS.debug.xcconfig │ │ ├── Pods-Driftwood_iOS.modulemap │ │ └── Pods-Driftwood_iOS.release.xcconfig ├── Driftwood_macOS │ ├── Driftwood_macOS.xcodeproj │ │ ├── project.pbxproj │ │ └── project.xcworkspace │ │ │ ├── contents.xcworkspacedata │ │ │ └── xcshareddata │ │ │ └── IDEWorkspaceChecks.plist │ ├── Driftwood_macOS.xcworkspace │ │ ├── contents.xcworkspacedata │ │ └── xcshareddata │ │ │ └── IDEWorkspaceChecks.plist │ ├── Driftwood_macOS │ │ ├── AppDelegate.swift │ │ ├── Assets.xcassets │ │ │ ├── AppIcon.appiconset │ │ │ │ └── Contents.json │ │ │ └── Contents.json │ │ ├── Base.lproj │ │ │ └── Main.storyboard │ │ ├── Driftwood_macOS.entitlements │ │ ├── Info.plist │ │ ├── Utils.swift │ │ └── ViewController.swift │ ├── Podfile │ ├── Podfile.lock │ └── Pods │ │ ├── Headers │ │ └── Public │ │ │ └── Driftwood │ │ │ ├── Driftwood-umbrella.h │ │ │ └── Driftwood.modulemap │ │ ├── Local Podspecs │ │ └── Driftwood.podspec.json │ │ ├── Manifest.lock │ │ ├── Pods.xcodeproj │ │ └── project.pbxproj │ │ └── Target Support Files │ │ ├── Driftwood │ │ ├── Driftwood-dummy.m │ │ ├── Driftwood-prefix.pch │ │ ├── Driftwood-umbrella.h │ │ ├── Driftwood.debug.xcconfig │ │ ├── Driftwood.modulemap │ │ ├── Driftwood.release.xcconfig │ │ └── Driftwood.xcconfig │ │ └── Pods-Driftwood_macOS │ │ ├── Pods-Driftwood_macOS-acknowledgements.markdown │ │ ├── Pods-Driftwood_macOS-acknowledgements.plist │ │ ├── Pods-Driftwood_macOS-dummy.m │ │ ├── Pods-Driftwood_macOS-frameworks.sh │ │ ├── Pods-Driftwood_macOS-resources.sh │ │ ├── Pods-Driftwood_macOS-umbrella.h │ │ ├── Pods-Driftwood_macOS.debug.xcconfig │ │ ├── Pods-Driftwood_macOS.modulemap │ │ └── Pods-Driftwood_macOS.release.xcconfig └── Driftwood_tvOS │ ├── Driftwood_tvOS.xcodeproj │ ├── project.pbxproj │ └── project.xcworkspace │ │ ├── contents.xcworkspacedata │ │ └── xcshareddata │ │ └── IDEWorkspaceChecks.plist │ ├── Driftwood_tvOS.xcworkspace │ ├── contents.xcworkspacedata │ └── xcshareddata │ │ └── IDEWorkspaceChecks.plist │ ├── Driftwood_tvOS │ ├── AppDelegate.swift │ ├── Assets.xcassets │ │ ├── App Icon & Top Shelf Image.brandassets │ │ │ ├── App Icon - App Store.imagestack │ │ │ │ ├── Back.imagestacklayer │ │ │ │ │ ├── Content.imageset │ │ │ │ │ │ └── Contents.json │ │ │ │ │ └── Contents.json │ │ │ │ ├── Contents.json │ │ │ │ ├── Front.imagestacklayer │ │ │ │ │ ├── Content.imageset │ │ │ │ │ │ └── Contents.json │ │ │ │ │ └── Contents.json │ │ │ │ └── Middle.imagestacklayer │ │ │ │ │ ├── Content.imageset │ │ │ │ │ └── Contents.json │ │ │ │ │ └── Contents.json │ │ │ ├── App Icon.imagestack │ │ │ │ ├── Back.imagestacklayer │ │ │ │ │ ├── Content.imageset │ │ │ │ │ │ └── Contents.json │ │ │ │ │ └── Contents.json │ │ │ │ ├── Contents.json │ │ │ │ ├── Front.imagestacklayer │ │ │ │ │ ├── Content.imageset │ │ │ │ │ │ └── Contents.json │ │ │ │ │ └── Contents.json │ │ │ │ └── Middle.imagestacklayer │ │ │ │ │ ├── Content.imageset │ │ │ │ │ └── Contents.json │ │ │ │ │ └── Contents.json │ │ │ ├── Contents.json │ │ │ ├── Top Shelf Image Wide.imageset │ │ │ │ └── Contents.json │ │ │ └── Top Shelf Image.imageset │ │ │ │ └── Contents.json │ │ ├── Contents.json │ │ └── Launch Image.launchimage │ │ │ └── Contents.json │ ├── Base.lproj │ │ └── Main.storyboard │ ├── Info.plist │ ├── Utils.swift │ └── ViewController.swift │ ├── Podfile │ ├── Podfile.lock │ └── Pods │ ├── Headers │ └── Public │ │ └── Driftwood │ │ ├── Driftwood-umbrella.h │ │ └── Driftwood.modulemap │ ├── Local Podspecs │ └── Driftwood.podspec.json │ ├── Manifest.lock │ ├── Pods.xcodeproj │ └── project.pbxproj │ └── Target Support Files │ ├── Driftwood │ ├── Driftwood-dummy.m │ ├── Driftwood-prefix.pch │ ├── Driftwood-umbrella.h │ ├── Driftwood.debug.xcconfig │ ├── Driftwood.modulemap │ ├── Driftwood.release.xcconfig │ └── Driftwood.xcconfig │ └── Pods-Driftwood_tvOS │ ├── Pods-Driftwood_tvOS-acknowledgements.markdown │ ├── Pods-Driftwood_tvOS-acknowledgements.plist │ ├── Pods-Driftwood_tvOS-dummy.m │ ├── Pods-Driftwood_tvOS-frameworks.sh │ ├── Pods-Driftwood_tvOS-resources.sh │ ├── Pods-Driftwood_tvOS-umbrella.h │ ├── Pods-Driftwood_tvOS.debug.xcconfig │ ├── Pods-Driftwood_tvOS.modulemap │ └── Pods-Driftwood_tvOS.release.xcconfig ├── Driftwood.podspec ├── LICENSE ├── Package.swift ├── README.md ├── README_ZH.md ├── Sources └── Driftwood │ ├── Attribute.swift │ ├── Constraint.swift │ ├── ConstraintKey.swift │ ├── ConstraintMaker+Handy.swift │ ├── ConstraintMaker.swift │ ├── ConstraintRemover+Handy.swift │ ├── ConstraintRemover.swift │ ├── ConstraintUpdater+Handy.swift │ ├── ConstraintUpdater.swift │ ├── Debugging.swift │ ├── Driftable+.swift │ ├── Driftable.swift │ ├── Preferences.swift │ ├── Priority+Safety.swift │ ├── Storage.swift │ ├── Typealiases.swift │ ├── Wood+Priority.swift │ ├── Wood+__Tuple2.swift │ ├── Wood.swift │ └── __Tuple2.swift └── driftwood.png /.github/workflows/driftwood_ci.yaml: -------------------------------------------------------------------------------- 1 | name: Driftwood CI 2 | on: 3 | push: 4 | paths: 5 | - '**.swift' 6 | - '**.podspec' 7 | - 'Demo/**' 8 | 9 | jobs: 10 | macOS: 11 | name: Test macOS 12 | runs-on: macOS-latest 13 | env: 14 | DEVELOPER_DIR: /Applications/Xcode_11.1.app/Contents/Developer 15 | steps: 16 | - uses: actions/checkout@v2 17 | - name: macOS 18 | run: | 19 | pod install 20 | xcodebuild -workspace "Driftwood_macOS.xcworkspace" -scheme "Driftwood_macOS" -destination "platform=macOS" clean test | xcpretty 21 | working-directory: Demo/Driftwood_macOS 22 | 23 | iOS: 24 | name: Test iOS 25 | runs-on: macOS-latest 26 | env: 27 | DEVELOPER_DIR: /Applications/Xcode_11.1.app/Contents/Developer 28 | strategy: 29 | matrix: 30 | destination: ["OS=13.1,name=iPhone 11 Pro"] #, "OS=12.4,name=iPhone XS", "OS=11.4,name=iPhone X", "OS=10.3.1,name=iPhone SE"] 31 | steps: 32 | - uses: actions/checkout@v2 33 | - name: iOS 34 | run: | 35 | pod install 36 | xcodebuild -workspace "Driftwood_iOS.xcworkspace" -scheme "Driftwood_iOS" -destination "platform=iOS" clean test | xcpretty 37 | working-directory: Demo/Driftwood_iOS 38 | 39 | tvOS: 40 | name: Test tvOS 41 | runs-on: macOS-latest 42 | env: 43 | DEVELOPER_DIR: /Applications/Xcode_11.1.app/Contents/Developer 44 | strategy: 45 | matrix: 46 | destination: ["OS=13.0,name=Apple TV 4K"] #, "OS=11.4,name=Apple TV 4K", "OS=10.2,name=Apple TV 1080p"] 47 | steps: 48 | - uses: actions/checkout@v2 49 | - name: tvOS 50 | run: | 51 | pod install 52 | xcodebuild -workspace "Driftwood_tvOS.xcworkspace" -scheme "Driftwood_tvOS" -destination "platform=tvOS" clean test | xcpretty 53 | working-directory: Demo/Driftwood_tvOS 54 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # OS X 2 | .DS_Store 3 | 4 | # Xcode 5 | build/ 6 | *.pbxuser 7 | !default.pbxuser 8 | *.mode1v3 9 | !default.mode1v3 10 | *.mode2v3 11 | !default.mode2v3 12 | *.perspectivev3 13 | !default.perspectivev3 14 | xcuserdata/ 15 | *.xccheckout 16 | profile 17 | *.moved-aside 18 | DerivedData 19 | *.hmap 20 | *.ipa 21 | 22 | # Swift PM 23 | .swiftpm/ 24 | -------------------------------------------------------------------------------- /.swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /Demo/Driftwood_iOS/Driftwood_iOS.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /Demo/Driftwood_iOS/Driftwood_iOS.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /Demo/Driftwood_iOS/Driftwood_iOS.xcodeproj/xcshareddata/xcschemes/Driftwood_iOS.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 37 | 38 | 39 | 40 | 41 | 42 | 52 | 54 | 60 | 61 | 62 | 63 | 69 | 71 | 77 | 78 | 79 | 80 | 82 | 83 | 86 | 87 | 88 | -------------------------------------------------------------------------------- /Demo/Driftwood_iOS/Driftwood_iOS.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /Demo/Driftwood_iOS/Driftwood_iOS.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /Demo/Driftwood_iOS/Driftwood_iOS/AppDelegate.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.swift 3 | // Driftwood_iOS 4 | // 5 | 6 | import UIKit 7 | 8 | @UIApplicationMain 9 | class AppDelegate: UIResponder, UIApplicationDelegate { 10 | 11 | var window: UIWindow? 12 | 13 | 14 | func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { 15 | // Override point for customization after application launch. 16 | return true 17 | } 18 | 19 | func applicationWillResignActive(_ application: UIApplication) { 20 | // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. 21 | // Use this method to pause ongoing tasks, disable timers, and invalidate graphics rendering callbacks. Games should use this method to pause the game. 22 | } 23 | 24 | func applicationDidEnterBackground(_ application: UIApplication) { 25 | // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. 26 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. 27 | } 28 | 29 | func applicationWillEnterForeground(_ application: UIApplication) { 30 | // Called as part of the transition from the background to the active state; here you can undo many of the changes made on entering the background. 31 | } 32 | 33 | func applicationDidBecomeActive(_ application: UIApplication) { 34 | // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. 35 | } 36 | 37 | func applicationWillTerminate(_ application: UIApplication) { 38 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. 39 | } 40 | 41 | 42 | } 43 | 44 | -------------------------------------------------------------------------------- /Demo/Driftwood_iOS/Driftwood_iOS/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "iphone", 5 | "size" : "20x20", 6 | "scale" : "2x" 7 | }, 8 | { 9 | "idiom" : "iphone", 10 | "size" : "20x20", 11 | "scale" : "3x" 12 | }, 13 | { 14 | "idiom" : "iphone", 15 | "size" : "29x29", 16 | "scale" : "2x" 17 | }, 18 | { 19 | "idiom" : "iphone", 20 | "size" : "29x29", 21 | "scale" : "3x" 22 | }, 23 | { 24 | "idiom" : "iphone", 25 | "size" : "40x40", 26 | "scale" : "2x" 27 | }, 28 | { 29 | "idiom" : "iphone", 30 | "size" : "40x40", 31 | "scale" : "3x" 32 | }, 33 | { 34 | "idiom" : "iphone", 35 | "size" : "60x60", 36 | "scale" : "2x" 37 | }, 38 | { 39 | "idiom" : "iphone", 40 | "size" : "60x60", 41 | "scale" : "3x" 42 | }, 43 | { 44 | "idiom" : "ipad", 45 | "size" : "20x20", 46 | "scale" : "1x" 47 | }, 48 | { 49 | "idiom" : "ipad", 50 | "size" : "20x20", 51 | "scale" : "2x" 52 | }, 53 | { 54 | "idiom" : "ipad", 55 | "size" : "29x29", 56 | "scale" : "1x" 57 | }, 58 | { 59 | "idiom" : "ipad", 60 | "size" : "29x29", 61 | "scale" : "2x" 62 | }, 63 | { 64 | "idiom" : "ipad", 65 | "size" : "40x40", 66 | "scale" : "1x" 67 | }, 68 | { 69 | "idiom" : "ipad", 70 | "size" : "40x40", 71 | "scale" : "2x" 72 | }, 73 | { 74 | "idiom" : "ipad", 75 | "size" : "76x76", 76 | "scale" : "1x" 77 | }, 78 | { 79 | "idiom" : "ipad", 80 | "size" : "76x76", 81 | "scale" : "2x" 82 | }, 83 | { 84 | "idiom" : "ipad", 85 | "size" : "83.5x83.5", 86 | "scale" : "2x" 87 | }, 88 | { 89 | "idiom" : "ios-marketing", 90 | "size" : "1024x1024", 91 | "scale" : "1x" 92 | } 93 | ], 94 | "info" : { 95 | "version" : 1, 96 | "author" : "xcode" 97 | } 98 | } -------------------------------------------------------------------------------- /Demo/Driftwood_iOS/Driftwood_iOS/Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "version" : 1, 4 | "author" : "xcode" 5 | } 6 | } -------------------------------------------------------------------------------- /Demo/Driftwood_iOS/Driftwood_iOS/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 | -------------------------------------------------------------------------------- /Demo/Driftwood_iOS/Driftwood_iOS/Base.lproj/Main.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 | -------------------------------------------------------------------------------- /Demo/Driftwood_iOS/Driftwood_iOS/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | $(DEVELOPMENT_LANGUAGE) 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | APPL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleVersion 20 | 1 21 | LSRequiresIPhoneOS 22 | 23 | UILaunchStoryboardName 24 | LaunchScreen 25 | UIMainStoryboardFile 26 | Main 27 | UIRequiredDeviceCapabilities 28 | 29 | armv7 30 | 31 | UISupportedInterfaceOrientations 32 | 33 | UIInterfaceOrientationPortrait 34 | UIInterfaceOrientationLandscapeLeft 35 | UIInterfaceOrientationLandscapeRight 36 | 37 | UISupportedInterfaceOrientations~ipad 38 | 39 | UIInterfaceOrientationPortrait 40 | UIInterfaceOrientationPortraitUpsideDown 41 | UIInterfaceOrientationLandscapeLeft 42 | UIInterfaceOrientationLandscapeRight 43 | 44 | 45 | 46 | -------------------------------------------------------------------------------- /Demo/Driftwood_iOS/Driftwood_iOS/Utils.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Utils.swift 3 | // Driftwood 4 | // 5 | 6 | import UIKit 7 | 8 | extension UIView { 9 | 10 | /// Create & Add & Return View 11 | func createSubView() -> T? { 12 | let v = T() 13 | self.addSubview(v) 14 | let c = UIColor(red: CGFloat.random(in: 0...1), green: CGFloat.random(in: 0...1), blue: CGFloat.random(in: 0...1), alpha: 0.5) 15 | v.backgroundColor = c 16 | return v 17 | } 18 | 19 | /// Create & Add & Return LayoutGuide 20 | func createSubLayoutGuide() -> UILayoutGuide { 21 | let g = UILayoutGuide() 22 | self.addLayoutGuide(g) 23 | return g 24 | } 25 | } 26 | 27 | extension UIStackView { 28 | 29 | /// Create & Add & Return View 30 | func createArrangedSubview() -> T? { 31 | let v = T() 32 | self.addArrangedSubview(v) 33 | let c = UIColor(red: CGFloat.random(in: 0...1), green: CGFloat.random(in: 0...1), blue: CGFloat.random(in: 0...1), alpha: 0.5) 34 | v.backgroundColor = c 35 | return v 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /Demo/Driftwood_iOS/Driftwood_iOS/ViewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.swift 3 | // Driftwood 4 | // 5 | 6 | import UIKit 7 | import Driftwood 8 | 9 | class ViewController: UIViewController { 10 | 11 | private weak var vTop: UIView! 12 | private weak var vBottom: UIView! 13 | private weak var stkCenter: UIStackView! 14 | private weak var vCenter0: UIView! 15 | private weak var vCenter1: UIView! 16 | private weak var vCenter2: UIView! 17 | 18 | override func viewDidLoad() { 19 | super.viewDidLoad() 20 | 21 | self.vTop = self.view.createSubView() 22 | self.vTop.dw.make() 23 | .top(0) 24 | .leading(0) 25 | .trailing(0) 26 | .bottom(0, to: self.view.safeAreaLayoutGuide.dw.top) 27 | 28 | self.vBottom = self.view.createSubView() 29 | self.vBottom.dw.make() 30 | .bottom(0) 31 | .leading(0) 32 | .trailing(0) 33 | .top(0, to: self.view.safeAreaLayoutGuide.dw.bottom) 34 | 35 | 36 | self.stkCenter = self.view.createSubView() 37 | self.stkCenter.axis = .vertical 38 | self.stkCenter.alignment = .fill 39 | self.stkCenter.distribution = .fill 40 | self.stkCenter.dw 41 | .setContentCompressionResistanceVerticalPriority(.required) 42 | .setContentHuggingVerticalPriority(.required) 43 | self.stkCenter.dw.make(labeled: "Center") 44 | .centerX(0) 45 | .centerY(0) 46 | .width(100) 47 | 48 | self.vCenter0 = self.stkCenter.createArrangedSubview() 49 | self.vCenter0.dw.make() 50 | .height(50) 51 | 52 | self.vCenter1 = self.stkCenter.createArrangedSubview() 53 | self.vCenter1.dw.make() 54 | .height(100) 55 | 56 | self.vCenter2 = self.stkCenter.createArrangedSubview() 57 | self.vCenter2.dw.make() 58 | .height(150) 59 | } 60 | 61 | override func touchesBegan(_ touches: Set, with event: UIEvent?) { 62 | 63 | self.stkCenter.dw.remake() 64 | .centerX(50, priority: UILayoutPriority.required.dw.lower) 65 | .centerY(100, priority: UILayoutPriority.required.dw.lower) 66 | .width(200, priority: UILayoutPriority.required.dw.lower) 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /Demo/Driftwood_iOS/Podfile: -------------------------------------------------------------------------------- 1 | # Uncomment the next line to define a global platform for your project 2 | platform :ios, '9.0' 3 | 4 | target 'Driftwood_iOS' do 5 | 6 | pod 'Driftwood', :path => '../../' 7 | 8 | end 9 | -------------------------------------------------------------------------------- /Demo/Driftwood_iOS/Podfile.lock: -------------------------------------------------------------------------------- 1 | PODS: 2 | - Driftwood (5.3.4) 3 | 4 | DEPENDENCIES: 5 | - Driftwood (from `../../`) 6 | 7 | EXTERNAL SOURCES: 8 | Driftwood: 9 | :path: "../../" 10 | 11 | SPEC CHECKSUMS: 12 | Driftwood: b5104840855baddf2ccf4736f4e7afd6f8b2ebd2 13 | 14 | PODFILE CHECKSUM: 2576c40cdb93abafef768f43323c2486df8bc558 15 | 16 | COCOAPODS: 1.11.2 17 | -------------------------------------------------------------------------------- /Demo/Driftwood_iOS/Pods/Headers/Public/Driftwood/Driftwood-umbrella.h: -------------------------------------------------------------------------------- 1 | ../../../Target Support Files/Driftwood/Driftwood-umbrella.h -------------------------------------------------------------------------------- /Demo/Driftwood_iOS/Pods/Headers/Public/Driftwood/Driftwood.modulemap: -------------------------------------------------------------------------------- 1 | ../../../Target Support Files/Driftwood/Driftwood.modulemap -------------------------------------------------------------------------------- /Demo/Driftwood_iOS/Pods/Local Podspecs/Driftwood.podspec.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Driftwood", 3 | "version": "5.3.4", 4 | "summary": "A lightweight, Swift library for AutoLayout.", 5 | "homepage": "https://github.com/wlgemini/Driftwood", 6 | "license": { 7 | "type": "MIT", 8 | "file": "LICENSE" 9 | }, 10 | "authors": { 11 | "wlgemini": "wangluguang@live.com" 12 | }, 13 | "source": { 14 | "git": "https://github.com/wlgemini/Driftwood.git", 15 | "tag": "5.3.4" 16 | }, 17 | "swift_versions": [ 18 | "5.3" 19 | ], 20 | "platforms": { 21 | "ios": "8.0", 22 | "osx": "10.11", 23 | "tvos": "9.0" 24 | }, 25 | "source_files": "Sources/Driftwood/*.swift", 26 | "swift_version": "5.3" 27 | } 28 | -------------------------------------------------------------------------------- /Demo/Driftwood_iOS/Pods/Manifest.lock: -------------------------------------------------------------------------------- 1 | PODS: 2 | - Driftwood (5.3.4) 3 | 4 | DEPENDENCIES: 5 | - Driftwood (from `../../`) 6 | 7 | EXTERNAL SOURCES: 8 | Driftwood: 9 | :path: "../../" 10 | 11 | SPEC CHECKSUMS: 12 | Driftwood: b5104840855baddf2ccf4736f4e7afd6f8b2ebd2 13 | 14 | PODFILE CHECKSUM: 2576c40cdb93abafef768f43323c2486df8bc558 15 | 16 | COCOAPODS: 1.11.2 17 | -------------------------------------------------------------------------------- /Demo/Driftwood_iOS/Pods/Target Support Files/Driftwood/Driftwood-dummy.m: -------------------------------------------------------------------------------- 1 | #import 2 | @interface PodsDummy_Driftwood : NSObject 3 | @end 4 | @implementation PodsDummy_Driftwood 5 | @end 6 | -------------------------------------------------------------------------------- /Demo/Driftwood_iOS/Pods/Target Support Files/Driftwood/Driftwood-prefix.pch: -------------------------------------------------------------------------------- 1 | #ifdef __OBJC__ 2 | #import 3 | #else 4 | #ifndef FOUNDATION_EXPORT 5 | #if defined(__cplusplus) 6 | #define FOUNDATION_EXPORT extern "C" 7 | #else 8 | #define FOUNDATION_EXPORT extern 9 | #endif 10 | #endif 11 | #endif 12 | 13 | -------------------------------------------------------------------------------- /Demo/Driftwood_iOS/Pods/Target Support Files/Driftwood/Driftwood-umbrella.h: -------------------------------------------------------------------------------- 1 | #ifdef __OBJC__ 2 | #import 3 | #else 4 | #ifndef FOUNDATION_EXPORT 5 | #if defined(__cplusplus) 6 | #define FOUNDATION_EXPORT extern "C" 7 | #else 8 | #define FOUNDATION_EXPORT extern 9 | #endif 10 | #endif 11 | #endif 12 | 13 | 14 | FOUNDATION_EXPORT double DriftwoodVersionNumber; 15 | FOUNDATION_EXPORT const unsigned char DriftwoodVersionString[]; 16 | 17 | -------------------------------------------------------------------------------- /Demo/Driftwood_iOS/Pods/Target Support Files/Driftwood/Driftwood.debug.xcconfig: -------------------------------------------------------------------------------- 1 | CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = NO 2 | CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/Driftwood 3 | GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 4 | OTHER_SWIFT_FLAGS = $(inherited) -D COCOAPODS -import-underlying-module -Xcc -fmodule-map-file="${SRCROOT}/${MODULEMAP_FILE}" 5 | PODS_BUILD_DIR = ${BUILD_DIR} 6 | PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) 7 | PODS_ROOT = ${SRCROOT} 8 | PODS_TARGET_SRCROOT = ${PODS_ROOT}/../../.. 9 | PODS_XCFRAMEWORKS_BUILD_DIR = $(PODS_CONFIGURATION_BUILD_DIR)/XCFrameworkIntermediates 10 | PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier} 11 | SKIP_INSTALL = YES 12 | USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES 13 | -------------------------------------------------------------------------------- /Demo/Driftwood_iOS/Pods/Target Support Files/Driftwood/Driftwood.modulemap: -------------------------------------------------------------------------------- 1 | module Driftwood { 2 | umbrella header "Driftwood-umbrella.h" 3 | 4 | export * 5 | module * { export * } 6 | } 7 | -------------------------------------------------------------------------------- /Demo/Driftwood_iOS/Pods/Target Support Files/Driftwood/Driftwood.release.xcconfig: -------------------------------------------------------------------------------- 1 | CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = NO 2 | CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/Driftwood 3 | GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 4 | OTHER_SWIFT_FLAGS = $(inherited) -D COCOAPODS -import-underlying-module -Xcc -fmodule-map-file="${SRCROOT}/${MODULEMAP_FILE}" 5 | PODS_BUILD_DIR = ${BUILD_DIR} 6 | PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) 7 | PODS_ROOT = ${SRCROOT} 8 | PODS_TARGET_SRCROOT = ${PODS_ROOT}/../../.. 9 | PODS_XCFRAMEWORKS_BUILD_DIR = $(PODS_CONFIGURATION_BUILD_DIR)/XCFrameworkIntermediates 10 | PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier} 11 | SKIP_INSTALL = YES 12 | USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES 13 | -------------------------------------------------------------------------------- /Demo/Driftwood_iOS/Pods/Target Support Files/Driftwood/Driftwood.xcconfig: -------------------------------------------------------------------------------- 1 | CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/Driftwood 2 | GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 3 | OTHER_SWIFT_FLAGS = $(inherited) -D COCOAPODS -import-underlying-module -Xcc -fmodule-map-file="${SRCROOT}/${MODULEMAP_FILE}" 4 | PODS_BUILD_DIR = ${BUILD_DIR} 5 | PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) 6 | PODS_ROOT = ${SRCROOT} 7 | PODS_TARGET_SRCROOT = ${PODS_ROOT}/../../.. 8 | PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier} 9 | SKIP_INSTALL = YES 10 | -------------------------------------------------------------------------------- /Demo/Driftwood_iOS/Pods/Target Support Files/Driftwood/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 | 4.2.6 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | ${CURRENT_PROJECT_VERSION} 23 | NSPrincipalClass 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /Demo/Driftwood_iOS/Pods/Target Support Files/Pods-Driftwood_iOS/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | ${EXECUTABLE_NAME} 9 | CFBundleIdentifier 10 | ${PRODUCT_BUNDLE_IDENTIFIER} 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | ${PRODUCT_NAME} 15 | CFBundlePackageType 16 | FMWK 17 | CFBundleShortVersionString 18 | 1.0.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | ${CURRENT_PROJECT_VERSION} 23 | NSPrincipalClass 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /Demo/Driftwood_iOS/Pods/Target Support Files/Pods-Driftwood_iOS/Pods-Driftwood_iOS-acknowledgements.markdown: -------------------------------------------------------------------------------- 1 | # Acknowledgements 2 | This application makes use of the following third party libraries: 3 | 4 | ## Driftwood 5 | 6 | Copyright (c) 2018 wlgemini 7 | 8 | Permission is hereby granted, free of charge, to any person obtaining a copy 9 | of this software and associated documentation files (the "Software"), to deal 10 | in the Software without restriction, including without limitation the rights 11 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | copies of the Software, and to permit persons to whom the Software is 13 | furnished to do so, subject to the following conditions: 14 | 15 | The above copyright notice and this permission notice shall be included in 16 | all copies or substantial portions of the Software. 17 | 18 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 24 | THE SOFTWARE. 25 | 26 | Generated by CocoaPods - https://cocoapods.org 27 | -------------------------------------------------------------------------------- /Demo/Driftwood_iOS/Pods/Target Support Files/Pods-Driftwood_iOS/Pods-Driftwood_iOS-acknowledgements.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | PreferenceSpecifiers 6 | 7 | 8 | FooterText 9 | This application makes use of the following third party libraries: 10 | Title 11 | Acknowledgements 12 | Type 13 | PSGroupSpecifier 14 | 15 | 16 | FooterText 17 | Copyright (c) 2018 wlgemini <wangluguang@live.com> 18 | 19 | Permission is hereby granted, free of charge, to any person obtaining a copy 20 | of this software and associated documentation files (the "Software"), to deal 21 | in the Software without restriction, including without limitation the rights 22 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 23 | copies of the Software, and to permit persons to whom the Software is 24 | furnished to do so, subject to the following conditions: 25 | 26 | The above copyright notice and this permission notice shall be included in 27 | all copies or substantial portions of the Software. 28 | 29 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 30 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 31 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 32 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 33 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 34 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 35 | THE SOFTWARE. 36 | 37 | License 38 | MIT 39 | Title 40 | Driftwood 41 | Type 42 | PSGroupSpecifier 43 | 44 | 45 | FooterText 46 | Generated by CocoaPods - https://cocoapods.org 47 | Title 48 | 49 | Type 50 | PSGroupSpecifier 51 | 52 | 53 | StringsTable 54 | Acknowledgements 55 | Title 56 | Acknowledgements 57 | 58 | 59 | -------------------------------------------------------------------------------- /Demo/Driftwood_iOS/Pods/Target Support Files/Pods-Driftwood_iOS/Pods-Driftwood_iOS-dummy.m: -------------------------------------------------------------------------------- 1 | #import 2 | @interface PodsDummy_Pods_Driftwood_iOS : NSObject 3 | @end 4 | @implementation PodsDummy_Pods_Driftwood_iOS 5 | @end 6 | -------------------------------------------------------------------------------- /Demo/Driftwood_iOS/Pods/Target Support Files/Pods-Driftwood_iOS/Pods-Driftwood_iOS-frameworks.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | set -e 3 | set -u 4 | set -o pipefail 5 | 6 | if [ -z ${FRAMEWORKS_FOLDER_PATH+x} ]; then 7 | # If FRAMEWORKS_FOLDER_PATH is not set, then there's nowhere for us to copy 8 | # frameworks to, so exit 0 (signalling the script phase was successful). 9 | exit 0 10 | fi 11 | 12 | echo "mkdir -p ${CONFIGURATION_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" 13 | mkdir -p "${CONFIGURATION_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" 14 | 15 | COCOAPODS_PARALLEL_CODE_SIGN="${COCOAPODS_PARALLEL_CODE_SIGN:-false}" 16 | SWIFT_STDLIB_PATH="${DT_TOOLCHAIN_DIR}/usr/lib/swift/${PLATFORM_NAME}" 17 | 18 | # Used as a return value for each invocation of `strip_invalid_archs` function. 19 | STRIP_BINARY_RETVAL=0 20 | 21 | # This protects against multiple targets copying the same framework dependency at the same time. The solution 22 | # was originally proposed here: https://lists.samba.org/archive/rsync/2008-February/020158.html 23 | RSYNC_PROTECT_TMP_FILES=(--filter "P .*.??????") 24 | 25 | # Copies and strips a vendored framework 26 | install_framework() 27 | { 28 | if [ -r "${BUILT_PRODUCTS_DIR}/$1" ]; then 29 | local source="${BUILT_PRODUCTS_DIR}/$1" 30 | elif [ -r "${BUILT_PRODUCTS_DIR}/$(basename "$1")" ]; then 31 | local source="${BUILT_PRODUCTS_DIR}/$(basename "$1")" 32 | elif [ -r "$1" ]; then 33 | local source="$1" 34 | fi 35 | 36 | local destination="${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" 37 | 38 | if [ -L "${source}" ]; then 39 | echo "Symlinked..." 40 | source="$(readlink "${source}")" 41 | fi 42 | 43 | # Use filter instead of exclude so missing patterns don't throw errors. 44 | echo "rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --filter \"- CVS/\" --filter \"- .svn/\" --filter \"- .git/\" --filter \"- .hg/\" --filter \"- Headers\" --filter \"- PrivateHeaders\" --filter \"- Modules\" \"${source}\" \"${destination}\"" 45 | rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --filter "- CVS/" --filter "- .svn/" --filter "- .git/" --filter "- .hg/" --filter "- Headers" --filter "- PrivateHeaders" --filter "- Modules" "${source}" "${destination}" 46 | 47 | local basename 48 | basename="$(basename -s .framework "$1")" 49 | binary="${destination}/${basename}.framework/${basename}" 50 | if ! [ -r "$binary" ]; then 51 | binary="${destination}/${basename}" 52 | fi 53 | 54 | # Strip invalid architectures so "fat" simulator / device frameworks work on device 55 | if [[ "$(file "$binary")" == *"dynamically linked shared library"* ]]; then 56 | strip_invalid_archs "$binary" 57 | fi 58 | 59 | # Resign the code if required by the build settings to avoid unstable apps 60 | code_sign_if_enabled "${destination}/$(basename "$1")" 61 | 62 | # Embed linked Swift runtime libraries. No longer necessary as of Xcode 7. 63 | if [ "${XCODE_VERSION_MAJOR}" -lt 7 ]; then 64 | local swift_runtime_libs 65 | swift_runtime_libs=$(xcrun otool -LX "$binary" | grep --color=never @rpath/libswift | sed -E s/@rpath\\/\(.+dylib\).*/\\1/g | uniq -u && exit ${PIPESTATUS[0]}) 66 | for lib in $swift_runtime_libs; do 67 | echo "rsync -auv \"${SWIFT_STDLIB_PATH}/${lib}\" \"${destination}\"" 68 | rsync -auv "${SWIFT_STDLIB_PATH}/${lib}" "${destination}" 69 | code_sign_if_enabled "${destination}/${lib}" 70 | done 71 | fi 72 | } 73 | 74 | # Copies and strips a vendored dSYM 75 | install_dsym() { 76 | local source="$1" 77 | if [ -r "$source" ]; then 78 | # Copy the dSYM into a the targets temp dir. 79 | echo "rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --filter \"- CVS/\" --filter \"- .svn/\" --filter \"- .git/\" --filter \"- .hg/\" --filter \"- Headers\" --filter \"- PrivateHeaders\" --filter \"- Modules\" \"${source}\" \"${DERIVED_FILES_DIR}\"" 80 | rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --filter "- CVS/" --filter "- .svn/" --filter "- .git/" --filter "- .hg/" --filter "- Headers" --filter "- PrivateHeaders" --filter "- Modules" "${source}" "${DERIVED_FILES_DIR}" 81 | 82 | local basename 83 | basename="$(basename -s .framework.dSYM "$source")" 84 | binary="${DERIVED_FILES_DIR}/${basename}.framework.dSYM/Contents/Resources/DWARF/${basename}" 85 | 86 | # Strip invalid architectures so "fat" simulator / device frameworks work on device 87 | if [[ "$(file "$binary")" == *"Mach-O dSYM companion"* ]]; then 88 | strip_invalid_archs "$binary" 89 | fi 90 | 91 | if [[ $STRIP_BINARY_RETVAL == 1 ]]; then 92 | # Move the stripped file into its final destination. 93 | echo "rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --filter \"- CVS/\" --filter \"- .svn/\" --filter \"- .git/\" --filter \"- .hg/\" --filter \"- Headers\" --filter \"- PrivateHeaders\" --filter \"- Modules\" \"${DERIVED_FILES_DIR}/${basename}.framework.dSYM\" \"${DWARF_DSYM_FOLDER_PATH}\"" 94 | rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --filter "- CVS/" --filter "- .svn/" --filter "- .git/" --filter "- .hg/" --filter "- Headers" --filter "- PrivateHeaders" --filter "- Modules" "${DERIVED_FILES_DIR}/${basename}.framework.dSYM" "${DWARF_DSYM_FOLDER_PATH}" 95 | else 96 | # The dSYM was not stripped at all, in this case touch a fake folder so the input/output paths from Xcode do not reexecute this script because the file is missing. 97 | touch "${DWARF_DSYM_FOLDER_PATH}/${basename}.framework.dSYM" 98 | fi 99 | fi 100 | } 101 | 102 | # Signs a framework with the provided identity 103 | code_sign_if_enabled() { 104 | if [ -n "${EXPANDED_CODE_SIGN_IDENTITY}" -a "${CODE_SIGNING_REQUIRED:-}" != "NO" -a "${CODE_SIGNING_ALLOWED}" != "NO" ]; then 105 | # Use the current code_sign_identitiy 106 | echo "Code Signing $1 with Identity ${EXPANDED_CODE_SIGN_IDENTITY_NAME}" 107 | local code_sign_cmd="/usr/bin/codesign --force --sign ${EXPANDED_CODE_SIGN_IDENTITY} ${OTHER_CODE_SIGN_FLAGS:-} --preserve-metadata=identifier,entitlements '$1'" 108 | 109 | if [ "${COCOAPODS_PARALLEL_CODE_SIGN}" == "true" ]; then 110 | code_sign_cmd="$code_sign_cmd &" 111 | fi 112 | echo "$code_sign_cmd" 113 | eval "$code_sign_cmd" 114 | fi 115 | } 116 | 117 | # Strip invalid architectures 118 | strip_invalid_archs() { 119 | binary="$1" 120 | # Get architectures for current target binary 121 | binary_archs="$(lipo -info "$binary" | rev | cut -d ':' -f1 | awk '{$1=$1;print}' | rev)" 122 | # Intersect them with the architectures we are building for 123 | intersected_archs="$(echo ${ARCHS[@]} ${binary_archs[@]} | tr ' ' '\n' | sort | uniq -d)" 124 | # If there are no archs supported by this binary then warn the user 125 | if [[ -z "$intersected_archs" ]]; then 126 | echo "warning: [CP] Vendored binary '$binary' contains architectures ($binary_archs) none of which match the current build architectures ($ARCHS)." 127 | STRIP_BINARY_RETVAL=0 128 | return 129 | fi 130 | stripped="" 131 | for arch in $binary_archs; do 132 | if ! [[ "${ARCHS}" == *"$arch"* ]]; then 133 | # Strip non-valid architectures in-place 134 | lipo -remove "$arch" -output "$binary" "$binary" || exit 1 135 | stripped="$stripped $arch" 136 | fi 137 | done 138 | if [[ "$stripped" ]]; then 139 | echo "Stripped $binary of architectures:$stripped" 140 | fi 141 | STRIP_BINARY_RETVAL=1 142 | } 143 | 144 | if [ "${COCOAPODS_PARALLEL_CODE_SIGN}" == "true" ]; then 145 | wait 146 | fi 147 | -------------------------------------------------------------------------------- /Demo/Driftwood_iOS/Pods/Target Support Files/Pods-Driftwood_iOS/Pods-Driftwood_iOS-resources.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | set -e 3 | set -u 4 | set -o pipefail 5 | 6 | if [ -z ${UNLOCALIZED_RESOURCES_FOLDER_PATH+x} ]; then 7 | # If UNLOCALIZED_RESOURCES_FOLDER_PATH is not set, then there's nowhere for us to copy 8 | # resources to, so exit 0 (signalling the script phase was successful). 9 | exit 0 10 | fi 11 | 12 | mkdir -p "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" 13 | 14 | RESOURCES_TO_COPY=${PODS_ROOT}/resources-to-copy-${TARGETNAME}.txt 15 | > "$RESOURCES_TO_COPY" 16 | 17 | XCASSET_FILES=() 18 | 19 | # This protects against multiple targets copying the same framework dependency at the same time. The solution 20 | # was originally proposed here: https://lists.samba.org/archive/rsync/2008-February/020158.html 21 | RSYNC_PROTECT_TMP_FILES=(--filter "P .*.??????") 22 | 23 | case "${TARGETED_DEVICE_FAMILY:-}" in 24 | 1,2) 25 | TARGET_DEVICE_ARGS="--target-device ipad --target-device iphone" 26 | ;; 27 | 1) 28 | TARGET_DEVICE_ARGS="--target-device iphone" 29 | ;; 30 | 2) 31 | TARGET_DEVICE_ARGS="--target-device ipad" 32 | ;; 33 | 3) 34 | TARGET_DEVICE_ARGS="--target-device tv" 35 | ;; 36 | 4) 37 | TARGET_DEVICE_ARGS="--target-device watch" 38 | ;; 39 | *) 40 | TARGET_DEVICE_ARGS="--target-device mac" 41 | ;; 42 | esac 43 | 44 | install_resource() 45 | { 46 | if [[ "$1" = /* ]] ; then 47 | RESOURCE_PATH="$1" 48 | else 49 | RESOURCE_PATH="${PODS_ROOT}/$1" 50 | fi 51 | if [[ ! -e "$RESOURCE_PATH" ]] ; then 52 | cat << EOM 53 | error: Resource "$RESOURCE_PATH" not found. Run 'pod install' to update the copy resources script. 54 | EOM 55 | exit 1 56 | fi 57 | case $RESOURCE_PATH in 58 | *.storyboard) 59 | echo "ibtool --reference-external-strings-file --errors --warnings --notices --minimum-deployment-target ${!DEPLOYMENT_TARGET_SETTING_NAME} --output-format human-readable-text --compile ${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$RESOURCE_PATH\" .storyboard`.storyboardc $RESOURCE_PATH --sdk ${SDKROOT} ${TARGET_DEVICE_ARGS}" || true 60 | ibtool --reference-external-strings-file --errors --warnings --notices --minimum-deployment-target ${!DEPLOYMENT_TARGET_SETTING_NAME} --output-format human-readable-text --compile "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$RESOURCE_PATH\" .storyboard`.storyboardc" "$RESOURCE_PATH" --sdk "${SDKROOT}" ${TARGET_DEVICE_ARGS} 61 | ;; 62 | *.xib) 63 | echo "ibtool --reference-external-strings-file --errors --warnings --notices --minimum-deployment-target ${!DEPLOYMENT_TARGET_SETTING_NAME} --output-format human-readable-text --compile ${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$RESOURCE_PATH\" .xib`.nib $RESOURCE_PATH --sdk ${SDKROOT} ${TARGET_DEVICE_ARGS}" || true 64 | ibtool --reference-external-strings-file --errors --warnings --notices --minimum-deployment-target ${!DEPLOYMENT_TARGET_SETTING_NAME} --output-format human-readable-text --compile "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$RESOURCE_PATH\" .xib`.nib" "$RESOURCE_PATH" --sdk "${SDKROOT}" ${TARGET_DEVICE_ARGS} 65 | ;; 66 | *.framework) 67 | echo "mkdir -p ${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" || true 68 | mkdir -p "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" 69 | echo "rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" $RESOURCE_PATH ${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" || true 70 | rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" "$RESOURCE_PATH" "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" 71 | ;; 72 | *.xcdatamodel) 73 | echo "xcrun momc \"$RESOURCE_PATH\" \"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH"`.mom\"" || true 74 | xcrun momc "$RESOURCE_PATH" "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcdatamodel`.mom" 75 | ;; 76 | *.xcdatamodeld) 77 | echo "xcrun momc \"$RESOURCE_PATH\" \"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcdatamodeld`.momd\"" || true 78 | xcrun momc "$RESOURCE_PATH" "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcdatamodeld`.momd" 79 | ;; 80 | *.xcmappingmodel) 81 | echo "xcrun mapc \"$RESOURCE_PATH\" \"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcmappingmodel`.cdm\"" || true 82 | xcrun mapc "$RESOURCE_PATH" "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcmappingmodel`.cdm" 83 | ;; 84 | *.xcassets) 85 | ABSOLUTE_XCASSET_FILE="$RESOURCE_PATH" 86 | XCASSET_FILES+=("$ABSOLUTE_XCASSET_FILE") 87 | ;; 88 | *) 89 | echo "$RESOURCE_PATH" || true 90 | echo "$RESOURCE_PATH" >> "$RESOURCES_TO_COPY" 91 | ;; 92 | esac 93 | } 94 | 95 | mkdir -p "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" 96 | rsync -avr --copy-links --no-relative --exclude '*/.svn/*' --files-from="$RESOURCES_TO_COPY" / "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" 97 | if [[ "${ACTION}" == "install" ]] && [[ "${SKIP_INSTALL}" == "NO" ]]; then 98 | mkdir -p "${INSTALL_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" 99 | rsync -avr --copy-links --no-relative --exclude '*/.svn/*' --files-from="$RESOURCES_TO_COPY" / "${INSTALL_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" 100 | fi 101 | rm -f "$RESOURCES_TO_COPY" 102 | 103 | if [[ -n "${WRAPPER_EXTENSION}" ]] && [ "`xcrun --find actool`" ] && [ -n "${XCASSET_FILES:-}" ] 104 | then 105 | # Find all other xcassets (this unfortunately includes those of path pods and other targets). 106 | OTHER_XCASSETS=$(find "$PWD" -iname "*.xcassets" -type d) 107 | while read line; do 108 | if [[ $line != "${PODS_ROOT}*" ]]; then 109 | XCASSET_FILES+=("$line") 110 | fi 111 | done <<<"$OTHER_XCASSETS" 112 | 113 | if [ -z ${ASSETCATALOG_COMPILER_APPICON_NAME+x} ]; then 114 | printf "%s\0" "${XCASSET_FILES[@]}" | xargs -0 xcrun actool --output-format human-readable-text --notices --warnings --platform "${PLATFORM_NAME}" --minimum-deployment-target "${!DEPLOYMENT_TARGET_SETTING_NAME}" ${TARGET_DEVICE_ARGS} --compress-pngs --compile "${BUILT_PRODUCTS_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" 115 | else 116 | printf "%s\0" "${XCASSET_FILES[@]}" | xargs -0 xcrun actool --output-format human-readable-text --notices --warnings --platform "${PLATFORM_NAME}" --minimum-deployment-target "${!DEPLOYMENT_TARGET_SETTING_NAME}" ${TARGET_DEVICE_ARGS} --compress-pngs --compile "${BUILT_PRODUCTS_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" --app-icon "${ASSETCATALOG_COMPILER_APPICON_NAME}" --output-partial-info-plist "${TARGET_TEMP_DIR}/assetcatalog_generated_info_cocoapods.plist" 117 | fi 118 | fi 119 | -------------------------------------------------------------------------------- /Demo/Driftwood_iOS/Pods/Target Support Files/Pods-Driftwood_iOS/Pods-Driftwood_iOS-umbrella.h: -------------------------------------------------------------------------------- 1 | #ifdef __OBJC__ 2 | #import 3 | #else 4 | #ifndef FOUNDATION_EXPORT 5 | #if defined(__cplusplus) 6 | #define FOUNDATION_EXPORT extern "C" 7 | #else 8 | #define FOUNDATION_EXPORT extern 9 | #endif 10 | #endif 11 | #endif 12 | 13 | 14 | FOUNDATION_EXPORT double Pods_Driftwood_iOSVersionNumber; 15 | FOUNDATION_EXPORT const unsigned char Pods_Driftwood_iOSVersionString[]; 16 | 17 | -------------------------------------------------------------------------------- /Demo/Driftwood_iOS/Pods/Target Support Files/Pods-Driftwood_iOS/Pods-Driftwood_iOS.debug.xcconfig: -------------------------------------------------------------------------------- 1 | ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES 2 | CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = NO 3 | GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 4 | LIBRARY_SEARCH_PATHS = $(inherited) "${DT_TOOLCHAIN_DIR}/usr/lib/swift/${PLATFORM_NAME}" "${PODS_CONFIGURATION_BUILD_DIR}/Driftwood" /usr/lib/swift 5 | OTHER_CFLAGS = $(inherited) -fmodule-map-file="${PODS_CONFIGURATION_BUILD_DIR}/Driftwood/Driftwood.modulemap" 6 | OTHER_LDFLAGS = $(inherited) -ObjC -l"Driftwood" 7 | OTHER_SWIFT_FLAGS = $(inherited) -D COCOAPODS -Xcc -fmodule-map-file="${PODS_CONFIGURATION_BUILD_DIR}/Driftwood/Driftwood.modulemap" 8 | PODS_BUILD_DIR = ${BUILD_DIR} 9 | PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) 10 | PODS_PODFILE_DIR_PATH = ${SRCROOT}/. 11 | PODS_ROOT = ${SRCROOT}/Pods 12 | PODS_XCFRAMEWORKS_BUILD_DIR = $(PODS_CONFIGURATION_BUILD_DIR)/XCFrameworkIntermediates 13 | SWIFT_INCLUDE_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/Driftwood" 14 | USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES 15 | -------------------------------------------------------------------------------- /Demo/Driftwood_iOS/Pods/Target Support Files/Pods-Driftwood_iOS/Pods-Driftwood_iOS.modulemap: -------------------------------------------------------------------------------- 1 | module Pods_Driftwood_iOS { 2 | umbrella header "Pods-Driftwood_iOS-umbrella.h" 3 | 4 | export * 5 | module * { export * } 6 | } 7 | -------------------------------------------------------------------------------- /Demo/Driftwood_iOS/Pods/Target Support Files/Pods-Driftwood_iOS/Pods-Driftwood_iOS.release.xcconfig: -------------------------------------------------------------------------------- 1 | ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES 2 | CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = NO 3 | GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 4 | LIBRARY_SEARCH_PATHS = $(inherited) "${DT_TOOLCHAIN_DIR}/usr/lib/swift/${PLATFORM_NAME}" "${PODS_CONFIGURATION_BUILD_DIR}/Driftwood" /usr/lib/swift 5 | OTHER_CFLAGS = $(inherited) -fmodule-map-file="${PODS_CONFIGURATION_BUILD_DIR}/Driftwood/Driftwood.modulemap" 6 | OTHER_LDFLAGS = $(inherited) -ObjC -l"Driftwood" 7 | OTHER_SWIFT_FLAGS = $(inherited) -D COCOAPODS -Xcc -fmodule-map-file="${PODS_CONFIGURATION_BUILD_DIR}/Driftwood/Driftwood.modulemap" 8 | PODS_BUILD_DIR = ${BUILD_DIR} 9 | PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) 10 | PODS_PODFILE_DIR_PATH = ${SRCROOT}/. 11 | PODS_ROOT = ${SRCROOT}/Pods 12 | PODS_XCFRAMEWORKS_BUILD_DIR = $(PODS_CONFIGURATION_BUILD_DIR)/XCFrameworkIntermediates 13 | SWIFT_INCLUDE_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/Driftwood" 14 | USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES 15 | -------------------------------------------------------------------------------- /Demo/Driftwood_macOS/Driftwood_macOS.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /Demo/Driftwood_macOS/Driftwood_macOS.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /Demo/Driftwood_macOS/Driftwood_macOS.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /Demo/Driftwood_macOS/Driftwood_macOS.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /Demo/Driftwood_macOS/Driftwood_macOS/AppDelegate.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.swift 3 | // Driftwood_macOS 4 | // 5 | 6 | import Cocoa 7 | 8 | @NSApplicationMain 9 | class AppDelegate: NSObject, NSApplicationDelegate { 10 | 11 | 12 | 13 | func applicationDidFinishLaunching(_ aNotification: Notification) { 14 | // Insert code here to initialize your application 15 | } 16 | 17 | func applicationWillTerminate(_ aNotification: Notification) { 18 | // Insert code here to tear down your application 19 | } 20 | 21 | 22 | } 23 | 24 | -------------------------------------------------------------------------------- /Demo/Driftwood_macOS/Driftwood_macOS/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "mac", 5 | "size" : "16x16", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "mac", 10 | "size" : "16x16", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "mac", 15 | "size" : "32x32", 16 | "scale" : "1x" 17 | }, 18 | { 19 | "idiom" : "mac", 20 | "size" : "32x32", 21 | "scale" : "2x" 22 | }, 23 | { 24 | "idiom" : "mac", 25 | "size" : "128x128", 26 | "scale" : "1x" 27 | }, 28 | { 29 | "idiom" : "mac", 30 | "size" : "128x128", 31 | "scale" : "2x" 32 | }, 33 | { 34 | "idiom" : "mac", 35 | "size" : "256x256", 36 | "scale" : "1x" 37 | }, 38 | { 39 | "idiom" : "mac", 40 | "size" : "256x256", 41 | "scale" : "2x" 42 | }, 43 | { 44 | "idiom" : "mac", 45 | "size" : "512x512", 46 | "scale" : "1x" 47 | }, 48 | { 49 | "idiom" : "mac", 50 | "size" : "512x512", 51 | "scale" : "2x" 52 | } 53 | ], 54 | "info" : { 55 | "version" : 1, 56 | "author" : "xcode" 57 | } 58 | } -------------------------------------------------------------------------------- /Demo/Driftwood_macOS/Driftwood_macOS/Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "version" : 1, 4 | "author" : "xcode" 5 | } 6 | } -------------------------------------------------------------------------------- /Demo/Driftwood_macOS/Driftwood_macOS/Driftwood_macOS.entitlements: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | com.apple.security.app-sandbox 6 | 7 | com.apple.security.files.user-selected.read-only 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /Demo/Driftwood_macOS/Driftwood_macOS/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | $(DEVELOPMENT_LANGUAGE) 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIconFile 10 | 11 | CFBundleIdentifier 12 | $(PRODUCT_BUNDLE_IDENTIFIER) 13 | CFBundleInfoDictionaryVersion 14 | 6.0 15 | CFBundleName 16 | $(PRODUCT_NAME) 17 | CFBundlePackageType 18 | APPL 19 | CFBundleShortVersionString 20 | 1.0 21 | CFBundleVersion 22 | 1 23 | LSMinimumSystemVersion 24 | $(MACOSX_DEPLOYMENT_TARGET) 25 | NSHumanReadableCopyright 26 | Copyright © 2019 wlgemini. All rights reserved. 27 | NSMainStoryboardFile 28 | Main 29 | NSPrincipalClass 30 | NSApplication 31 | 32 | 33 | -------------------------------------------------------------------------------- /Demo/Driftwood_macOS/Driftwood_macOS/Utils.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Utils.swift 3 | // Driftwood 4 | // 5 | 6 | import AppKit 7 | 8 | extension NSView { 9 | 10 | /// Create & Add & Return View 11 | func createSubView() -> T? { 12 | let v = T() 13 | v.translatesAutoresizingMaskIntoConstraints = false 14 | self.addSubview(v) 15 | return v 16 | } 17 | 18 | /// Create & Add & Return LayoutGuide 19 | func createSubLayoutGuide() -> NSLayoutGuide { 20 | let g = NSLayoutGuide() 21 | self.addLayoutGuide(g) 22 | return g 23 | } 24 | } 25 | 26 | extension NSColor { 27 | static var random: NSColor { 28 | return NSColor(deviceRed: CGFloat.random(in: 0...1), green: CGFloat.random(in: 0...1), blue: CGFloat.random(in: 0...1), alpha: 0.5) 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /Demo/Driftwood_macOS/Driftwood_macOS/ViewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.swift 3 | // Driftwood_macOS 4 | // 5 | 6 | import AppKit 7 | import Driftwood 8 | 9 | class ViewController: NSViewController { 10 | 11 | private weak var v1: NSButton! 12 | private weak var v2: NSButton! 13 | 14 | override func viewDidLoad() { 15 | super.viewDidLoad() 16 | self.view.wantsLayer = true 17 | self.view.dw.make().edge(insets: NSEdgeInsetsZero) 18 | self.v1 = self.view.createSubView() 19 | self.v1.bezelColor = NSColor.random 20 | self.v1.dw.make(labeled: "v1").centerX(0).centerY(0).width(50).height(100) 21 | 22 | self.v2 = self.view.createSubView() 23 | self.v1.bezelColor = NSColor.random 24 | self.v2.dw.make(labeled: "v2").top(10, to: self.v1.dw.bottom).centerX(0, to: self.v1.dw.centerX).width(100).height(to: self.v1.dw.width) 25 | } 26 | } 27 | 28 | -------------------------------------------------------------------------------- /Demo/Driftwood_macOS/Podfile: -------------------------------------------------------------------------------- 1 | # Uncomment the next line to define a global platform for your project 2 | platform :osx, '10.11' 3 | 4 | target 'Driftwood_macOS' do 5 | 6 | pod 'Driftwood', :path => '../../' 7 | 8 | end 9 | -------------------------------------------------------------------------------- /Demo/Driftwood_macOS/Podfile.lock: -------------------------------------------------------------------------------- 1 | PODS: 2 | - Driftwood (5.3.4) 3 | 4 | DEPENDENCIES: 5 | - Driftwood (from `../../`) 6 | 7 | EXTERNAL SOURCES: 8 | Driftwood: 9 | :path: "../../" 10 | 11 | SPEC CHECKSUMS: 12 | Driftwood: db053af5f771a6e1517452c8d6933ea4a288cebb 13 | 14 | PODFILE CHECKSUM: 90fdc768d8f35344c2f48df4b0b12d9e95b6f049 15 | 16 | COCOAPODS: 1.11.2 17 | -------------------------------------------------------------------------------- /Demo/Driftwood_macOS/Pods/Headers/Public/Driftwood/Driftwood-umbrella.h: -------------------------------------------------------------------------------- 1 | ../../../Target Support Files/Driftwood/Driftwood-umbrella.h -------------------------------------------------------------------------------- /Demo/Driftwood_macOS/Pods/Headers/Public/Driftwood/Driftwood.modulemap: -------------------------------------------------------------------------------- 1 | ../../../Target Support Files/Driftwood/Driftwood.modulemap -------------------------------------------------------------------------------- /Demo/Driftwood_macOS/Pods/Local Podspecs/Driftwood.podspec.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Driftwood", 3 | "version": "5.3.4", 4 | "summary": "A lightweight, Swift library for AutoLayout.", 5 | "homepage": "https://github.com/wlgemini/Driftwood", 6 | "license": { 7 | "type": "MIT", 8 | "file": "LICENSE" 9 | }, 10 | "authors": { 11 | "wlgemini": "wangluguang@live.com" 12 | }, 13 | "source": { 14 | "git": "https://github.com/wlgemini/Driftwood.git", 15 | "tag": "5.3.4" 16 | }, 17 | "swift_versions": [ 18 | "5.3", 19 | "5.4", 20 | "5.5" 21 | ], 22 | "platforms": { 23 | "ios": "8.0", 24 | "osx": "10.11", 25 | "tvos": "9.0" 26 | }, 27 | "source_files": "Sources/Driftwood/*.swift", 28 | "swift_version": "5.5" 29 | } 30 | -------------------------------------------------------------------------------- /Demo/Driftwood_macOS/Pods/Manifest.lock: -------------------------------------------------------------------------------- 1 | PODS: 2 | - Driftwood (5.3.4) 3 | 4 | DEPENDENCIES: 5 | - Driftwood (from `../../`) 6 | 7 | EXTERNAL SOURCES: 8 | Driftwood: 9 | :path: "../../" 10 | 11 | SPEC CHECKSUMS: 12 | Driftwood: db053af5f771a6e1517452c8d6933ea4a288cebb 13 | 14 | PODFILE CHECKSUM: 90fdc768d8f35344c2f48df4b0b12d9e95b6f049 15 | 16 | COCOAPODS: 1.11.2 17 | -------------------------------------------------------------------------------- /Demo/Driftwood_macOS/Pods/Target Support Files/Driftwood/Driftwood-dummy.m: -------------------------------------------------------------------------------- 1 | #import 2 | @interface PodsDummy_Driftwood : NSObject 3 | @end 4 | @implementation PodsDummy_Driftwood 5 | @end 6 | -------------------------------------------------------------------------------- /Demo/Driftwood_macOS/Pods/Target Support Files/Driftwood/Driftwood-prefix.pch: -------------------------------------------------------------------------------- 1 | #ifdef __OBJC__ 2 | #import 3 | #else 4 | #ifndef FOUNDATION_EXPORT 5 | #if defined(__cplusplus) 6 | #define FOUNDATION_EXPORT extern "C" 7 | #else 8 | #define FOUNDATION_EXPORT extern 9 | #endif 10 | #endif 11 | #endif 12 | 13 | -------------------------------------------------------------------------------- /Demo/Driftwood_macOS/Pods/Target Support Files/Driftwood/Driftwood-umbrella.h: -------------------------------------------------------------------------------- 1 | #ifdef __OBJC__ 2 | #import 3 | #else 4 | #ifndef FOUNDATION_EXPORT 5 | #if defined(__cplusplus) 6 | #define FOUNDATION_EXPORT extern "C" 7 | #else 8 | #define FOUNDATION_EXPORT extern 9 | #endif 10 | #endif 11 | #endif 12 | 13 | 14 | FOUNDATION_EXPORT double DriftwoodVersionNumber; 15 | FOUNDATION_EXPORT const unsigned char DriftwoodVersionString[]; 16 | 17 | -------------------------------------------------------------------------------- /Demo/Driftwood_macOS/Pods/Target Support Files/Driftwood/Driftwood.debug.xcconfig: -------------------------------------------------------------------------------- 1 | CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = NO 2 | CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/Driftwood 3 | GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 4 | OTHER_SWIFT_FLAGS = $(inherited) -D COCOAPODS -import-underlying-module -Xcc -fmodule-map-file="${SRCROOT}/${MODULEMAP_FILE}" 5 | PODS_BUILD_DIR = ${BUILD_DIR} 6 | PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) 7 | PODS_ROOT = ${SRCROOT} 8 | PODS_TARGET_SRCROOT = ${PODS_ROOT}/../../.. 9 | PODS_XCFRAMEWORKS_BUILD_DIR = $(PODS_CONFIGURATION_BUILD_DIR)/XCFrameworkIntermediates 10 | PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier} 11 | SKIP_INSTALL = YES 12 | USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES 13 | -------------------------------------------------------------------------------- /Demo/Driftwood_macOS/Pods/Target Support Files/Driftwood/Driftwood.modulemap: -------------------------------------------------------------------------------- 1 | module Driftwood { 2 | umbrella header "Driftwood-umbrella.h" 3 | 4 | export * 5 | module * { export * } 6 | } 7 | -------------------------------------------------------------------------------- /Demo/Driftwood_macOS/Pods/Target Support Files/Driftwood/Driftwood.release.xcconfig: -------------------------------------------------------------------------------- 1 | CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = NO 2 | CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/Driftwood 3 | GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 4 | OTHER_SWIFT_FLAGS = $(inherited) -D COCOAPODS -import-underlying-module -Xcc -fmodule-map-file="${SRCROOT}/${MODULEMAP_FILE}" 5 | PODS_BUILD_DIR = ${BUILD_DIR} 6 | PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) 7 | PODS_ROOT = ${SRCROOT} 8 | PODS_TARGET_SRCROOT = ${PODS_ROOT}/../../.. 9 | PODS_XCFRAMEWORKS_BUILD_DIR = $(PODS_CONFIGURATION_BUILD_DIR)/XCFrameworkIntermediates 10 | PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier} 11 | SKIP_INSTALL = YES 12 | USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES 13 | -------------------------------------------------------------------------------- /Demo/Driftwood_macOS/Pods/Target Support Files/Driftwood/Driftwood.xcconfig: -------------------------------------------------------------------------------- 1 | CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/Driftwood 2 | GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 3 | OTHER_SWIFT_FLAGS = $(inherited) -D COCOAPODS -import-underlying-module -Xcc -fmodule-map-file="${SRCROOT}/${MODULEMAP_FILE}" 4 | PODS_BUILD_DIR = ${BUILD_DIR} 5 | PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) 6 | PODS_ROOT = ${SRCROOT} 7 | PODS_TARGET_SRCROOT = ${PODS_ROOT}/../../.. 8 | PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier} 9 | SKIP_INSTALL = YES 10 | -------------------------------------------------------------------------------- /Demo/Driftwood_macOS/Pods/Target Support Files/Pods-Driftwood_macOS/Pods-Driftwood_macOS-acknowledgements.markdown: -------------------------------------------------------------------------------- 1 | # Acknowledgements 2 | This application makes use of the following third party libraries: 3 | 4 | ## Driftwood 5 | 6 | Copyright (c) 2018 wlgemini 7 | 8 | Permission is hereby granted, free of charge, to any person obtaining a copy 9 | of this software and associated documentation files (the "Software"), to deal 10 | in the Software without restriction, including without limitation the rights 11 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | copies of the Software, and to permit persons to whom the Software is 13 | furnished to do so, subject to the following conditions: 14 | 15 | The above copyright notice and this permission notice shall be included in 16 | all copies or substantial portions of the Software. 17 | 18 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 24 | THE SOFTWARE. 25 | 26 | Generated by CocoaPods - https://cocoapods.org 27 | -------------------------------------------------------------------------------- /Demo/Driftwood_macOS/Pods/Target Support Files/Pods-Driftwood_macOS/Pods-Driftwood_macOS-acknowledgements.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | PreferenceSpecifiers 6 | 7 | 8 | FooterText 9 | This application makes use of the following third party libraries: 10 | Title 11 | Acknowledgements 12 | Type 13 | PSGroupSpecifier 14 | 15 | 16 | FooterText 17 | Copyright (c) 2018 wlgemini <wangluguang@live.com> 18 | 19 | Permission is hereby granted, free of charge, to any person obtaining a copy 20 | of this software and associated documentation files (the "Software"), to deal 21 | in the Software without restriction, including without limitation the rights 22 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 23 | copies of the Software, and to permit persons to whom the Software is 24 | furnished to do so, subject to the following conditions: 25 | 26 | The above copyright notice and this permission notice shall be included in 27 | all copies or substantial portions of the Software. 28 | 29 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 30 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 31 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 32 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 33 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 34 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 35 | THE SOFTWARE. 36 | 37 | License 38 | MIT 39 | Title 40 | Driftwood 41 | Type 42 | PSGroupSpecifier 43 | 44 | 45 | FooterText 46 | Generated by CocoaPods - https://cocoapods.org 47 | Title 48 | 49 | Type 50 | PSGroupSpecifier 51 | 52 | 53 | StringsTable 54 | Acknowledgements 55 | Title 56 | Acknowledgements 57 | 58 | 59 | -------------------------------------------------------------------------------- /Demo/Driftwood_macOS/Pods/Target Support Files/Pods-Driftwood_macOS/Pods-Driftwood_macOS-dummy.m: -------------------------------------------------------------------------------- 1 | #import 2 | @interface PodsDummy_Pods_Driftwood_macOS : NSObject 3 | @end 4 | @implementation PodsDummy_Pods_Driftwood_macOS 5 | @end 6 | -------------------------------------------------------------------------------- /Demo/Driftwood_macOS/Pods/Target Support Files/Pods-Driftwood_macOS/Pods-Driftwood_macOS-frameworks.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | set -e 3 | set -u 4 | set -o pipefail 5 | 6 | if [ -z ${FRAMEWORKS_FOLDER_PATH+x} ]; then 7 | # If FRAMEWORKS_FOLDER_PATH is not set, then there's nowhere for us to copy 8 | # frameworks to, so exit 0 (signalling the script phase was successful). 9 | exit 0 10 | fi 11 | 12 | echo "mkdir -p ${CONFIGURATION_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" 13 | mkdir -p "${CONFIGURATION_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" 14 | 15 | COCOAPODS_PARALLEL_CODE_SIGN="${COCOAPODS_PARALLEL_CODE_SIGN:-false}" 16 | SWIFT_STDLIB_PATH="${DT_TOOLCHAIN_DIR}/usr/lib/swift/${PLATFORM_NAME}" 17 | 18 | # Used as a return value for each invocation of `strip_invalid_archs` function. 19 | STRIP_BINARY_RETVAL=0 20 | 21 | # This protects against multiple targets copying the same framework dependency at the same time. The solution 22 | # was originally proposed here: https://lists.samba.org/archive/rsync/2008-February/020158.html 23 | RSYNC_PROTECT_TMP_FILES=(--filter "P .*.??????") 24 | 25 | # Copies and strips a vendored framework 26 | install_framework() 27 | { 28 | if [ -r "${BUILT_PRODUCTS_DIR}/$1" ]; then 29 | local source="${BUILT_PRODUCTS_DIR}/$1" 30 | elif [ -r "${BUILT_PRODUCTS_DIR}/$(basename "$1")" ]; then 31 | local source="${BUILT_PRODUCTS_DIR}/$(basename "$1")" 32 | elif [ -r "$1" ]; then 33 | local source="$1" 34 | fi 35 | 36 | local destination="${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" 37 | 38 | if [ -L "${source}" ]; then 39 | echo "Symlinked..." 40 | source="$(readlink "${source}")" 41 | fi 42 | 43 | # Use filter instead of exclude so missing patterns don't throw errors. 44 | echo "rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --filter \"- CVS/\" --filter \"- .svn/\" --filter \"- .git/\" --filter \"- .hg/\" --filter \"- Headers\" --filter \"- PrivateHeaders\" --filter \"- Modules\" \"${source}\" \"${destination}\"" 45 | rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --filter "- CVS/" --filter "- .svn/" --filter "- .git/" --filter "- .hg/" --filter "- Headers" --filter "- PrivateHeaders" --filter "- Modules" "${source}" "${destination}" 46 | 47 | local basename 48 | basename="$(basename -s .framework "$1")" 49 | binary="${destination}/${basename}.framework/${basename}" 50 | if ! [ -r "$binary" ]; then 51 | binary="${destination}/${basename}" 52 | fi 53 | 54 | # Strip invalid architectures so "fat" simulator / device frameworks work on device 55 | if [[ "$(file "$binary")" == *"dynamically linked shared library"* ]]; then 56 | strip_invalid_archs "$binary" 57 | fi 58 | 59 | # Resign the code if required by the build settings to avoid unstable apps 60 | code_sign_if_enabled "${destination}/$(basename "$1")" 61 | 62 | # Embed linked Swift runtime libraries. No longer necessary as of Xcode 7. 63 | if [ "${XCODE_VERSION_MAJOR}" -lt 7 ]; then 64 | local swift_runtime_libs 65 | swift_runtime_libs=$(xcrun otool -LX "$binary" | grep --color=never @rpath/libswift | sed -E s/@rpath\\/\(.+dylib\).*/\\1/g | uniq -u && exit ${PIPESTATUS[0]}) 66 | for lib in $swift_runtime_libs; do 67 | echo "rsync -auv \"${SWIFT_STDLIB_PATH}/${lib}\" \"${destination}\"" 68 | rsync -auv "${SWIFT_STDLIB_PATH}/${lib}" "${destination}" 69 | code_sign_if_enabled "${destination}/${lib}" 70 | done 71 | fi 72 | } 73 | 74 | # Copies and strips a vendored dSYM 75 | install_dsym() { 76 | local source="$1" 77 | if [ -r "$source" ]; then 78 | # Copy the dSYM into a the targets temp dir. 79 | echo "rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --filter \"- CVS/\" --filter \"- .svn/\" --filter \"- .git/\" --filter \"- .hg/\" --filter \"- Headers\" --filter \"- PrivateHeaders\" --filter \"- Modules\" \"${source}\" \"${DERIVED_FILES_DIR}\"" 80 | rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --filter "- CVS/" --filter "- .svn/" --filter "- .git/" --filter "- .hg/" --filter "- Headers" --filter "- PrivateHeaders" --filter "- Modules" "${source}" "${DERIVED_FILES_DIR}" 81 | 82 | local basename 83 | basename="$(basename -s .framework.dSYM "$source")" 84 | binary="${DERIVED_FILES_DIR}/${basename}.framework.dSYM/Contents/Resources/DWARF/${basename}" 85 | 86 | # Strip invalid architectures so "fat" simulator / device frameworks work on device 87 | if [[ "$(file "$binary")" == *"Mach-O dSYM companion"* ]]; then 88 | strip_invalid_archs "$binary" 89 | fi 90 | 91 | if [[ $STRIP_BINARY_RETVAL == 1 ]]; then 92 | # Move the stripped file into its final destination. 93 | echo "rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --filter \"- CVS/\" --filter \"- .svn/\" --filter \"- .git/\" --filter \"- .hg/\" --filter \"- Headers\" --filter \"- PrivateHeaders\" --filter \"- Modules\" \"${DERIVED_FILES_DIR}/${basename}.framework.dSYM\" \"${DWARF_DSYM_FOLDER_PATH}\"" 94 | rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --filter "- CVS/" --filter "- .svn/" --filter "- .git/" --filter "- .hg/" --filter "- Headers" --filter "- PrivateHeaders" --filter "- Modules" "${DERIVED_FILES_DIR}/${basename}.framework.dSYM" "${DWARF_DSYM_FOLDER_PATH}" 95 | else 96 | # The dSYM was not stripped at all, in this case touch a fake folder so the input/output paths from Xcode do not reexecute this script because the file is missing. 97 | touch "${DWARF_DSYM_FOLDER_PATH}/${basename}.framework.dSYM" 98 | fi 99 | fi 100 | } 101 | 102 | # Signs a framework with the provided identity 103 | code_sign_if_enabled() { 104 | if [ -n "${EXPANDED_CODE_SIGN_IDENTITY}" -a "${CODE_SIGNING_REQUIRED:-}" != "NO" -a "${CODE_SIGNING_ALLOWED}" != "NO" ]; then 105 | # Use the current code_sign_identitiy 106 | echo "Code Signing $1 with Identity ${EXPANDED_CODE_SIGN_IDENTITY_NAME}" 107 | local code_sign_cmd="/usr/bin/codesign --force --sign ${EXPANDED_CODE_SIGN_IDENTITY} ${OTHER_CODE_SIGN_FLAGS:-} --preserve-metadata=identifier,entitlements '$1'" 108 | 109 | if [ "${COCOAPODS_PARALLEL_CODE_SIGN}" == "true" ]; then 110 | code_sign_cmd="$code_sign_cmd &" 111 | fi 112 | echo "$code_sign_cmd" 113 | eval "$code_sign_cmd" 114 | fi 115 | } 116 | 117 | # Strip invalid architectures 118 | strip_invalid_archs() { 119 | binary="$1" 120 | # Get architectures for current target binary 121 | binary_archs="$(lipo -info "$binary" | rev | cut -d ':' -f1 | awk '{$1=$1;print}' | rev)" 122 | # Intersect them with the architectures we are building for 123 | intersected_archs="$(echo ${ARCHS[@]} ${binary_archs[@]} | tr ' ' '\n' | sort | uniq -d)" 124 | # If there are no archs supported by this binary then warn the user 125 | if [[ -z "$intersected_archs" ]]; then 126 | echo "warning: [CP] Vendored binary '$binary' contains architectures ($binary_archs) none of which match the current build architectures ($ARCHS)." 127 | STRIP_BINARY_RETVAL=0 128 | return 129 | fi 130 | stripped="" 131 | for arch in $binary_archs; do 132 | if ! [[ "${ARCHS}" == *"$arch"* ]]; then 133 | # Strip non-valid architectures in-place 134 | lipo -remove "$arch" -output "$binary" "$binary" || exit 1 135 | stripped="$stripped $arch" 136 | fi 137 | done 138 | if [[ "$stripped" ]]; then 139 | echo "Stripped $binary of architectures:$stripped" 140 | fi 141 | STRIP_BINARY_RETVAL=1 142 | } 143 | 144 | if [ "${COCOAPODS_PARALLEL_CODE_SIGN}" == "true" ]; then 145 | wait 146 | fi 147 | -------------------------------------------------------------------------------- /Demo/Driftwood_macOS/Pods/Target Support Files/Pods-Driftwood_macOS/Pods-Driftwood_macOS-resources.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | set -e 3 | set -u 4 | set -o pipefail 5 | 6 | if [ -z ${UNLOCALIZED_RESOURCES_FOLDER_PATH+x} ]; then 7 | # If UNLOCALIZED_RESOURCES_FOLDER_PATH is not set, then there's nowhere for us to copy 8 | # resources to, so exit 0 (signalling the script phase was successful). 9 | exit 0 10 | fi 11 | 12 | mkdir -p "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" 13 | 14 | RESOURCES_TO_COPY=${PODS_ROOT}/resources-to-copy-${TARGETNAME}.txt 15 | > "$RESOURCES_TO_COPY" 16 | 17 | XCASSET_FILES=() 18 | 19 | # This protects against multiple targets copying the same framework dependency at the same time. The solution 20 | # was originally proposed here: https://lists.samba.org/archive/rsync/2008-February/020158.html 21 | RSYNC_PROTECT_TMP_FILES=(--filter "P .*.??????") 22 | 23 | case "${TARGETED_DEVICE_FAMILY:-}" in 24 | 1,2) 25 | TARGET_DEVICE_ARGS="--target-device ipad --target-device iphone" 26 | ;; 27 | 1) 28 | TARGET_DEVICE_ARGS="--target-device iphone" 29 | ;; 30 | 2) 31 | TARGET_DEVICE_ARGS="--target-device ipad" 32 | ;; 33 | 3) 34 | TARGET_DEVICE_ARGS="--target-device tv" 35 | ;; 36 | 4) 37 | TARGET_DEVICE_ARGS="--target-device watch" 38 | ;; 39 | *) 40 | TARGET_DEVICE_ARGS="--target-device mac" 41 | ;; 42 | esac 43 | 44 | install_resource() 45 | { 46 | if [[ "$1" = /* ]] ; then 47 | RESOURCE_PATH="$1" 48 | else 49 | RESOURCE_PATH="${PODS_ROOT}/$1" 50 | fi 51 | if [[ ! -e "$RESOURCE_PATH" ]] ; then 52 | cat << EOM 53 | error: Resource "$RESOURCE_PATH" not found. Run 'pod install' to update the copy resources script. 54 | EOM 55 | exit 1 56 | fi 57 | case $RESOURCE_PATH in 58 | *.storyboard) 59 | echo "ibtool --reference-external-strings-file --errors --warnings --notices --minimum-deployment-target ${!DEPLOYMENT_TARGET_SETTING_NAME} --output-format human-readable-text --compile ${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$RESOURCE_PATH\" .storyboard`.storyboardc $RESOURCE_PATH --sdk ${SDKROOT} ${TARGET_DEVICE_ARGS}" || true 60 | ibtool --reference-external-strings-file --errors --warnings --notices --minimum-deployment-target ${!DEPLOYMENT_TARGET_SETTING_NAME} --output-format human-readable-text --compile "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$RESOURCE_PATH\" .storyboard`.storyboardc" "$RESOURCE_PATH" --sdk "${SDKROOT}" ${TARGET_DEVICE_ARGS} 61 | ;; 62 | *.xib) 63 | echo "ibtool --reference-external-strings-file --errors --warnings --notices --minimum-deployment-target ${!DEPLOYMENT_TARGET_SETTING_NAME} --output-format human-readable-text --compile ${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$RESOURCE_PATH\" .xib`.nib $RESOURCE_PATH --sdk ${SDKROOT} ${TARGET_DEVICE_ARGS}" || true 64 | ibtool --reference-external-strings-file --errors --warnings --notices --minimum-deployment-target ${!DEPLOYMENT_TARGET_SETTING_NAME} --output-format human-readable-text --compile "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$RESOURCE_PATH\" .xib`.nib" "$RESOURCE_PATH" --sdk "${SDKROOT}" ${TARGET_DEVICE_ARGS} 65 | ;; 66 | *.framework) 67 | echo "mkdir -p ${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" || true 68 | mkdir -p "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" 69 | echo "rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" $RESOURCE_PATH ${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" || true 70 | rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" "$RESOURCE_PATH" "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" 71 | ;; 72 | *.xcdatamodel) 73 | echo "xcrun momc \"$RESOURCE_PATH\" \"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH"`.mom\"" || true 74 | xcrun momc "$RESOURCE_PATH" "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcdatamodel`.mom" 75 | ;; 76 | *.xcdatamodeld) 77 | echo "xcrun momc \"$RESOURCE_PATH\" \"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcdatamodeld`.momd\"" || true 78 | xcrun momc "$RESOURCE_PATH" "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcdatamodeld`.momd" 79 | ;; 80 | *.xcmappingmodel) 81 | echo "xcrun mapc \"$RESOURCE_PATH\" \"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcmappingmodel`.cdm\"" || true 82 | xcrun mapc "$RESOURCE_PATH" "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcmappingmodel`.cdm" 83 | ;; 84 | *.xcassets) 85 | ABSOLUTE_XCASSET_FILE="$RESOURCE_PATH" 86 | XCASSET_FILES+=("$ABSOLUTE_XCASSET_FILE") 87 | ;; 88 | *) 89 | echo "$RESOURCE_PATH" || true 90 | echo "$RESOURCE_PATH" >> "$RESOURCES_TO_COPY" 91 | ;; 92 | esac 93 | } 94 | 95 | mkdir -p "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" 96 | rsync -avr --copy-links --no-relative --exclude '*/.svn/*' --files-from="$RESOURCES_TO_COPY" / "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" 97 | if [[ "${ACTION}" == "install" ]] && [[ "${SKIP_INSTALL}" == "NO" ]]; then 98 | mkdir -p "${INSTALL_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" 99 | rsync -avr --copy-links --no-relative --exclude '*/.svn/*' --files-from="$RESOURCES_TO_COPY" / "${INSTALL_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" 100 | fi 101 | rm -f "$RESOURCES_TO_COPY" 102 | 103 | if [[ -n "${WRAPPER_EXTENSION}" ]] && [ "`xcrun --find actool`" ] && [ -n "${XCASSET_FILES:-}" ] 104 | then 105 | # Find all other xcassets (this unfortunately includes those of path pods and other targets). 106 | OTHER_XCASSETS=$(find "$PWD" -iname "*.xcassets" -type d) 107 | while read line; do 108 | if [[ $line != "${PODS_ROOT}*" ]]; then 109 | XCASSET_FILES+=("$line") 110 | fi 111 | done <<<"$OTHER_XCASSETS" 112 | 113 | if [ -z ${ASSETCATALOG_COMPILER_APPICON_NAME+x} ]; then 114 | printf "%s\0" "${XCASSET_FILES[@]}" | xargs -0 xcrun actool --output-format human-readable-text --notices --warnings --platform "${PLATFORM_NAME}" --minimum-deployment-target "${!DEPLOYMENT_TARGET_SETTING_NAME}" ${TARGET_DEVICE_ARGS} --compress-pngs --compile "${BUILT_PRODUCTS_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" 115 | else 116 | printf "%s\0" "${XCASSET_FILES[@]}" | xargs -0 xcrun actool --output-format human-readable-text --notices --warnings --platform "${PLATFORM_NAME}" --minimum-deployment-target "${!DEPLOYMENT_TARGET_SETTING_NAME}" ${TARGET_DEVICE_ARGS} --compress-pngs --compile "${BUILT_PRODUCTS_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" --app-icon "${ASSETCATALOG_COMPILER_APPICON_NAME}" --output-partial-info-plist "${TARGET_TEMP_DIR}/assetcatalog_generated_info_cocoapods.plist" 117 | fi 118 | fi 119 | -------------------------------------------------------------------------------- /Demo/Driftwood_macOS/Pods/Target Support Files/Pods-Driftwood_macOS/Pods-Driftwood_macOS-umbrella.h: -------------------------------------------------------------------------------- 1 | #ifdef __OBJC__ 2 | #import 3 | #else 4 | #ifndef FOUNDATION_EXPORT 5 | #if defined(__cplusplus) 6 | #define FOUNDATION_EXPORT extern "C" 7 | #else 8 | #define FOUNDATION_EXPORT extern 9 | #endif 10 | #endif 11 | #endif 12 | 13 | 14 | FOUNDATION_EXPORT double Pods_Driftwood_macOSVersionNumber; 15 | FOUNDATION_EXPORT const unsigned char Pods_Driftwood_macOSVersionString[]; 16 | 17 | -------------------------------------------------------------------------------- /Demo/Driftwood_macOS/Pods/Target Support Files/Pods-Driftwood_macOS/Pods-Driftwood_macOS.debug.xcconfig: -------------------------------------------------------------------------------- 1 | ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES 2 | CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = NO 3 | GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 4 | LIBRARY_SEARCH_PATHS = $(inherited) "${DT_TOOLCHAIN_DIR}/usr/lib/swift/${PLATFORM_NAME}" "${PODS_CONFIGURATION_BUILD_DIR}/Driftwood" /usr/lib/swift 5 | OTHER_CFLAGS = $(inherited) -fmodule-map-file="${PODS_CONFIGURATION_BUILD_DIR}/Driftwood/Driftwood.modulemap" 6 | OTHER_LDFLAGS = $(inherited) -ObjC -l"Driftwood" 7 | OTHER_SWIFT_FLAGS = $(inherited) -D COCOAPODS -Xcc -fmodule-map-file="${PODS_CONFIGURATION_BUILD_DIR}/Driftwood/Driftwood.modulemap" 8 | PODS_BUILD_DIR = ${BUILD_DIR} 9 | PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) 10 | PODS_PODFILE_DIR_PATH = ${SRCROOT}/. 11 | PODS_ROOT = ${SRCROOT}/Pods 12 | PODS_XCFRAMEWORKS_BUILD_DIR = $(PODS_CONFIGURATION_BUILD_DIR)/XCFrameworkIntermediates 13 | SWIFT_INCLUDE_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/Driftwood" 14 | USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES 15 | -------------------------------------------------------------------------------- /Demo/Driftwood_macOS/Pods/Target Support Files/Pods-Driftwood_macOS/Pods-Driftwood_macOS.modulemap: -------------------------------------------------------------------------------- 1 | module Pods_Driftwood_macOS { 2 | umbrella header "Pods-Driftwood_macOS-umbrella.h" 3 | 4 | export * 5 | module * { export * } 6 | } 7 | -------------------------------------------------------------------------------- /Demo/Driftwood_macOS/Pods/Target Support Files/Pods-Driftwood_macOS/Pods-Driftwood_macOS.release.xcconfig: -------------------------------------------------------------------------------- 1 | ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES 2 | CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = NO 3 | GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 4 | LIBRARY_SEARCH_PATHS = $(inherited) "${DT_TOOLCHAIN_DIR}/usr/lib/swift/${PLATFORM_NAME}" "${PODS_CONFIGURATION_BUILD_DIR}/Driftwood" /usr/lib/swift 5 | OTHER_CFLAGS = $(inherited) -fmodule-map-file="${PODS_CONFIGURATION_BUILD_DIR}/Driftwood/Driftwood.modulemap" 6 | OTHER_LDFLAGS = $(inherited) -ObjC -l"Driftwood" 7 | OTHER_SWIFT_FLAGS = $(inherited) -D COCOAPODS -Xcc -fmodule-map-file="${PODS_CONFIGURATION_BUILD_DIR}/Driftwood/Driftwood.modulemap" 8 | PODS_BUILD_DIR = ${BUILD_DIR} 9 | PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) 10 | PODS_PODFILE_DIR_PATH = ${SRCROOT}/. 11 | PODS_ROOT = ${SRCROOT}/Pods 12 | PODS_XCFRAMEWORKS_BUILD_DIR = $(PODS_CONFIGURATION_BUILD_DIR)/XCFrameworkIntermediates 13 | SWIFT_INCLUDE_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/Driftwood" 14 | USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES 15 | -------------------------------------------------------------------------------- /Demo/Driftwood_tvOS/Driftwood_tvOS.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /Demo/Driftwood_tvOS/Driftwood_tvOS.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /Demo/Driftwood_tvOS/Driftwood_tvOS.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /Demo/Driftwood_tvOS/Driftwood_tvOS.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /Demo/Driftwood_tvOS/Driftwood_tvOS/AppDelegate.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.swift 3 | // Driftwood_tvOS 4 | // 5 | 6 | import UIKit 7 | 8 | @UIApplicationMain 9 | class AppDelegate: UIResponder, UIApplicationDelegate { 10 | 11 | var window: UIWindow? 12 | 13 | 14 | func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { 15 | // Override point for customization after application launch. 16 | return true 17 | } 18 | 19 | func applicationWillResignActive(_ application: UIApplication) { 20 | // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. 21 | // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game. 22 | } 23 | 24 | func applicationDidEnterBackground(_ application: UIApplication) { 25 | // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. 26 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. 27 | } 28 | 29 | func applicationWillEnterForeground(_ application: UIApplication) { 30 | // Called as part of the transition from the background to the active state; here you can undo many of the changes made on entering the background. 31 | } 32 | 33 | func applicationDidBecomeActive(_ application: UIApplication) { 34 | // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. 35 | } 36 | 37 | func applicationWillTerminate(_ application: UIApplication) { 38 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. 39 | } 40 | 41 | 42 | } 43 | 44 | -------------------------------------------------------------------------------- /Demo/Driftwood_tvOS/Driftwood_tvOS/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - App Store.imagestack/Back.imagestacklayer/Content.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "tv" 5 | } 6 | ], 7 | "info" : { 8 | "version" : 1, 9 | "author" : "xcode" 10 | } 11 | } -------------------------------------------------------------------------------- /Demo/Driftwood_tvOS/Driftwood_tvOS/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - App Store.imagestack/Back.imagestacklayer/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "version" : 1, 4 | "author" : "xcode" 5 | } 6 | } -------------------------------------------------------------------------------- /Demo/Driftwood_tvOS/Driftwood_tvOS/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - App Store.imagestack/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "layers" : [ 3 | { 4 | "filename" : "Front.imagestacklayer" 5 | }, 6 | { 7 | "filename" : "Middle.imagestacklayer" 8 | }, 9 | { 10 | "filename" : "Back.imagestacklayer" 11 | } 12 | ], 13 | "info" : { 14 | "version" : 1, 15 | "author" : "xcode" 16 | } 17 | } -------------------------------------------------------------------------------- /Demo/Driftwood_tvOS/Driftwood_tvOS/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - App Store.imagestack/Front.imagestacklayer/Content.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "tv" 5 | } 6 | ], 7 | "info" : { 8 | "version" : 1, 9 | "author" : "xcode" 10 | } 11 | } -------------------------------------------------------------------------------- /Demo/Driftwood_tvOS/Driftwood_tvOS/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - App Store.imagestack/Front.imagestacklayer/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "version" : 1, 4 | "author" : "xcode" 5 | } 6 | } -------------------------------------------------------------------------------- /Demo/Driftwood_tvOS/Driftwood_tvOS/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - App Store.imagestack/Middle.imagestacklayer/Content.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "tv" 5 | } 6 | ], 7 | "info" : { 8 | "version" : 1, 9 | "author" : "xcode" 10 | } 11 | } -------------------------------------------------------------------------------- /Demo/Driftwood_tvOS/Driftwood_tvOS/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon - App Store.imagestack/Middle.imagestacklayer/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "version" : 1, 4 | "author" : "xcode" 5 | } 6 | } -------------------------------------------------------------------------------- /Demo/Driftwood_tvOS/Driftwood_tvOS/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon.imagestack/Back.imagestacklayer/Content.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "tv", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "tv", 9 | "scale" : "2x" 10 | } 11 | ], 12 | "info" : { 13 | "version" : 1, 14 | "author" : "xcode" 15 | } 16 | } -------------------------------------------------------------------------------- /Demo/Driftwood_tvOS/Driftwood_tvOS/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon.imagestack/Back.imagestacklayer/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "version" : 1, 4 | "author" : "xcode" 5 | } 6 | } -------------------------------------------------------------------------------- /Demo/Driftwood_tvOS/Driftwood_tvOS/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon.imagestack/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "layers" : [ 3 | { 4 | "filename" : "Front.imagestacklayer" 5 | }, 6 | { 7 | "filename" : "Middle.imagestacklayer" 8 | }, 9 | { 10 | "filename" : "Back.imagestacklayer" 11 | } 12 | ], 13 | "info" : { 14 | "version" : 1, 15 | "author" : "xcode" 16 | } 17 | } -------------------------------------------------------------------------------- /Demo/Driftwood_tvOS/Driftwood_tvOS/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon.imagestack/Front.imagestacklayer/Content.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "tv", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "tv", 9 | "scale" : "2x" 10 | } 11 | ], 12 | "info" : { 13 | "version" : 1, 14 | "author" : "xcode" 15 | } 16 | } -------------------------------------------------------------------------------- /Demo/Driftwood_tvOS/Driftwood_tvOS/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon.imagestack/Front.imagestacklayer/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "version" : 1, 4 | "author" : "xcode" 5 | } 6 | } -------------------------------------------------------------------------------- /Demo/Driftwood_tvOS/Driftwood_tvOS/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon.imagestack/Middle.imagestacklayer/Content.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "tv", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "tv", 9 | "scale" : "2x" 10 | } 11 | ], 12 | "info" : { 13 | "version" : 1, 14 | "author" : "xcode" 15 | } 16 | } -------------------------------------------------------------------------------- /Demo/Driftwood_tvOS/Driftwood_tvOS/Assets.xcassets/App Icon & Top Shelf Image.brandassets/App Icon.imagestack/Middle.imagestacklayer/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "version" : 1, 4 | "author" : "xcode" 5 | } 6 | } -------------------------------------------------------------------------------- /Demo/Driftwood_tvOS/Driftwood_tvOS/Assets.xcassets/App Icon & Top Shelf Image.brandassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "assets" : [ 3 | { 4 | "size" : "1280x768", 5 | "idiom" : "tv", 6 | "filename" : "App Icon - App Store.imagestack", 7 | "role" : "primary-app-icon" 8 | }, 9 | { 10 | "size" : "400x240", 11 | "idiom" : "tv", 12 | "filename" : "App Icon.imagestack", 13 | "role" : "primary-app-icon" 14 | }, 15 | { 16 | "size" : "2320x720", 17 | "idiom" : "tv", 18 | "filename" : "Top Shelf Image Wide.imageset", 19 | "role" : "top-shelf-image-wide" 20 | }, 21 | { 22 | "size" : "1920x720", 23 | "idiom" : "tv", 24 | "filename" : "Top Shelf Image.imageset", 25 | "role" : "top-shelf-image" 26 | } 27 | ], 28 | "info" : { 29 | "version" : 1, 30 | "author" : "xcode" 31 | } 32 | } -------------------------------------------------------------------------------- /Demo/Driftwood_tvOS/Driftwood_tvOS/Assets.xcassets/App Icon & Top Shelf Image.brandassets/Top Shelf Image Wide.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "tv", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "tv", 9 | "scale" : "2x" 10 | }, 11 | { 12 | "idiom" : "tv-marketing", 13 | "scale" : "1x" 14 | }, 15 | { 16 | "idiom" : "tv-marketing", 17 | "scale" : "2x" 18 | } 19 | ], 20 | "info" : { 21 | "version" : 1, 22 | "author" : "xcode" 23 | } 24 | } -------------------------------------------------------------------------------- /Demo/Driftwood_tvOS/Driftwood_tvOS/Assets.xcassets/App Icon & Top Shelf Image.brandassets/Top Shelf Image.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "tv", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "tv", 9 | "scale" : "2x" 10 | }, 11 | { 12 | "idiom" : "tv-marketing", 13 | "scale" : "1x" 14 | }, 15 | { 16 | "idiom" : "tv-marketing", 17 | "scale" : "2x" 18 | } 19 | ], 20 | "info" : { 21 | "version" : 1, 22 | "author" : "xcode" 23 | } 24 | } -------------------------------------------------------------------------------- /Demo/Driftwood_tvOS/Driftwood_tvOS/Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "version" : 1, 4 | "author" : "xcode" 5 | } 6 | } -------------------------------------------------------------------------------- /Demo/Driftwood_tvOS/Driftwood_tvOS/Assets.xcassets/Launch Image.launchimage/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "orientation" : "landscape", 5 | "idiom" : "tv", 6 | "extent" : "full-screen", 7 | "minimum-system-version" : "11.0", 8 | "scale" : "2x" 9 | }, 10 | { 11 | "orientation" : "landscape", 12 | "idiom" : "tv", 13 | "extent" : "full-screen", 14 | "minimum-system-version" : "9.0", 15 | "scale" : "1x" 16 | } 17 | ], 18 | "info" : { 19 | "version" : 1, 20 | "author" : "xcode" 21 | } 22 | } -------------------------------------------------------------------------------- /Demo/Driftwood_tvOS/Driftwood_tvOS/Base.lproj/Main.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 | 29 | -------------------------------------------------------------------------------- /Demo/Driftwood_tvOS/Driftwood_tvOS/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | $(DEVELOPMENT_LANGUAGE) 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | APPL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleVersion 20 | 1 21 | LSRequiresIPhoneOS 22 | 23 | UIMainStoryboardFile 24 | Main 25 | UIRequiredDeviceCapabilities 26 | 27 | arm64 28 | 29 | UIUserInterfaceStyle 30 | Automatic 31 | 32 | 33 | -------------------------------------------------------------------------------- /Demo/Driftwood_tvOS/Driftwood_tvOS/Utils.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Utils.swift 3 | // Driftwood 4 | // 5 | 6 | import UIKit 7 | 8 | extension UIView { 9 | 10 | /// Create & Add & Return View 11 | func createSubView() -> T? { 12 | let v = T() 13 | v.translatesAutoresizingMaskIntoConstraints = false 14 | self.addSubview(v) 15 | let c = UIColor(red: CGFloat.random(in: 0...1), green: CGFloat.random(in: 0...1), blue: CGFloat.random(in: 0...1), alpha: 0.5) 16 | v.backgroundColor = c 17 | return v 18 | } 19 | 20 | /// Create & Add & Return LayoutGuide 21 | func createSubLayoutGuide() -> UILayoutGuide { 22 | let g = UILayoutGuide() 23 | self.addLayoutGuide(g) 24 | return g 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /Demo/Driftwood_tvOS/Driftwood_tvOS/ViewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.swift 3 | // Driftwood_tvOS 4 | // 5 | 6 | import UIKit 7 | import Driftwood 8 | 9 | 10 | class ViewController: UIViewController { 11 | 12 | private weak var vTop: UIView! 13 | private weak var vBottom: UIView! 14 | private weak var vCenter: UIView! 15 | private weak var vLeading: UIView! 16 | private weak var vTrailing: UIView! 17 | 18 | override func viewDidLoad() { 19 | super.viewDidLoad() 20 | 21 | self.vTop = self.view.createSubView() 22 | self.vTop.dw.make(labeled: "Top").bottom(0, to: self.view.safeAreaLayoutGuide.dw.top).top(0).leading(0).trailing(0) 23 | 24 | self.vBottom = self.view.createSubView() 25 | self.vBottom.dw.make(labeled: "Bottom").top(0, to: self.view.safeAreaLayoutGuide.dw.bottom).bottom(0).leading(0).trailing(0) 26 | 27 | self.vCenter = self.view.createSubView() 28 | self.vCenter.dw.make(labeled: "Center").centerXY(offsets: .zero).width(100).height(150) 29 | 30 | self.vLeading = self.view.createSubView() 31 | self.vLeading.dw.make(labeled: "Leading").leading(0).trailing(0, to: self.vCenter.dw.leading).centerY(0, to: self.vCenter.dw.centerY).height(100) 32 | 33 | self.vTrailing = self.view.createSubView() 34 | self.vTrailing.dw.make(labeled: "Trailing").trailing(0).leading(0, to: self.vCenter.dw.trailing).top(0, to: self.vCenter.dw.top).height(100) 35 | } 36 | } 37 | 38 | -------------------------------------------------------------------------------- /Demo/Driftwood_tvOS/Podfile: -------------------------------------------------------------------------------- 1 | # Uncomment the next line to define a global platform for your project 2 | platform :tvos, '9.0' 3 | 4 | target 'Driftwood_tvOS' do 5 | 6 | pod 'Driftwood', :path => '../../' 7 | 8 | end 9 | -------------------------------------------------------------------------------- /Demo/Driftwood_tvOS/Podfile.lock: -------------------------------------------------------------------------------- 1 | PODS: 2 | - Driftwood (5.3.4) 3 | 4 | DEPENDENCIES: 5 | - Driftwood (from `../../`) 6 | 7 | EXTERNAL SOURCES: 8 | Driftwood: 9 | :path: "../../" 10 | 11 | SPEC CHECKSUMS: 12 | Driftwood: db053af5f771a6e1517452c8d6933ea4a288cebb 13 | 14 | PODFILE CHECKSUM: 9af28324e5abd116b9149951d5374765f55dbc74 15 | 16 | COCOAPODS: 1.11.2 17 | -------------------------------------------------------------------------------- /Demo/Driftwood_tvOS/Pods/Headers/Public/Driftwood/Driftwood-umbrella.h: -------------------------------------------------------------------------------- 1 | ../../../Target Support Files/Driftwood/Driftwood-umbrella.h -------------------------------------------------------------------------------- /Demo/Driftwood_tvOS/Pods/Headers/Public/Driftwood/Driftwood.modulemap: -------------------------------------------------------------------------------- 1 | ../../../Target Support Files/Driftwood/Driftwood.modulemap -------------------------------------------------------------------------------- /Demo/Driftwood_tvOS/Pods/Local Podspecs/Driftwood.podspec.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Driftwood", 3 | "version": "5.3.4", 4 | "summary": "A lightweight, Swift library for AutoLayout.", 5 | "homepage": "https://github.com/wlgemini/Driftwood", 6 | "license": { 7 | "type": "MIT", 8 | "file": "LICENSE" 9 | }, 10 | "authors": { 11 | "wlgemini": "wangluguang@live.com" 12 | }, 13 | "source": { 14 | "git": "https://github.com/wlgemini/Driftwood.git", 15 | "tag": "5.3.4" 16 | }, 17 | "swift_versions": [ 18 | "5.3", 19 | "5.4", 20 | "5.5" 21 | ], 22 | "platforms": { 23 | "ios": "8.0", 24 | "osx": "10.11", 25 | "tvos": "9.0" 26 | }, 27 | "source_files": "Sources/Driftwood/*.swift", 28 | "swift_version": "5.5" 29 | } 30 | -------------------------------------------------------------------------------- /Demo/Driftwood_tvOS/Pods/Manifest.lock: -------------------------------------------------------------------------------- 1 | PODS: 2 | - Driftwood (5.3.4) 3 | 4 | DEPENDENCIES: 5 | - Driftwood (from `../../`) 6 | 7 | EXTERNAL SOURCES: 8 | Driftwood: 9 | :path: "../../" 10 | 11 | SPEC CHECKSUMS: 12 | Driftwood: db053af5f771a6e1517452c8d6933ea4a288cebb 13 | 14 | PODFILE CHECKSUM: 9af28324e5abd116b9149951d5374765f55dbc74 15 | 16 | COCOAPODS: 1.11.2 17 | -------------------------------------------------------------------------------- /Demo/Driftwood_tvOS/Pods/Target Support Files/Driftwood/Driftwood-dummy.m: -------------------------------------------------------------------------------- 1 | #import 2 | @interface PodsDummy_Driftwood : NSObject 3 | @end 4 | @implementation PodsDummy_Driftwood 5 | @end 6 | -------------------------------------------------------------------------------- /Demo/Driftwood_tvOS/Pods/Target Support Files/Driftwood/Driftwood-prefix.pch: -------------------------------------------------------------------------------- 1 | #ifdef __OBJC__ 2 | #import 3 | #else 4 | #ifndef FOUNDATION_EXPORT 5 | #if defined(__cplusplus) 6 | #define FOUNDATION_EXPORT extern "C" 7 | #else 8 | #define FOUNDATION_EXPORT extern 9 | #endif 10 | #endif 11 | #endif 12 | 13 | -------------------------------------------------------------------------------- /Demo/Driftwood_tvOS/Pods/Target Support Files/Driftwood/Driftwood-umbrella.h: -------------------------------------------------------------------------------- 1 | #ifdef __OBJC__ 2 | #import 3 | #else 4 | #ifndef FOUNDATION_EXPORT 5 | #if defined(__cplusplus) 6 | #define FOUNDATION_EXPORT extern "C" 7 | #else 8 | #define FOUNDATION_EXPORT extern 9 | #endif 10 | #endif 11 | #endif 12 | 13 | 14 | FOUNDATION_EXPORT double DriftwoodVersionNumber; 15 | FOUNDATION_EXPORT const unsigned char DriftwoodVersionString[]; 16 | 17 | -------------------------------------------------------------------------------- /Demo/Driftwood_tvOS/Pods/Target Support Files/Driftwood/Driftwood.debug.xcconfig: -------------------------------------------------------------------------------- 1 | CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = NO 2 | CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/Driftwood 3 | GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 4 | OTHER_SWIFT_FLAGS = $(inherited) -D COCOAPODS -import-underlying-module -Xcc -fmodule-map-file="${SRCROOT}/${MODULEMAP_FILE}" 5 | PODS_BUILD_DIR = ${BUILD_DIR} 6 | PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) 7 | PODS_ROOT = ${SRCROOT} 8 | PODS_TARGET_SRCROOT = ${PODS_ROOT}/../../.. 9 | PODS_XCFRAMEWORKS_BUILD_DIR = $(PODS_CONFIGURATION_BUILD_DIR)/XCFrameworkIntermediates 10 | PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier} 11 | SKIP_INSTALL = YES 12 | USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES 13 | -------------------------------------------------------------------------------- /Demo/Driftwood_tvOS/Pods/Target Support Files/Driftwood/Driftwood.modulemap: -------------------------------------------------------------------------------- 1 | module Driftwood { 2 | umbrella header "Driftwood-umbrella.h" 3 | 4 | export * 5 | module * { export * } 6 | } 7 | -------------------------------------------------------------------------------- /Demo/Driftwood_tvOS/Pods/Target Support Files/Driftwood/Driftwood.release.xcconfig: -------------------------------------------------------------------------------- 1 | CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = NO 2 | CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/Driftwood 3 | GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 4 | OTHER_SWIFT_FLAGS = $(inherited) -D COCOAPODS -import-underlying-module -Xcc -fmodule-map-file="${SRCROOT}/${MODULEMAP_FILE}" 5 | PODS_BUILD_DIR = ${BUILD_DIR} 6 | PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) 7 | PODS_ROOT = ${SRCROOT} 8 | PODS_TARGET_SRCROOT = ${PODS_ROOT}/../../.. 9 | PODS_XCFRAMEWORKS_BUILD_DIR = $(PODS_CONFIGURATION_BUILD_DIR)/XCFrameworkIntermediates 10 | PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier} 11 | SKIP_INSTALL = YES 12 | USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES 13 | -------------------------------------------------------------------------------- /Demo/Driftwood_tvOS/Pods/Target Support Files/Driftwood/Driftwood.xcconfig: -------------------------------------------------------------------------------- 1 | CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/Driftwood 2 | GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 3 | OTHER_SWIFT_FLAGS = $(inherited) -D COCOAPODS -import-underlying-module -Xcc -fmodule-map-file="${SRCROOT}/${MODULEMAP_FILE}" 4 | PODS_BUILD_DIR = ${BUILD_DIR} 5 | PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) 6 | PODS_ROOT = ${SRCROOT} 7 | PODS_TARGET_SRCROOT = ${PODS_ROOT}/../../.. 8 | PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier} 9 | SKIP_INSTALL = YES 10 | -------------------------------------------------------------------------------- /Demo/Driftwood_tvOS/Pods/Target Support Files/Pods-Driftwood_tvOS/Pods-Driftwood_tvOS-acknowledgements.markdown: -------------------------------------------------------------------------------- 1 | # Acknowledgements 2 | This application makes use of the following third party libraries: 3 | 4 | ## Driftwood 5 | 6 | Copyright (c) 2018 wlgemini 7 | 8 | Permission is hereby granted, free of charge, to any person obtaining a copy 9 | of this software and associated documentation files (the "Software"), to deal 10 | in the Software without restriction, including without limitation the rights 11 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | copies of the Software, and to permit persons to whom the Software is 13 | furnished to do so, subject to the following conditions: 14 | 15 | The above copyright notice and this permission notice shall be included in 16 | all copies or substantial portions of the Software. 17 | 18 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 24 | THE SOFTWARE. 25 | 26 | Generated by CocoaPods - https://cocoapods.org 27 | -------------------------------------------------------------------------------- /Demo/Driftwood_tvOS/Pods/Target Support Files/Pods-Driftwood_tvOS/Pods-Driftwood_tvOS-acknowledgements.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | PreferenceSpecifiers 6 | 7 | 8 | FooterText 9 | This application makes use of the following third party libraries: 10 | Title 11 | Acknowledgements 12 | Type 13 | PSGroupSpecifier 14 | 15 | 16 | FooterText 17 | Copyright (c) 2018 wlgemini <wangluguang@live.com> 18 | 19 | Permission is hereby granted, free of charge, to any person obtaining a copy 20 | of this software and associated documentation files (the "Software"), to deal 21 | in the Software without restriction, including without limitation the rights 22 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 23 | copies of the Software, and to permit persons to whom the Software is 24 | furnished to do so, subject to the following conditions: 25 | 26 | The above copyright notice and this permission notice shall be included in 27 | all copies or substantial portions of the Software. 28 | 29 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 30 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 31 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 32 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 33 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 34 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 35 | THE SOFTWARE. 36 | 37 | License 38 | MIT 39 | Title 40 | Driftwood 41 | Type 42 | PSGroupSpecifier 43 | 44 | 45 | FooterText 46 | Generated by CocoaPods - https://cocoapods.org 47 | Title 48 | 49 | Type 50 | PSGroupSpecifier 51 | 52 | 53 | StringsTable 54 | Acknowledgements 55 | Title 56 | Acknowledgements 57 | 58 | 59 | -------------------------------------------------------------------------------- /Demo/Driftwood_tvOS/Pods/Target Support Files/Pods-Driftwood_tvOS/Pods-Driftwood_tvOS-dummy.m: -------------------------------------------------------------------------------- 1 | #import 2 | @interface PodsDummy_Pods_Driftwood_tvOS : NSObject 3 | @end 4 | @implementation PodsDummy_Pods_Driftwood_tvOS 5 | @end 6 | -------------------------------------------------------------------------------- /Demo/Driftwood_tvOS/Pods/Target Support Files/Pods-Driftwood_tvOS/Pods-Driftwood_tvOS-frameworks.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | set -e 3 | set -u 4 | set -o pipefail 5 | 6 | if [ -z ${FRAMEWORKS_FOLDER_PATH+x} ]; then 7 | # If FRAMEWORKS_FOLDER_PATH is not set, then there's nowhere for us to copy 8 | # frameworks to, so exit 0 (signalling the script phase was successful). 9 | exit 0 10 | fi 11 | 12 | echo "mkdir -p ${CONFIGURATION_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" 13 | mkdir -p "${CONFIGURATION_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" 14 | 15 | COCOAPODS_PARALLEL_CODE_SIGN="${COCOAPODS_PARALLEL_CODE_SIGN:-false}" 16 | SWIFT_STDLIB_PATH="${DT_TOOLCHAIN_DIR}/usr/lib/swift/${PLATFORM_NAME}" 17 | 18 | # Used as a return value for each invocation of `strip_invalid_archs` function. 19 | STRIP_BINARY_RETVAL=0 20 | 21 | # This protects against multiple targets copying the same framework dependency at the same time. The solution 22 | # was originally proposed here: https://lists.samba.org/archive/rsync/2008-February/020158.html 23 | RSYNC_PROTECT_TMP_FILES=(--filter "P .*.??????") 24 | 25 | # Copies and strips a vendored framework 26 | install_framework() 27 | { 28 | if [ -r "${BUILT_PRODUCTS_DIR}/$1" ]; then 29 | local source="${BUILT_PRODUCTS_DIR}/$1" 30 | elif [ -r "${BUILT_PRODUCTS_DIR}/$(basename "$1")" ]; then 31 | local source="${BUILT_PRODUCTS_DIR}/$(basename "$1")" 32 | elif [ -r "$1" ]; then 33 | local source="$1" 34 | fi 35 | 36 | local destination="${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" 37 | 38 | if [ -L "${source}" ]; then 39 | echo "Symlinked..." 40 | source="$(readlink "${source}")" 41 | fi 42 | 43 | # Use filter instead of exclude so missing patterns don't throw errors. 44 | echo "rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --filter \"- CVS/\" --filter \"- .svn/\" --filter \"- .git/\" --filter \"- .hg/\" --filter \"- Headers\" --filter \"- PrivateHeaders\" --filter \"- Modules\" \"${source}\" \"${destination}\"" 45 | rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --filter "- CVS/" --filter "- .svn/" --filter "- .git/" --filter "- .hg/" --filter "- Headers" --filter "- PrivateHeaders" --filter "- Modules" "${source}" "${destination}" 46 | 47 | local basename 48 | basename="$(basename -s .framework "$1")" 49 | binary="${destination}/${basename}.framework/${basename}" 50 | if ! [ -r "$binary" ]; then 51 | binary="${destination}/${basename}" 52 | fi 53 | 54 | # Strip invalid architectures so "fat" simulator / device frameworks work on device 55 | if [[ "$(file "$binary")" == *"dynamically linked shared library"* ]]; then 56 | strip_invalid_archs "$binary" 57 | fi 58 | 59 | # Resign the code if required by the build settings to avoid unstable apps 60 | code_sign_if_enabled "${destination}/$(basename "$1")" 61 | 62 | # Embed linked Swift runtime libraries. No longer necessary as of Xcode 7. 63 | if [ "${XCODE_VERSION_MAJOR}" -lt 7 ]; then 64 | local swift_runtime_libs 65 | swift_runtime_libs=$(xcrun otool -LX "$binary" | grep --color=never @rpath/libswift | sed -E s/@rpath\\/\(.+dylib\).*/\\1/g | uniq -u && exit ${PIPESTATUS[0]}) 66 | for lib in $swift_runtime_libs; do 67 | echo "rsync -auv \"${SWIFT_STDLIB_PATH}/${lib}\" \"${destination}\"" 68 | rsync -auv "${SWIFT_STDLIB_PATH}/${lib}" "${destination}" 69 | code_sign_if_enabled "${destination}/${lib}" 70 | done 71 | fi 72 | } 73 | 74 | # Copies and strips a vendored dSYM 75 | install_dsym() { 76 | local source="$1" 77 | if [ -r "$source" ]; then 78 | # Copy the dSYM into a the targets temp dir. 79 | echo "rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --filter \"- CVS/\" --filter \"- .svn/\" --filter \"- .git/\" --filter \"- .hg/\" --filter \"- Headers\" --filter \"- PrivateHeaders\" --filter \"- Modules\" \"${source}\" \"${DERIVED_FILES_DIR}\"" 80 | rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --filter "- CVS/" --filter "- .svn/" --filter "- .git/" --filter "- .hg/" --filter "- Headers" --filter "- PrivateHeaders" --filter "- Modules" "${source}" "${DERIVED_FILES_DIR}" 81 | 82 | local basename 83 | basename="$(basename -s .framework.dSYM "$source")" 84 | binary="${DERIVED_FILES_DIR}/${basename}.framework.dSYM/Contents/Resources/DWARF/${basename}" 85 | 86 | # Strip invalid architectures so "fat" simulator / device frameworks work on device 87 | if [[ "$(file "$binary")" == *"Mach-O dSYM companion"* ]]; then 88 | strip_invalid_archs "$binary" 89 | fi 90 | 91 | if [[ $STRIP_BINARY_RETVAL == 1 ]]; then 92 | # Move the stripped file into its final destination. 93 | echo "rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --filter \"- CVS/\" --filter \"- .svn/\" --filter \"- .git/\" --filter \"- .hg/\" --filter \"- Headers\" --filter \"- PrivateHeaders\" --filter \"- Modules\" \"${DERIVED_FILES_DIR}/${basename}.framework.dSYM\" \"${DWARF_DSYM_FOLDER_PATH}\"" 94 | rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --filter "- CVS/" --filter "- .svn/" --filter "- .git/" --filter "- .hg/" --filter "- Headers" --filter "- PrivateHeaders" --filter "- Modules" "${DERIVED_FILES_DIR}/${basename}.framework.dSYM" "${DWARF_DSYM_FOLDER_PATH}" 95 | else 96 | # The dSYM was not stripped at all, in this case touch a fake folder so the input/output paths from Xcode do not reexecute this script because the file is missing. 97 | touch "${DWARF_DSYM_FOLDER_PATH}/${basename}.framework.dSYM" 98 | fi 99 | fi 100 | } 101 | 102 | # Signs a framework with the provided identity 103 | code_sign_if_enabled() { 104 | if [ -n "${EXPANDED_CODE_SIGN_IDENTITY}" -a "${CODE_SIGNING_REQUIRED:-}" != "NO" -a "${CODE_SIGNING_ALLOWED}" != "NO" ]; then 105 | # Use the current code_sign_identitiy 106 | echo "Code Signing $1 with Identity ${EXPANDED_CODE_SIGN_IDENTITY_NAME}" 107 | local code_sign_cmd="/usr/bin/codesign --force --sign ${EXPANDED_CODE_SIGN_IDENTITY} ${OTHER_CODE_SIGN_FLAGS:-} --preserve-metadata=identifier,entitlements '$1'" 108 | 109 | if [ "${COCOAPODS_PARALLEL_CODE_SIGN}" == "true" ]; then 110 | code_sign_cmd="$code_sign_cmd &" 111 | fi 112 | echo "$code_sign_cmd" 113 | eval "$code_sign_cmd" 114 | fi 115 | } 116 | 117 | # Strip invalid architectures 118 | strip_invalid_archs() { 119 | binary="$1" 120 | # Get architectures for current target binary 121 | binary_archs="$(lipo -info "$binary" | rev | cut -d ':' -f1 | awk '{$1=$1;print}' | rev)" 122 | # Intersect them with the architectures we are building for 123 | intersected_archs="$(echo ${ARCHS[@]} ${binary_archs[@]} | tr ' ' '\n' | sort | uniq -d)" 124 | # If there are no archs supported by this binary then warn the user 125 | if [[ -z "$intersected_archs" ]]; then 126 | echo "warning: [CP] Vendored binary '$binary' contains architectures ($binary_archs) none of which match the current build architectures ($ARCHS)." 127 | STRIP_BINARY_RETVAL=0 128 | return 129 | fi 130 | stripped="" 131 | for arch in $binary_archs; do 132 | if ! [[ "${ARCHS}" == *"$arch"* ]]; then 133 | # Strip non-valid architectures in-place 134 | lipo -remove "$arch" -output "$binary" "$binary" || exit 1 135 | stripped="$stripped $arch" 136 | fi 137 | done 138 | if [[ "$stripped" ]]; then 139 | echo "Stripped $binary of architectures:$stripped" 140 | fi 141 | STRIP_BINARY_RETVAL=1 142 | } 143 | 144 | if [ "${COCOAPODS_PARALLEL_CODE_SIGN}" == "true" ]; then 145 | wait 146 | fi 147 | -------------------------------------------------------------------------------- /Demo/Driftwood_tvOS/Pods/Target Support Files/Pods-Driftwood_tvOS/Pods-Driftwood_tvOS-resources.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | set -e 3 | set -u 4 | set -o pipefail 5 | 6 | if [ -z ${UNLOCALIZED_RESOURCES_FOLDER_PATH+x} ]; then 7 | # If UNLOCALIZED_RESOURCES_FOLDER_PATH is not set, then there's nowhere for us to copy 8 | # resources to, so exit 0 (signalling the script phase was successful). 9 | exit 0 10 | fi 11 | 12 | mkdir -p "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" 13 | 14 | RESOURCES_TO_COPY=${PODS_ROOT}/resources-to-copy-${TARGETNAME}.txt 15 | > "$RESOURCES_TO_COPY" 16 | 17 | XCASSET_FILES=() 18 | 19 | # This protects against multiple targets copying the same framework dependency at the same time. The solution 20 | # was originally proposed here: https://lists.samba.org/archive/rsync/2008-February/020158.html 21 | RSYNC_PROTECT_TMP_FILES=(--filter "P .*.??????") 22 | 23 | case "${TARGETED_DEVICE_FAMILY:-}" in 24 | 1,2) 25 | TARGET_DEVICE_ARGS="--target-device ipad --target-device iphone" 26 | ;; 27 | 1) 28 | TARGET_DEVICE_ARGS="--target-device iphone" 29 | ;; 30 | 2) 31 | TARGET_DEVICE_ARGS="--target-device ipad" 32 | ;; 33 | 3) 34 | TARGET_DEVICE_ARGS="--target-device tv" 35 | ;; 36 | 4) 37 | TARGET_DEVICE_ARGS="--target-device watch" 38 | ;; 39 | *) 40 | TARGET_DEVICE_ARGS="--target-device mac" 41 | ;; 42 | esac 43 | 44 | install_resource() 45 | { 46 | if [[ "$1" = /* ]] ; then 47 | RESOURCE_PATH="$1" 48 | else 49 | RESOURCE_PATH="${PODS_ROOT}/$1" 50 | fi 51 | if [[ ! -e "$RESOURCE_PATH" ]] ; then 52 | cat << EOM 53 | error: Resource "$RESOURCE_PATH" not found. Run 'pod install' to update the copy resources script. 54 | EOM 55 | exit 1 56 | fi 57 | case $RESOURCE_PATH in 58 | *.storyboard) 59 | echo "ibtool --reference-external-strings-file --errors --warnings --notices --minimum-deployment-target ${!DEPLOYMENT_TARGET_SETTING_NAME} --output-format human-readable-text --compile ${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$RESOURCE_PATH\" .storyboard`.storyboardc $RESOURCE_PATH --sdk ${SDKROOT} ${TARGET_DEVICE_ARGS}" || true 60 | ibtool --reference-external-strings-file --errors --warnings --notices --minimum-deployment-target ${!DEPLOYMENT_TARGET_SETTING_NAME} --output-format human-readable-text --compile "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$RESOURCE_PATH\" .storyboard`.storyboardc" "$RESOURCE_PATH" --sdk "${SDKROOT}" ${TARGET_DEVICE_ARGS} 61 | ;; 62 | *.xib) 63 | echo "ibtool --reference-external-strings-file --errors --warnings --notices --minimum-deployment-target ${!DEPLOYMENT_TARGET_SETTING_NAME} --output-format human-readable-text --compile ${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$RESOURCE_PATH\" .xib`.nib $RESOURCE_PATH --sdk ${SDKROOT} ${TARGET_DEVICE_ARGS}" || true 64 | ibtool --reference-external-strings-file --errors --warnings --notices --minimum-deployment-target ${!DEPLOYMENT_TARGET_SETTING_NAME} --output-format human-readable-text --compile "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$RESOURCE_PATH\" .xib`.nib" "$RESOURCE_PATH" --sdk "${SDKROOT}" ${TARGET_DEVICE_ARGS} 65 | ;; 66 | *.framework) 67 | echo "mkdir -p ${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" || true 68 | mkdir -p "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" 69 | echo "rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" $RESOURCE_PATH ${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" || true 70 | rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" "$RESOURCE_PATH" "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" 71 | ;; 72 | *.xcdatamodel) 73 | echo "xcrun momc \"$RESOURCE_PATH\" \"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH"`.mom\"" || true 74 | xcrun momc "$RESOURCE_PATH" "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcdatamodel`.mom" 75 | ;; 76 | *.xcdatamodeld) 77 | echo "xcrun momc \"$RESOURCE_PATH\" \"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcdatamodeld`.momd\"" || true 78 | xcrun momc "$RESOURCE_PATH" "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcdatamodeld`.momd" 79 | ;; 80 | *.xcmappingmodel) 81 | echo "xcrun mapc \"$RESOURCE_PATH\" \"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcmappingmodel`.cdm\"" || true 82 | xcrun mapc "$RESOURCE_PATH" "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcmappingmodel`.cdm" 83 | ;; 84 | *.xcassets) 85 | ABSOLUTE_XCASSET_FILE="$RESOURCE_PATH" 86 | XCASSET_FILES+=("$ABSOLUTE_XCASSET_FILE") 87 | ;; 88 | *) 89 | echo "$RESOURCE_PATH" || true 90 | echo "$RESOURCE_PATH" >> "$RESOURCES_TO_COPY" 91 | ;; 92 | esac 93 | } 94 | 95 | mkdir -p "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" 96 | rsync -avr --copy-links --no-relative --exclude '*/.svn/*' --files-from="$RESOURCES_TO_COPY" / "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" 97 | if [[ "${ACTION}" == "install" ]] && [[ "${SKIP_INSTALL}" == "NO" ]]; then 98 | mkdir -p "${INSTALL_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" 99 | rsync -avr --copy-links --no-relative --exclude '*/.svn/*' --files-from="$RESOURCES_TO_COPY" / "${INSTALL_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" 100 | fi 101 | rm -f "$RESOURCES_TO_COPY" 102 | 103 | if [[ -n "${WRAPPER_EXTENSION}" ]] && [ "`xcrun --find actool`" ] && [ -n "${XCASSET_FILES:-}" ] 104 | then 105 | # Find all other xcassets (this unfortunately includes those of path pods and other targets). 106 | OTHER_XCASSETS=$(find "$PWD" -iname "*.xcassets" -type d) 107 | while read line; do 108 | if [[ $line != "${PODS_ROOT}*" ]]; then 109 | XCASSET_FILES+=("$line") 110 | fi 111 | done <<<"$OTHER_XCASSETS" 112 | 113 | if [ -z ${ASSETCATALOG_COMPILER_APPICON_NAME+x} ]; then 114 | printf "%s\0" "${XCASSET_FILES[@]}" | xargs -0 xcrun actool --output-format human-readable-text --notices --warnings --platform "${PLATFORM_NAME}" --minimum-deployment-target "${!DEPLOYMENT_TARGET_SETTING_NAME}" ${TARGET_DEVICE_ARGS} --compress-pngs --compile "${BUILT_PRODUCTS_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" 115 | else 116 | printf "%s\0" "${XCASSET_FILES[@]}" | xargs -0 xcrun actool --output-format human-readable-text --notices --warnings --platform "${PLATFORM_NAME}" --minimum-deployment-target "${!DEPLOYMENT_TARGET_SETTING_NAME}" ${TARGET_DEVICE_ARGS} --compress-pngs --compile "${BUILT_PRODUCTS_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}" --app-icon "${ASSETCATALOG_COMPILER_APPICON_NAME}" --output-partial-info-plist "${TARGET_TEMP_DIR}/assetcatalog_generated_info_cocoapods.plist" 117 | fi 118 | fi 119 | -------------------------------------------------------------------------------- /Demo/Driftwood_tvOS/Pods/Target Support Files/Pods-Driftwood_tvOS/Pods-Driftwood_tvOS-umbrella.h: -------------------------------------------------------------------------------- 1 | #ifdef __OBJC__ 2 | #import 3 | #else 4 | #ifndef FOUNDATION_EXPORT 5 | #if defined(__cplusplus) 6 | #define FOUNDATION_EXPORT extern "C" 7 | #else 8 | #define FOUNDATION_EXPORT extern 9 | #endif 10 | #endif 11 | #endif 12 | 13 | 14 | FOUNDATION_EXPORT double Pods_Driftwood_tvOSVersionNumber; 15 | FOUNDATION_EXPORT const unsigned char Pods_Driftwood_tvOSVersionString[]; 16 | 17 | -------------------------------------------------------------------------------- /Demo/Driftwood_tvOS/Pods/Target Support Files/Pods-Driftwood_tvOS/Pods-Driftwood_tvOS.debug.xcconfig: -------------------------------------------------------------------------------- 1 | ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES 2 | CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = NO 3 | GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 4 | LIBRARY_SEARCH_PATHS = $(inherited) "${DT_TOOLCHAIN_DIR}/usr/lib/swift/${PLATFORM_NAME}" "${PODS_CONFIGURATION_BUILD_DIR}/Driftwood" /usr/lib/swift 5 | OTHER_CFLAGS = $(inherited) -fmodule-map-file="${PODS_CONFIGURATION_BUILD_DIR}/Driftwood/Driftwood.modulemap" 6 | OTHER_LDFLAGS = $(inherited) -ObjC -l"Driftwood" 7 | OTHER_SWIFT_FLAGS = $(inherited) -D COCOAPODS -Xcc -fmodule-map-file="${PODS_CONFIGURATION_BUILD_DIR}/Driftwood/Driftwood.modulemap" 8 | PODS_BUILD_DIR = ${BUILD_DIR} 9 | PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) 10 | PODS_PODFILE_DIR_PATH = ${SRCROOT}/. 11 | PODS_ROOT = ${SRCROOT}/Pods 12 | PODS_XCFRAMEWORKS_BUILD_DIR = $(PODS_CONFIGURATION_BUILD_DIR)/XCFrameworkIntermediates 13 | SWIFT_INCLUDE_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/Driftwood" 14 | USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES 15 | -------------------------------------------------------------------------------- /Demo/Driftwood_tvOS/Pods/Target Support Files/Pods-Driftwood_tvOS/Pods-Driftwood_tvOS.modulemap: -------------------------------------------------------------------------------- 1 | module Pods_Driftwood_tvOS { 2 | umbrella header "Pods-Driftwood_tvOS-umbrella.h" 3 | 4 | export * 5 | module * { export * } 6 | } 7 | -------------------------------------------------------------------------------- /Demo/Driftwood_tvOS/Pods/Target Support Files/Pods-Driftwood_tvOS/Pods-Driftwood_tvOS.release.xcconfig: -------------------------------------------------------------------------------- 1 | ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES 2 | CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = NO 3 | GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 4 | LIBRARY_SEARCH_PATHS = $(inherited) "${DT_TOOLCHAIN_DIR}/usr/lib/swift/${PLATFORM_NAME}" "${PODS_CONFIGURATION_BUILD_DIR}/Driftwood" /usr/lib/swift 5 | OTHER_CFLAGS = $(inherited) -fmodule-map-file="${PODS_CONFIGURATION_BUILD_DIR}/Driftwood/Driftwood.modulemap" 6 | OTHER_LDFLAGS = $(inherited) -ObjC -l"Driftwood" 7 | OTHER_SWIFT_FLAGS = $(inherited) -D COCOAPODS -Xcc -fmodule-map-file="${PODS_CONFIGURATION_BUILD_DIR}/Driftwood/Driftwood.modulemap" 8 | PODS_BUILD_DIR = ${BUILD_DIR} 9 | PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) 10 | PODS_PODFILE_DIR_PATH = ${SRCROOT}/. 11 | PODS_ROOT = ${SRCROOT}/Pods 12 | PODS_XCFRAMEWORKS_BUILD_DIR = $(PODS_CONFIGURATION_BUILD_DIR)/XCFrameworkIntermediates 13 | SWIFT_INCLUDE_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/Driftwood" 14 | USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES 15 | -------------------------------------------------------------------------------- /Driftwood.podspec: -------------------------------------------------------------------------------- 1 | Pod::Spec.new do |s| 2 | s.name = 'Driftwood' 3 | s.version = '5.3.4' 4 | s.summary = 'A lightweight, Swift library for AutoLayout.' 5 | s.homepage = 'https://github.com/wlgemini/Driftwood' 6 | s.license = { :type => 'MIT', :file => 'LICENSE' } 7 | s.author = { 'wlgemini' => 'wangluguang@live.com' } 8 | s.source = { :git => 'https://github.com/wlgemini/Driftwood.git', :tag => s.version.to_s } 9 | 10 | s.swift_versions = ['5.3', '5.4', '5.5'] 11 | 12 | s.ios.deployment_target = '8.0' 13 | s.osx.deployment_target = '10.11' 14 | s.tvos.deployment_target = '9.0' 15 | 16 | s.source_files = 'Sources/Driftwood/*.swift' 17 | end 18 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2018 wlgemini 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 | -------------------------------------------------------------------------------- /Package.swift: -------------------------------------------------------------------------------- 1 | // swift-tools-version:5.5 2 | // The swift-tools-version declares the minimum version of Swift required to build this package. 3 | 4 | import PackageDescription 5 | 6 | let package = Package( 7 | name: "Driftwood", 8 | platforms: [ 9 | .iOS(.v8), .macOS(.v10_11), .tvOS(.v9) 10 | ], 11 | products: [ 12 | .library(name: "Driftwood", targets: ["Driftwood"]) 13 | ], 14 | targets: [ 15 | .target(name: "Driftwood", dependencies: []) 16 | ] 17 | ) 18 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | [![Driftwood CI](https://github.com/wlgemini/Driftwood/workflows/Driftwood%20CI/badge.svg)](https://github.com/wlgemini/Driftwood/actions) 4 | [![Version](https://img.shields.io/cocoapods/v/Driftwood.svg?style=flat)](https://cocoapods.org/pods/Driftwood) 5 | [![License](https://img.shields.io/cocoapods/l/Driftwood.svg?style=flat)](https://cocoapods.org/pods/Driftwood) 6 | [![Platform](https://img.shields.io/cocoapods/p/Driftwood.svg?style=flat)](https://cocoapods.org/pods/Driftwood) 7 | 8 | English|[中文](README_ZH.md) 9 | 10 | Driftwood is a DSL to make Auto Layout easy on iOS, tvOS and macOS. 11 | 12 | ## Usage 13 | 14 | Driftwood is easy to use, you can make full constraints satisfication in just a few code. 15 | 16 | Let's say we want to layout a box that is constrained to it’s superview’s edges with 0pts of padding. 17 | 18 | ```swift 19 | let box = UIView() 20 | superview.addSubview(box) 21 | box.dw.make().left(0).top(0).right(0).bottom(0) 22 | ``` 23 | Or another way: 24 | 25 | ```swift 26 | let box = UIView() 27 | superview.addSubview(box) 28 | box.dw.make().edge(insets: .zero) 29 | ``` 30 | 31 | ### Attribute 32 | 33 | All `NSLayoutConstraint.Attribute` cases are available in Driftwood. 34 | 35 | Let's say `view1` is at the bottom of `view2`, offset with 10pts. 36 | 37 | ```swift 38 | view1.dw.make().top(10, to: view2.dw.bottom) 39 | ``` 40 | 41 | Full list of `NSLayoutConstraint.Attribute`: 42 | 43 | | `Horizontal attribute property` | `Horizontal attribute function` | `NSLayoutConstraint.Attribute` | 44 | | :-------------------------- | :--------------------------- | :----------------------------- | 45 | | `dw.left` | `dw.make().left()` | `.left` | 46 | | `dw.right` | `dw.make().right()` | `.right` | 47 | | `dw.leading` | `dw.make().leading()` | `.leading` | 48 | | `dw.trailing` | `dw.make().trailing()` | `.trailing` | 49 | | `dw.centerX` | `dw.make().centerX()` | `.centerX` | 50 | | `dw.leftMargin` | `dw.make().leftMargin()` | `.leftMargin` | 51 | | `dw.rightMargin` | `dw.make().rightMargin()` | `.rightMargin` | 52 | | `dw.leadingMargin` | `dw.make().leadingMargin()` | `.leadingMargin` | 53 | | `dw.trailingMargin` | `dw.make().trailingMargin()` | `.trailingMargin` | 54 | 55 | | `Vertical attribute property` | `Vertical attribute function` | `NSLayoutConstraint.Attribute` | 56 | | :-------------------------- | :--------------------------------- | :----------------------------- | 57 | | `dw.top` | `dw.make().top()` | `.top` | 58 | | `dw.bottom` | `dw.make().bottom()` | `.bottom` | 59 | | `dw.centerY` | `dw.make().centerY()` | `.centerY` | 60 | | `dw.lastBaseline` | `dw.make().lastBaseline()` | `.lastBaseline` | 61 | | `dw.firstBaseline` | `dw.make().firstBaseline()` | `.firstBaseline` | 62 | | `dw.topMargin` | `dw.make().topMargin()` | `.topMargin` | 63 | | `dw.bottomMargin` | `dw.make().bottomMargin()` | `.bottomMargin` | 64 | | `dw.centerYWithinMargins` | `dw.make().centerYWithinMargins()` | `.centerYWithinMargins` | 65 | 66 | | `Size attribute property` | `Size attribute function` | `NSLayoutConstraint.Attribute` | 67 | | :------------------------ | :------------------------ | :----------------------------- | 68 | | `dw.width` | `dw.make().width()` | `.width` | 69 | | `dw.height` | `dw.make().height()` | `.height` | 70 | 71 | ### Relation & Multiply & Priority 72 | 73 | - `relation`: default is `.equal` 74 | - `multiply`: default is `1` 75 | - `priority`: default is `.required` 76 | 77 | ### dw.make() 78 | 79 | As you see above, you can use `dw.make()` to make full constraints easily. 80 | 81 | ### dw.update() 82 | 83 | You can use `dw.update()` to updating `constant` and `priority` value of a constraint. 84 | ```swift 85 | view1.dw.update().top(200) 86 | 87 | view2.dw.update().left(100, priority: .required) 88 | ``` 89 | 90 | ### dw.remake() 91 | 92 | `dw.remake()` is similar to `dw.make()`, but will first remove all existing constraints installed by Driftwood. 93 | 94 | ```swift 95 | view.dw.remake().left(20).top(30).width(20).height(10) 96 | ``` 97 | 98 | ### dw.remove() 99 | 100 | You can use `dw.remove()` to removing any existing constraints installed by Driftwood. 101 | ```swift 102 | view.dw.remove().left().top() 103 | ``` 104 | 105 | ### dw.removeAll() 106 | 107 | Sometimes, you may just want to remove all constraints installed before. You can use `dw.removeAll()` to removing all existing constraints installed by Driftwood. 108 | 109 | ```swift 110 | view.dw.removeAll() 111 | ``` 112 | 113 | ### LayoutGuide 114 | 115 | Driftwood can works with `LayoutGuide` easily. 116 | ```swift 117 | let guide = UILayoutGuide() 118 | superview.addLayoutGuide(guide) 119 | guide.dw.make().left(10).top(10).height(10).width(10) 120 | 121 | let box = UIView() 122 | superview.addSubview(box) 123 | box.dw.make().top(0, to: guide.dw.bottom).left(0).right(0).height(10) 124 | ``` 125 | 126 | ### Cache 127 | 128 | All constraints installed by Driftwood will be cached for future reuse. 129 | 130 | ### Debug 131 | 132 | You can labeled with a name to any `View` or `LayoutGuide` for debug. 133 | 134 | ```swift 135 | view.dw.make(labeled: "MyView").left(0).left(0) 136 | ``` 137 | 138 | It will be logs like this: 139 | 140 | ``` 141 | : Duplicated constraint. 142 | ``` 143 | 144 | If resulting `Unable to simultaneously satisfy constraints`, it will be logs like this for each constraint installed by Driftwood: 145 | 146 | ``` 147 | 148 | ``` 149 | 150 | > NOTE: In release, Driftwood will not log debug info. 151 | 152 | ## Demo 153 | 154 | You can download this repo to see more usage. 155 | 156 | ## Requirements 157 | 158 | - iOS 8.0+, macOS 10.11+, tvOS 9.0+ 159 | - Swift 4.2+ 160 | 161 | ## Installation 162 | 163 | Driftwood is available through [CocoaPods](https://cocoapods.org). To install it, simply add the following line to your Podfile: 164 | 165 | ```ruby 166 | pod 'Driftwood' 167 | ``` 168 | 169 | ## License 170 | 171 | Driftwood is available under the MIT license. See the LICENSE file for more info. 172 | -------------------------------------------------------------------------------- /README_ZH.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | [![Driftwood CI](https://github.com/wlgemini/Driftwood/workflows/Driftwood%20CI/badge.svg)](https://github.com/wlgemini/Driftwood/actions) 4 | [![Version](https://img.shields.io/cocoapods/v/Driftwood.svg?style=flat)](https://cocoapods.org/pods/Driftwood) 5 | [![License](https://img.shields.io/cocoapods/l/Driftwood.svg?style=flat)](https://cocoapods.org/pods/Driftwood) 6 | [![Platform](https://img.shields.io/cocoapods/p/Driftwood.svg?style=flat)](https://cocoapods.org/pods/Driftwood) 7 | 8 | [English](README.md)|中文 9 | 10 | Driftwood是一个轻量的自动布局框架,用于iOS, tvOS和macOS。 11 | 12 | ## Usage 13 | 14 | Driftwood的使用很简单,你只需要简单几行代码就能完整的设置好约束。 15 | 16 | 比如,一个`box`相对于`superview`的边距为0pt,代码如下: 17 | 18 | ```swift 19 | let box = UIView() 20 | superview.addSubview(box) // 先添加到superview上,才能再添加约束。 21 | box.dw.make().left(0).top(0).right(0).bottom(0) 22 | ``` 23 | 24 | 或者另外一种写法: 25 | 26 | ```swift 27 | let box = UIView() 28 | superview.addSubview(box) // 先添加到superview上,才能再添加约束。 29 | box.dw.make().edge(insets: .zero) 30 | ``` 31 | 32 | ### Attribute 33 | 34 | 所有的`NSLayoutConstraint.Attribute`情况在Driftwood中都是可用的. 35 | 36 | 比如说,`view1`在`view2`的底部,偏移10pt: 37 | 38 | ```swift 39 | view1.dw.make().top(10, to: view2.dw.bottom) 40 | ``` 41 | 42 | 全部的`NSLayoutConstraint.Attribute`情况在Driftwood中对应关系如下表: 43 | 44 | | `Horizontal attribute property` | `Horizontal attribute function` | `NSLayoutConstraint.Attribute` | 45 | | :-------------------------- | :--------------------------- | :----------------------------- | 46 | | `dw.left` | `dw.make().left()` | `.left` | 47 | | `dw.right` | `dw.make().right()` | `.right` | 48 | | `dw.leading` | `dw.make().leading()` | `.leading` | 49 | | `dw.trailing` | `dw.make().trailing()` | `.trailing` | 50 | | `dw.centerX` | `dw.make().centerX()` | `.centerX` | 51 | | `dw.leftMargin` | `dw.make().leftMargin()` | `.leftMargin` | 52 | | `dw.rightMargin` | `dw.make().rightMargin()` | `.rightMargin` | 53 | | `dw.leadingMargin` | `dw.make().leadingMargin()` | `.leadingMargin` | 54 | | `dw.trailingMargin` | `dw.make().trailingMargin()` | `.trailingMargin` | 55 | 56 | | `Vertical attribute property` | `Vertical attribute function` | `NSLayoutConstraint.Attribute` | 57 | | :-------------------------- | :--------------------------------- | :----------------------------- | 58 | | `dw.top` | `dw.make().top()` | `.top` | 59 | | `dw.bottom` | `dw.make().bottom()` | `.bottom` | 60 | | `dw.centerY` | `dw.make().centerY()` | `.centerY` | 61 | | `dw.lastBaseline` | `dw.make().lastBaseline()` | `.lastBaseline` | 62 | | `dw.firstBaseline` | `dw.make().firstBaseline()` | `.firstBaseline` | 63 | | `dw.topMargin` | `dw.make().topMargin()` | `.topMargin` | 64 | | `dw.bottomMargin` | `dw.make().bottomMargin()` | `.bottomMargin` | 65 | | `dw.centerYWithinMargins` | `dw.make().centerYWithinMargins()` | `.centerYWithinMargins` | 66 | 67 | | `Size attribute property` | `Size attribute function` | `NSLayoutConstraint.Attribute` | 68 | | :------------------------ | :------------------------ | :----------------------------- | 69 | | `dw.width` | `dw.make().width()` | `.width` | 70 | | `dw.height` | `dw.make().height()` | `.height` | 71 | 72 | ### Relation & Multiply & Priority 73 | 74 | - `relation`: 默认为`.equal` 75 | - `multiply`: 默认为 `1` 76 | - `priority`: 默认为 `.required` 77 | 78 | ### dw.make() 79 | 80 | 就像在**Quick Start**中看到的,你可以使用`dw.make()`来设置完整的约束。 81 | 82 | ### dw.update() 83 | 84 | 你可以使用`dw.update()`来更新约束的 `constant` 和 `priority` 的值 85 | 86 | ```swift 87 | view1.dw.update().top(200) // 更新top约束的constant为200pt 88 | 89 | view2.dw.update().left(100, priority: .required) // 更新left约束的constant为100pt,priority为required 90 | ``` 91 | 92 | ### dw.remake() 93 | 94 | `dw.remake()`和`dw.make()`很像,也用于设置约束,但会先移除当前view上所有通过Driftwood设置的约束。 95 | 96 | ```swift 97 | view.dw.remake().left(20).top(30).width(20).height(10) // 先移除view的相关约束,然后再设置新约束 98 | ``` 99 | 100 | ### dw.remove() 101 | 102 | 你可以使用`dw.remove()` 来移除当前view上通过Driftwood设置的约束。 103 | 104 | ```swift 105 | view.dw.remove().left().top() 106 | ``` 107 | 108 | ### dw.removeAll() 109 | 110 | 有时候,你可能只想移除之前设置的所有约束,你可以使用 `dw.removeAll()`来移除当前view上通过Driftwood设置的所有约束。 111 | 112 | ```swift 113 | view.dw.removeAll() 114 | ``` 115 | 116 | ### LayoutGuide 117 | 118 | Driftwood可以很方便的对LayoutGuide应用约束。 119 | 120 | ```swift 121 | let guide = UILayoutGuide() 122 | superview.addLayoutGuide(guide) // 添加LayoutGuide到superview 123 | guide.dw.make().left(10).top(10).height(10).width(10) // 给LayoutGuide添加约束 124 | 125 | let box = UIView() 126 | superview.addSubview(box) 127 | box.dw.make().top(0, to: guide.dw.bottom).left(0).right(0).height(10) // LayoutGuide和View混合使用 128 | ``` 129 | 130 | ### Cache 131 | 132 | 所有通过Driftwood创建的约束都会被缓存起来,以便于之后复用这些约束。 133 | 134 | ### Debug 135 | 136 | 你可以给一个 `View` 或者 `LayoutGuide`添加标签,以用于debug。 137 | 138 | ```swift 139 | view.dw.make(labeled: "MyView").left(0).left(0) // 给"MyView"添加了重复的left约束 140 | ``` 141 | 142 | 如果出现错误的话,会有如下样式的打印: 143 | 144 | ``` 145 | : Duplicated constraint. 146 | ``` 147 | 148 | 如果遇到 `Unable to simultaneously satisfy constraints` 这种约束错误,则会对每一个通过Driftwood设置的约束有如下样式的打印: 149 | 150 | ``` 151 | 152 | ``` 153 | 154 | > 注意:在release下,Driftwood不会打印debug信息。 155 | 156 | ## Demo 157 | 158 | 你可以下载这个仓库来查看更多的使用方法。 159 | 160 | ## Requirements 161 | 162 | - iOS 8.0+, macOS 10.11+, tvOS 9.0+ 163 | - Swift 4.2+ 164 | 165 | ## Installation 166 | 167 | Driftwood is available through [CocoaPods](https://cocoapods.org). To install it, simply add the following line to your Podfile: 168 | 169 | ```ruby 170 | pod 'Driftwood' 171 | ``` 172 | 173 | ## License 174 | 175 | Driftwood is available under the MIT license. See the LICENSE file for more info. 176 | -------------------------------------------------------------------------------- /Sources/Driftwood/Attribute.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Driftwood 3 | // 4 | // Copyright (c) 2018-Present wlgemini . 5 | // 6 | // Permission is hereby granted, free of charge, to any person obtaining a copy 7 | // of this software and associated documentation files (the "Software"), to deal 8 | // in the Software without restriction, including without limitation the rights 9 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | // copies of the Software, and to permit persons to whom the Software is 11 | // furnished to do so, subject to the following conditions: 12 | // 13 | // The above copyright notice and this permission notice shall be included in all 14 | // copies or substantial portions of the Software. 15 | 16 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | // SOFTWARE. 23 | 24 | 25 | /// Horizontal attribute 26 | public enum HAttribute { 27 | 28 | case superview 29 | 30 | case left(Item) 31 | 32 | case right(Item) 33 | 34 | case leading(Item) 35 | 36 | case trailing(Item) 37 | 38 | case centerX(Item) 39 | 40 | #if os(iOS) || os(tvOS) 41 | case leftMargin(Item) 42 | 43 | case rightMargin(Item) 44 | 45 | case leadingMargin(Item) 46 | 47 | case trailingMargin(Item) 48 | 49 | case centerXWithinMargins(Item) 50 | #endif 51 | } 52 | 53 | 54 | /// Vertical attribute 55 | public enum VAttribute { 56 | 57 | case superview 58 | 59 | case top(Item) 60 | 61 | case bottom(Item) 62 | 63 | case centerY(Item) 64 | 65 | case lastBaseline(Item) 66 | 67 | case firstBaseline(Item) 68 | 69 | #if os(iOS) || os(tvOS) 70 | case topMargin(Item) 71 | 72 | case bottomMargin(Item) 73 | 74 | case centerYWithinMargins(Item) 75 | #endif 76 | } 77 | 78 | 79 | /// Size attribute 80 | public enum SAttribute { 81 | 82 | case width(Item) 83 | 84 | case height(Item) 85 | } 86 | -------------------------------------------------------------------------------- /Sources/Driftwood/Constraint.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Driftwood 3 | // 4 | // Copyright (c) 2018-Present wlgemini . 5 | // 6 | // Permission is hereby granted, free of charge, to any person obtaining a copy 7 | // of this software and associated documentation files (the "Software"), to deal 8 | // in the Software without restriction, including without limitation the rights 9 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | // copies of the Software, and to permit persons to whom the Software is 11 | // furnished to do so, subject to the following conditions: 12 | // 13 | // The above copyright notice and this permission notice shall be included in all 14 | // copies or substantial portions of the Software. 15 | 16 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | // SOFTWARE. 23 | 24 | 25 | /// Constraint 26 | final class Constraint: LayoutConstraint { 27 | 28 | /// location (never nil when used) 29 | var location: Debug.Location! 30 | 31 | /// operation (never nil when used) 32 | var operation: Debug.Operation! 33 | 34 | /// description 35 | /// 36 | /// "" 37 | /// 38 | override var description: String { 39 | // < 40 | var desc = "<" 41 | 42 | // prefix 43 | desc += Debug.prefix(location: self.location, operation: self.operation) 44 | 45 | // constraint 46 | desc += ".(" 47 | 48 | if let fi = self.firstItem { 49 | desc += Debug.description(for: fi) 50 | } 51 | 52 | if self.firstAttribute != .notAnAttribute { 53 | desc += ".\(Debug.description(for: self.firstAttribute))" 54 | } 55 | 56 | desc += " \(Debug.description(for: self.relation))" 57 | 58 | if let si = self.secondItem { 59 | desc += " \(Debug.description(for: si))" 60 | } 61 | 62 | if self.secondAttribute != .notAnAttribute { 63 | desc += ".\(Debug.description(for: self.secondAttribute))" 64 | } 65 | 66 | if self.multiplier != 1.0 { 67 | desc += " * \(self.multiplier)" 68 | } 69 | 70 | if self.secondAttribute == .notAnAttribute { 71 | desc += " \(self.constant)" 72 | } else { 73 | if self.constant > 0.0 { 74 | desc += " + \(self.constant)" 75 | } else if self.constant < 0.0 { 76 | desc += " - \(abs(self.constant))" 77 | } 78 | } 79 | 80 | if self.priority.rawValue != 1000.0 { 81 | desc += " ^\(self.priority.rawValue)" 82 | } 83 | 84 | desc += ")" 85 | 86 | // > 87 | desc += ">" 88 | 89 | return desc 90 | } 91 | } 92 | -------------------------------------------------------------------------------- /Sources/Driftwood/ConstraintKey.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Driftwood 3 | // 4 | // Copyright (c) 2018-Present wlgemini . 5 | // 6 | // Permission is hereby granted, free of charge, to any person obtaining a copy 7 | // of this software and associated documentation files (the "Software"), to deal 8 | // in the Software without restriction, including without limitation the rights 9 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | // copies of the Software, and to permit persons to whom the Software is 11 | // furnished to do so, subject to the following conditions: 12 | // 13 | // The above copyright notice and this permission notice shall be included in all 14 | // copies or substantial portions of the Software. 15 | 16 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | // SOFTWARE. 23 | 24 | 25 | import CoreGraphics 26 | 27 | 28 | /// ConstraintKey 29 | struct ConstraintKey: Hashable { 30 | 31 | /// attribute 32 | let attribute: Attribute 33 | 34 | /// Using `ObjectIdentifier` to avoid ARC: [Difference between using ObjectIdentifier() and '===' Operator](https://stackoverflow.com/questions/39587027/difference-between-using-objectidentifier-and-operator) 35 | let toItem: ObjectIdentifier? 36 | 37 | /// toAttribute 38 | let toAttribute: Attribute 39 | 40 | /// relation 41 | let relation: Relation 42 | 43 | /// multiply 44 | let multiply: CGFloat 45 | 46 | /// init 47 | init(attribute: Attribute, toItem: Item?, toAttribute: Attribute, relation: Relation, multiply: CGFloat) { 48 | self.attribute = attribute 49 | self.toItem = toItem.map(ObjectIdentifier.init) 50 | self.toAttribute = toAttribute 51 | self.relation = relation 52 | self.multiply = multiply 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /Sources/Driftwood/ConstraintRemover+Handy.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Driftwood 3 | // 4 | // Copyright (c) 2018-Present wlgemini . 5 | // 6 | // Permission is hereby granted, free of charge, to any person obtaining a copy 7 | // of this software and associated documentation files (the "Software"), to deal 8 | // in the Software without restriction, including without limitation the rights 9 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | // copies of the Software, and to permit persons to whom the Software is 11 | // furnished to do so, subject to the following conditions: 12 | // 13 | // The above copyright notice and this permission notice shall be included in all 14 | // copies or substantial portions of the Software. 15 | 16 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | // SOFTWARE. 23 | 24 | 25 | /// ConstraintRemover (Handy) 26 | public extension ConstraintRemover { 27 | 28 | // MARK: - 29 | // MARK: Remove size constraint 30 | /// size 31 | @inlinable 32 | @discardableResult 33 | func size() -> Self { 34 | self.width() 35 | self.height() 36 | return self 37 | } 38 | 39 | // MARK: - 40 | // MARK: Remove horizontal & vertical constraint 41 | /// centerXY 42 | @inlinable 43 | @discardableResult 44 | func centerXY() -> Self { 45 | self.centerX() 46 | self.centerY() 47 | return self 48 | } 49 | 50 | /// edge 51 | @inlinable 52 | @discardableResult 53 | func edge() -> Self { 54 | self.left() 55 | self.right() 56 | self.top() 57 | self.bottom() 58 | return self 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /Sources/Driftwood/ConstraintRemover.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Driftwood 3 | // 4 | // Copyright (c) 2018-Present wlgemini . 5 | // 6 | // Permission is hereby granted, free of charge, to any person obtaining a copy 7 | // of this software and associated documentation files (the "Software"), to deal 8 | // in the Software without restriction, including without limitation the rights 9 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | // copies of the Software, and to permit persons to whom the Software is 11 | // furnished to do so, subject to the following conditions: 12 | // 13 | // The above copyright notice and this permission notice shall be included in all 14 | // copies or substantial portions of the Software. 15 | 16 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | // SOFTWARE. 23 | 24 | 25 | /// ConstraintRemover 26 | public struct ConstraintRemover { 27 | 28 | // MARK: - 29 | // MARK: Remove horizontal constraint 30 | /// left 31 | @discardableResult 32 | public func left() -> Self { 33 | self._remove(attribute: .left) 34 | } 35 | 36 | /// right 37 | @discardableResult 38 | public func right() -> Self { 39 | self._remove(attribute: .right) 40 | } 41 | 42 | /// leading 43 | @discardableResult 44 | public func leading() -> Self { 45 | self._remove(attribute: .leading) 46 | } 47 | 48 | /// trailing 49 | @discardableResult 50 | public func trailing() -> Self { 51 | self._remove(attribute: .trailing) 52 | } 53 | 54 | /// centerX 55 | @discardableResult 56 | public func centerX() -> Self { 57 | self._remove(attribute: .centerX) 58 | } 59 | 60 | #if os(iOS) || os(tvOS) 61 | /// leftMargin 62 | @discardableResult 63 | public func leftMargin() -> Self { 64 | self._remove(attribute: .leftMargin) 65 | } 66 | 67 | /// rightMargin 68 | @discardableResult 69 | public func rightMargin() -> Self { 70 | self._remove(attribute: .rightMargin) 71 | } 72 | 73 | /// leadingMargin 74 | @discardableResult 75 | public func leadingMargin() -> Self { 76 | self._remove(attribute: .leadingMargin) 77 | } 78 | 79 | /// trailingMargin 80 | @discardableResult 81 | public func trailingMargin() -> Self { 82 | self._remove(attribute: .trailingMargin) 83 | } 84 | 85 | /// centerXWithinMargins 86 | @discardableResult 87 | public func centerXWithinMargins() -> Self { 88 | self._remove(attribute: .centerXWithinMargins) 89 | } 90 | #endif 91 | 92 | // MARK: - 93 | // MARK: Remove vertical constraint 94 | /// top 95 | @discardableResult 96 | public func top() -> Self { 97 | self._remove(attribute: .top) 98 | } 99 | 100 | /// bottom 101 | @discardableResult 102 | public func bottom() -> Self { 103 | self._remove(attribute: .bottom) 104 | } 105 | 106 | /// centerY 107 | @discardableResult 108 | public func centerY() -> Self { 109 | self._remove(attribute: .centerY) 110 | } 111 | 112 | /// lastBaseline 113 | @discardableResult 114 | public func lastBaseline() -> Self { 115 | self._remove(attribute: .lastBaseline) 116 | } 117 | 118 | /// firstBaseline 119 | @discardableResult 120 | public func firstBaseline() -> Self { 121 | self._remove(attribute: .firstBaseline) 122 | } 123 | 124 | #if os(iOS) || os(tvOS) 125 | /// topMargin 126 | @discardableResult 127 | public func topMargin() -> Self { 128 | self._remove(attribute: .topMargin) 129 | } 130 | 131 | /// bottomMargin 132 | @discardableResult 133 | public func bottomMargin() -> Self { 134 | self._remove(attribute: .bottomMargin) 135 | } 136 | 137 | /// centerYWithinMargins 138 | @discardableResult 139 | public func centerYWithinMargins() -> Self { 140 | self._remove(attribute: .centerYWithinMargins) 141 | } 142 | #endif 143 | 144 | // MARK: - 145 | // MARK: Remove size constraint 146 | /// width 147 | @discardableResult 148 | public func width() -> Self { 149 | self._remove(attribute: .width) 150 | } 151 | 152 | /// height 153 | @discardableResult 154 | public func height() -> Self { 155 | self._remove(attribute: .height) 156 | } 157 | 158 | // MARK: - Internal 159 | /// init 160 | init(item: Item, location: Debug.Location, labeled name: String?) { 161 | self._item = item 162 | self._storage = Storage.storage(for: item) 163 | self._location = location 164 | 165 | // set label 166 | if let nm = name { 167 | self._storage.labeledName = nm 168 | } 169 | } 170 | 171 | // MARK: - Private 172 | /// remove constraint 173 | @discardableResult 174 | private func _remove(attribute: Attribute) -> Self { 175 | // 0. deactivate a constraint installed by driftwood if any 176 | guard let _ = self._storage.deactivate(for: attribute) else { 177 | Debug.log(location: self._location, operation: .remove(attribute), item: self._item, message: "No constraint.") 178 | return self 179 | } 180 | 181 | // 1. return self 182 | return self 183 | } 184 | 185 | /// a `View/LayoutGuide` 186 | private unowned(unsafe) let _item: Item 187 | 188 | /// a `Storage` 189 | private unowned(unsafe) let _storage: Storage 190 | 191 | /// a `Location` 192 | private let _location: Debug.Location 193 | } 194 | -------------------------------------------------------------------------------- /Sources/Driftwood/ConstraintUpdater+Handy.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Driftwood 3 | // 4 | // Copyright (c) 2018-Present wlgemini . 5 | // 6 | // Permission is hereby granted, free of charge, to any person obtaining a copy 7 | // of this software and associated documentation files (the "Software"), to deal 8 | // in the Software without restriction, including without limitation the rights 9 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | // copies of the Software, and to permit persons to whom the Software is 11 | // furnished to do so, subject to the following conditions: 12 | // 13 | // The above copyright notice and this permission notice shall be included in all 14 | // copies or substantial portions of the Software. 15 | 16 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | // SOFTWARE. 23 | 24 | 25 | import CoreGraphics 26 | 27 | 28 | /// ConstraintUpdater (Handy) 29 | public extension ConstraintUpdater { 30 | 31 | // MARK: - 32 | // MARK: Update horizontal & vertical constraint 33 | /// centerXY 34 | @inlinable 35 | @discardableResult 36 | func centerXY(offsets: CGPoint? = nil, priority: Priority? = nil) -> Self { 37 | self.centerX(offsets?.x, priority: priority) 38 | self.centerY(offsets?.y, priority: priority) 39 | return self 40 | } 41 | 42 | /// edge 43 | @inlinable 44 | @discardableResult 45 | func edge(insets: EdgeInsets? = nil, priority: Priority? = nil) -> Self { 46 | let insets = insets.map { EdgeInsets(top: $0.top, left: $0.left, bottom: -$0.bottom, right: -$0.right) } 47 | self.left(insets?.left, priority: priority) 48 | self.right(insets?.right, priority: priority) 49 | self.top(insets?.top, priority: priority) 50 | self.bottom(insets?.bottom, priority: priority) 51 | return self 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /Sources/Driftwood/ConstraintUpdater.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Driftwood 3 | // 4 | // Copyright (c) 2018-Present wlgemini . 5 | // 6 | // Permission is hereby granted, free of charge, to any person obtaining a copy 7 | // of this software and associated documentation files (the "Software"), to deal 8 | // in the Software without restriction, including without limitation the rights 9 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | // copies of the Software, and to permit persons to whom the Software is 11 | // furnished to do so, subject to the following conditions: 12 | // 13 | // The above copyright notice and this permission notice shall be included in all 14 | // copies or substantial portions of the Software. 15 | 16 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | // SOFTWARE. 23 | 24 | 25 | import CoreGraphics 26 | 27 | 28 | /// ConstraintUpdater 29 | public struct ConstraintUpdater { 30 | 31 | // MARK: - 32 | // MARK: Update horizontal constraint 33 | /// left 34 | @discardableResult 35 | public func left(_ constant: CGFloat? = nil, priority: Priority? = nil) -> Self { 36 | self._update(attribute: .left, constant: constant, priority: priority) 37 | } 38 | 39 | /// right 40 | @discardableResult 41 | public func right(_ constant: CGFloat? = nil, priority: Priority? = nil) -> Self { 42 | self._update(attribute: .right, constant: constant, priority: priority) 43 | } 44 | 45 | /// leading 46 | @discardableResult 47 | public func leading(_ constant: CGFloat? = nil, priority: Priority? = nil) -> Self { 48 | self._update(attribute: .leading, constant: constant, priority: priority) 49 | } 50 | 51 | /// trailing 52 | @discardableResult 53 | public func trailing(_ constant: CGFloat? = nil, priority: Priority? = nil) -> Self { 54 | self._update(attribute: .trailing, constant: constant, priority: priority) 55 | } 56 | 57 | /// centerX 58 | @discardableResult 59 | public func centerX(_ constant: CGFloat? = nil, priority: Priority? = nil) -> Self { 60 | self._update(attribute: .centerX, constant: constant, priority: priority) 61 | } 62 | 63 | #if os(iOS) || os(tvOS) 64 | /// leftMargin 65 | @discardableResult 66 | public func leftMargin(_ constant: CGFloat? = nil, priority: Priority? = nil) -> Self { 67 | self._update(attribute: .leftMargin, constant: constant, priority: priority) 68 | } 69 | 70 | /// rightMargin 71 | @discardableResult 72 | public func rightMargin(_ constant: CGFloat? = nil, priority: Priority? = nil) -> Self { 73 | self._update(attribute: .rightMargin, constant: constant, priority: priority) 74 | } 75 | 76 | /// leadingMargin 77 | @discardableResult 78 | public func leadingMargin(_ constant: CGFloat? = nil, priority: Priority? = nil) -> Self { 79 | self._update(attribute: .leadingMargin, constant: constant, priority: priority) 80 | } 81 | 82 | /// trailingMargin 83 | @discardableResult 84 | public func trailingMargin(_ constant: CGFloat? = nil, priority: Priority? = nil) -> Self { 85 | self._update(attribute: .trailingMargin, constant: constant, priority: priority) 86 | } 87 | 88 | /// centerXWithinMargins 89 | @discardableResult 90 | public func centerXWithinMargins(_ constant: CGFloat? = nil, priority: Priority? = nil) -> Self { 91 | self._update(attribute: .centerXWithinMargins, constant: constant, priority: priority) 92 | } 93 | #endif 94 | 95 | // MARK: - 96 | // MARK: Update vertical constraint 97 | /// top 98 | @discardableResult 99 | public func top(_ constant: CGFloat? = nil, priority: Priority? = nil) -> Self { 100 | self._update(attribute: .top, constant: constant, priority: priority) 101 | } 102 | 103 | /// bottom 104 | @discardableResult 105 | public func bottom(_ constant: CGFloat? = nil, priority: Priority? = nil) -> Self { 106 | self._update(attribute: .bottom, constant: constant, priority: priority) 107 | } 108 | 109 | /// centerY 110 | @discardableResult 111 | public func centerY(_ constant: CGFloat? = nil, priority: Priority? = nil) -> Self { 112 | self._update(attribute: .centerY, constant: constant, priority: priority) 113 | } 114 | 115 | /// lastBaseline 116 | @discardableResult 117 | public func lastBaseline(_ constant: CGFloat? = nil, priority: Priority? = nil) -> Self { 118 | self._update(attribute: .lastBaseline, constant: constant, priority: priority) 119 | } 120 | 121 | /// firstBaseline 122 | @discardableResult 123 | public func firstBaseline(_ constant: CGFloat? = nil, priority: Priority? = nil) -> Self { 124 | self._update(attribute: .firstBaseline, constant: constant, priority: priority) 125 | } 126 | 127 | #if os(iOS) || os(tvOS) 128 | /// topMargin 129 | @discardableResult 130 | public func topMargin(_ constant: CGFloat? = nil, priority: Priority? = nil) -> Self { 131 | self._update(attribute: .topMargin, constant: constant, priority: priority) 132 | } 133 | 134 | /// bottomMargin 135 | @discardableResult 136 | public func bottomMargin(_ constant: CGFloat? = nil, priority: Priority? = nil) -> Self { 137 | self._update(attribute: .bottomMargin, constant: constant, priority: priority) 138 | } 139 | 140 | /// centerYWithinMargins 141 | @discardableResult 142 | public func centerYWithinMargins(_ constant: CGFloat? = nil, priority: Priority? = nil) -> Self { 143 | self._update(attribute: .centerYWithinMargins, constant: constant, priority: priority) 144 | } 145 | #endif 146 | 147 | // MARK: - 148 | // MARK: Update size constraint 149 | /// width 150 | @discardableResult 151 | public func width(_ constant: CGFloat? = nil, priority: Priority? = nil) -> Self { 152 | self._update(attribute: .width, constant: constant, priority: priority) 153 | } 154 | 155 | /// height 156 | @discardableResult 157 | public func height(_ constant: CGFloat? = nil, priority: Priority? = nil) -> Self { 158 | self._update(attribute: .height, constant: constant, priority: priority) 159 | } 160 | 161 | // MARK: - Internal 162 | /// init 163 | init(item: Item, location: Debug.Location, labeled name: String?) { 164 | self._item = item 165 | self._storage = Storage.storage(for: item) 166 | self._location = location 167 | 168 | // set label 169 | if let nm = name { 170 | self._storage.labeledName = nm 171 | } 172 | } 173 | 174 | // MARK: - Private 175 | /// update constraint 176 | @discardableResult 177 | private func _update(attribute: Attribute, constant: CGFloat?, priority: Priority?) -> Self { 178 | // 0.0 check if there was a constraint already installed by driftwood 179 | guard let con = self._storage.activeConstraint(for: attribute) else { 180 | Debug.log(location: self._location, operation: .update(attribute), item: self._item, message: "No constraint.") 181 | return self 182 | } 183 | 184 | // 0.1 check priority 185 | if let priority = priority { 186 | // is valid 187 | guard Priority.isValidPriority(priority) else { 188 | Debug.log(location: self._location, operation: .update(attribute), item: self._item, message: "Invalid priority with value (\(priority.rawValue)).") 189 | return self 190 | } 191 | 192 | // is safe to change 193 | guard Priority.isSafeToChangePriority(from: con.priority, to: priority) else { 194 | Debug.log(location: self._location, operation: .update(attribute), item: self._item, message: "Changing priority from/to `required` is not supported.") 195 | return self 196 | } 197 | } 198 | 199 | // 1. update this constraint 200 | self._storage.update(con, constant: constant, priority: priority, location: self._location, operation: .update(attribute)) 201 | 202 | // 2. return self 203 | return self 204 | } 205 | 206 | /// a `View/LayoutGuide` 207 | private unowned(unsafe) let _item: Item 208 | 209 | /// a `Storage` 210 | private unowned(unsafe) let _storage: Storage 211 | 212 | /// a `Location` 213 | private let _location: Debug.Location 214 | } 215 | -------------------------------------------------------------------------------- /Sources/Driftwood/Debugging.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Driftwood 3 | // 4 | // Copyright (c) 2018-Present wlgemini . 5 | // 6 | // Permission is hereby granted, free of charge, to any person obtaining a copy 7 | // of this software and associated documentation files (the "Software"), to deal 8 | // in the Software without restriction, including without limitation the rights 9 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | // copies of the Software, and to permit persons to whom the Software is 11 | // furnished to do so, subject to the following conditions: 12 | // 13 | // The above copyright notice and this permission notice shall be included in all 14 | // copies or substantial portions of the Software. 15 | 16 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | // SOFTWARE. 23 | 24 | 25 | /// Debug 26 | enum Debug { 27 | 28 | /// log (execute only in debug mode) 29 | /// 30 | /// ": " 31 | /// 32 | static func log(location: Location, operation: Operation, item: Item, message: String) { 33 | Swift.assert({ 34 | var desc = "<" 35 | desc += Self.prefix(location: location, operation: operation) 36 | desc += ".(\(Self.description(for: item)))" 37 | desc += ">" 38 | desc += ": " 39 | desc += message 40 | print(desc) 41 | return true 42 | }()) 43 | } 44 | 45 | /// debug prefix 46 | /// 47 | /// "Driftwood.@ViewController#23.[make left]" 48 | /// "Driftwood.[make left]" 49 | /// 50 | static func prefix(location: Location?, operation: Operation) -> String { 51 | // Driftwood 52 | var pre = "Driftwood" 53 | 54 | // loction 55 | if let loc = location { 56 | pre += ".\(loc)" 57 | } 58 | 59 | // operation 60 | pre += ".[\(operation)]" 61 | 62 | return pre 63 | } 64 | 65 | /// description of Item 66 | /// 67 | /// "UIView`MyView`:0x00007fc636525111" 68 | /// "UIView:0x00007fc636525111" 69 | /// 70 | static func description(for item: Item) -> String { 71 | var desc = "\(Swift.type(of: item))" 72 | // using `Storage.anyStorage` to avoid unnecessary `Storage` object create. 73 | if let labeledName = Storage.anyStorage(for: item)?.labeledName { 74 | desc += "`\(labeledName)`" 75 | } 76 | desc += ":\(String(format: "%p", UInt(bitPattern: ObjectIdentifier(item))))" 77 | return desc 78 | } 79 | 80 | /// description of Attribute 81 | static func description(for attribute: Attribute) -> String { 82 | switch attribute { 83 | // HAttribute 84 | case .left: return "left" 85 | case .right: return "right" 86 | case .leading: return "leading" 87 | case .trailing: return "trailing" 88 | case .centerX: return "centerX" 89 | #if os(iOS) || os(tvOS) 90 | case .leftMargin: return "leftMargin" 91 | case .rightMargin: return "rightMargin" 92 | case .leadingMargin: return "leadingMargin" 93 | case .trailingMargin: return "trailingMargin" 94 | case .centerXWithinMargins: return "centerXWithinMargins" 95 | #endif 96 | 97 | // VAttribute 98 | case .top: return "top" 99 | case .bottom: return "bottom" 100 | case .centerY: return "centerY" 101 | case .lastBaseline: return "lastBaseline" 102 | case .firstBaseline: return "firstBaseline" 103 | #if os(iOS) || os(tvOS) 104 | case .topMargin: return "topMargin" 105 | case .bottomMargin: return "bottomMargin" 106 | case .centerYWithinMargins: return "centerYWithinMargins" 107 | #endif 108 | 109 | // SAttribute 110 | case .width: return "width" 111 | case .height: return "height" 112 | 113 | // notAnAttribute 114 | case .notAnAttribute: return "notAnAttribute" 115 | 116 | // default 117 | @unknown default: fatalError("New case need handled.") 118 | } 119 | } 120 | 121 | /// description of Relation 122 | static func description(for relation: Relation) -> String { 123 | switch relation { 124 | case .equal: return "==" 125 | case .greaterThanOrEqual: return ">=" 126 | case .lessThanOrEqual: return "<=" 127 | @unknown default: fatalError("New case need handled.") 128 | } 129 | } 130 | } 131 | 132 | 133 | extension Debug { 134 | 135 | /// Location 136 | struct Location: CustomStringConvertible { 137 | 138 | /// file 139 | let file: String 140 | 141 | /// line 142 | let line: UInt 143 | 144 | /// init 145 | init(_ file: String, _ line: UInt) { 146 | self.file = file 147 | self.line = line 148 | } 149 | 150 | /// description 151 | /// 152 | /// "@ViewController#23" 153 | /// 154 | var description: String { 155 | let fileName = self.file.split(separator: "/").last?.split(separator: ".").first ?? "" 156 | return "@\(String(fileName))#\(self.line)" 157 | } 158 | } 159 | 160 | 161 | /// Operation 162 | enum Operation: CustomStringConvertible { 163 | 164 | case make(Attribute) 165 | 166 | case update(Attribute) 167 | 168 | case remove(Attribute) 169 | 170 | /// description 171 | var description: String { 172 | switch self { 173 | case .make(let attribute): return "make \(Debug.description(for: attribute))" 174 | case .update(let attribute): return "update \(Debug.description(for: attribute))" 175 | case .remove(let attribute): return "remove \(Debug.description(for: attribute))" 176 | } 177 | } 178 | } 179 | } 180 | -------------------------------------------------------------------------------- /Sources/Driftwood/Driftable+.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Driftwood 3 | // 4 | // Copyright (c) 2018-Present wlgemini . 5 | // 6 | // Permission is hereby granted, free of charge, to any person obtaining a copy 7 | // of this software and associated documentation files (the "Software"), to deal 8 | // in the Software without restriction, including without limitation the rights 9 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | // copies of the Software, and to permit persons to whom the Software is 11 | // furnished to do so, subject to the following conditions: 12 | // 13 | // The above copyright notice and this permission notice shall be included in all 14 | // copies or substantial portions of the Software. 15 | 16 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | // SOFTWARE. 23 | 24 | 25 | /// View (Driftable) 26 | extension View: Driftable { 27 | 28 | public var dw: Wood<_Tuple2> { Wood(_Tuple2(first: self, second: self.superview)) } 29 | } 30 | 31 | 32 | /// LayoutGuide (Driftable) 33 | @available(iOS 9.0, macOS 10.11, *) 34 | extension LayoutGuide: Driftable { 35 | 36 | public var dw: Wood<_Tuple2> { Wood(_Tuple2(first: self, second: self.owningView)) } 37 | } 38 | 39 | 40 | /// Priority (Driftable) 41 | extension Priority: Driftable { 42 | 43 | public var dw: Wood { Wood(self) } 44 | } 45 | -------------------------------------------------------------------------------- /Sources/Driftwood/Driftable.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Driftwood 3 | // 4 | // Copyright (c) 2018-Present wlgemini . 5 | // 6 | // Permission is hereby granted, free of charge, to any person obtaining a copy 7 | // of this software and associated documentation files (the "Software"), to deal 8 | // in the Software without restriction, including without limitation the rights 9 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | // copies of the Software, and to permit persons to whom the Software is 11 | // furnished to do so, subject to the following conditions: 12 | // 13 | // The above copyright notice and this permission notice shall be included in all 14 | // copies or substantial portions of the Software. 15 | 16 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | // SOFTWARE. 23 | 24 | 25 | /// Protocol describing the `dw` extension points for Driftwood extended types. 26 | public protocol Driftable { 27 | 28 | /// Subject 29 | associatedtype Subject 30 | 31 | /// `dw` prefix 32 | var dw: Wood { get } 33 | } 34 | 35 | 36 | public extension Driftable { 37 | 38 | /// static `dw` prefix 39 | static var dw: StaticWood { StaticWood() } 40 | } 41 | -------------------------------------------------------------------------------- /Sources/Driftwood/Preferences.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Driftwood 3 | // 4 | // Copyright (c) 2018-Present wlgemini . 5 | // 6 | // Permission is hereby granted, free of charge, to any person obtaining a copy 7 | // of this software and associated documentation files (the "Software"), to deal 8 | // in the Software without restriction, including without limitation the rights 9 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | // copies of the Software, and to permit persons to whom the Software is 11 | // furnished to do so, subject to the following conditions: 12 | // 13 | // The above copyright notice and this permission notice shall be included in all 14 | // copies or substantial portions of the Software. 15 | 16 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | // SOFTWARE. 23 | 24 | 25 | import CoreGraphics 26 | 27 | 28 | /// Preferences 29 | public enum Preferences {} 30 | 31 | 32 | /// Preferences (Default settings for View) 33 | public extension Preferences { 34 | 35 | /// translatesAutoresizingMaskIntoConstraints for View 36 | static let translatesAutoresizingMaskIntoConstraints: Bool = false 37 | } 38 | 39 | 40 | /// Preferences (Default settings for Constraint) 41 | public extension Preferences { 42 | 43 | /// relation 44 | static let relation: Relation = .equal 45 | 46 | /// multiply 47 | static let multiply: CGFloat = 1.0 48 | 49 | /// priority 50 | static let priority: Priority = Priority.required 51 | } 52 | -------------------------------------------------------------------------------- /Sources/Driftwood/Priority+Safety.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Driftwood 3 | // 4 | // Copyright (c) 2018-Present wlgemini . 5 | // 6 | // Permission is hereby granted, free of charge, to any person obtaining a copy 7 | // of this software and associated documentation files (the "Software"), to deal 8 | // in the Software without restriction, including without limitation the rights 9 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | // copies of the Software, and to permit persons to whom the Software is 11 | // furnished to do so, subject to the following conditions: 12 | // 13 | // The above copyright notice and this permission notice shall be included in all 14 | // copies or substantial portions of the Software. 15 | 16 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | // SOFTWARE. 23 | 24 | 25 | /// Priority (Safety) 26 | extension Priority { 27 | 28 | /// Min optional priority 29 | static let minOptional: Self = Self(rawValue: 1) 30 | 31 | /// Max optional priority 32 | static let maxOptional: Self = Self(rawValue: Self.required.rawValue - 1) 33 | 34 | /// Check is valid priority 35 | /// 36 | /// Priorities must be greater than 0 and less than or equal to `.required`. 37 | static func isValidPriority(_ priority: Self) -> Bool { 38 | priority.rawValue >= Self.minOptional.rawValue && priority.rawValue <= Self.required.rawValue 39 | } 40 | 41 | /// Check is safe to change priority 42 | /// 43 | /// Constraint's priority may only be modified as part of initial set up or when optional. 44 | /// After a constraint has been added to a view, an exception will be thrown if the priority is changed from/to Priority.required. 45 | static func isSafeToChangePriority(from: Self, to: Self) -> Bool { 46 | if from.rawValue == to.rawValue { 47 | // same priority has no effect, so it's safe 48 | return true 49 | } else { 50 | // it's safe when `from` && `to` is optional 51 | return from.rawValue < Self.required.rawValue && to.rawValue < Self.required.rawValue 52 | } 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /Sources/Driftwood/Storage.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Driftwood 3 | // 4 | // Copyright (c) 2018-Present wlgemini . 5 | // 6 | // Permission is hereby granted, free of charge, to any person obtaining a copy 7 | // of this software and associated documentation files (the "Software"), to deal 8 | // in the Software without restriction, including without limitation the rights 9 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | // copies of the Software, and to permit persons to whom the Software is 11 | // furnished to do so, subject to the following conditions: 12 | // 13 | // The above copyright notice and this permission notice shall be included in all 14 | // copies or substantial portions of the Software. 15 | 16 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | // SOFTWARE. 23 | 24 | 25 | import ObjectiveC.runtime 26 | import CoreGraphics 27 | 28 | 29 | /// Storage 30 | final class Storage { 31 | 32 | // MARK: Instantiation for item 33 | /// Associated storage for item if any 34 | static func anyStorage(for item: Item) -> Storage? { 35 | objc_getAssociatedObject(item, &Self._associatedKey) as? Storage 36 | } 37 | 38 | /// Associated storage for item 39 | static func storage(for item: Item) -> Storage { 40 | if let s = Self.anyStorage(for: item) { 41 | return s 42 | } else { 43 | let s = Storage() 44 | objc_setAssociatedObject(item, &Self._associatedKey, s, .OBJC_ASSOCIATION_RETAIN_NONATOMIC) 45 | return s 46 | } 47 | } 48 | 49 | // MARK: Debug 50 | /// labeled name for current Item 51 | var labeledName: String? 52 | 53 | // MARK: Constraint activate & update & deactivate 54 | /// active constraint installed by driftwood 55 | func activeConstraint(for key: Attribute) -> Constraint? { 56 | self._activeConstraints[key] 57 | } 58 | 59 | /// activate a constraint 60 | func activate(_ con: Constraint, for key: Attribute, location: Debug.Location, operation: Debug.Operation) { 61 | // set debug info 62 | con.location = location 63 | con.operation = operation 64 | 65 | // activate constraint 66 | con.isActive = true 67 | 68 | // save constraint 69 | self._activeConstraints[key] = con 70 | } 71 | 72 | /// update an active constraint installed by driftwood 73 | func update(_ con: Constraint, constant: CGFloat?, priority: Priority?, location: Debug.Location, operation: Debug.Operation) { 74 | // set debug info 75 | con.location = location 76 | con.operation = operation 77 | 78 | // update constraint.constant 79 | if let constant = constant { 80 | con.constant = constant 81 | } 82 | 83 | // update constraint.priority 84 | if let priority = priority { 85 | con.priority = priority 86 | } 87 | } 88 | 89 | /// deactivate a constraint installed by driftwood 90 | @discardableResult 91 | func deactivate(for key: Attribute) -> Constraint? { 92 | // remove constraint 93 | let con = self._activeConstraints.removeValue(forKey: key) 94 | 95 | // deactivate constraint 96 | con?.isActive = false 97 | 98 | return con 99 | } 100 | 101 | /// deactivate all constraints installed by driftwood 102 | func deactivateAll() { 103 | // for each constraint 104 | self._activeConstraints.forEach { 105 | 106 | // deactivate constraint 107 | $1.isActive = false 108 | } 109 | 110 | // remove all constraint 111 | self._activeConstraints.removeAll() 112 | } 113 | 114 | /// get a constraint cached by driftwood 115 | func constraint(item: Item, attribute: Attribute, relation: Relation, toItem: Item?, toAttribute: Attribute, multiply: CGFloat, constant: CGFloat, priority: Priority) -> Constraint { 116 | // 0. generate a constraint key (key calculation not include item/constant/priority) 117 | let conKey = ConstraintKey(attribute: attribute, toItem: toItem, toAttribute: toAttribute, relation: relation, multiply: multiply) 118 | 119 | // 1. retrive a constraint from cache, and check is safe to change constraint's priority 120 | let con: Constraint 121 | if let c = self._cachedConstraints[conKey], Priority.isSafeToChangePriority(from: c.priority, to: priority) { 122 | // 1.1 cached and is safe to change constraint's priority 123 | con = c 124 | con.constant = constant 125 | con.priority = priority 126 | } else { 127 | // 1.2 no cache or is not safe to change constraint's priority, may replace cached constraint 128 | con = Constraint(item: item, attribute: attribute, relatedBy: relation, toItem: toItem, attribute: toAttribute, multiplier: multiply, constant: constant) 129 | con.priority = priority 130 | self._cachedConstraints[conKey] = con 131 | } 132 | 133 | // 2. return constraint 134 | return con 135 | } 136 | 137 | //=========================================== 138 | // Private 139 | //=========================================== 140 | // 141 | /// active constraints 142 | /// 143 | /// In most case, there will be 4 active constraints on current Item 144 | private var _activeConstraints = [Attribute: Constraint](minimumCapacity: 4) 145 | 146 | /// cached constraints (include active/deactive constraints) 147 | private var _cachedConstraints = [ConstraintKey: Constraint](minimumCapacity: 4) 148 | 149 | /// associated key 150 | private static var _associatedKey: Void? 151 | 152 | /// init 153 | private init() {} 154 | } 155 | -------------------------------------------------------------------------------- /Sources/Driftwood/Typealiases.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Driftwood 3 | // 4 | // Copyright (c) 2018-Present wlgemini . 5 | // 6 | // Permission is hereby granted, free of charge, to any person obtaining a copy 7 | // of this software and associated documentation files (the "Software"), to deal 8 | // in the Software without restriction, including without limitation the rights 9 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | // copies of the Software, and to permit persons to whom the Software is 11 | // furnished to do so, subject to the following conditions: 12 | // 13 | // The above copyright notice and this permission notice shall be included in all 14 | // copies or substantial portions of the Software. 15 | 16 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | // SOFTWARE. 23 | 24 | 25 | #if os(iOS) || os(tvOS) 26 | import UIKit 27 | #else 28 | import AppKit 29 | #endif 30 | 31 | 32 | #if os(iOS) || os(tvOS) 33 | /// View 34 | public typealias View = UIView 35 | 36 | 37 | /// LayoutGuide 38 | @available(iOS 9.0, *) 39 | public typealias LayoutGuide = UILayoutGuide 40 | 41 | 42 | /// LayoutConstraint 43 | typealias LayoutConstraint = NSLayoutConstraint 44 | 45 | 46 | /// Relation 47 | public typealias Relation = NSLayoutConstraint.Relation 48 | 49 | 50 | /// Priority 51 | public typealias Priority = UILayoutPriority 52 | 53 | 54 | /// Attribute 55 | typealias Attribute = NSLayoutConstraint.Attribute 56 | 57 | 58 | /// EdgeInsets 59 | public typealias EdgeInsets = UIEdgeInsets 60 | #else 61 | /// View 62 | public typealias View = NSView 63 | 64 | 65 | /// LayoutGuide 66 | @available(macOS 10.11, *) 67 | public typealias LayoutGuide = NSLayoutGuide 68 | 69 | 70 | /// LayoutConstraint 71 | typealias LayoutConstraint = NSLayoutConstraint 72 | 73 | 74 | /// Relation 75 | public typealias Relation = NSLayoutConstraint.Relation 76 | 77 | 78 | /// Priority 79 | public typealias Priority = NSLayoutConstraint.Priority 80 | 81 | 82 | /// Attribute 83 | typealias Attribute = NSLayoutConstraint.Attribute 84 | 85 | 86 | /// EdgeInsets 87 | public typealias EdgeInsets = NSEdgeInsets 88 | #endif 89 | 90 | 91 | /// Item 92 | public typealias Item = AnyObject 93 | -------------------------------------------------------------------------------- /Sources/Driftwood/Wood+Priority.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Driftwood 3 | // 4 | // Copyright (c) 2018-Present wlgemini . 5 | // 6 | // Permission is hereby granted, free of charge, to any person obtaining a copy 7 | // of this software and associated documentation files (the "Software"), to deal 8 | // in the Software without restriction, including without limitation the rights 9 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | // copies of the Software, and to permit persons to whom the Software is 11 | // furnished to do so, subject to the following conditions: 12 | // 13 | // The above copyright notice and this permission notice shall be included in all 14 | // copies or substantial portions of the Software. 15 | 16 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | // SOFTWARE. 23 | 24 | 25 | /// Wood (Priority) 26 | extension Wood where Subject == Priority { 27 | 28 | /// Get a lower priority (aka: `current - 1`), min to `1` 29 | @inlinable 30 | public var lower: Priority { self.lower(1) } 31 | 32 | /// Get a higher priority (aka: `current + 1`), max to `required - 1` 33 | @inlinable 34 | public var higher: Priority { self.higher(1) } 35 | 36 | /// Get a lower priority (aka: `current - value`), min to `1` 37 | public func lower(_ value: Float) -> Priority { 38 | let targetValue = self.subject.rawValue - abs(value) 39 | if targetValue > Priority.maxOptional.rawValue { 40 | return Priority.maxOptional 41 | } else if targetValue < Priority.minOptional.rawValue { 42 | return Priority.minOptional 43 | } else { 44 | return Priority(rawValue: targetValue) 45 | } 46 | } 47 | 48 | /// Get a higher priority (aka: `current + value`), max to `required - 1` 49 | public func higher(_ value: Float) -> Priority { 50 | let targetValue = self.subject.rawValue + abs(value) 51 | if targetValue > Priority.maxOptional.rawValue { 52 | return Priority.maxOptional 53 | } else if targetValue < Priority.minOptional.rawValue { 54 | return Priority.minOptional 55 | } else { 56 | return Priority(rawValue: targetValue) 57 | } 58 | } 59 | } 60 | 61 | 62 | /// StaticWood (Priority) 63 | extension StaticWood where Subject == Priority { 64 | 65 | /// Minimum optional priority 66 | public var minOptional: Priority { Priority.minOptional } 67 | 68 | /// Maximum optional priority 69 | public var maxOptional: Priority { Priority.maxOptional } 70 | } 71 | -------------------------------------------------------------------------------- /Sources/Driftwood/Wood+__Tuple2.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Driftwood 3 | // 4 | // Copyright (c) 2018-Present wlgemini . 5 | // 6 | // Permission is hereby granted, free of charge, to any person obtaining a copy 7 | // of this software and associated documentation files (the "Software"), to deal 8 | // in the Software without restriction, including without limitation the rights 9 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | // copies of the Software, and to permit persons to whom the Software is 11 | // furnished to do so, subject to the following conditions: 12 | // 13 | // The above copyright notice and this permission notice shall be included in all 14 | // copies or substantial portions of the Software. 15 | 16 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | // SOFTWARE. 23 | 24 | 25 | /// Wood (Make, Update, Remove constraint) 26 | public extension Wood where Subject: __Tuple2, Subject.Second: View { 27 | 28 | /// make 29 | func make(labeled name: String? = nil, file: String = #fileID, line: UInt = #line) -> ConstraintMaker { 30 | ConstraintMaker(item: self.subject.first, superview: self.subject.second, location: Debug.Location(file, line), labeled: name) 31 | } 32 | 33 | /// update 34 | func update(labeled name: String? = nil, file: String = #fileID, line: UInt = #line) -> ConstraintUpdater { 35 | ConstraintUpdater(item: self.subject.first, location: Debug.Location(file, line), labeled: name) 36 | } 37 | 38 | /// remove 39 | func remove(labeled name: String? = nil, file: String = #fileID, line: UInt = #line) -> ConstraintRemover { 40 | ConstraintRemover(item: self.subject.first, location: Debug.Location(file, line), labeled: name) 41 | } 42 | 43 | /// remove all 44 | func removeAll() { 45 | Storage.anyStorage(for: self.subject.first)?.deactivateAll() 46 | } 47 | 48 | /// remake 49 | func remake(labeled name: String? = nil, file: String = #fileID, line: UInt = #line) -> ConstraintMaker { 50 | self.removeAll() 51 | return ConstraintMaker(item: self.subject.first, superview: self.subject.second, location: Debug.Location(file, line), labeled: name) 52 | } 53 | } 54 | 55 | 56 | /// Wood (Make, Update, Remove constraint without argument `labeled:`) 57 | public extension Wood where Subject: __Tuple2, Subject.Second: View { 58 | 59 | /// make 60 | @inlinable 61 | func make(file: String = #fileID, line: UInt = #line) -> ConstraintMaker { 62 | self.make(labeled: nil, file: file, line: line) 63 | } 64 | 65 | /// update 66 | @inlinable 67 | func update(file: String = #fileID, line: UInt = #line) -> ConstraintUpdater { 68 | self.update(labeled: nil, file: file, line: line) 69 | } 70 | 71 | /// remove 72 | @inlinable 73 | func remove(file: String = #fileID, line: UInt = #line) -> ConstraintRemover { 74 | self.remove(labeled: nil, file: file, line: line) 75 | } 76 | 77 | /// remake 78 | @inlinable 79 | func remake(file: String = #fileID, line: UInt = #line) -> ConstraintMaker { 80 | self.remake(labeled: nil, file: file, line: line) 81 | } 82 | } 83 | 84 | 85 | /// Wood (Attribute) 86 | public extension Wood where Subject: __Tuple2, Subject.Second: View { 87 | 88 | // MARK: HAttribute 89 | /// left 90 | @inlinable 91 | var left: HAttribute { .left(self.subject.first) } 92 | 93 | /// right 94 | @inlinable 95 | var right: HAttribute { .right(self.subject.first) } 96 | 97 | /// leading 98 | @inlinable 99 | var leading: HAttribute { .leading(self.subject.first) } 100 | 101 | /// trailing 102 | @inlinable 103 | var trailing: HAttribute { .trailing(self.subject.first) } 104 | 105 | /// centerX 106 | @inlinable 107 | var centerX: HAttribute { .centerX(self.subject.first) } 108 | 109 | #if os(iOS) || os(tvOS) 110 | /// leftMargin 111 | @inlinable 112 | var leftMargin: HAttribute { .leftMargin(self.subject.first) } 113 | 114 | /// rightMargin 115 | @inlinable 116 | var rightMargin: HAttribute { .rightMargin(self.subject.first) } 117 | 118 | /// leadingMargin 119 | @inlinable 120 | var leadingMargin: HAttribute { .leadingMargin(self.subject.first) } 121 | 122 | /// trailingMargin 123 | @inlinable 124 | var trailingMargin: HAttribute { .trailingMargin(self.subject.first) } 125 | 126 | /// centerXWithinMargins 127 | @inlinable 128 | var centerXWithinMargins: HAttribute { .centerXWithinMargins(self.subject.first) } 129 | #endif 130 | 131 | // MARK: VAttribute 132 | /// top 133 | @inlinable 134 | var top: VAttribute { .top(self.subject.first) } 135 | 136 | /// bottom 137 | @inlinable 138 | var bottom: VAttribute { .bottom(self.subject.first) } 139 | 140 | /// centerY 141 | @inlinable 142 | var centerY: VAttribute { .centerY(self.subject.first) } 143 | 144 | /// lastBaseline 145 | @inlinable 146 | var lastBaseline: VAttribute { .lastBaseline(self.subject.first) } 147 | 148 | /// firstBaseline 149 | @inlinable 150 | var firstBaseline: VAttribute { .firstBaseline(self.subject.first) } 151 | 152 | #if os(iOS) || os(tvOS) 153 | /// topMargin 154 | @inlinable 155 | var topMargin: VAttribute { .topMargin(self.subject.first) } 156 | 157 | /// bottomMargin 158 | @inlinable 159 | var bottomMargin: VAttribute { .bottomMargin(self.subject.first) } 160 | 161 | /// centerYWithinMargins 162 | @inlinable 163 | var centerYWithinMargins: VAttribute { .centerYWithinMargins(self.subject.first) } 164 | #endif 165 | 166 | // MARK: SAttribute 167 | /// width 168 | @inlinable 169 | var width: SAttribute { .width(self.subject.first) } 170 | 171 | /// height 172 | @inlinable 173 | var height: SAttribute { .height(self.subject.first) } 174 | } 175 | 176 | 177 | /// Wood (ContentHugging/ContentCompressionResistance priority) 178 | public extension Wood where Subject: __Tuple2, Subject.First: View, Subject.Second: View { 179 | 180 | // MARK: Getter 181 | @inlinable 182 | var contentHuggingHorizontalPriority: Priority { 183 | self.subject.first.contentHuggingPriority(for: .horizontal) 184 | } 185 | 186 | @inlinable 187 | var contentHuggingVerticalPriority: Priority { 188 | self.subject.first.contentHuggingPriority(for: .vertical) 189 | } 190 | 191 | @inlinable 192 | var contentCompressionResistanceHorizontalPriority: Priority { 193 | self.subject.first.contentCompressionResistancePriority(for: .horizontal) 194 | } 195 | 196 | @inlinable 197 | var contentCompressionResistanceVerticalPriority: Priority { 198 | self.subject.first.contentCompressionResistancePriority(for: .vertical) 199 | } 200 | 201 | // MARK: Setter 202 | @inlinable 203 | @discardableResult 204 | func setContentHuggingHorizontalPriority(_ priority: Priority) -> Self { 205 | self.subject.first.setContentHuggingPriority(priority, for: .horizontal) 206 | return self 207 | } 208 | 209 | @inlinable 210 | @discardableResult 211 | func setContentHuggingVerticalPriority(_ priority: Priority) -> Self { 212 | self.subject.first.setContentHuggingPriority(priority, for: .vertical) 213 | return self 214 | } 215 | 216 | @inlinable 217 | @discardableResult 218 | func setContentCompressionResistanceHorizontalPriority(_ priority: Priority) -> Self { 219 | self.subject.first.setContentCompressionResistancePriority(priority, for: .horizontal) 220 | return self 221 | } 222 | 223 | @inlinable 224 | @discardableResult 225 | func setContentCompressionResistanceVerticalPriority(_ priority: Priority) -> Self { 226 | self.subject.first.setContentCompressionResistancePriority(priority, for: .vertical) 227 | return self 228 | } 229 | } 230 | -------------------------------------------------------------------------------- /Sources/Driftwood/Wood.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Driftwood 3 | // 4 | // Copyright (c) 2018-Present wlgemini . 5 | // 6 | // Permission is hereby granted, free of charge, to any person obtaining a copy 7 | // of this software and associated documentation files (the "Software"), to deal 8 | // in the Software without restriction, including without limitation the rights 9 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | // copies of the Software, and to permit persons to whom the Software is 11 | // furnished to do so, subject to the following conditions: 12 | // 13 | // The above copyright notice and this permission notice shall be included in all 14 | // copies or substantial portions of the Software. 15 | 16 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | // SOFTWARE. 23 | 24 | 25 | /// Wood 26 | /// 27 | /// For `dw` prefix wrapper 28 | public struct Wood { 29 | 30 | /// subject 31 | public private(set) var subject: Subject 32 | 33 | // MARK: - Internal 34 | /// init 35 | init(_ subject: Subject) { 36 | self.subject = subject 37 | } 38 | } 39 | 40 | 41 | /// StaticWood 42 | /// 43 | /// For `dw` prefix wrapper 44 | public struct StaticWood { 45 | 46 | // MARK: - Internal 47 | /// init 48 | init() {} 49 | } 50 | -------------------------------------------------------------------------------- /Sources/Driftwood/__Tuple2.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Driftwood 3 | // 4 | // Copyright (c) 2018-Present wlgemini . 5 | // 6 | // Permission is hereby granted, free of charge, to any person obtaining a copy 7 | // of this software and associated documentation files (the "Software"), to deal 8 | // in the Software without restriction, including without limitation the rights 9 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | // copies of the Software, and to permit persons to whom the Software is 11 | // furnished to do so, subject to the following conditions: 12 | // 13 | // The above copyright notice and this permission notice shall be included in all 14 | // copies or substantial portions of the Software. 15 | 16 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | // SOFTWARE. 23 | 24 | 25 | /// __Tuple2 26 | public protocol __Tuple2 { 27 | 28 | /// First item type 29 | associatedtype First: Item 30 | 31 | /// Second item type 32 | associatedtype Second: Item 33 | 34 | /// first 35 | var first: First { get } 36 | 37 | /// second 38 | var second: Second? { get } 39 | } 40 | 41 | 42 | /// _Tuple2 43 | public struct _Tuple2: __Tuple2 { 44 | 45 | /// first 46 | public unowned(unsafe) let first: First 47 | 48 | /// second 49 | public unowned(unsafe) let second: Second? 50 | 51 | // MARK: Internal 52 | /// init 53 | init(first: First, second: Second?) { 54 | self.first = first 55 | self.second = second 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /driftwood.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wlgemini/Driftwood/139fbe8ad649840406fdba9f3af6200e903ff816/driftwood.png --------------------------------------------------------------------------------