diff --git a/README.md b/README.md index 3a62cbc..6985818 100644 --- a/README.md +++ b/README.md @@ -1,27 +1,34 @@ -# Segmented Controller +### Updated for Swift 4 + +Requires Xcode 9 and Swift 4. + +### Segmented Controller + - Simple & highly customizable segmented control written in Swift - Designable on the Interface Builder ![SegmentedController](SegmentedController/images/SegmentedController.gif) -# Installation -- Via Carthage +### Installation +##### Via Carthage + - Add `github 'dobaduc/segmentedcontroller'` to your `Cartfile` - Run `carthage update` -- Via Cocoapods -``` -pod 'SegmentedController' -``` +##### Via Cocoapods + +- Add `pod 'SegmentedController'` to your `Podfile` +- Run `pod install` + +### Components -# Components - SegmentedControl - A customized segmentedControl - SegmentedViewController - A container view controller having a segmented control on top -# Examples +### Examples - Check out SegmentedControllerExample project for more details -# License +### License SegmentedController is released under the MIT license. See [LICENSE](LICENSE) for details. diff --git a/SegmentedController.podspec b/SegmentedController.podspec index 0e52d3e..4e39fbc 100644 --- a/SegmentedController.podspec +++ b/SegmentedController.podspec @@ -1,6 +1,6 @@ Pod::Spec.new do |s| s.name = "SegmentedController" - s.version = "0.1.1" + s.version = "0.2.0" s.summary = "Segmented controller component" s.description = "Simple yet highly customizable segmented controller component written in Swift" s.homepage = "https://github.com/dobaduc/segmentedcontroller" @@ -12,5 +12,5 @@ Pod::Spec.new do |s| } s.source_files = ["SegmentedController/**/*.{swift,h,xib}"] s.requires_arc = true - s.ios.deployment_target = '8.0' + s.ios.deployment_target = '10.0' end diff --git a/SegmentedController.xcodeproj/project.pbxproj b/SegmentedController.xcodeproj/project.pbxproj index e5bc4b9..a421e41 100644 --- a/SegmentedController.xcodeproj/project.pbxproj +++ b/SegmentedController.xcodeproj/project.pbxproj @@ -169,7 +169,7 @@ attributes = { LastSwiftMigration = 0720; LastSwiftUpdateCheck = 0720; - LastUpgradeCheck = 0640; + LastUpgradeCheck = 0920; ORGANIZATIONNAME = "Ducky Duke"; TargetAttributes = { C6D98F1F1B8DDF4D008C22E7 = { @@ -253,13 +253,21 @@ CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; 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_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; @@ -267,6 +275,7 @@ CURRENT_PROJECT_VERSION = 1; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; GCC_C_LANGUAGE_STANDARD = gnu99; GCC_DYNAMIC_NO_PIC = NO; GCC_NO_COMMON_BLOCKS = YES; @@ -301,13 +310,21 @@ CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; 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_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; @@ -327,6 +344,7 @@ IPHONEOS_DEPLOYMENT_TARGET = 8.4; MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = iphoneos; + SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; TARGETED_DEVICE_FAMILY = "1,2"; VALIDATE_PRODUCT = YES; VERSIONING_SYSTEM = "apple-generic"; @@ -338,6 +356,7 @@ isa = XCBuildConfiguration; buildSettings = { CLANG_ENABLE_MODULES = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; DEFINES_MODULE = YES; DYLIB_COMPATIBILITY_VERSION = 1; DYLIB_CURRENT_VERSION = 1; @@ -345,9 +364,11 @@ INFOPLIST_FILE = SegmentedController/Info.plist; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + PRODUCT_BUNDLE_IDENTIFIER = "ducky.duke.$(PRODUCT_NAME:rfc1034identifier)"; PRODUCT_NAME = "$(TARGET_NAME)"; SKIP_INSTALL = YES; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_VERSION = 4.0; }; name = Debug; }; @@ -355,6 +376,7 @@ isa = XCBuildConfiguration; buildSettings = { CLANG_ENABLE_MODULES = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; DEFINES_MODULE = YES; DYLIB_COMPATIBILITY_VERSION = 1; DYLIB_CURRENT_VERSION = 1; @@ -362,8 +384,10 @@ INFOPLIST_FILE = SegmentedController/Info.plist; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + PRODUCT_BUNDLE_IDENTIFIER = "ducky.duke.$(PRODUCT_NAME:rfc1034identifier)"; PRODUCT_NAME = "$(TARGET_NAME)"; SKIP_INSTALL = YES; + SWIFT_VERSION = 4.0; }; name = Release; }; @@ -380,6 +404,7 @@ ); INFOPLIST_FILE = SegmentedControllerTests/Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + PRODUCT_BUNDLE_IDENTIFIER = "ducky.duke.$(PRODUCT_NAME:rfc1034identifier)"; PRODUCT_NAME = "$(TARGET_NAME)"; }; name = Debug; @@ -393,6 +418,7 @@ ); INFOPLIST_FILE = SegmentedControllerTests/Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + PRODUCT_BUNDLE_IDENTIFIER = "ducky.duke.$(PRODUCT_NAME:rfc1034identifier)"; PRODUCT_NAME = "$(TARGET_NAME)"; }; name = Release; diff --git a/SegmentedController/Info.plist b/SegmentedController/Info.plist index ac3731e..d3de8ee 100644 --- a/SegmentedController/Info.plist +++ b/SegmentedController/Info.plist @@ -7,7 +7,7 @@ CFBundleExecutable $(EXECUTABLE_NAME) CFBundleIdentifier - ducky.duke.$(PRODUCT_NAME:rfc1034identifier) + $(PRODUCT_BUNDLE_IDENTIFIER) CFBundleInfoDictionaryVersion 6.0 CFBundleName diff --git a/SegmentedController/SegmentedControl.swift b/SegmentedController/SegmentedControl.swift index 61ab2a8..6b40d44 100644 --- a/SegmentedController/SegmentedControl.swift +++ b/SegmentedController/SegmentedControl.swift @@ -8,6 +8,13 @@ import UIKit +public enum AnimationType { + case bounce + case fade + case slide + case none +} + @IBDesignable public class SegmentedControl: UIControl { // Background @@ -15,22 +22,22 @@ public class SegmentedControl: UIControl { var selectedBackgroundViewHeight: CGFloat = 0 { didSet { updateSelectedBackgroundFrame() } } @IBInspectable public - var selectedBackgroundColor: UIColor = UIColor.darkGrayColor() { didSet { updateSelectedBackgroundColor() } } + var selectedBackgroundColor: UIColor = UIColor.darkGray { didSet { updateSelectedBackgroundColor() } } // Title @IBInspectable public - var titleFont: UIFont = UIFont.boldSystemFontOfSize(12) { didSet { updateTitleStyle() } } + var titleFont: UIFont = UIFont.boldSystemFont(ofSize: 12) { didSet { updateTitleStyle() } } @IBInspectable public - var titleColor: UIColor = UIColor.darkGrayColor() { didSet { updateTitleStyle() } } + var titleColor: UIColor = UIColor.darkGray { didSet { updateTitleStyle() } } @IBInspectable public - var highlightedTitleColor: UIColor = UIColor.yellowColor() { didSet { updateTitleStyle() } } + var highlightedTitleColor: UIColor = UIColor.yellow { didSet { updateTitleStyle() } } @IBInspectable public - var selectedTitleColor: UIColor = UIColor.whiteColor() { didSet { updateTitleStyle() } } + var selectedTitleColor: UIColor = UIColor.white { didSet { updateTitleStyle() } } // Segment @IBInspectable public - var segmentTitles: String = "" { didSet { updateSegments(segmentTitles) } } - public var segments: [SegmentTitleProvider] = ["Title 1", "Title 2"] { didSet { updateSegments(nil) } } + var segmentTitles: String = "" { didSet { updateSegments(titles: segmentTitles) } } + public var segments: [SegmentTitleProvider] = ["Title 1", "Title 2"] { didSet { updateSegments(titles: nil) } } public private(set) var segmentItems: [UIButton] = [] // Selected @@ -43,12 +50,12 @@ public class SegmentedControl: UIControl { selectedIndex = segments.count - 1 } if selectedIndex < segmentItems.count { - updateSelectedIndex(animationEnabled) + updateSelectedIndex(animated: true) } } } - @IBInspectable public var animationEnabled: Bool = true + public var animationType: AnimationType = .bounce public let selectedBackgroundView = UIView() @@ -66,11 +73,11 @@ public class SegmentedControl: UIControl { super.layoutSubviews() updateSegmentFrames() - updateSelectedIndex(false) + updateSelectedIndex(animated: false) } - public func segmentTouched(sender: UIButton) { - if let index = segmentItems.indexOf(sender) { + @objc public func segmentTouched(sender: UIButton) { + if let index = segmentItems.index(of: sender) { selectedIndex = index } } @@ -79,13 +86,13 @@ public class SegmentedControl: UIControl { // MARK:- Private methods private extension SegmentedControl { func configureElements() { - insertSubview(selectedBackgroundView, atIndex: 0) - updateSegments(nil) + insertSubview(selectedBackgroundView, at: 0) + updateSegments(titles: nil) } func updateSegments(titles: String?) { if let titles = titles { - let extractedTitles = titles.characters.split(100, allowEmptySlices: false, isSeparator: { $0 == "," }).map { String($0) } + let extractedTitles = titles.split(separator: ",").map { String($0) } segments = extractedTitles.map({ $0 }) return } @@ -94,12 +101,12 @@ private extension SegmentedControl { for segmentItem in segmentItems { segmentItem.removeFromSuperview() } - segmentItems.removeAll(keepCapacity: true) + segmentItems.removeAll(keepingCapacity: true) // Reset data if segments.count > 0 { let itemWidth: CGFloat = frame.width / CGFloat(segments.count) - for (index, segment) in segments.enumerate() { + for (index, segment) in segments.enumerated() { let item = UIButton(frame: CGRect( x: itemWidth * CGFloat(index), y: 0, @@ -107,9 +114,9 @@ private extension SegmentedControl { height: frame.height )) - item.selected = (index == selectedIndex) - item.setTitle(segment.segmentTitle(), forState: .Normal) - item.addTarget(self, action: "segmentTouched:", forControlEvents: UIControlEvents.TouchUpInside) + item.isSelected = (index == selectedIndex) + item.setTitle(segment.segmentTitle(), for: .normal) + item.addTarget(self, action: #selector(self.segmentTouched(sender:)), for: UIControl.Event.touchUpInside) addSubview(item) segmentItems.append(item) @@ -117,13 +124,13 @@ private extension SegmentedControl { } updateTitleStyle() - updateSelectedIndex(false) + updateSelectedIndex(animated: false) } func updateSegmentFrames() { if segments.count > 0 { let itemWidth: CGFloat = frame.width / CGFloat(segmentItems.count) - for (index, item) in segmentItems.enumerate() { + for (index, item) in segmentItems.enumerated() { item.frame = CGRect( x: itemWidth * CGFloat(index), y: 0, @@ -136,33 +143,54 @@ private extension SegmentedControl { func updateTitleStyle() { for item in segmentItems { - item.setTitleColor(titleColor, forState: .Normal) - item.setTitleColor(highlightedTitleColor, forState: .Highlighted) - item.setTitleColor(selectedTitleColor, forState: .Selected) + item.setTitleColor(titleColor, for: .normal) + item.setTitleColor(highlightedTitleColor, for: .highlighted) + item.setTitleColor(selectedTitleColor, for: .selected) + item.setTitleColor(selectedTitleColor, for: .disabled) item.titleLabel?.font = titleFont } } func updateSelectedIndex(animated: Bool) { for item in segmentItems { - item.selected = false + item.isSelected = false + + if animated { + switch animationType { + case .bounce, .fade, .slide: + item.fadeTransition(0.2) + case .none: + break + } + } } + + self.segmentItems[self.selectedIndex].isSelected = true + self.sendActions(for: .valueChanged) + if animated { - UIView.animateWithDuration(0.3, - delay: 0, - usingSpringWithDamping: 0.7, - initialSpringVelocity: 0.3, - options: UIViewAnimationOptions.CurveEaseOut, - animations: { + switch animationType { + case .bounce: + UIView.animate(withDuration: 0.3, + delay: 0, + usingSpringWithDamping: 0.7, + initialSpringVelocity: 0.3, + options: UIView.AnimationOptions.curveEaseInOut, + animations: { + self.updateSelectedBackgroundFrame() + }, completion: nil) + case .fade: + self.fadeTransition(0.2) + self.updateSelectedBackgroundFrame() + case .slide: + UIView.animate(withDuration: 0.1, delay: 0.0, options: [.curveEaseInOut], animations: { self.updateSelectedBackgroundFrame() - }, completion: { finished in - self.segmentItems[self.selectedIndex].selected = true - self.sendActionsForControlEvents(.ValueChanged) - }) + }) + case .none: + self.updateSelectedBackgroundFrame() + } } else { - updateSelectedBackgroundFrame() - segmentItems[selectedIndex].selected = true - sendActionsForControlEvents(.ValueChanged) + self.updateSelectedBackgroundFrame() } } @@ -197,4 +225,15 @@ extension UIViewController: SegmentTitleProvider { public func segmentTitle() -> String { return title ?? "" } -} \ No newline at end of file +} + +extension UIView { + func fadeTransition(_ duration:CFTimeInterval) { + let animation = CATransition() + animation.timingFunction = CAMediaTimingFunction(name: + CAMediaTimingFunctionName.easeInEaseOut) + animation.type = CATransitionType.fade + animation.duration = duration + layer.add(animation, forKey: CATransitionType.fade.rawValue) + } +} diff --git a/SegmentedController/SegmentedViewController.swift b/SegmentedController/SegmentedViewController.swift index 7fdc981..2b64db3 100644 --- a/SegmentedController/SegmentedViewController.swift +++ b/SegmentedController/SegmentedViewController.swift @@ -22,7 +22,7 @@ public class SegmentedViewController: UIViewController { } public init() { - super.init(nibName: "SegmentedViewController", bundle: NSBundle(forClass: SegmentedViewController.self)) + super.init(nibName: "SegmentedViewController", bundle: Bundle(for: SegmentedViewController.self)) } public override func viewDidLoad() { @@ -30,46 +30,46 @@ public class SegmentedViewController: UIViewController { configure() } - public func didChangeSelectedIndex(sender: SegmentedControl) { - showChildViewController(viewControllers[segmentedControl.selectedIndex]) + @objc public func didChangeSelectedIndex(sender: SegmentedControl) { + showChildViewController(viewController: viewControllers[segmentedControl.selectedIndex]) } func configure() { - segmentedControl.addTarget(self, action: "didChangeSelectedIndex:", forControlEvents: .ValueChanged) + segmentedControl.addTarget(self, action: #selector(self.didChangeSelectedIndex(sender:)), for: .valueChanged) } } public extension SegmentedViewController { public func showChildViewController(viewController: UIViewController) { - addChildViewController(viewController) + addChild(viewController) view.addSubview(viewController.view) - viewController.didMoveToParentViewController(self) + viewController.didMove(toParent: self) } public func hideChildViewController(viewController: UIViewController) { - viewController.willMoveToParentViewController(self) + viewController.willMove(toParent: self) viewController.view.removeFromSuperview() - viewController.removeFromParentViewController() + viewController.removeFromParent() } public func switchViewControllers(from: UIViewController, to: UIViewController) { - from.willMoveToParentViewController(self) + from.willMove(toParent: self) // Alpha only by default - addChildViewController(to) + addChild(to) to.view.alpha = 0 - transitionFromViewController( - from, - toViewController: to, + transition( + from: from, + to: to, duration: 0.3, - options: .CurveEaseOut, + options: .curveEaseOut, animations: { to.view.alpha = 1 from.view.alpha = 0 }) { finished in - from.removeFromParentViewController() - to.didMoveToParentViewController(self) + from.removeFromParent() + to.didMove(toParent: self) } } } diff --git a/SegmentedControllerExample/SegmentedControllerExample.xcodeproj/project.pbxproj b/SegmentedControllerExample/SegmentedControllerExample.xcodeproj/project.pbxproj index da30f03..806176c 100644 --- a/SegmentedControllerExample/SegmentedControllerExample.xcodeproj/project.pbxproj +++ b/SegmentedControllerExample/SegmentedControllerExample.xcodeproj/project.pbxproj @@ -7,13 +7,14 @@ objects = { /* Begin PBXBuildFile section */ + 26423432201770AB006B3C23 /* SegmentedController.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 26423433201770AB006B3C23 /* SegmentedController.framework */; }; + 26423436201771A5006B3C23 /* SegmentedController.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 26423433201770AB006B3C23 /* SegmentedController.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; C6D98F4B1B8DDF92008C22E7 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = C6D98F4A1B8DDF92008C22E7 /* AppDelegate.swift */; }; C6D98F4D1B8DDF92008C22E7 /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = C6D98F4C1B8DDF92008C22E7 /* ViewController.swift */; }; C6D98F501B8DDF92008C22E7 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = C6D98F4E1B8DDF92008C22E7 /* Main.storyboard */; }; C6D98F521B8DDF92008C22E7 /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = C6D98F511B8DDF92008C22E7 /* Images.xcassets */; }; C6D98F551B8DDF92008C22E7 /* LaunchScreen.xib in Resources */ = {isa = PBXBuildFile; fileRef = C6D98F531B8DDF92008C22E7 /* LaunchScreen.xib */; }; C6D98F611B8DDF92008C22E7 /* SegmentedControllerExampleTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = C6D98F601B8DDF92008C22E7 /* SegmentedControllerExampleTests.swift */; }; - C6D98F6B1B8DE007008C22E7 /* SegmentedController.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = C6D98F6A1B8DE007008C22E7 /* SegmentedController.framework */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ @@ -26,7 +27,22 @@ }; /* End PBXContainerItemProxy section */ +/* Begin PBXCopyFilesBuildPhase section */ + 26423437201771A6006B3C23 /* Embed Frameworks */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = ""; + dstSubfolderSpec = 10; + files = ( + 26423436201771A5006B3C23 /* SegmentedController.framework in Embed Frameworks */, + ); + name = "Embed Frameworks"; + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXCopyFilesBuildPhase section */ + /* Begin PBXFileReference section */ + 26423433201770AB006B3C23 /* SegmentedController.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = SegmentedController.framework; sourceTree = BUILT_PRODUCTS_DIR; }; C6D98F451B8DDF92008C22E7 /* SegmentedControllerExample.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = SegmentedControllerExample.app; sourceTree = BUILT_PRODUCTS_DIR; }; C6D98F491B8DDF92008C22E7 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; C6D98F4A1B8DDF92008C22E7 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; @@ -37,7 +53,6 @@ C6D98F5A1B8DDF92008C22E7 /* SegmentedControllerExampleTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = SegmentedControllerExampleTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; C6D98F5F1B8DDF92008C22E7 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; C6D98F601B8DDF92008C22E7 /* SegmentedControllerExampleTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SegmentedControllerExampleTests.swift; sourceTree = ""; }; - C6D98F6A1B8DE007008C22E7 /* SegmentedController.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SegmentedController.framework; path = "../build/Debug-iphoneos/SegmentedController.framework"; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -45,7 +60,7 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( - C6D98F6B1B8DE007008C22E7 /* SegmentedController.framework in Frameworks */, + 26423432201770AB006B3C23 /* SegmentedController.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -59,13 +74,21 @@ /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ + 26423431201770AB006B3C23 /* Frameworks */ = { + isa = PBXGroup; + children = ( + 26423433201770AB006B3C23 /* SegmentedController.framework */, + ); + name = Frameworks; + sourceTree = ""; + }; C6D98F3C1B8DDF92008C22E7 = { isa = PBXGroup; children = ( - C6D98F6A1B8DE007008C22E7 /* SegmentedController.framework */, C6D98F471B8DDF92008C22E7 /* SegmentedControllerExample */, C6D98F5D1B8DDF92008C22E7 /* SegmentedControllerExampleTests */, C6D98F461B8DDF92008C22E7 /* Products */, + 26423431201770AB006B3C23 /* Frameworks */, ); sourceTree = ""; }; @@ -126,6 +149,7 @@ C6D98F411B8DDF92008C22E7 /* Sources */, C6D98F421B8DDF92008C22E7 /* Frameworks */, C6D98F431B8DDF92008C22E7 /* Resources */, + 26423437201771A6006B3C23 /* Embed Frameworks */, ); buildRules = ( ); @@ -162,11 +186,12 @@ attributes = { LastSwiftMigration = 0720; LastSwiftUpdateCheck = 0720; - LastUpgradeCheck = 0640; + LastUpgradeCheck = 0920; ORGANIZATIONNAME = "Ducky Duke"; TargetAttributes = { C6D98F441B8DDF92008C22E7 = { CreatedOnToolsVersion = 6.4; + DevelopmentTeam = Z3UM9FW8JQ; }; C6D98F591B8DDF92008C22E7 = { CreatedOnToolsVersion = 6.4; @@ -269,19 +294,28 @@ CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; 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_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; COPY_PHASE_STRIP = NO; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; GCC_C_LANGUAGE_STANDARD = gnu99; GCC_DYNAMIC_NO_PIC = NO; GCC_NO_COMMON_BLOCKS = YES; @@ -302,6 +336,7 @@ ONLY_ACTIVE_ARCH = YES; SDKROOT = iphoneos; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_VERSION = 4.0; TARGETED_DEVICE_FAMILY = "1,2"; }; name = Debug; @@ -314,13 +349,21 @@ CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; 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_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; @@ -339,6 +382,8 @@ IPHONEOS_DEPLOYMENT_TARGET = 8.4; MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = iphoneos; + SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; + SWIFT_VERSION = 4.0; TARGETED_DEVICE_FAMILY = "1,2"; VALIDATE_PRODUCT = YES; }; @@ -347,28 +392,36 @@ C6D98F651B8DDF92008C22E7 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { + ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + DEVELOPMENT_TEAM = Z3UM9FW8JQ; FRAMEWORK_SEARCH_PATHS = ( "$(inherited)", "/Users/doba/workspace/ios/SegmentedController/build/Debug-iphoneos", ); INFOPLIST_FILE = SegmentedControllerExample/Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + PRODUCT_BUNDLE_IDENTIFIER = "ducky.duke.$(PRODUCT_NAME:rfc1034identifier)"; PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 4.0; }; name = Debug; }; C6D98F661B8DDF92008C22E7 /* Release */ = { isa = XCBuildConfiguration; buildSettings = { + ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + DEVELOPMENT_TEAM = Z3UM9FW8JQ; FRAMEWORK_SEARCH_PATHS = ( "$(inherited)", "/Users/doba/workspace/ios/SegmentedController/build/Debug-iphoneos", ); INFOPLIST_FILE = SegmentedControllerExample/Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + PRODUCT_BUNDLE_IDENTIFIER = "ducky.duke.$(PRODUCT_NAME:rfc1034identifier)"; PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 4.0; }; name = Release; }; @@ -386,7 +439,9 @@ ); INFOPLIST_FILE = SegmentedControllerExampleTests/Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + PRODUCT_BUNDLE_IDENTIFIER = "ducky.duke.$(PRODUCT_NAME:rfc1034identifier)"; PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 4.0; TEST_HOST = "$(BUILT_PRODUCTS_DIR)/SegmentedControllerExample.app/SegmentedControllerExample"; }; name = Debug; @@ -401,7 +456,9 @@ ); INFOPLIST_FILE = SegmentedControllerExampleTests/Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + PRODUCT_BUNDLE_IDENTIFIER = "ducky.duke.$(PRODUCT_NAME:rfc1034identifier)"; PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 4.0; TEST_HOST = "$(BUILT_PRODUCTS_DIR)/SegmentedControllerExample.app/SegmentedControllerExample"; }; name = Release; diff --git a/SegmentedControllerExample/SegmentedControllerExample/AppDelegate.swift b/SegmentedControllerExample/SegmentedControllerExample/AppDelegate.swift index d0a8757..8619ad5 100644 --- a/SegmentedControllerExample/SegmentedControllerExample/AppDelegate.swift +++ b/SegmentedControllerExample/SegmentedControllerExample/AppDelegate.swift @@ -14,30 +14,30 @@ class AppDelegate: UIResponder, UIApplicationDelegate { var window: UIWindow? - func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool { + func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool { // Override point for customization after application launch. return true } - func applicationWillResignActive(application: UIApplication) { + func applicationWillResignActive(_ application: UIApplication) { // 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. - // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game. + // Use this method to pause ongoing tasks, disable timers, and invalidate graphics rendering callbacks. Games should use this method to pause the game. } - - func applicationDidEnterBackground(application: UIApplication) { + + func applicationDidEnterBackground(_ application: UIApplication) { // 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. // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. } - - func applicationWillEnterForeground(application: UIApplication) { - // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background. + + func applicationWillEnterForeground(_ application: UIApplication) { + // 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. } - - func applicationDidBecomeActive(application: UIApplication) { + + func applicationDidBecomeActive(_ application: UIApplication) { // 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. } - - func applicationWillTerminate(application: UIApplication) { + + func applicationWillTerminate(_ application: UIApplication) { // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. } diff --git a/SegmentedControllerExample/SegmentedControllerExample/Base.lproj/Main.storyboard b/SegmentedControllerExample/SegmentedControllerExample/Base.lproj/Main.storyboard index c127d77..f2e62c3 100644 --- a/SegmentedControllerExample/SegmentedControllerExample/Base.lproj/Main.storyboard +++ b/SegmentedControllerExample/SegmentedControllerExample/Base.lproj/Main.storyboard @@ -1,8 +1,12 @@ - - + + + + + - + + @@ -14,10 +18,10 @@ - + - + @@ -25,18 +29,18 @@ - + - + - + @@ -45,13 +49,13 @@ - + - + @@ -59,7 +63,7 @@ - + @@ -89,7 +93,7 @@ - + @@ -102,13 +106,13 @@ - + - + @@ -139,14 +143,14 @@ - - + @@ -173,7 +177,6 @@ - @@ -188,7 +191,7 @@ - + diff --git a/SegmentedControllerExample/SegmentedControllerExample/Info.plist b/SegmentedControllerExample/SegmentedControllerExample/Info.plist index 665adf5..40c6215 100644 --- a/SegmentedControllerExample/SegmentedControllerExample/Info.plist +++ b/SegmentedControllerExample/SegmentedControllerExample/Info.plist @@ -7,7 +7,7 @@ CFBundleExecutable $(EXECUTABLE_NAME) CFBundleIdentifier - ducky.duke.$(PRODUCT_NAME:rfc1034identifier) + $(PRODUCT_BUNDLE_IDENTIFIER) CFBundleInfoDictionaryVersion 6.0 CFBundleName diff --git a/SegmentedControllerExample/SegmentedControllerExample/ViewController.swift b/SegmentedControllerExample/SegmentedControllerExample/ViewController.swift index e66088d..cb06fb5 100644 --- a/SegmentedControllerExample/SegmentedControllerExample/ViewController.swift +++ b/SegmentedControllerExample/SegmentedControllerExample/ViewController.swift @@ -27,19 +27,19 @@ class ViewController: UIViewController { segmentedVC.view.frame = segmentedViewControllerContainer.bounds segmentedVC.viewControllers = [ - tableViewVCWithColor(UIColor.redColor(), title: "Red"), - tableViewVCWithColor(UIColor.greenColor(), title: "Green"), - tableViewVCWithColor(UIColor.blueColor(), title: "Blue") + tableViewVCWithColor(color: UIColor.red, title: "Red"), + tableViewVCWithColor(color: UIColor.green, title: "Green"), + tableViewVCWithColor(color: UIColor.blue, title: "Blue") ] } - override func viewWillAppear(animated: Bool) { + override func viewWillAppear(_ animated: Bool) { super.viewWillAppear(animated) - segmentedVC.segmentedControl.selectedBackgroundColor = UIColor.orangeColor() + segmentedVC.segmentedControl.selectedBackgroundColor = UIColor.orange } func tableViewVCWithColor(color: UIColor, title: String) -> UITableViewController { - let tb = UITableViewController(style: .Plain) + let tb = UITableViewController(style: .plain) tb.tableView.backgroundColor = color tb.title = title diff --git a/SegmentedControllerExample/SegmentedControllerExampleTests/Info.plist b/SegmentedControllerExample/SegmentedControllerExampleTests/Info.plist index 7bdafde..ba72822 100644 --- a/SegmentedControllerExample/SegmentedControllerExampleTests/Info.plist +++ b/SegmentedControllerExample/SegmentedControllerExampleTests/Info.plist @@ -7,7 +7,7 @@ CFBundleExecutable $(EXECUTABLE_NAME) CFBundleIdentifier - ducky.duke.$(PRODUCT_NAME:rfc1034identifier) + $(PRODUCT_BUNDLE_IDENTIFIER) CFBundleInfoDictionaryVersion 6.0 CFBundleName diff --git a/SegmentedControllerTests/Info.plist b/SegmentedControllerTests/Info.plist index 7bdafde..ba72822 100644 --- a/SegmentedControllerTests/Info.plist +++ b/SegmentedControllerTests/Info.plist @@ -7,7 +7,7 @@ CFBundleExecutable $(EXECUTABLE_NAME) CFBundleIdentifier - ducky.duke.$(PRODUCT_NAME:rfc1034identifier) + $(PRODUCT_BUNDLE_IDENTIFIER) CFBundleInfoDictionaryVersion 6.0 CFBundleName