diff --git a/Alertift.podspec b/Alertift.podspec index f7b5486..edea248 100644 --- a/Alertift.podspec +++ b/Alertift.podspec @@ -1,6 +1,6 @@ Pod::Spec.new do |s| s.name = "Alertift" - s.version = "1.0.1" + s.version = "1.1" s.summary = "UIAlertControlelr wrapper for Swift." s.homepage = "https://github.com/sgr-ksmt/Alertift" # s.screenshots = "" diff --git a/Alertift.xcodeproj/project.pbxproj b/Alertift.xcodeproj/project.pbxproj index 7082a54..1293327 100644 --- a/Alertift.xcodeproj/project.pbxproj +++ b/Alertift.xcodeproj/project.pbxproj @@ -11,11 +11,11 @@ 4D13C7B11EB22B8F007BBB43 /* Action.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4D13C7AB1EB22B8F007BBB43 /* Action.swift */; }; 4D13C7B21EB22B8F007BBB43 /* ActionSheet.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4D13C7AC1EB22B8F007BBB43 /* ActionSheet.swift */; }; 4D13C7B31EB22B8F007BBB43 /* Alert.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4D13C7AD1EB22B8F007BBB43 /* Alert.swift */; }; - 4D13C7B41EB22B8F007BBB43 /* AlertBase.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4D13C7AE1EB22B8F007BBB43 /* AlertBase.swift */; }; 4D13C7B51EB22B8F007BBB43 /* Alertift.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4D13C7AF1EB22B8F007BBB43 /* Alertift.swift */; }; 4D13C7B61EB22B8F007BBB43 /* InnerAlertController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4D13C7B01EB22B8F007BBB43 /* InnerAlertController.swift */; }; 4D13C7BF1EB320D4007BBB43 /* ActionHandlerBuilder.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4D13C7BE1EB320D4007BBB43 /* ActionHandlerBuilder.swift */; }; 4D13C7C11EB32AE6007BBB43 /* Debug.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4D13C7C01EB32AE6007BBB43 /* Debug.swift */; }; + 4D13C7C51EB5DFB7007BBB43 /* AlertType.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4D13C7C41EB5DFB7007BBB43 /* AlertType.swift */; }; /* End PBXBuildFile section */ /* Begin PBXFileReference section */ @@ -25,11 +25,11 @@ 4D13C7AB1EB22B8F007BBB43 /* Action.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Action.swift; sourceTree = ""; }; 4D13C7AC1EB22B8F007BBB43 /* ActionSheet.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ActionSheet.swift; sourceTree = ""; }; 4D13C7AD1EB22B8F007BBB43 /* Alert.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Alert.swift; sourceTree = ""; }; - 4D13C7AE1EB22B8F007BBB43 /* AlertBase.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AlertBase.swift; sourceTree = ""; }; 4D13C7AF1EB22B8F007BBB43 /* Alertift.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Alertift.swift; sourceTree = ""; }; 4D13C7B01EB22B8F007BBB43 /* InnerAlertController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = InnerAlertController.swift; sourceTree = ""; }; 4D13C7BE1EB320D4007BBB43 /* ActionHandlerBuilder.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ActionHandlerBuilder.swift; sourceTree = ""; }; 4D13C7C01EB32AE6007BBB43 /* Debug.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Debug.swift; sourceTree = ""; }; + 4D13C7C41EB5DFB7007BBB43 /* AlertType.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AlertType.swift; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -73,13 +73,13 @@ isa = PBXGroup; children = ( 4D13C7AF1EB22B8F007BBB43 /* Alertift.swift */, - 4D13C7AE1EB22B8F007BBB43 /* AlertBase.swift */, 4D13C7AD1EB22B8F007BBB43 /* Alert.swift */, 4D13C7AC1EB22B8F007BBB43 /* ActionSheet.swift */, 4D13C7AB1EB22B8F007BBB43 /* Action.swift */, 4D13C7B01EB22B8F007BBB43 /* InnerAlertController.swift */, 4D13C7BE1EB320D4007BBB43 /* ActionHandlerBuilder.swift */, 4D13C7C01EB32AE6007BBB43 /* Debug.swift */, + 4D13C7C41EB5DFB7007BBB43 /* AlertType.swift */, ); path = Sources; sourceTree = ""; @@ -167,8 +167,8 @@ 4D13C7B31EB22B8F007BBB43 /* Alert.swift in Sources */, 4D13C7BF1EB320D4007BBB43 /* ActionHandlerBuilder.swift in Sources */, 4D13C7B61EB22B8F007BBB43 /* InnerAlertController.swift in Sources */, - 4D13C7B41EB22B8F007BBB43 /* AlertBase.swift in Sources */, 4D13C7B11EB22B8F007BBB43 /* Action.swift in Sources */, + 4D13C7C51EB5DFB7007BBB43 /* AlertType.swift in Sources */, 4D13C7C11EB32AE6007BBB43 /* Debug.swift in Sources */, 4D13C7B51EB22B8F007BBB43 /* Alertift.swift in Sources */, 4D13C7B21EB22B8F007BBB43 /* ActionSheet.swift in Sources */, diff --git a/Demo/Demo/ViewController.swift b/Demo/Demo/ViewController.swift index 09b8469..64f95d4 100644 --- a/Demo/Demo/ViewController.swift +++ b/Demo/Demo/ViewController.swift @@ -43,9 +43,15 @@ class ViewController: UIViewController { } } + override func viewDidLoad() { + super.viewDidLoad() + } + override func viewDidAppear(_ animated: Bool) { super.viewDidAppear(animated) Alertift.alert(title: "Alertift", message: "Alertift is swifty, modern, and awesome UIAlertController wrapper.") + .titleTextColor(.red) + .messageTextColor(.blue) .action(.default("❤")) .action(.default("⭐")) .show(on: self) @@ -96,22 +102,22 @@ class ViewController: UIViewController { .show() } private func showActionSheet(source: UIView, frame: CGRect) { - Alertift.actionSheet(message: "Which food do you like?") - .popover(sourceView: source, sourceRect: frame) - .action(.default("🍣")) - .action(.default("🍎")) - .action(.default("🍖")) - .action(.default("🍅")) - .action(.cancel("None of them")) - .finally { action, index in - if action.style == .cancel { - return + Alertift.actionSheet(message: "Which food do you like?") + .popover(sourceView: source, sourceRect: frame) + .action(.default("🍣")) + .action(.default("🍎")) + .action(.default("🍖")) + .action(.default("🍅")) + .action(.cancel("None of them")) + .finally { action, index in + if action.style == .cancel { + return + } + Alertift.alert(message: "\(index). \(action.title!)") + .action(.default("OK")) + .show() } - Alertift.alert(message: "\(index). \(action.title!)") - .action(.default("OK")) - .show() - } - .show() + .show() } } diff --git a/Documents/img6.png b/Documents/img6.png new file mode 100644 index 0000000..62695e0 Binary files /dev/null and b/Documents/img6.png differ diff --git a/README.md b/README.md index 09ff35e..6a48559 100644 --- a/README.md +++ b/README.md @@ -20,6 +20,7 @@ Alertift.alert(title: "Alertift", message: "Alertift is swifty, modern, and awes - Method chain - UITextField support - iPad support(Action Sheet, popover) +- Can change title/message/button text/ background color. (**without** private APIs.) ## Examples @@ -115,6 +116,44 @@ Alertift.actionSheet(message: "Which food do you like?") ![img5](Documents/img5.png) +### Change colors + +```swift +Alertift.alert(title: "Red color title", message: "Message text color is blue") + .titleTextColor(.red) + .messageTextColor(.blue) + .backgroundColor(.lightGray) + .buttonTextColor(.orange) + .action(.default("Orange")) + .show() +``` + +![img6](Documents/img6.png) + +```swift +public func backgroundColor(_ color: UIColor?) -> Self +public func buttonTextColor(_ color: UIColor?) -> Self +public func titleTextColor(_ color: UIColor?) -> Self +public func messageTextColor(_ color: UIColor?) -> Self +``` + +#### Always change color + +If you want to change Alertift's alert(action sheet) color always, +set color to `static var`. + +```swift +Alertift.Alert.titleTextColor = .red +Alertift.ActionSheet.backgroundColor = .gray +``` + +```swift +static var backgroundColor: UIColor? { get set } +static var buttonTextColor: UIColor? { get set } +static var titleTextColor: UIColor? { get set } +static var messageTextColor: UIColor? { get set } +``` + ## Requirements - iOS 9.0+ diff --git a/Sources/ActionSheet.swift b/Sources/ActionSheet.swift index 4de2830..185a8a2 100644 --- a/Sources/ActionSheet.swift +++ b/Sources/ActionSheet.swift @@ -10,7 +10,18 @@ import Foundation extension Alertift { /// ActionSheet - final public class ActionSheet: AlertBase { + final public class ActionSheet: AlertType, _AlertType { + + var _alertController: InnerAlertController! + public var alertController: UIAlertController { + return _alertController as UIAlertController + } + + public static var backgroundColor: UIColor? + public static var buttonTextColor: UIColor? + public static var titleTextColor: UIColor? + public static var messageTextColor: UIColor? + /// Make action sheet /// /// - Parameters: @@ -18,7 +29,7 @@ extension Alertift { /// - message: Descriptive text that provides additional details about the reason for the alert. /// - Returns: Instance of **ActionSheet** public init(title: String? = nil, message: String? = nil) { - super.init(title: title, message: message, style: .actionSheet) + buildAlertControlelr(title: title, message: message, style: .actionSheet) } /// Add action to alertController diff --git a/Sources/Alert.swift b/Sources/Alert.swift index 7d2766c..e1b4b46 100644 --- a/Sources/Alert.swift +++ b/Sources/Alert.swift @@ -10,13 +10,23 @@ import Foundation extension Alertift { /// Alert - final public class Alert: AlertBase { + final public class Alert: AlertType, _AlertType { /// TextFieldHandler public typealias TextFieldHandler = ((UITextField, Int) -> Void) /// ActionWithTextFieldsHandler public typealias ActionWithTextFieldsHandler = ([UITextField]?) -> Void + var _alertController: InnerAlertController! + public var alertController: UIAlertController { + return _alertController as UIAlertController + } + + public static var backgroundColor: UIColor? + public static var buttonTextColor: UIColor? + public static var titleTextColor: UIColor? + public static var messageTextColor: UIColor? + /// Make alert /// /// - Parameters: @@ -24,7 +34,7 @@ extension Alertift { /// - message: Descriptive text that provides additional details about the reason for the alert. /// - Returns: Instance of **Alert** public init(title: String? = nil, message: String? = nil) { - super.init(title: title, message: message, style: .alert) + buildAlertControlelr(title: title, message: message, style: .alert) } /// Add alertAction to alertController diff --git a/Sources/AlertBase.swift b/Sources/AlertBase.swift deleted file mode 100644 index 14bc60b..0000000 --- a/Sources/AlertBase.swift +++ /dev/null @@ -1,66 +0,0 @@ -// -// AlertBase.swift -// Alertift -// -// Created by Suguru Kishimoto on 4/27/17. -// Copyright © 2017 Suguru Kishimoto. All rights reserved. -// - -import Foundation - -extension Alertift { - /// AlertBase - /// superclass of Alert, ActionSheet. - public class AlertBase { - - /// UIAlertController - public var alertController: UIAlertController { - return _alertController as UIAlertController - } - - /// InnerAlertController (internal). - let _alertController: InnerAlertController - - /// Handler for finally. - private var finallyHandler: Alertift.FinallyHandler? - - - /// Initializer - /// - /// - Parameters: - /// - title: The title of the alert. Use this string to get the user’s attention and communicate the reason for the alert. - /// - message: Descriptive text that provides additional details about the reason for the alert. - /// - style: The style to use when presenting the alert controller. Use this parameter to configure the alert controller as an action sheet or as a modal alert. - init(title: String? = nil, message: String? = nil, style: UIAlertControllerStyle) { - _alertController = InnerAlertController(title: title, message: message, preferredStyle: style) - } - - /// Build **UIAlertAction** using **Alertift.Action** and handler. - /// - /// - Parameters: - /// - action: action - /// - handler: The handler to execute after the action selected. - /// - Returns: **UIAlertAction** - func buildAlertAction(_ action: Alertift.Action, handler: @escaping Alertift.ActionHandler) -> UIAlertAction { - return action.buildAlertAction(handler: ActionHandlerBuilder.build(handler, _alertController.finallyExecutor)) - } - - /// Add finally handler. - /// - /// - Parameter handler: The handler to execute after either alert selected. - /// - Returns: Myself - public func finally(handler: @escaping Alertift.FinallyHandler) -> Self { - _alertController.finallyHandler = handler - return self - } - - /// Show alert (or action sheet). - /// - /// - Parameters: - /// - viewController: The view controller to display over the current view controller’s content. Default is **UIApplication.shared.keyWindow?.rootViewController** - /// - completion: The block to execute after the presentation finishes. This block has no return value and takes no parameters. You may specify nil for this parameter. - final public func show(on viewController: UIViewController? = UIApplication.shared.keyWindow?.rootViewController, completion: (() -> Void)? = nil) { - viewController?.present(_alertController, animated: true, completion: completion) - } - } -} diff --git a/Sources/AlertType.swift b/Sources/AlertType.swift new file mode 100644 index 0000000..8d7005d --- /dev/null +++ b/Sources/AlertType.swift @@ -0,0 +1,114 @@ +// +// AlertType.swift +// Alertift +// +// Created by Suguru Kishimoto on 4/30/17. +// Copyright © 2017 Suguru Kishimoto. All rights reserved. +// + +import Foundation + +/// Internal AlertType protocol +internal protocol _AlertType: class { + /// inner alertController + var _alertController: InnerAlertController! { get set } +} + +extension _AlertType where Self: AlertType { + /// build AlertController + func buildAlertControlelr(title: String? = nil, message: String? = nil, style: UIAlertControllerStyle) { + _alertController = InnerAlertController(title: title, message: message, preferredStyle: style) + _alertController.alertBackgroundColor = type(of: self).backgroundColor + _alertController.view.tintColor = type(of: self).buttonTextColor + _alertController.titleTextColor = type(of: self).titleTextColor + _alertController.messageTextColor = type(of: self).messageTextColor + } +} + +/// AlertType protocol +public protocol AlertType: class { + /// UIAlertController + var alertController: UIAlertController { get } + /// default background color of Alert(ActionSheet). + static var backgroundColor: UIColor? { get set } + + /// default button text color of Alert(ActionSheet). + static var buttonTextColor: UIColor? { get set } + + /// default title text color of Alert(ActionSheet). + static var titleTextColor: UIColor? { get set } + + /// default message text color of Alert(ActionSheet). + static var messageTextColor: UIColor? { get set } +} + +extension AlertType { + /// get InnerAlertController. + private var _alertController: InnerAlertController { + return alertController as! InnerAlertController + } + + /// Build **UIAlertAction** using **Alertift.Action** and handler. + /// + /// - Parameters: + /// - action: action + /// - handler: The handler to execute after the action selected. + /// - Returns: **UIAlertAction** + func buildAlertAction(_ action: Alertift.Action, handler: @escaping Alertift.ActionHandler) -> UIAlertAction { + return action.buildAlertAction(handler: ActionHandlerBuilder.build(handler, _alertController.finallyExecutor)) + } + + /// Add finally handler. + /// + /// - Parameter handler: The handler to execute after either alert selected. + /// - Returns: Myself + public func finally(handler: @escaping Alertift.FinallyHandler) -> Self { + _alertController.finallyHandler = handler + return self + } + + /// Change background color + /// + /// - Parameter color: UIColor + /// - Returns: Myself + public func backgroundColor(_ color: UIColor?) -> Self { + _alertController.alertBackgroundColor = color + return self + } + + /// Change button text color + /// + /// - Parameter color: UIColor + /// - Returns: Myself + public func buttonTextColor(_ color: UIColor?) -> Self { + _alertController.view.tintColor = color + return self + } + + /// Change title text color + /// + /// - Parameter color: UIColor + /// - Returns: Myself + public func titleTextColor(_ color: UIColor?) -> Self { + _alertController.titleTextColor = color + return self + } + + /// Change message text color + /// + /// - Parameter color: UIColor + /// - Returns: Myself + public func messageTextColor(_ color: UIColor?) -> Self { + _alertController.messageTextColor = color + return self + } + + /// Show alert (or action sheet). + /// + /// - Parameters: + /// - viewController: The view controller to display over the current view controller’s content. Default is **UIApplication.shared.keyWindow?.rootViewController** + /// - completion: The block to execute after the presentation finishes. This block has no return value and takes no parameters. You may specify nil for this parameter. + final public func show(on viewController: UIViewController? = UIApplication.shared.keyWindow?.rootViewController, completion: (() -> Void)? = nil) { + viewController?.present(_alertController, animated: true, completion: completion) + } +} diff --git a/Sources/Alertift.swift b/Sources/Alertift.swift index f47d91d..f8d277f 100644 --- a/Sources/Alertift.swift +++ b/Sources/Alertift.swift @@ -46,6 +46,5 @@ extension Alertift { /// Internal typealiases -typealias _AlertBase = Alertift.AlertBase typealias _Alert = Alertift.Alert typealias _ActionSheet = Alertift.ActionSheet diff --git a/Sources/InnerAlertController.swift b/Sources/InnerAlertController.swift index 1b98840..dc14591 100644 --- a/Sources/InnerAlertController.swift +++ b/Sources/InnerAlertController.swift @@ -18,6 +18,10 @@ class InnerAlertController: UIAlertController { /// finallyHandler: (UIAlertAction, Int) -> Void var finallyHandler: Alertift.FinallyHandler? + var alertBackgroundColor: UIColor? + var titleTextColor: UIColor? = .black + var messageTextColor: UIColor? = .black + /// Register UITextFieldTextDidChange notification /// /// - Parameter textField: textField @@ -57,8 +61,57 @@ class InnerAlertController: UIAlertController { } } + override public func viewWillLayoutSubviews() { + super.viewWillLayoutSubviews() + + adaptBackgroundColor() + adaptTitleColor() + adaptMessageColor() + } + + private func adaptBackgroundColor() { + mainView?.backgroundColor = alertBackgroundColor + if preferredStyle == .actionSheet { + if let cancelTitle = actions.filter({ $0.style == .cancel }).first?.title { + if let cancelButton = searchLabel(from: cancelTitle )?.superview?.superview { + cancelButton.backgroundColor = alertBackgroundColor + } + } + } + } + + private func adaptTitleColor() { + if let title = title, let titleLabel = searchLabel(from: title) { + print(titleLabel.textColor) + titleLabel.textColor = titleTextColor + } + } + + private func adaptMessageColor() { + if let message = message, let messageLabel = searchLabel(from: message) { + messageLabel.textColor = messageTextColor + } + } + + private var mainView: UIView? { + return view.subviews.first?.subviews.first?.subviews.first + } + + private func searchLabel(from text: String) -> UILabel? { + return view.recursiveSubviews + .flatMap { $0 as? UILabel} + .first { $0.text == text } + } + deinit { NotificationCenter.default.removeObserver(self) Debug.log() } } + +extension UIView { + + var recursiveSubviews: [UIView] { + return subviews.reduce(subviews, { return $0 + $1.recursiveSubviews }) + } +}