diff --git a/CHANGELOG.md b/CHANGELOG.md index cd9865e..dc596c4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,8 @@ #### Changes +* Swift 3.0 + ## v1.2.0 #### Changes diff --git a/Example/Example.xcodeproj/project.pbxproj b/Example/Example.xcodeproj/project.pbxproj index e81455b..f3152d9 100644 --- a/Example/Example.xcodeproj/project.pbxproj +++ b/Example/Example.xcodeproj/project.pbxproj @@ -187,7 +187,7 @@ isa = PBXProject; attributes = { LastSwiftUpdateCheck = 0720; - LastUpgradeCheck = 0720; + LastUpgradeCheck = 0800; ORGANIZATIONNAME = "Polydice, Inc."; TargetAttributes = { B548C5C11C8E91B0009D5AEE = { @@ -269,7 +269,7 @@ ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; - shellScript = "diff \"${PODS_ROOT}/../Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [[ $? != 0 ]] ; then\n cat << EOM\nerror: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\nEOM\n exit 1\nfi\n"; + shellScript = "diff \"${PODS_ROOT}/../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"; showEnvVarsInLog = 0; }; B5C50ADD1C917F4A0059032B /* Swift Lint */ = { @@ -359,11 +359,12 @@ B548C5C91C8E91B0009D5AEE /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { + ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = "$(inherited)"; INFOPLIST_FILE = ICInputAccessoryUITests/Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = com.polydice.ICInputAccessoryUITests; PRODUCT_NAME = "$(TARGET_NAME)"; - SWIFT_VERSION = 2.3; + SWIFT_VERSION = 3.0; TEST_TARGET_NAME = Example; USES_XCTRUNNER = YES; }; @@ -372,11 +373,13 @@ B548C5CA1C8E91B0009D5AEE /* Release */ = { isa = XCBuildConfiguration; buildSettings = { + ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = "$(inherited)"; INFOPLIST_FILE = ICInputAccessoryUITests/Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = com.polydice.ICInputAccessoryUITests; PRODUCT_NAME = "$(TARGET_NAME)"; - SWIFT_VERSION = 2.3; + SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; + SWIFT_VERSION = 3.0; TEST_TARGET_NAME = Example; USES_XCTRUNNER = YES; }; @@ -385,6 +388,7 @@ B5E9F90B1C8D3B6E00443DC7 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { + ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; ALWAYS_SEARCH_USER_PATHS = NO; CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_CXX_LIBRARY = "libc++"; @@ -395,8 +399,10 @@ CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; CLANG_WARN_INT_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_SUSPICIOUS_MOVE = YES; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; @@ -429,6 +435,7 @@ B5E9F90C1C8D3B6E00443DC7 /* Release */ = { isa = XCBuildConfiguration; buildSettings = { + ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; ALWAYS_SEARCH_USER_PATHS = NO; CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_CXX_LIBRARY = "libc++"; @@ -439,8 +446,10 @@ CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; CLANG_WARN_INT_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_SUSPICIOUS_MOVE = YES; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; @@ -467,13 +476,14 @@ isa = XCBuildConfiguration; baseConfigurationReference = CA708B7D49E7D80A75ED81E3 /* Pods-Example.debug.xcconfig */; buildSettings = { + ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = "$(inherited)"; ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; INFOPLIST_FILE = Example/Info.plist; IPHONEOS_DEPLOYMENT_TARGET = 8.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = com.polydice.ICInputAccessoryExample; PRODUCT_NAME = "$(TARGET_NAME)"; - SWIFT_VERSION = 2.3; + SWIFT_VERSION = 3.0; TARGETED_DEVICE_FAMILY = "1,2"; }; name = Debug; @@ -482,13 +492,15 @@ isa = XCBuildConfiguration; baseConfigurationReference = FE1A89C8A77ED0438A206A24 /* Pods-Example.release.xcconfig */; buildSettings = { + ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = "$(inherited)"; ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; INFOPLIST_FILE = Example/Info.plist; IPHONEOS_DEPLOYMENT_TARGET = 8.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = com.polydice.ICInputAccessoryExample; PRODUCT_NAME = "$(TARGET_NAME)"; - SWIFT_VERSION = 2.3; + SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; + SWIFT_VERSION = 3.0; TARGETED_DEVICE_FAMILY = "1,2"; }; name = Release; diff --git a/Example/Example/AppDelegate.swift b/Example/Example/AppDelegate.swift index 3e21da6..23c28d5 100644 --- a/Example/Example/AppDelegate.swift +++ b/Example/Example/AppDelegate.swift @@ -31,9 +31,9 @@ class AppDelegate: UIResponder, UIApplicationDelegate { var window: UIWindow? - func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool { - window = UIWindow(frame: UIScreen.mainScreen().bounds) - window?.backgroundColor = UIColor.whiteColor() + func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey : Any]? = nil) -> Bool { + window = UIWindow(frame: UIScreen.main.bounds) + window?.backgroundColor = UIColor.white window?.rootViewController = UINavigationController(rootViewController: ExampleViewController()) window?.makeKeyAndVisible() return true diff --git a/Example/Example/CustomizedTokenField.swift b/Example/Example/CustomizedTokenField.swift index 4f8698a..b79d4fb 100644 --- a/Example/Example/CustomizedTokenField.swift +++ b/Example/Example/CustomizedTokenField.swift @@ -52,31 +52,31 @@ extension ICTokenField { layer.cornerRadius = 5 layer.shouldRasterize = true - layer.rasterizationScale = UIScreen.mainScreen().scale + layer.rasterizationScale = UIScreen.main.scale backgroundColor = UIColor(red:0.8, green:0.32, blue:0.24, alpha:1) - textField.textColor = UIColor.whiteColor() - textField.tintColor = UIColor.whiteColor() - textField.font = UIFont.boldSystemFontOfSize(14) + textField.textColor = UIColor.white + textField.tintColor = UIColor.white + textField.font = UIFont.boldSystemFont(ofSize: 14) attributedPlaceholder = NSAttributedString( - string: String(self.dynamicType), + string: String(describing: type(of: self)), attributes: [ - NSForegroundColorAttributeName: UIColor.whiteColor().colorWithAlphaComponent(0.5), - NSFontAttributeName: UIFont.boldSystemFontOfSize(14) + NSForegroundColorAttributeName: UIColor.white.withAlphaComponent(0.5), + NSFontAttributeName: UIFont.boldSystemFont(ofSize: 14) ] ) normalTokenAttributes = [ - NSForegroundColorAttributeName: UIColor.whiteColor(), - NSBackgroundColorAttributeName: UIColor.whiteColor().colorWithAlphaComponent(0.25), - NSFontAttributeName: UIFont.boldSystemFontOfSize(14) + NSForegroundColorAttributeName: UIColor.white, + NSBackgroundColorAttributeName: UIColor.white.withAlphaComponent(0.25), + NSFontAttributeName: UIFont.boldSystemFont(ofSize: 14) ] highlightedTokenAttributes = [ NSForegroundColorAttributeName: UIColor(red:0.8, green:0.32, blue:0.24, alpha:1), - NSBackgroundColorAttributeName: UIColor.whiteColor(), - NSFontAttributeName: UIFont.boldSystemFontOfSize(14) + NSBackgroundColorAttributeName: UIColor.white, + NSFontAttributeName: UIFont.boldSystemFont(ofSize: 14) ] } diff --git a/Example/Example/CustomizedTokenViewController.swift b/Example/Example/CustomizedTokenViewController.swift index 2f7ae64..0479529 100644 --- a/Example/Example/CustomizedTokenViewController.swift +++ b/Example/Example/CustomizedTokenViewController.swift @@ -36,73 +36,74 @@ class CustomizedTokenViewController: UIViewController, ICTokenFieldDelegate { override func loadView() { super.loadView() - view.backgroundColor = UIColor.whiteColor() + view.backgroundColor = UIColor.white textView.text = "[\n\n]"; - textView.font = UIFont.preferredFontForTextStyle(UIFontTextStyleSubheadline) + textView.font = UIFont.preferredFont(forTextStyle: .subheadline) textView.frame = view.bounds.insetBy(dx: 10, dy: 10) - textView.autoresizingMask = [.FlexibleWidth, .FlexibleHeight] + textView.autoresizingMask = [.flexibleWidth, .flexibleHeight] view.addSubview(textView) } override func viewDidLoad() { super.viewDidLoad() navigationController?.navigationBar.barTintColor = UIColor(red:0.96, green:0.48, blue:0.4, alpha:1) - navigationController?.navigationBar.translucent = false - navigationController?.navigationBar.barStyle = .Black + navigationController?.navigationBar.isTranslucent = false + navigationController?.navigationBar.barStyle = .black - let cancelBarButton = UIBarButtonItem(barButtonSystemItem: .Cancel, target: self, action: .dismiss) - cancelBarButton.tintColor = UIColor.whiteColor() + let cancelBarButton = UIBarButtonItem(barButtonSystemItem: .cancel, target: self, action: .dismiss) + cancelBarButton.tintColor = UIColor.white navigationItem.rightBarButtonItem = cancelBarButton navigationItem.titleView = tokenField tokenField.delegate = self } - override func viewWillAppear(animated: Bool) { + override func viewWillAppear(_ animated: Bool) { super.viewWillAppear(animated) - tokenField.becomeFirstResponder() + _ = tokenField.becomeFirstResponder() } - override func viewWillDisappear(animated: Bool) { + override func viewWillDisappear(_ animated: Bool) { super.viewWillAppear(animated) - tokenField.resignFirstResponder() + _ = tokenField.resignFirstResponder() textView.endEditing(true) } // MARK: - ICTokenFieldDelegate - func tokenFieldDidBeginEditing(tokenField: ICTokenField) { + func tokenFieldDidBeginEditing(_ tokenField: ICTokenField) { print(#function) } - func tokenFieldDidEndEditing(tokenField: ICTokenField) { + func tokenFieldDidEndEditing(_ tokenField: ICTokenField) { print(#function) } - func tokenFieldWillReturn(tokenField: ICTokenField) { + func tokenFieldWillReturn(_ tokenField: ICTokenField) { print(#function) } - func tokenField(tokenField: ICTokenField, didEnterText text: String) { + func tokenField(_ tokenField: ICTokenField, didEnterText text: String) { print("Add: \"\(text)\"") updateTexts() } - func tokenField(tokenField: ICTokenField, didDeleteText text: String, atIndex index: Int) { + func tokenField(_ tokenField: ICTokenField, didDeleteText text: String, atIndex index: Int) { print("Delete: \"\(text)\"") updateTexts() } // MARK: - UIResponder Callbacks - @objc private func dismiss(sender: UIBarButtonItem) { - presentingViewController?.dismissViewControllerAnimated(true, completion: nil) + @objc fileprivate func dismiss(_ sender: UIBarButtonItem) { + presentingViewController?.dismiss(animated: true, completion: nil) } // MARK: - Private Methods private func updateTexts() { - textView.text = "[\n " + tokenField.texts.map { "\"" + $0 + "\"" } .joinWithSeparator(",\n ") + "\n]" + let tokens = tokenField.texts.map { "\"" + $0 + "\"" } .joined(separator: ",\n ") + textView.text = "[\n " + tokens + "\n]" } } diff --git a/Example/Example/ExampleCell.swift b/Example/Example/ExampleCell.swift index 13b8379..a5cc615 100644 --- a/Example/Example/ExampleCell.swift +++ b/Example/Example/ExampleCell.swift @@ -36,14 +36,14 @@ class ExampleCell: UITableViewCell { displayingView.translatesAutoresizingMaskIntoConstraints = false if #available(iOS 9.0, *) { - displayingView.topAnchor.constraintEqualToAnchor(contentView.topAnchor).active = true - displayingView.leftAnchor.constraintEqualToAnchor(contentView.leftAnchor).active = true - displayingView.bottomAnchor.constraintEqualToAnchor(contentView.bottomAnchor).active = true - displayingView.rightAnchor.constraintEqualToAnchor(contentView.rightAnchor).active = true + displayingView.topAnchor.constraint(equalTo: contentView.topAnchor).isActive = true + displayingView.leftAnchor.constraint(equalTo: contentView.leftAnchor).isActive = true + displayingView.bottomAnchor.constraint(equalTo: contentView.bottomAnchor).isActive = true + displayingView.rightAnchor.constraint(equalTo: contentView.rightAnchor).isActive = true } else { let views = ["view": displayingView] - contentView.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("H:|[view]|", options: [], metrics: nil, views: views)) - contentView.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("V:|[view]|", options: [], metrics: nil, views: views)) + contentView.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "H:|[view]|", options: [], metrics: nil, views: views)) + contentView.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "V:|[view]|", options: [], metrics: nil, views: views)) } } } @@ -56,7 +56,7 @@ class ExampleCell: UITableViewCell { showcase?.removeFromSuperview() showcase = nil textLabel?.text = nil - accessoryType = .None + accessoryType = .none } } diff --git a/Example/Example/ExampleViewController.swift b/Example/Example/ExampleViewController.swift index f9c6c4f..fcbe458 100644 --- a/Example/Example/ExampleViewController.swift +++ b/Example/Example/ExampleViewController.swift @@ -36,17 +36,17 @@ class ExampleViewController: UITableViewController { ] private lazy var flipButton: UIButton = { - let _button = UIButton(type: .System) - _button.frame = CGRect(x: 0, y: 0, width: UIScreen.mainScreen().bounds.width, height: 88) - _button.setTitle("Storyboard", forState: .Normal) - _button.addTarget(self, action: .showStoryboard, forControlEvents: .TouchUpInside) + let _button = UIButton(type: .system) + _button.frame = CGRect(x: 0, y: 0, width: UIScreen.main.bounds.width, height: 88) + _button.setTitle("Storyboard", for: UIControlState()) + _button.addTarget(self, action: .showStoryboard, for: .touchUpInside) return _button }() // MARK: - Initialization convenience init() { - self.init(style: .Grouped) + self.init(style: .grouped) title = "ICInputAccessory" } @@ -54,22 +54,22 @@ class ExampleViewController: UITableViewController { override func loadView() { super.loadView() - tableView.registerClass(ExampleCell.self, forCellReuseIdentifier: NSStringFromClass(ExampleCell.self)) + tableView.register(ExampleCell.self, forCellReuseIdentifier: String(describing: ExampleCell.self)) tableView.tableFooterView = flipButton - tableView.tableFooterView?.userInteractionEnabled + tableView.tableFooterView?.isUserInteractionEnabled = true } // MARK: - UITableViewDataSource - override func numberOfSectionsInTableView(tableView: UITableView) -> Int { + override func numberOfSections(in tableView: UITableView) -> Int { return types.count } - override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int { + override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { return 1 } - override func tableView(tableView: UITableView, titleForHeaderInSection section: Int) -> String? { + override func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? { switch types[section] { case is ICKeyboardDismissTextField.Type: return "Dismiss Keyboard" @@ -82,26 +82,27 @@ class ExampleViewController: UITableViewController { } } - override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell { - let cell = tableView.dequeueReusableCellWithIdentifier(NSStringFromClass(ExampleCell.self), forIndexPath: indexPath) + override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { + let cell = tableView.dequeueReusableCell(withIdentifier: String(describing: ExampleCell.self), for: indexPath) + switch types[indexPath.section] { case let type as ICKeyboardDismissTextField.Type: let textField = type.init() - textField.leftViewMode = .Always + textField.leftViewMode = .always textField.leftView = UIView(frame: CGRect(x: 0, y: 0, width: 15, height: 15)) - textField.placeholder = String(type) + textField.placeholder = String(describing: type) (cell as? ExampleCell)?.showcase = textField case let type as CustomizedTokenField.Type: - cell.textLabel?.text = String(type) - cell.accessoryType = .DisclosureIndicator + cell.textLabel?.text = String(describing: type) + cell.accessoryType = .disclosureIndicator case let type as ICTokenField.Type: let container = UIView(frame: cell.bounds) let tokenField = type.init() - tokenField.placeholder = String(type) + tokenField.placeholder = String(describing: type) tokenField.frame = container.bounds.insetBy(dx: 5, dy: 0) - tokenField.autoresizingMask = [.FlexibleWidth, .FlexibleHeight] + tokenField.autoresizingMask = [.flexibleWidth, .flexibleHeight] container.addSubview(tokenField) (cell as? ExampleCell)?.showcase = container @@ -113,22 +114,22 @@ class ExampleViewController: UITableViewController { // MARK: - UITableViewDelegate - override func tableView(tableView: UITableView, shouldHighlightRowAtIndexPath indexPath: NSIndexPath) -> Bool { + override func tableView(_ tableView: UITableView, shouldHighlightRowAt indexPath: IndexPath) -> Bool { return types[indexPath.section] == CustomizedTokenField.self } - override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) { + override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { if types[indexPath.section] == CustomizedTokenField.self { - presentViewController(UINavigationController(rootViewController: CustomizedTokenViewController()), animated: true, completion: nil) + present(UINavigationController(rootViewController: CustomizedTokenViewController()), animated: true, completion: nil) } } // MARK: - UIResponder Callbacks - @objc private func showStoryboard(sender: UIButton) { - if let controller = UIStoryboard(name: "Main", bundle: NSBundle.mainBundle()).instantiateInitialViewController() { - controller.modalTransitionStyle = .FlipHorizontal - presentViewController(controller, animated: true, completion: nil) + @objc fileprivate func showStoryboard(_ sender: UIButton) { + if let controller = UIStoryboard(name: "Main", bundle: Bundle.main).instantiateInitialViewController() { + controller.modalTransitionStyle = .flipHorizontal + present(controller, animated: true, completion: nil) } } diff --git a/Example/Example/StoryboardViewController.swift b/Example/Example/StoryboardViewController.swift index 11936b7..9a3f5d2 100644 --- a/Example/Example/StoryboardViewController.swift +++ b/Example/Example/StoryboardViewController.swift @@ -32,19 +32,19 @@ class StoryboardViewController: UITableViewController { @IBOutlet weak var tokenField: ICTokenField! { didSet { tokenField.normalTokenAttributes = [ - NSForegroundColorAttributeName: UIColor.whiteColor(), - NSBackgroundColorAttributeName: UIColor.whiteColor().colorWithAlphaComponent(0.25), + NSForegroundColorAttributeName: UIColor.white, + NSBackgroundColorAttributeName: UIColor.white.withAlphaComponent(0.25), ] tokenField.highlightedTokenAttributes = [ - NSForegroundColorAttributeName: UIColor.darkGrayColor(), - NSBackgroundColorAttributeName: UIColor.whiteColor(), + NSForegroundColorAttributeName: UIColor.darkGray, + NSBackgroundColorAttributeName: UIColor.white, ] } } - @IBAction func dismiss(sender: UIButton) { - presentingViewController?.dismissViewControllerAnimated(true, completion: nil) + @IBAction func dismiss(_ sender: UIButton) { + presentingViewController?.dismiss(animated: true, completion: nil) } } diff --git a/Example/ICInputAccessoryUITests/ICKeyboardDismissTextFieldUITests.swift b/Example/ICInputAccessoryUITests/ICKeyboardDismissTextFieldUITests.swift index eee899c..a7f5f3a 100644 --- a/Example/ICInputAccessoryUITests/ICKeyboardDismissTextFieldUITests.swift +++ b/Example/ICInputAccessoryUITests/ICKeyboardDismissTextFieldUITests.swift @@ -45,9 +45,9 @@ class ICKeyboardDismissTextFieldUITests: XCTestCase { let app = XCUIApplication() app.tables.cells.textFields["ICKeyboardDismissTextField"].tap() - let keyboardWindow = app.childrenMatchingType(.Window).elementBoundByIndex(1) - let accessory = keyboardWindow.childrenMatchingType(.Other).element.childrenMatchingType(.Other).element.childrenMatchingType(.Other).elementBoundByIndex(0) - accessory.childrenMatchingType(.Button).element.tap() + let keyboardWindow = app.children(matching: .window).element(boundBy: 1) + let accessory = keyboardWindow.children(matching: .other).element.children(matching: .other).element.children(matching: .other).element(boundBy: 0) + accessory.children(matching: .button).element.tap() } func testStoryboard() { @@ -57,11 +57,11 @@ class ICKeyboardDismissTextFieldUITests: XCTestCase { tablesQuery.buttons["Storyboard"].tap() tablesQuery.textFields["Storyboard ICKeyboardDismissTextField"].tap() - let keyboardWindow = app.childrenMatchingType(.Window).elementBoundByIndex(1) - let accessory = keyboardWindow.childrenMatchingType(.Other).element.childrenMatchingType(.Other).element.childrenMatchingType(.Other).elementBoundByIndex(0) - accessory.childrenMatchingType(.Button).element.tap() + let keyboardWindow = app.children(matching: .window).element(boundBy: 1) + let accessory = keyboardWindow.children(matching: .other).element.children(matching: .other).element.children(matching: .other).element(boundBy: 0) + accessory.children(matching: .button).element.tap() tablesQuery.buttons["Back to Code"].tap() } -} \ No newline at end of file +} diff --git a/Example/ICInputAccessoryUITests/ICTokenFieldUITests.swift b/Example/ICInputAccessoryUITests/ICTokenFieldUITests.swift index 4290f36..45624a1 100644 --- a/Example/ICInputAccessoryUITests/ICTokenFieldUITests.swift +++ b/Example/ICInputAccessoryUITests/ICTokenFieldUITests.swift @@ -44,7 +44,7 @@ class ICTokenFieldUITests: XCTestCase { func testTokenField() { let app = XCUIApplication() let tablesQuery = app.tables - let textField = tablesQuery.cells.containingType(.StaticText, identifier:"ICTokenField").childrenMatchingType(.TextField).element + let textField = tablesQuery.cells.containing(.staticText, identifier:"ICTokenField").children(matching: .textField).element textField.tap() textField.typeText("Try") @@ -69,7 +69,7 @@ class ICTokenFieldUITests: XCTestCase { let app = XCUIApplication() app.tables.staticTexts["CustomizedTokenField"].tap() - let tokenField = app.navigationBars["Example.CustomizedTokenView"].scrollViews.childrenMatchingType(.TextField).element + let tokenField = app.navigationBars["Example.CustomizedTokenView"].scrollViews.children(matching: .textField).element tokenField.typeText("Try") tokenField.typeText(" ") tokenField.typeText("iCook") @@ -93,7 +93,7 @@ class ICTokenFieldUITests: XCTestCase { let tablesQuery = app.tables tablesQuery.buttons["Storyboard"].tap() - let tokenField = tablesQuery.cells.containingType(.StaticText, identifier:"Storyboard ICTokenField").childrenMatchingType(.TextField).element + let tokenField = tablesQuery.cells.containing(.staticText, identifier:"Storyboard ICTokenField").children(matching: .textField).element tokenField.tap() tokenField.typeText("Try") tokenField.typeText(" ") diff --git a/Gemfile b/Gemfile index 6830eaa..d23cb66 100644 --- a/Gemfile +++ b/Gemfile @@ -1,7 +1,7 @@ source "http://rubygems.org" ruby "2.3.1" -gem "cocoapods", "~> 1.0.0" +gem "cocoapods", "~> 1.1.0" gem "danger", "~> 3.5.0" gem "jazzy", "~> 0.7.0" gem "pry" diff --git a/Gemfile.lock b/Gemfile.lock index f67fbec..4ab48ee 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -1,54 +1,55 @@ GEM remote: http://rubygems.org/ specs: - activesupport (5.0.0.1) - concurrent-ruby (~> 1.0, >= 1.0.2) + activesupport (4.2.7.1) i18n (~> 0.7) + json (~> 1.7, >= 1.7.7) minitest (~> 5.1) + thread_safe (~> 0.3, >= 0.3.4) tzinfo (~> 1.1) addressable (2.4.0) - claide (1.0.0) + claide (1.0.1) claide-plugins (0.9.2) cork nap open4 (~> 1.3) - cocoapods (1.0.1) - activesupport (>= 4.0.2) - claide (>= 1.0.0, < 2.0) - cocoapods-core (= 1.0.1) - cocoapods-deintegrate (>= 1.0.0, < 2.0) - cocoapods-downloader (>= 1.0.0, < 2.0) + cocoapods (1.1.1) + activesupport (>= 4.0.2, < 5) + claide (>= 1.0.1, < 2.0) + cocoapods-core (= 1.1.1) + cocoapods-deintegrate (>= 1.0.1, < 2.0) + cocoapods-downloader (>= 1.1.2, < 2.0) cocoapods-plugins (>= 1.0.0, < 2.0) cocoapods-search (>= 1.0.0, < 2.0) cocoapods-stats (>= 1.0.0, < 2.0) - cocoapods-trunk (>= 1.0.0, < 2.0) - cocoapods-try (>= 1.0.0, < 2.0) + cocoapods-trunk (>= 1.1.1, < 2.0) + cocoapods-try (>= 1.1.0, < 2.0) colored (~> 1.2) escape (~> 0.0.4) - fourflusher (~> 0.3.0) - molinillo (~> 0.4.5) + fourflusher (~> 2.0.1) + gh_inspector (~> 1.0) + molinillo (~> 0.5.1) nap (~> 1.0) - xcodeproj (>= 1.1.0, < 2.0) - cocoapods-core (1.0.1) - activesupport (>= 4.0.2) + xcodeproj (>= 1.3.3, < 2.0) + cocoapods-core (1.1.1) + activesupport (>= 4.0.2, < 5) fuzzy_match (~> 2.0.4) nap (~> 1.0) cocoapods-deintegrate (1.0.1) - cocoapods-downloader (1.1.1) + cocoapods-downloader (1.1.2) cocoapods-plugins (1.0.0) nap cocoapods-search (1.0.0) cocoapods-stats (1.0.0) - cocoapods-trunk (1.0.0) + cocoapods-trunk (1.1.1) nap (>= 0.8, < 2.0) netrc (= 0.7.8) cocoapods-try (1.1.0) coderay (1.1.1) colored (1.2) - concurrent-ruby (1.0.2) cork (0.2.0) colored (~> 1.2) - danger (3.5.0) + danger (3.5.5) claide (~> 1.0) claide-plugins (>= 0.9.2) colored (~> 1.2) @@ -65,8 +66,9 @@ GEM multipart-post (>= 1.2, < 3) faraday-http-cache (1.3.1) faraday (~> 0.8) - fourflusher (0.3.2) + fourflusher (2.0.1) fuzzy_match (2.0.4) + gh_inspector (1.0.2) git (1.3.0) gitlab (3.7.0) httparty (~> 0.13.0) @@ -89,13 +91,13 @@ GEM liferaft (0.0.4) method_source (0.8.2) minitest (5.9.1) - molinillo (0.4.5) + molinillo (0.5.2) multi_xml (0.5.5) multipart-post (2.0.0) mustache (0.99.8) nap (1.1.0) netrc (0.7.8) - octokit (4.3.0) + octokit (4.4.0) sawyer (~> 0.7.0, >= 0.5.3) open4 (1.3.4) pry (0.10.4) @@ -119,18 +121,18 @@ GEM unicode-display_width (1.1.1) xcinvoke (0.2.1) liferaft (~> 0.0.4) - xcodeproj (1.3.1) + xcodeproj (1.3.3) activesupport (>= 3) - claide (>= 1.0.0, < 2.0) + claide (>= 1.0.1, < 2.0) colored (~> 1.2) - xcpretty (0.2.3) + xcpretty (0.2.4) rouge (~> 1.8) PLATFORMS ruby DEPENDENCIES - cocoapods (~> 1.0.0) + cocoapods (~> 1.1.0) danger (~> 3.5.0) jazzy (~> 0.7.0) pry diff --git a/ICInputAccessory.xcodeproj/project.pbxproj b/ICInputAccessory.xcodeproj/project.pbxproj index 121e6aa..f2f4519 100644 --- a/ICInputAccessory.xcodeproj/project.pbxproj +++ b/ICInputAccessory.xcodeproj/project.pbxproj @@ -183,6 +183,7 @@ B56BC4301C89A7EA00C20AD6 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { + ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; ALWAYS_SEARCH_USER_PATHS = NO; CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_CXX_LIBRARY = "libc++"; @@ -224,7 +225,7 @@ ONLY_ACTIVE_ARCH = YES; SDKROOT = iphoneos; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; - SWIFT_VERSION = 2.3; + SWIFT_VERSION = 3.0; TARGETED_DEVICE_FAMILY = "1,2"; VERSIONING_SYSTEM = "apple-generic"; VERSION_INFO_PREFIX = ""; @@ -234,6 +235,7 @@ B56BC4311C89A7EA00C20AD6 /* Release */ = { isa = XCBuildConfiguration; buildSettings = { + ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; ALWAYS_SEARCH_USER_PATHS = NO; CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_CXX_LIBRARY = "libc++"; @@ -267,7 +269,7 @@ IPHONEOS_DEPLOYMENT_TARGET = 8.0; MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = iphoneos; - SWIFT_VERSION = 2.3; + SWIFT_VERSION = 3.0; TARGETED_DEVICE_FAMILY = "1,2"; VALIDATE_PRODUCT = YES; VERSIONING_SYSTEM = "apple-generic"; @@ -278,6 +280,7 @@ B56BC4331C89A7EA00C20AD6 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { + ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = "$(inherited)"; CLANG_ENABLE_MODULES = YES; DEFINES_MODULE = YES; DYLIB_COMPATIBILITY_VERSION = 1; @@ -297,6 +300,7 @@ B56BC4341C89A7EA00C20AD6 /* Release */ = { isa = XCBuildConfiguration; buildSettings = { + ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = "$(inherited)"; CLANG_ENABLE_MODULES = YES; DEFINES_MODULE = YES; DYLIB_COMPATIBILITY_VERSION = 1; diff --git a/Podfile b/Podfile index a726ec4..ae0fb57 100644 --- a/Podfile +++ b/Podfile @@ -13,7 +13,7 @@ end post_install do |installer| installer.pods_project.targets.each do |target| target.build_configurations.each do |config| - config.build_settings["SWIFT_VERSION"] = "2.3" + config.build_settings["SWIFT_VERSION"] = "3.0" end end end diff --git a/Podfile.lock b/Podfile.lock index a939432..3b75e3c 100644 --- a/Podfile.lock +++ b/Podfile.lock @@ -13,6 +13,6 @@ EXTERNAL SOURCES: SPEC CHECKSUMS: ICInputAccessory: 75941a41865c7fab675c9252fd3101b79a7aea62 -PODFILE CHECKSUM: 41c0babd8a8e47d9dc4741ac44d6bb453b85139d +PODFILE CHECKSUM: 0d87bbf65bdc7c4668475091d7495d880f7fc618 -COCOAPODS: 1.0.1 +COCOAPODS: 1.1.1 diff --git a/README.md b/README.md index 0cad277..6b634f6 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,5 @@ # ICInputAccessory -[![Join the chat at https://gitter.im/ICInputAccessory/Lobby](https://badges.gitter.im/ICInputAccessory/Lobby.svg)](https://gitter.im/ICInputAccessory/Lobby?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) - Customized text fields used in the [iCook app](https://itunes.apple.com/app/id554065086). Try . @@ -9,8 +7,8 @@ Try . [![Carthage compatible](https://img.shields.io/badge/Carthage-compatible-4BC51D.svg)](https://github.com/Carthage/Carthage) [![CocoaPods Compatible](https://img.shields.io/cocoapods/v/ICInputAccessory.svg)](https://cocoapods.org/pods/ICInputAccessory) ![Platform](https://img.shields.io/cocoapods/p/ICInputAccessory.svg) -[![Docs](https://img.shields.io/cocoapods/metrics/doc-percent/ICInputAccessory.svg)](http://cocoadocs.org/docsets/ICInputAccessory/) -![Swift 2.3](https://img.shields.io/badge/Swift-2.3-orange.svg) +[![CocoaDocs](https://img.shields.io/cocoapods/metrics/doc-percent/ICInputAccessory.svg)](http://cocoadocs.org/docsets/ICInputAccessory/) +![Swift 3.0](https://img.shields.io/badge/Swift-3.0-orange.svg) ### ICKeyboardDismissTextField @@ -32,7 +30,7 @@ ICInputAccessory | iOS | Xcode | Swift `~> 1.0.0` | 8.0+ | 7.2 | ![Swift 2.1.1](https://img.shields.io/badge/Swift-2.1.1-orange.svg) `~> 1.1.0` | 8.0+ | 7.3 | ![Swift 2.2](https://img.shields.io/badge/Swift-2.2-orange.svg) `~> 1.2.0` | 8.0+ | 8.0 | ![Swift 2.3](https://img.shields.io/badge/Swift-2.3-orange.svg) -`feature/swift-3`| 8.0+ | 8.0 | ![Swift 3.0](https://img.shields.io/badge/Swift-3.0-orange.svg) +`develop` | 8.0+ | 8.0 | ![Swift 3.0](https://img.shields.io/badge/Swift-3.0-orange.svg) ## Installation @@ -164,6 +162,7 @@ Please fork this repository, create a branch named like `feature/some-new-featur ## Contact [![Twitter](https://img.shields.io/badge/twitter-@polydice-blue.svg?style=flat)](https://twitter.com/polydice) +[![Join the chat at https://gitter.im/polydice/ICInputAccessory](https://badges.gitter.im/polydice/ICInputAccessory.svg)](https://gitter.im/polydice/ICInputAccessory) ## License diff --git a/Rakefile b/Rakefile index f138ad8..9cea6f2 100644 --- a/Rakefile +++ b/Rakefile @@ -25,14 +25,14 @@ namespace :example do desc "Build the example project" task :build, [:os] do |t, args| version = args[:os] || "latest" - sh %(xcodebuild -workspace ICInputAccessory.xcworkspace -scheme Example -sdk iphonesimulator -destination "name=iPhone 5,OS=#{version}" clean build | xcpretty -c && exit ${PIPESTATUS[0]}) + sh %(xcodebuild -workspace ICInputAccessory.xcworkspace -scheme Example -sdk iphonesimulator -destination "name=iPhone 6s,OS=#{version}" clean build | xcpretty -c && exit ${PIPESTATUS[0]}) exit $?.exitstatus if not $?.success? end desc "Run the UI tests in the example project" task :test, [:os] do |t, args| version = args[:os] || "latest" - sh %(xcodebuild -workspace ICInputAccessory.xcworkspace -scheme Example -sdk iphonesimulator -destination "name=iPhone 6,OS=#{version}" clean test | xcpretty -c && exit ${PIPESTATUS[0]}) + sh %(xcodebuild -workspace ICInputAccessory.xcworkspace -scheme Example -sdk iphonesimulator -destination "name=iPhone 6s,OS=#{version}" clean test | xcpretty -c && exit ${PIPESTATUS[0]}) exit $?.exitstatus if not $?.success? end end @@ -41,7 +41,7 @@ namespace :framework do desc "Build the framework project" task :build, [:os] do |t, args| version = args[:os] || "latest" - sh %(xcodebuild -project ICInputAccessory.xcodeproj -scheme ICInputAccessory-iOS -sdk iphonesimulator -destination "name=iPhone 5,OS=#{version}" clean build | xcpretty -c && exit ${PIPESTATUS[0]}) + sh %(xcodebuild -project ICInputAccessory.xcodeproj -scheme ICInputAccessory-iOS -sdk iphonesimulator -destination "name=iPhone 6s,OS=#{version}" clean build | xcpretty -c && exit ${PIPESTATUS[0]}) exit $?.exitstatus if not $?.success? end end diff --git a/Source/KeyboardDismissTextField/ICKeyboardDismissAccessoryView.swift b/Source/KeyboardDismissTextField/ICKeyboardDismissAccessoryView.swift index 1b06b15..e6b8afa 100644 --- a/Source/KeyboardDismissTextField/ICKeyboardDismissAccessoryView.swift +++ b/Source/KeyboardDismissTextField/ICKeyboardDismissAccessoryView.swift @@ -28,7 +28,7 @@ import UIKit /// A customized keyboard accessory view with a dismiss button. @IBDesignable -public class ICKeyboardDismissAccessoryView: UIView { +open class ICKeyboardDismissAccessoryView: UIView { /// The background color of the button to dismiss keyboard. @IBInspectable public var buttonColor: UIColor = Constants.ButtonColor { @@ -40,14 +40,14 @@ public class ICKeyboardDismissAccessoryView: UIView { /// The button to dismiss keyboard. public private(set) lazy var dismissButton: UIButton = { let _button = UIButton() - let resources = NSBundle(forClass: self.dynamicType) - let icon = UIImage(named: "icook-iphone-button-hide-keyboard", inBundle: resources, compatibleWithTraitCollection: nil) - _button.setImage(icon, forState: .Normal) + let resources = Bundle(for: type(of: self)) + let icon = UIImage(named: "icook-iphone-button-hide-keyboard", in: resources, compatibleWith: nil) + _button.setImage(icon, for: UIControlState()) _button.backgroundColor = Constants.ButtonColor - _button.exclusiveTouch = true + _button.isExclusiveTouch = true _button.layer.cornerRadius = 4 _button.layer.shouldRasterize = true - _button.layer.rasterizationScale = UIScreen.mainScreen().scale + _button.layer.rasterizationScale = UIScreen.main.scale return _button }() @@ -73,11 +73,11 @@ public class ICKeyboardDismissAccessoryView: UIView { // MARK: - UIView - public override func pointInside(point: CGPoint, withEvent event: UIEvent?) -> Bool { + open override func point(inside point: CGPoint, with event: UIEvent?) -> Bool { for subview in subviews { - if !subview.hidden && subview.alpha > 0 && - subview.userInteractionEnabled && - subview.pointInside(convertPoint(point, toView: subview), withEvent: event) { + if !subview.isHidden && subview.alpha > 0 && + subview.isUserInteractionEnabled && + subview.point(inside: convert(point, to: subview), with: event) { return true } } @@ -86,8 +86,8 @@ public class ICKeyboardDismissAccessoryView: UIView { // MARK: - NSKeyValueCoding - public override func setValue(value: AnyObject?, forUndefinedKey key: String) { - if let color = value as? UIColor where key == "buttonColor" { + open override func setValue(_ value: Any?, forKey key: String) { + if let color = value as? UIColor, key == "buttonColor" { buttonColor = color } } @@ -95,7 +95,7 @@ public class ICKeyboardDismissAccessoryView: UIView { // MARK: - Private Methods private func setUpSubviews() { - backgroundColor = UIColor.clearColor() + backgroundColor = UIColor.clear addSubview(dismissButton) dismissButton.translatesAutoresizingMaskIntoConstraints = false @@ -107,14 +107,14 @@ public class ICKeyboardDismissAccessoryView: UIView { "padding": Constants.EdgePadding ] - addConstraints(NSLayoutConstraint.constraintsWithVisualFormat( - "H:[button(width)]-(padding)-|", + addConstraints(NSLayoutConstraint.constraints( + withVisualFormat: "H:[button(width)]-(padding)-|", options: [], metrics: metrics, views: views )) - addConstraints(NSLayoutConstraint.constraintsWithVisualFormat( - "V:[button(height)]-(padding)-|", + addConstraints(NSLayoutConstraint.constraints( + withVisualFormat: "V:[button(height)]-(padding)-|", options: [], metrics: metrics, views: views diff --git a/Source/KeyboardDismissTextField/ICKeyboardDismissTextField.swift b/Source/KeyboardDismissTextField/ICKeyboardDismissTextField.swift index aefea51..81980b3 100644 --- a/Source/KeyboardDismissTextField/ICKeyboardDismissTextField.swift +++ b/Source/KeyboardDismissTextField/ICKeyboardDismissTextField.swift @@ -28,13 +28,13 @@ import UIKit /// A text field that has a button to dismiss keyboard on the input accessory view. @IBDesignable -public class ICKeyboardDismissTextField: UITextField { +open class ICKeyboardDismissTextField: UITextField { /// The custom input accessory view with a button to dismiss keyboard. @IBOutlet public var keyboardAccessoryView: ICKeyboardDismissAccessoryView! { didSet { - if UI_USER_INTERFACE_IDIOM() != .Phone { return } - keyboardAccessoryView.dismissButton.addTarget(self, action: .dismiss, forControlEvents: .TouchUpInside) + if UI_USER_INTERFACE_IDIOM() != .phone { return } + keyboardAccessoryView.dismissButton.addTarget(self, action: .dismiss, for: .touchUpInside) inputAccessoryView = keyboardAccessoryView } } @@ -55,16 +55,16 @@ public class ICKeyboardDismissTextField: UITextField { // MARK: - UIResponder - public override func becomeFirstResponder() -> Bool { - if UI_USER_INTERFACE_IDIOM() == .Phone { + open override func becomeFirstResponder() -> Bool { + if UI_USER_INTERFACE_IDIOM() == .phone { keyboardAccessoryView.alpha = 1 } return super.becomeFirstResponder() } - @objc private func dismiss(sender: UIButton) { + @objc fileprivate func dismiss(_ sender: UIButton) { resignFirstResponder() - UIView.animateWithDuration(0.3) { + UIView.animate(withDuration: 0.3) { self.keyboardAccessoryView.alpha = 0 } } diff --git a/Source/TokenField/ICBackspaceTextField.swift b/Source/TokenField/ICBackspaceTextField.swift index 296d6ac..a83aa1f 100644 --- a/Source/TokenField/ICBackspaceTextField.swift +++ b/Source/TokenField/ICBackspaceTextField.swift @@ -27,7 +27,7 @@ import UIKit protocol ICBackspaceTextFieldDelegate: class { - func textFieldShouldDelete(textField: ICBackspaceTextField) -> Bool + func textFieldShouldDelete(_ textField: ICBackspaceTextField) -> Bool } //////////////////////////////////////////////////////////////////////////////// @@ -41,7 +41,7 @@ class ICBackspaceTextField: UITextField { didSet { // Trigger the lazy instantiation of cursorColor let color = cursorColor - tintColor = showsCursor ? color : UIColor.clearColor() + tintColor = showsCursor ? color : UIColor.clear } } @@ -49,14 +49,14 @@ class ICBackspaceTextField: UITextField { // MARK: - UIView - override func pointInside(point: CGPoint, withEvent event: UIEvent?) -> Bool { + override func point(inside point: CGPoint, with event: UIEvent?) -> Bool { // Forward touches to the superview when the cursor is hidden. - return showsCursor && super.pointInside(point, withEvent: event) + return showsCursor && super.point(inside: point, with: event) } // MARK: - UITextField - func keyboardInputShouldDelete(textField: UITextField) -> Bool { + func keyboardInputShouldDelete(_ textField: UITextField) -> Bool { return backspaceDelegate?.textFieldShouldDelete(self) ?? true } diff --git a/Source/TokenField/ICInsetLabel.swift b/Source/TokenField/ICInsetLabel.swift index 34edffb..a696e48 100644 --- a/Source/TokenField/ICInsetLabel.swift +++ b/Source/TokenField/ICInsetLabel.swift @@ -29,26 +29,26 @@ import UIKit class ICInsetLabel: UILabel { enum CornerRadius { - case Dynamic - case Constant(CGFloat) + case dynamic + case constant(CGFloat) } - var contentEdgeInsets = UIEdgeInsetsZero - var cornerRadius = CornerRadius.Constant(0) + var contentEdgeInsets = UIEdgeInsets.zero + var cornerRadius = CornerRadius.constant(0) - convenience init(contentEdgeInsets: UIEdgeInsets, cornerRadius: CornerRadius = .Constant(0)) { + convenience init(contentEdgeInsets: UIEdgeInsets, cornerRadius: CornerRadius = .constant(0)) { self.init(frame: CGRect.zero) self.contentEdgeInsets = contentEdgeInsets self.cornerRadius = cornerRadius switch cornerRadius { - case .Constant(let radius) where radius > 0: + case let .constant(radius) where radius > 0: layer.cornerRadius = radius fallthrough - case .Dynamic: + case .dynamic: layer.masksToBounds = true layer.shouldRasterize = true - layer.rasterizationScale = UIScreen.mainScreen().scale + layer.rasterizationScale = UIScreen.main.scale default: break } @@ -56,8 +56,8 @@ class ICInsetLabel: UILabel { // MARK: - UIView - override func intrinsicContentSize() -> CGSize { - let size = super.intrinsicContentSize() + override var intrinsicContentSize: CGSize { + let size = super.intrinsicContentSize return CGSize( width: contentEdgeInsets.left + size.width + contentEdgeInsets.right, height: contentEdgeInsets.top + size.height + contentEdgeInsets.bottom @@ -66,7 +66,7 @@ class ICInsetLabel: UILabel { override func layoutSubviews() { super.layoutSubviews() - if case .Dynamic = cornerRadius { + if case .dynamic = cornerRadius { layer.cornerRadius = frame.height / 2 } } diff --git a/Source/TokenField/ICToken.swift b/Source/TokenField/ICToken.swift index 6078169..10ff293 100644 --- a/Source/TokenField/ICToken.swift +++ b/Source/TokenField/ICToken.swift @@ -31,7 +31,7 @@ class ICToken: UIView { var text = "" { didSet { updateTextLabel() - frame = CGRect(origin: CGPoint.zero, size: systemLayoutSizeFittingSize(UILayoutFittingCompressedSize)) + frame = CGRect(origin: CGPoint.zero, size: systemLayoutSizeFitting(UILayoutFittingCompressedSize)) } } @@ -43,7 +43,7 @@ class ICToken: UIView { var normalTextAttributes: [String : NSObject] = [ NSForegroundColorAttributeName: UIColor(red:0.14, green:0.38, blue:0.95, alpha:1), - NSBackgroundColorAttributeName: UIColor.clearColor() + NSBackgroundColorAttributeName: UIColor.clear ] { didSet { if !highlighted { updateTextLabel() } @@ -52,7 +52,7 @@ class ICToken: UIView { } var highlightedTextAttributes: [String: NSObject] = [ - NSForegroundColorAttributeName: UIColor.whiteColor(), + NSForegroundColorAttributeName: UIColor.white, NSBackgroundColorAttributeName: UIColor(red:0.14, green:0.38, blue:0.95, alpha:1) ] { didSet { @@ -70,8 +70,8 @@ class ICToken: UIView { }() private(set) lazy var textLabel: UILabel = { - let _label = ICInsetLabel(contentEdgeInsets: UIEdgeInsets(top: 3, left: 5, bottom: 3, right: 5), cornerRadius: .Constant(3)) - _label.textAlignment = .Center + let _label = ICInsetLabel(contentEdgeInsets: UIEdgeInsets(top: 3, left: 5, bottom: 3, right: 5), cornerRadius: .constant(3)) + _label.textAlignment = .center _label.textColor = self.normalTextAttributes[NSForegroundColorAttributeName] as? UIColor _label.backgroundColor = self.normalTextAttributes[NSBackgroundColorAttributeName] as? UIColor _label.numberOfLines = 1 @@ -98,7 +98,7 @@ class ICToken: UIView { setText(text) } - private func setText(text: String) { + private func setText(_ text: String) { self.text = text } @@ -127,12 +127,12 @@ class ICToken: UIView { "text": textLabel, "delimiter": delimiterLabel ] - addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("H:|[text][delimiter]|", - options: [.AlignAllCenterY], + addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "H:|[text][delimiter]|", + options: [.alignAllCenterY], metrics: nil, views: views )) - addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("V:|-2-[text]-2-|", + addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "V:|-2-[text]-2-|", options: [], metrics: nil, views: views diff --git a/Source/TokenField/ICTokenField.swift b/Source/TokenField/ICTokenField.swift index 6d52e54..764d54a 100644 --- a/Source/TokenField/ICTokenField.swift +++ b/Source/TokenField/ICTokenField.swift @@ -29,21 +29,21 @@ import UIKit /// The protocol defines the messages sent to a delegate. All the methods are optional. @objc public protocol ICTokenFieldDelegate: NSObjectProtocol { /// Tells the delegate that editing began for the token field. - optional func tokenFieldDidBeginEditing(tokenField: ICTokenField) + @objc optional func tokenFieldDidBeginEditing(_ tokenField: ICTokenField) /// Tells the delegate that editing stopped for the token field. - optional func tokenFieldDidEndEditing(tokenField: ICTokenField) + @objc optional func tokenFieldDidEndEditing(_ tokenField: ICTokenField) /// Tells the delegate that the token field will process the pressing of the return button. - optional func tokenFieldWillReturn(tokenField: ICTokenField) + @objc optional func tokenFieldWillReturn(_ tokenField: ICTokenField) /// Tells the delegate that the text becomes a token in the token field. - optional func tokenField(tokenField: ICTokenField, didEnterText text: String) + @objc optional func tokenField(_ tokenField: ICTokenField, didEnterText text: String) /// Tells the delegate that the token at certain index is removed from the token field. - optional func tokenField(tokenField: ICTokenField, didDeleteText text: String, atIndex index: Int) + @objc optional func tokenField(_ tokenField: ICTokenField, didDeleteText text: String, atIndex index: Int) } /// A text field that groups input texts with delimiters. @IBDesignable -public class ICTokenField: UIView, UITextFieldDelegate, ICBackspaceTextFieldDelegate { +open class ICTokenField: UIView, UITextFieldDelegate, ICBackspaceTextFieldDelegate { // MARK: - Public Properties @@ -63,7 +63,7 @@ public class ICTokenField: UIView, UITextFieldDelegate, ICBackspaceTextFieldDele didSet { if let icon = icon { let imageView = UIImageView(image: icon) - imageView.contentMode = .Center + imageView.contentMode = .center leftView = imageView } else { leftView = nil @@ -108,10 +108,10 @@ public class ICTokenField: UIView, UITextFieldDelegate, ICBackspaceTextFieldDele if placeholderLabel.superview != nil { return } insertSubview(placeholderLabel, belowSubview: scrollView) placeholderLabel.translatesAutoresizingMaskIntoConstraints = false - placeholderLabel.setContentHuggingPriority(UILayoutPriorityDefaultLow - 1, forAxis: .Horizontal) - addConstraint(NSLayoutConstraint(item: placeholderLabel, attribute: .Leading, relatedBy: .Equal, toItem: scrollView, attribute: .Leading, multiplier: 1, constant: 0)) - addConstraint(NSLayoutConstraint(item: placeholderLabel, attribute: .Trailing, relatedBy: .GreaterThanOrEqual, toItem: scrollView, attribute: .Trailing, multiplier: 1, constant: 10)) - addConstraint(NSLayoutConstraint(item: placeholderLabel, attribute: .CenterY, relatedBy: .Equal, toItem: self, attribute: .CenterY, multiplier: 1, constant: 0)) + placeholderLabel.setContentHuggingPriority(UILayoutPriorityDefaultLow - 1, for: .horizontal) + addConstraint(NSLayoutConstraint(item: placeholderLabel, attribute: .leading, relatedBy: .equal, toItem: scrollView, attribute: .leading, multiplier: 1, constant: 0)) + addConstraint(NSLayoutConstraint(item: placeholderLabel, attribute: .trailing, relatedBy: .greaterThanOrEqual, toItem: scrollView, attribute: .trailing, multiplier: 1, constant: 10)) + addConstraint(NSLayoutConstraint(item: placeholderLabel, attribute: .centerY, relatedBy: .equal, toItem: self, attribute: .centerY, multiplier: 1, constant: 0)) } } @@ -130,7 +130,7 @@ public class ICTokenField: UIView, UITextFieldDelegate, ICBackspaceTextFieldDele } /// The tint color of icon image and text field. - public override var tintColor: UIColor! { + open override var tintColor: UIColor! { didSet { inputTextField.tintColor = tintColor leftView?.tintColor = tintColor @@ -164,25 +164,25 @@ public class ICTokenField: UIView, UITextFieldDelegate, ICBackspaceTextFieldDele private lazy var inputTextField: ICBackspaceTextField = { let _textField = ICBackspaceTextField() - _textField.backgroundColor = UIColor.clearColor() - _textField.clearButtonMode = .WhileEditing - _textField.autocorrectionType = .No - _textField.returnKeyType = .Search + _textField.backgroundColor = UIColor.clear + _textField.clearButtonMode = .whileEditing + _textField.autocorrectionType = .no + _textField.returnKeyType = .search _textField.delegate = self _textField.backspaceDelegate = self - _textField.addTarget(self, action: .togglePlaceholderIfNeeded, forControlEvents: .AllEditingEvents) + _textField.addTarget(self, action: .togglePlaceholderIfNeeded, for: .allEditingEvents) return _textField }() private var leftView: UIView? { didSet { oldValue?.removeFromSuperview() - leftEdgeConstraint.active = leftView == nil + leftEdgeConstraint.isActive = leftView == nil if let icon = leftView { addSubview(icon) icon.translatesAutoresizingMaskIntoConstraints = false - addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("H:|-10-[icon]-10-[wrapper]", options: [], metrics: nil, views: ["icon": icon, "wrapper": scrollView])) - addConstraint(NSLayoutConstraint(item: icon, attribute: .CenterY, relatedBy: .Equal, toItem: self, attribute: .CenterY, multiplier: 1, constant: 0)) + addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "H:|-10-[icon]-10-[wrapper]", options: [], metrics: nil, views: ["icon": icon, "wrapper": scrollView])) + addConstraint(NSLayoutConstraint(item: icon, attribute: .centerY, relatedBy: .equal, toItem: self, attribute: .centerY, multiplier: 1, constant: 0)) } } } @@ -192,15 +192,15 @@ public class ICTokenField: UIView, UITextFieldDelegate, ICBackspaceTextFieldDele private lazy var scrollView: UIScrollView = { let _scrollView = UIScrollView() _scrollView.clipsToBounds = true - _scrollView.directionalLockEnabled = true + _scrollView.isDirectionalLockEnabled = true _scrollView.showsHorizontalScrollIndicator = false _scrollView.showsVerticalScrollIndicator = false - _scrollView.backgroundColor = UIColor.clearColor() + _scrollView.backgroundColor = UIColor.clear return _scrollView }() private lazy var leftEdgeConstraint: NSLayoutConstraint = { - NSLayoutConstraint(item: self.scrollView, attribute: .Left, relatedBy: .Equal, toItem: self, attribute: .Left, multiplier: 1, constant: 10) + NSLayoutConstraint(item: self.scrollView, attribute: .left, relatedBy: .equal, toItem: self, attribute: .left, multiplier: 1, constant: 10) }() private lazy var tapGestureRecognizer: UITapGestureRecognizer = { @@ -223,29 +223,29 @@ public class ICTokenField: UIView, UITextFieldDelegate, ICBackspaceTextFieldDele // MARK: - UIResponder - public override func isFirstResponder() -> Bool { - return inputTextField.isFirstResponder() || super.isFirstResponder() + open override var isFirstResponder: Bool { + return inputTextField.isFirstResponder || super.isFirstResponder } - public override func becomeFirstResponder() -> Bool { + open override func becomeFirstResponder() -> Bool { return inputTextField.becomeFirstResponder() } - public override func resignFirstResponder() -> Bool { + open override func resignFirstResponder() -> Bool { super.resignFirstResponder() return inputTextField.resignFirstResponder() } // MARK: - UIView - public override func layoutSubviews() { + open override func layoutSubviews() { super.layoutSubviews() layoutTokenTextField() } // MARK: - NSKeyValueCoding - public override func setValue(value: AnyObject?, forUndefinedKey key: String) { + open override func setValue(_ value: Any?, forKey key: String) { switch value { case let image as UIImage? where key == "icon": icon = image @@ -262,37 +262,36 @@ public class ICTokenField: UIView, UITextFieldDelegate, ICBackspaceTextFieldDele // MARK: - UITextFieldDelegate - public func textFieldShouldBeginEditing(textField: UITextField) -> Bool { + open func textFieldShouldBeginEditing(_ textField: UITextField) -> Bool { tokens.forEach { $0.highlighted = false } return true } - public func textFieldDidBeginEditing(textField: UITextField) { + open func textFieldDidBeginEditing(_ textField: UITextField) { delegate?.tokenFieldDidBeginEditing?(self) } - public func textFieldDidEndEditing(textField: UITextField) { + open func textFieldDidEndEditing(_ textField: UITextField) { completeCurrentInputText() togglePlaceholderIfNeeded() tokens.forEach { $0.highlighted = false } delegate?.tokenFieldDidEndEditing?(self) } - public func textField(textField: UITextField, shouldChangeCharactersInRange range: NSRange, replacementString string: String) -> Bool { - removeHighlightedToken() // as user starts typing when a token is focused + open func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool { + _ = removeHighlightedToken() // as user starts typing when a token is focused inputTextField.showsCursor = true - guard let - input = textField.text, - text: NSString = (input as NSString).stringByReplacingCharactersInRange(range, withString: string) - else { + guard let input = textField.text else { return true } - for delimiter in delimiters as [NSString] { - let index = text.length - delimiter.length - if 0 < index && text.substringFromIndex(index) == delimiter { - let newToken = text.substringToIndex(index) + let text = (input as NSString).replacingCharacters(in: range, with: string) + + for delimiter in delimiters { + if text.hasSuffix(delimiter) { + let index = text.index(text.endIndex, offsetBy: -delimiter.characters.count) + let newToken = text.substring(to: index) textField.text = nil if newToken != delimiter { @@ -308,7 +307,7 @@ public class ICTokenField: UIView, UITextFieldDelegate, ICBackspaceTextFieldDele return true } - public func textFieldShouldReturn(textField: UITextField) -> Bool { + open func textFieldShouldReturn(_ textField: UITextField) -> Bool { completeCurrentInputText() togglePlaceholderIfNeeded() delegate?.tokenFieldWillReturn?(self) @@ -317,17 +316,17 @@ public class ICTokenField: UIView, UITextFieldDelegate, ICBackspaceTextFieldDele // MARK: - ICBackspaceTextFieldDelegate - func textFieldShouldDelete(textField: ICBackspaceTextField) -> Bool { + func textFieldShouldDelete(_ textField: ICBackspaceTextField) -> Bool { if tokens.isEmpty { return true } if !textField.showsCursor { - removeHighlightedToken() + _ = removeHighlightedToken() return true } - if let text = textField.text where text.isEmpty { + if let text = textField.text, text.isEmpty { textField.showsCursor = false tokens.last?.highlighted = true } @@ -336,17 +335,17 @@ public class ICTokenField: UIView, UITextFieldDelegate, ICBackspaceTextFieldDele // MARK: - UIResponder Callbacks - @objc private func togglePlaceholderIfNeeded(sender: UITextField? = nil) { + @objc fileprivate func togglePlaceholderIfNeeded(_ sender: UITextField? = nil) { let showsPlaceholder = tokens.isEmpty && (inputTextField.text?.isEmpty ?? true) - placeholderLabel.hidden = !showsPlaceholder + placeholderLabel.isHidden = !showsPlaceholder } - @objc private func handleTapGesture(sender: UITapGestureRecognizer) { - if !isFirstResponder() { + @objc fileprivate func handleTapGesture(_ sender: UITapGestureRecognizer) { + if !isFirstResponder { inputTextField.becomeFirstResponder() } - let touch = sender.locationInView(scrollView) + let touch = sender.location(in: scrollView) var shouldFocusInputTextField = true // Hilight the tapped token @@ -367,9 +366,9 @@ public class ICTokenField: UIView, UITextFieldDelegate, ICBackspaceTextFieldDele /// Returns true if any highlighted token is found and removed, otherwise false. private func removeHighlightedToken() -> Bool { - for (index, token) in tokens.enumerate() { + for (index, token) in tokens.enumerated() { if token.highlighted { - tokens.removeAtIndex(index) + tokens.remove(at: index) layoutTokenTextField() togglePlaceholderIfNeeded() inputTextField.showsCursor = true @@ -381,8 +380,8 @@ public class ICTokenField: UIView, UITextFieldDelegate, ICBackspaceTextFieldDele } private func setUpSubviews() { - if CGRectEqualToRect(frame, CGRect.zero) { - frame = CGRect(x: 0, y: 7, width: UIScreen.mainScreen().bounds.width, height: 30) + if frame.equalTo(CGRect.zero) { + frame = CGRect(x: 0, y: 7, width: UIScreen.main.bounds.width, height: 30) } addSubview(scrollView) @@ -390,9 +389,9 @@ public class ICTokenField: UIView, UITextFieldDelegate, ICBackspaceTextFieldDele scrollView.translatesAutoresizingMaskIntoConstraints = false let views = ["wrapper": scrollView] - addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("H:|-(>=10)-[wrapper]|", options: [], metrics: nil, views: views)) - addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("V:|[wrapper]|", options: [], metrics: nil, views: views)) - leftEdgeConstraint.active = true + addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "H:|-(>=10)-[wrapper]|", options: [], metrics: nil, views: views)) + addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "V:|[wrapper]|", options: [], metrics: nil, views: views)) + leftEdgeConstraint.isActive = true layoutTokenTextField() addGestureRecognizer(tapGestureRecognizer) @@ -433,8 +432,8 @@ public class ICTokenField: UIView, UITextFieldDelegate, ICBackspaceTextFieldDele // MARK: - Public Methods /// Creates a token with the current input text. - public func completeCurrentInputText() { - guard let text = inputTextField.text where !text.isEmpty else { + open func completeCurrentInputText() { + guard let text = inputTextField.text, !text.isEmpty else { return } inputTextField.text = nil @@ -444,7 +443,7 @@ public class ICTokenField: UIView, UITextFieldDelegate, ICBackspaceTextFieldDele } /// Removes the input text and all displayed tokens. - public func resetTokens() { + open func resetTokens() { inputTextField.text = nil tokens.removeAll() layoutTokenTextField()