├── .gitattributes ├── KiClipperImageDemo ├── KiClipperImageDemo.xcodeproj │ ├── project.xcworkspace │ │ ├── contents.xcworkspacedata │ │ ├── xcuserdata │ │ │ └── mbapple.xcuserdatad │ │ │ │ └── UserInterfaceState.xcuserstate │ │ └── xcshareddata │ │ │ └── IDEWorkspaceChecks.plist │ ├── xcuserdata │ │ └── mbapple.xcuserdatad │ │ │ ├── xcschemes │ │ │ └── xcschememanagement.plist │ │ │ └── xcdebugger │ │ │ └── Breakpoints_v2.xcbkptlist │ └── project.pbxproj ├── KiClipperImageDemoTests │ ├── Info.plist │ └── KiClipperImageDemoTests.swift ├── KiClipperImageDemoUITests │ ├── Info.plist │ └── KiClipperImageDemoUITests.swift ├── KiClipperImageDemo │ ├── Base.lproj │ │ ├── Main.storyboard │ │ └── LaunchScreen.storyboard │ ├── Info.plist │ ├── Assets.xcassets │ │ └── AppIcon.appiconset │ │ │ └── Contents.json │ ├── AppDelegate.swift │ └── ViewController.swift └── KiClipperHelper │ ├── KiClipperHelper.swift │ ├── KiImageClipperViewController.swift │ └── KiClipperView.swift └── README.md /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto -------------------------------------------------------------------------------- /KiClipperImageDemo/KiClipperImageDemo.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /KiClipperImageDemo/KiClipperImageDemo.xcodeproj/project.xcworkspace/xcuserdata/mbapple.xcuserdatad/UserInterfaceState.xcuserstate: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Kingzhijie/KiClipperImageDemo/HEAD/KiClipperImageDemo/KiClipperImageDemo.xcodeproj/project.xcworkspace/xcuserdata/mbapple.xcuserdatad/UserInterfaceState.xcuserstate -------------------------------------------------------------------------------- /KiClipperImageDemo/KiClipperImageDemo.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /KiClipperImageDemo/KiClipperImageDemo.xcodeproj/xcuserdata/mbapple.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | KiClipperImageDemo.xcscheme 8 | 9 | orderHint 10 | 0 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /KiClipperImageDemo/KiClipperImageDemoTests/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 | BNDL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleVersion 20 | 1 21 | 22 | 23 | -------------------------------------------------------------------------------- /KiClipperImageDemo/KiClipperImageDemoUITests/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 | BNDL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleVersion 20 | 1 21 | 22 | 23 | -------------------------------------------------------------------------------- /KiClipperImageDemo/KiClipperImageDemo.xcodeproj/xcuserdata/mbapple.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 8 | 20 | 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /KiClipperImageDemo/KiClipperImageDemoTests/KiClipperImageDemoTests.swift: -------------------------------------------------------------------------------- 1 | // 2 | // KiClipperImageDemoTests.swift 3 | // KiClipperImageDemoTests 4 | // 5 | // Created by mbApple on 2017/11/15. 6 | // Copyright © 2017年 panda誌. All rights reserved. 7 | // 8 | 9 | import XCTest 10 | @testable import KiClipperImageDemo 11 | 12 | class KiClipperImageDemoTests: XCTestCase { 13 | 14 | override func setUp() { 15 | super.setUp() 16 | // Put setup code here. This method is called before the invocation of each test method in the class. 17 | } 18 | 19 | override func tearDown() { 20 | // Put teardown code here. This method is called after the invocation of each test method in the class. 21 | super.tearDown() 22 | } 23 | 24 | func testExample() { 25 | // This is an example of a functional test case. 26 | // Use XCTAssert and related functions to verify your tests produce the correct results. 27 | } 28 | 29 | func testPerformanceExample() { 30 | // This is an example of a performance test case. 31 | self.measure { 32 | // Put the code you want to measure the time of here. 33 | } 34 | } 35 | 36 | } 37 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # KiClipperImageDemo 2 | ######图片裁剪工具类 3 | ###工具提供四种方式: 获取图片## 4 | 1. 直接获取图片 5 | 2. 直接获取图片, 并使用系统的编辑功能 6 | 3. 自定义裁剪图片, 设置好裁剪框的尺寸, 图片可以自由拖动和缩放 7 | 4. 自定义裁剪图片, 图片不移动, 自由拖动或者缩放裁剪框 8 | 9 | ###使用方法 : 使用单例工具类 KiClipperHelper 10 | 11 | KiClipperHelper.sharedInstance.nav = navigationController //获取当前导航 12 | KiClipperHelper.sharedInstance.clippedImgSize = size // 传入, 自定义的裁剪尺寸 (不需要裁剪, 可以不传) 13 | //获取图片成功的回调 img 即为目标图片 14 | KiClipperHelper.sharedInstance.clippedImageHandler = {[weak self]img in 15 | self?.clippedImageView?.image = img 16 | } 17 | 18 | ###参数说明: 19 | public var clippedImageHandler:clippedImageHandlerBlock? //裁剪结束回调 20 | public var systemEditing = false // 系统方式获取图片时, 是否允许系统编辑裁剪 21 | public var isSystemType = false //是否系统方式获取图片 22 | public var clippedImgSize:CGSize? //自定义裁剪的尺寸 23 | public weak var nav:UINavigationController? //当前导航 24 | public var clipperType:ClipperType = .Move //裁剪框移动类型 (move图片移动, stay裁剪框移动) 25 | ###方法说明 26 | //制定获取图片的方式, 相册或者相机 27 | public func photoWithSourceType(type:UIImagePickerControllerSourceType) 28 | //代理方法 , 获取图片后的回调方法 29 | func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : Any]) 30 | 31 | ![](http://www.code4app.com/data/attachment/forum/201608/22/101043v7py0bnmpaayppb5.gif) 32 | -------------------------------------------------------------------------------- /KiClipperImageDemo/KiClipperImageDemoUITests/KiClipperImageDemoUITests.swift: -------------------------------------------------------------------------------- 1 | // 2 | // KiClipperImageDemoUITests.swift 3 | // KiClipperImageDemoUITests 4 | // 5 | // Created by mbApple on 2017/11/15. 6 | // Copyright © 2017年 panda誌. All rights reserved. 7 | // 8 | 9 | import XCTest 10 | 11 | class KiClipperImageDemoUITests: XCTestCase { 12 | 13 | override func setUp() { 14 | super.setUp() 15 | 16 | // Put setup code here. This method is called before the invocation of each test method in the class. 17 | 18 | // In UI tests it is usually best to stop immediately when a failure occurs. 19 | continueAfterFailure = false 20 | // UI tests must launch the application that they test. Doing this in setup will make sure it happens for each test method. 21 | XCUIApplication().launch() 22 | 23 | // In UI tests it’s important to set the initial state - such as interface orientation - required for your tests before they run. The setUp method is a good place to do this. 24 | } 25 | 26 | override func tearDown() { 27 | // Put teardown code here. This method is called after the invocation of each test method in the class. 28 | super.tearDown() 29 | } 30 | 31 | func testExample() { 32 | // Use recording to get started writing UI tests. 33 | // Use XCTAssert and related functions to verify your tests produce the correct results. 34 | } 35 | 36 | } 37 | -------------------------------------------------------------------------------- /KiClipperImageDemo/KiClipperImageDemo/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 | -------------------------------------------------------------------------------- /KiClipperImageDemo/KiClipperImageDemo/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 | -------------------------------------------------------------------------------- /KiClipperImageDemo/KiClipperImageDemo/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | $(DEVELOPMENT_LANGUAGE) 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | APPL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleVersion 20 | 1 21 | LSRequiresIPhoneOS 22 | 23 | NSCameraUsageDescription 24 | 访问相机 25 | NSPhotoLibraryUsageDescription 26 | 访问相册 27 | UILaunchStoryboardName 28 | LaunchScreen 29 | UIMainStoryboardFile 30 | Main 31 | UIRequiredDeviceCapabilities 32 | 33 | armv7 34 | 35 | UISupportedInterfaceOrientations 36 | 37 | UIInterfaceOrientationPortrait 38 | UIInterfaceOrientationLandscapeLeft 39 | UIInterfaceOrientationLandscapeRight 40 | 41 | UISupportedInterfaceOrientations~ipad 42 | 43 | UIInterfaceOrientationPortrait 44 | UIInterfaceOrientationPortraitUpsideDown 45 | UIInterfaceOrientationLandscapeLeft 46 | UIInterfaceOrientationLandscapeRight 47 | 48 | 49 | 50 | -------------------------------------------------------------------------------- /KiClipperImageDemo/KiClipperImageDemo/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 | } -------------------------------------------------------------------------------- /KiClipperImageDemo/KiClipperImageDemo/AppDelegate.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.swift 3 | // KiClipperImageDemo 4 | // 5 | // Created by mbApple on 2017/11/15. 6 | // Copyright © 2017年 panda誌. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | @UIApplicationMain 12 | class AppDelegate: UIResponder, UIApplicationDelegate { 13 | 14 | var window: UIWindow? 15 | 16 | 17 | func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool { 18 | // Override point for customization after application launch. 19 | let VC = ViewController() 20 | let nav = UINavigationController(rootViewController: VC) 21 | self.window?.rootViewController = nav 22 | 23 | return true 24 | } 25 | 26 | func applicationWillResignActive(_ application: UIApplication) { 27 | // 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. 28 | // Use this method to pause ongoing tasks, disable timers, and invalidate graphics rendering callbacks. Games should use this method to pause the game. 29 | } 30 | 31 | func applicationDidEnterBackground(_ application: UIApplication) { 32 | // 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. 33 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. 34 | } 35 | 36 | func applicationWillEnterForeground(_ application: UIApplication) { 37 | // 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. 38 | } 39 | 40 | func applicationDidBecomeActive(_ application: UIApplication) { 41 | // 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. 42 | } 43 | 44 | func applicationWillTerminate(_ application: UIApplication) { 45 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. 46 | } 47 | 48 | 49 | } 50 | 51 | -------------------------------------------------------------------------------- /KiClipperImageDemo/KiClipperHelper/KiClipperHelper.swift: -------------------------------------------------------------------------------- 1 | // 2 | // KiClipperHelper.swift 3 | // KiClipperImageDemo 4 | // 5 | // Created by mbApple on 2017/11/15. 6 | // Copyright © 2017年 panda誌. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | private let shareManager = KiClipperHelper() 12 | typealias clippedImageHandlerBlock = (_ img:UIImage)->Void 13 | class KiClipperHelper: NSObject,UIImagePickerControllerDelegate,UINavigationControllerDelegate { 14 | 15 | class var sharedInstance : KiClipperHelper { //单例---工具类 16 | return shareManager 17 | } 18 | 19 | public var clippedImageHandler:clippedImageHandlerBlock? //裁剪结束回调 20 | public var systemEditing = false // 系统方式获取图片时, 是否允许系统编辑裁剪 21 | public var isSystemType = false //是否系统方式获取图片 22 | public var clippedImgSize:CGSize? //自定义裁剪的尺寸 23 | public weak var nav:UINavigationController? //当前导航 24 | public var clipperType:ClipperType = .Move //裁剪框移动类型 (move图片移动, stay裁剪框移动) 25 | 26 | public func photoWithSourceType(type:UIImagePickerControllerSourceType) { 27 | let imagePicker = UIImagePickerController() 28 | imagePicker.delegate = self 29 | imagePicker.sourceType = type 30 | imagePicker.allowsEditing = systemEditing 31 | // imagePicker.modalTransitionStyle = .crossDissolve 32 | nav?.present(imagePicker, animated: true, completion: nil) 33 | } 34 | 35 | //MARK UIImagePickerControllerDelegate 36 | func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : Any]){ 37 | if !isSystemType { //自定义裁剪 38 | let image = self.turnImageWithInfo(info: info) 39 | let clipperVC = KiImageClipperViewController() 40 | clipperVC.setBaseImg(image, resultImgSize: clippedImgSize!, type: clipperType) 41 | clipperVC.cancelClippedHandler = { 42 | picker.dismiss(animated: true, completion: nil) 43 | } 44 | clipperVC.successClippedHandler = {[weak self]img in 45 | if self?.clippedImageHandler != nil{ 46 | self?.clippedImageHandler!(img) 47 | } 48 | picker.dismiss(animated: true, completion: nil) 49 | } 50 | picker.pushViewController(clipperVC, animated: true) 51 | }else{ //系统获取 52 | if !self.systemEditing{ 53 | image = self.turnImageWithInfo(info: info) 54 | }else{ 55 | image = info[UIImagePickerControllerEditedImage] as? UIImage 56 | } 57 | if clippedImageHandler != nil{ 58 | clippedImageHandler!(image ?? UIImage()) 59 | } 60 | picker.dismiss(animated: true, completion: nil) 61 | } 62 | } 63 | 64 | private var image:UIImage? 65 | 66 | private func turnImageWithInfo(info:[String:Any]) -> UIImage { 67 | var image = info[UIImagePickerControllerOriginalImage] as? UIImage 68 | //类型为 UIImagePickerControllerOriginalImage 时调整图片角度 69 | let type = info[UIImagePickerControllerMediaType] as? String 70 | 71 | if type == "public.image" { 72 | let imageOrientation = image?.imageOrientation 73 | if imageOrientation != UIImageOrientation.up{ 74 | // 原始图片可以根据照相时的角度来显示,但 UIImage无法判定,于是出现获取的图片会向左转90度的现象。 75 | UIGraphicsBeginImageContext((image?.size)!) 76 | image?.draw(in: CGRect(x: 0, y: 0, width: (image?.size.width)!, height: (image?.size.height)!)) 77 | image = UIGraphicsGetImageFromCurrentImageContext() 78 | UIGraphicsEndImageContext() 79 | } 80 | } 81 | return image! 82 | } 83 | 84 | 85 | } 86 | -------------------------------------------------------------------------------- /KiClipperImageDemo/KiClipperHelper/KiImageClipperViewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // KiImageClipperViewController.swift 3 | // KiClipperImageDemo 4 | // 5 | // Created by mbApple on 2017/11/15. 6 | // Copyright © 2017年 panda誌. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | // iPhone X 11 | let iphoneX = (UIScreen.main.bounds.size.width == 375.0 && UIScreen.main.bounds.size.height == 812.0 ? true : false) as Bool 12 | 13 | typealias cancelClippedHandlerBlock = ()->Void 14 | typealias successClippedHandlerBlock = (_ clippedImage:UIImage)->Void 15 | class KiImageClipperViewController: UIViewController { 16 | //MARK Public 17 | public var cancelClippedHandler:cancelClippedHandlerBlock? 18 | public var successClippedHandler:successClippedHandlerBlock? 19 | public func setBaseImg(_ baseImg:UIImage,resultImgSize:CGSize,type:ClipperType) { 20 | clipperView = KiClipperView(frame: CGRect(x: 0, y: (iphoneX ? 88:64), width: UIScreen.main.bounds.size.width, height: UIScreen.main.bounds.size.height - (iphoneX ? 88:64))) 21 | clipperView?.resultImgSize = resultImgSize 22 | clipperView?.baseImg = baseImg 23 | clipperView?.type = type 24 | self.view.addSubview(clipperView!) 25 | } 26 | 27 | //MARK Private 28 | private var clipperView:KiClipperView? 29 | private let TITLE_BAR_HEIGHT:Int = 44 30 | private var rightBtn:UIButton? 31 | private var leftBtn:UIButton? 32 | 33 | override func viewDidLoad() { 34 | super.viewDidLoad() 35 | self.title = "选择图片" 36 | view.backgroundColor = .black 37 | 38 | self.hidesBottomBarWhenPushed = true 39 | if #available(iOS 11.0, *) { 40 | }else{ 41 | self.automaticallyAdjustsScrollViewInsets = false 42 | } 43 | 44 | self.creatLeftBtnWithTitle(title: "取消") 45 | self.creaRightBtnWithTitle(title: "确认") 46 | // Do any additional setup after loading the view. 47 | } 48 | 49 | @objc private func leftBtnTUI(btn: UIButton) { 50 | if cancelClippedHandler != nil { 51 | cancelClippedHandler!() 52 | } 53 | } 54 | 55 | @objc private func rightBtnTUI(btn: UIButton) { 56 | let clippedImg = self.clipperView?.clipImg() 57 | if successClippedHandler != nil { 58 | successClippedHandler!(clippedImg ?? UIImage()) 59 | } 60 | } 61 | 62 | //MARK 63 | private func creatLeftBtnWithTitle(title:String) { 64 | if leftBtn == nil { 65 | leftBtn = UIButton(type: .custom) 66 | leftBtn?.frame = CGRect(x: 20, y: 20, width: TITLE_BAR_HEIGHT, height: TITLE_BAR_HEIGHT) 67 | leftBtn?.contentEdgeInsets = UIEdgeInsets(top: 0, left: 0, bottom: 0, right: 0) 68 | leftBtn?.contentHorizontalAlignment = .left 69 | leftBtn?.setTitle(title, for: .normal) 70 | leftBtn?.setTitleColor(UIColor.init(red: 0.118, green: 0.133, blue: 0.153, alpha: 1.0), for: .normal) 71 | leftBtn?.titleLabel?.font = UIFont.systemFont(ofSize: 16) 72 | leftBtn?.addTarget(self, action: #selector(leftBtnTUI(btn:)), for: .touchUpInside) 73 | navigationItem.leftBarButtonItem = UIBarButtonItem(customView: leftBtn!) 74 | } 75 | } 76 | 77 | private func creaRightBtnWithTitle(title:String) { 78 | if rightBtn == nil { 79 | rightBtn = UIButton(type: .custom) 80 | rightBtn?.setTitleColor(UIColor.init(red: 0.118, green: 0.133, blue: 0.153, alpha: 1.0), for: .normal) 81 | rightBtn?.titleLabel?.font = UIFont.systemFont(ofSize: 16) 82 | rightBtn?.addTarget(self, action: #selector(rightBtnTUI(btn:)), for: .touchUpInside) 83 | rightBtn?.layer.cornerRadius = 8 84 | } 85 | rightBtn?.sizeToFit() 86 | rightBtn?.setTitle(title, for: .normal) 87 | navigationItem.rightBarButtonItem = UIBarButtonItem(customView: rightBtn!) 88 | } 89 | 90 | override func viewWillAppear(_ animated: Bool) { 91 | super.viewWillAppear(animated) 92 | navigationController?.isNavigationBarHidden = false 93 | } 94 | 95 | override func didReceiveMemoryWarning() { 96 | super.didReceiveMemoryWarning() 97 | // Dispose of any resources that can be recreated. 98 | } 99 | 100 | 101 | /* 102 | // MARK: - Navigation 103 | 104 | // In a storyboard-based application, you will often want to do a little preparation before navigation 105 | override func prepare(for segue: UIStoryboardSegue, sender: Any?) { 106 | // Get the new view controller using segue.destinationViewController. 107 | // Pass the selected object to the new view controller. 108 | } 109 | */ 110 | 111 | } 112 | -------------------------------------------------------------------------------- /KiClipperImageDemo/KiClipperImageDemo/ViewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.swift 3 | // KiClipperImageDemo 4 | // 5 | // Created by mbApple on 2017/11/15. 6 | // Copyright © 2017年 panda誌. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | class ViewController: UIViewController,UIActionSheetDelegate { 12 | 13 | lazy var clippedImageView: UIImageView? = { 14 | let clippedImageView = UIImageView(frame: CGRect(x: 20, y: 300, width: 300, height: 300)) 15 | clippedImageView.backgroundColor = .red 16 | return clippedImageView 17 | }() 18 | 19 | override func viewDidLoad() { 20 | super.viewDidLoad() 21 | view.backgroundColor = .white 22 | // Do any additional setup after loading the view, typically from a nib. 23 | self.view.addSubview(self.clippedImageView!) 24 | let button = UIButton(type: .custom) 25 | button.backgroundColor = .red 26 | button.setTitle("不裁剪", for: .normal) 27 | button.frame = CGRect(x: 10, y: 100, width: 60, height: 60) 28 | button.addTarget(self, action:#selector(action1), for: .touchUpInside) 29 | button.sizeToFit() 30 | self.view.addSubview(button) 31 | 32 | let button2 = UIButton(type: .custom) 33 | button2.backgroundColor = .red 34 | button2.setTitle("系统裁剪", for: .normal) 35 | button2.frame = CGRect(x: 200, y: 100, width: 60, height: 60) 36 | button2.addTarget(self, action:#selector(action2), for: .touchUpInside) 37 | button2.sizeToFit() 38 | self.view.addSubview(button2) 39 | 40 | let button3 = UIButton(type: .custom) 41 | button3.backgroundColor = .red 42 | button3.setTitle("图片移动,裁剪框不移动", for: .normal) 43 | button3.frame = CGRect(x: 10, y: 200, width: 60, height: 60) 44 | button3.addTarget(self, action:#selector(action3), for: .touchUpInside) 45 | button3.sizeToFit() 46 | self.view.addSubview(button3) 47 | 48 | let button4 = UIButton(type: .custom) 49 | button4.backgroundColor = .red 50 | button4.setTitle("裁剪框移动,图片不动", for: .normal) 51 | button4.frame = CGRect(x: 250, y: 200, width: 60, height: 60) 52 | button4.addTarget(self, action:#selector(action4), for: .touchUpInside) 53 | button4.sizeToFit() 54 | self.view.addSubview(button4) 55 | 56 | KiClipperHelper.sharedInstance.nav = navigationController 57 | KiClipperHelper.sharedInstance.clippedImgSize = self.clippedImageView?.frame.size 58 | KiClipperHelper.sharedInstance.clippedImageHandler = {[weak self]img in 59 | self?.clippedImageView?.image = img 60 | } 61 | 62 | } 63 | 64 | @objc func action1() { //直接系统方法获取图片, 不裁剪, 获取原图 65 | KiClipperHelper.sharedInstance.systemEditing = false 66 | KiClipperHelper.sharedInstance.isSystemType = true 67 | takePhoto() 68 | } 69 | @objc func action2() { //直接系统方法获取图片, 默认系统尺寸, 裁剪图片 70 | KiClipperHelper.sharedInstance.systemEditing = true 71 | KiClipperHelper.sharedInstance.isSystemType = true 72 | takePhoto() 73 | } 74 | @objc func action3() { //自定义裁剪图片, 图片移动, 裁剪框不移动 75 | KiClipperHelper.sharedInstance.clipperType = .Move 76 | KiClipperHelper.sharedInstance.systemEditing = false 77 | KiClipperHelper.sharedInstance.isSystemType = false 78 | takePhoto() 79 | } 80 | @objc func action4() { //自定义裁剪图片, 图片不移动, 裁剪框移动, 及自定义等比缩放大小 81 | KiClipperHelper.sharedInstance.clipperType = .Stay 82 | KiClipperHelper.sharedInstance.systemEditing = false 83 | KiClipperHelper.sharedInstance.isSystemType = false 84 | takePhoto() 85 | } 86 | 87 | func takePhoto() { 88 | 89 | KiClipperHelper.sharedInstance.photoWithSourceType(type: .photoLibrary) //直接打开相册选取图片 90 | 91 | // KiClipperHelper.sharedInstance.photoWithSourceType(type: .camera) //打开相机拍摄照片 92 | 93 | // let sheet = UIActionSheet(title: nil, delegate: self, cancelButtonTitle: "取消", destructiveButtonTitle: nil, otherButtonTitles: "相册", "拍照") 94 | // sheet.show(in: UIApplication.shared.keyWindow!) 95 | } 96 | 97 | func actionSheet(_ actionSheet: UIActionSheet, clickedButtonAt buttonIndex: Int){ 98 | DispatchQueue.main.async { 99 | if buttonIndex == 0 { 100 | //取消 101 | }else if buttonIndex == 1 { 102 | KiClipperHelper.sharedInstance.photoWithSourceType(type: .photoLibrary) 103 | }else if buttonIndex == 2 { 104 | // KiClipperHelper.sharedInstance.photoWithSourceType(type: .camera) //模拟机不支持相机 105 | } 106 | } 107 | } 108 | 109 | override func didReceiveMemoryWarning() { 110 | super.didReceiveMemoryWarning() 111 | // Dispose of any resources that can be recreated. 112 | } 113 | 114 | 115 | } 116 | 117 | -------------------------------------------------------------------------------- /KiClipperImageDemo/KiClipperHelper/KiClipperView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // KiClipperView.swift 3 | // KiClipperImageDemo 4 | // 5 | // Created by mbApple on 2017/11/15. 6 | // Copyright © 2017年 panda誌. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | enum ClipperType { 12 | case Move 13 | case Stay 14 | } 15 | 16 | class KiClipperView: UIView { 17 | 18 | public var resultImgSize:CGSize?{ 19 | didSet{ 20 | self.setClipperView() 21 | } 22 | } 23 | public var type:ClipperType = .Move 24 | public var baseImg:UIImage?{ 25 | didSet{ 26 | var width = baseImg?.size.width ?? 0 27 | var height = baseImg?.size.height ?? 0 28 | if width != self.frame.size.width { 29 | width = self.frame.size.width 30 | } 31 | height = (baseImg?.size.height ?? 0)! / (baseImg?.size.width ?? 0)! * width 32 | if height < (self.clipperView?.frame.size.height ?? 0)! { 33 | height = (self.clipperView?.frame.size.height ?? 0)! 34 | } 35 | width = (baseImg?.size.width ?? 0)! / (baseImg?.size.height ?? 0)! * height 36 | let img = baseImg?.scaledToSize(newSize: CGSize(width: width, height: height), withScale: false) 37 | self.baseImgView?.image = img 38 | self.baseImgView?.frame = CGRect(x: 0, y: 0, width: (img?.size.width)!, height: (img?.size.height)!) 39 | 40 | correctBackImgView() 41 | } 42 | } 43 | private let minWidth:CGFloat = 60 44 | private var clipperView: UIImageView? 45 | 46 | private lazy var baseImgView: UIImageView? = { 47 | let baseImgView = UIImageView() 48 | self.addSubview(baseImgView) 49 | self.sendSubview(toBack: baseImgView) 50 | return baseImgView 51 | }() 52 | private lazy var fillLayer: CAShapeLayer? = { 53 | let fillLayer = CAShapeLayer() 54 | fillLayer.fillRule = kCAFillRuleEvenOdd 55 | fillLayer.fillColor = UIColor.black.cgColor 56 | fillLayer.opacity = 0.5 57 | self.layer.addSublayer(fillLayer) 58 | return fillLayer 59 | }() 60 | private var panTouch:CGPoint? 61 | private var scaleDistance:CGFloat = 0 //缩放距离 62 | 63 | override init(frame: CGRect) { 64 | super.init(frame: frame) 65 | loadSubViews() 66 | } 67 | //MARK Public 68 | public func clipImg() -> UIImage { 69 | let scale = UIScreen.main.scale * (self.baseImgView?.image?.size.width)!/(self.baseImgView?.frame.size.width)! 70 | let rect = self.convert((self.clipperView?.frame)!, to: self.baseImgView) 71 | let rect2 = CGRect(x: rect.origin.x * scale, y: rect.origin.y * scale, width: rect.size.width * scale, height: rect.size.height * scale) 72 | let cgImg = self.baseImgView?.image?.cgImage?.cropping(to: rect2) 73 | let clippedImg = UIImage.init(cgImage: cgImg!) 74 | return clippedImg 75 | } 76 | 77 | private func loadSubViews() { 78 | self.layer.contentsGravity = kCAGravityResizeAspect 79 | } 80 | 81 | private func setClipperView() { 82 | let kscWidth = UIScreen.main.bounds.size.width 83 | let kscHeight = UIScreen.main.bounds.size.height - 64 84 | var width = kscWidth 85 | var height = kscHeight 86 | if (self.resultImgSize?.width)! > ((self.resultImgSize?.height ?? 0)! / height * width) { 87 | height = kscWidth / (self.resultImgSize?.width ?? 0)! * (self.resultImgSize?.height ?? 0)! 88 | }else{ 89 | width = kscHeight / (self.resultImgSize?.height ?? 0)! * (self.resultImgSize?.width ?? 0)! 90 | } 91 | let y = (kscHeight - height)/2 92 | let x = (kscWidth - width)/2 93 | clipperView = UIImageView(frame: CGRect(x: x, y: y, width: width, height: height)) 94 | clipperView?.layer.borderColor = UIColor.white.cgColor 95 | clipperView?.layer.borderWidth = 2 96 | self.addSubview(clipperView!) 97 | 98 | correctFillLayer() 99 | } 100 | 101 | //MARK Touches (注意问题::::) 102 | override func touchesBegan(_ touches: Set, with event: UIEvent?) { 103 | let allTouches = event?.allTouches 104 | switch allTouches?.count { 105 | case 1?: 106 | panTouch = allTouches?.first?.location(in: self) 107 | break 108 | default: 109 | break 110 | } 111 | } 112 | 113 | override func touchesMoved(_ touches: Set, with event: UIEvent?) { 114 | self.willChangeValue(forKey: "crop") 115 | let allTouches = event?.allTouches 116 | switch allTouches?.count { 117 | case 1?: 118 | let touchCurrent = allTouches?.first?.location(in: self) 119 | let x = (touchCurrent?.x ?? 0)! - (panTouch?.x ?? 0)! 120 | let y = (touchCurrent?.y ?? 0)! - (panTouch?.y ?? 0)! 121 | switch type { 122 | case .Move: 123 | self.baseImgView?.center = CGPoint(x: (self.baseImgView?.center.x ?? 0)! + x, y: (self.baseImgView?.center.y ?? 0)! + y) 124 | break 125 | case .Stay: 126 | self.clipperView?.center = CGPoint(x: (self.clipperView?.center.x ?? 0)! + x, y: (self.clipperView?.center.y ?? 0)! + y) 127 | break 128 | } 129 | panTouch = touchCurrent 130 | break 131 | case 2?: 132 | switch type { 133 | case .Move: 134 | self.scaleView(self.baseImgView!, touches: (allTouches! as NSSet).allObjects) 135 | break 136 | case .Stay: 137 | self.scaleView(self.clipperView!, touches: (allTouches! as NSSet).allObjects) 138 | break 139 | } 140 | break 141 | default: 142 | break 143 | } 144 | correctFillLayer() 145 | } 146 | 147 | override func touchesEnded(_ touches: Set, with event: UIEvent?) { 148 | switch type { 149 | case .Move: 150 | correctBackImgView() 151 | break 152 | case .Stay: 153 | correctClipperView() 154 | break 155 | } 156 | } 157 | 158 | //MARK Correct 159 | private func correctBackImgView(){ 160 | var x = self.baseImgView?.frame.origin.x ?? 0 161 | var y = self.baseImgView?.frame.origin.y ?? 0 162 | var height = self.baseImgView?.frame.size.height ?? 0 163 | var width = self.baseImgView?.frame.size.width ?? 0 164 | 165 | if width < (self.clipperView?.frame.size.width ?? 0)! { 166 | width = (self.clipperView?.frame.size.width ?? 0)! 167 | height = width / (self.baseImgView?.frame.size.width ?? 0)! * height 168 | } 169 | if height < (self.clipperView?.frame.size.height ?? 0)! { 170 | height = (self.clipperView?.frame.size.height ?? 0)! 171 | width = height / (self.baseImgView?.frame.size.height ?? 0)! * width 172 | } 173 | 174 | if x > (self.clipperView?.frame.origin.x ?? 0)! { 175 | x = (self.clipperView?.frame.origin.x ?? 0)! 176 | } else if x < ((self.clipperView?.frame.origin.x ?? 0)! + (self.clipperView?.frame.size.width ?? 0)! - width){ 177 | x = (self.clipperView?.frame.origin.x ?? 0)! + (self.clipperView?.frame.size.width ?? 0)! - width 178 | } 179 | 180 | if y > (self.clipperView?.frame.origin.y ?? 0)! { 181 | y = (self.clipperView?.frame.origin.y ?? 0)! 182 | } else if y < (self.clipperView?.frame.origin.y ?? 0)! + (self.clipperView?.frame.size.height ?? 0)! - height { 183 | y = (self.clipperView?.frame.origin.y ?? 0)! + (self.clipperView?.frame.size.height ?? 0)! - height 184 | } 185 | 186 | self.baseImgView?.frame = CGRect(x: x, y: y, width: width, height: height) 187 | } 188 | 189 | private func correctClipperView(){ 190 | var width = self.clipperView?.frame.size.width ?? 0 191 | var height:CGFloat = 0.0 192 | if width < minWidth { 193 | width = minWidth 194 | } 195 | if width > UIScreen.main.bounds.size.width { 196 | width = UIScreen.main.bounds.size.width 197 | } 198 | height = width / (self.resultImgSize?.width ?? 0)! * (self.resultImgSize?.height ?? 0)! 199 | var x = self.clipperView?.frame.origin.x ?? 0 200 | var y = self.clipperView?.frame.origin.y ?? 0 201 | if x < (self.baseImgView?.frame.origin.x ?? 0)! { 202 | x = (self.baseImgView?.frame.origin.x ?? 0)! 203 | } 204 | if x > UIScreen.main.bounds.size.width - width { 205 | x = UIScreen.main.bounds.size.width - width 206 | } 207 | if y < (self.baseImgView?.frame.origin.y ?? 0)! { 208 | y = (self.baseImgView?.frame.origin.y ?? 0)! 209 | } 210 | let tempy = (self.baseImgView?.frame.origin.y ?? 0)! + (self.baseImgView?.frame.size.height ?? 0)! - (self.clipperView?.frame.size.height ?? 0)! 211 | if y > tempy{ 212 | y = (self.baseImgView?.frame.origin.y ?? 0)! + (self.baseImgView?.frame.size.height ?? 0)! - (self.clipperView?.frame.size.height ?? 0)! 213 | } 214 | self.clipperView?.frame = CGRect(x: x, y: y, width: width, height: height) 215 | correctFillLayer() 216 | } 217 | 218 | private func correctFillLayer() { 219 | let path = UIBezierPath.init(roundedRect: self.bounds, cornerRadius: 0) 220 | let circlePath = UIBezierPath.init(roundedRect: (clipperView?.frame)!, cornerRadius: 0) 221 | path.append(circlePath) 222 | path.usesEvenOddFillRule = true 223 | self.fillLayer?.path = path.cgPath 224 | } 225 | 226 | //MARK Correct 227 | private func scaleView(_ view:UIView,touches:Array){ 228 | let touch1 = (touches[0] as AnyObject).location(in: self) 229 | let touch2 = (touches[1] as AnyObject).location(in: self) 230 | let distance = self.distanceBetweenTwoPoints(touch1, toPoint: touch2) 231 | if scaleDistance > 0 { 232 | var imgFrame = view.frame 233 | if distance > scaleDistance + 2{ 234 | imgFrame.size.width += 10 235 | scaleDistance = distance 236 | } 237 | if distance < scaleDistance - 2 { 238 | imgFrame.size.width -= 10 239 | scaleDistance = distance 240 | } 241 | if type == .Stay{ //图片不动 242 | imgFrame.size.height = view.frame.size.height * imgFrame.size.width / view.frame.size.width 243 | let mainWidth = UIScreen.main.bounds.size.width 244 | let imgWidth = imgFrame.size.width > mainWidth ? mainWidth : imgFrame.size.width 245 | let imgHeight = imgWidth * (resultImgSize?.height ?? 0) / (resultImgSize?.width == 0 ? 1 : (resultImgSize?.width ?? 1)!) 246 | let addwidth = imgWidth - view.frame.size.width 247 | let addheight = imgHeight - view.frame.size.height 248 | if imgHeight != 0 && imgWidth != 0{ 249 | view.frame = CGRect(x:imgFrame.origin.x - addwidth/2.0, y: imgFrame.origin.y - addheight/2.0, width: imgWidth, height: imgHeight) 250 | } 251 | }else{ //图片移动 252 | imgFrame.size.height = view.frame.size.height * imgFrame.size.width / view.frame.size.width 253 | let addwidth = imgFrame.size.width - view.frame.size.width 254 | let addheight = imgFrame.size.height - view.frame.size.height 255 | let cripWidth = imgFrame.size.width - (clipperView?.frame.width ?? 0) 256 | let cripHeight = imgFrame.size.height - (clipperView?.frame.height ?? 0) 257 | 258 | if imgFrame.size.width != 0 && imgFrame.size.height != 0 && cripWidth > -5 && cripHeight > -5 { 259 | view.frame = CGRect(x:imgFrame.origin.x - addwidth/2.0, y: imgFrame.origin.y - addheight/2.0, width: imgFrame.width, height: imgFrame.height) 260 | } 261 | } 262 | }else{ 263 | scaleDistance = distance 264 | } 265 | } 266 | 267 | private func distanceBetweenTwoPoints(_ fromPoint:CGPoint,toPoint:CGPoint) -> CGFloat { 268 | let x = toPoint.x - fromPoint.x 269 | let y = toPoint.y - fromPoint.y 270 | return CGFloat(sqrtf(Float(x * x + y * y))) 271 | } 272 | 273 | 274 | required init?(coder aDecoder: NSCoder) { 275 | fatalError("init(coder:) has not been implemented") 276 | } 277 | /* 278 | // Only override draw() if you perform custom drawing. 279 | // An empty implementation adversely affects performance during animation. 280 | override func draw(_ rect: CGRect) { 281 | // Drawing code 282 | } 283 | */ 284 | } 285 | 286 | extension UIImage{ 287 | func scaledToSize(newSize:CGSize,withScale:Bool) -> UIImage { 288 | var scale:CGFloat = 1 289 | if withScale { 290 | scale = UIScreen.main.scale 291 | } 292 | let mynewSize = CGSize(width: newSize.width * scale, height: newSize.height * scale) 293 | UIGraphicsBeginImageContextWithOptions(mynewSize, false, 0) 294 | self.draw(in: CGRect(origin: CGPoint.zero, size: mynewSize)) 295 | let newImage = UIGraphicsGetImageFromCurrentImageContext() 296 | UIGraphicsEndImageContext() 297 | return newImage ?? UIImage() 298 | } 299 | } 300 | -------------------------------------------------------------------------------- /KiClipperImageDemo/KiClipperImageDemo.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 48; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 4C1D7FF71FBBE88800B86C89 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4C1D7FF61FBBE88800B86C89 /* AppDelegate.swift */; }; 11 | 4C1D7FF91FBBE88800B86C89 /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4C1D7FF81FBBE88800B86C89 /* ViewController.swift */; }; 12 | 4C1D7FFC1FBBE88800B86C89 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 4C1D7FFA1FBBE88800B86C89 /* Main.storyboard */; }; 13 | 4C1D7FFE1FBBE88800B86C89 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 4C1D7FFD1FBBE88800B86C89 /* Assets.xcassets */; }; 14 | 4C1D80011FBBE88800B86C89 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 4C1D7FFF1FBBE88800B86C89 /* LaunchScreen.storyboard */; }; 15 | 4C1D800C1FBBE88800B86C89 /* KiClipperImageDemoTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4C1D800B1FBBE88800B86C89 /* KiClipperImageDemoTests.swift */; }; 16 | 4C1D80171FBBE88800B86C89 /* KiClipperImageDemoUITests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4C1D80161FBBE88800B86C89 /* KiClipperImageDemoUITests.swift */; }; 17 | 4C1D80331FBBE9EE00B86C89 /* KiClipperView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4C1D80321FBBE9EE00B86C89 /* KiClipperView.swift */; }; 18 | 4C1D80351FBC247B00B86C89 /* KiClipperHelper.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4C1D80341FBC247B00B86C89 /* KiClipperHelper.swift */; }; 19 | 4C1D80391FBC2F6C00B86C89 /* KiImageClipperViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4C1D80381FBC2F6C00B86C89 /* KiImageClipperViewController.swift */; }; 20 | /* End PBXBuildFile section */ 21 | 22 | /* Begin PBXContainerItemProxy section */ 23 | 4C1D80081FBBE88800B86C89 /* PBXContainerItemProxy */ = { 24 | isa = PBXContainerItemProxy; 25 | containerPortal = 4C1D7FEB1FBBE88700B86C89 /* Project object */; 26 | proxyType = 1; 27 | remoteGlobalIDString = 4C1D7FF21FBBE88800B86C89; 28 | remoteInfo = KiClipperImageDemo; 29 | }; 30 | 4C1D80131FBBE88800B86C89 /* PBXContainerItemProxy */ = { 31 | isa = PBXContainerItemProxy; 32 | containerPortal = 4C1D7FEB1FBBE88700B86C89 /* Project object */; 33 | proxyType = 1; 34 | remoteGlobalIDString = 4C1D7FF21FBBE88800B86C89; 35 | remoteInfo = KiClipperImageDemo; 36 | }; 37 | /* End PBXContainerItemProxy section */ 38 | 39 | /* Begin PBXFileReference section */ 40 | 4C1D7FF31FBBE88800B86C89 /* KiClipperImageDemo.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = KiClipperImageDemo.app; sourceTree = BUILT_PRODUCTS_DIR; }; 41 | 4C1D7FF61FBBE88800B86C89 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; 42 | 4C1D7FF81FBBE88800B86C89 /* ViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewController.swift; sourceTree = ""; }; 43 | 4C1D7FFB1FBBE88800B86C89 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; 44 | 4C1D7FFD1FBBE88800B86C89 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 45 | 4C1D80001FBBE88800B86C89 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; 46 | 4C1D80021FBBE88800B86C89 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 47 | 4C1D80071FBBE88800B86C89 /* KiClipperImageDemoTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = KiClipperImageDemoTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 48 | 4C1D800B1FBBE88800B86C89 /* KiClipperImageDemoTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = KiClipperImageDemoTests.swift; sourceTree = ""; }; 49 | 4C1D800D1FBBE88800B86C89 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 50 | 4C1D80121FBBE88800B86C89 /* KiClipperImageDemoUITests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = KiClipperImageDemoUITests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 51 | 4C1D80161FBBE88800B86C89 /* KiClipperImageDemoUITests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = KiClipperImageDemoUITests.swift; sourceTree = ""; }; 52 | 4C1D80181FBBE88800B86C89 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 53 | 4C1D80321FBBE9EE00B86C89 /* KiClipperView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = KiClipperView.swift; sourceTree = ""; }; 54 | 4C1D80341FBC247B00B86C89 /* KiClipperHelper.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = KiClipperHelper.swift; sourceTree = ""; }; 55 | 4C1D80381FBC2F6C00B86C89 /* KiImageClipperViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = KiImageClipperViewController.swift; sourceTree = ""; }; 56 | /* End PBXFileReference section */ 57 | 58 | /* Begin PBXFrameworksBuildPhase section */ 59 | 4C1D7FF01FBBE88800B86C89 /* Frameworks */ = { 60 | isa = PBXFrameworksBuildPhase; 61 | buildActionMask = 2147483647; 62 | files = ( 63 | ); 64 | runOnlyForDeploymentPostprocessing = 0; 65 | }; 66 | 4C1D80041FBBE88800B86C89 /* Frameworks */ = { 67 | isa = PBXFrameworksBuildPhase; 68 | buildActionMask = 2147483647; 69 | files = ( 70 | ); 71 | runOnlyForDeploymentPostprocessing = 0; 72 | }; 73 | 4C1D800F1FBBE88800B86C89 /* Frameworks */ = { 74 | isa = PBXFrameworksBuildPhase; 75 | buildActionMask = 2147483647; 76 | files = ( 77 | ); 78 | runOnlyForDeploymentPostprocessing = 0; 79 | }; 80 | /* End PBXFrameworksBuildPhase section */ 81 | 82 | /* Begin PBXGroup section */ 83 | 4C1D7FEA1FBBE88700B86C89 = { 84 | isa = PBXGroup; 85 | children = ( 86 | 4C1D80311FBBE9D800B86C89 /* KiClipperHelper */, 87 | 4C1D7FF51FBBE88800B86C89 /* KiClipperImageDemo */, 88 | 4C1D800A1FBBE88800B86C89 /* KiClipperImageDemoTests */, 89 | 4C1D80151FBBE88800B86C89 /* KiClipperImageDemoUITests */, 90 | 4C1D7FF41FBBE88800B86C89 /* Products */, 91 | ); 92 | sourceTree = ""; 93 | }; 94 | 4C1D7FF41FBBE88800B86C89 /* Products */ = { 95 | isa = PBXGroup; 96 | children = ( 97 | 4C1D7FF31FBBE88800B86C89 /* KiClipperImageDemo.app */, 98 | 4C1D80071FBBE88800B86C89 /* KiClipperImageDemoTests.xctest */, 99 | 4C1D80121FBBE88800B86C89 /* KiClipperImageDemoUITests.xctest */, 100 | ); 101 | name = Products; 102 | sourceTree = ""; 103 | }; 104 | 4C1D7FF51FBBE88800B86C89 /* KiClipperImageDemo */ = { 105 | isa = PBXGroup; 106 | children = ( 107 | 4C1D7FF61FBBE88800B86C89 /* AppDelegate.swift */, 108 | 4C1D7FF81FBBE88800B86C89 /* ViewController.swift */, 109 | 4C1D7FFA1FBBE88800B86C89 /* Main.storyboard */, 110 | 4C1D7FFD1FBBE88800B86C89 /* Assets.xcassets */, 111 | 4C1D7FFF1FBBE88800B86C89 /* LaunchScreen.storyboard */, 112 | 4C1D80021FBBE88800B86C89 /* Info.plist */, 113 | ); 114 | path = KiClipperImageDemo; 115 | sourceTree = ""; 116 | }; 117 | 4C1D800A1FBBE88800B86C89 /* KiClipperImageDemoTests */ = { 118 | isa = PBXGroup; 119 | children = ( 120 | 4C1D800B1FBBE88800B86C89 /* KiClipperImageDemoTests.swift */, 121 | 4C1D800D1FBBE88800B86C89 /* Info.plist */, 122 | ); 123 | path = KiClipperImageDemoTests; 124 | sourceTree = ""; 125 | }; 126 | 4C1D80151FBBE88800B86C89 /* KiClipperImageDemoUITests */ = { 127 | isa = PBXGroup; 128 | children = ( 129 | 4C1D80161FBBE88800B86C89 /* KiClipperImageDemoUITests.swift */, 130 | 4C1D80181FBBE88800B86C89 /* Info.plist */, 131 | ); 132 | path = KiClipperImageDemoUITests; 133 | sourceTree = ""; 134 | }; 135 | 4C1D80311FBBE9D800B86C89 /* KiClipperHelper */ = { 136 | isa = PBXGroup; 137 | children = ( 138 | 4C1D80321FBBE9EE00B86C89 /* KiClipperView.swift */, 139 | 4C1D80341FBC247B00B86C89 /* KiClipperHelper.swift */, 140 | 4C1D80381FBC2F6C00B86C89 /* KiImageClipperViewController.swift */, 141 | ); 142 | path = KiClipperHelper; 143 | sourceTree = ""; 144 | }; 145 | /* End PBXGroup section */ 146 | 147 | /* Begin PBXNativeTarget section */ 148 | 4C1D7FF21FBBE88800B86C89 /* KiClipperImageDemo */ = { 149 | isa = PBXNativeTarget; 150 | buildConfigurationList = 4C1D801B1FBBE88800B86C89 /* Build configuration list for PBXNativeTarget "KiClipperImageDemo" */; 151 | buildPhases = ( 152 | 4C1D7FEF1FBBE88800B86C89 /* Sources */, 153 | 4C1D7FF01FBBE88800B86C89 /* Frameworks */, 154 | 4C1D7FF11FBBE88800B86C89 /* Resources */, 155 | ); 156 | buildRules = ( 157 | ); 158 | dependencies = ( 159 | ); 160 | name = KiClipperImageDemo; 161 | productName = KiClipperImageDemo; 162 | productReference = 4C1D7FF31FBBE88800B86C89 /* KiClipperImageDemo.app */; 163 | productType = "com.apple.product-type.application"; 164 | }; 165 | 4C1D80061FBBE88800B86C89 /* KiClipperImageDemoTests */ = { 166 | isa = PBXNativeTarget; 167 | buildConfigurationList = 4C1D801E1FBBE88800B86C89 /* Build configuration list for PBXNativeTarget "KiClipperImageDemoTests" */; 168 | buildPhases = ( 169 | 4C1D80031FBBE88800B86C89 /* Sources */, 170 | 4C1D80041FBBE88800B86C89 /* Frameworks */, 171 | 4C1D80051FBBE88800B86C89 /* Resources */, 172 | ); 173 | buildRules = ( 174 | ); 175 | dependencies = ( 176 | 4C1D80091FBBE88800B86C89 /* PBXTargetDependency */, 177 | ); 178 | name = KiClipperImageDemoTests; 179 | productName = KiClipperImageDemoTests; 180 | productReference = 4C1D80071FBBE88800B86C89 /* KiClipperImageDemoTests.xctest */; 181 | productType = "com.apple.product-type.bundle.unit-test"; 182 | }; 183 | 4C1D80111FBBE88800B86C89 /* KiClipperImageDemoUITests */ = { 184 | isa = PBXNativeTarget; 185 | buildConfigurationList = 4C1D80211FBBE88800B86C89 /* Build configuration list for PBXNativeTarget "KiClipperImageDemoUITests" */; 186 | buildPhases = ( 187 | 4C1D800E1FBBE88800B86C89 /* Sources */, 188 | 4C1D800F1FBBE88800B86C89 /* Frameworks */, 189 | 4C1D80101FBBE88800B86C89 /* Resources */, 190 | ); 191 | buildRules = ( 192 | ); 193 | dependencies = ( 194 | 4C1D80141FBBE88800B86C89 /* PBXTargetDependency */, 195 | ); 196 | name = KiClipperImageDemoUITests; 197 | productName = KiClipperImageDemoUITests; 198 | productReference = 4C1D80121FBBE88800B86C89 /* KiClipperImageDemoUITests.xctest */; 199 | productType = "com.apple.product-type.bundle.ui-testing"; 200 | }; 201 | /* End PBXNativeTarget section */ 202 | 203 | /* Begin PBXProject section */ 204 | 4C1D7FEB1FBBE88700B86C89 /* Project object */ = { 205 | isa = PBXProject; 206 | attributes = { 207 | LastSwiftUpdateCheck = 0900; 208 | LastUpgradeCheck = 0900; 209 | ORGANIZATIONNAME = "panda誌"; 210 | TargetAttributes = { 211 | 4C1D7FF21FBBE88800B86C89 = { 212 | CreatedOnToolsVersion = 9.0; 213 | ProvisioningStyle = Automatic; 214 | }; 215 | 4C1D80061FBBE88800B86C89 = { 216 | CreatedOnToolsVersion = 9.0; 217 | ProvisioningStyle = Automatic; 218 | TestTargetID = 4C1D7FF21FBBE88800B86C89; 219 | }; 220 | 4C1D80111FBBE88800B86C89 = { 221 | CreatedOnToolsVersion = 9.0; 222 | ProvisioningStyle = Automatic; 223 | TestTargetID = 4C1D7FF21FBBE88800B86C89; 224 | }; 225 | }; 226 | }; 227 | buildConfigurationList = 4C1D7FEE1FBBE88700B86C89 /* Build configuration list for PBXProject "KiClipperImageDemo" */; 228 | compatibilityVersion = "Xcode 8.0"; 229 | developmentRegion = en; 230 | hasScannedForEncodings = 0; 231 | knownRegions = ( 232 | en, 233 | Base, 234 | ); 235 | mainGroup = 4C1D7FEA1FBBE88700B86C89; 236 | productRefGroup = 4C1D7FF41FBBE88800B86C89 /* Products */; 237 | projectDirPath = ""; 238 | projectRoot = ""; 239 | targets = ( 240 | 4C1D7FF21FBBE88800B86C89 /* KiClipperImageDemo */, 241 | 4C1D80061FBBE88800B86C89 /* KiClipperImageDemoTests */, 242 | 4C1D80111FBBE88800B86C89 /* KiClipperImageDemoUITests */, 243 | ); 244 | }; 245 | /* End PBXProject section */ 246 | 247 | /* Begin PBXResourcesBuildPhase section */ 248 | 4C1D7FF11FBBE88800B86C89 /* Resources */ = { 249 | isa = PBXResourcesBuildPhase; 250 | buildActionMask = 2147483647; 251 | files = ( 252 | 4C1D80011FBBE88800B86C89 /* LaunchScreen.storyboard in Resources */, 253 | 4C1D7FFE1FBBE88800B86C89 /* Assets.xcassets in Resources */, 254 | 4C1D7FFC1FBBE88800B86C89 /* Main.storyboard in Resources */, 255 | ); 256 | runOnlyForDeploymentPostprocessing = 0; 257 | }; 258 | 4C1D80051FBBE88800B86C89 /* Resources */ = { 259 | isa = PBXResourcesBuildPhase; 260 | buildActionMask = 2147483647; 261 | files = ( 262 | ); 263 | runOnlyForDeploymentPostprocessing = 0; 264 | }; 265 | 4C1D80101FBBE88800B86C89 /* Resources */ = { 266 | isa = PBXResourcesBuildPhase; 267 | buildActionMask = 2147483647; 268 | files = ( 269 | ); 270 | runOnlyForDeploymentPostprocessing = 0; 271 | }; 272 | /* End PBXResourcesBuildPhase section */ 273 | 274 | /* Begin PBXSourcesBuildPhase section */ 275 | 4C1D7FEF1FBBE88800B86C89 /* Sources */ = { 276 | isa = PBXSourcesBuildPhase; 277 | buildActionMask = 2147483647; 278 | files = ( 279 | 4C1D7FF91FBBE88800B86C89 /* ViewController.swift in Sources */, 280 | 4C1D7FF71FBBE88800B86C89 /* AppDelegate.swift in Sources */, 281 | 4C1D80391FBC2F6C00B86C89 /* KiImageClipperViewController.swift in Sources */, 282 | 4C1D80331FBBE9EE00B86C89 /* KiClipperView.swift in Sources */, 283 | 4C1D80351FBC247B00B86C89 /* KiClipperHelper.swift in Sources */, 284 | ); 285 | runOnlyForDeploymentPostprocessing = 0; 286 | }; 287 | 4C1D80031FBBE88800B86C89 /* Sources */ = { 288 | isa = PBXSourcesBuildPhase; 289 | buildActionMask = 2147483647; 290 | files = ( 291 | 4C1D800C1FBBE88800B86C89 /* KiClipperImageDemoTests.swift in Sources */, 292 | ); 293 | runOnlyForDeploymentPostprocessing = 0; 294 | }; 295 | 4C1D800E1FBBE88800B86C89 /* Sources */ = { 296 | isa = PBXSourcesBuildPhase; 297 | buildActionMask = 2147483647; 298 | files = ( 299 | 4C1D80171FBBE88800B86C89 /* KiClipperImageDemoUITests.swift in Sources */, 300 | ); 301 | runOnlyForDeploymentPostprocessing = 0; 302 | }; 303 | /* End PBXSourcesBuildPhase section */ 304 | 305 | /* Begin PBXTargetDependency section */ 306 | 4C1D80091FBBE88800B86C89 /* PBXTargetDependency */ = { 307 | isa = PBXTargetDependency; 308 | target = 4C1D7FF21FBBE88800B86C89 /* KiClipperImageDemo */; 309 | targetProxy = 4C1D80081FBBE88800B86C89 /* PBXContainerItemProxy */; 310 | }; 311 | 4C1D80141FBBE88800B86C89 /* PBXTargetDependency */ = { 312 | isa = PBXTargetDependency; 313 | target = 4C1D7FF21FBBE88800B86C89 /* KiClipperImageDemo */; 314 | targetProxy = 4C1D80131FBBE88800B86C89 /* PBXContainerItemProxy */; 315 | }; 316 | /* End PBXTargetDependency section */ 317 | 318 | /* Begin PBXVariantGroup section */ 319 | 4C1D7FFA1FBBE88800B86C89 /* Main.storyboard */ = { 320 | isa = PBXVariantGroup; 321 | children = ( 322 | 4C1D7FFB1FBBE88800B86C89 /* Base */, 323 | ); 324 | name = Main.storyboard; 325 | sourceTree = ""; 326 | }; 327 | 4C1D7FFF1FBBE88800B86C89 /* LaunchScreen.storyboard */ = { 328 | isa = PBXVariantGroup; 329 | children = ( 330 | 4C1D80001FBBE88800B86C89 /* Base */, 331 | ); 332 | name = LaunchScreen.storyboard; 333 | sourceTree = ""; 334 | }; 335 | /* End PBXVariantGroup section */ 336 | 337 | /* Begin XCBuildConfiguration section */ 338 | 4C1D80191FBBE88800B86C89 /* Debug */ = { 339 | isa = XCBuildConfiguration; 340 | buildSettings = { 341 | ALWAYS_SEARCH_USER_PATHS = NO; 342 | CLANG_ANALYZER_NONNULL = YES; 343 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 344 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; 345 | CLANG_CXX_LIBRARY = "libc++"; 346 | CLANG_ENABLE_MODULES = YES; 347 | CLANG_ENABLE_OBJC_ARC = YES; 348 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 349 | CLANG_WARN_BOOL_CONVERSION = YES; 350 | CLANG_WARN_COMMA = YES; 351 | CLANG_WARN_CONSTANT_CONVERSION = YES; 352 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 353 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 354 | CLANG_WARN_EMPTY_BODY = YES; 355 | CLANG_WARN_ENUM_CONVERSION = YES; 356 | CLANG_WARN_INFINITE_RECURSION = YES; 357 | CLANG_WARN_INT_CONVERSION = YES; 358 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 359 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 360 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 361 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 362 | CLANG_WARN_STRICT_PROTOTYPES = YES; 363 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 364 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 365 | CLANG_WARN_UNREACHABLE_CODE = YES; 366 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 367 | CODE_SIGN_IDENTITY = "iPhone Developer"; 368 | COPY_PHASE_STRIP = NO; 369 | DEBUG_INFORMATION_FORMAT = dwarf; 370 | ENABLE_STRICT_OBJC_MSGSEND = YES; 371 | ENABLE_TESTABILITY = YES; 372 | GCC_C_LANGUAGE_STANDARD = gnu11; 373 | GCC_DYNAMIC_NO_PIC = NO; 374 | GCC_NO_COMMON_BLOCKS = YES; 375 | GCC_OPTIMIZATION_LEVEL = 0; 376 | GCC_PREPROCESSOR_DEFINITIONS = ( 377 | "DEBUG=1", 378 | "$(inherited)", 379 | ); 380 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 381 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 382 | GCC_WARN_UNDECLARED_SELECTOR = YES; 383 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 384 | GCC_WARN_UNUSED_FUNCTION = YES; 385 | GCC_WARN_UNUSED_VARIABLE = YES; 386 | IPHONEOS_DEPLOYMENT_TARGET = 11.0; 387 | MTL_ENABLE_DEBUG_INFO = YES; 388 | ONLY_ACTIVE_ARCH = YES; 389 | SDKROOT = iphoneos; 390 | SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; 391 | SWIFT_OPTIMIZATION_LEVEL = "-Onone"; 392 | }; 393 | name = Debug; 394 | }; 395 | 4C1D801A1FBBE88800B86C89 /* Release */ = { 396 | isa = XCBuildConfiguration; 397 | buildSettings = { 398 | ALWAYS_SEARCH_USER_PATHS = NO; 399 | CLANG_ANALYZER_NONNULL = YES; 400 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 401 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; 402 | CLANG_CXX_LIBRARY = "libc++"; 403 | CLANG_ENABLE_MODULES = YES; 404 | CLANG_ENABLE_OBJC_ARC = YES; 405 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 406 | CLANG_WARN_BOOL_CONVERSION = YES; 407 | CLANG_WARN_COMMA = YES; 408 | CLANG_WARN_CONSTANT_CONVERSION = YES; 409 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 410 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 411 | CLANG_WARN_EMPTY_BODY = YES; 412 | CLANG_WARN_ENUM_CONVERSION = YES; 413 | CLANG_WARN_INFINITE_RECURSION = YES; 414 | CLANG_WARN_INT_CONVERSION = YES; 415 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 416 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 417 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 418 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 419 | CLANG_WARN_STRICT_PROTOTYPES = YES; 420 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 421 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 422 | CLANG_WARN_UNREACHABLE_CODE = YES; 423 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 424 | CODE_SIGN_IDENTITY = "iPhone Developer"; 425 | COPY_PHASE_STRIP = NO; 426 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 427 | ENABLE_NS_ASSERTIONS = NO; 428 | ENABLE_STRICT_OBJC_MSGSEND = YES; 429 | GCC_C_LANGUAGE_STANDARD = gnu11; 430 | GCC_NO_COMMON_BLOCKS = YES; 431 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 432 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 433 | GCC_WARN_UNDECLARED_SELECTOR = YES; 434 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 435 | GCC_WARN_UNUSED_FUNCTION = YES; 436 | GCC_WARN_UNUSED_VARIABLE = YES; 437 | IPHONEOS_DEPLOYMENT_TARGET = 11.0; 438 | MTL_ENABLE_DEBUG_INFO = NO; 439 | SDKROOT = iphoneos; 440 | SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; 441 | VALIDATE_PRODUCT = YES; 442 | }; 443 | name = Release; 444 | }; 445 | 4C1D801C1FBBE88800B86C89 /* Debug */ = { 446 | isa = XCBuildConfiguration; 447 | buildSettings = { 448 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 449 | CODE_SIGN_STYLE = Automatic; 450 | DEVELOPMENT_TEAM = ZXV6VE2UUN; 451 | INFOPLIST_FILE = KiClipperImageDemo/Info.plist; 452 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 453 | PRODUCT_BUNDLE_IDENTIFIER = XXXXXX.KiClipperImageDemo; 454 | PRODUCT_NAME = "$(TARGET_NAME)"; 455 | SWIFT_VERSION = 4.0; 456 | TARGETED_DEVICE_FAMILY = "1,2"; 457 | }; 458 | name = Debug; 459 | }; 460 | 4C1D801D1FBBE88800B86C89 /* Release */ = { 461 | isa = XCBuildConfiguration; 462 | buildSettings = { 463 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 464 | CODE_SIGN_STYLE = Automatic; 465 | DEVELOPMENT_TEAM = ZXV6VE2UUN; 466 | INFOPLIST_FILE = KiClipperImageDemo/Info.plist; 467 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 468 | PRODUCT_BUNDLE_IDENTIFIER = XXXXXX.KiClipperImageDemo; 469 | PRODUCT_NAME = "$(TARGET_NAME)"; 470 | SWIFT_VERSION = 4.0; 471 | TARGETED_DEVICE_FAMILY = "1,2"; 472 | }; 473 | name = Release; 474 | }; 475 | 4C1D801F1FBBE88800B86C89 /* Debug */ = { 476 | isa = XCBuildConfiguration; 477 | buildSettings = { 478 | ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; 479 | BUNDLE_LOADER = "$(TEST_HOST)"; 480 | CODE_SIGN_STYLE = Automatic; 481 | DEVELOPMENT_TEAM = 7R27LC3TJ9; 482 | INFOPLIST_FILE = KiClipperImageDemoTests/Info.plist; 483 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 484 | PRODUCT_BUNDLE_IDENTIFIER = XXXXXX.KiClipperImageDemoTests; 485 | PRODUCT_NAME = "$(TARGET_NAME)"; 486 | SWIFT_VERSION = 4.0; 487 | TARGETED_DEVICE_FAMILY = "1,2"; 488 | TEST_HOST = "$(BUILT_PRODUCTS_DIR)/KiClipperImageDemo.app/KiClipperImageDemo"; 489 | }; 490 | name = Debug; 491 | }; 492 | 4C1D80201FBBE88800B86C89 /* Release */ = { 493 | isa = XCBuildConfiguration; 494 | buildSettings = { 495 | ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; 496 | BUNDLE_LOADER = "$(TEST_HOST)"; 497 | CODE_SIGN_STYLE = Automatic; 498 | DEVELOPMENT_TEAM = 7R27LC3TJ9; 499 | INFOPLIST_FILE = KiClipperImageDemoTests/Info.plist; 500 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 501 | PRODUCT_BUNDLE_IDENTIFIER = XXXXXX.KiClipperImageDemoTests; 502 | PRODUCT_NAME = "$(TARGET_NAME)"; 503 | SWIFT_VERSION = 4.0; 504 | TARGETED_DEVICE_FAMILY = "1,2"; 505 | TEST_HOST = "$(BUILT_PRODUCTS_DIR)/KiClipperImageDemo.app/KiClipperImageDemo"; 506 | }; 507 | name = Release; 508 | }; 509 | 4C1D80221FBBE88800B86C89 /* Debug */ = { 510 | isa = XCBuildConfiguration; 511 | buildSettings = { 512 | ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; 513 | CODE_SIGN_STYLE = Automatic; 514 | DEVELOPMENT_TEAM = 7R27LC3TJ9; 515 | INFOPLIST_FILE = KiClipperImageDemoUITests/Info.plist; 516 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 517 | PRODUCT_BUNDLE_IDENTIFIER = XXXXXX.KiClipperImageDemoUITests; 518 | PRODUCT_NAME = "$(TARGET_NAME)"; 519 | SWIFT_VERSION = 4.0; 520 | TARGETED_DEVICE_FAMILY = "1,2"; 521 | TEST_TARGET_NAME = KiClipperImageDemo; 522 | }; 523 | name = Debug; 524 | }; 525 | 4C1D80231FBBE88800B86C89 /* Release */ = { 526 | isa = XCBuildConfiguration; 527 | buildSettings = { 528 | ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; 529 | CODE_SIGN_STYLE = Automatic; 530 | DEVELOPMENT_TEAM = 7R27LC3TJ9; 531 | INFOPLIST_FILE = KiClipperImageDemoUITests/Info.plist; 532 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 533 | PRODUCT_BUNDLE_IDENTIFIER = XXXXXX.KiClipperImageDemoUITests; 534 | PRODUCT_NAME = "$(TARGET_NAME)"; 535 | SWIFT_VERSION = 4.0; 536 | TARGETED_DEVICE_FAMILY = "1,2"; 537 | TEST_TARGET_NAME = KiClipperImageDemo; 538 | }; 539 | name = Release; 540 | }; 541 | /* End XCBuildConfiguration section */ 542 | 543 | /* Begin XCConfigurationList section */ 544 | 4C1D7FEE1FBBE88700B86C89 /* Build configuration list for PBXProject "KiClipperImageDemo" */ = { 545 | isa = XCConfigurationList; 546 | buildConfigurations = ( 547 | 4C1D80191FBBE88800B86C89 /* Debug */, 548 | 4C1D801A1FBBE88800B86C89 /* Release */, 549 | ); 550 | defaultConfigurationIsVisible = 0; 551 | defaultConfigurationName = Release; 552 | }; 553 | 4C1D801B1FBBE88800B86C89 /* Build configuration list for PBXNativeTarget "KiClipperImageDemo" */ = { 554 | isa = XCConfigurationList; 555 | buildConfigurations = ( 556 | 4C1D801C1FBBE88800B86C89 /* Debug */, 557 | 4C1D801D1FBBE88800B86C89 /* Release */, 558 | ); 559 | defaultConfigurationIsVisible = 0; 560 | defaultConfigurationName = Release; 561 | }; 562 | 4C1D801E1FBBE88800B86C89 /* Build configuration list for PBXNativeTarget "KiClipperImageDemoTests" */ = { 563 | isa = XCConfigurationList; 564 | buildConfigurations = ( 565 | 4C1D801F1FBBE88800B86C89 /* Debug */, 566 | 4C1D80201FBBE88800B86C89 /* Release */, 567 | ); 568 | defaultConfigurationIsVisible = 0; 569 | defaultConfigurationName = Release; 570 | }; 571 | 4C1D80211FBBE88800B86C89 /* Build configuration list for PBXNativeTarget "KiClipperImageDemoUITests" */ = { 572 | isa = XCConfigurationList; 573 | buildConfigurations = ( 574 | 4C1D80221FBBE88800B86C89 /* Debug */, 575 | 4C1D80231FBBE88800B86C89 /* Release */, 576 | ); 577 | defaultConfigurationIsVisible = 0; 578 | defaultConfigurationName = Release; 579 | }; 580 | /* End XCConfigurationList section */ 581 | }; 582 | rootObject = 4C1D7FEB1FBBE88700B86C89 /* Project object */; 583 | } 584 | --------------------------------------------------------------------------------