├── BezierCurveExample ├── Cartfile ├── Podfile ├── BezierCurveExample │ ├── Info.plist │ ├── Base.lproj │ │ ├── LaunchScreen.storyboard │ │ └── Main.storyboard │ ├── Assets.xcassets │ │ └── AppIcon.appiconset │ │ │ └── Contents.json │ ├── AppDelegate.swift │ └── ViewController.swift └── BezierCurveExample.xcodeproj │ └── project.pbxproj ├── .travis.yml ├── .gitignore ├── BezierCurveView ├── Info.plist ├── BezierHandleProtocol.swift ├── BezierHandleView.swift └── BezierCurveView.swift ├── LICENSE ├── BezierCurveView.podspec ├── README.md └── BezierCurveView.xcodeproj └── project.pbxproj /BezierCurveExample/Cartfile: -------------------------------------------------------------------------------- 1 | github "SwiftArchitect/BezierCurveView" 2 | 3 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: objective-c 2 | osx_image: xcode9.3 3 | 4 | script: xcodebuild clean && xcodebuild build -project BezierCurveView.xcodeproj -scheme BezierCurveView CODE_SIGNING_REQUIRED=NO 5 | -------------------------------------------------------------------------------- /BezierCurveExample/Podfile: -------------------------------------------------------------------------------- 1 | platform :ios, '11.0' 2 | 3 | target 'BezierCurveExample' do 4 | use_frameworks! 5 | 6 | #pod 'BezierCurveView', :path => '../.' 7 | pod 'BezierCurveView' 8 | 9 | end 10 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Mac OS X Finder 2 | .DS_Store 3 | 4 | # Sparkle distribution Private Key (Don’t check me in!) 5 | dsa_priv.pem 6 | 7 | # XCode (and ancestors) per-user config (very noisy, and not relevant) 8 | *.mode1 9 | *.mode1v3 10 | *.mode2v3 11 | *.perspective 12 | *.perspectivev3 13 | *.pbxuser 14 | 15 | # Xcode 4 16 | xcuserdata/ 17 | *.xcworkspace/ 18 | DerivedData/ 19 | 20 | # Generated files 21 | VersionX-revision.h 22 | 23 | # build products 24 | build/ 25 | *.[oa] 26 | 27 | # Other source repository archive directories (protects when importing) 28 | .hg 29 | .svn 30 | CVS 31 | 32 | # automatic backup files 33 | *~.nib 34 | *.swp 35 | *~ 36 | *(Autosaved).rtfd/ 37 | Backup[ ]of[ ]*.pages/ 38 | Backup[ ]of[ ]*.key/ 39 | Backup[ ]of[ ]*.numbers/ 40 | 41 | # Cocoapods 42 | Podfile.lock 43 | Pods/ 44 | 45 | # Carthage 46 | Cartfile.resolved 47 | Carthage/ 48 | 49 | -------------------------------------------------------------------------------- /BezierCurveView/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 | FMWK 17 | CFBundleShortVersionString 18 | 4.0.1 19 | CFBundleVersion 20 | $(CURRENT_PROJECT_VERSION) 21 | NSPrincipalClass 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright © 2017, 2018 Xavier Schott 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | -------------------------------------------------------------------------------- /BezierCurveView/BezierHandleProtocol.swift: -------------------------------------------------------------------------------- 1 | // @file: BezierHandleProtocol.swift 2 | // @project: BezierCurveView 3 | // 4 | // Copyright © 2017, 2018 Xavier Schott 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 14 | // all 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 22 | // THE SOFTWARE. 23 | 24 | import UIKit 25 | 26 | protocol BezierHandleProtocol { 27 | var controlPoint: CGPoint { get } 28 | var anchor: CGPoint { get } 29 | var terminalShape: BezierCurveView.Shape { get } 30 | var terminalSize: CGFloat { get } 31 | } 32 | -------------------------------------------------------------------------------- /BezierCurveExample/BezierCurveExample/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | APPL 17 | CFBundleShortVersionString 18 | 4.0.1 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 | -------------------------------------------------------------------------------- /BezierCurveView.podspec: -------------------------------------------------------------------------------- 1 | Pod::Spec.new do |spec| 2 | 3 | # ――― Spec Metadata ―――――――――――――――――――――――――――――――――――――――――――――――――――――――――― # 4 | spec.name = "BezierCurveView" 5 | spec.version = "4.0.1" 6 | spec.summary = "Swift Bezier Curve View" 7 | spec.description = <<-DESC 8 | Draw Bezier Arrows in a UIView, using familiar control handles. 9 | These arrows will adjust neatly as the view gets resized, making 10 | the best of interface orientation and device sizes. 11 | DESC 12 | spec.homepage = "https://github.com/SwiftArchitect/BezierCurveView" 13 | spec.screenshots = "https://cloud.githubusercontent.com/assets/4073988/10705183/0ecbd50e-7991-11e5-8693-10b54587c837.png" 14 | 15 | # ――― Spec License ――――――――――――――――――――――――――――――――――――――――――――――――――――――――――― # 16 | spec.license = { :type => "MIT", :file => "LICENSE" } 17 | 18 | # ――― Author Metadata ――――――――――――――――――――――――――――――――――――――――――――――――――――――――― # 19 | spec.author = { "Xavier Schott" => "http://swiftarchitect.com/swiftarchitect/" } 20 | 21 | # ――― Platform Specifics ――――――――――――――――――――――――――――――――――――――――――――――――――――――― # 22 | spec.platform = :ios 23 | spec.ios.deployment_target = '11.0' 24 | spec.requires_arc = true 25 | spec.swift_version = '4.1.2' 26 | 27 | # ――― Source Location ―――――――――――――――――――――――――――――――――――――――――――――――――――――――――― # 28 | spec.source = { :git => "https://github.com/SwiftArchitect/BezierCurveView.git", :tag => "v4.0.1" } 29 | spec.exclude_files = "BezierCurveExample/*" 30 | spec.source_files = "BezierCurveView/*.{swift}" 31 | 32 | # ――― Project Linking ―――――――――――――――――――――――――――――――――――――――――――――――――――――――――― # 33 | spec.framework = "UIKit" 34 | 35 | end 36 | -------------------------------------------------------------------------------- /BezierCurveExample/BezierCurveExample/Base.lproj/LaunchScreen.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /BezierCurveExample/BezierCurveExample/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 | "info" : { 90 | "version" : 1, 91 | "author" : "xcode" 92 | } 93 | } -------------------------------------------------------------------------------- /BezierCurveView/BezierHandleView.swift: -------------------------------------------------------------------------------- 1 | // @file: BezierHandleView.swift 2 | // @project: BezierCurveView 3 | // 4 | // Copyright © 2017, 2018 Xavier Schott 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 14 | // all 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 22 | // THE SOFTWARE. 23 | 24 | import UIKit 25 | 26 | @IBDesignable 27 | class BezierHandleView: UIView { 28 | 29 | @IBInspectable public var dx:CGFloat = 0 30 | @IBInspectable public var dy:CGFloat = -10 31 | @IBInspectable public var shape:NSInteger = BezierCurveView.Shape.none.rawValue 32 | @IBInspectable public var size:CGFloat = 15 33 | 34 | override func draw(_ rect: CGRect) { 35 | // Invisible 36 | } 37 | } 38 | 39 | extension BezierHandleView: BezierHandleProtocol { 40 | 41 | public var controlPoint: CGPoint { 42 | get { 43 | return CGPoint(x: dx, y: dy) 44 | } 45 | set { 46 | dx = newValue.x 47 | dy = newValue.y 48 | } 49 | } 50 | 51 | public var anchor:CGPoint { 52 | get { 53 | return center 54 | } 55 | set { 56 | center = newValue 57 | } 58 | } 59 | 60 | public var terminalShape: BezierCurveView.Shape { 61 | get { 62 | return BezierCurveView.Shape(rawValue: shape) ?? BezierCurveView.Shape.none 63 | } 64 | set { 65 | self.shape = newValue.rawValue 66 | } 67 | } 68 | 69 | public var terminalSize: CGFloat { 70 | get { 71 | return size 72 | } 73 | set { 74 | size = newValue 75 | } 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /BezierCurveExample/BezierCurveExample/AppDelegate.swift: -------------------------------------------------------------------------------- 1 | // @file: AppDelegate.swift 2 | // @project: BezierCurveExample 3 | // 4 | // Copyright © 2017, 2018 Xavier Schott 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 14 | // all 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 22 | // THE SOFTWARE. 23 | 24 | import UIKit 25 | 26 | @UIApplicationMain 27 | class AppDelegate: UIResponder, UIApplicationDelegate { 28 | 29 | var window: UIWindow? 30 | 31 | 32 | func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool { 33 | // Override point for customization after application launch. 34 | return true 35 | } 36 | 37 | func applicationWillResignActive(_ application: UIApplication) { 38 | // 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. 39 | // Use this method to pause ongoing tasks, disable timers, and invalidate graphics rendering callbacks. Games should use this method to pause the game. 40 | } 41 | 42 | func applicationDidEnterBackground(_ application: UIApplication) { 43 | // 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. 44 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. 45 | } 46 | 47 | func applicationWillEnterForeground(_ application: UIApplication) { 48 | // 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. 49 | } 50 | 51 | func applicationDidBecomeActive(_ application: UIApplication) { 52 | // 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. 53 | } 54 | 55 | func applicationWillTerminate(_ application: UIApplication) { 56 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. 57 | } 58 | } 59 | 60 | -------------------------------------------------------------------------------- /BezierCurveExample/BezierCurveExample/ViewController.swift: -------------------------------------------------------------------------------- 1 | // @file: ViewController.swift 2 | // @project: BezierCurveExample 3 | // 4 | // Copyright © 2017, 2018 Xavier Schott 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 14 | // all 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 22 | // THE SOFTWARE. 23 | 24 | import UIKit 25 | 26 | class ViewController: UIViewController { 27 | 28 | @IBOutlet weak var verticalConstraint: NSLayoutConstraint! 29 | @IBOutlet weak var horizontalConstraint: NSLayoutConstraint! 30 | var saveConstants = CGSize.zero 31 | 32 | @IBAction func doPanAction(_ sender: UIPanGestureRecognizer) { 33 | switch sender.state { 34 | case .possible: 35 | break 36 | 37 | case .began: 38 | saveConstants = CGSize(width: horizontalConstraint.constant, 39 | height: verticalConstraint.constant) 40 | case .changed: 41 | let translation = sender.translation(in: view) 42 | horizontalConstraint.constant = saveConstants.width + translation.x 43 | verticalConstraint.constant = saveConstants.height + translation.y 44 | view.layoutIfNeeded() 45 | 46 | case .ended: 47 | fallthrough 48 | // UIView.animate(withDuration: 0.7, 49 | // delay: 0, 50 | // usingSpringWithDamping: 0.5, 51 | // initialSpringVelocity: 0, 52 | // options: .curveLinear, 53 | // animations: { 54 | // self.horizontalConstraint.constant = self.saveConstants.width 55 | // self.verticalConstraint.constant = self.saveConstants.height 56 | // self.view.layoutIfNeeded()}, 57 | // completion: nil) 58 | 59 | case .cancelled: 60 | fallthrough 61 | 62 | case .failed: 63 | self.horizontalConstraint.constant = self.saveConstants.width 64 | self.verticalConstraint.constant = self.saveConstants.height 65 | self.view.layoutIfNeeded() 66 | } 67 | } 68 | 69 | @IBAction func doHintAction(_ sender: Any) { 70 | let alert = UIAlertController(title: nil, 71 | message: "Touch and drag anywhere to animate", 72 | preferredStyle: .actionSheet) 73 | alert.addAction(UIAlertAction(title: "OK", style: .default)) 74 | present(alert, animated: true, completion: nil) 75 | } 76 | } 77 | 78 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Swift Bezier Curve View 2 | 3 | [![Build Status](https://travis-ci.org/SwiftArchitect/BezierCurveView.svg?branch=master)](https://travis-ci.org/SwiftArchitect/BezierCurveView) 4 | [![CocoaPods](https://img.shields.io/cocoapods/v/BezierCurveView.svg)](https://cocoapods.org/pods/BezierCurveView) 5 | [![Carthage compatible](https://img.shields.io/badge/Carthage-compatible-4BC51D.svg)](https://github.com/Carthage/Carthage) 6 | ![MIT License](https://img.shields.io/cocoapods/l/BezierCurveView.svg) 7 | 8 | Bezier curves are very handy to point to objects in your interface, for onboarding and help screens: 9 | 10 | ![camerahint](https://cloud.githubusercontent.com/assets/4073988/23232001/a1028ede-f8fe-11e6-85c9-e48058e45e35.png) 11 | 12 | Create and edit arrows to light up your interface, with visual preview in Xcode **Storyboard** and **Interface Builder**. 13 | 14 | ## Technical Discussion 15 | 16 | In **Interface Builder**, position a `BezierCurveView` and drop two `BezierCurveHandle` inside it. 17 | 1. `BezierCurveView` represents the drawing space. It can be as large as the `UIWindow` to prevent curve clipping. 18 | 2. `BezierCurveHandle` represents the two handles required by a [Cubic Bezier Curve](http://learn.scannerlicker.net/2014/04/16/bezier-curves-and-type-design-a-tutorial/). It adopts the `BezierHandleProtocol`, which provides control point information. 19 | 20 | The combination `BezierCurveView` + 2 `BezierCurveHandle` yields live preview in **Interface Builder**, with unprecedented flexibility: 21 | ![cameraib](https://cloud.githubusercontent.com/assets/4073988/23231917/58469bfe-f8fe-11e6-89f8-c5a4741a9534.png). 22 | Because a `BezierCurveHandle` is itself a `UIView`, it can be controlled by **AutoLayout** constraints, and thus adapt automatically to changes in sizes and orientations, with exactly **0 lines of code**. And since these handles are themselves extensions to the `BezierHandleProtocol`, you can tailor any of your `UIView` subclasses to control handles as well. 23 | 24 | #### Notes 25 | 1. _Make sure that a `BezierCurveView` contains exactly two subviews adopting `BezierHandleProtocol` for any drawing to take place_ 26 | 2. _In most situations, `BezierCurveView` and `BezierCurveHandle` background color should be clear_ 27 | 3. `BezierCurveView` will be refreshed any time its `frame` is updated, providing dynamic animations: 28 | ![bezierelasticity](https://cloud.githubusercontent.com/assets/4073988/23234535/3973f36c-f907-11e6-83b5-b02b9d5e13b4.gif) 29 | ([replay](https://cloud.githubusercontent.com/assets/4073988/23234535/3973f36c-f907-11e6-83b5-b02b9d5e13b4.gif)) 30 | 31 | # Bezier Curve View Properties 32 | | IBInspectable | What it does | 33 | |:-------|:-----------| 34 | | `lineWidth` | bezier curve thickness ; default is 1.5 | 35 | | `tintColor` | color of the curve ; defaults to black if absent | 36 | 37 | # Bezier Handle View Properties 38 | | IBInspectable | What it does | 39 | |:-------|:-----------| 40 | | `dx` | horizontal component of the control point ; default is 0 | 41 | | `dy` | vertical component of the control point ; default is -10.0 (control point is 10.0 pixels below the anchor | 42 | | `shape` | one of `none`, `arrowHead`, `circle` or `disc`, default is `none` | 43 | | `size` | dimensions of the `shape`: a shaft **length** for the arrow, a **radius** for circles and discs (†) ; default is 15.0 44 | 45 | 46 | (†) _The bezier curve end point is **adjusted** to start from the end of the shape_ 47 | 48 | ## Installation 49 | 50 | Use Cocoapods or include the source file directly. Cocoapods preferred. 51 | 52 | **API Compatibility**: version 4.x introduces `BezierHandleProtocol`, `BezierHandleView` and `BezierCurveView`, deprecating 3.x `BezierCurveArrowView`. 53 | ## Demo 54 | 55 | Run `pod install` in the `BezierCurveExample` directory, open `BezierCurveExample.xcworkspace` and run. 56 | ![beziercurveviewstoryboard](https://cloud.githubusercontent.com/assets/4073988/10705183/0ecbd50e-7991-11e5-8693-10b54587c837.png) 57 | 58 | ## Getting Help 59 | 60 | Search for **BezierCurveView** answers on [Stack Overflow](http://stackoverflow.com/), or ask questions to be adressed by the community. You can also [contact the author](http://swiftarchitect.com/contact/). 61 | 62 | -------------------------------------------------------------------------------- /BezierCurveView/BezierCurveView.swift: -------------------------------------------------------------------------------- 1 | // @file: BezierCurveView.swift 2 | // @project: BezierCurveView 3 | // 4 | // Copyright © 2017, 2018 Xavier Schott 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 14 | // all 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 22 | // THE SOFTWARE. 23 | 24 | import UIKit 25 | 26 | @IBDesignable 27 | public class BezierCurveView: UIView { 28 | 29 | public enum Shape:NSInteger { 30 | case none = 0 31 | case arrowHead 32 | case circle 33 | case disc 34 | } 35 | 36 | @IBInspectable public var lineWidth:CGFloat = 1.5 37 | 38 | // MARK: Calculated properties 39 | 40 | var curveColor:UIColor { 41 | get { 42 | return tintColor ?? UIColor.black 43 | } 44 | } 45 | 46 | var handleColor: UIColor { 47 | get{ 48 | return UIColor.red 49 | } 50 | } 51 | 52 | // MARK: BezierCurveView 53 | 54 | override init(frame: CGRect) { 55 | super.init(frame: frame) 56 | contentMode = .redraw 57 | } 58 | 59 | public required init?(coder aDecoder: NSCoder) { 60 | super.init(coder: aDecoder) 61 | contentMode = .redraw 62 | } 63 | 64 | public override func draw(_ rect: CGRect) { 65 | if let context = UIGraphicsGetCurrentContext() { 66 | var handles:[BezierHandleProtocol] = [] 67 | for view in subviews { 68 | if let bezierCurveHandleView = view as? BezierHandleProtocol { 69 | handles.append(bezierCurveHandleView) 70 | } 71 | } 72 | 73 | if 2 == handles.count, 74 | let handle1 = handles.first, 75 | let handle2 = handles.last { 76 | 77 | // controls are expressed in relative terms against their anchors 78 | let cp1 = CGPoint(x: handle1.anchor.x + handle1.controlPoint.x, 79 | y: handle1.anchor.y + handle1.controlPoint.y) 80 | let cp2 = CGPoint(x: handle2.anchor.x + handle2.controlPoint.x, 81 | y: handle2.anchor.y + handle2.controlPoint.y) 82 | 83 | // Terminal shapes 84 | let anchor1 = drawShape(shape: handle1.terminalShape, 85 | size: handle1.terminalSize, 86 | o: handle1.anchor, 87 | m: cp1, 88 | inContext: context) 89 | let anchor2 = drawShape(shape: handle2.terminalShape, 90 | size: handle2.terminalSize, 91 | o: handle2.anchor, 92 | m: cp2, 93 | inContext: context) 94 | 95 | // Curve 96 | context.setStrokeColor(curveColor.cgColor) 97 | context.setLineWidth(lineWidth) 98 | 99 | context.beginPath() 100 | context.move(to: anchor1) 101 | context.addCurve(to: anchor2, 102 | control1: CGPoint(x: anchor1.x + handle1.controlPoint.x, 103 | y: anchor1.y + handle1.controlPoint.y), 104 | control2: CGPoint(x: anchor2.x + handle2.controlPoint.x, 105 | y: anchor2.y + handle2.controlPoint.y)) // Cubic curve 106 | context.strokePath() 107 | 108 | // Handles and control points 109 | drawHandle(handle: handle1, inContext: context) 110 | drawHandle(handle: handle2, inContext: context) 111 | } 112 | } 113 | } 114 | 115 | func drawHandle(handle:BezierHandleProtocol, inContext context:CGContext) { 116 | #if TARGET_INTERFACE_BUILDER 117 | // Control Points 118 | let cpRadius:CGFloat = 2 119 | 120 | let cp = CGPoint(x: handle.anchor.x + handle.controlPoint.x, 121 | y: handle.anchor.y + handle.controlPoint.y) 122 | 123 | context.beginPath() 124 | context.move(to: handle.anchor) 125 | context.addLine(to: cp) 126 | context.setStrokeColor(handleColor.cgColor) 127 | context.setLineWidth(1) 128 | context.strokePath() 129 | 130 | context.setFillColor(handleColor.cgColor) 131 | context.fillEllipse(in: CGRect(x: cp.x-cpRadius, 132 | y: cp.y-cpRadius, 133 | width: cpRadius+cpRadius, 134 | height: cpRadius+cpRadius)) 135 | #endif // TARGET_INTERFACE_BUILDER 136 | } 137 | 138 | // Return the location of the new anchor point for the curve 139 | func drawShape(shape:BezierCurveView.Shape, 140 | size:CGFloat, 141 | o:CGPoint, 142 | m:CGPoint, 143 | inContext context:CGContext) -> CGPoint { 144 | switch shape { 145 | 146 | case .arrowHead: 147 | // Connect the arrowhead to the shaft 148 | let θ = radAngle(o:o, m:m) 149 | let π = CGFloat.pi 150 | let origin = polarToCartesian(o: o, r: -size, θ: θ + π) 151 | let shaft = polarToCartesian(o: origin, r: size/2, θ: θ + π) 152 | context.move(to: origin) 153 | context.addLine(to: shaft) 154 | 155 | context.setStrokeColor(curveColor.cgColor) 156 | context.setLineWidth(lineWidth) 157 | context.strokePath() 158 | 159 | // Draw arrowhead point and ears (retraction) 160 | let headPath = CGMutablePath() 161 | headPath.move(to: o) 162 | 163 | let ear1 = polarToCartesian(o: o, r: size, θ: θ + 0.3) 164 | headPath.addLine(to: ear1) 165 | 166 | let neck = polarToCartesian(o: origin, r: size/4, θ: θ + π) 167 | headPath.addLine(to: neck) 168 | 169 | let ear2 = polarToCartesian(o: o, r: size, θ: θ - 0.3) 170 | headPath.addLine( to: ear2) 171 | 172 | headPath.closeSubpath() 173 | context.setFillColor(curveColor.cgColor) 174 | context.addPath(headPath) 175 | context.fillPath() 176 | 177 | return origin 178 | 179 | case .circle: 180 | fallthrough 181 | case .disc: 182 | let θ = radAngle(o:o, m:m) 183 | let π = CGFloat.pi 184 | let origin = polarToCartesian(o: o, r: -size, θ: θ + π) 185 | context.addEllipse(in: CGRect(x: o.x - size, 186 | y: o.y - size, 187 | width: size + size, 188 | height: size + size)) 189 | if .circle == shape { 190 | context.setStrokeColor(curveColor.cgColor) 191 | context.setLineWidth(lineWidth) 192 | context.strokePath() 193 | } else { // .disc 194 | context.setFillColor(curveColor.cgColor) 195 | context.fillPath() 196 | } 197 | return origin 198 | 199 | case .none: 200 | return o 201 | } 202 | } 203 | 204 | func polarToCartesian(o:CGPoint, r:CGFloat, θ:CGFloat) -> CGPoint { 205 | let m = CGPoint(x: r * CGFloat(cos(θ)), 206 | y: r * CGFloat(sin(θ))) 207 | return CGPoint(x: o.x + m.x, 208 | y: o.y + m.y) 209 | } 210 | 211 | func radAngle(o:CGPoint, m:CGPoint) -> CGFloat { 212 | let vector = CGVector(dx: m.x - o.x, 213 | dy: m.y - o.y) 214 | return atan2(vector.dy, vector.dx) // in radians 215 | } 216 | } 217 | 218 | -------------------------------------------------------------------------------- /BezierCurveView.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 50; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | DCC83416212A7ACF00762C01 /* BezierCurveView.swift in Sources */ = {isa = PBXBuildFile; fileRef = DCC83413212A7ACE00762C01 /* BezierCurveView.swift */; }; 11 | DCC83417212A7ACF00762C01 /* BezierHandleProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = DCC83414212A7ACE00762C01 /* BezierHandleProtocol.swift */; }; 12 | DCC83418212A7ACF00762C01 /* BezierHandleView.swift in Sources */ = {isa = PBXBuildFile; fileRef = DCC83415212A7ACF00762C01 /* BezierHandleView.swift */; }; 13 | /* End PBXBuildFile section */ 14 | 15 | /* Begin PBXFileReference section */ 16 | DCC83408212A7A3D00762C01 /* BezierCurveView.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = BezierCurveView.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 17 | DCC8340C212A7A3D00762C01 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 18 | DCC83413212A7ACE00762C01 /* BezierCurveView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BezierCurveView.swift; sourceTree = ""; }; 19 | DCC83414212A7ACE00762C01 /* BezierHandleProtocol.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BezierHandleProtocol.swift; sourceTree = ""; }; 20 | DCC83415212A7ACF00762C01 /* BezierHandleView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BezierHandleView.swift; sourceTree = ""; }; 21 | /* End PBXFileReference section */ 22 | 23 | /* Begin PBXFrameworksBuildPhase section */ 24 | DCC83404212A7A3D00762C01 /* Frameworks */ = { 25 | isa = PBXFrameworksBuildPhase; 26 | buildActionMask = 2147483647; 27 | files = ( 28 | ); 29 | runOnlyForDeploymentPostprocessing = 0; 30 | }; 31 | /* End PBXFrameworksBuildPhase section */ 32 | 33 | /* Begin PBXGroup section */ 34 | DCC833FE212A7A3D00762C01 = { 35 | isa = PBXGroup; 36 | children = ( 37 | DCC8340A212A7A3D00762C01 /* BezierCurveView */, 38 | DCC83409212A7A3D00762C01 /* Products */, 39 | ); 40 | sourceTree = ""; 41 | }; 42 | DCC83409212A7A3D00762C01 /* Products */ = { 43 | isa = PBXGroup; 44 | children = ( 45 | DCC83408212A7A3D00762C01 /* BezierCurveView.framework */, 46 | ); 47 | name = Products; 48 | sourceTree = ""; 49 | }; 50 | DCC8340A212A7A3D00762C01 /* BezierCurveView */ = { 51 | isa = PBXGroup; 52 | children = ( 53 | DCC83413212A7ACE00762C01 /* BezierCurveView.swift */, 54 | DCC83414212A7ACE00762C01 /* BezierHandleProtocol.swift */, 55 | DCC83415212A7ACF00762C01 /* BezierHandleView.swift */, 56 | DCC8340C212A7A3D00762C01 /* Info.plist */, 57 | ); 58 | path = BezierCurveView; 59 | sourceTree = ""; 60 | }; 61 | /* End PBXGroup section */ 62 | 63 | /* Begin PBXHeadersBuildPhase section */ 64 | DCC83405212A7A3D00762C01 /* Headers */ = { 65 | isa = PBXHeadersBuildPhase; 66 | buildActionMask = 2147483647; 67 | files = ( 68 | ); 69 | runOnlyForDeploymentPostprocessing = 0; 70 | }; 71 | /* End PBXHeadersBuildPhase section */ 72 | 73 | /* Begin PBXNativeTarget section */ 74 | DCC83407212A7A3D00762C01 /* BezierCurveView */ = { 75 | isa = PBXNativeTarget; 76 | buildConfigurationList = DCC83410212A7A3D00762C01 /* Build configuration list for PBXNativeTarget "BezierCurveView" */; 77 | buildPhases = ( 78 | DCC83403212A7A3D00762C01 /* Sources */, 79 | DCC83404212A7A3D00762C01 /* Frameworks */, 80 | DCC83405212A7A3D00762C01 /* Headers */, 81 | DCC83406212A7A3D00762C01 /* Resources */, 82 | ); 83 | buildRules = ( 84 | ); 85 | dependencies = ( 86 | ); 87 | name = BezierCurveView; 88 | productName = BezierCurveView; 89 | productReference = DCC83408212A7A3D00762C01 /* BezierCurveView.framework */; 90 | productType = "com.apple.product-type.framework"; 91 | }; 92 | /* End PBXNativeTarget section */ 93 | 94 | /* Begin PBXProject section */ 95 | DCC833FF212A7A3D00762C01 /* Project object */ = { 96 | isa = PBXProject; 97 | attributes = { 98 | LastUpgradeCheck = 0940; 99 | ORGANIZATIONNAME = SwiftArchitect; 100 | TargetAttributes = { 101 | DCC83407212A7A3D00762C01 = { 102 | CreatedOnToolsVersion = 9.4.1; 103 | LastSwiftMigration = 0940; 104 | }; 105 | }; 106 | }; 107 | buildConfigurationList = DCC83402212A7A3D00762C01 /* Build configuration list for PBXProject "BezierCurveView" */; 108 | compatibilityVersion = "Xcode 9.3"; 109 | developmentRegion = en; 110 | hasScannedForEncodings = 0; 111 | knownRegions = ( 112 | en, 113 | ); 114 | mainGroup = DCC833FE212A7A3D00762C01; 115 | productRefGroup = DCC83409212A7A3D00762C01 /* Products */; 116 | projectDirPath = ""; 117 | projectRoot = ""; 118 | targets = ( 119 | DCC83407212A7A3D00762C01 /* BezierCurveView */, 120 | ); 121 | }; 122 | /* End PBXProject section */ 123 | 124 | /* Begin PBXResourcesBuildPhase section */ 125 | DCC83406212A7A3D00762C01 /* Resources */ = { 126 | isa = PBXResourcesBuildPhase; 127 | buildActionMask = 2147483647; 128 | files = ( 129 | ); 130 | runOnlyForDeploymentPostprocessing = 0; 131 | }; 132 | /* End PBXResourcesBuildPhase section */ 133 | 134 | /* Begin PBXSourcesBuildPhase section */ 135 | DCC83403212A7A3D00762C01 /* Sources */ = { 136 | isa = PBXSourcesBuildPhase; 137 | buildActionMask = 2147483647; 138 | files = ( 139 | DCC83418212A7ACF00762C01 /* BezierHandleView.swift in Sources */, 140 | DCC83417212A7ACF00762C01 /* BezierHandleProtocol.swift in Sources */, 141 | DCC83416212A7ACF00762C01 /* BezierCurveView.swift in Sources */, 142 | ); 143 | runOnlyForDeploymentPostprocessing = 0; 144 | }; 145 | /* End PBXSourcesBuildPhase section */ 146 | 147 | /* Begin XCBuildConfiguration section */ 148 | DCC8340E212A7A3D00762C01 /* Debug */ = { 149 | isa = XCBuildConfiguration; 150 | buildSettings = { 151 | ALWAYS_SEARCH_USER_PATHS = NO; 152 | CLANG_ANALYZER_NONNULL = YES; 153 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 154 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; 155 | CLANG_CXX_LIBRARY = "libc++"; 156 | CLANG_ENABLE_MODULES = YES; 157 | CLANG_ENABLE_OBJC_ARC = YES; 158 | CLANG_ENABLE_OBJC_WEAK = YES; 159 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 160 | CLANG_WARN_BOOL_CONVERSION = YES; 161 | CLANG_WARN_COMMA = YES; 162 | CLANG_WARN_CONSTANT_CONVERSION = YES; 163 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 164 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 165 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 166 | CLANG_WARN_EMPTY_BODY = YES; 167 | CLANG_WARN_ENUM_CONVERSION = YES; 168 | CLANG_WARN_INFINITE_RECURSION = YES; 169 | CLANG_WARN_INT_CONVERSION = YES; 170 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 171 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 172 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 173 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 174 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 175 | CLANG_WARN_STRICT_PROTOTYPES = YES; 176 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 177 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 178 | CLANG_WARN_UNREACHABLE_CODE = YES; 179 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 180 | CODE_SIGN_IDENTITY = "iPhone Developer"; 181 | COPY_PHASE_STRIP = NO; 182 | CURRENT_PROJECT_VERSION = 1; 183 | DEBUG_INFORMATION_FORMAT = dwarf; 184 | ENABLE_STRICT_OBJC_MSGSEND = YES; 185 | ENABLE_TESTABILITY = YES; 186 | GCC_C_LANGUAGE_STANDARD = gnu11; 187 | GCC_DYNAMIC_NO_PIC = NO; 188 | GCC_NO_COMMON_BLOCKS = YES; 189 | GCC_OPTIMIZATION_LEVEL = 0; 190 | GCC_PREPROCESSOR_DEFINITIONS = ( 191 | "DEBUG=1", 192 | "$(inherited)", 193 | ); 194 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 195 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 196 | GCC_WARN_UNDECLARED_SELECTOR = YES; 197 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 198 | GCC_WARN_UNUSED_FUNCTION = YES; 199 | GCC_WARN_UNUSED_VARIABLE = YES; 200 | MTL_ENABLE_DEBUG_INFO = YES; 201 | ONLY_ACTIVE_ARCH = YES; 202 | SDKROOT = iphoneos; 203 | SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; 204 | SWIFT_OPTIMIZATION_LEVEL = "-Onone"; 205 | VERSIONING_SYSTEM = "apple-generic"; 206 | VERSION_INFO_PREFIX = ""; 207 | }; 208 | name = Debug; 209 | }; 210 | DCC8340F212A7A3D00762C01 /* Release */ = { 211 | isa = XCBuildConfiguration; 212 | buildSettings = { 213 | ALWAYS_SEARCH_USER_PATHS = NO; 214 | CLANG_ANALYZER_NONNULL = YES; 215 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 216 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; 217 | CLANG_CXX_LIBRARY = "libc++"; 218 | CLANG_ENABLE_MODULES = YES; 219 | CLANG_ENABLE_OBJC_ARC = YES; 220 | CLANG_ENABLE_OBJC_WEAK = YES; 221 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 222 | CLANG_WARN_BOOL_CONVERSION = YES; 223 | CLANG_WARN_COMMA = YES; 224 | CLANG_WARN_CONSTANT_CONVERSION = YES; 225 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 226 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 227 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 228 | CLANG_WARN_EMPTY_BODY = YES; 229 | CLANG_WARN_ENUM_CONVERSION = YES; 230 | CLANG_WARN_INFINITE_RECURSION = YES; 231 | CLANG_WARN_INT_CONVERSION = YES; 232 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 233 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 234 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 235 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 236 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 237 | CLANG_WARN_STRICT_PROTOTYPES = YES; 238 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 239 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 240 | CLANG_WARN_UNREACHABLE_CODE = YES; 241 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 242 | CODE_SIGN_IDENTITY = "iPhone Developer"; 243 | COPY_PHASE_STRIP = NO; 244 | CURRENT_PROJECT_VERSION = 1; 245 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 246 | ENABLE_NS_ASSERTIONS = NO; 247 | ENABLE_STRICT_OBJC_MSGSEND = YES; 248 | GCC_C_LANGUAGE_STANDARD = gnu11; 249 | GCC_NO_COMMON_BLOCKS = YES; 250 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 251 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 252 | GCC_WARN_UNDECLARED_SELECTOR = YES; 253 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 254 | GCC_WARN_UNUSED_FUNCTION = YES; 255 | GCC_WARN_UNUSED_VARIABLE = YES; 256 | MTL_ENABLE_DEBUG_INFO = NO; 257 | SDKROOT = iphoneos; 258 | SWIFT_COMPILATION_MODE = wholemodule; 259 | SWIFT_OPTIMIZATION_LEVEL = "-O"; 260 | VALIDATE_PRODUCT = YES; 261 | VERSIONING_SYSTEM = "apple-generic"; 262 | VERSION_INFO_PREFIX = ""; 263 | }; 264 | name = Release; 265 | }; 266 | DCC83411212A7A3D00762C01 /* Debug */ = { 267 | isa = XCBuildConfiguration; 268 | buildSettings = { 269 | CLANG_ENABLE_MODULES = YES; 270 | CODE_SIGN_IDENTITY = ""; 271 | CODE_SIGN_STYLE = Automatic; 272 | DEFINES_MODULE = YES; 273 | DYLIB_COMPATIBILITY_VERSION = 1; 274 | DYLIB_CURRENT_VERSION = 1; 275 | DYLIB_INSTALL_NAME_BASE = "@rpath"; 276 | INFOPLIST_FILE = BezierCurveView/Info.plist; 277 | INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; 278 | LD_RUNPATH_SEARCH_PATHS = ( 279 | "$(inherited)", 280 | "@executable_path/Frameworks", 281 | "@loader_path/Frameworks", 282 | ); 283 | PRODUCT_BUNDLE_IDENTIFIER = com.swiftarchitect.BezierCurveView; 284 | PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; 285 | SKIP_INSTALL = YES; 286 | SWIFT_OPTIMIZATION_LEVEL = "-Onone"; 287 | SWIFT_VERSION = 4.0; 288 | TARGETED_DEVICE_FAMILY = "1,2"; 289 | }; 290 | name = Debug; 291 | }; 292 | DCC83412212A7A3D00762C01 /* Release */ = { 293 | isa = XCBuildConfiguration; 294 | buildSettings = { 295 | CLANG_ENABLE_MODULES = YES; 296 | CODE_SIGN_IDENTITY = ""; 297 | CODE_SIGN_STYLE = Automatic; 298 | DEFINES_MODULE = YES; 299 | DYLIB_COMPATIBILITY_VERSION = 1; 300 | DYLIB_CURRENT_VERSION = 1; 301 | DYLIB_INSTALL_NAME_BASE = "@rpath"; 302 | INFOPLIST_FILE = BezierCurveView/Info.plist; 303 | INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; 304 | LD_RUNPATH_SEARCH_PATHS = ( 305 | "$(inherited)", 306 | "@executable_path/Frameworks", 307 | "@loader_path/Frameworks", 308 | ); 309 | PRODUCT_BUNDLE_IDENTIFIER = com.swiftarchitect.BezierCurveView; 310 | PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; 311 | SKIP_INSTALL = YES; 312 | SWIFT_VERSION = 4.0; 313 | TARGETED_DEVICE_FAMILY = "1,2"; 314 | }; 315 | name = Release; 316 | }; 317 | /* End XCBuildConfiguration section */ 318 | 319 | /* Begin XCConfigurationList section */ 320 | DCC83402212A7A3D00762C01 /* Build configuration list for PBXProject "BezierCurveView" */ = { 321 | isa = XCConfigurationList; 322 | buildConfigurations = ( 323 | DCC8340E212A7A3D00762C01 /* Debug */, 324 | DCC8340F212A7A3D00762C01 /* Release */, 325 | ); 326 | defaultConfigurationIsVisible = 0; 327 | defaultConfigurationName = Release; 328 | }; 329 | DCC83410212A7A3D00762C01 /* Build configuration list for PBXNativeTarget "BezierCurveView" */ = { 330 | isa = XCConfigurationList; 331 | buildConfigurations = ( 332 | DCC83411212A7A3D00762C01 /* Debug */, 333 | DCC83412212A7A3D00762C01 /* Release */, 334 | ); 335 | defaultConfigurationIsVisible = 0; 336 | defaultConfigurationName = Release; 337 | }; 338 | /* End XCConfigurationList section */ 339 | }; 340 | rootObject = DCC833FF212A7A3D00762C01 /* Project object */; 341 | } 342 | -------------------------------------------------------------------------------- /BezierCurveExample/BezierCurveExample.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 50; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 7531DF473E406A0350AB16F2 /* Pods_BezierCurveExample.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 2E4EA301154B187C8ADC2DB5 /* Pods_BezierCurveExample.framework */; }; 11 | DC5AE10D1E4FE76200F060C9 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = DC5AE10C1E4FE76200F060C9 /* AppDelegate.swift */; }; 12 | DC5AE10F1E4FE76200F060C9 /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = DC5AE10E1E4FE76200F060C9 /* ViewController.swift */; }; 13 | DC5AE1121E4FE76200F060C9 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = DC5AE1101E4FE76200F060C9 /* Main.storyboard */; }; 14 | DC5AE1141E4FE76200F060C9 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = DC5AE1131E4FE76200F060C9 /* Assets.xcassets */; }; 15 | DC5AE1171E4FE76200F060C9 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = DC5AE1151E4FE76200F060C9 /* LaunchScreen.storyboard */; }; 16 | /* End PBXBuildFile section */ 17 | 18 | /* Begin PBXFileReference section */ 19 | 2E4EA301154B187C8ADC2DB5 /* Pods_BezierCurveExample.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_BezierCurveExample.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 20 | 339A9EBD9084E64069B25502 /* Pods-BezierCurveExample.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-BezierCurveExample.release.xcconfig"; path = "Pods/Target Support Files/Pods-BezierCurveExample/Pods-BezierCurveExample.release.xcconfig"; sourceTree = ""; }; 21 | 9B3AC2A300F934115A76CBBF /* Pods-BezierCurveExample.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-BezierCurveExample.debug.xcconfig"; path = "Pods/Target Support Files/Pods-BezierCurveExample/Pods-BezierCurveExample.debug.xcconfig"; sourceTree = ""; }; 22 | DC5AE1091E4FE76200F060C9 /* BezierCurveExample.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = BezierCurveExample.app; sourceTree = BUILT_PRODUCTS_DIR; }; 23 | DC5AE10C1E4FE76200F060C9 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; 24 | DC5AE10E1E4FE76200F060C9 /* ViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewController.swift; sourceTree = ""; }; 25 | DC5AE1111E4FE76200F060C9 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; 26 | DC5AE1131E4FE76200F060C9 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 27 | DC5AE1161E4FE76200F060C9 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; 28 | DC5AE1181E4FE76200F060C9 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 29 | /* End PBXFileReference section */ 30 | 31 | /* Begin PBXFrameworksBuildPhase section */ 32 | DC5AE1061E4FE76200F060C9 /* Frameworks */ = { 33 | isa = PBXFrameworksBuildPhase; 34 | buildActionMask = 2147483647; 35 | files = ( 36 | 7531DF473E406A0350AB16F2 /* Pods_BezierCurveExample.framework in Frameworks */, 37 | ); 38 | runOnlyForDeploymentPostprocessing = 0; 39 | }; 40 | /* End PBXFrameworksBuildPhase section */ 41 | 42 | /* Begin PBXGroup section */ 43 | 3FCB618CACDFE708FCFB52AD /* Pods */ = { 44 | isa = PBXGroup; 45 | children = ( 46 | 9B3AC2A300F934115A76CBBF /* Pods-BezierCurveExample.debug.xcconfig */, 47 | 339A9EBD9084E64069B25502 /* Pods-BezierCurveExample.release.xcconfig */, 48 | ); 49 | name = Pods; 50 | sourceTree = ""; 51 | }; 52 | B1A2C61E661CD0710FA6BA59 /* Frameworks */ = { 53 | isa = PBXGroup; 54 | children = ( 55 | 2E4EA301154B187C8ADC2DB5 /* Pods_BezierCurveExample.framework */, 56 | ); 57 | name = Frameworks; 58 | sourceTree = ""; 59 | }; 60 | DC5AE1001E4FE76200F060C9 = { 61 | isa = PBXGroup; 62 | children = ( 63 | DC5AE10B1E4FE76200F060C9 /* BezierCurveExample */, 64 | DC5AE10A1E4FE76200F060C9 /* Products */, 65 | 3FCB618CACDFE708FCFB52AD /* Pods */, 66 | B1A2C61E661CD0710FA6BA59 /* Frameworks */, 67 | ); 68 | sourceTree = ""; 69 | }; 70 | DC5AE10A1E4FE76200F060C9 /* Products */ = { 71 | isa = PBXGroup; 72 | children = ( 73 | DC5AE1091E4FE76200F060C9 /* BezierCurveExample.app */, 74 | ); 75 | name = Products; 76 | sourceTree = ""; 77 | }; 78 | DC5AE10B1E4FE76200F060C9 /* BezierCurveExample */ = { 79 | isa = PBXGroup; 80 | children = ( 81 | DC5AE10C1E4FE76200F060C9 /* AppDelegate.swift */, 82 | DC5AE10E1E4FE76200F060C9 /* ViewController.swift */, 83 | DC5AE1101E4FE76200F060C9 /* Main.storyboard */, 84 | DC5AE1131E4FE76200F060C9 /* Assets.xcassets */, 85 | DC5AE1151E4FE76200F060C9 /* LaunchScreen.storyboard */, 86 | DC5AE1181E4FE76200F060C9 /* Info.plist */, 87 | ); 88 | path = BezierCurveExample; 89 | sourceTree = ""; 90 | }; 91 | /* End PBXGroup section */ 92 | 93 | /* Begin PBXNativeTarget section */ 94 | DC5AE1081E4FE76200F060C9 /* BezierCurveExample */ = { 95 | isa = PBXNativeTarget; 96 | buildConfigurationList = DC5AE11B1E4FE76200F060C9 /* Build configuration list for PBXNativeTarget "BezierCurveExample" */; 97 | buildPhases = ( 98 | 956FA8D49F4ECFFA80FF2D82 /* [CP] Check Pods Manifest.lock */, 99 | DC5AE1051E4FE76200F060C9 /* Sources */, 100 | DC5AE1061E4FE76200F060C9 /* Frameworks */, 101 | DC5AE1071E4FE76200F060C9 /* Resources */, 102 | C4A1D4EBB46AC12E74EDFFDE /* [CP] Embed Pods Frameworks */, 103 | ); 104 | buildRules = ( 105 | ); 106 | dependencies = ( 107 | ); 108 | name = BezierCurveExample; 109 | productName = BezierCurveExample; 110 | productReference = DC5AE1091E4FE76200F060C9 /* BezierCurveExample.app */; 111 | productType = "com.apple.product-type.application"; 112 | }; 113 | /* End PBXNativeTarget section */ 114 | 115 | /* Begin PBXProject section */ 116 | DC5AE1011E4FE76200F060C9 /* Project object */ = { 117 | isa = PBXProject; 118 | attributes = { 119 | LastSwiftUpdateCheck = 0820; 120 | LastUpgradeCheck = 0940; 121 | ORGANIZATIONNAME = SwiftArchitect; 122 | TargetAttributes = { 123 | DC5AE1081E4FE76200F060C9 = { 124 | CreatedOnToolsVersion = 8.2.1; 125 | DevelopmentTeam = 55K7THBUV8; 126 | LastSwiftMigration = 0940; 127 | ProvisioningStyle = Automatic; 128 | }; 129 | }; 130 | }; 131 | buildConfigurationList = DC5AE1041E4FE76200F060C9 /* Build configuration list for PBXProject "BezierCurveExample" */; 132 | compatibilityVersion = "Xcode 9.3"; 133 | developmentRegion = English; 134 | hasScannedForEncodings = 0; 135 | knownRegions = ( 136 | en, 137 | Base, 138 | ); 139 | mainGroup = DC5AE1001E4FE76200F060C9; 140 | productRefGroup = DC5AE10A1E4FE76200F060C9 /* Products */; 141 | projectDirPath = ""; 142 | projectRoot = ""; 143 | targets = ( 144 | DC5AE1081E4FE76200F060C9 /* BezierCurveExample */, 145 | ); 146 | }; 147 | /* End PBXProject section */ 148 | 149 | /* Begin PBXResourcesBuildPhase section */ 150 | DC5AE1071E4FE76200F060C9 /* Resources */ = { 151 | isa = PBXResourcesBuildPhase; 152 | buildActionMask = 2147483647; 153 | files = ( 154 | DC5AE1171E4FE76200F060C9 /* LaunchScreen.storyboard in Resources */, 155 | DC5AE1141E4FE76200F060C9 /* Assets.xcassets in Resources */, 156 | DC5AE1121E4FE76200F060C9 /* Main.storyboard in Resources */, 157 | ); 158 | runOnlyForDeploymentPostprocessing = 0; 159 | }; 160 | /* End PBXResourcesBuildPhase section */ 161 | 162 | /* Begin PBXShellScriptBuildPhase section */ 163 | 956FA8D49F4ECFFA80FF2D82 /* [CP] Check Pods Manifest.lock */ = { 164 | isa = PBXShellScriptBuildPhase; 165 | buildActionMask = 2147483647; 166 | files = ( 167 | ); 168 | inputPaths = ( 169 | "${PODS_PODFILE_DIR_PATH}/Podfile.lock", 170 | "${PODS_ROOT}/Manifest.lock", 171 | ); 172 | name = "[CP] Check Pods Manifest.lock"; 173 | outputPaths = ( 174 | "$(DERIVED_FILE_DIR)/Pods-BezierCurveExample-checkManifestLockResult.txt", 175 | ); 176 | runOnlyForDeploymentPostprocessing = 0; 177 | shellPath = /bin/sh; 178 | shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; 179 | showEnvVarsInLog = 0; 180 | }; 181 | C4A1D4EBB46AC12E74EDFFDE /* [CP] Embed Pods Frameworks */ = { 182 | isa = PBXShellScriptBuildPhase; 183 | buildActionMask = 2147483647; 184 | files = ( 185 | ); 186 | inputPaths = ( 187 | "${SRCROOT}/Pods/Target Support Files/Pods-BezierCurveExample/Pods-BezierCurveExample-frameworks.sh", 188 | "${BUILT_PRODUCTS_DIR}/BezierCurveView/BezierCurveView.framework", 189 | ); 190 | name = "[CP] Embed Pods Frameworks"; 191 | outputPaths = ( 192 | "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/BezierCurveView.framework", 193 | ); 194 | runOnlyForDeploymentPostprocessing = 0; 195 | shellPath = /bin/sh; 196 | shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-BezierCurveExample/Pods-BezierCurveExample-frameworks.sh\"\n"; 197 | showEnvVarsInLog = 0; 198 | }; 199 | /* End PBXShellScriptBuildPhase section */ 200 | 201 | /* Begin PBXSourcesBuildPhase section */ 202 | DC5AE1051E4FE76200F060C9 /* Sources */ = { 203 | isa = PBXSourcesBuildPhase; 204 | buildActionMask = 2147483647; 205 | files = ( 206 | DC5AE10F1E4FE76200F060C9 /* ViewController.swift in Sources */, 207 | DC5AE10D1E4FE76200F060C9 /* AppDelegate.swift in Sources */, 208 | ); 209 | runOnlyForDeploymentPostprocessing = 0; 210 | }; 211 | /* End PBXSourcesBuildPhase section */ 212 | 213 | /* Begin PBXVariantGroup section */ 214 | DC5AE1101E4FE76200F060C9 /* Main.storyboard */ = { 215 | isa = PBXVariantGroup; 216 | children = ( 217 | DC5AE1111E4FE76200F060C9 /* Base */, 218 | ); 219 | name = Main.storyboard; 220 | sourceTree = ""; 221 | }; 222 | DC5AE1151E4FE76200F060C9 /* LaunchScreen.storyboard */ = { 223 | isa = PBXVariantGroup; 224 | children = ( 225 | DC5AE1161E4FE76200F060C9 /* Base */, 226 | ); 227 | name = LaunchScreen.storyboard; 228 | sourceTree = ""; 229 | }; 230 | /* End PBXVariantGroup section */ 231 | 232 | /* Begin XCBuildConfiguration section */ 233 | DC5AE1191E4FE76200F060C9 /* Debug */ = { 234 | isa = XCBuildConfiguration; 235 | buildSettings = { 236 | ALWAYS_SEARCH_USER_PATHS = NO; 237 | CLANG_ANALYZER_NONNULL = YES; 238 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 239 | CLANG_CXX_LIBRARY = "libc++"; 240 | CLANG_ENABLE_MODULES = YES; 241 | CLANG_ENABLE_OBJC_ARC = YES; 242 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 243 | CLANG_WARN_BOOL_CONVERSION = YES; 244 | CLANG_WARN_COMMA = YES; 245 | CLANG_WARN_CONSTANT_CONVERSION = YES; 246 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 247 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 248 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 249 | CLANG_WARN_EMPTY_BODY = YES; 250 | CLANG_WARN_ENUM_CONVERSION = YES; 251 | CLANG_WARN_INFINITE_RECURSION = YES; 252 | CLANG_WARN_INT_CONVERSION = YES; 253 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 254 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 255 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 256 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 257 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 258 | CLANG_WARN_STRICT_PROTOTYPES = YES; 259 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 260 | CLANG_WARN_UNREACHABLE_CODE = YES; 261 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 262 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 263 | COPY_PHASE_STRIP = NO; 264 | DEBUG_INFORMATION_FORMAT = dwarf; 265 | ENABLE_STRICT_OBJC_MSGSEND = YES; 266 | ENABLE_TESTABILITY = YES; 267 | GCC_C_LANGUAGE_STANDARD = gnu99; 268 | GCC_DYNAMIC_NO_PIC = NO; 269 | GCC_NO_COMMON_BLOCKS = YES; 270 | GCC_OPTIMIZATION_LEVEL = 0; 271 | GCC_PREPROCESSOR_DEFINITIONS = ( 272 | "DEBUG=1", 273 | "$(inherited)", 274 | ); 275 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 276 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 277 | GCC_WARN_UNDECLARED_SELECTOR = YES; 278 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 279 | GCC_WARN_UNUSED_FUNCTION = YES; 280 | GCC_WARN_UNUSED_VARIABLE = YES; 281 | MTL_ENABLE_DEBUG_INFO = YES; 282 | ONLY_ACTIVE_ARCH = YES; 283 | SDKROOT = iphoneos; 284 | SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; 285 | SWIFT_OPTIMIZATION_LEVEL = "-Onone"; 286 | TARGETED_DEVICE_FAMILY = "1,2"; 287 | }; 288 | name = Debug; 289 | }; 290 | DC5AE11A1E4FE76200F060C9 /* Release */ = { 291 | isa = XCBuildConfiguration; 292 | buildSettings = { 293 | ALWAYS_SEARCH_USER_PATHS = NO; 294 | CLANG_ANALYZER_NONNULL = YES; 295 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 296 | CLANG_CXX_LIBRARY = "libc++"; 297 | CLANG_ENABLE_MODULES = YES; 298 | CLANG_ENABLE_OBJC_ARC = YES; 299 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 300 | CLANG_WARN_BOOL_CONVERSION = YES; 301 | CLANG_WARN_COMMA = YES; 302 | CLANG_WARN_CONSTANT_CONVERSION = YES; 303 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 304 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 305 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 306 | CLANG_WARN_EMPTY_BODY = YES; 307 | CLANG_WARN_ENUM_CONVERSION = YES; 308 | CLANG_WARN_INFINITE_RECURSION = YES; 309 | CLANG_WARN_INT_CONVERSION = YES; 310 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 311 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 312 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 313 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 314 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 315 | CLANG_WARN_STRICT_PROTOTYPES = YES; 316 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 317 | CLANG_WARN_UNREACHABLE_CODE = YES; 318 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 319 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 320 | COPY_PHASE_STRIP = NO; 321 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 322 | ENABLE_NS_ASSERTIONS = NO; 323 | ENABLE_STRICT_OBJC_MSGSEND = YES; 324 | GCC_C_LANGUAGE_STANDARD = gnu99; 325 | GCC_NO_COMMON_BLOCKS = YES; 326 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 327 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 328 | GCC_WARN_UNDECLARED_SELECTOR = YES; 329 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 330 | GCC_WARN_UNUSED_FUNCTION = YES; 331 | GCC_WARN_UNUSED_VARIABLE = YES; 332 | MTL_ENABLE_DEBUG_INFO = NO; 333 | SDKROOT = iphoneos; 334 | SWIFT_COMPILATION_MODE = wholemodule; 335 | SWIFT_OPTIMIZATION_LEVEL = "-O"; 336 | TARGETED_DEVICE_FAMILY = "1,2"; 337 | VALIDATE_PRODUCT = YES; 338 | }; 339 | name = Release; 340 | }; 341 | DC5AE11C1E4FE76200F060C9 /* Debug */ = { 342 | isa = XCBuildConfiguration; 343 | baseConfigurationReference = 9B3AC2A300F934115A76CBBF /* Pods-BezierCurveExample.debug.xcconfig */; 344 | buildSettings = { 345 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 346 | DEVELOPMENT_TEAM = 55K7THBUV8; 347 | INFOPLIST_FILE = BezierCurveExample/Info.plist; 348 | LD_RUNPATH_SEARCH_PATHS = ( 349 | "$(inherited)", 350 | "@executable_path/Frameworks", 351 | ); 352 | PRODUCT_BUNDLE_IDENTIFIER = com.swiftarchitect.BezierCurveExample; 353 | PRODUCT_NAME = "$(TARGET_NAME)"; 354 | SWIFT_SWIFT3_OBJC_INFERENCE = Default; 355 | SWIFT_VERSION = 4.0; 356 | }; 357 | name = Debug; 358 | }; 359 | DC5AE11D1E4FE76200F060C9 /* Release */ = { 360 | isa = XCBuildConfiguration; 361 | baseConfigurationReference = 339A9EBD9084E64069B25502 /* Pods-BezierCurveExample.release.xcconfig */; 362 | buildSettings = { 363 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 364 | DEVELOPMENT_TEAM = 55K7THBUV8; 365 | INFOPLIST_FILE = BezierCurveExample/Info.plist; 366 | LD_RUNPATH_SEARCH_PATHS = ( 367 | "$(inherited)", 368 | "@executable_path/Frameworks", 369 | ); 370 | PRODUCT_BUNDLE_IDENTIFIER = com.swiftarchitect.BezierCurveExample; 371 | PRODUCT_NAME = "$(TARGET_NAME)"; 372 | SWIFT_SWIFT3_OBJC_INFERENCE = Default; 373 | SWIFT_VERSION = 4.0; 374 | }; 375 | name = Release; 376 | }; 377 | /* End XCBuildConfiguration section */ 378 | 379 | /* Begin XCConfigurationList section */ 380 | DC5AE1041E4FE76200F060C9 /* Build configuration list for PBXProject "BezierCurveExample" */ = { 381 | isa = XCConfigurationList; 382 | buildConfigurations = ( 383 | DC5AE1191E4FE76200F060C9 /* Debug */, 384 | DC5AE11A1E4FE76200F060C9 /* Release */, 385 | ); 386 | defaultConfigurationIsVisible = 0; 387 | defaultConfigurationName = Release; 388 | }; 389 | DC5AE11B1E4FE76200F060C9 /* Build configuration list for PBXNativeTarget "BezierCurveExample" */ = { 390 | isa = XCConfigurationList; 391 | buildConfigurations = ( 392 | DC5AE11C1E4FE76200F060C9 /* Debug */, 393 | DC5AE11D1E4FE76200F060C9 /* Release */, 394 | ); 395 | defaultConfigurationIsVisible = 0; 396 | defaultConfigurationName = Release; 397 | }; 398 | /* End XCConfigurationList section */ 399 | }; 400 | rootObject = DC5AE1011E4FE76200F060C9 /* Project object */; 401 | } 402 | -------------------------------------------------------------------------------- /BezierCurveExample/BezierCurveExample/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 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | 177 | 178 | 179 | 180 | 181 | 182 | 183 | 184 | 185 | 186 | 187 | 188 | 189 | 190 | 191 | 192 | 193 | 194 | 195 | 196 | 197 | 198 | 199 | 200 | 201 | 202 | 203 | 204 | 205 | 206 | 207 | 208 | 209 | 210 | 211 | 212 | 213 | 214 | 215 | 216 | 217 | 218 | 219 | 220 | 221 | 222 | 223 | 224 | 225 | 226 | 227 | 228 | 229 | 230 | 231 | 232 | 233 | 234 | 235 | 236 | 237 | 238 | 239 | 240 | 241 | 242 | 243 | 244 | 245 | 246 | 247 | 248 | 249 | 250 | 251 | 252 | 253 | 254 | 255 | 256 | 257 | 258 | 259 | 260 | 261 | 262 | 263 | 264 | 265 | 266 | 267 | 268 | 269 | 270 | 271 | 272 | 273 | 274 | 275 | 276 | 277 | 278 | 279 | 280 | 281 | 282 | 283 | 284 | 285 | 286 | 287 | 288 | 289 | 290 | 291 | 292 | 293 | 294 | 295 | 296 | 297 | 298 | 299 | 300 | 301 | 302 | 303 | 304 | 305 | 306 | 307 | 308 | 309 | 310 | 311 | 312 | 313 | 314 | 315 | 316 | 317 | 318 | 319 | 320 | 321 | 322 | 323 | 324 | 325 | 326 | 327 | 328 | 329 | 330 | 331 | 332 | 333 | 334 | 335 | 336 | 337 | 338 | 339 | 340 | 341 | 342 | 343 | 344 | 345 | 346 | 347 | 348 | 349 | 350 | 351 | 352 | 353 | 354 | 355 | 356 | 357 | 358 | 359 | 360 | 361 | 362 | 363 | 364 | 365 | 366 | 367 | 368 | 369 | 370 | 371 | 372 | 373 | 374 | 375 | 376 | 377 | 378 | 379 | 380 | 381 | 382 | 383 | 384 | 385 | 386 | 387 | 388 | 389 | 390 | 391 | 392 | 393 | 394 | 395 | 396 | 397 | 398 | 399 | 400 | 401 | 402 | 403 | 404 | 405 | 406 | 407 | 408 | 409 | 410 | 411 | 412 | 413 | 414 | 415 | 416 | 417 | 418 | 419 | 420 | 421 | 422 | 423 | 424 | 425 | 426 | 427 | 428 | 429 | 430 | 431 | 432 | 433 | 434 | 435 | 436 | 437 | 438 | 439 | 440 | 441 | 442 | 443 | 444 | 445 | 446 | 447 | 448 | 449 | 450 | 451 | 452 | 453 | 454 | 455 | 456 | 457 | 458 | 459 | 460 | 461 | 462 | 463 | 464 | 465 | 466 | 467 | 468 | 469 | 470 | 471 | 472 | 473 | 474 | 475 | 476 | 477 | 478 | 479 | 480 | 481 | 482 | 483 | 484 | 485 | 486 | 487 | 488 | 489 | 490 | 491 | 492 | 493 | 494 | 495 | 496 | 497 | 498 | 499 | 500 | 501 | 502 | 503 | 504 | 505 | 506 | 507 | 508 | 509 | 510 | 511 | 512 | 513 | 514 | 515 | 516 | 517 | 518 | 519 | 520 | 521 | 522 | 523 | 524 | 525 | 526 | 527 | 528 | 529 | 530 | 531 | 532 | 533 | 534 | 535 | 536 | 537 | 538 | 539 | 540 | 541 | 542 | 543 | 544 | 545 | 546 | 547 | 548 | 549 | 550 | 551 | 552 | 553 | 554 | 555 | 556 | 557 | 558 | 559 | 560 | 561 | 562 | 569 | 575 | 576 | 577 | 578 | 579 | 580 | 581 | 582 | 583 | 584 | 585 | 586 | 587 | 588 | 589 | 590 | 591 | 592 | 593 | 594 | 595 | 596 | 597 | 598 | 599 | 600 | 601 | 602 | 603 | 604 | 605 | 606 | 607 | 608 | 609 | 610 | 611 | 612 | 613 | 614 | 615 | 616 | 617 | 618 | 619 | 620 | 621 | 622 | 623 | 624 | 625 | 626 | 627 | 628 | 629 | 630 | 631 | 632 | 633 | 634 | 635 | 636 | 637 | 638 | 639 | 640 | 641 | 642 | 643 | 644 | 645 | 646 | 647 | 648 | 649 | 650 | 651 | 652 | 653 | 654 | 655 | 656 | 657 | 658 | 659 | 660 | 661 | 662 | 663 | 664 | 665 | 666 | 667 | 668 | 669 | 670 | 671 | 672 | 673 | 674 | 675 | 676 | 677 | 678 | 679 | 680 | 681 | 682 | 683 | 684 | 685 | 686 | 687 | 688 | 689 | 690 | 691 | 692 | 693 | 694 | 695 | 696 | 697 | 703 | 704 | 705 | 706 | 707 | 708 | 709 | 710 | 717 | 718 | 719 | 720 | 721 | 722 | 723 | 724 | 725 | 726 | 727 | 728 | 729 | 730 | 731 | 732 | 733 | 734 | 735 | 736 | 737 | 738 | 739 | 740 | 741 | 742 | 743 | 744 | 745 | 746 | 747 | 748 | 749 | 750 | 751 | 752 | 753 | 754 | 755 | 756 | 757 | 758 | 759 | 760 | 761 | 762 | 763 | 764 | 765 | 766 | 767 | 768 | 769 | 770 | 771 | 772 | 773 | 774 | 775 | 776 | 777 | 778 | 779 | 780 | 781 | 782 | 783 | 784 | 785 | 786 | 787 | 788 | 789 | 790 | 791 | 792 | 793 | 794 | 795 | 796 | 797 | 798 | 799 | 800 | 801 | 802 | 803 | 804 | 805 | 806 | 807 | 808 | 809 | 810 | 811 | 812 | 813 | 814 | 815 | 816 | 817 | 818 | 819 | 820 | 831 | 832 | 833 | 834 | 835 | 836 | 837 | 838 | 839 | 840 | 841 | 842 | 843 | 844 | 845 | 846 | 847 | 848 | 849 | 850 | 851 | 852 | 853 | 854 | 855 | 856 | 857 | 858 | 859 | 860 | 861 | 862 | 863 | 864 | 865 | 866 | 867 | 868 | 869 | 870 | 871 | 872 | 873 | 874 | 875 | 876 | 877 | 878 | 879 | 880 | 881 | 882 | 883 | 884 | 885 | 886 | 887 | 888 | 889 | 890 | 891 | 892 | 893 | 894 | 895 | 896 | 897 | 898 | 899 | 900 | 901 | 902 | 903 | 904 | 905 | 906 | 907 | 908 | 909 | 910 | 911 | 912 | 913 | 914 | 915 | 916 | 917 | 918 | 919 | 920 | 921 | 922 | 923 | 924 | 925 | 926 | 927 | --------------------------------------------------------------------------------