diff --git a/README.md b/README.md index b1e02c2..242f9aa 100644 --- a/README.md +++ b/README.md @@ -1,9 +1,14 @@ + ![image](https://github.com/wangrui460/WRNavigationBar/raw/master/screenshots/WRNavigationBar.png) [For Objective-C:https://github.com/wangrui460/WRNavigationBar](https://github.com/wangrui460/WRNavigationBar) ------------------------------------------------------------ +## iOS 技术交流 +我创建了一个 微信 iOS 技术交流群,欢迎小伙伴们加入一起交流学习~ + +可以加我微信我拉你进去(备注iOS),我的微信号 wr1204607318 ## Requirements - iOS 8+ @@ -12,6 +17,10 @@ ## Demo +![导航栏显示渐变色](https://github.com/wangrui460/WRNavigationBar_swift/raw/master/screenshots/导航栏显示渐变色.gif) + +![导航栏显示图片](https://github.com/wangrui460/WRNavigationBar_swift/raw/master/screenshots/导航栏显示图片.gif) + ![新浪微博个人中心](https://github.com/wangrui460/WRNavigationBar_swift/raw/master/screenshots/新浪微博个人中心.gif) ![qq空间](https://github.com/wangrui460/WRNavigationBar_swift/raw/master/screenshots/qq空间.gif) @@ -22,6 +31,8 @@ ![蚂蚁森林](https://github.com/wangrui460/WRNavigationBar_swift/raw/master/screenshots/蚂蚁森林.gif) +![连续多个界面导航栏透明](https://github.com/wangrui460/WRNavigationBar_swift/raw/master/screenshots/连续多个界面导航栏透明.gif) + ![自定义导航栏](https://github.com/wangrui460/WRNavigationBar_swift/raw/master/screenshots/自定义导航栏.gif) ![移动导航栏](https://github.com/wangrui460/WRNavigationBar_swift/raw/master/screenshots/移动导航栏.gif) @@ -34,6 +45,7 @@ ## How To Use +具体使用方法请参考Demo

 // 一行代码搞定导航栏颜色
 navBarBarTintColor = .white
@@ -45,6 +57,21 @@ navBarTintColor = UIColor(red: 0, green: 0.478431, blue: 1, alpha: 1.0)
 navBarTitleColor = .black
 // 一行代码搞定状态栏是 default 还是 lightContent
 statusBarStyle = .default
+// 一行代码搞定导航栏底部分割线是否隐藏
+navBarShadowImageHidden = true;
+
+ +

+// 设置导航栏默认的背景颜色
+UIColor.defaultNavBarBarTintColor = UIColor.init(red: 0/255.0, green: 175/255.0, blue: 240/255.0, alpha: 1)
+// 设置导航栏所有按钮的默认颜色
+UIColor.defaultNavBarTintColor = .white
+// 设置导航栏标题默认颜色
+UIColor.defaultNavBarTitleColor = .white
+// 统一设置状态栏样式
+UIColor.defaultStatusBarStyle = .lightContent
+// 如果需要设置导航栏底部分割线隐藏,可以在这里统一设置
+UIColor.defaultShadowImageHidden = true
 
@@ -53,35 +80,59 @@ statusBarStyle = .default ## Update +- **2017.12.09** +解决问题:解决导航栏颜色和标题颜色改变失败的bug -- **2017.05.12** -解决问题:侧滑一点松开透明的导航栏会变不透明 +- **2017.12.09** +解决问题:解决点击返回按钮导航栏标题颜色闪烁的问题 -- **2017.05.16** -新增Demo:完成自定义导航栏实现透明渐变等效果 +- **2017.11.29**- +更新:解决部分用户设置导航栏无效的问题~ -- **2017.05.20** -解决问题:解决侧滑返回导航栏没有渐变动画太突兀的**问题 +- **2017.11.29**- +更新:支持自定义导航栏~ -- **2017.05.21** -解决问题:解决push导航栏没有渐变动画太突兀的问题 +- **2017.11.25** +更新:更新到 Swift 4,适配iOS 11、iPhone X,自定义导航栏再等两天~ -- **2017.06.15** -解决问题:解决scrollView正在滑动的时候,点击返回按钮,导航栏颜色变化突兀的问题 +- **2017.07.22** +添加新DEMO:连续多个界面导航栏透明 + +- **2017.07.09** +解决问题:当一个控制器中包含多个控制器时,导航栏颜色或透明度不正常的问题 + +- **2017.07.04** +添加新功能:全局设置导航栏显示图片(不建议在非自定义导航栏中使用) + +- **2017.07.01** +添加新功能:导航栏可显示图片 + +- **2017.06.29** +添加新功能:可单独设置每个控制器对应导航栏底部分割线是否隐藏 + +- **2017.06.29** +解决问题:解决引入WRNavigationBar后,无法设置导航栏标题大小的问题 - **2017.06.19** 解决问题:解决移动导航栏后右滑返回中途取消导致的导航栏错位的问题 +- **2017.06.15** +解决问题:解决scrollView正在滑动的时候,点击返回按钮,导航栏颜色变化突兀的问题 -## Features +- **2017.05.21** +解决问题:解决push导航栏没有渐变动画太突兀的问题 +- **2017.05.20** +解决问题:解决侧滑返回导航栏没有渐变动画太突兀的**问题 + +- **2017.05.16** +新增Demo:完成自定义导航栏实现透明渐变等效果 + +- **2017.05.12** +解决问题:侧滑一点松开透明的导航栏会变不透明 -# Contact me -- Weibo: [@wangrui460](http://weibo.com/u/5145779726?is_all=1) -- Email: wangruidev@gmail.com -- QQ:1204607318 -# License +## License WRNavigationBar is available under the MIT license. See the LICENSE file for more info. diff --git a/WRNavigationBar/WRCustomNavigationBar.swift b/WRNavigationBar/WRCustomNavigationBar.swift new file mode 100644 index 0000000..5066e10 --- /dev/null +++ b/WRNavigationBar/WRCustomNavigationBar.swift @@ -0,0 +1,301 @@ +// +// WRCustomNavigationBar.swift +// WRNavigationBar_swift +// +// Created by itwangrui on 2017/11/25. +// Copyright © 2017年 wangrui. All rights reserved. +// + +import UIKit + +fileprivate let WRDefaultTitleSize:CGFloat = 18 +fileprivate let WRDefaultTitleColor = UIColor.black +fileprivate let WRDefaultBackgroundColor = UIColor.white +fileprivate let WRScreenWidth = UIScreen.main.bounds.size.width + + +// MARK: - Router +extension UIViewController +{ + // A页面 弹出 登录页面B + // presentedViewController: A页面 + // presentingViewController: B页面 + + func wr_toLastViewController(animated:Bool) + { + if self.navigationController != nil + { + if self.navigationController?.viewControllers.count == 1 + { + self.dismiss(animated: animated, completion: nil) + } else { + self.navigationController?.popViewController(animated: animated) + } + } + else if self.presentingViewController != nil { + self.dismiss(animated: animated, completion: nil) + } + } + + class func wr_currentViewController() -> UIViewController + { + if let rootVC = UIApplication.shared.delegate?.window??.rootViewController { + return self.wr_currentViewController(from: rootVC) + } else { + return UIViewController() + } + } + + class func wr_currentViewController(from fromVC:UIViewController) -> UIViewController + { + if fromVC.isKind(of: UINavigationController.self) { + let navigationController = fromVC as! UINavigationController + return wr_currentViewController(from: navigationController.viewControllers.last!) + } + else if fromVC.isKind(of: UITabBarController.self) { + let tabBarController = fromVC as! UITabBarController + return wr_currentViewController(from: tabBarController.selectedViewController!) + } + else if fromVC.presentedViewController != nil { + return wr_currentViewController(from:fromVC.presentingViewController!) + } + else { + return fromVC + } + } +} + + +//////////////////////////////////////////////////////////////////////////////////////////////////////////// +class WRCustomNavigationBar: UIView +{ + var onClickLeftButton:(()->())? + var onClickRightButton:(()->())? + var title:String? { + willSet { + titleLabel.isHidden = false + titleLabel.text = newValue + } + } + var titleLabelColor:UIColor? { + willSet { + titleLabel.textColor = newValue + } + } + var titleLabelFont:UIFont? { + willSet { + titleLabel.font = newValue + } + } + var barBackgroundColor:UIColor? { + willSet { + backgroundImageView.isHidden = true + backgroundView.isHidden = false + backgroundView.backgroundColor = newValue + } + } + var barBackgroundImage:UIImage? { + willSet { + backgroundView.isHidden = true + backgroundImageView.isHidden = false + backgroundImageView.image = newValue + } + } + + // fileprivate UI variable + fileprivate lazy var titleLabel:UILabel = { + let label = UILabel() + label.textColor = WRDefaultTitleColor + label.font = UIFont.systemFont(ofSize: WRDefaultTitleSize) + label.textAlignment = .center + label.isHidden = true + return label + }() + + fileprivate lazy var leftButton:UIButton = { + let button = UIButton() + button.imageView?.contentMode = .center + button.isHidden = true + button.addTarget(self, action: #selector(clickBack), for: .touchUpInside) + return button + }() + + fileprivate lazy var rightButton:UIButton = { + let button = UIButton() + button.imageView?.contentMode = .center + button.isHidden = true + button.addTarget(self, action: #selector(clickRight), for: .touchUpInside) + return button + }() + + fileprivate lazy var bottomLine:UIView = { + let view = UIView() + view.backgroundColor = UIColor(red: (218.0/255.0), green: (218.0/255.0), blue: (218.0/255.0), alpha: 1.0) + return view + }() + + fileprivate lazy var backgroundView:UIView = { + let view = UIView() + return view + }() + + fileprivate lazy var backgroundImageView:UIImageView = { + let imgView = UIImageView() + imgView.isHidden = true + return imgView + }() + + // fileprivate other variable + fileprivate static var isIphoneX:Bool { + get { + return UIScreen.main.bounds.equalTo(CGRect(x: 0, y: 0, width: 375, height: 812)) + } + } + fileprivate static var navBarBottom:Int { + get { + return isIphoneX ? 88 : 64 + } + } + + // init + class func CustomNavigationBar() -> WRCustomNavigationBar { + let frame = CGRect(x: 0, y: 0, width: WRScreenWidth, height: CGFloat(navBarBottom)) + return WRCustomNavigationBar(frame: frame) + } + override init(frame: CGRect) { + super.init(frame: frame) + setupView() + } + required init?(coder aDecoder: NSCoder) { + super.init(coder: aDecoder) + setupView() + } + + func setupView() + { + addSubview(backgroundView) + addSubview(backgroundImageView) + addSubview(leftButton) + addSubview(titleLabel) + addSubview(rightButton) + addSubview(bottomLine) + updateFrame() + backgroundColor = UIColor.clear + backgroundView.backgroundColor = WRDefaultBackgroundColor + } + func updateFrame() + { + let top:CGFloat = WRCustomNavigationBar.isIphoneX ? 44 : 20 + let margin:CGFloat = 0 + let buttonHeight:CGFloat = 44 + let buttonWidth:CGFloat = 44 + let titleLabelHeight:CGFloat = 44 + let titleLabelWidth:CGFloat = 180 + + backgroundView.frame = self.bounds + backgroundImageView.frame = self.bounds + leftButton.frame = CGRect(x: margin, y: top, width: buttonWidth, height: buttonHeight) + rightButton.frame = CGRect(x: WRScreenWidth-buttonWidth-margin, y: top, width: buttonWidth, height: buttonHeight) + titleLabel.frame = CGRect(x: (WRScreenWidth-titleLabelWidth)/2.0, y: top, width: titleLabelWidth, height: titleLabelHeight) + bottomLine.frame = CGRect(x: 0, y: bounds.height-0.5, width: WRScreenWidth, height: 0.5) + } +} + + +extension WRCustomNavigationBar +{ + func wr_setBottomLineHidden(hidden:Bool) { + bottomLine.isHidden = hidden + } + func wr_setBackgroundAlpha(alpha:CGFloat) { + backgroundView.alpha = alpha + backgroundImageView.alpha = alpha + bottomLine.alpha = alpha + } + func wr_setTintColor(color:UIColor) { + leftButton.setTitleColor(color, for: .normal) + rightButton.setTitleColor(color, for: .normal) + titleLabel.textColor = color + } + + // 左右按钮共有方法 + func wr_setLeftButton(normal:UIImage, highlighted:UIImage) { + wr_setLeftButton(normal: normal, highlighted: highlighted, title: nil, titleColor: nil) + } + func wr_setLeftButton(image:UIImage) { + wr_setLeftButton(normal: image, highlighted: image, title: nil, titleColor: nil) + } + func wr_setLeftButton(title:String, titleColor:UIColor) { + wr_setLeftButton(normal: nil, highlighted: nil, title: title, titleColor: titleColor) + } + + func wr_setRightButton(normal:UIImage, highlighted:UIImage) { + wr_setRightButton(normal: normal, highlighted: highlighted, title: nil, titleColor: nil) + } + func wr_setRightButton(image:UIImage) { + wr_setRightButton(normal: image, highlighted: image, title: nil, titleColor: nil) + } + func wr_setRightButton(title:String, titleColor:UIColor) { + wr_setRightButton(normal: nil, highlighted: nil, title: title, titleColor: titleColor) + } + + + // 左右按钮私有方法 + private func wr_setLeftButton(normal:UIImage?, highlighted:UIImage?, title:String?, titleColor:UIColor?) { + leftButton.isHidden = false + leftButton.setImage(normal, for: .normal) + leftButton.setImage(highlighted, for: .highlighted) + leftButton.setTitle(title, for: .normal) + leftButton.setTitleColor(titleColor, for: .normal) + } + private func wr_setRightButton(normal:UIImage?, highlighted:UIImage?, title:String?, titleColor:UIColor?) { + rightButton.isHidden = false + rightButton.setImage(normal, for: .normal) + rightButton.setImage(highlighted, for: .highlighted) + rightButton.setTitle(title, for: .normal) + rightButton.setTitleColor(titleColor, for: .normal) + } +} + + +// MARK: - 导航栏左右按钮事件 +extension WRCustomNavigationBar +{ + @objc func clickBack() { + if let onClickBack = onClickLeftButton { + onClickBack() + } else { + let currentVC = UIViewController.wr_currentViewController() + currentVC.wr_toLastViewController(animated: true) + } + } + @objc func clickRight() { + if let onClickRight = onClickRightButton { + onClickRight() + } + } +} + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/WRNavigationBar/WRNavigationBar.swift b/WRNavigationBar/WRNavigationBar.swift index c1af906..1322e4c 100644 --- a/WRNavigationBar/WRNavigationBar.swift +++ b/WRNavigationBar/WRNavigationBar.swift @@ -9,10 +9,11 @@ import UIKit -extension UINavigationBar +extension UINavigationBar:WRAwakeProtocol { fileprivate struct AssociatedKeys { - static var backgroundView:UIView = UIView() + static var backgroundView: UIView = UIView() + static var backgroundImageView: UIImageView = UIImageView() } fileprivate var backgroundView:UIView? { @@ -27,14 +28,46 @@ extension UINavigationBar } } + fileprivate var backgroundImageView:UIImageView? { + get { + guard let bgImageView = objc_getAssociatedObject(self, &AssociatedKeys.backgroundImageView) as? UIImageView else { + return nil + } + return bgImageView + } + set { + objc_setAssociatedObject(self, &AssociatedKeys.backgroundImageView, newValue, .OBJC_ASSOCIATION_RETAIN_NONATOMIC) + } + } + + // set navigationBar backgroundImage + fileprivate func wr_setBackgroundImage(image:UIImage) + { + backgroundView?.removeFromSuperview() + backgroundView = nil + if (backgroundImageView == nil) + { + // add a image(nil color) to _UIBarBackground make it clear + setBackgroundImage(UIImage(), for: .default) + backgroundImageView = UIImageView(frame: CGRect(x: 0, y: 0, width: Int(bounds.width), height: WRNavigationBar.navBarBottom())) + backgroundImageView?.autoresizingMask = .flexibleWidth + // _UIBarBackground is first subView for navigationBar + subviews.first?.insertSubview(backgroundImageView ?? UIImageView(), at: 0) + } + backgroundImageView?.image = image + } + // set navigationBar barTintColor fileprivate func wr_setBackgroundColor(color:UIColor) { + backgroundImageView?.removeFromSuperview() + backgroundImageView = nil if (backgroundView == nil) { // add a image(nil color) to _UIBarBackground make it clear setBackgroundImage(UIImage(), for: .default) - backgroundView = UIView(frame: CGRect(x: 0, y: 0, width: Int(bounds.width), height: 64)) + backgroundView = UIView(frame: CGRect(x: 0, y: 0, width: Int(bounds.width), height: WRNavigationBar.navBarBottom())) + backgroundView?.autoresizingMask = .flexibleWidth // _UIBarBackground is first subView for navigationBar subviews.first?.insertSubview(backgroundView ?? UIView(), at: 0) } @@ -44,8 +77,17 @@ extension UINavigationBar // set _UIBarBackground alpha (_UIBarBackground subviews alpha <= _UIBarBackground alpha) fileprivate func wr_setBackgroundAlpha(alpha:CGFloat) { - let barBackgroundView = subviews[0] - barBackgroundView.alpha = alpha + if let barBackgroundView = subviews.first + { + if #available(iOS 11.0, *) + { // sometimes we can't change _UIBarBackground alpha + for view in barBackgroundView.subviews { + view.alpha = alpha + } + } else { + barBackgroundView.alpha = alpha + } + } } // 设置导航栏所有BarButtonItem的透明度 @@ -104,15 +146,73 @@ extension UINavigationBar { return transform.ty } + + // call swizzling methods active 主动调用交换方法 + private static let onceToken = UUID().uuidString + public static func wrAwake() + { + DispatchQueue.once(token: onceToken) + { + let needSwizzleSelectorArr = [ + #selector(setter: titleTextAttributes) + ] + + for selector in needSwizzleSelectorArr { + let str = ("wr_" + selector.description) + if let originalMethod = class_getInstanceMethod(self, selector), + let swizzledMethod = class_getInstanceMethod(self, Selector(str)) { + method_exchangeImplementations(originalMethod, swizzledMethod) + } + } + } + } + + //========================================================================== + // MARK: swizzling pop + //========================================================================== + @objc func wr_setTitleTextAttributes(_ newTitleTextAttributes:[String : Any]?) + { + guard var attributes = newTitleTextAttributes else { + return + } + + guard let originTitleTextAttributes = titleTextAttributes else { + wr_setTitleTextAttributes(attributes) + return + } + + var titleColor:UIColor? + for attribute in originTitleTextAttributes { + if attribute.key == NSAttributedStringKey.foregroundColor { + titleColor = attribute.value as? UIColor + break + } + } + + guard let originTitleColor = titleColor else { + wr_setTitleTextAttributes(attributes) + return + } + + if attributes[NSAttributedStringKey.foregroundColor.rawValue] == nil { + attributes.updateValue(originTitleColor, forKey: NSAttributedStringKey.foregroundColor.rawValue) + } + wr_setTitleTextAttributes(attributes) + } } //========================================================================== // MARK: - UINavigationController //========================================================================== -extension UINavigationController +extension UINavigationController: WRFatherAwakeProtocol { override open var preferredStatusBarStyle: UIStatusBarStyle { - return topViewController?.statusBarStyle ?? UIColor.defaultStatusBarStyle + return topViewController?.statusBarStyle ?? WRNavigationBar.defaultStatusBarStyle + } + + fileprivate func setNeedsNavigationBarUpdate(backgroundImage: UIImage) + { + navigationBar.wr_setBackgroundImage(image: backgroundImage) } fileprivate func setNeedsNavigationBarUpdate(barTintColor: UIColor) @@ -128,43 +228,55 @@ extension UINavigationController fileprivate func setNeedsNavigationBarUpdate(tintColor: UIColor) { navigationBar.tintColor = tintColor } + + fileprivate func setNeedsNavigationBarUpdate(hideShadowImage: Bool) + { + navigationBar.shadowImage = (hideShadowImage == true) ? UIImage() : nil + } - fileprivate func setNeedsNavigationBarUpdate(titleColor: UIColor) { - navigationBar.titleTextAttributes = [NSForegroundColorAttributeName:titleColor] + fileprivate func setNeedsNavigationBarUpdate(titleColor: UIColor) + { + guard let titleTextAttributes = navigationBar.titleTextAttributes else { + navigationBar.titleTextAttributes = [NSAttributedStringKey.foregroundColor:titleColor] + return + } + + var newTitleTextAttributes = titleTextAttributes + newTitleTextAttributes.updateValue(titleColor, forKey: NSAttributedStringKey.foregroundColor) + navigationBar.titleTextAttributes = newTitleTextAttributes } fileprivate func updateNavigationBar(fromVC: UIViewController?, toVC: UIViewController?, progress: CGFloat) { // change navBarBarTintColor - let fromBarTintColor = fromVC?.navBarBarTintColor ?? .defaultNavBarBarTintColor - let toBarTintColor = toVC?.navBarBarTintColor ?? .defaultNavBarBarTintColor - let newBarTintColor = UIColor.middleColor(fromColor: fromBarTintColor, toColor: toBarTintColor, percent: progress) + let fromBarTintColor = fromVC?.navBarBarTintColor ?? WRNavigationBar.defaultNavBarBarTintColor + let toBarTintColor = toVC?.navBarBarTintColor ?? WRNavigationBar.defaultNavBarBarTintColor + let newBarTintColor = WRNavigationBar.middleColor(fromColor: fromBarTintColor, toColor: toBarTintColor, percent: progress) setNeedsNavigationBarUpdate(barTintColor: newBarTintColor) // change navBarTintColor - let fromTintColor = fromVC?.navBarTintColor ?? .defaultNavBarTintColor - let toTintColor = toVC?.navBarTintColor ?? .defaultNavBarTintColor - let newTintColor = UIColor.middleColor(fromColor: fromTintColor, toColor: toTintColor, percent: progress) + let fromTintColor = fromVC?.navBarTintColor ?? WRNavigationBar.defaultNavBarTintColor + let toTintColor = toVC?.navBarTintColor ?? WRNavigationBar.defaultNavBarTintColor + let newTintColor = WRNavigationBar.middleColor(fromColor: fromTintColor, toColor: toTintColor, percent: progress) setNeedsNavigationBarUpdate(tintColor: newTintColor) // change navBarTitleColor - let fromTitleColor = fromVC?.navBarTitleColor ?? .defaultNavBarTitleColor - let toTitleColor = toVC?.navBarTitleColor ?? .defaultNavBarTitleColor - let newTitleColor = UIColor.middleColor(fromColor: fromTitleColor, toColor: toTitleColor, percent: progress) - setNeedsNavigationBarUpdate(titleColor: newTitleColor) +// let fromTitleColor = fromVC?.navBarTitleColor ?? WRNavigationBar.defaultNavBarTitleColor +// let toTitleColor = toVC?.navBarTitleColor ?? WRNavigationBar.defaultNavBarTitleColor +// let newTitleColor = WRNavigationBar.middleColor(fromColor: fromTitleColor, toColor: toTitleColor, percent: progress) +// setNeedsNavigationBarUpdate(titleColor: newTitleColor) // change navBar _UIBarBackground alpha - let fromBarBackgroundAlpha = fromVC?.navBarBackgroundAlpha ?? UIColor.defaultBackgroundAlpha - let toBarBackgroundAlpha = toVC?.navBarBackgroundAlpha ?? UIColor.defaultBackgroundAlpha - let newBarBackgroundAlpha = UIColor.middleAlpha(fromAlpha: fromBarBackgroundAlpha, toAlpha: toBarBackgroundAlpha, percent: progress) + let fromBarBackgroundAlpha = fromVC?.navBarBackgroundAlpha ?? WRNavigationBar.defaultBackgroundAlpha + let toBarBackgroundAlpha = toVC?.navBarBackgroundAlpha ?? WRNavigationBar.defaultBackgroundAlpha + let newBarBackgroundAlpha = WRNavigationBar.middleAlpha(fromAlpha: fromBarBackgroundAlpha, toAlpha: toBarBackgroundAlpha, percent: progress) setNeedsNavigationBarUpdate(barBackgroundAlpha: newBarBackgroundAlpha) } // call swizzling methods active 主动调用交换方法 private static let onceToken = UUID().uuidString - open override class func initialize() + public static func fatherAwake() { - guard self == UINavigationController.self else { return } DispatchQueue.once(token: onceToken) { let needSwizzleSelectorArr = [ @@ -173,13 +285,14 @@ extension UINavigationController #selector(popToRootViewController), #selector(pushViewController) ] - + for selector in needSwizzleSelectorArr { // _updateInteractiveTransition: => wr_updateInteractiveTransition: let str = ("wr_" + selector.description).replacingOccurrences(of: "__", with: "_") - let originalMethod = class_getInstanceMethod(self, selector) - let swizzledMethod = class_getInstanceMethod(self, Selector(str)) - method_exchangeImplementations(originalMethod, swizzledMethod) + if let originalMethod = class_getInstanceMethod(self, selector), + let swizzledMethod = class_getInstanceMethod(self, Selector(str)) { + method_exchangeImplementations(originalMethod, swizzledMethod) + } } } } @@ -198,8 +311,9 @@ extension UINavigationController } // swizzling system method: popToViewController - func wr_popToViewController(_ viewController: UIViewController, animated: Bool) -> [UIViewController]? + @objc func wr_popToViewController(_ viewController: UIViewController, animated: Bool) -> [UIViewController]? { + setNeedsNavigationBarUpdate(titleColor: viewController.navBarTitleColor) var displayLink:CADisplayLink? = CADisplayLink(target: self, selector: #selector(popNeedDisplay)) // UITrackingRunLoopMode: 界面跟踪 Mode,用于 ScrollView 追踪触摸滑动,保证界面滑动时不受其他 Mode 影响 // NSRunLoopCommonModes contains kCFRunLoopDefaultMode and UITrackingRunLoopMode @@ -217,7 +331,7 @@ extension UINavigationController } // swizzling system method: popToRootViewControllerAnimated - func wr_popToRootViewControllerAnimated(_ animated: Bool) -> [UIViewController]? + @objc func wr_popToRootViewControllerAnimated(_ animated: Bool) -> [UIViewController]? { var displayLink:CADisplayLink? = CADisplayLink(target: self, selector: #selector(popNeedDisplay)) displayLink?.add(to: RunLoop.main, forMode: .commonModes) @@ -234,7 +348,7 @@ extension UINavigationController } // change navigationBar barTintColor smooth before pop to current VC finished - func popNeedDisplay() + @objc fileprivate func popNeedDisplay() { guard let topViewController = topViewController, let coordinator = topViewController.transitionCoordinator else { @@ -264,10 +378,10 @@ extension UINavigationController } // swizzling system method: pushViewController - func wr_pushViewController(_ viewController: UIViewController, animated: Bool) + @objc func wr_pushViewController(_ viewController: UIViewController, animated: Bool) { var displayLink:CADisplayLink? = CADisplayLink(target: self, selector: #selector(pushNeedDisplay)) - displayLink?.add(to: RunLoop.main, forMode: .defaultRunLoopMode) + displayLink?.add(to: RunLoop.main, forMode: .commonModes) CATransaction.setCompletionBlock { displayLink?.invalidate() displayLink = nil @@ -281,7 +395,7 @@ extension UINavigationController } // change navigationBar barTintColor smooth before push to current VC finished or before pop to current VC finished - func pushNeedDisplay() + @objc fileprivate func pushNeedDisplay() { guard let topViewController = topViewController, let coordinator = topViewController.transitionCoordinator else { @@ -330,8 +444,8 @@ extension UINavigationController: UINavigationBarDelegate private func dealInteractionChanges(_ context: UIViewControllerTransitionCoordinatorContext) { let animations: (UITransitionContextViewControllerKey) -> () = { - let curColor = context.viewController(forKey: $0)?.navBarBarTintColor ?? UIColor.defaultNavBarBarTintColor - let curAlpha = context.viewController(forKey: $0)?.navBarBackgroundAlpha ?? UIColor.defaultBackgroundAlpha + let curColor = context.viewController(forKey: $0)?.navBarBarTintColor ?? WRNavigationBar.defaultNavBarBarTintColor + let curAlpha = context.viewController(forKey: $0)?.navBarBackgroundAlpha ?? WRNavigationBar.defaultBackgroundAlpha self.setNeedsNavigationBarUpdate(barTintColor: curColor) self.setNeedsNavigationBarUpdate(barBackgroundAlpha: curAlpha) @@ -356,7 +470,7 @@ extension UINavigationController: UINavigationBarDelegate } // swizzling system method: _updateInteractiveTransition - func wr_updateInteractiveTransition(_ percentComplete: CGFloat) + @objc func wr_updateInteractiveTransition(_ percentComplete: CGFloat) { guard let topViewController = topViewController, let coordinator = topViewController.transitionCoordinator else { @@ -375,24 +489,27 @@ extension UINavigationController: UINavigationBarDelegate //============================================================================= // MARK: - store navigationBar barTintColor and tintColor every viewController //============================================================================= -extension UIViewController +extension UIViewController: WRAwakeProtocol { fileprivate struct AssociatedKeys { static var pushToCurrentVCFinished: Bool = false static var pushToNextVCFinished:Bool = false - static var navBarBarTintColor: UIColor = UIColor.defaultNavBarBarTintColor + static var navBarBackgroundImage: UIImage = UIImage() + + static var navBarBarTintColor: UIColor = WRNavigationBar.defaultNavBarBarTintColor static var navBarBackgroundAlpha:CGFloat = 1.0 - static var navBarTintColor: UIColor = UIColor.defaultNavBarTintColor - static var navBarTitleColor: UIColor = UIColor.defaultNavBarTitleColor + static var navBarTintColor: UIColor = WRNavigationBar.defaultNavBarTintColor + static var navBarTitleColor: UIColor = WRNavigationBar.defaultNavBarTitleColor static var statusBarStyle: UIStatusBarStyle = UIStatusBarStyle.default + static var navBarShadowImageHidden: Bool = false static var customNavBar: UINavigationBar = UINavigationBar() } // navigationBar barTintColor can not change by currentVC before fromVC push to currentVC finished - var pushToCurrentVCFinished:Bool { + fileprivate var pushToCurrentVCFinished:Bool { get { guard let isFinished = objc_getAssociatedObject(self, &AssociatedKeys.pushToCurrentVCFinished) as? Bool else { return false @@ -405,7 +522,7 @@ extension UIViewController } // navigationBar barTintColor can not change by currentVC when currentVC push to nextVC finished - var pushToNextVCFinished:Bool { + fileprivate var pushToNextVCFinished:Bool { get { guard let isFinished = objc_getAssociatedObject(self, &AssociatedKeys.pushToNextVCFinished) as? Bool else { return false @@ -417,11 +534,31 @@ extension UIViewController } } + // you can set navigationBar backgroundImage + var navBarBackgroundImage: UIImage? + { + get { + guard let bgImage = objc_getAssociatedObject(self, &AssociatedKeys.navBarBackgroundImage) as? UIImage else { + return WRNavigationBar.defaultNavBarBackgroundImage + } + return bgImage + } +// set { +// if customNavBar.isKind(of: UINavigationBar.self) { +// let navBar = customNavBar as! UINavigationBar +// navBar.wr_setBackgroundImage(image: newValue!) +// } +// else { +// objc_setAssociatedObject(self, &AssociatedKeys.navBarBackgroundImage, newValue, .OBJC_ASSOCIATION_RETAIN_NONATOMIC) +// } +// } + } + // navigationBar barTintColor var navBarBarTintColor: UIColor { get { guard let barTintColor = objc_getAssociatedObject(self, &AssociatedKeys.navBarBarTintColor) as? UIColor else { - return UIColor.defaultNavBarBarTintColor + return WRNavigationBar.defaultNavBarBarTintColor } return barTintColor } @@ -429,12 +566,11 @@ extension UIViewController objc_setAssociatedObject(self, &AssociatedKeys.navBarBarTintColor, newValue, .OBJC_ASSOCIATION_RETAIN_NONATOMIC) if customNavBar.isKind(of: UINavigationBar.self) { - let navBar = customNavBar as! UINavigationBar - navBar.wr_setBackgroundColor(color: newValue) +// let navBar = customNavBar as! UINavigationBar +// navBar.wr_setBackgroundColor(color: newValue) } - else - { - if pushToCurrentVCFinished == true && pushToNextVCFinished == false { + else { + if canUpdateNavBarBarTintColorOrBackgroundAlpha == true { navigationController?.setNeedsNavigationBarUpdate(barTintColor: newValue) } } @@ -453,23 +589,32 @@ extension UIViewController objc_setAssociatedObject(self, &AssociatedKeys.navBarBackgroundAlpha, newValue, .OBJC_ASSOCIATION_RETAIN_NONATOMIC) if customNavBar.isKind(of: UINavigationBar.self) { - let navBar = customNavBar as! UINavigationBar - navBar.wr_setBackgroundAlpha(alpha: newValue) +// let navBar = customNavBar as! UINavigationBar +// navBar.wr_setBackgroundAlpha(alpha: newValue) } - else - { - if pushToCurrentVCFinished == true && pushToNextVCFinished == false { + else { + if canUpdateNavBarBarTintColorOrBackgroundAlpha == true { navigationController?.setNeedsNavigationBarUpdate(barBackgroundAlpha: newValue) } } } } + private var canUpdateNavBarBarTintColorOrBackgroundAlpha:Bool { + get { + let isRootViewController = self.navigationController?.viewControllers.first == self + if (pushToCurrentVCFinished == true || isRootViewController == true) && pushToNextVCFinished == false { + return true + } else { + return false + } + } + } // navigationBar tintColor var navBarTintColor: UIColor { get { guard let tintColor = objc_getAssociatedObject(self, &AssociatedKeys.navBarTintColor) as? UIColor else { - return UIColor.defaultNavBarTintColor + return WRNavigationBar.defaultNavBarTintColor } return tintColor } @@ -477,8 +622,8 @@ extension UIViewController objc_setAssociatedObject(self, &AssociatedKeys.navBarTintColor, newValue, .OBJC_ASSOCIATION_RETAIN_NONATOMIC) if customNavBar.isKind(of: UINavigationBar.self) { - let navBar = customNavBar as! UINavigationBar - navBar.tintColor = newValue +// let navBar = customNavBar as! UINavigationBar +// navBar.tintColor = newValue } else { @@ -493,7 +638,7 @@ extension UIViewController var navBarTitleColor: UIColor { get { guard let titleColor = objc_getAssociatedObject(self, &AssociatedKeys.navBarTitleColor) as? UIColor else { - return UIColor.defaultNavBarTitleColor + return WRNavigationBar.defaultNavBarTitleColor } return titleColor } @@ -501,8 +646,8 @@ extension UIViewController objc_setAssociatedObject(self, &AssociatedKeys.navBarTitleColor, newValue, .OBJC_ASSOCIATION_RETAIN_NONATOMIC) if customNavBar.isKind(of: UINavigationBar.self) { - let navBar = customNavBar as! UINavigationBar - navBar.titleTextAttributes = [NSForegroundColorAttributeName:newValue] +// let navBar = customNavBar as! UINavigationBar +// navBar.titleTextAttributes = [NSAttributedStringKey.foregroundColor:newValue] } else { @@ -517,7 +662,7 @@ extension UIViewController var statusBarStyle: UIStatusBarStyle { get { guard let style = objc_getAssociatedObject(self, &AssociatedKeys.statusBarStyle) as? UIStatusBarStyle else { - return UIColor.defaultStatusBarStyle + return WRNavigationBar.defaultStatusBarStyle } return style } @@ -527,6 +672,20 @@ extension UIViewController } } + // if you want shadowImage hidden,you can via hideShadowImage = true + var navBarShadowImageHidden:Bool { + get { + guard let isHidden = objc_getAssociatedObject(self, &AssociatedKeys.navBarShadowImageHidden) as? Bool else { + return WRNavigationBar.defaultShadowImageHidden + } + return isHidden + } + set { + objc_setAssociatedObject(self, &AssociatedKeys.navBarShadowImageHidden, newValue, .OBJC_ASSOCIATION_ASSIGN) + navigationController?.setNeedsNavigationBarUpdate(hideShadowImage: newValue) + } + } + // custom navigationBar var customNavBar: UIView { get { @@ -542,12 +701,8 @@ extension UIViewController // swizzling two system methods: viewWillAppear(_:) and viewWillDisappear(_:) private static let onceToken = UUID().uuidString - open override class func initialize() + @objc public static func wrAwake() { - guard self == UIViewController.self else { - return - } - DispatchQueue.once(token: onceToken) { let needSwizzleSelectors = [ @@ -555,39 +710,72 @@ extension UIViewController #selector(viewWillDisappear(_:)), #selector(viewDidAppear(_:)) ] - + for selector in needSwizzleSelectors { let newSelectorStr = "wr_" + selector.description - let originalMethod = class_getInstanceMethod(self, selector) - let swizzledMethod = class_getInstanceMethod(self, Selector(newSelectorStr)) - method_exchangeImplementations(originalMethod, swizzledMethod) + if let originalMethod = class_getInstanceMethod(self, selector), + let swizzledMethod = class_getInstanceMethod(self, Selector(newSelectorStr)) { + method_exchangeImplementations(originalMethod, swizzledMethod) + } } } } - func wr_viewWillAppear(_ animated: Bool) + @objc func wr_viewWillAppear(_ animated: Bool) { - pushToNextVCFinished = false - navigationController?.setNeedsNavigationBarUpdate(tintColor: navBarTintColor) - navigationController?.setNeedsNavigationBarUpdate(titleColor: navBarTitleColor) + if canUpdateNavigationBar() == true { + pushToNextVCFinished = false + navigationController?.setNeedsNavigationBarUpdate(tintColor: navBarTintColor) + navigationController?.setNeedsNavigationBarUpdate(titleColor: navBarTitleColor) + } wr_viewWillAppear(animated) } - func wr_viewWillDisappear(_ animated: Bool) + @objc func wr_viewWillDisappear(_ animated: Bool) { - pushToNextVCFinished = true + if canUpdateNavigationBar() == true { + pushToNextVCFinished = true + } wr_viewWillDisappear(animated) } - func wr_viewDidAppear(_ animated: Bool) + @objc func wr_viewDidAppear(_ animated: Bool) { - navigationController?.setNeedsNavigationBarUpdate(barTintColor: navBarBarTintColor) - navigationController?.setNeedsNavigationBarUpdate(barBackgroundAlpha: navBarBackgroundAlpha) - navigationController?.setNeedsNavigationBarUpdate(tintColor: navBarTintColor) - navigationController?.setNeedsNavigationBarUpdate(titleColor: navBarTitleColor) + + if self.navigationController?.viewControllers.first != self { + self.pushToCurrentVCFinished = true + } + if canUpdateNavigationBar() == true + { + if let navBarBgImage = navBarBackgroundImage { + navigationController?.setNeedsNavigationBarUpdate(backgroundImage: navBarBgImage) + } else { + navigationController?.setNeedsNavigationBarUpdate(barTintColor: navBarBarTintColor) + } + navigationController?.setNeedsNavigationBarUpdate(barBackgroundAlpha: navBarBackgroundAlpha) + navigationController?.setNeedsNavigationBarUpdate(tintColor: navBarTintColor) + navigationController?.setNeedsNavigationBarUpdate(titleColor: navBarTitleColor) + navigationController?.setNeedsNavigationBarUpdate(hideShadowImage: navBarShadowImageHidden) + } wr_viewDidAppear(animated) } + + func canUpdateNavigationBar() -> Bool + { + let viewFrame = view.frame + let maxFrame = UIScreen.main.bounds + let middleFrame = CGRect(x: 0, y: WRNavigationBar.navBarBottom(), width: WRNavigationBar.screenWidth(), height: WRNavigationBar.screenHeight()-WRNavigationBar.navBarBottom()) + let minFrame = CGRect(x: 0, y: WRNavigationBar.navBarBottom(), width: WRNavigationBar.screenWidth(), height: WRNavigationBar.screenHeight()-WRNavigationBar.navBarBottom()-WRNavigationBar.tabBarHeight()) + // 蝙蝠🦇 + let isBat = viewFrame.equalTo(maxFrame) || viewFrame.equalTo(middleFrame) || viewFrame.equalTo(minFrame) + if self.navigationController != nil && isBat == true { + return true + } else { + return false + } + } + } //==================================================================================== @@ -618,15 +806,18 @@ extension DispatchQueue { //=========================================================================================== // MARK: - default navigationBar barTintColor、tintColor and statusBarStyle YOU CAN CHANGE!!! //=========================================================================================== -extension UIColor +class WRNavigationBar { fileprivate struct AssociatedKeys { // default is system attributes static var defNavBarBarTintColor: UIColor = UIColor.white + static var defNavBarBackgroundImage: UIImage = UIImage() static var defNavBarTintColor: UIColor = UIColor(red: 0, green: 0.478431, blue: 1, alpha: 1.0) static var defNavBarTitleColor: UIColor = UIColor.black static var defStatusBarStyle: UIStatusBarStyle = UIStatusBarStyle.default + static var defShadowImageHidden: Bool = false } + class var defaultNavBarBarTintColor: UIColor { get { guard let def = objc_getAssociatedObject(self, &AssociatedKeys.defNavBarBarTintColor) as? UIColor else { @@ -639,6 +830,18 @@ extension UIColor } } + class var defaultNavBarBackgroundImage: UIImage? { + get { + guard let def = objc_getAssociatedObject(self, &AssociatedKeys.defNavBarBackgroundImage) as? UIImage else { + return nil + } + return def + } + set { + objc_setAssociatedObject(self, &AssociatedKeys.defNavBarBackgroundImage, newValue, .OBJC_ASSOCIATION_RETAIN_NONATOMIC) + } + } + class var defaultNavBarTintColor: UIColor { get { guard let def = objc_getAssociatedObject(self, &AssociatedKeys.defNavBarTintColor) as? UIColor else { @@ -675,6 +878,18 @@ extension UIColor } } + class var defaultShadowImageHidden: Bool { + get { + guard let def = objc_getAssociatedObject(self, &AssociatedKeys.defShadowImageHidden) as? Bool else { + return false + } + return def + } + set { + objc_setAssociatedObject(self, &AssociatedKeys.defShadowImageHidden, newValue, .OBJC_ASSOCIATION_ASSIGN) + } + } + class var defaultBackgroundAlpha: CGFloat { get { return 1.0 @@ -714,8 +929,76 @@ extension UIColor } } +extension WRNavigationBar +{ + class func isIphoneX() -> Bool { + return UIScreen.main.bounds.equalTo(CGRect(x: 0, y: 0, width: 375, height: 812)) + } + class func navBarBottom() -> Int { + return self.isIphoneX() ? 88 : 64; + } + class func tabBarHeight() -> Int { + return self.isIphoneX() ? 83 : 49; + } + class func screenWidth() -> Int { + return Int(UIScreen.main.bounds.size.width) + } + class func screenHeight() -> Int { + return Int(UIScreen.main.bounds.size.height) + } +} + + + + + + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// 1. 定义 WRAwakeProtocol 协议 +public protocol WRAwakeProtocol: class { + static func wrAwake() +} +public protocol WRFatherAwakeProtocol: class +{ // 1.1 定义 WRFatherAwakeProtocol () + static func fatherAwake() +} + +class NothingToSeeHere +{ + static func harmlessFunction(){ +// let typeCount = Int(objc_getClassList(nil, 0)) +// let types = UnsafeMutablePointer.allocate(capacity: typeCount) +// let autoreleaseintTypes = AutoreleasingUnsafeMutablePointer(types) +// objc_getClassList(autoreleaseintTypes, Int32(typeCount)) //获取所有的类 +// for index in 0 ..< typeCount { +// (types[index] as? WRAwakeProtocol.Type)?.wrAwake() //如果该类实现了SelfAware协议,那么调用 awake 方法 +// (types[index] as? WRFatherAwakeProtocol.Type)?.fatherAwake() +// } +// types.deallocate(capacity: typeCount) + UINavigationBar.wrAwake() + UIViewController.wrAwake() + UINavigationController.fatherAwake() + } +} + +// 2. 让APP启动时只执行一次 harmlessFunction 方法 +extension UIApplication +{ + private static let runOnce:Void = { //使用静态属性以保证只调用一次(该属性是个方法) + NothingToSeeHere.harmlessFunction() + }() + + open override var next: UIResponder?{ //重写next属性 + UIApplication.runOnce + return super.next + } +} + +// 3. 自定义类实现 WRAwakeProtocol 协议,重写 wrAwake 方法 +// 自定义类实现 WRFatherAwakeProtocol 协议,重写 fatherAwake 方法 + diff --git a/WRNavigationBar_swift/Podfile b/WRNavigationBar_swift/Podfile index 4caf475..81b4c14 100644 --- a/WRNavigationBar_swift/Podfile +++ b/WRNavigationBar_swift/Podfile @@ -1,13 +1,4 @@ -# Uncomment this line to define a global platform for your project -#官方Cocoapods的源 -#source 'https://github.com/CocoaPods/Specs.git' - -#本地私有源 -#source 'https://git.oschina.net/scx/JLSpecs.git' - -# 本项目地址 -#source https://github.com/wangrui460 # 修改过得第三方库 diff --git a/WRNavigationBar_swift/Podfile.lock b/WRNavigationBar_swift/Podfile.lock index a57cf55..c6c2166 100644 --- a/WRNavigationBar_swift/Podfile.lock +++ b/WRNavigationBar_swift/Podfile.lock @@ -1,12 +1,12 @@ PODS: - - Kingfisher (3.6.2) + - Kingfisher (4.3.1) DEPENDENCIES: - Kingfisher SPEC CHECKSUMS: - Kingfisher: 2c94e72c6830622c71d06adf4ea024c37d316830 + Kingfisher: 75541c4b62f02e1fde6f9772303de3d9ebe8f5b3 PODFILE CHECKSUM: eedd5593b4e862f4a6b0ebf6fd6f3f022a9f6b1d -COCOAPODS: 1.2.1 +COCOAPODS: 1.3.1 diff --git a/WRNavigationBar_swift/Pods/Kingfisher/README.md b/WRNavigationBar_swift/Pods/Kingfisher/README.md index bd3c0f1..b696677 100644 --- a/WRNavigationBar_swift/Pods/Kingfisher/README.md +++ b/WRNavigationBar_swift/Pods/Kingfisher/README.md @@ -7,12 +7,12 @@

- codebeat badge - + +

Kingfisher is a lightweight, pure-Swift library for downloading and caching images from the web. This project is heavily inspired by the popular [SDWebImage](https://github.com/rs/SDWebImage). It provides you a chance to use a pure-Swift alternative in your next app. @@ -27,6 +27,7 @@ Kingfisher is a lightweight, pure-Swift library for downloading and caching imag - [x] Prefetching images and showing them from cache later when necessary. - [x] Extensions for `UIImageView`, `NSImage` and `UIButton` to directly set an image from a URL. - [x] Built-in transition animation when setting images. +- [x] Customizable placeholder while loading images. - [x] Extensible image processing and image format support. The simplest use-case is setting an image to an image view with the `UIImageView` extension: @@ -41,11 +42,12 @@ Kingfisher will download the image from `url`, send it to both the memory cache ## Requirements - iOS 8.0+ / macOS 10.10+ / tvOS 9.0+ / watchOS 2.0+ -- Swift 3 (Kingfisher 3.x), Swift 2.3 (Kingfisher 2.x) +- Swift 4 (Kingfisher 4.x), Swift 3 (Kingfisher 3.x) -Main development of Kingfisher will support Swift 3. Only critical bug fixes will be made for Kingfisher 2.x. +Main development of Kingfisher is based on Swift 4. Only critical bug fixes will be applied to Kingfisher 3.x. -[Kingfisher 3.0 Migration Guide](https://github.com/onevcat/Kingfisher/wiki/Kingfisher-3.0-Migration-Guide) - If you are upgrading to Kingfisher 3.x from an earlier version, please read this for more information. +- Kingfisher 4.0 Migration - Kingfisher 3.x should be source compatible to Kingfisher 4. The reason for a major update is that we need to specify the Swift version explicitly for Xcode. All deprecated methods in Kingfisher 3 has been removed, so please ensure you have no warning left before you migrate from Kingfisher 3 to Kingfisher 4. If you have any trouble in migrating, please open an issue to discuss. +- [Kingfisher 3.0 Migration Guide](https://github.com/onevcat/Kingfisher/wiki/Kingfisher-3.0-Migration-Guide) - If you are upgrading to Kingfisher 3.x from an earlier version, please read this for more information. ## Next Steps @@ -75,6 +77,36 @@ The logo of Kingfisher is inspired by [Tangram (七巧板)](http://en.wikipedia. Follow and contact me on [Twitter](http://twitter.com/onevcat) or [Sina Weibo](http://weibo.com/onevcat). If you find an issue, just [open a ticket](https://github.com/onevcat/Kingfisher/issues/new). Pull requests are warmly welcome as well. +## Contributors + +This project exists thanks to all the people who contribute. [[Contribute]](https://github.com/onevcat/Kingfisher/blob/master/CONTRIBUTING.md). + + + +## Backers + +Thank you to all our backers! 🙏 [[Become a backer](https://opencollective.com/Kingfisher#backer)] + + + + +## Sponsors + +Support this project by becoming a sponsor. Your logo will show up here with a link to your website. [[Become a sponsor](https://opencollective.com/Kingfisher#sponsor)] + + + + + + + + + + + + + + ### License Kingfisher is released under the MIT license. See LICENSE for details. diff --git a/WRNavigationBar_swift/Pods/Kingfisher/Sources/AnimatedImageView.swift b/WRNavigationBar_swift/Pods/Kingfisher/Sources/AnimatedImageView.swift index 5ea04dc..df65bff 100755 --- a/WRNavigationBar_swift/Pods/Kingfisher/Sources/AnimatedImageView.swift +++ b/WRNavigationBar_swift/Pods/Kingfisher/Sources/AnimatedImageView.swift @@ -149,12 +149,12 @@ open class AnimatedImageView: UIImageView { super.didMoveToSuperview() didMove() } - - // This is for back compatibility that using regular UIImageView to show GIF. - override func shouldPreloadAllGIF() -> Bool { + + // This is for back compatibility that using regular UIImageView to show animated image. + override func shouldPreloadAllAnimation() -> Bool { return false } - + // MARK: - Private method /// Reset the animator. private func reset() { @@ -179,7 +179,25 @@ open class AnimatedImageView: UIImageView { /// Update the current frame with the displayLink duration. private func updateFrame() { - if animator?.updateCurrentFrame(duration: displayLink.duration) ?? false { + let duration: CFTimeInterval + + // CA based display link is opt-out from ProMotion by default. + // So the duration and its FPS might not match. + // See [#718](https://github.com/onevcat/Kingfisher/issues/718) + if #available(iOS 10.0, tvOS 10.0, *) { + // By setting CADisableMinimumFrameDuration to YES in Info.plist may + // cause the preferredFramesPerSecond being 0 + if displayLink.preferredFramesPerSecond == 0 { + duration = displayLink.duration + } else { + // Some devices (like iPad Pro 10.5) will have a different FPS. + duration = 1.0 / Double(displayLink.preferredFramesPerSecond) + } + } else { + duration = displayLink.duration + } + + if animator?.updateCurrentFrame(duration: duration) ?? false { layer.setNeedsDisplay() } } @@ -208,7 +226,7 @@ class Animator { fileprivate var timeSinceLastFrameChange: TimeInterval = 0.0 fileprivate var needsPrescaling = true - /// Loop count of animatd image. + /// Loop count of animated image. private var loopCount = 0 var currentFrame: UIImage? { diff --git a/WRNavigationBar_swift/Pods/Kingfisher/Sources/CacheSerializer.swift b/WRNavigationBar_swift/Pods/Kingfisher/Sources/CacheSerializer.swift index 8d8cdc9..9d4ec7d 100644 --- a/WRNavigationBar_swift/Pods/Kingfisher/Sources/CacheSerializer.swift +++ b/WRNavigationBar_swift/Pods/Kingfisher/Sources/CacheSerializer.swift @@ -64,7 +64,7 @@ public struct DefaultCacheSerializer: CacheSerializer { public func data(with image: Image, original: Data?) -> Data? { let imageFormat = original?.kf.imageFormat ?? .unknown - + let data: Data? switch imageFormat { case .PNG: data = image.kf.pngRepresentation() @@ -72,7 +72,7 @@ public struct DefaultCacheSerializer: CacheSerializer { case .GIF: data = image.kf.gifRepresentation() case .unknown: data = original ?? image.kf.normalized.kf.pngRepresentation() } - + return data } @@ -81,7 +81,7 @@ public struct DefaultCacheSerializer: CacheSerializer { return Kingfisher.image( data: data, scale: options.scaleFactor, - preloadAllGIFData: options.preloadAllGIFData, + preloadAllAnimationData: options.preloadAllAnimationData, onlyFirstFrame: options.onlyLoadFirstFrame) } } diff --git a/WRNavigationBar_swift/Pods/Kingfisher/Sources/Filter.swift b/WRNavigationBar_swift/Pods/Kingfisher/Sources/Filter.swift index 5f20987..b2f4504 100644 --- a/WRNavigationBar_swift/Pods/Kingfisher/Sources/Filter.swift +++ b/WRNavigationBar_swift/Pods/Kingfisher/Sources/Filter.swift @@ -71,23 +71,32 @@ public struct Filter { let filter = CIFilter(name: "CISourceOverCompositing")! filter.setValue(colorImage, forKey: kCIInputImageKey) filter.setValue(input, forKey: kCIInputBackgroundImageKey) + #if swift(>=4.0) + return filter.outputImage?.cropped(to: input.extent) + #else return filter.outputImage?.cropping(to: input.extent) + #endif } } public typealias ColorElement = (CGFloat, CGFloat, CGFloat, CGFloat) /// Color control filter which will apply color control change to images. - public static var colorControl: (ColorElement) -> Filter = { - brightness, contrast, saturation, inputEV in - Filter { input in + public static var colorControl: (ColorElement) -> Filter = { arg -> Filter in + let (brightness, contrast, saturation, inputEV) = arg + return Filter { input in let paramsColor = [kCIInputBrightnessKey: brightness, kCIInputContrastKey: contrast, kCIInputSaturationKey: saturation] - let blackAndWhite = input.applyingFilter("CIColorControls", withInputParameters: paramsColor) let paramsExposure = [kCIInputEVKey: inputEV] + #if swift(>=4.0) + let blackAndWhite = input.applyingFilter("CIColorControls", parameters: paramsColor) + return blackAndWhite.applyingFilter("CIExposureAdjust", parameters: paramsExposure) + #else + let blackAndWhite = input.applyingFilter("CIColorControls", withInputParameters: paramsColor) return blackAndWhite.applyingFilter("CIExposureAdjust", withInputParameters: paramsExposure) + #endif } } @@ -126,20 +135,3 @@ extension Kingfisher where Base: Image { } } - -public extension Image { - - /// Apply a `Filter` containing `CIImage` transformer to `self`. - /// - /// - parameter filter: The filter used to transform `self`. - /// - /// - returns: A transformed image by input `Filter`. - /// - /// - Note: Only CG-based images are supported. If any error happens during transforming, `self` will be returned. - @available(*, deprecated, - message: "Extensions directly on Image are deprecated. Use `kf.apply` instead.", - renamed: "kf.apply") - public func kf_apply(_ filter: Filter) -> Image { - return kf.apply(filter) - } -} diff --git a/WRNavigationBar_swift/Pods/Kingfisher/Sources/FormatIndicatedCacheSerializer.swift b/WRNavigationBar_swift/Pods/Kingfisher/Sources/FormatIndicatedCacheSerializer.swift new file mode 100644 index 0000000..9014e37 --- /dev/null +++ b/WRNavigationBar_swift/Pods/Kingfisher/Sources/FormatIndicatedCacheSerializer.swift @@ -0,0 +1,96 @@ +// +// RequestModifier.swift +// Kingfisher +// +// Created by Junyu Kuang on 5/28/17. +// +// Copyright (c) 2017 Wei Wang +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +import Foundation + +/// `FormatIndicatedCacheSerializer` let you indicate an image format for serialized caches. +/// +/// It could serialize and deserialize PNG, JEPG and GIF images. For +/// image other than these formats, a normalized `pngRepresentation` will be used. +/// +/// Example: +/// ```` +/// private let profileImageSize = CGSize(width: 44, height: 44) +/// +/// private let imageProcessor = RoundCornerImageProcessor( +/// cornerRadius: profileImageSize.width / 2, targetSize: profileImageSize) +/// +/// private let optionsInfo: KingfisherOptionsInfo = [ +/// .cacheSerializer(FormatIndicatedCacheSerializer.png), +/// .backgroundDecode, .processor(imageProcessor), .scaleFactor(UIScreen.main.scale)] +/// +/// extension UIImageView { +/// func setProfileImage(with url: URL) { +/// // Image will always cached as PNG format to preserve alpha channel for round rect. +/// _ = kf.setImage(with: url, options: optionsInfo) +/// } +///} +/// ```` +public struct FormatIndicatedCacheSerializer: CacheSerializer { + + public static let png = FormatIndicatedCacheSerializer(imageFormat: .PNG) + public static let jpeg = FormatIndicatedCacheSerializer(imageFormat: .JPEG) + public static let gif = FormatIndicatedCacheSerializer(imageFormat: .GIF) + + /// The indicated image format. + private let imageFormat: ImageFormat + + public func data(with image: Image, original: Data?) -> Data? { + + func imageData(withFormat imageFormat: ImageFormat) -> Data? { + switch imageFormat { + case .PNG: return image.kf.pngRepresentation() + case .JPEG: return image.kf.jpegRepresentation(compressionQuality: 1.0) + case .GIF: return image.kf.gifRepresentation() + case .unknown: return nil + } + } + + // generate data with indicated image format + if let data = imageData(withFormat: imageFormat) { + return data + } + + let originalFormat = original?.kf.imageFormat ?? .unknown + + // generate data with original image's format + if originalFormat != imageFormat, let data = imageData(withFormat: originalFormat) { + return data + } + + return original ?? image.kf.normalized.kf.pngRepresentation() + } + + /// Same implementation as `DefaultCacheSerializer`. + public func image(with data: Data, options: KingfisherOptionsInfo?) -> Image? { + let options = options ?? KingfisherEmptyOptionsInfo + return Kingfisher.image( + data: data, + scale: options.scaleFactor, + preloadAllAnimationData: options.preloadAllAnimationData, + onlyFirstFrame: options.onlyLoadFirstFrame) + } +} diff --git a/WRNavigationBar_swift/Pods/Kingfisher/Sources/Image.swift b/WRNavigationBar_swift/Pods/Kingfisher/Sources/Image.swift index c132523..5e0aaf4 100755 --- a/WRNavigationBar_swift/Pods/Kingfisher/Sources/Image.swift +++ b/WRNavigationBar_swift/Pods/Kingfisher/Sources/Image.swift @@ -179,7 +179,7 @@ extension Kingfisher where Base: Image { return nil } let rep = NSBitmapImageRep(cgImage: cgimage) - return rep.representation(using: .PNG, properties: [:]) + return rep.representation(using: .png, properties: [:]) #else return UIImagePNGRepresentation(base) #endif @@ -192,7 +192,7 @@ extension Kingfisher where Base: Image { return nil } let rep = NSBitmapImageRep(cgImage: cgImage) - return rep.representation(using:.JPEG, properties: [NSImageCompressionFactor: compressionQuality]) + return rep.representation(using:.jpeg, properties: [.compressionFactor: compressionQuality]) #else return UIImageJPEGRepresentation(base, compressionQuality) #endif @@ -292,10 +292,10 @@ extension Kingfisher where Base: Image { return image #endif } - - static func image(data: Data, scale: CGFloat, preloadAllGIFData: Bool, onlyFirstFrame: Bool) -> Image? { + + static func image(data: Data, scale: CGFloat, preloadAllAnimationData: Bool, onlyFirstFrame: Bool) -> Image? { var image: Image? - + #if os(macOS) switch data.kf.imageFormat { case .JPEG: @@ -307,7 +307,7 @@ extension Kingfisher where Base: Image { with: data, scale: scale, duration: 0.0, - preloadAll: preloadAllGIFData, + preloadAll: preloadAllAnimationData, onlyFirstFrame: onlyFirstFrame) case .unknown: image = Image(data: data) @@ -323,13 +323,13 @@ extension Kingfisher where Base: Image { with: data, scale: scale, duration: 0.0, - preloadAll: preloadAllGIFData, + preloadAll: preloadAllAnimationData, onlyFirstFrame: onlyFirstFrame) case .unknown: image = Image(data: data, scale: scale) } #endif - + return image } } @@ -340,14 +340,19 @@ extension Kingfisher where Base: Image { // MARK: - Round Corner /// Create a round corner image based on `self`. /// - /// - parameter radius: The round corner radius of creating image. - /// - parameter size: The target size of creating image. + /// - parameter radius: The round corner radius of creating image. + /// - parameter size: The target size of creating image. + /// - parameter corners: The target corners which will be applied rounding. + /// - parameter backgroundColor: The background color for the output image /// /// - returns: An image with round corner of `self`. /// /// - Note: This method only works for CG-based image. - public func image(withRoundRadius radius: CGFloat, fit size: CGSize) -> Image { - + public func image(withRoundRadius radius: CGFloat, + fit size: CGSize, + roundingCorners corners: RectCorner = .all, + backgroundColor: Color? = nil) -> Image + { guard let cgImage = cgImage else { assertionFailure("[Kingfisher] Round corner image only works for CG-based image.") return base @@ -356,7 +361,13 @@ extension Kingfisher where Base: Image { let rect = CGRect(origin: CGPoint(x: 0, y: 0), size: size) return draw(cgImage: cgImage, to: size) { #if os(macOS) - let path = NSBezierPath(roundedRect: rect, xRadius: radius, yRadius: radius) + if let backgroundColor = backgroundColor { + let rectPath = NSBezierPath(rect: rect) + backgroundColor.setFill() + rectPath.fill() + } + + let path = NSBezierPath(roundedRect: rect, byRoundingCorners: corners, radius: radius) path.windingRule = .evenOddWindingRule path.addClip() base.draw(in: rect) @@ -365,7 +376,16 @@ extension Kingfisher where Base: Image { assertionFailure("[Kingfisher] Failed to create CG context for image.") return } - let path = UIBezierPath(roundedRect: rect, byRoundingCorners: .allCorners, cornerRadii: CGSize(width: radius, height: radius)).cgPath + + if let backgroundColor = backgroundColor { + let rectPath = UIBezierPath(rect: rect) + backgroundColor.setFill() + rectPath.fill() + } + + let path = UIBezierPath(roundedRect: rect, + byRoundingCorners: corners.uiRectCorner, + cornerRadii: CGSize(width: radius, height: radius)).cgPath context.addPath(path) context.clip() base.draw(in: rect) @@ -449,7 +469,7 @@ extension Kingfisher where Base: Image { /// Create an image with blur effect based on `self`. /// - /// - parameter radius: The blur radius should be used when creating blue. + /// - parameter radius: The blur radius should be used when creating blur effect. /// /// - returns: An image with blur effect applied. /// @@ -501,7 +521,7 @@ extension Kingfisher where Base: Image { return vImage_Buffer(data: data, height: height, width: width, rowBytes: rowBytes) } - guard let context = beginContext(size: size) else { + guard let context = beginContext(size: size, scale: scale) else { assertionFailure("[Kingfisher] Failed to create CG context for blurring image.") return base } @@ -511,7 +531,7 @@ extension Kingfisher where Base: Image { var inBuffer = createEffectBuffer(context) - guard let outContext = beginContext(size: size) else { + guard let outContext = beginContext(size: size, scale: scale) else { assertionFailure("[Kingfisher] Failed to create CG context for blurring image.") return base } @@ -560,7 +580,7 @@ extension Kingfisher where Base: Image { base.draw(in: rect) if fraction > 0 { color.withAlphaComponent(1 - fraction).set() - NSRectFillUsingOperation(rect, .sourceAtop) + rect.fill(using: .sourceAtop) } #else color.set() @@ -603,14 +623,14 @@ extension Kingfisher where Base: Image { #if os(watchOS) return base #else - return apply(.colorControl(brightness, contrast, saturation, inputEV)) + return apply(.colorControl((brightness, contrast, saturation, inputEV))) #endif } } // MARK: - Decode extension Kingfisher where Base: Image { - var decoded: Image? { + var decoded: Image { return decoded(scale: scale) } @@ -626,15 +646,16 @@ extension Kingfisher where Base: Image { assertionFailure("[Kingfisher] Decoding only works for CG-based image.") return base } - let colorSpace = CGColorSpaceCreateDeviceRGB() - guard let context = beginContext(size: CGSize(width: imageRef.width, height: imageRef.height)) else { + + // Draw CGImage in a plain context with scale of 1.0. + guard let context = beginContext(size: CGSize(width: imageRef.width, height: imageRef.height), scale: 1.0) else { assertionFailure("[Kingfisher] Decoding fails to create a valid context.") return base } defer { endContext() } - let rect = CGRect(x: 0, y: 0, width: imageRef.width, height: imageRef.height) + let rect = CGRect(x: 0, y: 0, width: CGFloat(imageRef.width), height: CGFloat(imageRef.height)) context.draw(imageRef, in: rect) let decompressedImageRef = context.makeImage() return Kingfisher.image(cgImage: decompressedImageRef!, scale: scale, refImage: base) @@ -762,7 +783,7 @@ extension Comparable { extension Kingfisher where Base: Image { - func beginContext(size: CGSize) -> CGContext? { + func beginContext(size: CGSize, scale: CGFloat) -> CGContext? { #if os(macOS) guard let rep = NSBitmapImageRep( bitmapDataPlanes: nil, @@ -772,7 +793,7 @@ extension Kingfisher where Base: Image { samplesPerPixel: 4, hasAlpha: true, isPlanar: false, - colorSpaceName: NSCalibratedRGBColorSpace, + colorSpaceName: .calibratedRGB, bytesPerRow: 0, bitsPerPixel: 0) else { @@ -786,7 +807,7 @@ extension Kingfisher where Base: Image { return nil } - NSGraphicsContext.setCurrent(context) + NSGraphicsContext.current = context return context.cgContext #else UIGraphicsBeginImageContextWithOptions(size, false, scale) @@ -815,7 +836,7 @@ extension Kingfisher where Base: Image { samplesPerPixel: 4, hasAlpha: true, isPlanar: false, - colorSpaceName: NSCalibratedRGBColorSpace, + colorSpaceName: .calibratedRGB, bytesPerRow: 0, bitsPerPixel: 0) else { @@ -827,7 +848,7 @@ extension Kingfisher where Base: Image { NSGraphicsContext.saveGraphicsState() let context = NSGraphicsContext(bitmapImageRep: rep) - NSGraphicsContext.setCurrent(context) + NSGraphicsContext.current = context draw() NSGraphicsContext.restoreGraphicsState() @@ -863,120 +884,60 @@ extension Float { } } -// MARK: - Deprecated. Only for back compatibility. -extension Image { - /** - Normalize the image. This method does nothing in OS X. - - - returns: The image itself. - */ - @available(*, deprecated, - message: "Extensions directly on Image are deprecated. Use `kf.normalized` instead.", - renamed: "kf.normalized") - public func kf_normalized() -> Image { - return kf.normalized - } - - // MARK: - Round Corner - - /// Create a round corner image based on `self`. - /// - /// - parameter radius: The round corner radius of creating image. - /// - parameter size: The target size of creating image. - /// - parameter scale: The image scale of creating image. - /// - /// - returns: An image with round corner of `self`. - /// - /// - Note: This method only works for CG-based image. - @available(*, deprecated, - message: "Extensions directly on Image are deprecated. Use `kf.image(withRoundRadius:fit:scale:)` instead.", - renamed: "kf.image") - public func kf_image(withRoundRadius radius: CGFloat, fit size: CGSize, scale: CGFloat) -> Image { - return kf.image(withRoundRadius: radius, fit: size) - } - - // MARK: - Resize - /// Resize `self` to an image of new size. - /// - /// - parameter size: The target size. - /// - /// - returns: An image with new size. - /// - /// - Note: This method only works for CG-based image. - @available(*, deprecated, - message: "Extensions directly on Image are deprecated. Use `kf.resize(to:)` instead.", - renamed: "kf.resize") - public func kf_resize(to size: CGSize) -> Image { - return kf.resize(to: size) - } - - // MARK: - Blur - /// Create an image with blur effect based on `self`. - /// - /// - parameter radius: The blur radius should be used when creating blue. - /// - /// - returns: An image with blur effect applied. - /// - /// - Note: This method only works for CG-based image. - @available(*, deprecated, - message: "Extensions directly on Image are deprecated. Use `kf.blurred(withRadius:)` instead.", - renamed: "kf.blurred") - public func kf_blurred(withRadius radius: CGFloat) -> Image { - return kf.blurred(withRadius: radius) - } - - // MARK: - Overlay - /// Create an image from `self` with a color overlay layer. - /// - /// - parameter color: The color should be use to overlay. - /// - parameter fraction: Fraction of input color. From 0.0 to 1.0. 0.0 means solid color, 1.0 means transparent overlay. - /// - /// - returns: An image with a color overlay applied. - /// - /// - Note: This method only works for CG-based image. - @available(*, deprecated, - message: "Extensions directly on Image are deprecated. Use `kf.overlaying(with:fraction:)` instead.", - renamed: "kf.overlaying") - public func kf_overlaying(with color: Color, fraction: CGFloat) -> Image { - return kf.overlaying(with: color, fraction: fraction) - } - - // MARK: - Tint - - /// Create an image from `self` with a color tint. - /// - /// - parameter color: The color should be used to tint `self` - /// - /// - returns: An image with a color tint applied. - @available(*, deprecated, - message: "Extensions directly on Image are deprecated. Use `kf.tinted(with:)` instead.", - renamed: "kf.tinted") - public func kf_tinted(with color: Color) -> Image { - return kf.tinted(with: color) +#if os(macOS) +extension NSBezierPath { + convenience init(roundedRect rect: NSRect, topLeftRadius: CGFloat, topRightRadius: CGFloat, + bottomLeftRadius: CGFloat, bottomRightRadius: CGFloat) + { + self.init() + + let maxCorner = min(rect.width, rect.height) / 2 + + let radiusTopLeft = min(maxCorner, max(0, topLeftRadius)) + let radiustopRight = min(maxCorner, max(0, topRightRadius)) + let radiusbottomLeft = min(maxCorner, max(0, bottomLeftRadius)) + let radiusbottomRight = min(maxCorner, max(0, bottomRightRadius)) + + guard !NSIsEmptyRect(rect) else { + return + } + + let topLeft = NSMakePoint(NSMinX(rect), NSMaxY(rect)); + let topRight = NSMakePoint(NSMaxX(rect), NSMaxY(rect)); + let bottomRight = NSMakePoint(NSMaxX(rect), NSMinY(rect)); + + move(to: NSMakePoint(NSMidX(rect), NSMaxY(rect))) + appendArc(from: topLeft, to: rect.origin, radius: radiusTopLeft) + appendArc(from: rect.origin, to: bottomRight, radius: radiusbottomLeft) + appendArc(from: bottomRight, to: topRight, radius: radiusbottomRight) + appendArc(from: topRight, to: topLeft, radius: radiustopRight) + close() + } + + convenience init(roundedRect rect: NSRect, byRoundingCorners corners: RectCorner, radius: CGFloat) { + let radiusTopLeft = corners.contains(.topLeft) ? radius : 0 + let radiusTopRight = corners.contains(.topRight) ? radius : 0 + let radiusBottomLeft = corners.contains(.bottomLeft) ? radius : 0 + let radiusBottomRight = corners.contains(.bottomRight) ? radius : 0 + + self.init(roundedRect: rect, topLeftRadius: radiusTopLeft, topRightRadius: radiusTopRight, + bottomLeftRadius: radiusBottomLeft, bottomRightRadius: radiusBottomRight) } +} - // MARK: - Color Control - - /// Create an image from `self` with color control. - /// - /// - parameter brightness: Brightness changing to image. - /// - parameter contrast: Contrast changing to image. - /// - parameter saturation: Saturation changing to image. - /// - parameter inputEV: InputEV changing to image. - /// - /// - returns: An image with color control applied. - @available(*, deprecated, - message: "Extensions directly on Image are deprecated. Use `kf.adjusted` instead.", - renamed: "kf.adjusted") - public func kf_adjusted(brightness: CGFloat, contrast: CGFloat, saturation: CGFloat, inputEV: CGFloat) -> Image { - return kf.adjusted(brightness: brightness, contrast: contrast, saturation: saturation, inputEV: inputEV) +#else +extension RectCorner { + var uiRectCorner: UIRectCorner { + + var result: UIRectCorner = [] + + if self.contains(.topLeft) { result.insert(.topLeft) } + if self.contains(.topRight) { result.insert(.topRight) } + if self.contains(.bottomLeft) { result.insert(.bottomLeft) } + if self.contains(.bottomRight) { result.insert(.bottomRight) } + + return result } } +#endif -extension Kingfisher where Base: Image { - @available(*, deprecated, - message: "`scale` is not used. Use the version without scale instead. (Remove the `scale` argument)") - public func image(withRoundRadius radius: CGFloat, fit size: CGSize, scale: CGFloat) -> Image { - return image(withRoundRadius: radius, fit: size) - } -} diff --git a/WRNavigationBar_swift/Pods/Kingfisher/Sources/ImageCache.swift b/WRNavigationBar_swift/Pods/Kingfisher/Sources/ImageCache.swift index 62aaa0b..8d445b5 100755 --- a/WRNavigationBar_swift/Pods/Kingfisher/Sources/ImageCache.swift +++ b/WRNavigationBar_swift/Pods/Kingfisher/Sources/ImageCache.swift @@ -60,6 +60,13 @@ Cache type of a cached image. */ public enum CacheType { case none, memory, disk + + public var cached: Bool { + switch self { + case .memory, .disk: return true + case .none: return false + } + } } /// `ImageCache` represents both the memory and disk cache system of Kingfisher. @@ -288,6 +295,10 @@ open class ImageCache { options.callbackDispatchQueue.safeAsync { completionHandler(image, .memory) } + } else if options.fromMemoryCacheOrRefresh { // Only allows to get images from memory cache. + options.callbackDispatchQueue.safeAsync { + completionHandler(nil, .none) + } } else { var sSelf: ImageCache! = self block = DispatchWorkItem(block: { @@ -295,7 +306,7 @@ open class ImageCache { if let image = sSelf.retrieveImageInDiskCache(forKey: key, options: options) { if options.backgroundDecode { sSelf.processQueue.async { - let result = image.kf.decoded(scale: options.scaleFactor) + let result = image.kf.decoded sSelf.store(result, forKey: key, @@ -303,7 +314,6 @@ open class ImageCache { cacheSerializer: options.cacheSerializer, toDisk: false, completionHandler: nil) - options.callbackDispatchQueue.safeAsync { completionHandler(result, .memory) sSelf = nil @@ -542,27 +552,17 @@ open class ImageCache { // MARK: - Check cache status - /** - * Cache result for checking whether an image is cached for a key. - */ - public struct CacheCheckResult { - public let cached: Bool - public let cacheType: CacheType? - } - - /** - Check whether an image is cached for a key. - - - parameter key: Key for the image. - - - returns: The check result. - */ - open func isImageCached(forKey key: String, processorIdentifier identifier: String = "") -> CacheCheckResult { - + /// Cache type for checking whether an image is cached for a key in current cache. + /// + /// - Parameters: + /// - key: Key for the image. + /// - identifier: Processor identifier which used for this image. Default is empty string. + /// - Returns: A `CacheType` instance which indicates the cache status. `.none` means the image is not in cache yet. + open func imageCachedType(forKey key: String, processorIdentifier identifier: String = "") -> CacheType { let computedKey = key.computedKey(with: identifier) if memoryCache.object(forKey: computedKey as NSString) != nil { - return CacheCheckResult(cached: true, cacheType: .memory) + return .memory } let filePath = cachePath(forComputedKey: computedKey) @@ -571,12 +571,12 @@ open class ImageCache { ioQueue.sync { diskCached = fileManager.fileExists(atPath: filePath) } - + if diskCached { - return CacheCheckResult(cached: true, cacheType: .disk) + return .disk } - return CacheCheckResult(cached: false, cacheType: nil) + return .none } /** @@ -652,6 +652,39 @@ extension ImageCache { } } +// MARK: - Deprecated +extension ImageCache { + /** + * Cache result for checking whether an image is cached for a key. + */ + @available(*, deprecated, + message: "CacheCheckResult is deprecated. Use imageCachedType(forKey:processorIdentifier:) API instead.") + public struct CacheCheckResult { + public let cached: Bool + public let cacheType: CacheType? + } + + /** + Check whether an image is cached for a key. + + - parameter key: Key for the image. + + - returns: The check result. + */ + @available(*, deprecated, + message: "Use imageCachedType(forKey:processorIdentifier:) instead. CacheCheckResult.none indicates not being cached.", + renamed: "imageCachedType(forKey:processorIdentifier:)") + open func isImageCached(forKey key: String, processorIdentifier identifier: String = "") -> CacheCheckResult { + let result = imageCachedType(forKey: key, processorIdentifier: identifier) + switch result { + case .memory, .disk: + return CacheCheckResult(cached: true, cacheType: result) + case .none: + return CacheCheckResult(cached: false, cacheType: nil) + } + } +} + extension Kingfisher where Base: Image { var imageCost: Int { return images == nil ? diff --git a/WRNavigationBar_swift/Pods/Kingfisher/Sources/ImageDownloader.swift b/WRNavigationBar_swift/Pods/Kingfisher/Sources/ImageDownloader.swift index 46039b4..e318d59 100755 --- a/WRNavigationBar_swift/Pods/Kingfisher/Sources/ImageDownloader.swift +++ b/WRNavigationBar_swift/Pods/Kingfisher/Sources/ImageDownloader.swift @@ -108,6 +108,14 @@ public protocol ImageDownloaderDelegate: class { */ func imageDownloader(_ downloader: ImageDownloader, didDownload image: Image, for url: URL, with response: URLResponse?) + /** + Called when the `ImageDownloader` object starts to download an image from specified URL. + + - parameter downloader: The `ImageDownloader` object starts the downloading. + - parameter url: URL of the original request. + - parameter response: The request object of the downloading process. + */ + func imageDownloader(_ downloader: ImageDownloader, willDownloadImageForURL url: URL, with request: URLRequest?) /** Check if a received HTTP status code is valid or not. @@ -124,14 +132,32 @@ public protocol ImageDownloaderDelegate: class { you can implement this method to change that behavior. */ func isValidStatusCode(_ code: Int, for downloader: ImageDownloader) -> Bool + + /** + Called when the `ImageDownloader` object successfully downloaded image data from specified URL. + + - parameter downloader: The `ImageDownloader` object finishes data downloading. + - parameter data: Downloaded data. + - parameter url: URL of the original request URL. + + - returns: The data from which Kingfisher should use to create an image. + + - Note: This callback can be used to preprocess raw image data + before creation of UIImage instance (i.e. decrypting or verification). + */ + func imageDownloader(_ downloader: ImageDownloader, didDownload data: Data, for url: URL) -> Data? } extension ImageDownloaderDelegate { public func imageDownloader(_ downloader: ImageDownloader, didDownload image: Image, for url: URL, with response: URLResponse?) {} + public func imageDownloader(_ downloader: ImageDownloader, willDownloadImageForURL url: URL, with request: URLRequest?) {} public func isValidStatusCode(_ code: Int, for downloader: ImageDownloader) -> Bool { return (200..<400).contains(code) } + public func imageDownloader(_ downloader: ImageDownloader, didDownload data: Data, for url: URL) -> Data? { + return data + } } /// Protocol indicates that an authentication challenge could be handled. @@ -144,9 +170,22 @@ public protocol AuthenticationChallengeResponsable: class { - parameter challenge: An object that contains the request for authentication. - parameter completionHandler: A handler that your delegate method must call. - - Note: This method is a forward from `URLSession(:didReceiveChallenge:completionHandler:)`. Please refer to the document of it in `NSURLSessionDelegate`. + - Note: This method is a forward from `URLSessionDelegate.urlSession(:didReceiveChallenge:completionHandler:)`. Please refer to the document of it in `URLSessionDelegate`. */ func downloader(_ downloader: ImageDownloader, didReceive challenge: URLAuthenticationChallenge, completionHandler: @escaping (URLSession.AuthChallengeDisposition, URLCredential?) -> Void) + + /** + Called when an session level authentication challenge is received. + This method provide a chance to handle and response to the authentication challenge before downloading could start. + + - parameter downloader: The downloader which receives this challenge. + - parameter task: The task whose request requires authentication. + - parameter challenge: An object that contains the request for authentication. + - parameter completionHandler: A handler that your delegate method must call. + + - Note: This method is a forward from `URLSessionTaskDelegate.urlSession(:task:didReceiveChallenge:completionHandler:)`. Please refer to the document of it in `URLSessionTaskDelegate`. + */ + func downloader(_ downloader: ImageDownloader, task: URLSessionTask, didReceive challenge: URLAuthenticationChallenge, completionHandler: @escaping (URLSession.AuthChallengeDisposition, URLCredential?) -> Void) } extension AuthenticationChallengeResponsable { @@ -163,6 +202,12 @@ extension AuthenticationChallengeResponsable { completionHandler(.performDefaultHandling, nil) } + + func downloader(_ downloader: ImageDownloader, task: URLSessionTask, didReceive challenge: URLAuthenticationChallenge, completionHandler: @escaping (URLSession.AuthChallengeDisposition, URLCredential?) -> Void) { + + completionHandler(.performDefaultHandling, nil) + } + } /// `ImageDownloader` represents a downloading manager for requesting the image with a URL from server. @@ -174,6 +219,7 @@ open class ImageDownloader { var downloadTaskCount = 0 var downloadTask: RetrieveImageDownloadTask? + var cancelSemaphore: DispatchSemaphore? } // MARK: - Public property @@ -189,12 +235,13 @@ open class ImageDownloader { /// You could change the configuration before a downloaing task starts. A configuration without persistent storage for caches is requsted for downloader working correctly. open var sessionConfiguration = URLSessionConfiguration.ephemeral { didSet { + session?.invalidateAndCancel() session = URLSession(configuration: sessionConfiguration, delegate: sessionHandler, delegateQueue: OperationQueue.main) } } /// Whether the download requests should use pipeling or not. Default is false. - open var requestsUsePipeling = false + open var requestsUsePipelining = false fileprivate let sessionHandler: ImageDownloaderSessionHandler fileprivate var session: URLSession? @@ -209,6 +256,7 @@ open class ImageDownloader { // MARK: - Internal property let barrierQueue: DispatchQueue let processQueue: DispatchQueue + let cancelQueue: DispatchQueue typealias CallbackPair = (progressBlock: ImageDownloaderProgressBlock?, completionHandler: ImageDownloaderCompletionHandler?) @@ -232,6 +280,7 @@ open class ImageDownloader { barrierQueue = DispatchQueue(label: "com.onevcat.Kingfisher.ImageDownloader.Barrier.\(name)", attributes: .concurrent) processQueue = DispatchQueue(label: "com.onevcat.Kingfisher.ImageDownloader.Process.\(name)", attributes: .concurrent) + cancelQueue = DispatchQueue(label: "com.onevcat.Kingfisher.ImageDownloader.Cancel.\(name)") sessionHandler = ImageDownloaderSessionHandler() @@ -240,9 +289,13 @@ open class ImageDownloader { session = URLSession(configuration: sessionConfiguration, delegate: sessionHandler, delegateQueue: .main) } + deinit { + session?.invalidateAndCancel() + } + func fetchLoad(for url: URL) -> ImageFetchLoad? { var fetchLoad: ImageFetchLoad? - barrierQueue.sync { fetchLoad = fetchLoads[url] } + barrierQueue.sync(flags: .barrier) { fetchLoad = fetchLoads[url] } return fetchLoad } @@ -250,6 +303,7 @@ open class ImageDownloader { Download an image with a URL and option. - parameter url: Target URL. + - parameter retrieveImageTask: The task to cooporate with cache. Pass `nil` if you are not trying to use downloader and cache. - parameter options: The options could control download behavior. See `KingfisherOptionsInfo`. - parameter progressBlock: Called when the download progress updated. - parameter completionHandler: Called when the download progress finishes. @@ -258,25 +312,10 @@ open class ImageDownloader { */ @discardableResult open func downloadImage(with url: URL, - options: KingfisherOptionsInfo? = nil, - progressBlock: ImageDownloaderProgressBlock? = nil, - completionHandler: ImageDownloaderCompletionHandler? = nil) -> RetrieveImageDownloadTask? - { - return downloadImage(with: url, - retrieveImageTask: nil, - options: options, - progressBlock: progressBlock, - completionHandler: completionHandler) - } -} - -// MARK: - Download method -extension ImageDownloader { - func downloadImage(with url: URL, - retrieveImageTask: RetrieveImageTask?, - options: KingfisherOptionsInfo?, - progressBlock: ImageDownloaderProgressBlock?, - completionHandler: ImageDownloaderCompletionHandler?) -> RetrieveImageDownloadTask? + retrieveImageTask: RetrieveImageTask? = nil, + options: KingfisherOptionsInfo? = nil, + progressBlock: ImageDownloaderProgressBlock? = nil, + completionHandler: ImageDownloaderCompletionHandler? = nil) -> RetrieveImageDownloadTask? { if let retrieveImageTask = retrieveImageTask, retrieveImageTask.cancelledBeforeDownloadStarting { completionHandler?(nil, NSError(domain: KingfisherErrorDomain, code: KingfisherError.downloadCancelledBeforeStarting.rawValue, userInfo: nil), nil, nil) @@ -287,7 +326,7 @@ extension ImageDownloader { // We need to set the URL as the load key. So before setup progress, we need to ask the `requestModifier` for a final URL. var request = URLRequest(url: url, cachePolicy: .reloadIgnoringLocalCacheData, timeoutInterval: timeout) - request.httpShouldUsePipelining = requestsUsePipeling + request.httpShouldUsePipelining = requestsUsePipelining if let modifier = options?.modifier { guard let r = modifier.modified(for: request) else { @@ -309,9 +348,10 @@ extension ImageDownloader { let dataTask = session.dataTask(with: request) fetchLoad.downloadTask = RetrieveImageDownloadTask(internalTask: dataTask, ownerDownloader: self) - + dataTask.priority = options?.downloadPriority ?? URLSessionTask.defaultPriority dataTask.resume() + self.delegate?.imageDownloader(self, willDownloadImageForURL: url, with: request) // Hold self while the task is executing. self.sessionHandler.downloadHolder = self @@ -325,25 +365,45 @@ extension ImageDownloader { return downloadTask } +} + +// MARK: - Download method +extension ImageDownloader { + // A single key may have multiple callbacks. Only download once. - func setup(progressBlock: ImageDownloaderProgressBlock?, with completionHandler: ImageDownloaderCompletionHandler?, for url: URL, options: KingfisherOptionsInfo?, started: ((URLSession, ImageFetchLoad) -> Void)) { + func setup(progressBlock: ImageDownloaderProgressBlock?, with completionHandler: ImageDownloaderCompletionHandler?, for url: URL, options: KingfisherOptionsInfo?, started: @escaping ((URLSession, ImageFetchLoad) -> Void)) { - barrierQueue.sync(flags: .barrier) { - let loadObjectForURL = fetchLoads[url] ?? ImageFetchLoad() - let callbackPair = (progressBlock: progressBlock, completionHandler: completionHandler) - - loadObjectForURL.contents.append((callbackPair, options ?? KingfisherEmptyOptionsInfo)) - - fetchLoads[url] = loadObjectForURL - - if let session = session { - started(session, loadObjectForURL) + func prepareFetchLoad() { + barrierQueue.sync(flags: .barrier) { + let loadObjectForURL = fetchLoads[url] ?? ImageFetchLoad() + let callbackPair = (progressBlock: progressBlock, completionHandler: completionHandler) + + loadObjectForURL.contents.append((callbackPair, options ?? KingfisherEmptyOptionsInfo)) + + fetchLoads[url] = loadObjectForURL + + if let session = session { + started(session, loadObjectForURL) + } } } + + if let fetchLoad = fetchLoad(for: url), fetchLoad.downloadTaskCount == 0 { + if fetchLoad.cancelSemaphore == nil { + fetchLoad.cancelSemaphore = DispatchSemaphore(value: 0) + } + cancelQueue.async { + _ = fetchLoad.cancelSemaphore?.wait(timeout: .distantFuture) + fetchLoad.cancelSemaphore = nil + prepareFetchLoad() + } + } else { + prepareFetchLoad() + } } func cancelDownloadingTask(_ task: RetrieveImageDownloadTask) { - barrierQueue.sync { + barrierQueue.sync(flags: .barrier) { if let URL = task.internalTask.originalRequest?.url, let imageFetchLoad = self.fetchLoads[URL] { imageFetchLoad.downloadTaskCount -= 1 if imageFetchLoad.downloadTaskCount == 0 { @@ -352,13 +412,6 @@ extension ImageDownloader { } } } - - func clean(for url: URL) { - barrierQueue.sync(flags: .barrier) { - fetchLoads.removeValue(forKey: url) - return - } - } } // MARK: - NSURLSessionDataDelegate @@ -438,15 +491,24 @@ class ImageDownloaderSessionHandler: NSObject, URLSessionDataDelegate, Authentic downloader.authenticationChallengeResponder?.downloader(downloader, didReceive: challenge, completionHandler: completionHandler) } - private func cleanFetchLoad(for url: URL) { + func urlSession(_ session: URLSession, task: URLSessionTask, didReceive challenge: URLAuthenticationChallenge, completionHandler: @escaping (URLSession.AuthChallengeDisposition, URLCredential?) -> Void) { guard let downloader = downloadHolder else { return } - downloader.clean(for: url) - - if downloader.fetchLoads.isEmpty { - downloadHolder = nil + downloader.authenticationChallengeResponder?.downloader(downloader, task: task, didReceive: challenge, completionHandler: completionHandler) + } + + private func cleanFetchLoad(for url: URL) { + guard let downloader = downloadHolder else { + return + } + + downloader.barrierQueue.sync(flags: .barrier) { + downloader.fetchLoads.removeValue(forKey: url) + if downloader.fetchLoads.isEmpty { + downloadHolder = nil + } } } @@ -458,6 +520,11 @@ class ImageDownloaderSessionHandler: NSObject, URLSessionDataDelegate, Authentic // We need to clean the fetch load first, before actually calling completion handler. cleanFetchLoad(for: url) + var leftSignal: Int + repeat { + leftSignal = fetchLoad.cancelSemaphore?.signal() ?? 0 + } while leftSignal != 0 + for content in fetchLoad.contents { content.options.callbackDispatchQueue.safeAsync { content.callback.completionHandler?(nil, error as NSError, url, nil) @@ -480,7 +547,14 @@ class ImageDownloaderSessionHandler: NSObject, URLSessionDataDelegate, Authentic self.cleanFetchLoad(for: url) - let data = fetchLoad.responseData as Data + let data: Data? + let fetchedData = fetchLoad.responseData as Data + + if let delegate = downloader.delegate { + data = delegate.imageDownloader(downloader, didDownload: fetchedData, for: url) + } else { + data = fetchedData + } // Cache the processed images. So we do not need to re-process the image if using the same processor. // Key is the identifier of processor. @@ -494,9 +568,8 @@ class ImageDownloaderSessionHandler: NSObject, URLSessionDataDelegate, Authentic let processor = options.processor var image = imageCache[processor.identifier] - if image == nil { + if let data = data, image == nil { image = processor.process(item: .data(data), options: options) - // Add the processed image to cache. // If `image` is nil, nothing will happen (since the key is not existing before). imageCache[processor.identifier] = image @@ -507,7 +580,7 @@ class ImageDownloaderSessionHandler: NSObject, URLSessionDataDelegate, Authentic downloader.delegate?.imageDownloader(downloader, didDownload: image, for: url, with: task.response) if options.backgroundDecode { - let decodedImage = image.kf.decoded(scale: options.scaleFactor) + let decodedImage = image.kf.decoded callbackQueue.safeAsync { completionHandler?(decodedImage, nil, url, data) } } else { callbackQueue.safeAsync { completionHandler?(image, nil, url, data) } @@ -530,3 +603,4 @@ class ImageDownloaderSessionHandler: NSObject, URLSessionDataDelegate, Authentic // Placeholder. For retrieving extension methods of ImageDownloaderDelegate extension ImageDownloader: ImageDownloaderDelegate {} + diff --git a/WRNavigationBar_swift/Pods/Kingfisher/Sources/ImagePrefetcher.swift b/WRNavigationBar_swift/Pods/Kingfisher/Sources/ImagePrefetcher.swift index b7c0a21..558ddfa 100755 --- a/WRNavigationBar_swift/Pods/Kingfisher/Sources/ImagePrefetcher.swift +++ b/WRNavigationBar_swift/Pods/Kingfisher/Sources/ImagePrefetcher.swift @@ -181,13 +181,9 @@ public class ImagePrefetcher { */ public func stop() { DispatchQueue.main.safeAsync { - if self.finished { return } - self.stopped = true - self.tasks.forEach { (_, task) -> () in - task.cancel() - } + self.tasks.values.forEach { $0.cancel() } } } @@ -237,9 +233,8 @@ public class ImagePrefetcher { if optionsInfo.forceRefresh { downloadAndCache(resource) } else { - let alreadyInCache = manager.cache.isImageCached(forKey: resource.cacheKey, + let alreadyInCache = manager.cache.imageCachedType(forKey: resource.cacheKey, processorIdentifier: optionsInfo.processor.identifier).cached - if alreadyInCache { append(cached: resource) } else { diff --git a/WRNavigationBar_swift/Pods/Kingfisher/Sources/ImageProcessor.swift b/WRNavigationBar_swift/Pods/Kingfisher/Sources/ImageProcessor.swift index dc9088f..e448802 100644 --- a/WRNavigationBar_swift/Pods/Kingfisher/Sources/ImageProcessor.swift +++ b/WRNavigationBar_swift/Pods/Kingfisher/Sources/ImageProcessor.swift @@ -27,7 +27,6 @@ import Foundation import CoreGraphics - /// The item which could be processed by an `ImageProcessor` /// /// - image: Input image @@ -88,6 +87,14 @@ public extension ImageProcessor { } } +func ==(left: ImageProcessor, right: ImageProcessor) -> Bool { + return left.identifier == right.identifier +} + +func !=(left: ImageProcessor, right: ImageProcessor) -> Bool { + return !(left == right) +} + fileprivate struct GeneralProcessor: ImageProcessor { let identifier: String let p: ProcessorImp @@ -127,12 +134,32 @@ public struct DefaultImageProcessor: ImageProcessor { return Kingfisher.image( data: data, scale: options.scaleFactor, - preloadAllGIFData: options.preloadAllGIFData, + preloadAllAnimationData: options.preloadAllAnimationData, onlyFirstFrame: options.onlyLoadFirstFrame) } } } +public struct RectCorner: OptionSet { + public let rawValue: Int + public static let topLeft = RectCorner(rawValue: 1 << 0) + public static let topRight = RectCorner(rawValue: 1 << 1) + public static let bottomLeft = RectCorner(rawValue: 1 << 2) + public static let bottomRight = RectCorner(rawValue: 1 << 3) + public static let all: RectCorner = [.topLeft, .topRight, .bottomLeft, .bottomRight] + + public init(rawValue: Int) { + self.rawValue = rawValue + } + + var cornerIdentifier: String { + if self == .all { + return "" + } + return "_corner(\(rawValue))" + } +} + /// Processor for making round corner images. Only CG-based images are supported in macOS, /// if a non-CG image passed in, the processor will do nothing. public struct RoundCornerImageProcessor: ImageProcessor { @@ -144,23 +171,43 @@ public struct RoundCornerImageProcessor: ImageProcessor { /// Corner radius will be applied in processing. public let cornerRadius: CGFloat + /// The target corners which will be applied rounding. + public let roundingCorners: RectCorner + /// Target size of output image should be. If `nil`, the image will keep its original size after processing. public let targetSize: CGSize? - + + /// Background color of the output image. If `nil`, it will stay transparent. + public let backgroundColor: Color? + /// Initialize a `RoundCornerImageProcessor` /// - /// - parameter cornerRadius: Corner radius will be applied in processing. - /// - parameter targetSize: Target size of output image should be. If `nil`, - /// the image will keep its original size after processing. - /// Default is `nil`. - public init(cornerRadius: CGFloat, targetSize: CGSize? = nil) { + /// - parameter cornerRadius: Corner radius will be applied in processing. + /// - parameter targetSize: Target size of output image should be. If `nil`, + /// the image will keep its original size after processing. + /// Default is `nil`. + /// - parameter corners: The target corners which will be applied rounding. Default is `.all`. + /// - parameter backgroundColor: Backgroud color to apply for the output image. Default is `nil`. + public init(cornerRadius: CGFloat, targetSize: CGSize? = nil, roundingCorners corners: RectCorner = .all, backgroundColor: Color? = nil) { self.cornerRadius = cornerRadius self.targetSize = targetSize - if let size = targetSize { - self.identifier = "com.onevcat.Kingfisher.RoundCornerImageProcessor(\(cornerRadius)_\(size))" - } else { - self.identifier = "com.onevcat.Kingfisher.RoundCornerImageProcessor(\(cornerRadius))" - } + self.roundingCorners = corners + self.backgroundColor = backgroundColor + + self.identifier = { + var identifier = "" + + if let size = targetSize { + identifier = "com.onevcat.Kingfisher.RoundCornerImageProcessor(\(cornerRadius)_\(size)\(corners.cornerIdentifier))" + } else { + identifier = "com.onevcat.Kingfisher.RoundCornerImageProcessor(\(cornerRadius)\(corners.cornerIdentifier))" + } + if let backgroundColor = backgroundColor { + identifier += "_\(backgroundColor)" + } + + return identifier + }() } /// Process an input `ImageProcessItem` item to an image for this processor. @@ -175,7 +222,7 @@ public struct RoundCornerImageProcessor: ImageProcessor { switch item { case .image(let image): let size = targetSize ?? image.kf.size - return image.kf.image(withRoundRadius: cornerRadius, fit: size) + return image.kf.image(withRoundRadius: cornerRadius, fit: size, roundingCorners: roundingCorners, backgroundColor: backgroundColor) case .data(_): return (DefaultImageProcessor.default >> self).process(item: item, options: options) } @@ -537,25 +584,3 @@ fileprivate extension Color { return String(format:"#%08x", rgba) } } - -// MARK: - Deprecated -extension ResizingImageProcessor { - /// Reference size of output image should follow. - @available(*, deprecated, - message: "targetSize are renamed. Use `referenceSize` instead", - renamed: "referenceSize") - public var targetSize: CGSize { - return referenceSize - } - - /// Initialize a `ResizingImageProcessor` - /// - /// - parameter targetSize: Reference size of output image should follow. - /// - parameter contentMode: Target content mode of output image should be. - @available(*, deprecated, - message: "targetSize and contentMode are renamed. Use `init(referenceSize:mode:)` instead", - renamed: "init(referenceSize:mode:)") - public init(targetSize: CGSize, contentMode: ContentMode = .none) { - self.init(referenceSize: targetSize, mode: contentMode) - } -} diff --git a/WRNavigationBar_swift/Pods/Kingfisher/Sources/ImageView+Kingfisher.swift b/WRNavigationBar_swift/Pods/Kingfisher/Sources/ImageView+Kingfisher.swift index ac92a4f..b39bfae 100755 --- a/WRNavigationBar_swift/Pods/Kingfisher/Sources/ImageView+Kingfisher.swift +++ b/WRNavigationBar_swift/Pods/Kingfisher/Sources/ImageView+Kingfisher.swift @@ -33,7 +33,7 @@ import UIKit // MARK: - Extension methods. /** - * Set image to use from web. + * Set image to use from web. */ extension Kingfisher where Base: ImageView { /** @@ -49,25 +49,29 @@ extension Kingfisher where Base: ImageView { - note: Both the `progressBlock` and `completionHandler` will be invoked in main thread. The `CallbackDispatchQueue` specified in `optionsInfo` will not be used in callbacks of this method. + + If `resource` is `nil`, the `placeholder` image will be set and + `completionHandler` will be called with both `error` and `image` being `nil`. */ @discardableResult public func setImage(with resource: Resource?, - placeholder: Image? = nil, + placeholder: Placeholder? = nil, options: KingfisherOptionsInfo? = nil, progressBlock: DownloadProgressBlock? = nil, completionHandler: CompletionHandler? = nil) -> RetrieveImageTask { guard let resource = resource else { - base.image = placeholder + self.placeholder = placeholder setWebURL(nil) completionHandler?(nil, nil, .none, nil) return .empty } - var options = options ?? KingfisherEmptyOptionsInfo + var options = KingfisherManager.shared.defaultOptions + (options ?? KingfisherEmptyOptionsInfo) + let noImageOrPlaceholderSet = base.image == nil && self.placeholder == nil - if !options.keepCurrentImageWhileLoading { - base.image = placeholder + if !options.keepCurrentImageWhileLoading || noImageOrPlaceholderSet { // Always set placeholder while there is no image/placehoer yet. + self.placeholder = placeholder } let maybeIndicator = indicator @@ -75,8 +79,8 @@ extension Kingfisher where Base: ImageView { setWebURL(resource.downloadURL) - if base.shouldPreloadAllGIF() { - options.append(.preloadAllGIFData) + if base.shouldPreloadAllAnimation() { + options.append(.preloadAllAnimationData) } let task = KingfisherManager.shared.retrieveImage( @@ -92,20 +96,22 @@ extension Kingfisher where Base: ImageView { }, completionHandler: {[weak base] image, error, cacheType, imageURL in DispatchQueue.main.safeAsync { + maybeIndicator?.stopAnimatingView() guard let strongBase = base, imageURL == self.webURL else { + completionHandler?(image, error, cacheType, imageURL) return } + self.setImageTask(nil) guard let image = image else { - maybeIndicator?.stopAnimatingView() completionHandler?(nil, error, cacheType, imageURL) return } - guard let transitionItem = options.firstMatchIgnoringAssociatedValue(.transition(.none)), + guard let transitionItem = options.lastMatchIgnoringAssociatedValue(.transition(.none)), case .transition(let transition) = transitionItem, ( options.forceTransition || cacheType == .none) else { - maybeIndicator?.stopAnimatingView() + self.placeholder = nil strongBase.image = image completionHandler?(image, error, cacheType, imageURL) return @@ -115,6 +121,8 @@ extension Kingfisher where Base: ImageView { UIView.transition(with: strongBase, duration: 0.0, options: [], animations: { maybeIndicator?.stopAnimatingView() }, completion: { _ in + + self.placeholder = nil UIView.transition(with: strongBase, duration: transition.duration, options: [transition.animationOptions, .allowUserInteraction], animations: { @@ -148,6 +156,7 @@ extension Kingfisher where Base: ImageView { private var lastURLKey: Void? private var indicatorKey: Void? private var indicatorTypeKey: Void? +private var placeholderKey: Void? private var imageTaskKey: Void? extension Kingfisher where Base: ImageView { @@ -200,7 +209,10 @@ extension Kingfisher where Base: ImageView { // Add new if var newIndicator = newValue { - newIndicator.view.frame = base.frame + // Set default indicator frame if the view's frame not set. + if newIndicator.view.frame == .zero { + newIndicator.view.frame = base.frame + } newIndicator.viewCenter = CGPoint(x: base.bounds.midX, y: base.bounds.midY) newIndicator.view.isHidden = true base.addSubview(newIndicator.view) @@ -218,75 +230,29 @@ extension Kingfisher where Base: ImageView { fileprivate func setImageTask(_ task: RetrieveImageTask?) { objc_setAssociatedObject(base, &imageTaskKey, task, .OBJC_ASSOCIATION_RETAIN_NONATOMIC) } -} - - -// MARK: - Deprecated. Only for back compatibility. -/** -* Set image to use from web. Deprecated. Use `kf` namespacing instead. -*/ -extension ImageView { - /** - Set an image with a resource, a placeholder image, options, progress handler and completion handler. - - - parameter resource: Resource object contains information such as `cacheKey` and `downloadURL`. - - parameter placeholder: A placeholder image when retrieving the image at URL. - - parameter options: A dictionary could control some behaviors. See `KingfisherOptionsInfo` for more. - - parameter progressBlock: Called when the image downloading progress gets updated. - - parameter completionHandler: Called when the image retrieved and set. - - returns: A task represents the retrieving process. - - - note: Both the `progressBlock` and `completionHandler` will be invoked in main thread. - The `CallbackDispatchQueue` specified in `optionsInfo` will not be used in callbacks of this method. - */ - @available(*, deprecated, message: "Extensions directly on image views are deprecated. Use `imageView.kf.setImage` instead.", renamed: "kf.setImage") - @discardableResult - public func kf_setImage(with resource: Resource?, - placeholder: Image? = nil, - options: KingfisherOptionsInfo? = nil, - progressBlock: DownloadProgressBlock? = nil, - completionHandler: CompletionHandler? = nil) -> RetrieveImageTask - { - return kf.setImage(with: resource, placeholder: placeholder, options: options, progressBlock: progressBlock, completionHandler: completionHandler) - } - - /** - Cancel the image download task bounded to the image view if it is running. - Nothing will happen if the downloading has already finished. - */ - @available(*, deprecated, message: "Extensions directly on image views are deprecated. Use `imageView.kf.cancelDownloadTask` instead.", renamed: "kf.cancelDownloadTask") - public func kf_cancelDownloadTask() { kf.cancelDownloadTask() } - - /// Get the image URL binded to this image view. - @available(*, deprecated, message: "Extensions directly on image views are deprecated. Use `imageView.kf.webURL` instead.", renamed: "kf.webURL") - public var kf_webURL: URL? { return kf.webURL } - - /// Holds which indicator type is going to be used. - /// Default is .none, means no indicator will be shown. - @available(*, deprecated, message: "Extensions directly on image views are deprecated. Use `imageView.kf.indicatorType` instead.", renamed: "kf.indicatorType") - public var kf_indicatorType: IndicatorType { - get { return kf.indicatorType } - set { kf.indicatorType = newValue } - } - - @available(*, deprecated, message: "Extensions directly on image views are deprecated. Use `imageView.kf.indicator` instead.", renamed: "kf.indicator") - /// Holds any type that conforms to the protocol `Indicator`. - /// The protocol `Indicator` has a `view` property that will be shown when loading an image. - /// It will be `nil` if `kf_indicatorType` is `.none`. - public private(set) var kf_indicator: Indicator? { - get { return kf.indicator } - set { kf.indicator = newValue } + public fileprivate(set) var placeholder: Placeholder? { + get { + return (objc_getAssociatedObject(base, &placeholderKey) as? Box)?.value + } + + set { + if let previousPlaceholder = placeholder { + previousPlaceholder.remove(from: base) + } + + if let newPlaceholder = newValue { + newPlaceholder.add(to: base) + } else { + base.image = nil + } + + objc_setAssociatedObject(base, &placeholderKey, Box(value: newValue), .OBJC_ASSOCIATION_RETAIN_NONATOMIC) + } } - - @available(*, deprecated, message: "Extensions directly on image views are deprecated.", renamed: "kf.imageTask") - fileprivate var kf_imageTask: RetrieveImageTask? { return kf.imageTask } - @available(*, deprecated, message: "Extensions directly on image views are deprecated.", renamed: "kf.setImageTask") - fileprivate func kf_setImageTask(_ task: RetrieveImageTask?) { kf.setImageTask(task) } - @available(*, deprecated, message: "Extensions directly on image views are deprecated.", renamed: "kf.setWebURL") - fileprivate func kf_setWebURL(_ url: URL) { kf.setWebURL(url) } } -extension ImageView { - func shouldPreloadAllGIF() -> Bool { return true } + +@objc extension ImageView { + func shouldPreloadAllAnimation() -> Bool { return true } } diff --git a/WRNavigationBar_swift/Pods/Kingfisher/Sources/Indicator.swift b/WRNavigationBar_swift/Pods/Kingfisher/Sources/Indicator.swift index d1f55f0..5ec5f97 100644 --- a/WRNavigationBar_swift/Pods/Kingfisher/Sources/Indicator.swift +++ b/WRNavigationBar_swift/Pods/Kingfisher/Sources/Indicator.swift @@ -86,41 +86,49 @@ extension Indicator { // MARK: - ActivityIndicator // Displays a NSProgressIndicator / UIActivityIndicatorView -struct ActivityIndicator: Indicator { +class ActivityIndicator: Indicator { #if os(macOS) private let activityIndicatorView: NSProgressIndicator #else private let activityIndicatorView: UIActivityIndicatorView #endif + private var animatingCount = 0 var view: IndicatorView { return activityIndicatorView } func startAnimatingView() { - #if os(macOS) - activityIndicatorView.startAnimation(nil) - #else - activityIndicatorView.startAnimating() - #endif - activityIndicatorView.isHidden = false + animatingCount += 1 + // Alrady animating + if animatingCount == 1 { + #if os(macOS) + activityIndicatorView.startAnimation(nil) + #else + activityIndicatorView.startAnimating() + #endif + activityIndicatorView.isHidden = false + } } func stopAnimatingView() { - #if os(macOS) - activityIndicatorView.stopAnimation(nil) - #else - activityIndicatorView.stopAnimating() - #endif - activityIndicatorView.isHidden = true + animatingCount = max(animatingCount - 1, 0) + if animatingCount == 0 { + #if os(macOS) + activityIndicatorView.stopAnimation(nil) + #else + activityIndicatorView.stopAnimating() + #endif + activityIndicatorView.isHidden = true + } } init() { #if os(macOS) activityIndicatorView = NSProgressIndicator(frame: CGRect(x: 0, y: 0, width: 16, height: 16)) activityIndicatorView.controlSize = .small - activityIndicatorView.style = .spinningStyle + activityIndicatorView.style = .spinning #else #if os(tvOS) let indicatorStyle = UIActivityIndicatorViewStyle.white @@ -135,7 +143,7 @@ struct ActivityIndicator: Indicator { // MARK: - ImageIndicator // Displays an ImageView. Supports gif -struct ImageIndicator: Indicator { +class ImageIndicator: Indicator { private let animatedImageIndicatorView: ImageView var view: IndicatorView { @@ -145,9 +153,9 @@ struct ImageIndicator: Indicator { init?(imageData data: Data, processor: ImageProcessor = DefaultImageProcessor.default, options: KingfisherOptionsInfo = KingfisherEmptyOptionsInfo) { var options = options - // Use normal image view to show gif, so we need to preload all gif data. - if !options.preloadAllGIFData { - options.append(.preloadAllGIFData) + // Use normal image view to show animations, so we need to preload all animation data. + if !options.preloadAllAnimationData { + options.append(.preloadAllAnimationData) } guard let image = processor.process(item: .data(data), options: options) else { @@ -156,6 +164,7 @@ struct ImageIndicator: Indicator { animatedImageIndicatorView = ImageView() animatedImageIndicatorView.image = image + animatedImageIndicatorView.frame = CGRect(x: 0, y: 0, width: image.size.width, height: image.size.height) #if os(macOS) // Need for gif to animate on macOS @@ -163,7 +172,6 @@ struct ImageIndicator: Indicator { self.animatedImageIndicatorView.canDrawSubviewsIntoLayer = true #else animatedImageIndicatorView.contentMode = .center - animatedImageIndicatorView.autoresizingMask = [.flexibleLeftMargin, .flexibleRightMargin, .flexibleBottomMargin, diff --git a/WRNavigationBar_swift/Pods/Kingfisher/Sources/Kingfisher.swift b/WRNavigationBar_swift/Pods/Kingfisher/Sources/Kingfisher.swift index 6e2d409..c97818e 100644 --- a/WRNavigationBar_swift/Pods/Kingfisher/Sources/Kingfisher.swift +++ b/WRNavigationBar_swift/Pods/Kingfisher/Sources/Kingfisher.swift @@ -30,16 +30,18 @@ import ImageIO #if os(macOS) import AppKit public typealias Image = NSImage + public typealias View = NSView public typealias Color = NSColor public typealias ImageView = NSImageView - typealias Button = NSButton + public typealias Button = NSButton #else import UIKit public typealias Image = UIImage public typealias Color = UIColor #if !os(watchOS) public typealias ImageView = UIImageView - typealias Button = UIButton + public typealias View = UIView + public typealias Button = UIButton #endif #endif diff --git a/WRNavigationBar_swift/Pods/Kingfisher/Sources/KingfisherManager.swift b/WRNavigationBar_swift/Pods/Kingfisher/Sources/KingfisherManager.swift index eb29f3d..85503f5 100755 --- a/WRNavigationBar_swift/Pods/Kingfisher/Sources/KingfisherManager.swift +++ b/WRNavigationBar_swift/Pods/Kingfisher/Sources/KingfisherManager.swift @@ -43,11 +43,6 @@ public class RetrieveImageTask { // the download task should not begin. var cancelledBeforeDownloadStarting: Bool = false - /// The disk retrieve task in this image task. Kingfisher will try to look up in cache first. This task represent the cache search task. - @available(*, deprecated, - message: "diskRetrieveTask is not in use anymore. You cannot cancel a disk retrieve task anymore once it started.") - public var diskRetrieveTask: RetrieveImageDiskTask? - /// The network retrieve task in this image task. public var downloadTask: RetrieveImageDownloadTask? @@ -79,6 +74,19 @@ public class KingfisherManager { /// Downloader used by this manager public var downloader: ImageDownloader + /// Default options used by the manager. This option will be used in + /// Kingfisher manager related methods, including all image view and + /// button extension methods. You can also passing the options per image by + /// sending an `options` parameter to Kingfisher's APIs, the per image option + /// will overwrite the default ones if exist. + /// + /// - Note: This option will not be applied to independent using of `ImageDownloader` or `ImageCache`. + public var defaultOptions = KingfisherEmptyOptionsInfo + + var currentDefaultOptions: KingfisherOptionsInfo { + return [.downloader(downloader), .targetCache(cache)] + defaultOptions + } + convenience init() { self.init(downloader: .default, cache: .default) } @@ -108,8 +116,8 @@ public class KingfisherManager { completionHandler: CompletionHandler?) -> RetrieveImageTask { let task = RetrieveImageTask() - - if let options = options, options.forceRefresh { + let options = currentDefaultOptions + (options ?? KingfisherEmptyOptionsInfo) + if options.forceRefresh { _ = downloadAndCacheImage( with: resource.downloadURL, forKey: resource.cacheKey, @@ -136,9 +144,8 @@ public class KingfisherManager { retrieveImageTask: RetrieveImageTask, progressBlock: DownloadProgressBlock?, completionHandler: CompletionHandler?, - options: KingfisherOptionsInfo?) -> RetrieveImageDownloadTask? + options: KingfisherOptionsInfo) -> RetrieveImageDownloadTask? { - let options = options ?? KingfisherEmptyOptionsInfo let downloader = options.downloader return downloader.downloadImage(with: url, retrieveImageTask: retrieveImageTask, options: options, progressBlock: { receivedSize, totalSize in @@ -164,6 +171,19 @@ public class KingfisherManager { cacheSerializer: options.cacheSerializer, toDisk: !options.cacheMemoryOnly, completionHandler: nil) + if options.cacheOriginalImage && options.processor != DefaultImageProcessor.default { + let originalCache = options.originalCache + let defaultProcessor = DefaultImageProcessor.default + if let originalImage = defaultProcessor.process(item: .data(originalData), options: options) { + originalCache.store(originalImage, + original: originalData, + forKey: key, + processorIdentifier: defaultProcessor.identifier, + cacheSerializer: options.cacheSerializer, + toDisk: !options.cacheMemoryOnly, + completionHandler: nil) + } + } } completionHandler?(image, error, .none, url) @@ -176,30 +196,71 @@ public class KingfisherManager { retrieveImageTask: RetrieveImageTask, progressBlock: DownloadProgressBlock?, completionHandler: CompletionHandler?, - options: KingfisherOptionsInfo?) + options: KingfisherOptionsInfo) { + + let diskTaskCompletionHandler: CompletionHandler = { (image, error, cacheType, imageURL) -> () in completionHandler?(image, error, cacheType, imageURL) } - let targetCache = options?.targetCache ?? cache - targetCache.retrieveImage(forKey: key, options: options, - completionHandler: { image, cacheType in - if image != nil { - diskTaskCompletionHandler(image, nil, cacheType, url) - } else if let options = options, options.onlyFromCache { - let error = NSError(domain: KingfisherErrorDomain, code: KingfisherError.notCached.rawValue, userInfo: nil) - diskTaskCompletionHandler(nil, error, .none, url) - } else { - self.downloadAndCacheImage( - with: url, - forKey: key, - retrieveImageTask: retrieveImageTask, - progressBlock: progressBlock, - completionHandler: diskTaskCompletionHandler, - options: options) + func handleNoCache() { + if options.onlyFromCache { + let error = NSError(domain: KingfisherErrorDomain, code: KingfisherError.notCached.rawValue, userInfo: nil) + diskTaskCompletionHandler(nil, error, .none, url) + return + } + self.downloadAndCacheImage( + with: url, + forKey: key, + retrieveImageTask: retrieveImageTask, + progressBlock: progressBlock, + completionHandler: diskTaskCompletionHandler, + options: options) + + } + + let targetCache = options.targetCache + // First, try to get the exactly image from cache + targetCache.retrieveImage(forKey: key, options: options) { image, cacheType in + // If found, we could finish now. + if image != nil { + diskTaskCompletionHandler(image, nil, cacheType, url) + return + } + + // If not found, and we are using a default processor, download it! + let processor = options.processor + guard processor != DefaultImageProcessor.default else { + handleNoCache() + return + } + + // If processor is not the default one, we have a chance to check whether + // the original image is already in cache. + let originalCache = options.originalCache + let optionsWithoutProcessor = options.removeAllMatchesIgnoringAssociatedValue(.processor(processor)) + originalCache.retrieveImage(forKey: key, options: optionsWithoutProcessor) { image, cacheType in + // If we found the original image, there is no need to download it again. + // We could just apply processor to it now. + guard let image = image else { + handleNoCache() + return } + + guard let processedImage = processor.process(item: .image(image), options: options) else { + diskTaskCompletionHandler(nil, nil, .none, url) + return + } + targetCache.store(processedImage, + original: nil, + forKey: key, + processorIdentifier:options.processor.identifier, + cacheSerializer: options.cacheSerializer, + toDisk: !options.cacheMemoryOnly, + completionHandler: nil) + diskTaskCompletionHandler(processedImage, nil, .none, url) } - ) + } } } diff --git a/WRNavigationBar_swift/Pods/Kingfisher/Sources/KingfisherOptionsInfo.swift b/WRNavigationBar_swift/Pods/Kingfisher/Sources/KingfisherOptionsInfo.swift index 948906e..1d275dc 100755 --- a/WRNavigationBar_swift/Pods/Kingfisher/Sources/KingfisherOptionsInfo.swift +++ b/WRNavigationBar_swift/Pods/Kingfisher/Sources/KingfisherOptionsInfo.swift @@ -46,6 +46,11 @@ public enum KingfisherOptionsInfoItem { /// the downloaded image to it. case targetCache(ImageCache) + /// Cache for storing and retrieving original image. + /// Preferred prior to targetCache for storing and retrieving original images if specified. + /// Only used if a non-default image processor is involved. + case originalCache(ImageCache) + /// The associated value of this member should be an ImageDownloader object. Kingfisher will use this /// downloader to download the images. case downloader(ImageDownloader) @@ -62,6 +67,11 @@ public enum KingfisherOptionsInfoItem { /// If set, `Kingfisher` will ignore the cache and try to fire a download task for the resource. case forceRefresh + + /// If set, `Kingfisher` will try to retrieve the image from memory cache first. If the image is not in memory + /// cache, then it will ignore the disk cache but download the image again from network. This is useful when + /// you want to display a changeable image behind the same url, while avoiding download it again and again. + case fromMemoryCacheOrRefresh /// If set, setting the image to an image view will happen with transition even when retrieved from cache. /// See `Transition` option for more. @@ -84,13 +94,13 @@ public enum KingfisherOptionsInfoItem { /// It is the image scale, instead of your screen scale. You may need to specify the correct scale when you dealing /// with 2x or 3x retina images. case scaleFactor(CGFloat) - - /// Whether all the GIF data should be preloaded. Default it false, which means following frames will be - /// loaded on need. If true, all the GIF data will be loaded and decoded into memory. This option is mainly + + /// Whether all the animated image data should be preloaded. Default it false, which means following frames will be + /// loaded on need. If true, all the animated image data will be loaded and decoded into memory. This option is mainly /// used for back compatibility internally. You should not set it directly. `AnimatedImageView` will not preload /// all data, while a normal image view (`UIImageView` or `NSImageView`) will load all data. Choose to use /// corresponding image view type instead of setting this option. - case preloadAllGIFData + case preloadAllAnimationData /// The `ImageDownloadRequestModifier` contained will be used to change the request before it being sent. /// This is the last chance you can modify the request. You can modify the request for some customizing purpose, @@ -114,11 +124,17 @@ public enum KingfisherOptionsInfoItem { /// will be ignored and the current image will be kept while loading or downloading the new image. case keepCurrentImageWhileLoading - /// If set, Kingfisher will only load the first frame from a GIF file as a single image. - /// Loading a lot of GIFs may take too much memory. It will be useful when you want to display a - /// static preview of the first frame from a GIF image. - /// This option will be ignored if the target image is not GIF. + /// If set, Kingfisher will only load the first frame from a animated image data file as a single image. + /// Loading a lot of animated images may take too much memory. It will be useful when you want to display a + /// static preview of the first frame from a animated image. + /// This option will be ignored if the target image is not animated image data. case onlyLoadFirstFrame + + /// If set and an `ImageProcessor` is used, Kingfisher will try to cache both + /// the final result and original image. Kingfisher will have a chance to use + /// the original image when another processor is applied to the same resouce, + /// instead of downloading it again. + case cacheOriginalImage } precedencegroup ItemComparisonPrecedence { @@ -132,40 +148,44 @@ infix operator <== : ItemComparisonPrecedence func <== (lhs: KingfisherOptionsInfoItem, rhs: KingfisherOptionsInfoItem) -> Bool { switch (lhs, rhs) { case (.targetCache(_), .targetCache(_)): return true + case (.originalCache(_), .originalCache(_)): return true case (.downloader(_), .downloader(_)): return true case (.transition(_), .transition(_)): return true case (.downloadPriority(_), .downloadPriority(_)): return true case (.forceRefresh, .forceRefresh): return true + case (.fromMemoryCacheOrRefresh, .fromMemoryCacheOrRefresh): return true case (.forceTransition, .forceTransition): return true case (.cacheMemoryOnly, .cacheMemoryOnly): return true case (.onlyFromCache, .onlyFromCache): return true case (.backgroundDecode, .backgroundDecode): return true case (.callbackDispatchQueue(_), .callbackDispatchQueue(_)): return true case (.scaleFactor(_), .scaleFactor(_)): return true - case (.preloadAllGIFData, .preloadAllGIFData): return true + case (.preloadAllAnimationData, .preloadAllAnimationData): return true case (.requestModifier(_), .requestModifier(_)): return true case (.processor(_), .processor(_)): return true case (.cacheSerializer(_), .cacheSerializer(_)): return true case (.keepCurrentImageWhileLoading, .keepCurrentImageWhileLoading): return true case (.onlyLoadFirstFrame, .onlyLoadFirstFrame): return true + case (.cacheOriginalImage, .cacheOriginalImage): return true default: return false } } + extension Collection where Iterator.Element == KingfisherOptionsInfoItem { - func firstMatchIgnoringAssociatedValue(_ target: Iterator.Element) -> Iterator.Element? { - return index { $0 <== target }.flatMap { self[$0] } + func lastMatchIgnoringAssociatedValue(_ target: Iterator.Element) -> Iterator.Element? { + return reversed().first { $0 <== target } } func removeAllMatchesIgnoringAssociatedValue(_ target: Iterator.Element) -> [Iterator.Element] { - return self.filter { !($0 <== target) } + return filter { !($0 <== target) } } } public extension Collection where Iterator.Element == KingfisherOptionsInfoItem { /// The target `ImageCache` which is used. public var targetCache: ImageCache { - if let item = firstMatchIgnoringAssociatedValue(.targetCache(.default)), + if let item = lastMatchIgnoringAssociatedValue(.targetCache(.default)), case .targetCache(let cache) = item { return cache @@ -173,9 +193,19 @@ public extension Collection where Iterator.Element == KingfisherOptionsInfoItem return ImageCache.default } + /// The original `ImageCache` which is used. + public var originalCache: ImageCache { + if let item = lastMatchIgnoringAssociatedValue(.originalCache(.default)), + case .originalCache(let cache) = item + { + return cache + } + return targetCache + } + /// The `ImageDownloader` which is specified. public var downloader: ImageDownloader { - if let item = firstMatchIgnoringAssociatedValue(.downloader(.default)), + if let item = lastMatchIgnoringAssociatedValue(.downloader(.default)), case .downloader(let downloader) = item { return downloader @@ -185,7 +215,7 @@ public extension Collection where Iterator.Element == KingfisherOptionsInfoItem /// Member for animation transition when using UIImageView. public var transition: ImageTransition { - if let item = firstMatchIgnoringAssociatedValue(.transition(.none)), + if let item = lastMatchIgnoringAssociatedValue(.transition(.none)), case .transition(let transition) = item { return transition @@ -196,7 +226,7 @@ public extension Collection where Iterator.Element == KingfisherOptionsInfoItem /// A `Float` value set as the priority of image download task. The value for it should be /// between 0.0~1.0. public var downloadPriority: Float { - if let item = firstMatchIgnoringAssociatedValue(.downloadPriority(0)), + if let item = lastMatchIgnoringAssociatedValue(.downloadPriority(0)), case .downloadPriority(let priority) = item { return priority @@ -208,6 +238,11 @@ public extension Collection where Iterator.Element == KingfisherOptionsInfoItem public var forceRefresh: Bool { return contains{ $0 <== .forceRefresh } } + + /// Whether an image should be got only from memory cache or download. + public var fromMemoryCacheOrRefresh: Bool { + return contains{ $0 <== .fromMemoryCacheOrRefresh } + } /// Whether the transition should always happen or not. public var forceTransition: Bool { @@ -228,15 +263,15 @@ public extension Collection where Iterator.Element == KingfisherOptionsInfoItem public var backgroundDecode: Bool { return contains{ $0 <== .backgroundDecode } } - - /// Whether the image data should be all loaded at once if it is a GIF. - public var preloadAllGIFData: Bool { - return contains { $0 <== .preloadAllGIFData } + + /// Whether the image data should be all loaded at once if it is an animated image. + public var preloadAllAnimationData: Bool { + return contains { $0 <== .preloadAllAnimationData } } /// The queue of callbacks should happen from Kingfisher. public var callbackDispatchQueue: DispatchQueue { - if let item = firstMatchIgnoringAssociatedValue(.callbackDispatchQueue(nil)), + if let item = lastMatchIgnoringAssociatedValue(.callbackDispatchQueue(nil)), case .callbackDispatchQueue(let queue) = item { return queue ?? DispatchQueue.main @@ -246,7 +281,7 @@ public extension Collection where Iterator.Element == KingfisherOptionsInfoItem /// The scale factor which should be used for the image. public var scaleFactor: CGFloat { - if let item = firstMatchIgnoringAssociatedValue(.scaleFactor(0)), + if let item = lastMatchIgnoringAssociatedValue(.scaleFactor(0)), case .scaleFactor(let scale) = item { return scale @@ -256,7 +291,7 @@ public extension Collection where Iterator.Element == KingfisherOptionsInfoItem /// The `ImageDownloadRequestModifier` will be used before sending a download request. public var modifier: ImageDownloadRequestModifier { - if let item = firstMatchIgnoringAssociatedValue(.requestModifier(NoModifier.default)), + if let item = lastMatchIgnoringAssociatedValue(.requestModifier(NoModifier.default)), case .requestModifier(let modifier) = item { return modifier @@ -266,7 +301,7 @@ public extension Collection where Iterator.Element == KingfisherOptionsInfoItem /// `ImageProcessor` for processing when the downloading finishes. public var processor: ImageProcessor { - if let item = firstMatchIgnoringAssociatedValue(.processor(DefaultImageProcessor.default)), + if let item = lastMatchIgnoringAssociatedValue(.processor(DefaultImageProcessor.default)), case .processor(let processor) = item { return processor @@ -276,7 +311,7 @@ public extension Collection where Iterator.Element == KingfisherOptionsInfoItem /// `CacheSerializer` to convert image to data for storing in cache. public var cacheSerializer: CacheSerializer { - if let item = firstMatchIgnoringAssociatedValue(.cacheSerializer(DefaultCacheSerializer.default)), + if let item = lastMatchIgnoringAssociatedValue(.cacheSerializer(DefaultCacheSerializer.default)), case .cacheSerializer(let cacheSerializer) = item { return cacheSerializer @@ -293,4 +328,8 @@ public extension Collection where Iterator.Element == KingfisherOptionsInfoItem public var onlyLoadFirstFrame: Bool { return contains { $0 <== .onlyLoadFirstFrame } } + + public var cacheOriginalImage: Bool { + return contains { $0 <== .cacheOriginalImage } + } } diff --git a/WRNavigationBar_swift/Pods/Kingfisher/Sources/Placeholder.swift b/WRNavigationBar_swift/Pods/Kingfisher/Sources/Placeholder.swift new file mode 100755 index 0000000..b6076b5 --- /dev/null +++ b/WRNavigationBar_swift/Pods/Kingfisher/Sources/Placeholder.swift @@ -0,0 +1,82 @@ +// +// Placeholder.swift +// Kingfisher +// +// Created by Tieme van Veen on 28/08/2017. +// +// Copyright (c) 2017 Wei Wang +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +#if os(macOS) + import AppKit +#else + import UIKit +#endif + + +/// Represent a placeholder type which could be set while loading as well as +/// loading finished without getting an image. +public protocol Placeholder { + + /// How the placeholder should be added to a given image view. + func add(to imageView: ImageView) + + /// How the placeholder should be removed from a given image view. + func remove(from imageView: ImageView) +} + +/// Default implementation of an image placeholder. The image will be set or +/// reset directly for `image` property of the image view. +extension Placeholder where Self: Image { + + /// How the placeholder should be added to a given image view. + public func add(to imageView: ImageView) { imageView.image = self } + + /// How the placeholder should be removed from a given image view. + public func remove(from imageView: ImageView) { imageView.image = nil } +} + +extension Image: Placeholder {} + +/// Default implementation of an arbitrary view as placeholder. The view will be +/// added as a subview when adding and be removed from its super view when removing. +/// +/// To use your customize View type as placeholder, simply let it conforming to +/// `Placeholder` by `extension MyView: Placeholder {}`. +extension Placeholder where Self: View { + + /// How the placeholder should be added to a given image view. + public func add(to imageView: ImageView) { + imageView.addSubview(self) + + self.translatesAutoresizingMaskIntoConstraints = false + NSLayoutConstraint.activate([ + NSLayoutConstraint(item: self, attribute: .centerX, relatedBy: .equal, toItem: imageView, attribute: .centerX, multiplier: 1, constant: 0), + NSLayoutConstraint(item: self, attribute: .centerY, relatedBy: .equal, toItem: imageView, attribute: .centerY, multiplier: 1, constant: 0), + NSLayoutConstraint(item: self, attribute: .height, relatedBy: .equal, toItem: imageView, attribute: .height, multiplier: 1, constant: 0), + NSLayoutConstraint(item: self, attribute: .width, relatedBy: .equal, toItem: imageView, attribute: .width, multiplier: 1, constant: 0) + ]) + } + + /// How the placeholder should be removed from a given image view. + public func remove(from imageView: ImageView) { + self.removeFromSuperview() + } +} diff --git a/WRNavigationBar_swift/Pods/Kingfisher/Sources/UIButton+Kingfisher.swift b/WRNavigationBar_swift/Pods/Kingfisher/Sources/UIButton+Kingfisher.swift index 97d3aab..c9a5e0e 100755 --- a/WRNavigationBar_swift/Pods/Kingfisher/Sources/UIButton+Kingfisher.swift +++ b/WRNavigationBar_swift/Pods/Kingfisher/Sources/UIButton+Kingfisher.swift @@ -46,6 +46,9 @@ extension Kingfisher where Base: UIButton { - note: Both the `progressBlock` and `completionHandler` will be invoked in main thread. The `CallbackDispatchQueue` specified in `optionsInfo` will not be used in callbacks of this method. + + If `resource` is `nil`, the `placeholder` image will be set and + `completionHandler` will be called with both `error` and `image` being `nil`. */ @discardableResult public func setImage(with resource: Resource?, @@ -62,7 +65,7 @@ extension Kingfisher where Base: UIButton { return .empty } - let options = options ?? KingfisherEmptyOptionsInfo + let options = KingfisherManager.shared.defaultOptions + (options ?? KingfisherEmptyOptionsInfo) if !options.keepCurrentImageWhileLoading { base.setImage(placeholder, for: state) } @@ -82,10 +85,10 @@ extension Kingfisher where Base: UIButton { completionHandler: {[weak base] image, error, cacheType, imageURL in DispatchQueue.main.safeAsync { guard let strongBase = base, imageURL == self.webURL(for: state) else { + completionHandler?(image, error, cacheType, imageURL) return } self.setImageTask(nil) - if image != nil { strongBase.setImage(image, for: state) } @@ -121,6 +124,9 @@ extension Kingfisher where Base: UIButton { - note: Both the `progressBlock` and `completionHandler` will be invoked in main thread. The `CallbackDispatchQueue` specified in `optionsInfo` will not be used in callbacks of this method. + + If `resource` is `nil`, the `placeholder` image will be set and + `completionHandler` will be called with both `error` and `image` being `nil`. */ @discardableResult public func setBackgroundImage(with resource: Resource?, @@ -137,7 +143,7 @@ extension Kingfisher where Base: UIButton { return .empty } - let options = options ?? KingfisherEmptyOptionsInfo + let options = KingfisherManager.shared.defaultOptions + (options ?? KingfisherEmptyOptionsInfo) if !options.keepCurrentImageWhileLoading { base.setBackgroundImage(placeholder, for: state) } @@ -157,6 +163,7 @@ extension Kingfisher where Base: UIButton { completionHandler: { [weak base] image, error, cacheType, imageURL in DispatchQueue.main.safeAsync { guard let strongBase = base, imageURL == self.backgroundWebURL(for: state) else { + completionHandler?(image, error, cacheType, imageURL) return } self.setBackgroundImageTask(nil) @@ -265,151 +272,3 @@ extension Kingfisher where Base: UIButton { objc_setAssociatedObject(base, &backgroundImageTaskKey, task, .OBJC_ASSOCIATION_RETAIN_NONATOMIC) } } - -// MARK: - Deprecated. Only for back compatibility. -/** -* Set image to use from web for a specified state. Deprecated. Use `kf` namespacing instead. -*/ -extension UIButton { - /** - Set an image to use for a specified state with a resource, a placeholder image, options, progress handler and - completion handler. - - - parameter resource: Resource object contains information such as `cacheKey` and `downloadURL`. - - parameter state: The state that uses the specified image. - - parameter placeholder: A placeholder image when retrieving the image at URL. - - parameter options: A dictionary could control some behaviors. See `KingfisherOptionsInfo` for more. - - parameter progressBlock: Called when the image downloading progress gets updated. - - parameter completionHandler: Called when the image retrieved and set. - - - returns: A task represents the retrieving process. - - - note: Both the `progressBlock` and `completionHandler` will be invoked in main thread. - The `CallbackDispatchQueue` specified in `optionsInfo` will not be used in callbacks of this method. - */ - @discardableResult - @available(*, deprecated, - message: "Extensions directly on UIButton are deprecated. Use `button.kf.setImage` instead.", - renamed: "kf.setImage") - public func kf_setImage(with resource: Resource?, - for state: UIControlState, - placeholder: UIImage? = nil, - options: KingfisherOptionsInfo? = nil, - progressBlock: DownloadProgressBlock? = nil, - completionHandler: CompletionHandler? = nil) -> RetrieveImageTask - { - return kf.setImage(with: resource, for: state, placeholder: placeholder, options: options, - progressBlock: progressBlock, completionHandler: completionHandler) - } - - /** - Cancel the image download task bounded to the image view if it is running. - Nothing will happen if the downloading has already finished. - */ - @available(*, deprecated, - message: "Extensions directly on UIButton are deprecated. Use `button.kf.cancelImageDownloadTask` instead.", - renamed: "kf.cancelImageDownloadTask") - public func kf_cancelImageDownloadTask() { kf.cancelImageDownloadTask() } - - /** - Set the background image to use for a specified state with a resource, - a placeholder image, options progress handler and completion handler. - - - parameter resource: Resource object contains information such as `cacheKey` and `downloadURL`. - - parameter state: The state that uses the specified image. - - parameter placeholder: A placeholder image when retrieving the image at URL. - - parameter options: A dictionary could control some behaviors. See `KingfisherOptionsInfo` for more. - - parameter progressBlock: Called when the image downloading progress gets updated. - - parameter completionHandler: Called when the image retrieved and set. - - - returns: A task represents the retrieving process. - - - note: Both the `progressBlock` and `completionHandler` will be invoked in main thread. - The `CallbackDispatchQueue` specified in `optionsInfo` will not be used in callbacks of this method. - */ - @discardableResult - @available(*, deprecated, - message: "Extensions directly on UIButton are deprecated. Use `button.kf.setBackgroundImage` instead.", - renamed: "kf.setBackgroundImage") - public func kf_setBackgroundImage(with resource: Resource?, - for state: UIControlState, - placeholder: UIImage? = nil, - options: KingfisherOptionsInfo? = nil, - progressBlock: DownloadProgressBlock? = nil, - completionHandler: CompletionHandler? = nil) -> RetrieveImageTask - { - return kf.setBackgroundImage(with: resource, for: state, placeholder: placeholder, options: options, - progressBlock: progressBlock, completionHandler: completionHandler) - } - - /** - Cancel the background image download task bounded to the image view if it is running. - Nothing will happen if the downloading has already finished. - */ - @available(*, deprecated, - message: "Extensions directly on UIButton are deprecated. Use `button.kf.cancelBackgroundImageDownloadTask` instead.", - renamed: "kf.cancelBackgroundImageDownloadTask") - public func kf_cancelBackgroundImageDownloadTask() { kf.cancelBackgroundImageDownloadTask() } - - /** - Get the image URL binded to this button for a specified state. - - - parameter state: The state that uses the specified image. - - - returns: Current URL for image. - */ - @available(*, deprecated, - message: "Extensions directly on UIButton are deprecated. Use `button.kf.webURL` instead.", - renamed: "kf.webURL") - public func kf_webURL(for state: UIControlState) -> URL? { return kf.webURL(for: state) } - - @available(*, deprecated, message: "Extensions directly on UIButton are deprecated.",renamed: "kf.setWebURL") - fileprivate func kf_setWebURL(_ url: URL, for state: UIControlState) { kf.setWebURL(url, for: state) } - - @available(*, deprecated, message: "Extensions directly on UIButton are deprecated.",renamed: "kf.webURLs") - fileprivate var kf_webURLs: NSMutableDictionary { return kf.webURLs } - - @available(*, deprecated, message: "Extensions directly on UIButton are deprecated.",renamed: "kf.setWebURLs") - fileprivate func kf_setWebURLs(_ URLs: NSMutableDictionary) { kf.setWebURLs(URLs) } - - @available(*, deprecated, message: "Extensions directly on UIButton are deprecated.",renamed: "kf.imageTask") - fileprivate var kf_imageTask: RetrieveImageTask? { return kf.imageTask } - - @available(*, deprecated, message: "Extensions directly on UIButton are deprecated.",renamed: "kf.setImageTask") - fileprivate func kf_setImageTask(_ task: RetrieveImageTask?) { kf.setImageTask(task) } - - /** - Get the background image URL binded to this button for a specified state. - - - parameter state: The state that uses the specified background image. - - - returns: Current URL for background image. - */ - @available(*, deprecated, - message: "Extensions directly on UIButton are deprecated. Use `button.kf.backgroundWebURL` instead.", - renamed: "kf.backgroundWebURL") - public func kf_backgroundWebURL(for state: UIControlState) -> URL? { return kf.backgroundWebURL(for: state) } - - @available(*, deprecated, - message: "Extensions directly on UIButton are deprecated.",renamed: "kf.setBackgroundWebURL") - fileprivate func kf_setBackgroundWebURL(_ url: URL, for state: UIControlState) { - kf.setBackgroundWebURL(url, for: state) - } - - @available(*, deprecated, - message: "Extensions directly on UIButton are deprecated.",renamed: "kf.backgroundWebURLs") - fileprivate var kf_backgroundWebURLs: NSMutableDictionary { return kf.backgroundWebURLs } - - @available(*, deprecated, - message: "Extensions directly on UIButton are deprecated.",renamed: "kf.setBackgroundWebURLs") - fileprivate func kf_setBackgroundWebURLs(_ URLs: NSMutableDictionary) { kf.setBackgroundWebURLs(URLs) } - - @available(*, deprecated, - message: "Extensions directly on UIButton are deprecated.",renamed: "kf.backgroundImageTask") - fileprivate var kf_backgroundImageTask: RetrieveImageTask? { return kf.backgroundImageTask } - - @available(*, deprecated, - message: "Extensions directly on UIButton are deprecated.",renamed: "kf.setBackgroundImageTask") - fileprivate func kf_setBackgroundImageTask(_ task: RetrieveImageTask?) { return kf.setBackgroundImageTask(task) } - -} diff --git a/WRNavigationBar_swift/Pods/Manifest.lock b/WRNavigationBar_swift/Pods/Manifest.lock index a57cf55..c6c2166 100644 --- a/WRNavigationBar_swift/Pods/Manifest.lock +++ b/WRNavigationBar_swift/Pods/Manifest.lock @@ -1,12 +1,12 @@ PODS: - - Kingfisher (3.6.2) + - Kingfisher (4.3.1) DEPENDENCIES: - Kingfisher SPEC CHECKSUMS: - Kingfisher: 2c94e72c6830622c71d06adf4ea024c37d316830 + Kingfisher: 75541c4b62f02e1fde6f9772303de3d9ebe8f5b3 PODFILE CHECKSUM: eedd5593b4e862f4a6b0ebf6fd6f3f022a9f6b1d -COCOAPODS: 1.2.1 +COCOAPODS: 1.3.1 diff --git a/WRNavigationBar_swift/Pods/Pods.xcodeproj/project.pbxproj b/WRNavigationBar_swift/Pods/Pods.xcodeproj/project.pbxproj index adb3bc2..dcc6904 100644 --- a/WRNavigationBar_swift/Pods/Pods.xcodeproj/project.pbxproj +++ b/WRNavigationBar_swift/Pods/Pods.xcodeproj/project.pbxproj @@ -7,34 +7,36 @@ objects = { /* Begin PBXBuildFile section */ - 0E9CC28AC8E34FE8E1C87E933E04BC7A /* ImageProcessor.swift in Sources */ = {isa = PBXBuildFile; fileRef = 449745419F19FD32556B5DB4C4713E19 /* ImageProcessor.swift */; }; - 179523942E7D1E3EB210EF05E2C7AE79 /* Kingfisher.h in Headers */ = {isa = PBXBuildFile; fileRef = 814A249890448FEA6045B315BCF3CBDD /* Kingfisher.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 2D41430007CE8464586F521838A882C2 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 72913984B3E4B2AD01F71E405D688036 /* Foundation.framework */; }; - 2E5E570FFC49EF98550401421A243C0F /* CacheSerializer.swift in Sources */ = {isa = PBXBuildFile; fileRef = CDB06CA9125048730F6F8EDD92103BD0 /* CacheSerializer.swift */; }; - 33395912F2FFA355C4C36B7EDEAA3DA7 /* ImageView+Kingfisher.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0EACA73146F2EFD5728BDDE27435FBD5 /* ImageView+Kingfisher.swift */; }; - 33A14E817C0FA585D5DA3A55E453299D /* Image.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9EC672E8EA725C5D07B841DD0564BE8A /* Image.swift */; }; - 3414E1D9CB15149A296E16C45967B021 /* ImagePrefetcher.swift in Sources */ = {isa = PBXBuildFile; fileRef = A095EF160FF9234364CDD94B8926E24A /* ImagePrefetcher.swift */; }; - 342AE33215135AD56B73580012DC22AB /* AnimatedImageView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 40F4491E340CD8AFA20CA333A7248C0A /* AnimatedImageView.swift */; }; - 378B44CAA91C2106076668FDE72E1E02 /* KingfisherOptionsInfo.swift in Sources */ = {isa = PBXBuildFile; fileRef = E7F836E9F331D1DFAA871B794EC40647 /* KingfisherOptionsInfo.swift */; }; - 4089E39F76F86466B8DDD39A1C1ABB6B /* Filter.swift in Sources */ = {isa = PBXBuildFile; fileRef = A59DB5A84662EBAFEC776E1D05FC2A56 /* Filter.swift */; }; - 52A280AB4852FDE92DF09B5E79D5C2AA /* Indicator.swift in Sources */ = {isa = PBXBuildFile; fileRef = DE39F8F9D08B99E2AC56305CB28004D2 /* Indicator.swift */; }; + 07432E8DEA8B25795C7C545AA67A0187 /* ImageTransition.swift in Sources */ = {isa = PBXBuildFile; fileRef = 88C862B0902EAF74B609F90285CFB7C6 /* ImageTransition.swift */; }; + 0CA6357476373C221D44C498AA1D65FE /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 72913984B3E4B2AD01F71E405D688036 /* Foundation.framework */; }; + 10AD5E70FDD53228153032C58FBF4D52 /* String+MD5.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8D9580FED9E6FCE2C7845BC03E63D50A /* String+MD5.swift */; }; + 1827E7D94F3A12CA0C58EF33AE4B026D /* KingfisherOptionsInfo.swift in Sources */ = {isa = PBXBuildFile; fileRef = ECB8A9E00B1031B5EEF4FADC65A407A6 /* KingfisherOptionsInfo.swift */; }; + 1DAF3BB88351664576507F774FEB051C /* Filter.swift in Sources */ = {isa = PBXBuildFile; fileRef = EADB697E25B5800CAEFBC6A13A1DCBA9 /* Filter.swift */; }; + 1FCC0970C8435F10768CA84C2025A177 /* Resource.swift in Sources */ = {isa = PBXBuildFile; fileRef = 835802EEFCA95C3BECB444475FEB53AD /* Resource.swift */; }; + 2082EB4AA16440FFD5479FAFC0181066 /* Indicator.swift in Sources */ = {isa = PBXBuildFile; fileRef = A1791E48E319018D19A4085F3A0308EC /* Indicator.swift */; }; + 282E6F0E67F3799B0ABCB9ED96B666A9 /* RequestModifier.swift in Sources */ = {isa = PBXBuildFile; fileRef = 835C82F8B413C5FC71B973BC63C7530C /* RequestModifier.swift */; }; + 2F288ED3641B2B4775884C462AE377E6 /* Kingfisher-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = F1DA91233A58A2FDA9DBACE4D8B923A8 /* Kingfisher-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 383C9A8DB84B83233633C3A00A2C1608 /* KingfisherManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 023C24331AF069FFB31BE4575FF92A66 /* KingfisherManager.swift */; }; + 40765AAA791D6DFC0022639E348F0E6A /* FormatIndicatedCacheSerializer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8DC875D6BCDEC1D273EDD95695790E7B /* FormatIndicatedCacheSerializer.swift */; }; + 413C2A3759ABEC870AAE61F28C258C31 /* ImageDownloader.swift in Sources */ = {isa = PBXBuildFile; fileRef = CA951D80476B7B25AF48029C77615E15 /* ImageDownloader.swift */; }; + 48EC78A50C61424D4DFDC33A325CAA72 /* ThreadHelper.swift in Sources */ = {isa = PBXBuildFile; fileRef = A4C9AE39E7B57A63ADA77C5411A94EBA /* ThreadHelper.swift */; }; + 52416A6AC7387ECACCC45596498D96AD /* CFNetwork.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F46EFC5CDAF57A92A7B136FFD3525675 /* CFNetwork.framework */; }; + 5B5D8AE167BD8E304CE474A9B8DBA2B4 /* Kingfisher.h in Headers */ = {isa = PBXBuildFile; fileRef = C82DCFCD04A890F33F6873466BB8F21E /* Kingfisher.h */; settings = {ATTRIBUTES = (Public, ); }; }; 5D03025A98024CDF4F5DC9AC69A6D838 /* Pods-WRNavigationBar_swift-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = 7CECED3FD3EA864979CAFC7D2E34BD93 /* Pods-WRNavigationBar_swift-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 6A375593407BC7937234B2B6A0811760 /* Kingfisher-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = 9856B231053FF41FC9B14ACCC6F9215C /* Kingfisher-dummy.m */; }; - 6CD63E1564618B6213B98E0ABBC3127C /* ThreadHelper.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5D06CAA9AFC94CB86E9CB96D78BD0923 /* ThreadHelper.swift */; }; - 6DA770087D354CDCD3889CDAE7C4C698 /* Box.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9DE6AD548C8531F1E89A4AC6B1C6B3A8 /* Box.swift */; }; - 7636F846675C9F4ED96E00C6C19A4890 /* KingfisherManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = FBB1ACC8AAF2B55915F99167EE149FA6 /* KingfisherManager.swift */; }; - 86B7DA678C8705523C300947117C0706 /* ImageTransition.swift in Sources */ = {isa = PBXBuildFile; fileRef = AA1EE6FB137B9949B921A201014D9660 /* ImageTransition.swift */; }; - 8DA7E6883118CB3C8132B64D3D43AE0B /* Resource.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0CCAABA051F2B62FEC94F6629032960D /* Resource.swift */; }; - 9F826F893E86EB86591B637A1CE4B13A /* String+MD5.swift in Sources */ = {isa = PBXBuildFile; fileRef = AFD3C40826560CCA979FBF1A30879C5D /* String+MD5.swift */; }; - A8F35D1EBAEF99D38F02A0B8CA5D8FBE /* Kingfisher-umbrella.h in Headers */ = {isa = PBXBuildFile; fileRef = A24D7C6D5AC7A569D95092B9FA066ABA /* Kingfisher-umbrella.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 5D83206A9A4656F11D511158EC8E0784 /* CacheSerializer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2DFCC4FC32F83B831601673C6818F019 /* CacheSerializer.swift */; }; + 873BA68C2E24D634D38E4A8BCB74B08D /* Kingfisher.swift in Sources */ = {isa = PBXBuildFile; fileRef = 81AE08F84342F7AB3680E0E6F7574A5A /* Kingfisher.swift */; }; + 8D7D42C25F9430F572E14200C399D57B /* ImageCache.swift in Sources */ = {isa = PBXBuildFile; fileRef = C98A82CA32E1D54EA4FB0140C87A0D5F /* ImageCache.swift */; }; + 93D444FC9D79520E14FB8EF178F0B76E /* ImageProcessor.swift in Sources */ = {isa = PBXBuildFile; fileRef = A5B32513990923B73428F091F7DE8A5B /* ImageProcessor.swift */; }; + 950D8E334E011B13CC5786595E6AE615 /* Image.swift in Sources */ = {isa = PBXBuildFile; fileRef = A9B28D20BE64B86A107267022F1E7064 /* Image.swift */; }; + A7EC09EC6EFAB3778E0A0341E7DC9CE3 /* AnimatedImageView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9295207D7CEECE2F5BDCD8CD84920ABE /* AnimatedImageView.swift */; }; + B0033530A0EAABBB31CD46CA2899F3BD /* Box.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9F0AEF804C3FF811567DCF8CBD32A1D5 /* Box.swift */; }; C1C52534BAF0801C90F6B3DDF3A59896 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 72913984B3E4B2AD01F71E405D688036 /* Foundation.framework */; }; - C9CC5ED97D29C6C3DE22B78A9AA2AD91 /* Kingfisher.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6211E96F580D34F3E3F84D65BD80EC24 /* Kingfisher.swift */; }; + CB4222BC34D92C2E06A5BCF730FEFE71 /* Kingfisher-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = E62FDCDEE52FFBAACE80CC15C761D7C6 /* Kingfisher-dummy.m */; }; + CB8DF027448816C623E9B02A3685A59F /* ImageView+Kingfisher.swift in Sources */ = {isa = PBXBuildFile; fileRef = DF8738D6ED045E7C089A8AE94F21A0A0 /* ImageView+Kingfisher.swift */; }; D5B9985DA680B07E486A07969DA20D79 /* Pods-WRNavigationBar_swift-dummy.m in Sources */ = {isa = PBXBuildFile; fileRef = F8219BF94193F7436659F916DA2353FE /* Pods-WRNavigationBar_swift-dummy.m */; }; - DC6080C64C269628C3F5107BE87055E2 /* ImageDownloader.swift in Sources */ = {isa = PBXBuildFile; fileRef = 94DE4AC69094EC3015FFF1BF0AD4AFE7 /* ImageDownloader.swift */; }; - EA816A580C3858934ED6FE92040C26DD /* RequestModifier.swift in Sources */ = {isa = PBXBuildFile; fileRef = 799CA99214B1F57CE947563E43D6E995 /* RequestModifier.swift */; }; - EE89512E8D36E67CDC525DB9D5BBF5A7 /* UIButton+Kingfisher.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9E4022814E31F041CA8E6FFA328C8639 /* UIButton+Kingfisher.swift */; }; - F5C8C3F45F42FBDE5D87000C71178D20 /* CFNetwork.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F46EFC5CDAF57A92A7B136FFD3525675 /* CFNetwork.framework */; }; - F8E957950566622A3E4B61AACE8F0B4A /* ImageCache.swift in Sources */ = {isa = PBXBuildFile; fileRef = F0C72AFC42CED429C7A71F7A7704D20C /* ImageCache.swift */; }; + E710FF1F4EB4B125F9C5DBDFE3B9320F /* Placeholder.swift in Sources */ = {isa = PBXBuildFile; fileRef = 685A4E99CB4F94AC0F404F519C7AC866 /* Placeholder.swift */; }; + F99792883819ADBD16123F91F6A9F3F8 /* ImagePrefetcher.swift in Sources */ = {isa = PBXBuildFile; fileRef = 308FC14D7DDFBB406C2E4ED7415C8D7B /* ImagePrefetcher.swift */; }; + FAC3C67720C7E6EF51CCAE58F62645BC /* UIButton+Kingfisher.swift in Sources */ = {isa = PBXBuildFile; fileRef = C1AF856B3D835339E6E446917C5312B6 /* UIButton+Kingfisher.swift */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ @@ -42,54 +44,56 @@ isa = PBXContainerItemProxy; containerPortal = D41D8CD98F00B204E9800998ECF8427E /* Project object */; proxyType = 1; - remoteGlobalIDString = C4944FEC314D1A66588651D006273ADE; + remoteGlobalIDString = 6F712943B3C5592E82604940D11CE08A; remoteInfo = Kingfisher; }; /* End PBXContainerItemProxy section */ /* Begin PBXFileReference section */ + 023C24331AF069FFB31BE4575FF92A66 /* KingfisherManager.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = KingfisherManager.swift; path = Sources/KingfisherManager.swift; sourceTree = ""; }; 077D151C882C36797498299FA868DD45 /* Pods-WRNavigationBar_swift.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = "Pods-WRNavigationBar_swift.release.xcconfig"; sourceTree = ""; }; - 0CCAABA051F2B62FEC94F6629032960D /* Resource.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Resource.swift; path = Sources/Resource.swift; sourceTree = ""; }; - 0EACA73146F2EFD5728BDDE27435FBD5 /* ImageView+Kingfisher.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = "ImageView+Kingfisher.swift"; path = "Sources/ImageView+Kingfisher.swift"; sourceTree = ""; }; + 0F7DF0BCFC0710953CC5FF9972BE0B04 /* Kingfisher-prefix.pch */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "Kingfisher-prefix.pch"; sourceTree = ""; }; + 2DFCC4FC32F83B831601673C6818F019 /* CacheSerializer.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = CacheSerializer.swift; path = Sources/CacheSerializer.swift; sourceTree = ""; }; 2E03BC01661E426D39F6C97D69CBD5DA /* Pods-WRNavigationBar_swift-resources.sh */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.script.sh; path = "Pods-WRNavigationBar_swift-resources.sh"; sourceTree = ""; }; + 308FC14D7DDFBB406C2E4ED7415C8D7B /* ImagePrefetcher.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = ImagePrefetcher.swift; path = Sources/ImagePrefetcher.swift; sourceTree = ""; }; 3CE01395EF504C101EFDBC103EC6E461 /* Pods-WRNavigationBar_swift.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; path = "Pods-WRNavigationBar_swift.modulemap"; sourceTree = ""; }; - 40F4491E340CD8AFA20CA333A7248C0A /* AnimatedImageView.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = AnimatedImageView.swift; path = Sources/AnimatedImageView.swift; sourceTree = ""; }; - 449745419F19FD32556B5DB4C4713E19 /* ImageProcessor.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = ImageProcessor.swift; path = Sources/ImageProcessor.swift; sourceTree = ""; }; - 5207B9BA1FAC60A316B91128301138B6 /* Kingfisher.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; path = Kingfisher.modulemap; sourceTree = ""; }; + 52DC30D7E6C1223D54467216A97B0B7D /* Kingfisher.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = Kingfisher.xcconfig; sourceTree = ""; }; 5B49DEB9DF25D6EA7B6693213B7B90B3 /* Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; - 5D06CAA9AFC94CB86E9CB96D78BD0923 /* ThreadHelper.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = ThreadHelper.swift; path = Sources/ThreadHelper.swift; sourceTree = ""; }; - 6211E96F580D34F3E3F84D65BD80EC24 /* Kingfisher.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Kingfisher.swift; path = Sources/Kingfisher.swift; sourceTree = ""; }; 638E15C347D7A409389BE9A0476CC59F /* Kingfisher.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; name = Kingfisher.framework; path = Kingfisher.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 685A4E99CB4F94AC0F404F519C7AC866 /* Placeholder.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Placeholder.swift; path = Sources/Placeholder.swift; sourceTree = ""; }; 72913984B3E4B2AD01F71E405D688036 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS10.3.sdk/System/Library/Frameworks/Foundation.framework; sourceTree = DEVELOPER_DIR; }; 75E959B193E767DED64E98D2D01CDA5F /* Pods_WRNavigationBar_swift.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; name = Pods_WRNavigationBar_swift.framework; path = "Pods-WRNavigationBar_swift.framework"; sourceTree = BUILT_PRODUCTS_DIR; }; - 799CA99214B1F57CE947563E43D6E995 /* RequestModifier.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = RequestModifier.swift; path = Sources/RequestModifier.swift; sourceTree = ""; }; 7CECED3FD3EA864979CAFC7D2E34BD93 /* Pods-WRNavigationBar_swift-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "Pods-WRNavigationBar_swift-umbrella.h"; sourceTree = ""; }; - 814A249890448FEA6045B315BCF3CBDD /* Kingfisher.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = Kingfisher.h; path = Sources/Kingfisher.h; sourceTree = ""; }; + 7FA6100B5CDA0A51737954E7E2D1DE2D /* Kingfisher.modulemap */ = {isa = PBXFileReference; includeInIndex = 1; path = Kingfisher.modulemap; sourceTree = ""; }; + 81AE08F84342F7AB3680E0E6F7574A5A /* Kingfisher.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Kingfisher.swift; path = Sources/Kingfisher.swift; sourceTree = ""; }; + 835802EEFCA95C3BECB444475FEB53AD /* Resource.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Resource.swift; path = Sources/Resource.swift; sourceTree = ""; }; + 835C82F8B413C5FC71B973BC63C7530C /* RequestModifier.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = RequestModifier.swift; path = Sources/RequestModifier.swift; sourceTree = ""; }; + 854A8362EFD3CAC49FA4502B9F0FCB96 /* Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 88C862B0902EAF74B609F90285CFB7C6 /* ImageTransition.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = ImageTransition.swift; path = Sources/ImageTransition.swift; sourceTree = ""; }; + 8D9580FED9E6FCE2C7845BC03E63D50A /* String+MD5.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = "String+MD5.swift"; path = "Sources/String+MD5.swift"; sourceTree = ""; }; + 8DC875D6BCDEC1D273EDD95695790E7B /* FormatIndicatedCacheSerializer.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = FormatIndicatedCacheSerializer.swift; path = Sources/FormatIndicatedCacheSerializer.swift; sourceTree = ""; }; + 9295207D7CEECE2F5BDCD8CD84920ABE /* AnimatedImageView.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = AnimatedImageView.swift; path = Sources/AnimatedImageView.swift; sourceTree = ""; }; 93A4A3777CF96A4AAC1D13BA6DCCEA73 /* Podfile */ = {isa = PBXFileReference; explicitFileType = text.script.ruby; includeInIndex = 1; lastKnownFileType = text; name = Podfile; path = ../Podfile; sourceTree = SOURCE_ROOT; xcLanguageSpecificationIdentifier = xcode.lang.ruby; }; - 94DE4AC69094EC3015FFF1BF0AD4AFE7 /* ImageDownloader.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = ImageDownloader.swift; path = Sources/ImageDownloader.swift; sourceTree = ""; }; - 968C4EE1CB49CA730B177A530E6BC12F /* Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; - 9856B231053FF41FC9B14ACCC6F9215C /* Kingfisher-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "Kingfisher-dummy.m"; sourceTree = ""; }; - 9DE6AD548C8531F1E89A4AC6B1C6B3A8 /* Box.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Box.swift; path = Sources/Box.swift; sourceTree = ""; }; - 9E4022814E31F041CA8E6FFA328C8639 /* UIButton+Kingfisher.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = "UIButton+Kingfisher.swift"; path = "Sources/UIButton+Kingfisher.swift"; sourceTree = ""; }; - 9EC672E8EA725C5D07B841DD0564BE8A /* Image.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Image.swift; path = Sources/Image.swift; sourceTree = ""; }; - A095EF160FF9234364CDD94B8926E24A /* ImagePrefetcher.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = ImagePrefetcher.swift; path = Sources/ImagePrefetcher.swift; sourceTree = ""; }; - A24D7C6D5AC7A569D95092B9FA066ABA /* Kingfisher-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "Kingfisher-umbrella.h"; sourceTree = ""; }; - A59DB5A84662EBAFEC776E1D05FC2A56 /* Filter.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Filter.swift; path = Sources/Filter.swift; sourceTree = ""; }; - AA1EE6FB137B9949B921A201014D9660 /* ImageTransition.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = ImageTransition.swift; path = Sources/ImageTransition.swift; sourceTree = ""; }; + 9F0AEF804C3FF811567DCF8CBD32A1D5 /* Box.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Box.swift; path = Sources/Box.swift; sourceTree = ""; }; + A1791E48E319018D19A4085F3A0308EC /* Indicator.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Indicator.swift; path = Sources/Indicator.swift; sourceTree = ""; }; + A4C9AE39E7B57A63ADA77C5411A94EBA /* ThreadHelper.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = ThreadHelper.swift; path = Sources/ThreadHelper.swift; sourceTree = ""; }; + A5B32513990923B73428F091F7DE8A5B /* ImageProcessor.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = ImageProcessor.swift; path = Sources/ImageProcessor.swift; sourceTree = ""; }; + A9B28D20BE64B86A107267022F1E7064 /* Image.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Image.swift; path = Sources/Image.swift; sourceTree = ""; }; AE66F7EA3A06D631F5729F90A9F79406 /* Pods-WRNavigationBar_swift.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = "Pods-WRNavigationBar_swift.debug.xcconfig"; sourceTree = ""; }; - AFD3C40826560CCA979FBF1A30879C5D /* String+MD5.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = "String+MD5.swift"; path = "Sources/String+MD5.swift"; sourceTree = ""; }; BA4CB1BACA72306DD38BD93DB7EDC37F /* Pods-WRNavigationBar_swift-acknowledgements.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; path = "Pods-WRNavigationBar_swift-acknowledgements.plist"; sourceTree = ""; }; - BC79E2E5D62D71F36463838727DAA58D /* Kingfisher.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; path = Kingfisher.xcconfig; sourceTree = ""; }; - CDB06CA9125048730F6F8EDD92103BD0 /* CacheSerializer.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = CacheSerializer.swift; path = Sources/CacheSerializer.swift; sourceTree = ""; }; - D7A3C90E9DF742791B93F3793008064F /* Kingfisher-prefix.pch */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "Kingfisher-prefix.pch"; sourceTree = ""; }; - DE39F8F9D08B99E2AC56305CB28004D2 /* Indicator.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Indicator.swift; path = Sources/Indicator.swift; sourceTree = ""; }; - E7F836E9F331D1DFAA871B794EC40647 /* KingfisherOptionsInfo.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = KingfisherOptionsInfo.swift; path = Sources/KingfisherOptionsInfo.swift; sourceTree = ""; }; - F0C72AFC42CED429C7A71F7A7704D20C /* ImageCache.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = ImageCache.swift; path = Sources/ImageCache.swift; sourceTree = ""; }; + C1AF856B3D835339E6E446917C5312B6 /* UIButton+Kingfisher.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = "UIButton+Kingfisher.swift"; path = "Sources/UIButton+Kingfisher.swift"; sourceTree = ""; }; + C82DCFCD04A890F33F6873466BB8F21E /* Kingfisher.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; name = Kingfisher.h; path = Sources/Kingfisher.h; sourceTree = ""; }; + C98A82CA32E1D54EA4FB0140C87A0D5F /* ImageCache.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = ImageCache.swift; path = Sources/ImageCache.swift; sourceTree = ""; }; + CA951D80476B7B25AF48029C77615E15 /* ImageDownloader.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = ImageDownloader.swift; path = Sources/ImageDownloader.swift; sourceTree = ""; }; + DF8738D6ED045E7C089A8AE94F21A0A0 /* ImageView+Kingfisher.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = "ImageView+Kingfisher.swift"; path = "Sources/ImageView+Kingfisher.swift"; sourceTree = ""; }; + E62FDCDEE52FFBAACE80CC15C761D7C6 /* Kingfisher-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "Kingfisher-dummy.m"; sourceTree = ""; }; + EADB697E25B5800CAEFBC6A13A1DCBA9 /* Filter.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = Filter.swift; path = Sources/Filter.swift; sourceTree = ""; }; + ECB8A9E00B1031B5EEF4FADC65A407A6 /* KingfisherOptionsInfo.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = KingfisherOptionsInfo.swift; path = Sources/KingfisherOptionsInfo.swift; sourceTree = ""; }; F108F08B8C9ACDA3F91D31E82E22633F /* Pods-WRNavigationBar_swift-acknowledgements.markdown */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text; path = "Pods-WRNavigationBar_swift-acknowledgements.markdown"; sourceTree = ""; }; + F1DA91233A58A2FDA9DBACE4D8B923A8 /* Kingfisher-umbrella.h */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.h; path = "Kingfisher-umbrella.h"; sourceTree = ""; }; F3572B8CC9A94DF04AEAD640C7F3B46F /* Pods-WRNavigationBar_swift-frameworks.sh */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.script.sh; path = "Pods-WRNavigationBar_swift-frameworks.sh"; sourceTree = ""; }; F46EFC5CDAF57A92A7B136FFD3525675 /* CFNetwork.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CFNetwork.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS10.3.sdk/System/Library/Frameworks/CFNetwork.framework; sourceTree = DEVELOPER_DIR; }; F8219BF94193F7436659F916DA2353FE /* Pods-WRNavigationBar_swift-dummy.m */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.c.objc; path = "Pods-WRNavigationBar_swift-dummy.m"; sourceTree = ""; }; - FBB1ACC8AAF2B55915F99167EE149FA6 /* KingfisherManager.swift */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = sourcecode.swift; name = KingfisherManager.swift; path = Sources/KingfisherManager.swift; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -101,18 +105,32 @@ ); runOnlyForDeploymentPostprocessing = 0; }; - ED03E5917B811BACFE75189AE0C2A469 /* Frameworks */ = { + C0B9722E352CF90C920286E6F029D3C0 /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( - F5C8C3F45F42FBDE5D87000C71178D20 /* CFNetwork.framework in Frameworks */, - 2D41430007CE8464586F521838A882C2 /* Foundation.framework in Frameworks */, + 52416A6AC7387ECACCC45596498D96AD /* CFNetwork.framework in Frameworks */, + 0CA6357476373C221D44C498AA1D65FE /* Foundation.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ + 0DEE2A01FA885B4899312B6F6826FDBF /* Support Files */ = { + isa = PBXGroup; + children = ( + 854A8362EFD3CAC49FA4502B9F0FCB96 /* Info.plist */, + 7FA6100B5CDA0A51737954E7E2D1DE2D /* Kingfisher.modulemap */, + 52DC30D7E6C1223D54467216A97B0B7D /* Kingfisher.xcconfig */, + E62FDCDEE52FFBAACE80CC15C761D7C6 /* Kingfisher-dummy.m */, + 0F7DF0BCFC0710953CC5FF9972BE0B04 /* Kingfisher-prefix.pch */, + F1DA91233A58A2FDA9DBACE4D8B923A8 /* Kingfisher-umbrella.h */, + ); + name = "Support Files"; + path = "../Target Support Files/Kingfisher"; + sourceTree = ""; + }; 1BF2B0C737CAAE286BA4320319120121 /* Targets Support Files */ = { isa = PBXGroup; children = ( @@ -148,6 +166,38 @@ name = Products; sourceTree = ""; }; + 3B1085458B794CEAF49F0B0EE79A1FBD /* Kingfisher */ = { + isa = PBXGroup; + children = ( + 9295207D7CEECE2F5BDCD8CD84920ABE /* AnimatedImageView.swift */, + 9F0AEF804C3FF811567DCF8CBD32A1D5 /* Box.swift */, + 2DFCC4FC32F83B831601673C6818F019 /* CacheSerializer.swift */, + EADB697E25B5800CAEFBC6A13A1DCBA9 /* Filter.swift */, + 8DC875D6BCDEC1D273EDD95695790E7B /* FormatIndicatedCacheSerializer.swift */, + A9B28D20BE64B86A107267022F1E7064 /* Image.swift */, + C98A82CA32E1D54EA4FB0140C87A0D5F /* ImageCache.swift */, + CA951D80476B7B25AF48029C77615E15 /* ImageDownloader.swift */, + 308FC14D7DDFBB406C2E4ED7415C8D7B /* ImagePrefetcher.swift */, + A5B32513990923B73428F091F7DE8A5B /* ImageProcessor.swift */, + 88C862B0902EAF74B609F90285CFB7C6 /* ImageTransition.swift */, + DF8738D6ED045E7C089A8AE94F21A0A0 /* ImageView+Kingfisher.swift */, + A1791E48E319018D19A4085F3A0308EC /* Indicator.swift */, + C82DCFCD04A890F33F6873466BB8F21E /* Kingfisher.h */, + 81AE08F84342F7AB3680E0E6F7574A5A /* Kingfisher.swift */, + 023C24331AF069FFB31BE4575FF92A66 /* KingfisherManager.swift */, + ECB8A9E00B1031B5EEF4FADC65A407A6 /* KingfisherOptionsInfo.swift */, + 685A4E99CB4F94AC0F404F519C7AC866 /* Placeholder.swift */, + 835C82F8B413C5FC71B973BC63C7530C /* RequestModifier.swift */, + 835802EEFCA95C3BECB444475FEB53AD /* Resource.swift */, + 8D9580FED9E6FCE2C7845BC03E63D50A /* String+MD5.swift */, + A4C9AE39E7B57A63ADA77C5411A94EBA /* ThreadHelper.swift */, + C1AF856B3D835339E6E446917C5312B6 /* UIButton+Kingfisher.swift */, + 0DEE2A01FA885B4899312B6F6826FDBF /* Support Files */, + ); + name = Kingfisher; + path = Kingfisher; + sourceTree = ""; + }; 3DC75C8869B42AB93D04871325A0707E /* iOS */ = { isa = PBXGroup; children = ( @@ -165,67 +215,23 @@ name = Frameworks; sourceTree = ""; }; - 6D6A3E96995405C682083EAC9705D118 /* Pods */ = { - isa = PBXGroup; - children = ( - BC43CE0E4B9A087C6F738A912A8078EB /* Kingfisher */, - ); - name = Pods; - sourceTree = ""; - }; 7DB346D0F39D3F0E887471402A8071AB = { isa = PBXGroup; children = ( 93A4A3777CF96A4AAC1D13BA6DCCEA73 /* Podfile */, 433CD3331B6C3787F473C941B61FC68F /* Frameworks */, - 6D6A3E96995405C682083EAC9705D118 /* Pods */, + 9469D748404B6E4D4F3E90E0B84F53A3 /* Pods */, 33668159F3B925188A23B48976230B79 /* Products */, 1BF2B0C737CAAE286BA4320319120121 /* Targets Support Files */, ); sourceTree = ""; }; - BC43CE0E4B9A087C6F738A912A8078EB /* Kingfisher */ = { + 9469D748404B6E4D4F3E90E0B84F53A3 /* Pods */ = { isa = PBXGroup; children = ( - 40F4491E340CD8AFA20CA333A7248C0A /* AnimatedImageView.swift */, - 9DE6AD548C8531F1E89A4AC6B1C6B3A8 /* Box.swift */, - CDB06CA9125048730F6F8EDD92103BD0 /* CacheSerializer.swift */, - A59DB5A84662EBAFEC776E1D05FC2A56 /* Filter.swift */, - 9EC672E8EA725C5D07B841DD0564BE8A /* Image.swift */, - F0C72AFC42CED429C7A71F7A7704D20C /* ImageCache.swift */, - 94DE4AC69094EC3015FFF1BF0AD4AFE7 /* ImageDownloader.swift */, - A095EF160FF9234364CDD94B8926E24A /* ImagePrefetcher.swift */, - 449745419F19FD32556B5DB4C4713E19 /* ImageProcessor.swift */, - AA1EE6FB137B9949B921A201014D9660 /* ImageTransition.swift */, - 0EACA73146F2EFD5728BDDE27435FBD5 /* ImageView+Kingfisher.swift */, - DE39F8F9D08B99E2AC56305CB28004D2 /* Indicator.swift */, - 814A249890448FEA6045B315BCF3CBDD /* Kingfisher.h */, - 6211E96F580D34F3E3F84D65BD80EC24 /* Kingfisher.swift */, - FBB1ACC8AAF2B55915F99167EE149FA6 /* KingfisherManager.swift */, - E7F836E9F331D1DFAA871B794EC40647 /* KingfisherOptionsInfo.swift */, - 799CA99214B1F57CE947563E43D6E995 /* RequestModifier.swift */, - 0CCAABA051F2B62FEC94F6629032960D /* Resource.swift */, - AFD3C40826560CCA979FBF1A30879C5D /* String+MD5.swift */, - 5D06CAA9AFC94CB86E9CB96D78BD0923 /* ThreadHelper.swift */, - 9E4022814E31F041CA8E6FFA328C8639 /* UIButton+Kingfisher.swift */, - DF56DAAF6901EA25B7722FFAC391B276 /* Support Files */, + 3B1085458B794CEAF49F0B0EE79A1FBD /* Kingfisher */, ); - name = Kingfisher; - path = Kingfisher; - sourceTree = ""; - }; - DF56DAAF6901EA25B7722FFAC391B276 /* Support Files */ = { - isa = PBXGroup; - children = ( - 968C4EE1CB49CA730B177A530E6BC12F /* Info.plist */, - 5207B9BA1FAC60A316B91128301138B6 /* Kingfisher.modulemap */, - BC79E2E5D62D71F36463838727DAA58D /* Kingfisher.xcconfig */, - 9856B231053FF41FC9B14ACCC6F9215C /* Kingfisher-dummy.m */, - D7A3C90E9DF742791B93F3793008064F /* Kingfisher-prefix.pch */, - A24D7C6D5AC7A569D95092B9FA066ABA /* Kingfisher-umbrella.h */, - ); - name = "Support Files"; - path = "../Target Support Files/Kingfisher"; + name = Pods; sourceTree = ""; }; /* End PBXGroup section */ @@ -239,51 +245,51 @@ ); runOnlyForDeploymentPostprocessing = 0; }; - 0F94B6BFE5A6242FBBB0BE3D27F7CEE9 /* Headers */ = { + 84676F7D46FF521291CDEB2AB04A454C /* Headers */ = { isa = PBXHeadersBuildPhase; buildActionMask = 2147483647; files = ( - A8F35D1EBAEF99D38F02A0B8CA5D8FBE /* Kingfisher-umbrella.h in Headers */, - 179523942E7D1E3EB210EF05E2C7AE79 /* Kingfisher.h in Headers */, + 2F288ED3641B2B4775884C462AE377E6 /* Kingfisher-umbrella.h in Headers */, + 5B5D8AE167BD8E304CE474A9B8DBA2B4 /* Kingfisher.h in Headers */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXHeadersBuildPhase section */ /* Begin PBXNativeTarget section */ - B4F69341F1BC6A4E6AA3F83A92D32FFB /* Pods-WRNavigationBar_swift */ = { + 6F712943B3C5592E82604940D11CE08A /* Kingfisher */ = { isa = PBXNativeTarget; - buildConfigurationList = 3BC883AEA3BFFB398C35E6F6E3F9689C /* Build configuration list for PBXNativeTarget "Pods-WRNavigationBar_swift" */; + buildConfigurationList = 8C1E4CEFB2390CBE75E70BAC20F44BBF /* Build configuration list for PBXNativeTarget "Kingfisher" */; buildPhases = ( - 19F926DB586A9A35FDF12C265BB83504 /* Sources */, - 1E9938AFCEAD1D190C671C902B3A903E /* Frameworks */, - 05C013F10E4A08DCD31F044A7072C25E /* Headers */, + FD12B015E1FDA3498428EF09C91D1F17 /* Sources */, + C0B9722E352CF90C920286E6F029D3C0 /* Frameworks */, + 84676F7D46FF521291CDEB2AB04A454C /* Headers */, ); buildRules = ( ); dependencies = ( - 570F164AD107B6339FFB8826978C5EF4 /* PBXTargetDependency */, ); - name = "Pods-WRNavigationBar_swift"; - productName = "Pods-WRNavigationBar_swift"; - productReference = 75E959B193E767DED64E98D2D01CDA5F /* Pods_WRNavigationBar_swift.framework */; + name = Kingfisher; + productName = Kingfisher; + productReference = 638E15C347D7A409389BE9A0476CC59F /* Kingfisher.framework */; productType = "com.apple.product-type.framework"; }; - C4944FEC314D1A66588651D006273ADE /* Kingfisher */ = { + B4F69341F1BC6A4E6AA3F83A92D32FFB /* Pods-WRNavigationBar_swift */ = { isa = PBXNativeTarget; - buildConfigurationList = 76E7EFBCEA1340954A03AA68051C2306 /* Build configuration list for PBXNativeTarget "Kingfisher" */; + buildConfigurationList = 3BC883AEA3BFFB398C35E6F6E3F9689C /* Build configuration list for PBXNativeTarget "Pods-WRNavigationBar_swift" */; buildPhases = ( - EAC7EA95310C5E1E724C632852F7D186 /* Sources */, - ED03E5917B811BACFE75189AE0C2A469 /* Frameworks */, - 0F94B6BFE5A6242FBBB0BE3D27F7CEE9 /* Headers */, + 19F926DB586A9A35FDF12C265BB83504 /* Sources */, + 1E9938AFCEAD1D190C671C902B3A903E /* Frameworks */, + 05C013F10E4A08DCD31F044A7072C25E /* Headers */, ); buildRules = ( ); dependencies = ( + 570F164AD107B6339FFB8826978C5EF4 /* PBXTargetDependency */, ); - name = Kingfisher; - productName = Kingfisher; - productReference = 638E15C347D7A409389BE9A0476CC59F /* Kingfisher.framework */; + name = "Pods-WRNavigationBar_swift"; + productName = "Pods-WRNavigationBar_swift"; + productReference = 75E959B193E767DED64E98D2D01CDA5F /* Pods_WRNavigationBar_swift.framework */; productType = "com.apple.product-type.framework"; }; /* End PBXNativeTarget section */ @@ -307,7 +313,7 @@ projectDirPath = ""; projectRoot = ""; targets = ( - C4944FEC314D1A66588651D006273ADE /* Kingfisher */, + 6F712943B3C5592E82604940D11CE08A /* Kingfisher */, B4F69341F1BC6A4E6AA3F83A92D32FFB /* Pods-WRNavigationBar_swift */, ); }; @@ -322,31 +328,33 @@ ); runOnlyForDeploymentPostprocessing = 0; }; - EAC7EA95310C5E1E724C632852F7D186 /* Sources */ = { + FD12B015E1FDA3498428EF09C91D1F17 /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - 342AE33215135AD56B73580012DC22AB /* AnimatedImageView.swift in Sources */, - 6DA770087D354CDCD3889CDAE7C4C698 /* Box.swift in Sources */, - 2E5E570FFC49EF98550401421A243C0F /* CacheSerializer.swift in Sources */, - 4089E39F76F86466B8DDD39A1C1ABB6B /* Filter.swift in Sources */, - 33A14E817C0FA585D5DA3A55E453299D /* Image.swift in Sources */, - F8E957950566622A3E4B61AACE8F0B4A /* ImageCache.swift in Sources */, - DC6080C64C269628C3F5107BE87055E2 /* ImageDownloader.swift in Sources */, - 3414E1D9CB15149A296E16C45967B021 /* ImagePrefetcher.swift in Sources */, - 0E9CC28AC8E34FE8E1C87E933E04BC7A /* ImageProcessor.swift in Sources */, - 86B7DA678C8705523C300947117C0706 /* ImageTransition.swift in Sources */, - 33395912F2FFA355C4C36B7EDEAA3DA7 /* ImageView+Kingfisher.swift in Sources */, - 52A280AB4852FDE92DF09B5E79D5C2AA /* Indicator.swift in Sources */, - 6A375593407BC7937234B2B6A0811760 /* Kingfisher-dummy.m in Sources */, - C9CC5ED97D29C6C3DE22B78A9AA2AD91 /* Kingfisher.swift in Sources */, - 7636F846675C9F4ED96E00C6C19A4890 /* KingfisherManager.swift in Sources */, - 378B44CAA91C2106076668FDE72E1E02 /* KingfisherOptionsInfo.swift in Sources */, - EA816A580C3858934ED6FE92040C26DD /* RequestModifier.swift in Sources */, - 8DA7E6883118CB3C8132B64D3D43AE0B /* Resource.swift in Sources */, - 9F826F893E86EB86591B637A1CE4B13A /* String+MD5.swift in Sources */, - 6CD63E1564618B6213B98E0ABBC3127C /* ThreadHelper.swift in Sources */, - EE89512E8D36E67CDC525DB9D5BBF5A7 /* UIButton+Kingfisher.swift in Sources */, + A7EC09EC6EFAB3778E0A0341E7DC9CE3 /* AnimatedImageView.swift in Sources */, + B0033530A0EAABBB31CD46CA2899F3BD /* Box.swift in Sources */, + 5D83206A9A4656F11D511158EC8E0784 /* CacheSerializer.swift in Sources */, + 1DAF3BB88351664576507F774FEB051C /* Filter.swift in Sources */, + 40765AAA791D6DFC0022639E348F0E6A /* FormatIndicatedCacheSerializer.swift in Sources */, + 950D8E334E011B13CC5786595E6AE615 /* Image.swift in Sources */, + 8D7D42C25F9430F572E14200C399D57B /* ImageCache.swift in Sources */, + 413C2A3759ABEC870AAE61F28C258C31 /* ImageDownloader.swift in Sources */, + F99792883819ADBD16123F91F6A9F3F8 /* ImagePrefetcher.swift in Sources */, + 93D444FC9D79520E14FB8EF178F0B76E /* ImageProcessor.swift in Sources */, + 07432E8DEA8B25795C7C545AA67A0187 /* ImageTransition.swift in Sources */, + CB8DF027448816C623E9B02A3685A59F /* ImageView+Kingfisher.swift in Sources */, + 2082EB4AA16440FFD5479FAFC0181066 /* Indicator.swift in Sources */, + CB4222BC34D92C2E06A5BCF730FEFE71 /* Kingfisher-dummy.m in Sources */, + 873BA68C2E24D634D38E4A8BCB74B08D /* Kingfisher.swift in Sources */, + 383C9A8DB84B83233633C3A00A2C1608 /* KingfisherManager.swift in Sources */, + 1827E7D94F3A12CA0C58EF33AE4B026D /* KingfisherOptionsInfo.swift in Sources */, + E710FF1F4EB4B125F9C5DBDFE3B9320F /* Placeholder.swift in Sources */, + 282E6F0E67F3799B0ABCB9ED96B666A9 /* RequestModifier.swift in Sources */, + 1FCC0970C8435F10768CA84C2025A177 /* Resource.swift in Sources */, + 10AD5E70FDD53228153032C58FBF4D52 /* String+MD5.swift in Sources */, + 48EC78A50C61424D4DFDC33A325CAA72 /* ThreadHelper.swift in Sources */, + FAC3C67720C7E6EF51CCAE58F62645BC /* UIButton+Kingfisher.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -356,126 +364,133 @@ 570F164AD107B6339FFB8826978C5EF4 /* PBXTargetDependency */ = { isa = PBXTargetDependency; name = Kingfisher; - target = C4944FEC314D1A66588651D006273ADE /* Kingfisher */; + target = 6F712943B3C5592E82604940D11CE08A /* Kingfisher */; targetProxy = 39ED95EEBDF3F99D9600C1827FE92AF7 /* PBXContainerItemProxy */; }; /* End PBXTargetDependency section */ /* Begin XCBuildConfiguration section */ - 20B5F4B4605A7E04AEE71183A359E092 /* Release */ = { + 576C583E88A92DC2279EB3BFC2CA8A6C /* Debug */ = { isa = XCBuildConfiguration; - baseConfigurationReference = BC79E2E5D62D71F36463838727DAA58D /* Kingfisher.xcconfig */; + baseConfigurationReference = 52DC30D7E6C1223D54467216A97B0B7D /* Kingfisher.xcconfig */; buildSettings = { CODE_SIGN_IDENTITY = ""; "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; CURRENT_PROJECT_VERSION = 1; - DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; DEFINES_MODULE = YES; DYLIB_COMPATIBILITY_VERSION = 1; DYLIB_CURRENT_VERSION = 1; DYLIB_INSTALL_NAME_BASE = "@rpath"; - ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_NO_COMMON_BLOCKS = YES; GCC_PREFIX_HEADER = "Target Support Files/Kingfisher/Kingfisher-prefix.pch"; INFOPLIST_FILE = "Target Support Files/Kingfisher/Info.plist"; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; IPHONEOS_DEPLOYMENT_TARGET = 8.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; MODULEMAP_FILE = "Target Support Files/Kingfisher/Kingfisher.modulemap"; - MTL_ENABLE_DEBUG_INFO = NO; PRODUCT_NAME = Kingfisher; SDKROOT = iphoneos; SKIP_INSTALL = YES; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) "; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_VERSION = 4.0; + TARGETED_DEVICE_FAMILY = "1,2"; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Debug; + }; + 961384A12D2CE6B1C90AD0CABD2F3B67 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 077D151C882C36797498299FA868DD45 /* Pods-WRNavigationBar_swift.release.xcconfig */; + buildSettings = { + CODE_SIGN_IDENTITY = ""; + "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + INFOPLIST_FILE = "Target Support Files/Pods-WRNavigationBar_swift/Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + MACH_O_TYPE = staticlib; + MODULEMAP_FILE = "Target Support Files/Pods-WRNavigationBar_swift/Pods-WRNavigationBar_swift.modulemap"; + OTHER_LDFLAGS = ""; + OTHER_LIBTOOLFLAGS = ""; + PODS_ROOT = "$(SRCROOT)"; + PRODUCT_BUNDLE_IDENTIFIER = "org.cocoapods.${PRODUCT_NAME:rfc1034identifier}"; + PRODUCT_NAME = Pods_WRNavigationBar_swift; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; - SWIFT_VERSION = 3.0; TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; VERSIONING_SYSTEM = "apple-generic"; VERSION_INFO_PREFIX = ""; }; name = Release; }; - 34FE9531DA9AF2820790339988D5FF41 /* Release */ = { + B254DAA6CF0CE39F4A3D11B90A7E059A /* Release */ = { isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; CLANG_ANALYZER_NONNULL = YES; - CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; 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; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 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; + 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_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; CODE_SIGNING_REQUIRED = NO; - COPY_PHASE_STRIP = YES; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; ENABLE_NS_ASSERTIONS = NO; - GCC_C_LANGUAGE_STANDARD = gnu99; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_NO_COMMON_BLOCKS = YES; GCC_PREPROCESSOR_DEFINITIONS = ( "POD_CONFIGURATION_RELEASE=1", "$(inherited)", ); GCC_WARN_64_TO_32_BIT_CONVERSION = YES; - GCC_WARN_ABOUT_RETURN_TYPE = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; GCC_WARN_UNDECLARED_SELECTOR = YES; - GCC_WARN_UNINITIALIZED_AUTOS = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; IPHONEOS_DEPLOYMENT_TARGET = 8.0; + MTL_ENABLE_DEBUG_INFO = NO; + PRODUCT_NAME = "$(TARGET_NAME)"; PROVISIONING_PROFILE_SPECIFIER = NO_SIGNING/; STRIP_INSTALLED_PRODUCT = NO; SYMROOT = "${SRCROOT}/../build"; - VALIDATE_PRODUCT = YES; }; name = Release; }; - A794525992F2457D34942D108D9E942A /* Debug */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = BC79E2E5D62D71F36463838727DAA58D /* Kingfisher.xcconfig */; - buildSettings = { - CODE_SIGN_IDENTITY = ""; - "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; - "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; - CURRENT_PROJECT_VERSION = 1; - DEBUG_INFORMATION_FORMAT = dwarf; - DEFINES_MODULE = YES; - DYLIB_COMPATIBILITY_VERSION = 1; - DYLIB_CURRENT_VERSION = 1; - DYLIB_INSTALL_NAME_BASE = "@rpath"; - ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_NO_COMMON_BLOCKS = YES; - GCC_PREFIX_HEADER = "Target Support Files/Kingfisher/Kingfisher-prefix.pch"; - INFOPLIST_FILE = "Target Support Files/Kingfisher/Info.plist"; - INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; - IPHONEOS_DEPLOYMENT_TARGET = 8.0; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; - MODULEMAP_FILE = "Target Support Files/Kingfisher/Kingfisher.modulemap"; - MTL_ENABLE_DEBUG_INFO = YES; - PRODUCT_NAME = Kingfisher; - SDKROOT = iphoneos; - SKIP_INSTALL = YES; - SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; - SWIFT_OPTIMIZATION_LEVEL = "-Onone"; - SWIFT_VERSION = 3.0; - TARGETED_DEVICE_FAMILY = "1,2"; - VERSIONING_SYSTEM = "apple-generic"; - VERSION_INFO_PREFIX = ""; - }; - name = Debug; - }; - B1AC7D6C94B5F6C383D0C0DF11F6AE13 /* Debug */ = { + B44E7915DC09BA8049ACD6E6966BF9CC /* Debug */ = { isa = XCBuildConfiguration; baseConfigurationReference = AE66F7EA3A06D631F5729F90A9F79406 /* Pods-WRNavigationBar_swift.debug.xcconfig */; buildSettings = { @@ -484,20 +499,16 @@ "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; CURRENT_PROJECT_VERSION = 1; - DEBUG_INFORMATION_FORMAT = dwarf; DEFINES_MODULE = YES; DYLIB_COMPATIBILITY_VERSION = 1; DYLIB_CURRENT_VERSION = 1; DYLIB_INSTALL_NAME_BASE = "@rpath"; - ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_NO_COMMON_BLOCKS = YES; INFOPLIST_FILE = "Target Support Files/Pods-WRNavigationBar_swift/Info.plist"; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; IPHONEOS_DEPLOYMENT_TARGET = 8.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; MACH_O_TYPE = staticlib; MODULEMAP_FILE = "Target Support Files/Pods-WRNavigationBar_swift/Pods-WRNavigationBar_swift.modulemap"; - MTL_ENABLE_DEBUG_INFO = YES; OTHER_LDFLAGS = ""; OTHER_LIBTOOLFLAGS = ""; PODS_ROOT = "$(SRCROOT)"; @@ -507,107 +518,112 @@ SKIP_INSTALL = YES; SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; - SWIFT_VERSION = 3.0; TARGETED_DEVICE_FAMILY = "1,2"; VERSIONING_SYSTEM = "apple-generic"; VERSION_INFO_PREFIX = ""; }; name = Debug; }; - B693A57C53A73E642AA38054EA7FA303 /* Release */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 077D151C882C36797498299FA868DD45 /* Pods-WRNavigationBar_swift.release.xcconfig */; - buildSettings = { - CODE_SIGN_IDENTITY = ""; - "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; - "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; - CURRENT_PROJECT_VERSION = 1; - DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; - DEFINES_MODULE = YES; - DYLIB_COMPATIBILITY_VERSION = 1; - DYLIB_CURRENT_VERSION = 1; - DYLIB_INSTALL_NAME_BASE = "@rpath"; - ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_NO_COMMON_BLOCKS = YES; - INFOPLIST_FILE = "Target Support Files/Pods-WRNavigationBar_swift/Info.plist"; - INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; - IPHONEOS_DEPLOYMENT_TARGET = 8.0; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; - MACH_O_TYPE = staticlib; - MODULEMAP_FILE = "Target Support Files/Pods-WRNavigationBar_swift/Pods-WRNavigationBar_swift.modulemap"; - MTL_ENABLE_DEBUG_INFO = NO; - OTHER_LDFLAGS = ""; - OTHER_LIBTOOLFLAGS = ""; - PODS_ROOT = "$(SRCROOT)"; - PRODUCT_BUNDLE_IDENTIFIER = "org.cocoapods.${PRODUCT_NAME:rfc1034identifier}"; - PRODUCT_NAME = Pods_WRNavigationBar_swift; - SDKROOT = iphoneos; - SKIP_INSTALL = YES; - SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; - SWIFT_VERSION = 3.0; - TARGETED_DEVICE_FAMILY = "1,2"; - VERSIONING_SYSTEM = "apple-generic"; - VERSION_INFO_PREFIX = ""; - }; - name = Release; - }; - C104F7F091290C3D1E248192F07FE689 /* Debug */ = { + E4B68EE12B21C47CB798D9B1ECA6D7A7 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; CLANG_ANALYZER_NONNULL = YES; - CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; 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; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 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; + 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_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; CODE_SIGNING_REQUIRED = NO; COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; ENABLE_TESTABILITY = YES; - GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_C_LANGUAGE_STANDARD = gnu11; GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; GCC_OPTIMIZATION_LEVEL = 0; GCC_PREPROCESSOR_DEFINITIONS = ( "POD_CONFIGURATION_DEBUG=1", "DEBUG=1", "$(inherited)", ); - GCC_SYMBOLS_PRIVATE_EXTERN = NO; GCC_WARN_64_TO_32_BIT_CONVERSION = YES; - GCC_WARN_ABOUT_RETURN_TYPE = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; GCC_WARN_UNDECLARED_SELECTOR = YES; - GCC_WARN_UNINITIALIZED_AUTOS = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; IPHONEOS_DEPLOYMENT_TARGET = 8.0; + MTL_ENABLE_DEBUG_INFO = YES; ONLY_ACTIVE_ARCH = YES; + PRODUCT_NAME = "$(TARGET_NAME)"; PROVISIONING_PROFILE_SPECIFIER = NO_SIGNING/; STRIP_INSTALLED_PRODUCT = NO; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; SYMROOT = "${SRCROOT}/../build"; }; name = Debug; }; + E8652F35BF322A3957D0F62338910B79 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 52DC30D7E6C1223D54467216A97B0B7D /* Kingfisher.xcconfig */; + buildSettings = { + CODE_SIGN_IDENTITY = ""; + "CODE_SIGN_IDENTITY[sdk=appletvos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=watchos*]" = ""; + CURRENT_PROJECT_VERSION = 1; + DEFINES_MODULE = YES; + DYLIB_COMPATIBILITY_VERSION = 1; + DYLIB_CURRENT_VERSION = 1; + DYLIB_INSTALL_NAME_BASE = "@rpath"; + GCC_PREFIX_HEADER = "Target Support Files/Kingfisher/Kingfisher-prefix.pch"; + INFOPLIST_FILE = "Target Support Files/Kingfisher/Info.plist"; + INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + MODULEMAP_FILE = "Target Support Files/Kingfisher/Kingfisher.modulemap"; + PRODUCT_NAME = Kingfisher; + SDKROOT = iphoneos; + SKIP_INSTALL = YES; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) "; + SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; + SWIFT_VERSION = 4.0; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + VERSIONING_SYSTEM = "apple-generic"; + VERSION_INFO_PREFIX = ""; + }; + name = Release; + }; /* End XCBuildConfiguration section */ /* Begin XCConfigurationList section */ 2D8E8EC45A3A1A1D94AE762CB5028504 /* Build configuration list for PBXProject "Pods" */ = { isa = XCConfigurationList; buildConfigurations = ( - C104F7F091290C3D1E248192F07FE689 /* Debug */, - 34FE9531DA9AF2820790339988D5FF41 /* Release */, + E4B68EE12B21C47CB798D9B1ECA6D7A7 /* Debug */, + B254DAA6CF0CE39F4A3D11B90A7E059A /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; @@ -615,17 +631,17 @@ 3BC883AEA3BFFB398C35E6F6E3F9689C /* Build configuration list for PBXNativeTarget "Pods-WRNavigationBar_swift" */ = { isa = XCConfigurationList; buildConfigurations = ( - B1AC7D6C94B5F6C383D0C0DF11F6AE13 /* Debug */, - B693A57C53A73E642AA38054EA7FA303 /* Release */, + B44E7915DC09BA8049ACD6E6966BF9CC /* Debug */, + 961384A12D2CE6B1C90AD0CABD2F3B67 /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; - 76E7EFBCEA1340954A03AA68051C2306 /* Build configuration list for PBXNativeTarget "Kingfisher" */ = { + 8C1E4CEFB2390CBE75E70BAC20F44BBF /* Build configuration list for PBXNativeTarget "Kingfisher" */ = { isa = XCConfigurationList; buildConfigurations = ( - A794525992F2457D34942D108D9E942A /* Debug */, - 20B5F4B4605A7E04AEE71183A359E092 /* Release */, + 576C583E88A92DC2279EB3BFC2CA8A6C /* Debug */, + E8652F35BF322A3957D0F62338910B79 /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; diff --git a/WRNavigationBar_swift/Pods/Target Support Files/Kingfisher/Info.plist b/WRNavigationBar_swift/Pods/Target Support Files/Kingfisher/Info.plist index f4b9ea8..33563de 100644 --- a/WRNavigationBar_swift/Pods/Target Support Files/Kingfisher/Info.plist +++ b/WRNavigationBar_swift/Pods/Target Support Files/Kingfisher/Info.plist @@ -15,7 +15,7 @@ CFBundlePackageType FMWK CFBundleShortVersionString - 3.6.2 + 4.3.1 CFBundleSignature ???? CFBundleVersion diff --git a/WRNavigationBar_swift/Pods/Target Support Files/Kingfisher/Kingfisher.xcconfig b/WRNavigationBar_swift/Pods/Target Support Files/Kingfisher/Kingfisher.xcconfig index 6e8fd9e..e05e95c 100644 --- a/WRNavigationBar_swift/Pods/Target Support Files/Kingfisher/Kingfisher.xcconfig +++ b/WRNavigationBar_swift/Pods/Target Support Files/Kingfisher/Kingfisher.xcconfig @@ -9,4 +9,4 @@ PODS_ROOT = ${SRCROOT} PODS_TARGET_SRCROOT = ${PODS_ROOT}/Kingfisher PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier} SKIP_INSTALL = YES -SWIFT_VERSION = 3.0 +SWIFT_VERSION = 4.0 diff --git a/WRNavigationBar_swift/Pods/Target Support Files/Pods-WRNavigationBar_swift/Pods-WRNavigationBar_swift-frameworks.sh b/WRNavigationBar_swift/Pods/Target Support Files/Pods-WRNavigationBar_swift/Pods-WRNavigationBar_swift-frameworks.sh index b1c3c96..82bcb19 100755 --- a/WRNavigationBar_swift/Pods/Target Support Files/Pods-WRNavigationBar_swift/Pods-WRNavigationBar_swift-frameworks.sh +++ b/WRNavigationBar_swift/Pods/Target Support Files/Pods-WRNavigationBar_swift/Pods-WRNavigationBar_swift-frameworks.sh @@ -6,6 +6,10 @@ mkdir -p "${CONFIGURATION_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" SWIFT_STDLIB_PATH="${DT_TOOLCHAIN_DIR}/usr/lib/swift/${PLATFORM_NAME}" +# This protects against multiple targets copying the same framework dependency at the same time. The solution +# was originally proposed here: https://lists.samba.org/archive/rsync/2008-February/020158.html +RSYNC_PROTECT_TMP_FILES=(--filter "P .*.??????") + install_framework() { if [ -r "${BUILT_PRODUCTS_DIR}/$1" ]; then @@ -23,9 +27,9 @@ install_framework() source="$(readlink "${source}")" fi - # use filter instead of exclude so missing patterns dont' throw errors - echo "rsync -av --filter \"- CVS/\" --filter \"- .svn/\" --filter \"- .git/\" --filter \"- .hg/\" --filter \"- Headers\" --filter \"- PrivateHeaders\" --filter \"- Modules\" \"${source}\" \"${destination}\"" - rsync -av --filter "- CVS/" --filter "- .svn/" --filter "- .git/" --filter "- .hg/" --filter "- Headers" --filter "- PrivateHeaders" --filter "- Modules" "${source}" "${destination}" + # Use filter instead of exclude so missing patterns don't throw errors. + echo "rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --filter \"- CVS/\" --filter \"- .svn/\" --filter \"- .git/\" --filter \"- .hg/\" --filter \"- Headers\" --filter \"- PrivateHeaders\" --filter \"- Modules\" \"${source}\" \"${destination}\"" + rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --filter "- CVS/" --filter "- .svn/" --filter "- .git/" --filter "- .hg/" --filter "- Headers" --filter "- PrivateHeaders" --filter "- Modules" "${source}" "${destination}" local basename basename="$(basename -s .framework "$1")" @@ -54,6 +58,15 @@ install_framework() fi } +# Copies the dSYM of a vendored framework +install_dsym() { + local source="$1" + if [ -r "$source" ]; then + echo "rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --filter \"- CVS/\" --filter \"- .svn/\" --filter \"- .git/\" --filter \"- .hg/\" --filter \"- Headers\" --filter \"- PrivateHeaders\" --filter \"- Modules\" \"${source}\" \"${DWARF_DSYM_FOLDER_PATH}\"" + rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" --filter "- CVS/" --filter "- .svn/" --filter "- .git/" --filter "- .hg/" --filter "- Headers" --filter "- PrivateHeaders" --filter "- Modules" "${source}" "${DWARF_DSYM_FOLDER_PATH}" + fi +} + # Signs a framework with the provided identity code_sign_if_enabled() { if [ -n "${EXPANDED_CODE_SIGN_IDENTITY}" -a "${CODE_SIGNING_REQUIRED}" != "NO" -a "${CODE_SIGNING_ALLOWED}" != "NO" ]; then @@ -76,7 +89,7 @@ strip_invalid_archs() { archs="$(lipo -info "$binary" | rev | cut -d ':' -f1 | rev)" stripped="" for arch in $archs; do - if ! [[ "${VALID_ARCHS}" == *"$arch"* ]]; then + if ! [[ "${ARCHS}" == *"$arch"* ]]; then # Strip non-valid architectures in-place lipo -remove "$arch" -output "$binary" "$binary" || exit 1 stripped="$stripped $arch" @@ -89,10 +102,10 @@ strip_invalid_archs() { if [[ "$CONFIGURATION" == "Debug" ]]; then - install_framework "$BUILT_PRODUCTS_DIR/Kingfisher/Kingfisher.framework" + install_framework "${BUILT_PRODUCTS_DIR}/Kingfisher/Kingfisher.framework" fi if [[ "$CONFIGURATION" == "Release" ]]; then - install_framework "$BUILT_PRODUCTS_DIR/Kingfisher/Kingfisher.framework" + install_framework "${BUILT_PRODUCTS_DIR}/Kingfisher/Kingfisher.framework" fi if [ "${COCOAPODS_PARALLEL_CODE_SIGN}" == "true" ]; then wait diff --git a/WRNavigationBar_swift/Pods/Target Support Files/Pods-WRNavigationBar_swift/Pods-WRNavigationBar_swift-resources.sh b/WRNavigationBar_swift/Pods/Target Support Files/Pods-WRNavigationBar_swift/Pods-WRNavigationBar_swift-resources.sh index aed060f..a7df440 100755 --- a/WRNavigationBar_swift/Pods/Target Support Files/Pods-WRNavigationBar_swift/Pods-WRNavigationBar_swift-resources.sh +++ b/WRNavigationBar_swift/Pods/Target Support Files/Pods-WRNavigationBar_swift/Pods-WRNavigationBar_swift-resources.sh @@ -8,6 +8,10 @@ RESOURCES_TO_COPY=${PODS_ROOT}/resources-to-copy-${TARGETNAME}.txt XCASSET_FILES=() +# This protects against multiple targets copying the same framework dependency at the same time. The solution +# was originally proposed here: https://lists.samba.org/archive/rsync/2008-February/020158.html +RSYNC_PROTECT_TMP_FILES=(--filter "P .*.??????") + case "${TARGETED_DEVICE_FAMILY}" in 1,2) TARGET_DEVICE_ARGS="--target-device ipad --target-device iphone" @@ -44,29 +48,29 @@ EOM fi case $RESOURCE_PATH in *.storyboard) - echo "ibtool --reference-external-strings-file --errors --warnings --notices --minimum-deployment-target ${!DEPLOYMENT_TARGET_SETTING_NAME} --output-format human-readable-text --compile ${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$RESOURCE_PATH\" .storyboard`.storyboardc $RESOURCE_PATH --sdk ${SDKROOT} ${TARGET_DEVICE_ARGS}" + echo "ibtool --reference-external-strings-file --errors --warnings --notices --minimum-deployment-target ${!DEPLOYMENT_TARGET_SETTING_NAME} --output-format human-readable-text --compile ${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$RESOURCE_PATH\" .storyboard`.storyboardc $RESOURCE_PATH --sdk ${SDKROOT} ${TARGET_DEVICE_ARGS}" || true ibtool --reference-external-strings-file --errors --warnings --notices --minimum-deployment-target ${!DEPLOYMENT_TARGET_SETTING_NAME} --output-format human-readable-text --compile "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$RESOURCE_PATH\" .storyboard`.storyboardc" "$RESOURCE_PATH" --sdk "${SDKROOT}" ${TARGET_DEVICE_ARGS} ;; *.xib) - echo "ibtool --reference-external-strings-file --errors --warnings --notices --minimum-deployment-target ${!DEPLOYMENT_TARGET_SETTING_NAME} --output-format human-readable-text --compile ${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$RESOURCE_PATH\" .xib`.nib $RESOURCE_PATH --sdk ${SDKROOT} ${TARGET_DEVICE_ARGS}" + echo "ibtool --reference-external-strings-file --errors --warnings --notices --minimum-deployment-target ${!DEPLOYMENT_TARGET_SETTING_NAME} --output-format human-readable-text --compile ${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$RESOURCE_PATH\" .xib`.nib $RESOURCE_PATH --sdk ${SDKROOT} ${TARGET_DEVICE_ARGS}" || true ibtool --reference-external-strings-file --errors --warnings --notices --minimum-deployment-target ${!DEPLOYMENT_TARGET_SETTING_NAME} --output-format human-readable-text --compile "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename \"$RESOURCE_PATH\" .xib`.nib" "$RESOURCE_PATH" --sdk "${SDKROOT}" ${TARGET_DEVICE_ARGS} ;; *.framework) - echo "mkdir -p ${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" + echo "mkdir -p ${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" || true mkdir -p "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" - echo "rsync -av $RESOURCE_PATH ${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" - rsync -av "$RESOURCE_PATH" "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" + echo "rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" $RESOURCE_PATH ${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" || true + rsync --delete -av "${RSYNC_PROTECT_TMP_FILES[@]}" "$RESOURCE_PATH" "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}" ;; *.xcdatamodel) - echo "xcrun momc \"$RESOURCE_PATH\" \"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH"`.mom\"" + echo "xcrun momc \"$RESOURCE_PATH\" \"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH"`.mom\"" || true xcrun momc "$RESOURCE_PATH" "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcdatamodel`.mom" ;; *.xcdatamodeld) - echo "xcrun momc \"$RESOURCE_PATH\" \"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcdatamodeld`.momd\"" + echo "xcrun momc \"$RESOURCE_PATH\" \"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcdatamodeld`.momd\"" || true xcrun momc "$RESOURCE_PATH" "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcdatamodeld`.momd" ;; *.xcmappingmodel) - echo "xcrun mapc \"$RESOURCE_PATH\" \"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcmappingmodel`.cdm\"" + echo "xcrun mapc \"$RESOURCE_PATH\" \"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcmappingmodel`.cdm\"" || true xcrun mapc "$RESOURCE_PATH" "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/`basename "$RESOURCE_PATH" .xcmappingmodel`.cdm" ;; *.xcassets) @@ -74,7 +78,7 @@ EOM XCASSET_FILES+=("$ABSOLUTE_XCASSET_FILE") ;; *) - echo "$RESOURCE_PATH" + echo "$RESOURCE_PATH" || true echo "$RESOURCE_PATH" >> "$RESOURCES_TO_COPY" ;; esac diff --git a/WRNavigationBar_swift/WRNavigationBar_swift.xcodeproj/project.pbxproj b/WRNavigationBar_swift/WRNavigationBar_swift.xcodeproj/project.pbxproj index 15e7de6..f37db52 100644 --- a/WRNavigationBar_swift/WRNavigationBar_swift.xcodeproj/project.pbxproj +++ b/WRNavigationBar_swift/WRNavigationBar_swift.xcodeproj/project.pbxproj @@ -7,23 +7,25 @@ objects = { /* Begin PBXBuildFile section */ + 1A05B4741F07FA9C001D7B64 /* WRNavigationBar.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1A05B4731F07FA9C001D7B64 /* WRNavigationBar.swift */; }; + 1A05B4761F07FAB4001D7B64 /* NormalListController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1A05B4751F07FAB4001D7B64 /* NormalListController.swift */; }; + 1A05B4781F07FAD7001D7B64 /* ImageNavController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1A05B4771F07FAD7001D7B64 /* ImageNavController.swift */; }; + 1A05B47A1F080D0B001D7B64 /* MillcolorGradController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1A05B4791F080D0B001D7B64 /* MillcolorGradController.swift */; }; 1A0DF77B1EA7176500191349 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1A0DF77A1EA7176500191349 /* AppDelegate.swift */; }; 1A0DF7801EA7176500191349 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 1A0DF77E1EA7176500191349 /* Main.storyboard */; }; 1A0DF7821EA7176500191349 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 1A0DF7811EA7176500191349 /* Assets.xcassets */; }; 1A0DF7851EA7176500191349 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 1A0DF7831EA7176500191349 /* LaunchScreen.storyboard */; }; 1A0DF7901EA7176500191349 /* WRNavigationBar_swiftTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1A0DF78F1EA7176500191349 /* WRNavigationBar_swiftTests.swift */; }; - 1A0DF7B31EA7372800191349 /* NormalListController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1A0DF7B21EA7372800191349 /* NormalListController.swift */; }; 1A0DF7B51EA7380600191349 /* SixthViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1A0DF7B41EA7380600191349 /* SixthViewController.swift */; }; 1A0DF7B71EA7471B00191349 /* WeiBoMineController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1A0DF7B61EA7471B00191349 /* WeiBoMineController.swift */; }; 1A0DF7B91EA7521C00191349 /* BaseNavigationController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1A0DF7B81EA7521C00191349 /* BaseNavigationController.swift */; }; - 1A0DF7BE1EA7545900191349 /* WRNavigationBar.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1A0DF7BD1EA7545900191349 /* WRNavigationBar.swift */; }; 1A869EDD1ECAA0C1006D96F8 /* BaseViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1A869EDC1ECAA0C1006D96F8 /* BaseViewController.swift */; }; 1A869EDF1ECAA36B006D96F8 /* CustomNavBarController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1A869EDE1ECAA36B006D96F8 /* CustomNavBarController.swift */; }; 1A96559C1ED6B64F00A89E30 /* CustomListController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1A96559B1ED6B64F00A89E30 /* CustomListController.swift */; }; 1A96559E1ED6B8C600A89E30 /* MoveListController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1A96559D1ED6B8C600A89E30 /* MoveListController.swift */; }; 1A966E8D1EE048F60045FCB8 /* AntForestController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1A966E8C1EE048F60045FCB8 /* AntForestController.swift */; }; + 1AADC3941F23088600BB73D9 /* AllTransparent.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1AADC3931F23088600BB73D9 /* AllTransparent.swift */; }; 1AB702661EA9A43C006DBA79 /* SecondViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1AB702651EA9A43C006DBA79 /* SecondViewController.swift */; }; - 1AB702681EA9A9BC006DBA79 /* ThirdViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1AB702671EA9A9BC006DBA79 /* ThirdViewController.swift */; }; 1AB7026A1EA9AC7A006DBA79 /* QQAppController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1AB702691EA9AC7A006DBA79 /* QQAppController.swift */; }; 1AB7026C1EA9B753006DBA79 /* QQZoneController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1AB7026B1EA9B753006DBA79 /* QQZoneController.swift */; }; 1AD0140A1EDBFB4500A6893C /* ZhiHuController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1AD014091EDBFB4500A6893C /* ZhiHuController.swift */; }; @@ -31,6 +33,7 @@ 1AD014101EDBFEAC00A6893C /* WRCycleScrollView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1AD0140D1EDBFEAC00A6893C /* WRCycleScrollView.swift */; }; 1AD014111EDBFEAC00A6893C /* WRProxy.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1AD0140E1EDBFEAC00A6893C /* WRProxy.swift */; }; 1AD014131EDC091F00A6893C /* QQMineController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1AD014121EDC091F00A6893C /* QQMineController.swift */; }; + 34A093CA1FC941B0009119BF /* WRCustomNavigationBar.swift in Sources */ = {isa = PBXBuildFile; fileRef = 34A093C91FC941B0009119BF /* WRCustomNavigationBar.swift */; }; BA823A4F29CFCD6EEC3B52B9 /* Pods_WRNavigationBar_swift.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 63C8A182323696F064D8660C /* Pods_WRNavigationBar_swift.framework */; }; /* End PBXBuildFile section */ @@ -45,6 +48,10 @@ /* End PBXContainerItemProxy section */ /* Begin PBXFileReference section */ + 1A05B4731F07FA9C001D7B64 /* WRNavigationBar.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = WRNavigationBar.swift; sourceTree = ""; }; + 1A05B4751F07FAB4001D7B64 /* NormalListController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NormalListController.swift; sourceTree = ""; }; + 1A05B4771F07FAD7001D7B64 /* ImageNavController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ImageNavController.swift; sourceTree = ""; }; + 1A05B4791F080D0B001D7B64 /* MillcolorGradController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MillcolorGradController.swift; sourceTree = ""; }; 1A0DF7771EA7176500191349 /* WRNavigationBar_swift.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = WRNavigationBar_swift.app; sourceTree = BUILT_PRODUCTS_DIR; }; 1A0DF77A1EA7176500191349 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; 1A0DF77F1EA7176500191349 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; @@ -54,18 +61,16 @@ 1A0DF78B1EA7176500191349 /* WRNavigationBar_swiftTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = WRNavigationBar_swiftTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 1A0DF78F1EA7176500191349 /* WRNavigationBar_swiftTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WRNavigationBar_swiftTests.swift; sourceTree = ""; }; 1A0DF7911EA7176500191349 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; - 1A0DF7B21EA7372800191349 /* NormalListController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NormalListController.swift; sourceTree = ""; }; 1A0DF7B41EA7380600191349 /* SixthViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SixthViewController.swift; sourceTree = ""; }; 1A0DF7B61EA7471B00191349 /* WeiBoMineController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = WeiBoMineController.swift; sourceTree = ""; }; 1A0DF7B81EA7521C00191349 /* BaseNavigationController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = BaseNavigationController.swift; path = Demos/BaseNavigationController.swift; sourceTree = ""; }; - 1A0DF7BD1EA7545900191349 /* WRNavigationBar.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = WRNavigationBar.swift; sourceTree = ""; }; 1A869EDC1ECAA0C1006D96F8 /* BaseViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BaseViewController.swift; sourceTree = ""; }; 1A869EDE1ECAA36B006D96F8 /* CustomNavBarController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CustomNavBarController.swift; sourceTree = ""; }; 1A96559B1ED6B64F00A89E30 /* CustomListController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CustomListController.swift; sourceTree = ""; }; 1A96559D1ED6B8C600A89E30 /* MoveListController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MoveListController.swift; sourceTree = ""; }; 1A966E8C1EE048F60045FCB8 /* AntForestController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AntForestController.swift; sourceTree = ""; }; + 1AADC3931F23088600BB73D9 /* AllTransparent.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AllTransparent.swift; sourceTree = ""; }; 1AB702651EA9A43C006DBA79 /* SecondViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SecondViewController.swift; sourceTree = ""; }; - 1AB702671EA9A9BC006DBA79 /* ThirdViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ThirdViewController.swift; sourceTree = ""; }; 1AB702691EA9AC7A006DBA79 /* QQAppController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = QQAppController.swift; sourceTree = ""; }; 1AB7026B1EA9B753006DBA79 /* QQZoneController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = QQZoneController.swift; sourceTree = ""; }; 1AD014091EDBFB4500A6893C /* ZhiHuController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ZhiHuController.swift; sourceTree = ""; }; @@ -74,6 +79,7 @@ 1AD0140E1EDBFEAC00A6893C /* WRProxy.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = WRProxy.swift; sourceTree = ""; }; 1AD014121EDC091F00A6893C /* QQMineController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = QQMineController.swift; sourceTree = ""; }; 272C2A7862DC39DA91D57781 /* Pods-WRNavigationBar_swift.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-WRNavigationBar_swift.release.xcconfig"; path = "Pods/Target Support Files/Pods-WRNavigationBar_swift/Pods-WRNavigationBar_swift.release.xcconfig"; sourceTree = ""; }; + 34A093C91FC941B0009119BF /* WRCustomNavigationBar.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WRCustomNavigationBar.swift; sourceTree = ""; }; 63C8A182323696F064D8660C /* Pods_WRNavigationBar_swift.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_WRNavigationBar_swift.framework; sourceTree = BUILT_PRODUCTS_DIR; }; D76868588A082EB7E7777210 /* Pods-WRNavigationBar_swift.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-WRNavigationBar_swift.debug.xcconfig"; path = "Pods/Target Support Files/Pods-WRNavigationBar_swift/Pods-WRNavigationBar_swift.debug.xcconfig"; sourceTree = ""; }; /* End PBXFileReference section */ @@ -147,7 +153,8 @@ 1A0DF79A1EA7179500191349 /* WRNavigationBar */ = { isa = PBXGroup; children = ( - 1A0DF7BD1EA7545900191349 /* WRNavigationBar.swift */, + 1A05B4731F07FA9C001D7B64 /* WRNavigationBar.swift */, + 34A093C91FC941B0009119BF /* WRCustomNavigationBar.swift */, ); path = WRNavigationBar; sourceTree = ""; @@ -155,13 +162,14 @@ 1A0DF7B11EA7370000191349 /* 普通 */ = { isa = PBXGroup; children = ( - 1A0DF7B21EA7372800191349 /* NormalListController.swift */, + 1A05B4751F07FAB4001D7B64 /* NormalListController.swift */, 1A0DF7B61EA7471B00191349 /* WeiBoMineController.swift */, 1AB702691EA9AC7A006DBA79 /* QQAppController.swift */, 1AB7026B1EA9B753006DBA79 /* QQZoneController.swift */, 1AD014091EDBFB4500A6893C /* ZhiHuController.swift */, 1AD014121EDC091F00A6893C /* QQMineController.swift */, 1A966E8C1EE048F60045FCB8 /* AntForestController.swift */, + 1AADC3931F23088600BB73D9 /* AllTransparent.swift */, ); name = "普通"; path = Demos; @@ -173,6 +181,8 @@ 1A869EDC1ECAA0C1006D96F8 /* BaseViewController.swift */, 1A96559B1ED6B64F00A89E30 /* CustomListController.swift */, 1A869EDE1ECAA36B006D96F8 /* CustomNavBarController.swift */, + 1A05B4771F07FAD7001D7B64 /* ImageNavController.swift */, + 1A05B4791F080D0B001D7B64 /* MillcolorGradController.swift */, ); name = "自定义导航栏"; path = Demos; @@ -183,7 +193,6 @@ children = ( 1A96559D1ED6B8C600A89E30 /* MoveListController.swift */, 1AB702651EA9A43C006DBA79 /* SecondViewController.swift */, - 1AB702671EA9A9BC006DBA79 /* ThirdViewController.swift */, 1A0DF7B41EA7380600191349 /* SixthViewController.swift */, ); name = "移动导航栏"; @@ -266,17 +275,19 @@ isa = PBXProject; attributes = { LastSwiftUpdateCheck = 0810; - LastUpgradeCheck = 0810; + LastUpgradeCheck = 0900; ORGANIZATIONNAME = wangrui; TargetAttributes = { 1A0DF7761EA7176500191349 = { CreatedOnToolsVersion = 8.1; DevelopmentTeam = 652U6LDTX4; + LastSwiftMigration = 0900; ProvisioningStyle = Automatic; }; 1A0DF78A1EA7176500191349 = { CreatedOnToolsVersion = 8.1; DevelopmentTeam = 652U6LDTX4; + LastSwiftMigration = 0900; ProvisioningStyle = Automatic; TestTargetID = 1A0DF7761EA7176500191349; }; @@ -343,13 +354,16 @@ files = ( ); inputPaths = ( + "${PODS_PODFILE_DIR_PATH}/Podfile.lock", + "${PODS_ROOT}/Manifest.lock", ); name = "[CP] Check Pods Manifest.lock"; outputPaths = ( + "$(DERIVED_FILE_DIR)/Pods-WRNavigationBar_swift-checkManifestLockResult.txt", ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; - shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n"; + shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; showEnvVarsInLog = 0; }; D52EBFEB66FB9C860C432F23 /* [CP] Embed Pods Frameworks */ = { @@ -358,9 +372,12 @@ files = ( ); inputPaths = ( + "${SRCROOT}/Pods/Target Support Files/Pods-WRNavigationBar_swift/Pods-WRNavigationBar_swift-frameworks.sh", + "${BUILT_PRODUCTS_DIR}/Kingfisher/Kingfisher.framework", ); name = "[CP] Embed Pods Frameworks"; outputPaths = ( + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/Kingfisher.framework", ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; @@ -377,13 +394,16 @@ 1A869EDF1ECAA36B006D96F8 /* CustomNavBarController.swift in Sources */, 1AD014131EDC091F00A6893C /* QQMineController.swift in Sources */, 1AB7026C1EA9B753006DBA79 /* QQZoneController.swift in Sources */, + 1A05B47A1F080D0B001D7B64 /* MillcolorGradController.swift in Sources */, + 1A05B4781F07FAD7001D7B64 /* ImageNavController.swift in Sources */, 1A96559E1ED6B8C600A89E30 /* MoveListController.swift in Sources */, 1AD014111EDBFEAC00A6893C /* WRProxy.swift in Sources */, - 1A0DF7BE1EA7545900191349 /* WRNavigationBar.swift in Sources */, 1AD0140A1EDBFB4500A6893C /* ZhiHuController.swift in Sources */, 1AD0140F1EDBFEAC00A6893C /* WRCycleCell.swift in Sources */, + 34A093CA1FC941B0009119BF /* WRCustomNavigationBar.swift in Sources */, 1A869EDD1ECAA0C1006D96F8 /* BaseViewController.swift in Sources */, - 1A0DF7B31EA7372800191349 /* NormalListController.swift in Sources */, + 1A05B4761F07FAB4001D7B64 /* NormalListController.swift in Sources */, + 1A05B4741F07FA9C001D7B64 /* WRNavigationBar.swift in Sources */, 1AD014101EDBFEAC00A6893C /* WRCycleScrollView.swift in Sources */, 1A0DF7B51EA7380600191349 /* SixthViewController.swift in Sources */, 1AB7026A1EA9AC7A006DBA79 /* QQAppController.swift in Sources */, @@ -392,7 +412,7 @@ 1A96559C1ED6B64F00A89E30 /* CustomListController.swift in Sources */, 1AB702661EA9A43C006DBA79 /* SecondViewController.swift in Sources */, 1A0DF7B91EA7521C00191349 /* BaseNavigationController.swift in Sources */, - 1AB702681EA9A9BC006DBA79 /* ThirdViewController.swift in Sources */, + 1AADC3941F23088600BB73D9 /* AllTransparent.swift in Sources */, 1A0DF7B71EA7471B00191349 /* WeiBoMineController.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; @@ -444,7 +464,9 @@ 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_DOCUMENTATION_COMMENTS = YES; @@ -452,7 +474,12 @@ 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_SUSPICIOUS_MOVES = YES; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; @@ -494,7 +521,9 @@ 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_DOCUMENTATION_COMMENTS = YES; @@ -502,7 +531,12 @@ 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_SUSPICIOUS_MOVES = YES; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; @@ -537,9 +571,10 @@ INFOPLIST_FILE = WRNavigationBar_swift/Info.plist; IPHONEOS_DEPLOYMENT_TARGET = 8.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; - PRODUCT_BUNDLE_IDENTIFIER = "video.wangrui.com.WRNavigationBar-swift"; + PRODUCT_BUNDLE_IDENTIFIER = video.com.wangrui; PRODUCT_NAME = "$(TARGET_NAME)"; - SWIFT_VERSION = 3.0; + SWIFT_SWIFT3_OBJC_INFERENCE = Default; + SWIFT_VERSION = 4.0; TARGETED_DEVICE_FAMILY = 1; }; name = Debug; @@ -553,9 +588,10 @@ INFOPLIST_FILE = WRNavigationBar_swift/Info.plist; IPHONEOS_DEPLOYMENT_TARGET = 8.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; - PRODUCT_BUNDLE_IDENTIFIER = "video.wangrui.com.WRNavigationBar-swift"; + PRODUCT_BUNDLE_IDENTIFIER = video.com.wangrui; PRODUCT_NAME = "$(TARGET_NAME)"; - SWIFT_VERSION = 3.0; + SWIFT_SWIFT3_OBJC_INFERENCE = Default; + SWIFT_VERSION = 4.0; TARGETED_DEVICE_FAMILY = 1; }; name = Release; @@ -570,7 +606,8 @@ LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = "video.wangrui.com.WRNavigationBar-swiftTests"; PRODUCT_NAME = "$(TARGET_NAME)"; - SWIFT_VERSION = 3.0; + SWIFT_SWIFT3_OBJC_INFERENCE = On; + SWIFT_VERSION = 4.0; TEST_HOST = "$(BUILT_PRODUCTS_DIR)/WRNavigationBar_swift.app/WRNavigationBar_swift"; }; name = Debug; @@ -585,7 +622,8 @@ LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = "video.wangrui.com.WRNavigationBar-swiftTests"; PRODUCT_NAME = "$(TARGET_NAME)"; - SWIFT_VERSION = 3.0; + SWIFT_SWIFT3_OBJC_INFERENCE = On; + SWIFT_VERSION = 4.0; TEST_HOST = "$(BUILT_PRODUCTS_DIR)/WRNavigationBar_swift.app/WRNavigationBar_swift"; }; name = Release; diff --git a/WRNavigationBar_swift/WRNavigationBar_swift/AppDelegate.swift b/WRNavigationBar_swift/WRNavigationBar_swift/AppDelegate.swift index cfa6f8e..3928939 100644 --- a/WRNavigationBar_swift/WRNavigationBar_swift/AppDelegate.swift +++ b/WRNavigationBar_swift/WRNavigationBar_swift/AppDelegate.swift @@ -59,13 +59,15 @@ class AppDelegate: UIResponder, UIApplicationDelegate { func setNavBarAppearence() { // 设置导航栏默认的背景颜色 - UIColor.defaultNavBarBarTintColor = UIColor.init(red: 0/255.0, green: 175/255.0, blue: 240/255.0, alpha: 1) + WRNavigationBar.defaultNavBarBarTintColor = UIColor.init(red: 0/255.0, green: 175/255.0, blue: 240/255.0, alpha: 1) // 设置导航栏所有按钮的默认颜色 - UIColor.defaultNavBarTintColor = .white + WRNavigationBar.defaultNavBarTintColor = .white // 设置导航栏标题默认颜色 - UIColor.defaultNavBarTitleColor = .white + WRNavigationBar.defaultNavBarTitleColor = .white // 统一设置状态栏样式 - UIColor.defaultStatusBarStyle = .lightContent + WRNavigationBar.defaultStatusBarStyle = .lightContent + // 如果需要设置导航栏底部分割线隐藏,可以在这里统一设置 + WRNavigationBar.defaultShadowImageHidden = true } } diff --git a/WRNavigationBar_swift/WRNavigationBar_swift/Assets.xcassets/AppIcon.appiconset/Contents.json b/WRNavigationBar_swift/WRNavigationBar_swift/Assets.xcassets/AppIcon.appiconset/Contents.json index a954173..440402b 100644 --- a/WRNavigationBar_swift/WRNavigationBar_swift/Assets.xcassets/AppIcon.appiconset/Contents.json +++ b/WRNavigationBar_swift/WRNavigationBar_swift/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -41,6 +41,11 @@ "idiom" : "iphone", "filename" : "180wr.png", "scale" : "3x" + }, + { + "idiom" : "ios-marketing", + "size" : "1024x1024", + "scale" : "1x" } ], "info" : { diff --git a/WRNavigationBar_swift/WRNavigationBar_swift/Assets.xcassets/image7.imageset/Contents.json b/WRNavigationBar_swift/WRNavigationBar_swift/Assets.xcassets/image7.imageset/Contents.json new file mode 100644 index 0000000..2f0fafd --- /dev/null +++ b/WRNavigationBar_swift/WRNavigationBar_swift/Assets.xcassets/image7.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "u=2864424897,2473674229&fm=26&gp=0.jpg", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/WRNavigationBar_swift/WRNavigationBar_swift/Assets.xcassets/image7.imageset/u=2864424897,2473674229&fm=26&gp=0.jpg b/WRNavigationBar_swift/WRNavigationBar_swift/Assets.xcassets/image7.imageset/u=2864424897,2473674229&fm=26&gp=0.jpg new file mode 100644 index 0000000..bb033b5 Binary files /dev/null and b/WRNavigationBar_swift/WRNavigationBar_swift/Assets.xcassets/image7.imageset/u=2864424897,2473674229&fm=26&gp=0.jpg differ diff --git a/WRNavigationBar_swift/WRNavigationBar_swift/Assets.xcassets/image8.imageset/Contents.json b/WRNavigationBar_swift/WRNavigationBar_swift/Assets.xcassets/image8.imageset/Contents.json new file mode 100644 index 0000000..3113f50 --- /dev/null +++ b/WRNavigationBar_swift/WRNavigationBar_swift/Assets.xcassets/image8.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "cad334853a19ab63f278ed8532ff8ae1.jpeg", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/WRNavigationBar_swift/WRNavigationBar_swift/Assets.xcassets/image8.imageset/cad334853a19ab63f278ed8532ff8ae1.jpeg b/WRNavigationBar_swift/WRNavigationBar_swift/Assets.xcassets/image8.imageset/cad334853a19ab63f278ed8532ff8ae1.jpeg new file mode 100644 index 0000000..d2e2e85 Binary files /dev/null and b/WRNavigationBar_swift/WRNavigationBar_swift/Assets.xcassets/image8.imageset/cad334853a19ab63f278ed8532ff8ae1.jpeg differ diff --git a/WRNavigationBar_swift/WRNavigationBar_swift/Assets.xcassets/imageNav.imageset/Contents.json b/WRNavigationBar_swift/WRNavigationBar_swift/Assets.xcassets/imageNav.imageset/Contents.json new file mode 100644 index 0000000..47c7b4b --- /dev/null +++ b/WRNavigationBar_swift/WRNavigationBar_swift/Assets.xcassets/imageNav.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "u=1206318416,27195661&fm=26&gp=0.jpg", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/WRNavigationBar_swift/WRNavigationBar_swift/Assets.xcassets/imageNav.imageset/u=1206318416,27195661&fm=26&gp=0.jpg b/WRNavigationBar_swift/WRNavigationBar_swift/Assets.xcassets/imageNav.imageset/u=1206318416,27195661&fm=26&gp=0.jpg new file mode 100644 index 0000000..49bf221 Binary files /dev/null and b/WRNavigationBar_swift/WRNavigationBar_swift/Assets.xcassets/imageNav.imageset/u=1206318416,27195661&fm=26&gp=0.jpg differ diff --git a/WRNavigationBar_swift/WRNavigationBar_swift/Assets.xcassets/millcolorGrad.imageset/Contents.json b/WRNavigationBar_swift/WRNavigationBar_swift/Assets.xcassets/millcolorGrad.imageset/Contents.json new file mode 100644 index 0000000..ea26b9f --- /dev/null +++ b/WRNavigationBar_swift/WRNavigationBar_swift/Assets.xcassets/millcolorGrad.imageset/Contents.json @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "millcolorGrad.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/WRNavigationBar_swift/WRNavigationBar_swift/Assets.xcassets/millcolorGrad.imageset/millcolorGrad.png b/WRNavigationBar_swift/WRNavigationBar_swift/Assets.xcassets/millcolorGrad.imageset/millcolorGrad.png new file mode 100644 index 0000000..ab99e3c Binary files /dev/null and b/WRNavigationBar_swift/WRNavigationBar_swift/Assets.xcassets/millcolorGrad.imageset/millcolorGrad.png differ diff --git a/WRNavigationBar_swift/WRNavigationBar_swift/Demos/AllTransparent.swift b/WRNavigationBar_swift/WRNavigationBar_swift/Demos/AllTransparent.swift new file mode 100644 index 0000000..bb73ab7 --- /dev/null +++ b/WRNavigationBar_swift/WRNavigationBar_swift/Demos/AllTransparent.swift @@ -0,0 +1,107 @@ +// +// WeiBoMineController.swift +// WRNavigationBar_swift +// +// Created by wangrui on 2017/4/19. +// Copyright © 2017年 wangrui. All rights reserved. +// +// Github地址:https://github.com/wangrui460/WRNavigationBar_swift + +import UIKit + +private let IMAGE_HEIGHT:CGFloat = 220 +private let NAVBAR_COLORCHANGE_POINT:CGFloat = IMAGE_HEIGHT - CGFloat(kNavBarBottom * 2) + +class AllTransparent: UIViewController +{ + lazy var tableView:UITableView = { + let table:UITableView = UITableView(frame: CGRect.init(x: 0, y: 0, width: kScreenWidth, height: self.view.bounds.height), style: .plain) + table.contentInset = UIEdgeInsetsMake(-CGFloat(kNavBarBottom), 0, 0, 0); + table.delegate = self + table.dataSource = self + return table + }() + lazy var topView:UIImageView = { + let imgView = UIImageView(image: UIImage(named: "wbBg")) + imgView.frame = CGRect(x: 0, y: 0, width: kScreenWidth, height: IMAGE_HEIGHT) + imgView.contentMode = UIViewContentMode.scaleAspectFill + imgView.clipsToBounds = true + return imgView + }() + + override func viewDidLoad() + { + super.viewDidLoad() + title = "wangrui460" + view.backgroundColor = UIColor.red + view.addSubview(tableView) + tableView.tableHeaderView = topView + navigationItem.rightBarButtonItem = UIBarButtonItem(title: "··· ", style: .done, target: nil, action: nil) + + // 设置导航栏颜色 + navBarBarTintColor = UIColor.init(red: 247/255.0, green: 247/255.0, blue: 247/255.0, alpha: 1.0) + + // 设置初始导航栏透明度 + navBarBackgroundAlpha = 0 + + // 设置导航栏按钮和标题颜色 + navBarTintColor = .white + + // 如果需要隐藏导航栏底部分割线,设置 hideShadowImage 为true + // hideShadowImage = true + } + + deinit { + tableView.delegate = nil + print("FirstVC deinit") + } +} + + +// MARK: - 滑动改变导航栏透明度、标题颜色、左右按钮颜色、状态栏颜色 +extension AllTransparent +{ + func scrollViewDidScroll(_ scrollView: UIScrollView) + { + let offsetY = scrollView.contentOffset.y + if (offsetY > NAVBAR_COLORCHANGE_POINT) + { + let alpha = (offsetY - NAVBAR_COLORCHANGE_POINT) / CGFloat(kNavBarBottom) + navBarBackgroundAlpha = alpha + navBarTintColor = UIColor.black.withAlphaComponent(alpha) + navBarTitleColor = UIColor.black.withAlphaComponent(alpha) + statusBarStyle = .default + } + else + { + navBarBackgroundAlpha = 0 + navBarTintColor = .white + navBarTitleColor = .white + statusBarStyle = .lightContent + } + } +} + + +extension AllTransparent:UITableViewDelegate,UITableViewDataSource +{ + func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { + return 40 + } + + func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell + { + let cell = UITableViewCell.init(style: .default, reuseIdentifier: nil) + let str = String(format: "WRNavigationBar %zd", indexPath.row) + cell.textLabel?.text = str + cell.textLabel?.font = UIFont.systemFont(ofSize: 15) + return cell + } + + func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) + { + tableView.deselectRow(at: indexPath, animated: true) + let vc:AllTransparent = AllTransparent() + navigationController?.pushViewController(vc, animated: true) + } +} diff --git a/WRNavigationBar_swift/WRNavigationBar_swift/Demos/AntForestController.swift b/WRNavigationBar_swift/WRNavigationBar_swift/Demos/AntForestController.swift index 4f70dc6..0299261 100644 --- a/WRNavigationBar_swift/WRNavigationBar_swift/Demos/AntForestController.swift +++ b/WRNavigationBar_swift/WRNavigationBar_swift/Demos/AntForestController.swift @@ -101,7 +101,7 @@ extension AntForestController extension AntForestController: UITableViewDelegate,UITableViewDataSource { func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { - return 15 + return 25 } func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell diff --git a/WRNavigationBar_swift/WRNavigationBar_swift/Demos/BaseViewController.swift b/WRNavigationBar_swift/WRNavigationBar_swift/Demos/BaseViewController.swift index e4edb40..d00029b 100644 --- a/WRNavigationBar_swift/WRNavigationBar_swift/Demos/BaseViewController.swift +++ b/WRNavigationBar_swift/WRNavigationBar_swift/Demos/BaseViewController.swift @@ -11,8 +11,7 @@ import UIKit class BaseViewController: UIViewController { - lazy var navBar = UINavigationBar(frame: CGRect(x: 0, y: 0, width: kScreenWidth, height: 64)) - lazy var navItem = UINavigationItem() + lazy var navBar = WRCustomNavigationBar.CustomNavigationBar() override func viewDidLoad() { @@ -25,16 +24,28 @@ class BaseViewController: UIViewController fileprivate func setupNavBar() { - // 自定义导航栏必须设置这个属性!!!!!! - customNavBar = navBar view.addSubview(navBar) - navBar.items = [navItem] - // 导航条背景颜色 - navBar.barTintColor = MainNavBarColor - // 导航条标题颜色 - navBar.titleTextAttributes = [NSForegroundColorAttributeName:UIColor.white] - // 导航条左右按钮字体颜色 - navBar.tintColor = UIColor.white + + // 设置自定义导航栏背景图片 + navBar.barBackgroundImage = UIImage(named: "millcolorGrad") + + // 设置自定义导航栏背景颜色 + // navBar.backgroundColor = MainNavBarColor + + // 设置自定义导航栏标题颜色 + navBar.titleLabelColor = .white + + // 设置自定义导航栏左右按钮字体颜色 + navBar.wr_setTintColor(color: .white) + + if self.navigationController?.childViewControllers.count != 1 { + navBar.wr_setLeftButton(title: "<<", titleColor: UIColor.white) + } + } + + @objc fileprivate func back() + { + _ = navigationController?.popViewController(animated: true) } } diff --git a/WRNavigationBar_swift/WRNavigationBar_swift/Demos/CustomListController.swift b/WRNavigationBar_swift/WRNavigationBar_swift/Demos/CustomListController.swift index 9be2fa5..5b08864 100644 --- a/WRNavigationBar_swift/WRNavigationBar_swift/Demos/CustomListController.swift +++ b/WRNavigationBar_swift/WRNavigationBar_swift/Demos/CustomListController.swift @@ -22,12 +22,11 @@ class CustomListController: BaseViewController tableView.dataSource = self tableView.delegate = self tableView.backgroundColor = UIColor.white + if #available(iOS 11.0, *) { + tableView.contentInsetAdjustmentBehavior = .never + } view.insertSubview(navBar, aboveSubview: tableView) - navItem.title = "自定义导航栏" - - navBarBarTintColor = UIColor.init(red: 247/255.0, green: 247/255.0, blue: 247/255.0, alpha: 1.0) - navBarTitleColor = .black - statusBarStyle = .default + navBar.title = "自定义导航栏" } } @@ -45,7 +44,11 @@ extension CustomListController: UITableViewDelegate, UITableViewDataSource var str:String? = nil switch indexPath.row { case 0: - str = "主页"; + str = "主页" + case 1: + str = "导航栏显示图片" + case 2: + str = "实现导航栏渐变色的另一种方式" default: str = "" } @@ -64,6 +67,10 @@ extension CustomListController: UITableViewDelegate, UITableViewDataSource switch indexPath.row { case 0: navigationController?.pushViewController(CustomNavBarController(), animated: true) + case 1: + navigationController?.pushViewController(ImageNavController(), animated: true) + case 2: + navigationController?.pushViewController(MillcolorGradController(), animated: true) default: break } diff --git a/WRNavigationBar_swift/WRNavigationBar_swift/Demos/CustomNavBarController.swift b/WRNavigationBar_swift/WRNavigationBar_swift/Demos/CustomNavBarController.swift index dcb62f4..2cc35e5 100644 --- a/WRNavigationBar_swift/WRNavigationBar_swift/Demos/CustomNavBarController.swift +++ b/WRNavigationBar_swift/WRNavigationBar_swift/Demos/CustomNavBarController.swift @@ -17,7 +17,7 @@ class CustomNavBarController: BaseViewController lazy var tableView:UITableView = { let frame = CGRect(x: 0, y: 0, width: kScreenWidth, height: self.view.bounds.height) let table:UITableView = UITableView(frame: frame, style: .plain) - table.contentInset = UIEdgeInsetsMake(0, 0, CGFloat(kTabBarHeight), 0); + table.contentInset = UIEdgeInsetsMake(0, 0, 0, 0); table.delegate = self table.dataSource = self return table @@ -43,21 +43,21 @@ class CustomNavBarController: BaseViewController topView.addSubview(imageView) imageView.center = topView.center tableView.tableHeaderView = topView + if #available(iOS 11.0, *) { + tableView.contentInsetAdjustmentBehavior = .never + } view.insertSubview(navBar, aboveSubview: tableView) - navItem.leftBarButtonItem = UIBarButtonItem(title: "<<", style: .plain, target: self, action: #selector(back)) - navItem.title = "个人中心" + + navBar.title = "个人中心" // 设置导航栏颜色 - navBarBarTintColor = UIColor.init(red: 247/255.0, green: 247/255.0, blue: 247/255.0, alpha: 1.0) + navBar.barBackgroundColor = UIColor(red: 247/255.0, green: 247/255.0, blue: 247/255.0, alpha: 1.0) // 设置初始导航栏透明度 - navBarBackgroundAlpha = 0 - - // 设置导航栏按钮 - navBarTintColor = .white + navBar.wr_setBackgroundAlpha(alpha: 0) // 设置标题文字颜色 - navBarTitleColor = .white + navBar.titleLabelColor = UIColor.white } } @@ -71,16 +71,16 @@ extension CustomNavBarController if (offsetY > NAVBAR_COLORCHANGE_POINT) { let alpha = (offsetY - NAVBAR_COLORCHANGE_POINT) / CGFloat(kNavBarBottom) - navBarBackgroundAlpha = alpha - navBarTintColor = UIColor.black.withAlphaComponent(alpha) - navBarTitleColor = UIColor.black.withAlphaComponent(alpha) + navBar.wr_setBackgroundAlpha(alpha: alpha) + navBar.wr_setTintColor(color: UIColor.black.withAlphaComponent(alpha)) + navBar.titleLabelColor = UIColor.black.withAlphaComponent(alpha) statusBarStyle = .default } else { - navBarBackgroundAlpha = 0 - navBarTintColor = .white - navBarTitleColor = .white + navBar.wr_setBackgroundAlpha(alpha: 0) + navBar.wr_setTintColor(color: .white) + navBar.titleLabelColor = .white statusBarStyle = .lightContent } } @@ -108,13 +108,7 @@ extension CustomNavBarController:UITableViewDelegate,UITableViewDataSource let vc:BaseViewController = BaseViewController() vc.view.backgroundColor = UIColor.red let str = String(format: "右滑返回查看效果 ", indexPath.row) - vc.navItem.title = str - vc.navItem.leftBarButtonItem = UIBarButtonItem(title: "返回", style: .plain, target: self, action: #selector(back)) + vc.navBar.title = str navigationController?.pushViewController(vc, animated: true) } - - @objc fileprivate func back() - { - _ = navigationController?.popViewController(animated: true) - } } diff --git a/WRNavigationBar_swift/WRNavigationBar_swift/Demos/ImageNavController.swift b/WRNavigationBar_swift/WRNavigationBar_swift/Demos/ImageNavController.swift new file mode 100644 index 0000000..8843a5f --- /dev/null +++ b/WRNavigationBar_swift/WRNavigationBar_swift/Demos/ImageNavController.swift @@ -0,0 +1,107 @@ +// +// ImageNavController .swift +// WRNavigationBar_swift +// +// Created by wangrui on 2017/4/19. +// Copyright © 2017年 wangrui. All rights reserved. +// +// Github地址:https://github.com/wangrui460/WRNavigationBar_swift + +import UIKit + +private let IMAGE_HEIGHT:CGFloat = 220 +private let NAVBAR_COLORCHANGE_POINT:CGFloat = IMAGE_HEIGHT - CGFloat(kNavBarBottom * 2) + +class ImageNavController: BaseViewController +{ + lazy var tableView:UITableView = { + let table:UITableView = UITableView(frame: CGRect.init(x: 0, y: 0, width: kScreenWidth, height: self.view.bounds.height), style: .plain) + table.contentInset = UIEdgeInsetsMake(0, 0, 0, 0); + table.delegate = self + table.dataSource = self + return table + }() + lazy var topView:UIImageView = { + let imgView = UIImageView(image: UIImage(named: "image7")) + imgView.frame = CGRect(x: 0, y: 0, width: kScreenWidth, height: IMAGE_HEIGHT) + imgView.contentMode = UIViewContentMode.scaleAspectFill + imgView.clipsToBounds = true + return imgView + }() + + override func viewDidLoad() + { + super.viewDidLoad() + navBar.title = "玛丽莲·梦露" + view.backgroundColor = UIColor.red + view.addSubview(tableView) + tableView.tableHeaderView = topView + if #available(iOS 11.0, *) { + tableView.contentInsetAdjustmentBehavior = .never + } + view.insertSubview(navBar, aboveSubview: tableView) + + // 设置导航栏显示图片 + navBar.barBackgroundImage = UIImage(named: "imageNav") + + // 设置初始导航栏透明度 + navBar.wr_setBackgroundAlpha(alpha: 0) + + // 设置导航栏按钮和标题颜色 + navBar.wr_setTintColor(color: .white) + + // 设置状态栏style + statusBarStyle = .lightContent + } + + deinit { + tableView.delegate = nil + print("FirstVC deinit") + } +} + + +// MARK: - 滑动改变导航栏透明度、标题颜色、左右按钮颜色、状态栏颜色 +extension ImageNavController +{ + func scrollViewDidScroll(_ scrollView: UIScrollView) + { + let offsetY = scrollView.contentOffset.y + if (offsetY > NAVBAR_COLORCHANGE_POINT) + { + let alpha = (offsetY - NAVBAR_COLORCHANGE_POINT) / CGFloat(kNavBarBottom) + navBar.wr_setBackgroundAlpha(alpha: alpha) + } + else + { + navBar.wr_setBackgroundAlpha(alpha: 0) + } + } +} + + +extension ImageNavController:UITableViewDelegate,UITableViewDataSource +{ + func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { + return 40 + } + + func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell + { + let cell = UITableViewCell.init(style: .default, reuseIdentifier: nil) + let str = String(format: "WRNavigationBar %zd", indexPath.row) + cell.textLabel?.text = str + cell.textLabel?.font = UIFont.systemFont(ofSize: 15) + return cell + } + + func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) + { + tableView.deselectRow(at: indexPath, animated: true) + let vc:BaseViewController = BaseViewController() + vc.view.backgroundColor = UIColor.red + let str = String(format: "右滑返回查看效果 ", indexPath.row) + vc.navBar.title = str + navigationController?.pushViewController(vc, animated: true) + } +} diff --git a/WRNavigationBar_swift/WRNavigationBar_swift/Demos/MillcolorGradController.swift b/WRNavigationBar_swift/WRNavigationBar_swift/Demos/MillcolorGradController.swift new file mode 100644 index 0000000..e956dab --- /dev/null +++ b/WRNavigationBar_swift/WRNavigationBar_swift/Demos/MillcolorGradController.swift @@ -0,0 +1,104 @@ +// +// ImageNavController .swift +// WRNavigationBar_swift +// +// Created by wangrui on 2017/4/19. +// Copyright © 2017年 wangrui. All rights reserved. +// +// Github地址:https://github.com/wangrui460/WRNavigationBar_swift + +import UIKit + +private let IMAGE_HEIGHT:CGFloat = 250 +private let NAVBAR_COLORCHANGE_POINT:CGFloat = IMAGE_HEIGHT - CGFloat(kNavBarBottom * 2) + +class MillcolorGradController: BaseViewController +{ + lazy var tableView:UITableView = { + let table:UITableView = UITableView(frame: CGRect.init(x: 0, y: 0, width: kScreenWidth, height: self.view.bounds.height), style: .plain) + table.contentInset = UIEdgeInsetsMake(0, 0, 0, 0); + table.delegate = self + table.dataSource = self + return table + }() + lazy var topView:UIImageView = { + let imgView = UIImageView(image: UIImage(named: "image8")) + imgView.frame = CGRect(x: 0, y: 0, width: kScreenWidth, height: IMAGE_HEIGHT) + imgView.contentMode = UIViewContentMode.scaleAspectFill + imgView.clipsToBounds = true + return imgView + }() + + override func viewDidLoad() + { + super.viewDidLoad() + navBar.title = "奥黛丽·赫本" + view.backgroundColor = UIColor.red + view.addSubview(tableView) + tableView.tableHeaderView = topView + if #available(iOS 11.0, *) { + tableView.contentInsetAdjustmentBehavior = .never + } + view.insertSubview(navBar, aboveSubview: tableView) + + // 设置初始导航栏透明度 + navBar.wr_setBackgroundAlpha(alpha: 0) + + // 设置导航栏按钮和标题颜色 + navBar.wr_setTintColor(color: .white) + + // 设置状态栏style + statusBarStyle = .lightContent + } + + deinit { + tableView.delegate = nil + print("FirstVC deinit") + } +} + + +// MARK: - 滑动改变导航栏透明度、标题颜色、左右按钮颜色、状态栏颜色 +extension MillcolorGradController +{ + func scrollViewDidScroll(_ scrollView: UIScrollView) + { + let offsetY = scrollView.contentOffset.y + if (offsetY > NAVBAR_COLORCHANGE_POINT) + { + let alpha = (offsetY - NAVBAR_COLORCHANGE_POINT) / CGFloat(kNavBarBottom) + navBar.wr_setBackgroundAlpha(alpha: alpha) + } + else + { + navBar.wr_setBackgroundAlpha(alpha: 0) + } + } +} + + +extension MillcolorGradController:UITableViewDelegate,UITableViewDataSource +{ + func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { + return 40 + } + + func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell + { + let cell = UITableViewCell.init(style: .default, reuseIdentifier: nil) + let str = String(format: "WRNavigationBar %zd", indexPath.row) + cell.textLabel?.text = str + cell.textLabel?.font = UIFont.systemFont(ofSize: 15) + return cell + } + + func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) + { + tableView.deselectRow(at: indexPath, animated: true) + let vc:BaseViewController = BaseViewController() + vc.view.backgroundColor = UIColor.red + let str = String(format: "右滑返回查看效果 ", indexPath.row) + vc.navBar.title = str + navigationController?.pushViewController(vc, animated: true) + } +} diff --git a/WRNavigationBar_swift/WRNavigationBar_swift/Demos/MoveListController.swift b/WRNavigationBar_swift/WRNavigationBar_swift/Demos/MoveListController.swift index dcf4c5a..3bbe554 100644 --- a/WRNavigationBar_swift/WRNavigationBar_swift/Demos/MoveListController.swift +++ b/WRNavigationBar_swift/WRNavigationBar_swift/Demos/MoveListController.swift @@ -48,8 +48,6 @@ extension MoveListController: UITableViewDelegate, UITableViewDataSource case 0: str = "超过临界点移动导航栏"; case 1: - str = "超过临界点多少,移动导航栏多少(不会超过44)"; - case 2: str = "没有系统返回按钮的情况"; default: str = "" @@ -70,8 +68,6 @@ extension MoveListController: UITableViewDelegate, UITableViewDataSource case 0: navigationController?.pushViewController(SecondViewController(), animated: true) case 1: - navigationController?.pushViewController(ThirdViewController(), animated: true) - case 2: navigationController?.pushViewController(SixthViewController(), animated: true) default: break diff --git a/WRNavigationBar_swift/WRNavigationBar_swift/Demos/NormalListController.swift b/WRNavigationBar_swift/WRNavigationBar_swift/Demos/NormalListController.swift index 9300018..837f2f9 100644 --- a/WRNavigationBar_swift/WRNavigationBar_swift/Demos/NormalListController.swift +++ b/WRNavigationBar_swift/WRNavigationBar_swift/Demos/NormalListController.swift @@ -9,7 +9,7 @@ import UIKit -let kNavBarBottom = 64 +let kNavBarBottom = WRNavigationBar.navBarBottom() class NormalListController: UIViewController { @@ -23,6 +23,9 @@ class NormalListController: UIViewController tableView.dataSource = self tableView.delegate = self tableView.backgroundColor = UIColor.white + + // 改变标题文字大小 + // navigationController?.navigationBar.titleTextAttributes = [NSFontAttributeName:UIFont.systemFont(ofSize: 22)] } } @@ -53,6 +56,8 @@ extension NormalListController: UITableViewDelegate, UITableViewDataSource str = "QQ我的资料页" case 5: str = "蚂蚁森林" + case 6: + str = "连续多个界面导航栏透明" default: str = "" } @@ -81,6 +86,8 @@ extension NormalListController: UITableViewDelegate, UITableViewDataSource navigationController?.pushViewController(QQMineController(), animated: true) case 5: navigationController?.pushViewController(AntForestController(), animated: true) + case 6: + navigationController?.pushViewController(AllTransparent(), animated: true) default: break } diff --git a/WRNavigationBar_swift/WRNavigationBar_swift/Demos/QQAppController.swift b/WRNavigationBar_swift/WRNavigationBar_swift/Demos/QQAppController.swift index c7f5655..ac53622 100644 --- a/WRNavigationBar_swift/WRNavigationBar_swift/Demos/QQAppController.swift +++ b/WRNavigationBar_swift/WRNavigationBar_swift/Demos/QQAppController.swift @@ -106,7 +106,7 @@ extension QQAppController extension QQAppController: UITableViewDelegate,UITableViewDataSource { func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { - return 15 + return 25 } func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell diff --git a/WRNavigationBar_swift/WRNavigationBar_swift/Demos/QQMineController.swift b/WRNavigationBar_swift/WRNavigationBar_swift/Demos/QQMineController.swift index 7ae6224..84c0e8d 100644 --- a/WRNavigationBar_swift/WRNavigationBar_swift/Demos/QQMineController.swift +++ b/WRNavigationBar_swift/WRNavigationBar_swift/Demos/QQMineController.swift @@ -17,7 +17,7 @@ class QQMineController: UIViewController lazy var tableView:UITableView = { let table:UITableView = UITableView(frame: CGRect.init(x: 0, y: 0, width: kScreenWidth, height: self.view.bounds.height), style: .plain) table.backgroundColor = UIColor.clear - table.contentInset = UIEdgeInsetsMake(-64, 0, 0, 0); + table.contentInset = UIEdgeInsetsMake(-CGFloat(kNavBarBottom), 0, 0, 0); table.delegate = self table.dataSource = self return table @@ -46,7 +46,7 @@ class QQMineController: UIViewController return imgView }() lazy var topView:UIView = { - let view = UIView(frame: CGRect(x: 0, y: 64, width: kScreenWidth, height: IMAGE_HEIGHT)) + let view = UIView(frame: CGRect(x: 0, y: CGFloat(kNavBarBottom), width: kScreenWidth, height: IMAGE_HEIGHT)) view.backgroundColor = UIColor.clear return view }() @@ -122,7 +122,7 @@ extension QQMineController extension QQMineController:UITableViewDelegate,UITableViewDataSource { func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { - return 20 + return 25 } func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell diff --git a/WRNavigationBar_swift/WRNavigationBar_swift/Demos/SecondViewController.swift b/WRNavigationBar_swift/WRNavigationBar_swift/Demos/SecondViewController.swift index 41da9af..366008d 100644 --- a/WRNavigationBar_swift/WRNavigationBar_swift/Demos/SecondViewController.swift +++ b/WRNavigationBar_swift/WRNavigationBar_swift/Demos/SecondViewController.swift @@ -15,7 +15,7 @@ class SecondViewController: UIViewController { lazy var tableView:UITableView = { let table:UITableView = UITableView(frame: CGRect.init(x: 0, y: 0, width: kScreenWidth, height: self.view.bounds.height), style: .plain) - table.contentInset = UIEdgeInsetsMake(-64, 0, 0, 0); + table.contentInset = UIEdgeInsetsMake(-CGFloat(kNavBarBottom), 0, 0, 0); table.delegate = self table.dataSource = self return table diff --git a/WRNavigationBar_swift/WRNavigationBar_swift/Demos/SixthViewController.swift b/WRNavigationBar_swift/WRNavigationBar_swift/Demos/SixthViewController.swift index 7b6bb6f..afb67a7 100644 --- a/WRNavigationBar_swift/WRNavigationBar_swift/Demos/SixthViewController.swift +++ b/WRNavigationBar_swift/WRNavigationBar_swift/Demos/SixthViewController.swift @@ -15,7 +15,7 @@ class SixthViewController: UIViewController { lazy var tableView:UITableView = { let table:UITableView = UITableView(frame: CGRect.init(x: 0, y: 0, width: kScreenWidth, height: self.view.bounds.height), style: .plain) - table.contentInset = UIEdgeInsetsMake(-64, 0, 0, 0); + table.contentInset = UIEdgeInsetsMake(-CGFloat(kNavBarBottom), 0, 0, 0); table.delegate = self table.dataSource = self return table @@ -35,7 +35,7 @@ class SixthViewController: UIViewController self.navigationItem.leftBarButtonItem = UIBarButtonItem(title: "自定义返回", style: .done, target: self, action: #selector(back)) } - func back() { + @objc func back() { _ = self.navigationController?.popViewController(animated: true) } diff --git a/WRNavigationBar_swift/WRNavigationBar_swift/Demos/ThirdViewController.swift b/WRNavigationBar_swift/WRNavigationBar_swift/Demos/ThirdViewController.swift deleted file mode 100644 index f1cc156..0000000 --- a/WRNavigationBar_swift/WRNavigationBar_swift/Demos/ThirdViewController.swift +++ /dev/null @@ -1,164 +0,0 @@ -// -// ThirdViewController.swift -// WRNavigationBar_swift -// -// Created by wangrui on 2017/4/21. -// Copyright © 2017年 wangrui. All rights reserved. -// -// Github地址:https://github.com/wangrui460/WRNavigationBar_swift - -import UIKit - - -class ThirdViewController: UIViewController -{ - fileprivate var NAVBAR_TRANSLATION_POINT:CGFloat = 0 - fileprivate var lastOffsetY:CGFloat = 0 - - lazy var tableView:UITableView = { - let table:UITableView = UITableView(frame: CGRect.init(x: 0, y: 0, width: kScreenWidth, height: self.view.bounds.height), style: .plain) - table.contentInset = UIEdgeInsetsMake(-64, 0, 0, 0); - table.delegate = self - table.dataSource = self - return table - }() - lazy var imageView:UIImageView = { - let imgView = UIImageView(image: UIImage(named: "image2")) - return imgView - }() - - override func viewDidLoad() - { - super.viewDidLoad() - title = "WR" - view.backgroundColor = UIColor.red - view.addSubview(tableView) - tableView.tableHeaderView = imageView - } - - deinit { - tableView.delegate = nil - print("ThirdVC deinit") - } -} - - -// MARK: - viewWillAppear .. ScrollViewDidScroll -extension ThirdViewController -{ - override func viewDidAppear(_ animated: Bool) - { - super.viewDidAppear(animated) - tableView.delegate = self; - } - - override func viewWillDisappear(_ animated: Bool) - { - super.viewWillDisappear(animated) - tableView.delegate = nil - navigationController?.navigationBar.wr_setTranslationY(translationY: 0) - } - - func scrollViewDidEndDecelerating(_ scrollView: UIScrollView) - { - stopScroll(scrollView) - } - - func scrollViewDidEndDragging(_ scrollView: UIScrollView, willDecelerate decelerate: Bool) - { - if decelerate == false { - stopScroll(scrollView) - } - } - - func stopScroll(_ scrollView: UIScrollView) - { - let offsetY = scrollView.contentOffset.y - // 向上滑动的距离 - let scrollUpHeight = offsetY - NAVBAR_TRANSLATION_POINT - if (scrollUpHeight >= 22) - { // 超过导航栏高度的一半,只显示状态栏 - UIView.animate(withDuration: 0.3, animations: { [weak self] in - if let weakSelf = self { - weakSelf.setNavigationBarTransform(scrollUpHeight: 44) - } - }) - print("point:\(NAVBAR_TRANSLATION_POINT)") - } - else - { // 没有超过导航栏高度的一半,导航栏全部显示 - UIView.animate(withDuration: 0.3, animations: { [weak self] in - if let weakSelf = self { - weakSelf.setNavigationBarTransform(scrollUpHeight: 0) - } - }) - print("point:\(NAVBAR_TRANSLATION_POINT)") - } - NAVBAR_TRANSLATION_POINT = offsetY - } - - func scrollViewDidScroll(_ scrollView: UIScrollView) - { - let offsetY = scrollView.contentOffset.y - // 向上滑动的距离 - let isScrollup = (offsetY - lastOffsetY) > 0 ? true : false - let scrollUpHeight = (offsetY - NAVBAR_TRANSLATION_POINT) > 44 ? 44 : (offsetY - NAVBAR_TRANSLATION_POINT) - let curTransformY = navigationController?.navigationBar.wr_getTranslationY() - - - if isScrollup == true - { // 上滑 - if curTransformY == -44 { - return - } - else - { - if offsetY > 0 { - setNavigationBarTransform(scrollUpHeight: scrollUpHeight) - } - } - } - else - { // 下滑 - UIView.animate(withDuration: 0.3, animations: { [weak self] in - if let weakSelf = self { - weakSelf.setNavigationBarTransform(scrollUpHeight: 0) - } - }) - } - - lastOffsetY = offsetY - } - - func setNavigationBarTransform(scrollUpHeight:CGFloat) - { - navigationController?.navigationBar.wr_setTranslationY(translationY: -scrollUpHeight) - // 有系统的返回按钮,所以 hasSystemBackIndicator = YES - let curTransformY = navigationController?.navigationBar.wr_getTranslationY() ?? 0 - navigationController?.navigationBar.wr_setBarButtonItemsAlpha(alpha: 1 - (-curTransformY / 44.0), hasSystemBackIndicator: true) - } -} - - -extension ThirdViewController:UITableViewDelegate,UITableViewDataSource -{ - func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { - return 15 - } - - func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell - { - let cell = UITableViewCell.init(style: .default, reuseIdentifier: nil) - let str = String(format: "WRNavigationBar %zd", indexPath.row) - cell.textLabel?.text = str - cell.textLabel?.font = UIFont.systemFont(ofSize: 15) - return cell - } - - func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) - { - tableView.deselectRow(at: indexPath, animated: true) - - // 做成这种样式,最好不要有点击事件 - } -} diff --git a/WRNavigationBar_swift/WRNavigationBar_swift/Demos/WeiBoMineController.swift b/WRNavigationBar_swift/WRNavigationBar_swift/Demos/WeiBoMineController.swift index 46fcfa9..d121f1a 100644 --- a/WRNavigationBar_swift/WRNavigationBar_swift/Demos/WeiBoMineController.swift +++ b/WRNavigationBar_swift/WRNavigationBar_swift/Demos/WeiBoMineController.swift @@ -16,7 +16,7 @@ class WeiBoMineController: UIViewController { lazy var tableView:UITableView = { let table:UITableView = UITableView(frame: CGRect.init(x: 0, y: 0, width: kScreenWidth, height: self.view.bounds.height), style: .plain) - table.contentInset = UIEdgeInsetsMake(-64, 0, 0, 0); + table.contentInset = UIEdgeInsetsMake(-CGFloat(kNavBarBottom), 0, 0, 0); table.delegate = self table.dataSource = self return table @@ -43,7 +43,7 @@ class WeiBoMineController: UIViewController let label = UILabel() label.backgroundColor = UIColor.clear label.textColor = UIColor.white - label.text = "关注 121 | 粉丝 17" + label.text = "关注 121 | 粉丝 891" label.textAlignment = .center label.font = .boldSystemFont(ofSize: 14) return label @@ -90,6 +90,9 @@ class WeiBoMineController: UIViewController // 设置导航栏按钮和标题颜色 navBarTintColor = .white + + // 如果需要隐藏导航栏底部分割线,设置 hideShadowImage 为true + // hideShadowImage = true } deinit { diff --git a/WRNavigationBar_swift/WRNavigationBar_swift/Demos/ZhiHuController.swift b/WRNavigationBar_swift/WRNavigationBar_swift/Demos/ZhiHuController.swift index 2457263..ffb14af 100644 --- a/WRNavigationBar_swift/WRNavigationBar_swift/Demos/ZhiHuController.swift +++ b/WRNavigationBar_swift/WRNavigationBar_swift/Demos/ZhiHuController.swift @@ -102,7 +102,7 @@ extension ZhiHuController extension ZhiHuController: UITableViewDelegate,UITableViewDataSource { func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { - return 15 + return 25 } func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell diff --git a/WRNavigationBar_swift/WRNavigationBar_swift/WRNavigationBar/WRCustomNavigationBar.swift b/WRNavigationBar_swift/WRNavigationBar_swift/WRNavigationBar/WRCustomNavigationBar.swift new file mode 100644 index 0000000..5066e10 --- /dev/null +++ b/WRNavigationBar_swift/WRNavigationBar_swift/WRNavigationBar/WRCustomNavigationBar.swift @@ -0,0 +1,301 @@ +// +// WRCustomNavigationBar.swift +// WRNavigationBar_swift +// +// Created by itwangrui on 2017/11/25. +// Copyright © 2017年 wangrui. All rights reserved. +// + +import UIKit + +fileprivate let WRDefaultTitleSize:CGFloat = 18 +fileprivate let WRDefaultTitleColor = UIColor.black +fileprivate let WRDefaultBackgroundColor = UIColor.white +fileprivate let WRScreenWidth = UIScreen.main.bounds.size.width + + +// MARK: - Router +extension UIViewController +{ + // A页面 弹出 登录页面B + // presentedViewController: A页面 + // presentingViewController: B页面 + + func wr_toLastViewController(animated:Bool) + { + if self.navigationController != nil + { + if self.navigationController?.viewControllers.count == 1 + { + self.dismiss(animated: animated, completion: nil) + } else { + self.navigationController?.popViewController(animated: animated) + } + } + else if self.presentingViewController != nil { + self.dismiss(animated: animated, completion: nil) + } + } + + class func wr_currentViewController() -> UIViewController + { + if let rootVC = UIApplication.shared.delegate?.window??.rootViewController { + return self.wr_currentViewController(from: rootVC) + } else { + return UIViewController() + } + } + + class func wr_currentViewController(from fromVC:UIViewController) -> UIViewController + { + if fromVC.isKind(of: UINavigationController.self) { + let navigationController = fromVC as! UINavigationController + return wr_currentViewController(from: navigationController.viewControllers.last!) + } + else if fromVC.isKind(of: UITabBarController.self) { + let tabBarController = fromVC as! UITabBarController + return wr_currentViewController(from: tabBarController.selectedViewController!) + } + else if fromVC.presentedViewController != nil { + return wr_currentViewController(from:fromVC.presentingViewController!) + } + else { + return fromVC + } + } +} + + +//////////////////////////////////////////////////////////////////////////////////////////////////////////// +class WRCustomNavigationBar: UIView +{ + var onClickLeftButton:(()->())? + var onClickRightButton:(()->())? + var title:String? { + willSet { + titleLabel.isHidden = false + titleLabel.text = newValue + } + } + var titleLabelColor:UIColor? { + willSet { + titleLabel.textColor = newValue + } + } + var titleLabelFont:UIFont? { + willSet { + titleLabel.font = newValue + } + } + var barBackgroundColor:UIColor? { + willSet { + backgroundImageView.isHidden = true + backgroundView.isHidden = false + backgroundView.backgroundColor = newValue + } + } + var barBackgroundImage:UIImage? { + willSet { + backgroundView.isHidden = true + backgroundImageView.isHidden = false + backgroundImageView.image = newValue + } + } + + // fileprivate UI variable + fileprivate lazy var titleLabel:UILabel = { + let label = UILabel() + label.textColor = WRDefaultTitleColor + label.font = UIFont.systemFont(ofSize: WRDefaultTitleSize) + label.textAlignment = .center + label.isHidden = true + return label + }() + + fileprivate lazy var leftButton:UIButton = { + let button = UIButton() + button.imageView?.contentMode = .center + button.isHidden = true + button.addTarget(self, action: #selector(clickBack), for: .touchUpInside) + return button + }() + + fileprivate lazy var rightButton:UIButton = { + let button = UIButton() + button.imageView?.contentMode = .center + button.isHidden = true + button.addTarget(self, action: #selector(clickRight), for: .touchUpInside) + return button + }() + + fileprivate lazy var bottomLine:UIView = { + let view = UIView() + view.backgroundColor = UIColor(red: (218.0/255.0), green: (218.0/255.0), blue: (218.0/255.0), alpha: 1.0) + return view + }() + + fileprivate lazy var backgroundView:UIView = { + let view = UIView() + return view + }() + + fileprivate lazy var backgroundImageView:UIImageView = { + let imgView = UIImageView() + imgView.isHidden = true + return imgView + }() + + // fileprivate other variable + fileprivate static var isIphoneX:Bool { + get { + return UIScreen.main.bounds.equalTo(CGRect(x: 0, y: 0, width: 375, height: 812)) + } + } + fileprivate static var navBarBottom:Int { + get { + return isIphoneX ? 88 : 64 + } + } + + // init + class func CustomNavigationBar() -> WRCustomNavigationBar { + let frame = CGRect(x: 0, y: 0, width: WRScreenWidth, height: CGFloat(navBarBottom)) + return WRCustomNavigationBar(frame: frame) + } + override init(frame: CGRect) { + super.init(frame: frame) + setupView() + } + required init?(coder aDecoder: NSCoder) { + super.init(coder: aDecoder) + setupView() + } + + func setupView() + { + addSubview(backgroundView) + addSubview(backgroundImageView) + addSubview(leftButton) + addSubview(titleLabel) + addSubview(rightButton) + addSubview(bottomLine) + updateFrame() + backgroundColor = UIColor.clear + backgroundView.backgroundColor = WRDefaultBackgroundColor + } + func updateFrame() + { + let top:CGFloat = WRCustomNavigationBar.isIphoneX ? 44 : 20 + let margin:CGFloat = 0 + let buttonHeight:CGFloat = 44 + let buttonWidth:CGFloat = 44 + let titleLabelHeight:CGFloat = 44 + let titleLabelWidth:CGFloat = 180 + + backgroundView.frame = self.bounds + backgroundImageView.frame = self.bounds + leftButton.frame = CGRect(x: margin, y: top, width: buttonWidth, height: buttonHeight) + rightButton.frame = CGRect(x: WRScreenWidth-buttonWidth-margin, y: top, width: buttonWidth, height: buttonHeight) + titleLabel.frame = CGRect(x: (WRScreenWidth-titleLabelWidth)/2.0, y: top, width: titleLabelWidth, height: titleLabelHeight) + bottomLine.frame = CGRect(x: 0, y: bounds.height-0.5, width: WRScreenWidth, height: 0.5) + } +} + + +extension WRCustomNavigationBar +{ + func wr_setBottomLineHidden(hidden:Bool) { + bottomLine.isHidden = hidden + } + func wr_setBackgroundAlpha(alpha:CGFloat) { + backgroundView.alpha = alpha + backgroundImageView.alpha = alpha + bottomLine.alpha = alpha + } + func wr_setTintColor(color:UIColor) { + leftButton.setTitleColor(color, for: .normal) + rightButton.setTitleColor(color, for: .normal) + titleLabel.textColor = color + } + + // 左右按钮共有方法 + func wr_setLeftButton(normal:UIImage, highlighted:UIImage) { + wr_setLeftButton(normal: normal, highlighted: highlighted, title: nil, titleColor: nil) + } + func wr_setLeftButton(image:UIImage) { + wr_setLeftButton(normal: image, highlighted: image, title: nil, titleColor: nil) + } + func wr_setLeftButton(title:String, titleColor:UIColor) { + wr_setLeftButton(normal: nil, highlighted: nil, title: title, titleColor: titleColor) + } + + func wr_setRightButton(normal:UIImage, highlighted:UIImage) { + wr_setRightButton(normal: normal, highlighted: highlighted, title: nil, titleColor: nil) + } + func wr_setRightButton(image:UIImage) { + wr_setRightButton(normal: image, highlighted: image, title: nil, titleColor: nil) + } + func wr_setRightButton(title:String, titleColor:UIColor) { + wr_setRightButton(normal: nil, highlighted: nil, title: title, titleColor: titleColor) + } + + + // 左右按钮私有方法 + private func wr_setLeftButton(normal:UIImage?, highlighted:UIImage?, title:String?, titleColor:UIColor?) { + leftButton.isHidden = false + leftButton.setImage(normal, for: .normal) + leftButton.setImage(highlighted, for: .highlighted) + leftButton.setTitle(title, for: .normal) + leftButton.setTitleColor(titleColor, for: .normal) + } + private func wr_setRightButton(normal:UIImage?, highlighted:UIImage?, title:String?, titleColor:UIColor?) { + rightButton.isHidden = false + rightButton.setImage(normal, for: .normal) + rightButton.setImage(highlighted, for: .highlighted) + rightButton.setTitle(title, for: .normal) + rightButton.setTitleColor(titleColor, for: .normal) + } +} + + +// MARK: - 导航栏左右按钮事件 +extension WRCustomNavigationBar +{ + @objc func clickBack() { + if let onClickBack = onClickLeftButton { + onClickBack() + } else { + let currentVC = UIViewController.wr_currentViewController() + currentVC.wr_toLastViewController(animated: true) + } + } + @objc func clickRight() { + if let onClickRight = onClickRightButton { + onClickRight() + } + } +} + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/WRNavigationBar_swift/WRNavigationBar_swift/WRNavigationBar/WRCycleScrollView/WRCycleScrollView.swift b/WRNavigationBar_swift/WRNavigationBar_swift/WRNavigationBar/WRCycleScrollView/WRCycleScrollView.swift index 3768856..47935a3 100644 --- a/WRNavigationBar_swift/WRNavigationBar_swift/WRNavigationBar/WRCycleScrollView/WRCycleScrollView.swift +++ b/WRNavigationBar_swift/WRNavigationBar_swift/WRNavigationBar/WRCycleScrollView/WRCycleScrollView.swift @@ -237,7 +237,7 @@ extension WRCycleScrollView } // 执行这个方法的前提是 isAutoScroll = true - func changeCycleCell() + @objc func changeCycleCell() { if canChangeCycleCell == true { diff --git a/WRNavigationBar_swift/WRNavigationBar_swift/WRNavigationBar/WRNavigationBar.swift b/WRNavigationBar_swift/WRNavigationBar_swift/WRNavigationBar/WRNavigationBar.swift index c1af906..1322e4c 100644 --- a/WRNavigationBar_swift/WRNavigationBar_swift/WRNavigationBar/WRNavigationBar.swift +++ b/WRNavigationBar_swift/WRNavigationBar_swift/WRNavigationBar/WRNavigationBar.swift @@ -9,10 +9,11 @@ import UIKit -extension UINavigationBar +extension UINavigationBar:WRAwakeProtocol { fileprivate struct AssociatedKeys { - static var backgroundView:UIView = UIView() + static var backgroundView: UIView = UIView() + static var backgroundImageView: UIImageView = UIImageView() } fileprivate var backgroundView:UIView? { @@ -27,14 +28,46 @@ extension UINavigationBar } } + fileprivate var backgroundImageView:UIImageView? { + get { + guard let bgImageView = objc_getAssociatedObject(self, &AssociatedKeys.backgroundImageView) as? UIImageView else { + return nil + } + return bgImageView + } + set { + objc_setAssociatedObject(self, &AssociatedKeys.backgroundImageView, newValue, .OBJC_ASSOCIATION_RETAIN_NONATOMIC) + } + } + + // set navigationBar backgroundImage + fileprivate func wr_setBackgroundImage(image:UIImage) + { + backgroundView?.removeFromSuperview() + backgroundView = nil + if (backgroundImageView == nil) + { + // add a image(nil color) to _UIBarBackground make it clear + setBackgroundImage(UIImage(), for: .default) + backgroundImageView = UIImageView(frame: CGRect(x: 0, y: 0, width: Int(bounds.width), height: WRNavigationBar.navBarBottom())) + backgroundImageView?.autoresizingMask = .flexibleWidth + // _UIBarBackground is first subView for navigationBar + subviews.first?.insertSubview(backgroundImageView ?? UIImageView(), at: 0) + } + backgroundImageView?.image = image + } + // set navigationBar barTintColor fileprivate func wr_setBackgroundColor(color:UIColor) { + backgroundImageView?.removeFromSuperview() + backgroundImageView = nil if (backgroundView == nil) { // add a image(nil color) to _UIBarBackground make it clear setBackgroundImage(UIImage(), for: .default) - backgroundView = UIView(frame: CGRect(x: 0, y: 0, width: Int(bounds.width), height: 64)) + backgroundView = UIView(frame: CGRect(x: 0, y: 0, width: Int(bounds.width), height: WRNavigationBar.navBarBottom())) + backgroundView?.autoresizingMask = .flexibleWidth // _UIBarBackground is first subView for navigationBar subviews.first?.insertSubview(backgroundView ?? UIView(), at: 0) } @@ -44,8 +77,17 @@ extension UINavigationBar // set _UIBarBackground alpha (_UIBarBackground subviews alpha <= _UIBarBackground alpha) fileprivate func wr_setBackgroundAlpha(alpha:CGFloat) { - let barBackgroundView = subviews[0] - barBackgroundView.alpha = alpha + if let barBackgroundView = subviews.first + { + if #available(iOS 11.0, *) + { // sometimes we can't change _UIBarBackground alpha + for view in barBackgroundView.subviews { + view.alpha = alpha + } + } else { + barBackgroundView.alpha = alpha + } + } } // 设置导航栏所有BarButtonItem的透明度 @@ -104,15 +146,73 @@ extension UINavigationBar { return transform.ty } + + // call swizzling methods active 主动调用交换方法 + private static let onceToken = UUID().uuidString + public static func wrAwake() + { + DispatchQueue.once(token: onceToken) + { + let needSwizzleSelectorArr = [ + #selector(setter: titleTextAttributes) + ] + + for selector in needSwizzleSelectorArr { + let str = ("wr_" + selector.description) + if let originalMethod = class_getInstanceMethod(self, selector), + let swizzledMethod = class_getInstanceMethod(self, Selector(str)) { + method_exchangeImplementations(originalMethod, swizzledMethod) + } + } + } + } + + //========================================================================== + // MARK: swizzling pop + //========================================================================== + @objc func wr_setTitleTextAttributes(_ newTitleTextAttributes:[String : Any]?) + { + guard var attributes = newTitleTextAttributes else { + return + } + + guard let originTitleTextAttributes = titleTextAttributes else { + wr_setTitleTextAttributes(attributes) + return + } + + var titleColor:UIColor? + for attribute in originTitleTextAttributes { + if attribute.key == NSAttributedStringKey.foregroundColor { + titleColor = attribute.value as? UIColor + break + } + } + + guard let originTitleColor = titleColor else { + wr_setTitleTextAttributes(attributes) + return + } + + if attributes[NSAttributedStringKey.foregroundColor.rawValue] == nil { + attributes.updateValue(originTitleColor, forKey: NSAttributedStringKey.foregroundColor.rawValue) + } + wr_setTitleTextAttributes(attributes) + } } //========================================================================== // MARK: - UINavigationController //========================================================================== -extension UINavigationController +extension UINavigationController: WRFatherAwakeProtocol { override open var preferredStatusBarStyle: UIStatusBarStyle { - return topViewController?.statusBarStyle ?? UIColor.defaultStatusBarStyle + return topViewController?.statusBarStyle ?? WRNavigationBar.defaultStatusBarStyle + } + + fileprivate func setNeedsNavigationBarUpdate(backgroundImage: UIImage) + { + navigationBar.wr_setBackgroundImage(image: backgroundImage) } fileprivate func setNeedsNavigationBarUpdate(barTintColor: UIColor) @@ -128,43 +228,55 @@ extension UINavigationController fileprivate func setNeedsNavigationBarUpdate(tintColor: UIColor) { navigationBar.tintColor = tintColor } + + fileprivate func setNeedsNavigationBarUpdate(hideShadowImage: Bool) + { + navigationBar.shadowImage = (hideShadowImage == true) ? UIImage() : nil + } - fileprivate func setNeedsNavigationBarUpdate(titleColor: UIColor) { - navigationBar.titleTextAttributes = [NSForegroundColorAttributeName:titleColor] + fileprivate func setNeedsNavigationBarUpdate(titleColor: UIColor) + { + guard let titleTextAttributes = navigationBar.titleTextAttributes else { + navigationBar.titleTextAttributes = [NSAttributedStringKey.foregroundColor:titleColor] + return + } + + var newTitleTextAttributes = titleTextAttributes + newTitleTextAttributes.updateValue(titleColor, forKey: NSAttributedStringKey.foregroundColor) + navigationBar.titleTextAttributes = newTitleTextAttributes } fileprivate func updateNavigationBar(fromVC: UIViewController?, toVC: UIViewController?, progress: CGFloat) { // change navBarBarTintColor - let fromBarTintColor = fromVC?.navBarBarTintColor ?? .defaultNavBarBarTintColor - let toBarTintColor = toVC?.navBarBarTintColor ?? .defaultNavBarBarTintColor - let newBarTintColor = UIColor.middleColor(fromColor: fromBarTintColor, toColor: toBarTintColor, percent: progress) + let fromBarTintColor = fromVC?.navBarBarTintColor ?? WRNavigationBar.defaultNavBarBarTintColor + let toBarTintColor = toVC?.navBarBarTintColor ?? WRNavigationBar.defaultNavBarBarTintColor + let newBarTintColor = WRNavigationBar.middleColor(fromColor: fromBarTintColor, toColor: toBarTintColor, percent: progress) setNeedsNavigationBarUpdate(barTintColor: newBarTintColor) // change navBarTintColor - let fromTintColor = fromVC?.navBarTintColor ?? .defaultNavBarTintColor - let toTintColor = toVC?.navBarTintColor ?? .defaultNavBarTintColor - let newTintColor = UIColor.middleColor(fromColor: fromTintColor, toColor: toTintColor, percent: progress) + let fromTintColor = fromVC?.navBarTintColor ?? WRNavigationBar.defaultNavBarTintColor + let toTintColor = toVC?.navBarTintColor ?? WRNavigationBar.defaultNavBarTintColor + let newTintColor = WRNavigationBar.middleColor(fromColor: fromTintColor, toColor: toTintColor, percent: progress) setNeedsNavigationBarUpdate(tintColor: newTintColor) // change navBarTitleColor - let fromTitleColor = fromVC?.navBarTitleColor ?? .defaultNavBarTitleColor - let toTitleColor = toVC?.navBarTitleColor ?? .defaultNavBarTitleColor - let newTitleColor = UIColor.middleColor(fromColor: fromTitleColor, toColor: toTitleColor, percent: progress) - setNeedsNavigationBarUpdate(titleColor: newTitleColor) +// let fromTitleColor = fromVC?.navBarTitleColor ?? WRNavigationBar.defaultNavBarTitleColor +// let toTitleColor = toVC?.navBarTitleColor ?? WRNavigationBar.defaultNavBarTitleColor +// let newTitleColor = WRNavigationBar.middleColor(fromColor: fromTitleColor, toColor: toTitleColor, percent: progress) +// setNeedsNavigationBarUpdate(titleColor: newTitleColor) // change navBar _UIBarBackground alpha - let fromBarBackgroundAlpha = fromVC?.navBarBackgroundAlpha ?? UIColor.defaultBackgroundAlpha - let toBarBackgroundAlpha = toVC?.navBarBackgroundAlpha ?? UIColor.defaultBackgroundAlpha - let newBarBackgroundAlpha = UIColor.middleAlpha(fromAlpha: fromBarBackgroundAlpha, toAlpha: toBarBackgroundAlpha, percent: progress) + let fromBarBackgroundAlpha = fromVC?.navBarBackgroundAlpha ?? WRNavigationBar.defaultBackgroundAlpha + let toBarBackgroundAlpha = toVC?.navBarBackgroundAlpha ?? WRNavigationBar.defaultBackgroundAlpha + let newBarBackgroundAlpha = WRNavigationBar.middleAlpha(fromAlpha: fromBarBackgroundAlpha, toAlpha: toBarBackgroundAlpha, percent: progress) setNeedsNavigationBarUpdate(barBackgroundAlpha: newBarBackgroundAlpha) } // call swizzling methods active 主动调用交换方法 private static let onceToken = UUID().uuidString - open override class func initialize() + public static func fatherAwake() { - guard self == UINavigationController.self else { return } DispatchQueue.once(token: onceToken) { let needSwizzleSelectorArr = [ @@ -173,13 +285,14 @@ extension UINavigationController #selector(popToRootViewController), #selector(pushViewController) ] - + for selector in needSwizzleSelectorArr { // _updateInteractiveTransition: => wr_updateInteractiveTransition: let str = ("wr_" + selector.description).replacingOccurrences(of: "__", with: "_") - let originalMethod = class_getInstanceMethod(self, selector) - let swizzledMethod = class_getInstanceMethod(self, Selector(str)) - method_exchangeImplementations(originalMethod, swizzledMethod) + if let originalMethod = class_getInstanceMethod(self, selector), + let swizzledMethod = class_getInstanceMethod(self, Selector(str)) { + method_exchangeImplementations(originalMethod, swizzledMethod) + } } } } @@ -198,8 +311,9 @@ extension UINavigationController } // swizzling system method: popToViewController - func wr_popToViewController(_ viewController: UIViewController, animated: Bool) -> [UIViewController]? + @objc func wr_popToViewController(_ viewController: UIViewController, animated: Bool) -> [UIViewController]? { + setNeedsNavigationBarUpdate(titleColor: viewController.navBarTitleColor) var displayLink:CADisplayLink? = CADisplayLink(target: self, selector: #selector(popNeedDisplay)) // UITrackingRunLoopMode: 界面跟踪 Mode,用于 ScrollView 追踪触摸滑动,保证界面滑动时不受其他 Mode 影响 // NSRunLoopCommonModes contains kCFRunLoopDefaultMode and UITrackingRunLoopMode @@ -217,7 +331,7 @@ extension UINavigationController } // swizzling system method: popToRootViewControllerAnimated - func wr_popToRootViewControllerAnimated(_ animated: Bool) -> [UIViewController]? + @objc func wr_popToRootViewControllerAnimated(_ animated: Bool) -> [UIViewController]? { var displayLink:CADisplayLink? = CADisplayLink(target: self, selector: #selector(popNeedDisplay)) displayLink?.add(to: RunLoop.main, forMode: .commonModes) @@ -234,7 +348,7 @@ extension UINavigationController } // change navigationBar barTintColor smooth before pop to current VC finished - func popNeedDisplay() + @objc fileprivate func popNeedDisplay() { guard let topViewController = topViewController, let coordinator = topViewController.transitionCoordinator else { @@ -264,10 +378,10 @@ extension UINavigationController } // swizzling system method: pushViewController - func wr_pushViewController(_ viewController: UIViewController, animated: Bool) + @objc func wr_pushViewController(_ viewController: UIViewController, animated: Bool) { var displayLink:CADisplayLink? = CADisplayLink(target: self, selector: #selector(pushNeedDisplay)) - displayLink?.add(to: RunLoop.main, forMode: .defaultRunLoopMode) + displayLink?.add(to: RunLoop.main, forMode: .commonModes) CATransaction.setCompletionBlock { displayLink?.invalidate() displayLink = nil @@ -281,7 +395,7 @@ extension UINavigationController } // change navigationBar barTintColor smooth before push to current VC finished or before pop to current VC finished - func pushNeedDisplay() + @objc fileprivate func pushNeedDisplay() { guard let topViewController = topViewController, let coordinator = topViewController.transitionCoordinator else { @@ -330,8 +444,8 @@ extension UINavigationController: UINavigationBarDelegate private func dealInteractionChanges(_ context: UIViewControllerTransitionCoordinatorContext) { let animations: (UITransitionContextViewControllerKey) -> () = { - let curColor = context.viewController(forKey: $0)?.navBarBarTintColor ?? UIColor.defaultNavBarBarTintColor - let curAlpha = context.viewController(forKey: $0)?.navBarBackgroundAlpha ?? UIColor.defaultBackgroundAlpha + let curColor = context.viewController(forKey: $0)?.navBarBarTintColor ?? WRNavigationBar.defaultNavBarBarTintColor + let curAlpha = context.viewController(forKey: $0)?.navBarBackgroundAlpha ?? WRNavigationBar.defaultBackgroundAlpha self.setNeedsNavigationBarUpdate(barTintColor: curColor) self.setNeedsNavigationBarUpdate(barBackgroundAlpha: curAlpha) @@ -356,7 +470,7 @@ extension UINavigationController: UINavigationBarDelegate } // swizzling system method: _updateInteractiveTransition - func wr_updateInteractiveTransition(_ percentComplete: CGFloat) + @objc func wr_updateInteractiveTransition(_ percentComplete: CGFloat) { guard let topViewController = topViewController, let coordinator = topViewController.transitionCoordinator else { @@ -375,24 +489,27 @@ extension UINavigationController: UINavigationBarDelegate //============================================================================= // MARK: - store navigationBar barTintColor and tintColor every viewController //============================================================================= -extension UIViewController +extension UIViewController: WRAwakeProtocol { fileprivate struct AssociatedKeys { static var pushToCurrentVCFinished: Bool = false static var pushToNextVCFinished:Bool = false - static var navBarBarTintColor: UIColor = UIColor.defaultNavBarBarTintColor + static var navBarBackgroundImage: UIImage = UIImage() + + static var navBarBarTintColor: UIColor = WRNavigationBar.defaultNavBarBarTintColor static var navBarBackgroundAlpha:CGFloat = 1.0 - static var navBarTintColor: UIColor = UIColor.defaultNavBarTintColor - static var navBarTitleColor: UIColor = UIColor.defaultNavBarTitleColor + static var navBarTintColor: UIColor = WRNavigationBar.defaultNavBarTintColor + static var navBarTitleColor: UIColor = WRNavigationBar.defaultNavBarTitleColor static var statusBarStyle: UIStatusBarStyle = UIStatusBarStyle.default + static var navBarShadowImageHidden: Bool = false static var customNavBar: UINavigationBar = UINavigationBar() } // navigationBar barTintColor can not change by currentVC before fromVC push to currentVC finished - var pushToCurrentVCFinished:Bool { + fileprivate var pushToCurrentVCFinished:Bool { get { guard let isFinished = objc_getAssociatedObject(self, &AssociatedKeys.pushToCurrentVCFinished) as? Bool else { return false @@ -405,7 +522,7 @@ extension UIViewController } // navigationBar barTintColor can not change by currentVC when currentVC push to nextVC finished - var pushToNextVCFinished:Bool { + fileprivate var pushToNextVCFinished:Bool { get { guard let isFinished = objc_getAssociatedObject(self, &AssociatedKeys.pushToNextVCFinished) as? Bool else { return false @@ -417,11 +534,31 @@ extension UIViewController } } + // you can set navigationBar backgroundImage + var navBarBackgroundImage: UIImage? + { + get { + guard let bgImage = objc_getAssociatedObject(self, &AssociatedKeys.navBarBackgroundImage) as? UIImage else { + return WRNavigationBar.defaultNavBarBackgroundImage + } + return bgImage + } +// set { +// if customNavBar.isKind(of: UINavigationBar.self) { +// let navBar = customNavBar as! UINavigationBar +// navBar.wr_setBackgroundImage(image: newValue!) +// } +// else { +// objc_setAssociatedObject(self, &AssociatedKeys.navBarBackgroundImage, newValue, .OBJC_ASSOCIATION_RETAIN_NONATOMIC) +// } +// } + } + // navigationBar barTintColor var navBarBarTintColor: UIColor { get { guard let barTintColor = objc_getAssociatedObject(self, &AssociatedKeys.navBarBarTintColor) as? UIColor else { - return UIColor.defaultNavBarBarTintColor + return WRNavigationBar.defaultNavBarBarTintColor } return barTintColor } @@ -429,12 +566,11 @@ extension UIViewController objc_setAssociatedObject(self, &AssociatedKeys.navBarBarTintColor, newValue, .OBJC_ASSOCIATION_RETAIN_NONATOMIC) if customNavBar.isKind(of: UINavigationBar.self) { - let navBar = customNavBar as! UINavigationBar - navBar.wr_setBackgroundColor(color: newValue) +// let navBar = customNavBar as! UINavigationBar +// navBar.wr_setBackgroundColor(color: newValue) } - else - { - if pushToCurrentVCFinished == true && pushToNextVCFinished == false { + else { + if canUpdateNavBarBarTintColorOrBackgroundAlpha == true { navigationController?.setNeedsNavigationBarUpdate(barTintColor: newValue) } } @@ -453,23 +589,32 @@ extension UIViewController objc_setAssociatedObject(self, &AssociatedKeys.navBarBackgroundAlpha, newValue, .OBJC_ASSOCIATION_RETAIN_NONATOMIC) if customNavBar.isKind(of: UINavigationBar.self) { - let navBar = customNavBar as! UINavigationBar - navBar.wr_setBackgroundAlpha(alpha: newValue) +// let navBar = customNavBar as! UINavigationBar +// navBar.wr_setBackgroundAlpha(alpha: newValue) } - else - { - if pushToCurrentVCFinished == true && pushToNextVCFinished == false { + else { + if canUpdateNavBarBarTintColorOrBackgroundAlpha == true { navigationController?.setNeedsNavigationBarUpdate(barBackgroundAlpha: newValue) } } } } + private var canUpdateNavBarBarTintColorOrBackgroundAlpha:Bool { + get { + let isRootViewController = self.navigationController?.viewControllers.first == self + if (pushToCurrentVCFinished == true || isRootViewController == true) && pushToNextVCFinished == false { + return true + } else { + return false + } + } + } // navigationBar tintColor var navBarTintColor: UIColor { get { guard let tintColor = objc_getAssociatedObject(self, &AssociatedKeys.navBarTintColor) as? UIColor else { - return UIColor.defaultNavBarTintColor + return WRNavigationBar.defaultNavBarTintColor } return tintColor } @@ -477,8 +622,8 @@ extension UIViewController objc_setAssociatedObject(self, &AssociatedKeys.navBarTintColor, newValue, .OBJC_ASSOCIATION_RETAIN_NONATOMIC) if customNavBar.isKind(of: UINavigationBar.self) { - let navBar = customNavBar as! UINavigationBar - navBar.tintColor = newValue +// let navBar = customNavBar as! UINavigationBar +// navBar.tintColor = newValue } else { @@ -493,7 +638,7 @@ extension UIViewController var navBarTitleColor: UIColor { get { guard let titleColor = objc_getAssociatedObject(self, &AssociatedKeys.navBarTitleColor) as? UIColor else { - return UIColor.defaultNavBarTitleColor + return WRNavigationBar.defaultNavBarTitleColor } return titleColor } @@ -501,8 +646,8 @@ extension UIViewController objc_setAssociatedObject(self, &AssociatedKeys.navBarTitleColor, newValue, .OBJC_ASSOCIATION_RETAIN_NONATOMIC) if customNavBar.isKind(of: UINavigationBar.self) { - let navBar = customNavBar as! UINavigationBar - navBar.titleTextAttributes = [NSForegroundColorAttributeName:newValue] +// let navBar = customNavBar as! UINavigationBar +// navBar.titleTextAttributes = [NSAttributedStringKey.foregroundColor:newValue] } else { @@ -517,7 +662,7 @@ extension UIViewController var statusBarStyle: UIStatusBarStyle { get { guard let style = objc_getAssociatedObject(self, &AssociatedKeys.statusBarStyle) as? UIStatusBarStyle else { - return UIColor.defaultStatusBarStyle + return WRNavigationBar.defaultStatusBarStyle } return style } @@ -527,6 +672,20 @@ extension UIViewController } } + // if you want shadowImage hidden,you can via hideShadowImage = true + var navBarShadowImageHidden:Bool { + get { + guard let isHidden = objc_getAssociatedObject(self, &AssociatedKeys.navBarShadowImageHidden) as? Bool else { + return WRNavigationBar.defaultShadowImageHidden + } + return isHidden + } + set { + objc_setAssociatedObject(self, &AssociatedKeys.navBarShadowImageHidden, newValue, .OBJC_ASSOCIATION_ASSIGN) + navigationController?.setNeedsNavigationBarUpdate(hideShadowImage: newValue) + } + } + // custom navigationBar var customNavBar: UIView { get { @@ -542,12 +701,8 @@ extension UIViewController // swizzling two system methods: viewWillAppear(_:) and viewWillDisappear(_:) private static let onceToken = UUID().uuidString - open override class func initialize() + @objc public static func wrAwake() { - guard self == UIViewController.self else { - return - } - DispatchQueue.once(token: onceToken) { let needSwizzleSelectors = [ @@ -555,39 +710,72 @@ extension UIViewController #selector(viewWillDisappear(_:)), #selector(viewDidAppear(_:)) ] - + for selector in needSwizzleSelectors { let newSelectorStr = "wr_" + selector.description - let originalMethod = class_getInstanceMethod(self, selector) - let swizzledMethod = class_getInstanceMethod(self, Selector(newSelectorStr)) - method_exchangeImplementations(originalMethod, swizzledMethod) + if let originalMethod = class_getInstanceMethod(self, selector), + let swizzledMethod = class_getInstanceMethod(self, Selector(newSelectorStr)) { + method_exchangeImplementations(originalMethod, swizzledMethod) + } } } } - func wr_viewWillAppear(_ animated: Bool) + @objc func wr_viewWillAppear(_ animated: Bool) { - pushToNextVCFinished = false - navigationController?.setNeedsNavigationBarUpdate(tintColor: navBarTintColor) - navigationController?.setNeedsNavigationBarUpdate(titleColor: navBarTitleColor) + if canUpdateNavigationBar() == true { + pushToNextVCFinished = false + navigationController?.setNeedsNavigationBarUpdate(tintColor: navBarTintColor) + navigationController?.setNeedsNavigationBarUpdate(titleColor: navBarTitleColor) + } wr_viewWillAppear(animated) } - func wr_viewWillDisappear(_ animated: Bool) + @objc func wr_viewWillDisappear(_ animated: Bool) { - pushToNextVCFinished = true + if canUpdateNavigationBar() == true { + pushToNextVCFinished = true + } wr_viewWillDisappear(animated) } - func wr_viewDidAppear(_ animated: Bool) + @objc func wr_viewDidAppear(_ animated: Bool) { - navigationController?.setNeedsNavigationBarUpdate(barTintColor: navBarBarTintColor) - navigationController?.setNeedsNavigationBarUpdate(barBackgroundAlpha: navBarBackgroundAlpha) - navigationController?.setNeedsNavigationBarUpdate(tintColor: navBarTintColor) - navigationController?.setNeedsNavigationBarUpdate(titleColor: navBarTitleColor) + + if self.navigationController?.viewControllers.first != self { + self.pushToCurrentVCFinished = true + } + if canUpdateNavigationBar() == true + { + if let navBarBgImage = navBarBackgroundImage { + navigationController?.setNeedsNavigationBarUpdate(backgroundImage: navBarBgImage) + } else { + navigationController?.setNeedsNavigationBarUpdate(barTintColor: navBarBarTintColor) + } + navigationController?.setNeedsNavigationBarUpdate(barBackgroundAlpha: navBarBackgroundAlpha) + navigationController?.setNeedsNavigationBarUpdate(tintColor: navBarTintColor) + navigationController?.setNeedsNavigationBarUpdate(titleColor: navBarTitleColor) + navigationController?.setNeedsNavigationBarUpdate(hideShadowImage: navBarShadowImageHidden) + } wr_viewDidAppear(animated) } + + func canUpdateNavigationBar() -> Bool + { + let viewFrame = view.frame + let maxFrame = UIScreen.main.bounds + let middleFrame = CGRect(x: 0, y: WRNavigationBar.navBarBottom(), width: WRNavigationBar.screenWidth(), height: WRNavigationBar.screenHeight()-WRNavigationBar.navBarBottom()) + let minFrame = CGRect(x: 0, y: WRNavigationBar.navBarBottom(), width: WRNavigationBar.screenWidth(), height: WRNavigationBar.screenHeight()-WRNavigationBar.navBarBottom()-WRNavigationBar.tabBarHeight()) + // 蝙蝠🦇 + let isBat = viewFrame.equalTo(maxFrame) || viewFrame.equalTo(middleFrame) || viewFrame.equalTo(minFrame) + if self.navigationController != nil && isBat == true { + return true + } else { + return false + } + } + } //==================================================================================== @@ -618,15 +806,18 @@ extension DispatchQueue { //=========================================================================================== // MARK: - default navigationBar barTintColor、tintColor and statusBarStyle YOU CAN CHANGE!!! //=========================================================================================== -extension UIColor +class WRNavigationBar { fileprivate struct AssociatedKeys { // default is system attributes static var defNavBarBarTintColor: UIColor = UIColor.white + static var defNavBarBackgroundImage: UIImage = UIImage() static var defNavBarTintColor: UIColor = UIColor(red: 0, green: 0.478431, blue: 1, alpha: 1.0) static var defNavBarTitleColor: UIColor = UIColor.black static var defStatusBarStyle: UIStatusBarStyle = UIStatusBarStyle.default + static var defShadowImageHidden: Bool = false } + class var defaultNavBarBarTintColor: UIColor { get { guard let def = objc_getAssociatedObject(self, &AssociatedKeys.defNavBarBarTintColor) as? UIColor else { @@ -639,6 +830,18 @@ extension UIColor } } + class var defaultNavBarBackgroundImage: UIImage? { + get { + guard let def = objc_getAssociatedObject(self, &AssociatedKeys.defNavBarBackgroundImage) as? UIImage else { + return nil + } + return def + } + set { + objc_setAssociatedObject(self, &AssociatedKeys.defNavBarBackgroundImage, newValue, .OBJC_ASSOCIATION_RETAIN_NONATOMIC) + } + } + class var defaultNavBarTintColor: UIColor { get { guard let def = objc_getAssociatedObject(self, &AssociatedKeys.defNavBarTintColor) as? UIColor else { @@ -675,6 +878,18 @@ extension UIColor } } + class var defaultShadowImageHidden: Bool { + get { + guard let def = objc_getAssociatedObject(self, &AssociatedKeys.defShadowImageHidden) as? Bool else { + return false + } + return def + } + set { + objc_setAssociatedObject(self, &AssociatedKeys.defShadowImageHidden, newValue, .OBJC_ASSOCIATION_ASSIGN) + } + } + class var defaultBackgroundAlpha: CGFloat { get { return 1.0 @@ -714,8 +929,76 @@ extension UIColor } } +extension WRNavigationBar +{ + class func isIphoneX() -> Bool { + return UIScreen.main.bounds.equalTo(CGRect(x: 0, y: 0, width: 375, height: 812)) + } + class func navBarBottom() -> Int { + return self.isIphoneX() ? 88 : 64; + } + class func tabBarHeight() -> Int { + return self.isIphoneX() ? 83 : 49; + } + class func screenWidth() -> Int { + return Int(UIScreen.main.bounds.size.width) + } + class func screenHeight() -> Int { + return Int(UIScreen.main.bounds.size.height) + } +} + + + + + + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// 1. 定义 WRAwakeProtocol 协议 +public protocol WRAwakeProtocol: class { + static func wrAwake() +} +public protocol WRFatherAwakeProtocol: class +{ // 1.1 定义 WRFatherAwakeProtocol () + static func fatherAwake() +} + +class NothingToSeeHere +{ + static func harmlessFunction(){ +// let typeCount = Int(objc_getClassList(nil, 0)) +// let types = UnsafeMutablePointer.allocate(capacity: typeCount) +// let autoreleaseintTypes = AutoreleasingUnsafeMutablePointer(types) +// objc_getClassList(autoreleaseintTypes, Int32(typeCount)) //获取所有的类 +// for index in 0 ..< typeCount { +// (types[index] as? WRAwakeProtocol.Type)?.wrAwake() //如果该类实现了SelfAware协议,那么调用 awake 方法 +// (types[index] as? WRFatherAwakeProtocol.Type)?.fatherAwake() +// } +// types.deallocate(capacity: typeCount) + UINavigationBar.wrAwake() + UIViewController.wrAwake() + UINavigationController.fatherAwake() + } +} + +// 2. 让APP启动时只执行一次 harmlessFunction 方法 +extension UIApplication +{ + private static let runOnce:Void = { //使用静态属性以保证只调用一次(该属性是个方法) + NothingToSeeHere.harmlessFunction() + }() + + open override var next: UIResponder?{ //重写next属性 + UIApplication.runOnce + return super.next + } +} + +// 3. 自定义类实现 WRAwakeProtocol 协议,重写 wrAwake 方法 +// 自定义类实现 WRFatherAwakeProtocol 协议,重写 fatherAwake 方法 + diff --git "a/screenshots/\345\257\274\350\210\252\346\240\217\346\230\276\347\244\272\345\233\276\347\211\207.gif" "b/screenshots/\345\257\274\350\210\252\346\240\217\346\230\276\347\244\272\345\233\276\347\211\207.gif" new file mode 100644 index 0000000..471df25 Binary files /dev/null and "b/screenshots/\345\257\274\350\210\252\346\240\217\346\230\276\347\244\272\345\233\276\347\211\207.gif" differ diff --git "a/screenshots/\345\257\274\350\210\252\346\240\217\346\230\276\347\244\272\346\270\220\345\217\230\350\211\262.gif" "b/screenshots/\345\257\274\350\210\252\346\240\217\346\230\276\347\244\272\346\270\220\345\217\230\350\211\262.gif" new file mode 100644 index 0000000..9452626 Binary files /dev/null and "b/screenshots/\345\257\274\350\210\252\346\240\217\346\230\276\347\244\272\346\270\220\345\217\230\350\211\262.gif" differ diff --git "a/screenshots/\346\213\211\351\222\251App\351\246\226\351\241\265.gif" "b/screenshots/\346\213\211\351\222\251App\351\246\226\351\241\265.gif" new file mode 100644 index 0000000..fa5249b Binary files /dev/null and "b/screenshots/\346\213\211\351\222\251App\351\246\226\351\241\265.gif" differ diff --git "a/screenshots/\350\277\236\347\273\255\345\244\232\344\270\252\347\225\214\351\235\242\345\257\274\350\210\252\346\240\217\351\200\217\346\230\216.gif" "b/screenshots/\350\277\236\347\273\255\345\244\232\344\270\252\347\225\214\351\235\242\345\257\274\350\210\252\346\240\217\351\200\217\346\230\216.gif" new file mode 100644 index 0000000..480e5a6 Binary files /dev/null and "b/screenshots/\350\277\236\347\273\255\345\244\232\344\270\252\347\225\214\351\235\242\345\257\274\350\210\252\346\240\217\351\200\217\346\230\216.gif" differ