├── 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 | [](https://travis-ci.org/SwiftArchitect/BezierCurveView)
4 | [](https://cocoapods.org/pods/BezierCurveView)
5 | [](https://github.com/Carthage/Carthage)
6 | 
7 |
8 | Bezier curves are very handy to point to objects in your interface, for onboarding and help screens:
9 |
10 | 
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 | .
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 | 
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 | 
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 |
--------------------------------------------------------------------------------