Swift3 Update

This commit is contained in:
Olga Vorona 2016-10-11 17:22:57 +03:00
parent 2f8e094c09
commit 2e56e21848
19 changed files with 351 additions and 307 deletions

48
Classes/Default/RMRPullToRefreshBaseMessageView.swift Normal file → Executable file
View File

@ -33,16 +33,16 @@ class RMRPullToRefreshBaseMessageView: RMRPullToRefreshBaseView {
func configureLabel() {
let label = UILabel(frame: self.messageView.bounds)
label.textColor = UIColor.whiteColor()
label.textAlignment = .Center
label.textColor = UIColor.white
label.textAlignment = .center
label.text = messageText()
messageView.addSubview(label)
label.translatesAutoresizingMaskIntoConstraints = false
for attribute in [NSLayoutAttribute.Top, NSLayoutAttribute.Right, NSLayoutAttribute.Left, NSLayoutAttribute.Bottom] {
for attribute in [NSLayoutAttribute.top, NSLayoutAttribute.right, NSLayoutAttribute.left, NSLayoutAttribute.bottom] {
messageView.addConstraint(NSLayoutConstraint(item: label,
attribute: attribute,
relatedBy: NSLayoutRelation.Equal,
relatedBy: NSLayoutRelation.equal,
toItem: messageView,
attribute: attribute,
multiplier: 1,
@ -58,36 +58,36 @@ class RMRPullToRefreshBaseMessageView: RMRPullToRefreshBaseView {
messageView.translatesAutoresizingMaskIntoConstraints = false
let heightConstraint = NSLayoutConstraint(item: messageView,
attribute: NSLayoutAttribute.Height,
relatedBy: NSLayoutRelation.Equal,
attribute: NSLayoutAttribute.height,
relatedBy: NSLayoutRelation.equal,
toItem: nil,
attribute: NSLayoutAttribute.NotAnAttribute,
attribute: NSLayoutAttribute.notAnAttribute,
multiplier: 1,
constant: 30)
let widthConstraint = NSLayoutConstraint(item: messageView,
attribute: NSLayoutAttribute.Width,
relatedBy: NSLayoutRelation.Equal,
attribute: NSLayoutAttribute.width,
relatedBy: NSLayoutRelation.equal,
toItem: nil,
attribute: NSLayoutAttribute.NotAnAttribute,
attribute: NSLayoutAttribute.notAnAttribute,
multiplier: 1,
constant: 150)
messageView.addConstraints([heightConstraint, widthConstraint])
let verticalConstraint = NSLayoutConstraint(item: messageView,
attribute: .CenterY,
relatedBy: NSLayoutRelation.Equal,
attribute: .centerY,
relatedBy: NSLayoutRelation.equal,
toItem: self,
attribute: .CenterY,
attribute: .centerY,
multiplier: 1,
constant: 0)
let leftConstraint = NSLayoutConstraint(item: messageView,
attribute: .Left,
relatedBy: NSLayoutRelation.Equal,
attribute: .left,
relatedBy: NSLayoutRelation.equal,
toItem: self,
attribute: .Right,
attribute: .right,
multiplier: 1,
constant: 0)
@ -97,7 +97,7 @@ class RMRPullToRefreshBaseMessageView: RMRPullToRefreshBaseView {
}
func messageBackgroundColor() -> UIColor {
return UIColor.whiteColor()
return UIColor.white
}
func messageText() -> String? {
@ -114,20 +114,20 @@ class RMRPullToRefreshBaseMessageView: RMRPullToRefreshBaseView {
if self.messageViewLeftConstaint?.constant != 0.0 {
self.messageViewLeftConstaint?.constant = 0.0
}
UIView.animateWithDuration(0.4) {[weak self] in
UIView.animate(withDuration: 0.4, animations: {[weak self] in
self?.layoutIfNeeded()
}
})
}
override func willEndLoadingAnimation() {
self.logoHorizontalConstraint?.constant = -CGRectGetWidth(self.bounds)/2.0 + CGRectGetWidth(self.logoImageView.bounds)
self.messageViewLeftConstaint?.constant = -CGRectGetWidth(messageView.bounds) - 10.0
UIView.animateWithDuration(0.4) {[weak self] in
self.logoHorizontalConstraint?.constant = -self.bounds.width/2.0 + self.logoImageView.bounds.width
self.messageViewLeftConstaint?.constant = -messageView.bounds.width - 10.0
UIView.animate(withDuration: 0.4, animations: {[weak self] in
self?.layoutIfNeeded()
}
})
}
override func didEndLoadingAnimation(hidden: Bool) {
override func didEndLoadingAnimation(_ hidden: Bool) {
super.didEndLoadingAnimation(hidden)
if hidden {
self.logoHorizontalConstraint?.constant = 0.0

44
Classes/Default/RMRPullToRefreshBaseView.swift Normal file → Executable file
View File

@ -45,36 +45,36 @@ class RMRPullToRefreshBaseView: RMRPullToRefreshView {
func configureConstraints() {
logoImageView.translatesAutoresizingMaskIntoConstraints = false
let heightConstraint = NSLayoutConstraint(item: logoImageView,
attribute: NSLayoutAttribute.Height,
relatedBy: NSLayoutRelation.Equal,
attribute: NSLayoutAttribute.height,
relatedBy: NSLayoutRelation.equal,
toItem: nil,
attribute: NSLayoutAttribute.NotAnAttribute,
attribute: NSLayoutAttribute.notAnAttribute,
multiplier: 1,
constant: 50)
let widthConstraint = NSLayoutConstraint(item: logoImageView,
attribute: NSLayoutAttribute.Width,
relatedBy: NSLayoutRelation.Equal,
attribute: NSLayoutAttribute.width,
relatedBy: NSLayoutRelation.equal,
toItem: nil,
attribute: NSLayoutAttribute.NotAnAttribute,
attribute: NSLayoutAttribute.notAnAttribute,
multiplier: 1,
constant: 50)
logoImageView.addConstraints([heightConstraint, widthConstraint])
let verticalConstraint = NSLayoutConstraint(item: logoImageView,
attribute: .CenterY,
relatedBy: NSLayoutRelation.Equal,
attribute: .centerY,
relatedBy: NSLayoutRelation.equal,
toItem: self,
attribute: .CenterY,
attribute: .centerY,
multiplier: 1,
constant: 0)
let horizontalConstraint = NSLayoutConstraint(item: logoImageView,
attribute: .CenterX,
relatedBy: NSLayoutRelation.Equal,
attribute: .centerX,
relatedBy: NSLayoutRelation.equal,
toItem: self,
attribute: .CenterX,
attribute: .centerX,
multiplier: 1,
constant: 0)
@ -85,18 +85,18 @@ class RMRPullToRefreshBaseView: RMRPullToRefreshView {
func resetTransformIfNecessary() {
if !isConfigured {
logoImageView.transform = CGAffineTransformMakeRotation(CGFloat(M_PI))
logoImageView.transform = CGAffineTransform(rotationAngle: CGFloat(M_PI))
didRotateToBottom = true
isConfigured = true
}
}
func makeIncreasePulling(animated: Bool) {
func makeIncreasePulling(_ animated: Bool) {
didRotateToTop = true
didRotateToBottom = false
let rotateTransform = CGAffineTransformRotate(logoImageView.transform, CGFloat(M_PI));
let rotateTransform = logoImageView.transform.rotated(by: CGFloat(M_PI));
if animated {
UIView .animateWithDuration(0.4, animations: { [weak self] in
UIView .animate(withDuration: 0.4, animations: { [weak self] in
self?.logoImageView.transform = rotateTransform
})
} else {
@ -104,12 +104,12 @@ class RMRPullToRefreshBaseView: RMRPullToRefreshView {
}
}
func makeDecreasePulling(animated: Bool) {
func makeDecreasePulling(_ animated: Bool) {
didRotateToBottom = true
didRotateToTop = false
let rotateTransform = CGAffineTransformRotate(logoImageView.transform, -CGFloat(M_PI));
let rotateTransform = logoImageView.transform.rotated(by: -CGFloat(M_PI));
if animated {
UIView .animateWithDuration(0.4, animations: { [weak self] in
UIView .animate(withDuration: 0.4, animations: { [weak self] in
self?.logoImageView.transform = rotateTransform
})
} else {
@ -119,7 +119,7 @@ class RMRPullToRefreshBaseView: RMRPullToRefreshView {
// MARK: - RMRPullToRefreshViewProtocol
override func didChangeDraggingProgress(progress: CGFloat) {
override func didChangeDraggingProgress(_ progress: CGFloat) {
resetTransformIfNecessary()
@ -133,7 +133,7 @@ class RMRPullToRefreshBaseView: RMRPullToRefreshView {
}
}
override func prepareForLoadingAnimation(startProgress: CGFloat) {
override func prepareForLoadingAnimation(_ startProgress: CGFloat) {
if logoImageView.animationImages == nil {
logoImageView.animationImages = images
logoImageView.animationDuration = 0.8
@ -145,7 +145,7 @@ class RMRPullToRefreshBaseView: RMRPullToRefreshView {
logoImageView.startAnimating()
}
override func didEndLoadingAnimation(hidden: Bool) {
override func didEndLoadingAnimation(_ hidden: Bool) {
logoImageView.stopAnimating()
logoImageView.layer.removeAllAnimations()
didRotateToTop = false

0
Classes/Default/RMRPullToRefreshErrorView.swift Normal file → Executable file
View File

0
Classes/Default/RMRPullToRefreshNoUpdatesView.swift Normal file → Executable file
View File

0
Classes/Default/RMRPullToRefreshSuccessView.swift Normal file → Executable file
View File

10
Classes/Default/RMRPullToRefreshViewFactory.swift Normal file → Executable file
View File

@ -8,15 +8,15 @@
import UIKit
public class RMRPullToRefreshViewFactory: NSObject {
open class RMRPullToRefreshViewFactory: NSObject {
class func create(result: RMRPullToRefreshResultType) -> RMRPullToRefreshView? {
class func create(_ result: RMRPullToRefreshResultType) -> RMRPullToRefreshView? {
switch result {
case .Success:
case .success:
return RMRPullToRefreshSuccessView(result: result)
case .NoUpdates:
case .noUpdates:
return RMRPullToRefreshNoUpdatesView(result: result)
case .Error:
case .error:
return RMRPullToRefreshErrorView(result: result)
}

39
Classes/RMRPullToRefresh.swift Normal file → Executable file
View File

@ -8,64 +8,69 @@
import UIKit
public class RMRPullToRefresh: NSObject {
open class RMRPullToRefresh: NSObject {
private var сontroller: RMRPullToRefreshController?
fileprivate var сontroller: RMRPullToRefreshController?
public var height : CGFloat = RMRPullToRefreshConstants.DefaultHeight {
open var height : CGFloat = RMRPullToRefreshConstants.DefaultHeight {
didSet {
сontroller?.configureHeight(height)
}
}
public var backgroundColor : UIColor = RMRPullToRefreshConstants.DefaultBackgroundColor {
open var backgroundColor : UIColor = RMRPullToRefreshConstants.DefaultBackgroundColor {
didSet {
сontroller?.configureBackgroundColor(backgroundColor)
}
}
public var hideWhenError: Bool = true {
open var hideWhenError: Bool = true {
didSet {
сontroller?.hideWhenError = hideWhenError
}
}
public init(scrollView: UIScrollView, position:RMRPullToRefreshPosition, actionHandler: () -> Void) {
public init(
scrollView: UIScrollView,
position:RMRPullToRefreshPosition,
actionHandler: @escaping () -> Void)
{
super.init()
let controller = RMRPullToRefreshController(scrollView: scrollView,
position: position,
actionHandler: actionHandler)
let controller = RMRPullToRefreshController(
scrollView: scrollView,
position: position,
actionHandler: actionHandler)
scrollView.addSubview(controller.containerView)
self.сontroller = controller
}
public func configureView(view :RMRPullToRefreshView, state:RMRPullToRefreshState, result:RMRPullToRefreshResultType) {
open func configureView(_ view :RMRPullToRefreshView, state:RMRPullToRefreshState, result:RMRPullToRefreshResultType) {
сontroller?.configureView(view, state: state, result: result)
}
public func configureView(view :RMRPullToRefreshView, result:RMRPullToRefreshResultType) {
open func configureView(_ view :RMRPullToRefreshView, result:RMRPullToRefreshResultType) {
сontroller?.configureView(view, result: result)
}
public func setupDefaultSettings() {
open func setupDefaultSettings() {
сontroller?.setupDefaultSettings()
}
public func startLoading() {
open func startLoading() {
сontroller?.startLoading()
}
public func stopLoading() {
stopLoading(.Success)
open func stopLoading() {
stopLoading(.success)
}
public func stopLoading(result:RMRPullToRefreshResultType) {
open func stopLoading(_ result:RMRPullToRefreshResultType) {
сontroller?.stopLoading(result)
}
public func setHideDelay(delay: NSTimeInterval, result: RMRPullToRefreshResultType) {
open func setHideDelay(_ delay: TimeInterval, result: RMRPullToRefreshResultType) {
сontroller?.setHideDelay(delay, result: result)
}
}

20
Classes/RMRPullToRefreshConstants.swift Normal file → Executable file
View File

@ -9,20 +9,20 @@
import UIKit
public enum RMRPullToRefreshPosition: Int {
case Top
case Bottom
case top
case bottom
}
public enum RMRPullToRefreshState: Int {
case Stopped
case Dragging
case Loading
case stopped
case dragging
case loading
}
public enum RMRPullToRefreshResultType: Int {
case Success = 0
case NoUpdates
case Error
case success = 0
case noUpdates
case error
}
public struct RMRPullToRefreshConstants {
@ -36,5 +36,5 @@ public struct RMRPullToRefreshConstants {
}
static let DefaultHeight = CGFloat(90.0)
static let DefaultBackgroundColor = UIColor.whiteColor()
}
static let DefaultBackgroundColor = UIColor.white
}

28
Classes/RMRPullToRefreshContainerView.swift Normal file → Executable file
View File

@ -8,39 +8,39 @@
import UIKit
public class RMRPullToRefreshContainerView: UIView {
open class RMRPullToRefreshContainerView: UIView {
var currentView: RMRPullToRefreshView?
var storage = [String: RMRPullToRefreshView]()
public func configureView(view:RMRPullToRefreshView, state:RMRPullToRefreshState, result:RMRPullToRefreshResultType) {
open func configureView(_ view:RMRPullToRefreshView, state:RMRPullToRefreshState, result:RMRPullToRefreshResultType) {
let key = storageKey(state, result:result)
self.storage[key] = view
}
func updateView(state: RMRPullToRefreshState, result: RMRPullToRefreshResultType) {
func updateView(_ state: RMRPullToRefreshState, result: RMRPullToRefreshResultType) {
clear()
if let view = obtainView(state, result: result) {
view.translatesAutoresizingMaskIntoConstraints = false
addSubview(view)
addConstraint(constraint(self, subview: view, attribute: NSLayoutAttribute.Left))
addConstraint(constraint(self, subview: view, attribute: NSLayoutAttribute.Top))
addConstraint(constraint(self, subview: view, attribute: NSLayoutAttribute.Right))
addConstraint(constraint(self, subview: view, attribute: NSLayoutAttribute.Bottom))
addConstraint(constraint(self, subview: view, attribute: NSLayoutAttribute.left))
addConstraint(constraint(self, subview: view, attribute: NSLayoutAttribute.top))
addConstraint(constraint(self, subview: view, attribute: NSLayoutAttribute.right))
addConstraint(constraint(self, subview: view, attribute: NSLayoutAttribute.bottom))
view.layoutIfNeeded()
self.currentView = view
}
}
func dragging(progress: CGFloat) {
func dragging(_ progress: CGFloat) {
if let view = self.currentView {
view.didChangeDraggingProgress(progress)
}
}
func startLoadingAnimation(startProgress: CGFloat) {
func startLoadingAnimation(_ startProgress: CGFloat) {
if let view = self.currentView {
if !view.pullToRefreshIsLoading {
view.prepareForLoadingAnimation(startProgress)
@ -56,7 +56,7 @@ public class RMRPullToRefreshContainerView: UIView {
}
}
func stopAllAnimations(hidden: Bool) {
func stopAllAnimations(_ hidden: Bool) {
for view in storage.values {
view.didEndLoadingAnimation(hidden)
view.pullToRefreshIsLoading = false
@ -72,19 +72,19 @@ public class RMRPullToRefreshContainerView: UIView {
self.currentView = nil
}
func obtainView(state: RMRPullToRefreshState, result: RMRPullToRefreshResultType) -> RMRPullToRefreshView? {
func obtainView(_ state: RMRPullToRefreshState, result: RMRPullToRefreshResultType) -> RMRPullToRefreshView? {
let key = storageKey(state, result:result)
return self.storage[key]
}
func storageKey(state: RMRPullToRefreshState, result: RMRPullToRefreshResultType) -> String {
func storageKey(_ state: RMRPullToRefreshState, result: RMRPullToRefreshResultType) -> String {
return String(state.rawValue) + "_" + String(result.rawValue)
}
// MARK: - Constraint
func constraint(superview: UIView, subview: UIView, attribute: NSLayoutAttribute) -> NSLayoutConstraint {
return NSLayoutConstraint(item: subview, attribute: attribute, relatedBy: NSLayoutRelation.Equal, toItem: superview, attribute: attribute, multiplier: 1, constant: 0)
func constraint(_ superview: UIView, subview: UIView, attribute: NSLayoutAttribute) -> NSLayoutConstraint {
return NSLayoutConstraint(item: subview, attribute: attribute, relatedBy: NSLayoutRelation.equal, toItem: superview, attribute: attribute, multiplier: 1, constant: 0)
}
}

233
Classes/RMRPullToRefreshController.swift Normal file → Executable file
View File

@ -7,8 +7,28 @@
//
import UIKit
fileprivate func < <T : Comparable>(lhs: T?, rhs: T?) -> Bool {
switch (lhs, rhs) {
case let (l?, r?):
return l < r
case (nil, _?):
return true
default:
return false
}
}
public class RMRPullToRefreshController: NSObject {
fileprivate func > <T : Comparable>(lhs: T?, rhs: T?) -> Bool {
switch (lhs, rhs) {
case let (l?, r?):
return l > r
default:
return rhs < lhs
}
}
open class RMRPullToRefreshController: NSObject {
// MARK: - Vars
@ -16,7 +36,7 @@ public class RMRPullToRefreshController: NSObject {
let containerView = RMRPullToRefreshContainerView()
let backgroundView = UIView(frame: CGRectZero)
let backgroundView = UIView(frame: CGRect.zero)
var backgroundViewHeightConstraint: NSLayoutConstraint?
var backgroundViewTopConstraint: NSLayoutConstraint?
@ -29,20 +49,20 @@ public class RMRPullToRefreshController: NSObject {
var originalTopInset = CGFloat(0.0)
var originalBottomInset = CGFloat(0.0)
var state = RMRPullToRefreshState.Stopped
var result = RMRPullToRefreshResultType.Success
var state = RMRPullToRefreshState.stopped
var result = RMRPullToRefreshResultType.success
var position: RMRPullToRefreshPosition?
var changingContentInset = false
var contentSizeWhenStartLoading: CGSize?
var hideDelayValues = [RMRPullToRefreshResultType: NSTimeInterval]()
var hideDelayValues = [RMRPullToRefreshResultType: TimeInterval]()
public var hideWhenError: Bool = true
open var hideWhenError: Bool = true
// MARK: - Init
init(scrollView: UIScrollView, position:RMRPullToRefreshPosition, actionHandler: () -> Void) {
init(scrollView: UIScrollView, position:RMRPullToRefreshPosition, actionHandler: @escaping () -> Void) {
super.init()
self.scrollView = scrollView
@ -52,7 +72,7 @@ public class RMRPullToRefreshController: NSObject {
self.configureBackgroundView(self.backgroundView)
self.configureHeight()
self.containerView.backgroundColor = UIColor.clearColor()
self.containerView.backgroundColor = UIColor.clear
self.subscribeOnScrollViewEvents()
}
@ -61,29 +81,29 @@ public class RMRPullToRefreshController: NSObject {
self.unsubscribeFromScrollViewEvents()
}
private func configureBackgroundView(backgroundView: UIView) {
fileprivate func configureBackgroundView(_ backgroundView: UIView) {
backgroundView.translatesAutoresizingMaskIntoConstraints = false
scrollView?.addSubview(backgroundView)
addBackgroundViewConstraints(backgroundView)
}
private func addBackgroundViewConstraints(backgroundView: UIView) {
fileprivate func addBackgroundViewConstraints(_ backgroundView: UIView) {
// Constraints
self.backgroundViewHeightConstraint = NSLayoutConstraint(item: backgroundView, attribute: NSLayoutAttribute.Height, relatedBy: NSLayoutRelation.Equal, toItem: nil, attribute: NSLayoutAttribute.NotAnAttribute, multiplier: 1, constant: 0)
self.backgroundViewHeightConstraint = NSLayoutConstraint(item: backgroundView, attribute: NSLayoutAttribute.height, relatedBy: NSLayoutRelation.equal, toItem: nil, attribute: NSLayoutAttribute.notAnAttribute, multiplier: 1, constant: 0)
backgroundView.addConstraint(self.backgroundViewHeightConstraint!)
scrollView?.addConstraint(NSLayoutConstraint(item: backgroundView, attribute: NSLayoutAttribute.Width, relatedBy: NSLayoutRelation.Equal, toItem: scrollView, attribute: NSLayoutAttribute.Width, multiplier: 1, constant: 0))
scrollView?.addConstraint(NSLayoutConstraint(item: backgroundView, attribute: NSLayoutAttribute.width, relatedBy: NSLayoutRelation.equal, toItem: scrollView, attribute: NSLayoutAttribute.width, multiplier: 1, constant: 0))
if position == .Top {
scrollView?.addConstraint(NSLayoutConstraint(item: backgroundView, attribute: NSLayoutAttribute.Bottom, relatedBy: NSLayoutRelation.Equal, toItem: scrollView, attribute: NSLayoutAttribute.Top, multiplier: 1, constant: 0))
} else if position == .Bottom, let scrollView = self.scrollView {
let constant = max(scrollView.contentSize.height, CGRectGetHeight(scrollView.bounds))
self.backgroundViewTopConstraint = NSLayoutConstraint(item: backgroundView, attribute: NSLayoutAttribute.Top, relatedBy: NSLayoutRelation.Equal, toItem: scrollView, attribute: NSLayoutAttribute.Top, multiplier: 1, constant: constant)
if position == .top {
scrollView?.addConstraint(NSLayoutConstraint(item: backgroundView, attribute: NSLayoutAttribute.bottom, relatedBy: NSLayoutRelation.equal, toItem: scrollView, attribute: NSLayoutAttribute.top, multiplier: 1, constant: 0))
} else if position == .bottom, let scrollView = self.scrollView {
let constant = max(scrollView.contentSize.height, scrollView.bounds.height)
self.backgroundViewTopConstraint = NSLayoutConstraint(item: backgroundView, attribute: NSLayoutAttribute.top, relatedBy: NSLayoutRelation.equal, toItem: scrollView, attribute: NSLayoutAttribute.top, multiplier: 1, constant: constant)
scrollView.addConstraint(self.backgroundViewTopConstraint!)
}
}
private func configureHeight() {
fileprivate func configureHeight() {
if let scrollView = self.scrollView {
self.originalTopInset = scrollView.contentInset.top
@ -94,96 +114,96 @@ public class RMRPullToRefreshController: NSObject {
// MARK: - Public
public func configureView(view:RMRPullToRefreshView, result:RMRPullToRefreshResultType) {
configureView(view, state: .Loading, result: result)
configureView(view, state: .Dragging, result: result)
configureView(view, state: .Stopped, result: result)
open func configureView(_ view:RMRPullToRefreshView, result:RMRPullToRefreshResultType) {
configureView(view, state: .loading, result: result)
configureView(view, state: .dragging, result: result)
configureView(view, state: .stopped, result: result)
}
public func configureView(view:RMRPullToRefreshView, state:RMRPullToRefreshState, result:RMRPullToRefreshResultType) {
open func configureView(_ view:RMRPullToRefreshView, state:RMRPullToRefreshState, result:RMRPullToRefreshResultType) {
containerView.configureView(view, state: state, result: result)
}
public func configureHeight(height: CGFloat) {
open func configureHeight(_ height: CGFloat) {
self.height = height
updateContainerFrame()
}
public func configureBackgroundColor(color: UIColor) {
open func configureBackgroundColor(_ color: UIColor) {
self.backgroundView.backgroundColor = color
}
public func setupDefaultSettings() {
setupDefaultSettings(.Success, hideDelay: 0.0)
setupDefaultSettings(.NoUpdates, hideDelay: 2.0)
setupDefaultSettings(.Error, hideDelay: 2.0)
configureBackgroundColor(UIColor.whiteColor())
open func setupDefaultSettings() {
setupDefaultSettings(.success, hideDelay: 0.0)
setupDefaultSettings(.noUpdates, hideDelay: 2.0)
setupDefaultSettings(.error, hideDelay: 2.0)
configureBackgroundColor(UIColor.white)
updateContainerView(self.state)
}
public func startLoading() {
open func startLoading() {
startLoading(0.0)
}
public func stopLoading(result:RMRPullToRefreshResultType) {
open func stopLoading(_ result:RMRPullToRefreshResultType) {
self.result = result
self.state = .Stopped
self.state = .stopped
updateContainerView(self.state)
containerView.prepareForStopAnimations()
var delay = hideDelay(result)
var afterDelay = 0.4
let afterDelay = 0.4
if result == .Error && !hideWhenError {
if result == .error && !hideWhenError {
delay = 0.0
}
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, Int64(delay * Double(NSEC_PER_SEC))), dispatch_get_main_queue(), { [weak self] in
DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + Double(Int64(delay * Double(NSEC_PER_SEC))) / Double(NSEC_PER_SEC), execute: { [weak self] in
if self?.shouldHideWhenStopLoading() == true {
self?.resetContentInset()
if let position = self?.position {
switch (position) {
case .Top:
case .top:
self?.scrollToTop(true)
case .Bottom:
case .bottom:
self?.scrollToBottom(true)
}
}
self?.contentSizeWhenStartLoading = nil
self?.performSelector(#selector(self?.resetBackgroundViewHeightConstraint), withObject: nil, afterDelay: afterDelay)
self?.perform(#selector(self?.resetBackgroundViewHeightConstraint), with: nil, afterDelay: afterDelay)
}
self?.performSelector(#selector(self?.stopAllAnimations), withObject: nil, afterDelay: afterDelay)
self?.perform(#selector(self?.stopAllAnimations), with: nil, afterDelay: afterDelay)
})
}
public func setHideDelay(delay: NSTimeInterval, result: RMRPullToRefreshResultType) {
open func setHideDelay(_ delay: TimeInterval, result: RMRPullToRefreshResultType) {
self.hideDelayValues[result] = delay
}
// MARK: - Private
func setupDefaultSettings(result:RMRPullToRefreshResultType, hideDelay: NSTimeInterval) {
func setupDefaultSettings(_ result:RMRPullToRefreshResultType, hideDelay: TimeInterval) {
if let view = RMRPullToRefreshViewFactory.create(result) {
configureView(view, result: result)
setHideDelay(hideDelay, result: result)
}
}
func scrollToTop(animated: Bool) {
func scrollToTop(_ animated: Bool) {
if let scrollView = self.scrollView {
if scrollView.contentOffset.y < -originalTopInset {
let offset = CGPointMake(scrollView.contentOffset.x, -self.originalTopInset)
let offset = CGPoint(x: scrollView.contentOffset.x, y: -self.originalTopInset)
scrollView.setContentOffset(offset, animated: true)
}
}
}
func scrollToBottom(animated: Bool) {
func scrollToBottom(_ animated: Bool) {
if let scrollView = self.scrollView {
var offset = scrollView.contentOffset
if let contentSize = self.contentSizeWhenStartLoading {
offset.y = contentSize.height - CGRectGetHeight(scrollView.bounds) + scrollView.contentInset.bottom
if state == .Stopped {
offset.y = contentSize.height - scrollView.bounds.height + scrollView.contentInset.bottom
if state == .stopped {
if scrollView.contentOffset.y < offset.y {
return
} else if scrollView.contentOffset.y > offset.y {
@ -191,105 +211,114 @@ public class RMRPullToRefreshController: NSObject {
}
}
} else {
offset.y = scrollView.contentSize.height - CGRectGetHeight(scrollView.bounds) + scrollView.contentInset.bottom
offset.y = scrollView.contentSize.height - scrollView.bounds.height + scrollView.contentInset.bottom
}
scrollView.setContentOffset(offset, animated: animated)
}
}
func startLoading(startProgress: CGFloat) {
func startLoading(_ startProgress: CGFloat) {
stopped = false
contentSizeWhenStartLoading = scrollView?.contentSize
state = .Loading
state = .loading
updateContainerView(state)
actionHandler()
containerView.startLoadingAnimation(startProgress)
}
@objc private func stopAllAnimations() {
@objc fileprivate func stopAllAnimations() {
if shouldHideWhenStopLoading() {
stopped = true
}
containerView.stopAllAnimations(shouldHideWhenStopLoading())
}
@objc private func forceStopAllAnimations() {
@objc fileprivate func forceStopAllAnimations() {
stopped = true
containerView.stopAllAnimations(true)
}
@objc private func resetBackgroundViewHeightConstraint() {
@objc fileprivate func resetBackgroundViewHeightConstraint() {
backgroundViewHeightConstraint?.constant = 0
}
private func scrollViewDidChangePanState(scrollView: UIScrollView, panState: UIGestureRecognizerState) {
if panState == .Ended || panState == .Cancelled || panState == .Failed {
fileprivate func scrollViewDidChangePanState(_ scrollView: UIScrollView, panState: UIGestureRecognizerState) {
if panState == .ended || panState == .cancelled || panState == .failed {
if state == .Loading || (shouldHideWhenStopLoading() && !stopped) {
if state == .loading || (shouldHideWhenStopLoading() && !stopped) {
return
}
var y: CGFloat = 0.0
if position == .Top {
if position == .top {
y = -scrollView.contentOffset.y
} else if position == .Bottom {
y = -(scrollView.contentSize.height - (scrollView.contentOffset.y + CGRectGetHeight(scrollView.bounds) + originalBottomInset));
} else if position == .bottom {
y = -(scrollView.contentSize.height - (scrollView.contentOffset.y + scrollView.bounds.height + originalBottomInset));
}
if y >= height {
startLoading(y/height)
// inset
var inset = scrollView.contentInset
if position == .Top {
if position == .top {
inset.top = originalTopInset+height
} else if position == .Bottom {
} else if position == .bottom {
inset.bottom = originalBottomInset+height
}
setContentInset(inset, animated: true)
} else {
state = .Stopped
state = .stopped
updateContainerView(state)
}
}
}
private func scrollViewDidChangeContentSize(scrollView: UIScrollView, contentSize: CGSize) {
fileprivate func scrollViewDidChangeContentSize(_ scrollView: UIScrollView, contentSize: CGSize) {
updateContainerFrame()
if position == .Bottom {
self.backgroundViewTopConstraint?.constant = max(scrollView.contentSize.height, CGRectGetHeight(scrollView.bounds))
if position == .bottom {
self.backgroundViewTopConstraint?.constant = max(scrollView.contentSize.height, scrollView.bounds.height)
if changingContentInset {
scrollToBottom(true)
}
}
}
private func scrollViewDidScroll(scrollView: UIScrollView, contentOffset: CGPoint) {
fileprivate func scrollViewDidScroll(_ scrollView: UIScrollView, contentOffset: CGPoint) {
if state == .loading {
if scrollView.contentOffset.y >= 0 {
scrollView.contentInset = UIEdgeInsets.zero
} else {
scrollView.contentInset = UIEdgeInsetsMake(min(-scrollView.contentOffset.y, originalTopInset+height),0,0,0)
}
}
if !stopped {
return
}
if scrollView.dragging && state == .Stopped {
state = .Dragging
if scrollView.isDragging && state == .stopped {
state = .dragging
updateContainerView(state)
}
var y: CGFloat = 0.0
if position == .Top {
if position == .top {
y = -(contentOffset.y)
} else if position == .Bottom {
y = -(scrollView.contentSize.height - (contentOffset.y + CGRectGetHeight(scrollView.bounds) + originalBottomInset))
} else if position == .bottom {
y = -(scrollView.contentSize.height - (contentOffset.y + scrollView.bounds.height + originalBottomInset))
}
if y > 0 {
if state == .Dragging {
if state == .dragging {
containerView.dragging(y/height)
}
configureBackgroundHeightConstraint(y, contentInset: scrollView.contentInset)
}
}
private func configureBackgroundHeightConstraint(contentOffsetY: CGFloat, contentInset: UIEdgeInsets) {
fileprivate func configureBackgroundHeightConstraint(_ contentOffsetY: CGFloat, contentInset: UIEdgeInsets) {
var constant = CGFloat(-1.0)
if position == .Top {
if position == .top {
constant = contentOffsetY + contentInset.top
} else {
constant = contentOffsetY + contentInset.bottom
@ -299,19 +328,19 @@ public class RMRPullToRefreshController: NSObject {
}
}
func updateContainerView(state: RMRPullToRefreshState) {
func updateContainerView(_ state: RMRPullToRefreshState) {
containerView.updateView(state, result: self.result)
}
func updateContainerFrame() {
if let scrollView = self.scrollView, let position = self.position {
var frame = CGRectZero
var frame = CGRect.zero
switch (position) {
case .Top:
frame = CGRectMake(0, -height, CGRectGetWidth(scrollView.bounds), height)
case .Bottom:
let y = max(scrollView.contentSize.height, CGRectGetHeight(scrollView.bounds))
frame = CGRectMake(0, y, CGRectGetWidth(scrollView.bounds), height)
case .top:
frame = CGRect(x: 0, y: -height, width: scrollView.bounds.width, height: height)
case .bottom:
let y = max(scrollView.contentSize.height, scrollView.bounds.height)
frame = CGRect(x: 0, y: y, width: scrollView.bounds.width, height: height)
}
self.containerView.frame = frame
@ -322,20 +351,20 @@ public class RMRPullToRefreshController: NSObject {
if let scrollView = scrollView, let position = self.position {
var inset = scrollView.contentInset
switch (position) {
case .Top:
case .top:
inset.top = originalTopInset
case .Bottom:
case .bottom:
inset.bottom = originalBottomInset
}
setContentInset(inset, animated: true)
}
}
func setContentInset(contentInset: UIEdgeInsets, animated: Bool) {
func setContentInset(_ contentInset: UIEdgeInsets, animated: Bool) {
changingContentInset = true
UIView.animateWithDuration(0.3,
UIView.animate(withDuration: 0.3,
delay: 0.0,
options: UIViewAnimationOptions.BeginFromCurrentState,
options: UIViewAnimationOptions.beginFromCurrentState,
animations: { [weak self]() -> Void in
self?.scrollView?.contentInset = contentInset
}, completion: { [weak self](finished) -> Void in
@ -343,20 +372,20 @@ public class RMRPullToRefreshController: NSObject {
})
}
func checkContentSize(scrollView: UIScrollView) -> Bool{
let height = CGRectGetHeight(scrollView.bounds)
func checkContentSize(_ scrollView: UIScrollView) -> Bool{
let height = scrollView.bounds.height
if scrollView.contentSize.height < height {
scrollView.contentSize = CGSizeMake(scrollView.contentSize.width, height)
scrollView.contentSize = CGSize(width: scrollView.contentSize.width, height: height)
return false
}
return true
}
func shouldHideWhenStopLoading() -> Bool{
return (result != .Error) || (result == .Error && hideWhenError)
return (result != .error) || (result == .error && hideWhenError)
}
func hideDelay(result: RMRPullToRefreshResultType) -> NSTimeInterval {
func hideDelay(_ result: RMRPullToRefreshResultType) -> TimeInterval {
if let delay = hideDelayValues[result] {
return delay
}
@ -365,16 +394,16 @@ public class RMRPullToRefreshController: NSObject {
// MARK: - KVO
public func subscribeOnScrollViewEvents() {
open func subscribeOnScrollViewEvents() {
if !subscribing, let scrollView = self.scrollView {
scrollView.addObserver(self, forKeyPath: RMRPullToRefreshConstants.KeyPaths.ContentOffset, options: .New, context: nil)
scrollView.addObserver(self, forKeyPath: RMRPullToRefreshConstants.KeyPaths.ContentSize, options: .New, context: nil)
scrollView.addObserver(self, forKeyPath: RMRPullToRefreshConstants.KeyPaths.PanState, options: .New, context: nil)
scrollView.addObserver(self, forKeyPath: RMRPullToRefreshConstants.KeyPaths.ContentOffset, options: .new, context: nil)
scrollView.addObserver(self, forKeyPath: RMRPullToRefreshConstants.KeyPaths.ContentSize, options: .new, context: nil)
scrollView.addObserver(self, forKeyPath: RMRPullToRefreshConstants.KeyPaths.PanState, options: .new, context: nil)
subscribing = true
}
}
public func unsubscribeFromScrollViewEvents() {
open func unsubscribeFromScrollViewEvents() {
if subscribing, let scrollView = self.containerView.superview {
scrollView.removeObserver(self, forKeyPath: RMRPullToRefreshConstants.KeyPaths.ContentOffset)
scrollView.removeObserver(self, forKeyPath: RMRPullToRefreshConstants.KeyPaths.ContentSize)
@ -383,24 +412,24 @@ public class RMRPullToRefreshController: NSObject {
}
}
override public func observeValueForKeyPath(keyPath: String?, ofObject object: AnyObject?, change: [String : AnyObject]?, context: UnsafeMutablePointer<Void>) {
override open func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) {
if keyPath == RMRPullToRefreshConstants.KeyPaths.ContentOffset {
if let newContentOffset = change?[NSKeyValueChangeNewKey]?.CGPointValue, scrollView = self.scrollView {
if let newContentOffset = (change?[NSKeyValueChangeKey.newKey] as? NSValue)?.cgPointValue, let scrollView = self.scrollView {
scrollViewDidScroll(scrollView, contentOffset:newContentOffset)
}
} else if keyPath == RMRPullToRefreshConstants.KeyPaths.ContentSize {
if let newContentSize = change?[NSKeyValueChangeNewKey]?.CGSizeValue(), scrollView = self.scrollView {
if let newContentSize = (change?[NSKeyValueChangeKey.newKey] as? NSValue)?.cgSizeValue, let scrollView = self.scrollView {
if checkContentSize(scrollView) {
scrollViewDidChangeContentSize(scrollView, contentSize: newContentSize)
}
}
} else if keyPath == RMRPullToRefreshConstants.KeyPaths.PanState {
if let rawValue = change?[NSKeyValueChangeNewKey] as? Int {
if let state = UIGestureRecognizerState(rawValue: rawValue), scrollView = self.scrollView {
if let rawValue = change?[NSKeyValueChangeKey.newKey] as? Int {
if let state = UIGestureRecognizerState(rawValue: rawValue), let scrollView = self.scrollView {
scrollViewDidChangePanState(scrollView, panState: state)
}
}
}
}
}
}

12
Classes/RMRPullToRefreshView.swift Normal file → Executable file
View File

@ -8,18 +8,18 @@
import UIKit
public class RMRPullToRefreshView: UIView, RMRPullToRefreshViewProtocol {
open class RMRPullToRefreshView: UIView, RMRPullToRefreshViewProtocol {
var pullToRefreshIsLoading = false
// Begin Loading
public func prepareForLoadingAnimation(startProgress: CGFloat) {}
public func beginLoadingAnimation() {}
open func prepareForLoadingAnimation(_ startProgress: CGFloat) {}
open func beginLoadingAnimation() {}
// End Loading
public func willEndLoadingAnimation() {}
public func didEndLoadingAnimation(hidden: Bool) {}
open func willEndLoadingAnimation() {}
open func didEndLoadingAnimation(_ hidden: Bool) {}
// Dragging
public func didChangeDraggingProgress(progress: CGFloat) {}
open func didChangeDraggingProgress(_ progress: CGFloat) {}
}

8
Classes/RMRPullToRefreshViewProtocol.swift Normal file → Executable file
View File

@ -11,13 +11,13 @@ import UIKit
public protocol RMRPullToRefreshViewProtocol {
// Begin Loading
func prepareForLoadingAnimation(startProgress: CGFloat)
func prepareForLoadingAnimation(_ startProgress: CGFloat)
func beginLoadingAnimation()
// End Loading
func willEndLoadingAnimation()
func didEndLoadingAnimation(hidden: Bool)
func didEndLoadingAnimation(_ hidden: Bool)
// Dragging
func didChangeDraggingProgress(progress: CGFloat)
}
func didChangeDraggingProgress(_ progress: CGFloat)
}

View File

@ -2,4 +2,7 @@ source 'https://github.com/CocoaPods/Specs.git'
use_frameworks!
pod 'RMRPullToRefresh', :git => "git@git.redmadrobot.com:im/RMRPullToRefresh.git"
target 'RMRPullToRefreshExample' do
project 'RMRPullToRefreshExample.xcodeproj'
pod 'RMRPullToRefresh, :path => "../"
end

View File

@ -14,30 +14,30 @@ class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow?
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
// Override point for customization after application launch.
return true
}
func applicationWillResignActive(application: UIApplication) {
func applicationWillResignActive(_ application: UIApplication) {
// Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.
// Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game.
}
func applicationDidEnterBackground(application: UIApplication) {
func applicationDidEnterBackground(_ application: UIApplication) {
// Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later.
// If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
}
func applicationWillEnterForeground(application: UIApplication) {
func applicationWillEnterForeground(_ application: UIApplication) {
// Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background.
}
func applicationDidBecomeActive(application: UIApplication) {
func applicationDidBecomeActive(_ application: UIApplication) {
// Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
}
func applicationWillTerminate(application: UIApplication) {
func applicationWillTerminate(_ application: UIApplication) {
// Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
}

View File

@ -10,14 +10,14 @@ import UIKit
import RMRPullToRefresh
enum AnimationStage: Int {
case Stage1 // big medium small
case Stage2 // big medium
case Stage3 // big
case Stage4 //
case Stage5 // big
case Stage6 // big medium
case stage1 // big medium small
case stage2 // big medium
case stage3 // big
case stage4 //
case stage5 // big
case stage6 // big medium
static var count: Int { return AnimationStage.Stage6.hashValue + 1}
static var count: Int { return AnimationStage.stage6.hashValue + 1}
}
class BeelineView: RMRPullToRefreshView {
@ -30,22 +30,22 @@ class BeelineView: RMRPullToRefreshView {
var animationStage: AnimationStage?
class func XIB_VIEW() -> BeelineView? {
let subviewArray = NSBundle.mainBundle().loadNibNamed("BeelineView", owner: self, options: nil)
return subviewArray.first as? BeelineView
let subviewArray = Bundle.main.loadNibNamed("BeelineView", owner: self, options: nil)
return subviewArray?.first as? BeelineView
}
// MARK: - Private
func hideBigIcons(hide: Bool) {
for iV in bigIcons { iV.hidden = hide }
func hideBigIcons(_ hide: Bool) {
for iV in bigIcons { iV.isHidden = hide }
}
func hideMediumIcons(hide: Bool) {
for iV in mediumIcons { iV.hidden = hide }
func hideMediumIcons(_ hide: Bool) {
for iV in mediumIcons { iV.isHidden = hide }
}
func hideSmallIcons(hide: Bool) {
for iV in smallIcons { iV.hidden = hide }
func hideSmallIcons(_ hide: Bool) {
for iV in smallIcons { iV.isHidden = hide }
}
@objc func executeAnimation() {
@ -54,20 +54,20 @@ class BeelineView: RMRPullToRefreshView {
return
}
hideBigIcons(animationStage == .Stage4)
hideMediumIcons(animationStage == .Stage3 || animationStage == .Stage4 || animationStage == .Stage5)
hideSmallIcons(animationStage != .Stage1)
hideBigIcons(animationStage == .stage4)
hideMediumIcons(animationStage == .stage3 || animationStage == .stage4 || animationStage == .stage5)
hideSmallIcons(animationStage != .stage1)
if let stage = animationStage {
animationStage = AnimationStage(rawValue: (stage.rawValue+1)%AnimationStage.count)
}
performSelector(#selector(executeAnimation), withObject: nil, afterDelay: 0.4)
perform(#selector(executeAnimation), with: nil, afterDelay: 0.4)
}
// MARK: - RMRPullToRefreshViewProtocol
override func didChangeDraggingProgress(progress: CGFloat) {
override func didChangeDraggingProgress(_ progress: CGFloat) {
hideBigIcons(progress < 0.33)
hideMediumIcons(progress < 0.66)
hideSmallIcons(progress < 0.99)
@ -75,11 +75,11 @@ class BeelineView: RMRPullToRefreshView {
override func beginLoadingAnimation() {
animationIsCanceled = false
animationStage = .Stage1
animationStage = .stage1
executeAnimation()
}
override func didEndLoadingAnimation(hidden: Bool) {
override func didEndLoadingAnimation(_ hidden: Bool) {
animationIsCanceled = true
}
}

View File

@ -16,23 +16,23 @@ class PerekrestokView: RMRPullToRefreshView {
var fromValue: CGFloat = 0.0
class func XIB_VIEW() -> PerekrestokView? {
let subviewArray = NSBundle.mainBundle().loadNibNamed("PerekrestokView", owner: self, options: nil)
return subviewArray.first as? PerekrestokView
let subviewArray = Bundle.main.loadNibNamed("PerekrestokView", owner: self, options: nil)
return subviewArray?.first as? PerekrestokView
}
// MARK: - Private
func angle(progress: CGFloat) -> CGFloat {
func angle(_ progress: CGFloat) -> CGFloat {
return -CGFloat(M_PI)/progress
}
// MARK: - RMRPullToRefreshViewProtocol
override func didChangeDraggingProgress(progress: CGFloat) {
logoImageView.transform = CGAffineTransformMakeRotation(angle(progress));
override func didChangeDraggingProgress(_ progress: CGFloat) {
logoImageView.transform = CGAffineTransform(rotationAngle: angle(progress));
}
override func prepareForLoadingAnimation(startProgress: CGFloat) {
override func prepareForLoadingAnimation(_ startProgress: CGFloat) {
fromValue = angle(startProgress)
}
@ -43,10 +43,10 @@ class PerekrestokView: RMRPullToRefreshView {
rotationAnimation.duration = 0.9
rotationAnimation.repeatCount = HUGE
self.logoImageView.layer.addAnimation(rotationAnimation, forKey: "transformAnimation")
self.logoImageView.layer.add(rotationAnimation, forKey: "transformAnimation")
}
override func didEndLoadingAnimation(hidden: Bool) {
self.logoImageView.layer.removeAnimationForKey("transformAnimation")
override func didEndLoadingAnimation(_ hidden: Bool) {
self.logoImageView.layer.removeAnimation(forKey: "transformAnimation")
}
}

View File

@ -11,23 +11,23 @@ import UIKit
class TableViewController: UITableViewController {
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
super.prepareForSegue(segue, sender: sender)
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
super.prepare(for: segue, sender: sender)
if let identifier = segue.identifier, let controller = segue.destinationViewController as? ViewController {
if let identifier = segue.identifier, let controller = segue.destination as? ViewController {
switch identifier {
case "perekrestok_top":
controller.exampleType = .PerekrestokTop
controller.exampleType = .perekrestokTop
case "perekrestok_bottom":
controller.exampleType = .PerekrestokBottom
controller.exampleType = .perekrestokBottom
case "beeline_top":
controller.exampleType = .BeelineTop
controller.exampleType = .beelineTop
case "beeline_bottom":
controller.exampleType = .BeelineBottom
controller.exampleType = .beelineBottom
case "redmadrobot_top":
controller.exampleType = .RedmadrobotTop
controller.exampleType = .redmadrobotTop
case "redmadrobot_bottom":
controller.exampleType = .RedmadrobotBottom
controller.exampleType = .redmadrobotBottom
default:
break
}

View File

@ -10,28 +10,28 @@ import UIKit
import RMRPullToRefresh
public enum ExampleType: Int {
case PerekrestokTop
case PerekrestokBottom
case BeelineTop
case BeelineBottom
case RedmadrobotTop
case RedmadrobotBottom
case perekrestokTop
case perekrestokBottom
case beelineTop
case beelineBottom
case redmadrobotTop
case redmadrobotBottom
}
class ViewController: UIViewController, UITableViewDataSource, UITableViewDelegate, UIActionSheetDelegate {
@IBOutlet weak var tableView: UITableView!
var exampleType: ExampleType = .BeelineBottom
var exampleType: ExampleType = .beelineBottom
var pullToRefresh: RMRPullToRefresh?
let formatter = NSDateFormatter()
let formatter = DateFormatter()
var items: [String] = []
var count = 2
var result = RMRPullToRefreshResultType.Success
var result = RMRPullToRefreshResultType.success
override func viewDidLoad() {
super.viewDidLoad()
@ -47,8 +47,8 @@ class ViewController: UIViewController, UITableViewDataSource, UITableViewDelega
func configurePullToRefresh() {
pullToRefresh = RMRPullToRefresh(scrollView: tableView, position: position()) { [weak self] _ in
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, Int64(5.0 * Double(NSEC_PER_SEC))), dispatch_get_main_queue(), {
if self?.result == .Success {
DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + Double(Int64(5.0 * Double(NSEC_PER_SEC))) / Double(NSEC_PER_SEC), execute: {
if self?.result == .success {
self?.loadMore()
}
if let result = self?.result {
@ -57,15 +57,15 @@ class ViewController: UIViewController, UITableViewDataSource, UITableViewDelega
})
}
if exampleType == .PerekrestokTop || exampleType == .PerekrestokBottom {
if exampleType == .perekrestokTop || exampleType == .perekrestokBottom {
perekrestok()
} else if exampleType == .BeelineTop || exampleType == .BeelineBottom {
} else if exampleType == .beelineTop || exampleType == .beelineBottom {
beeline()
} else if exampleType == .RedmadrobotTop || exampleType == .RedmadrobotBottom {
} else if exampleType == .redmadrobotTop || exampleType == .redmadrobotBottom {
redmadrobot()
}
pullToRefresh?.setHideDelay(5.0, result: .Success)
pullToRefresh?.setHideDelay(5.0, result: .success)
pullToRefresh?.hideWhenError = false
}
@ -75,8 +75,8 @@ class ViewController: UIViewController, UITableViewDataSource, UITableViewDelega
func perekrestok() {
if let pullToRefreshView = PerekrestokView.XIB_VIEW() {
pullToRefresh?.configureView(pullToRefreshView, state: .Dragging, result: .Success)
pullToRefresh?.configureView(pullToRefreshView, state: .Loading, result: .Success)
pullToRefresh?.configureView(pullToRefreshView, state: .dragging, result: .success)
pullToRefresh?.configureView(pullToRefreshView, state: .loading, result: .success)
}
pullToRefresh?.height = 90.0
pullToRefresh?.backgroundColor = UIColor(red: 16.0/255.0,
@ -88,11 +88,11 @@ class ViewController: UIViewController, UITableViewDataSource, UITableViewDelega
func beeline() {
if let pullToRefreshView = BeelineView.XIB_VIEW() {
pullToRefresh?.configureView(pullToRefreshView, state: .Dragging, result: .Success)
pullToRefresh?.configureView(pullToRefreshView, state: .Loading, result: .Success)
pullToRefresh?.configureView(pullToRefreshView, state: .dragging, result: .success)
pullToRefresh?.configureView(pullToRefreshView, state: .loading, result: .success)
}
pullToRefresh?.height = 90.0
pullToRefresh?.backgroundColor = UIColor.whiteColor()
pullToRefresh?.backgroundColor = UIColor.white
}
func redmadrobot() {
@ -100,36 +100,36 @@ class ViewController: UIViewController, UITableViewDataSource, UITableViewDelega
}
func position() -> RMRPullToRefreshPosition {
if exampleType == .PerekrestokTop || exampleType == .BeelineTop || exampleType == .RedmadrobotTop {
return .Top
if exampleType == .perekrestokTop || exampleType == .beelineTop || exampleType == .redmadrobotTop {
return .top
}
return .Bottom
return .bottom
}
// MARK: - Configure
func someConfiguring() {
formatter.dateStyle = NSDateFormatterStyle.LongStyle
formatter.timeStyle = .MediumStyle
formatter.dateStyle = DateFormatter.Style.long
formatter.timeStyle = .medium
}
// MARK: - Action
@IBAction func settings(sender: AnyObject) {
UIActionSheet(title: "Result type", delegate: self, cancelButtonTitle: nil, destructiveButtonTitle: nil, otherButtonTitles: ".Success", ".NoUpdates", ".Error").showInView(self.view)
@IBAction func settings(_ sender: AnyObject) {
UIActionSheet(title: "Result type", delegate: self, cancelButtonTitle: nil, destructiveButtonTitle: nil, otherButtonTitles: ".Success", ".NoUpdates", ".Error").show(in: self.view)
}
// MARK: - UIActionSheetDelegate
func actionSheet(actionSheet: UIActionSheet, clickedButtonAtIndex buttonIndex: Int) {
func actionSheet(_ actionSheet: UIActionSheet, clickedButtonAt buttonIndex: Int) {
switch buttonIndex {
case 0:
self.result = .Success
self.result = .success
case 1:
self.result = .NoUpdates
self.result = .noUpdates
case 2:
self.result = .Error
self.result = .error
default:
break;
}
@ -139,30 +139,30 @@ class ViewController: UIViewController, UITableViewDataSource, UITableViewDelega
func loadData() {
for _ in 0...count {
items.append(formatter.stringFromDate(NSDate()))
items.append(formatter.string(from: Date()))
}
}
func loadMore() {
for _ in 0...20 {
self.items.append(formatter.stringFromDate(NSDate(timeIntervalSinceNow: 20)))
self.items.append(formatter.string(from: Date(timeIntervalSinceNow: 20)))
}
self.tableView.reloadData()
}
// MARK: - TableView
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("Cell", forIndexPath: indexPath)
cell.textLabel?.text = items[indexPath.row]
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath)
cell.textLabel?.text = items[(indexPath as NSIndexPath).row]
return cell
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return items.count
}
func numberOfSectionsInTableView(tableView: UITableView) -> Int {
func numberOfSections(in tableView: UITableView) -> Int {
return 1;
}
}

View File

@ -7,10 +7,10 @@
objects = {
/* Begin PBXBuildFile section */
2CEF3E7B42820531D2D97DCC /* Pods_RMRPullToRefreshExample.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A4DF5731A80639276BB33DCA /* Pods_RMRPullToRefreshExample.framework */; };
8921D4F51CA425B4000D28E3 /* PerekrestokView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8921D4F41CA425B4000D28E3 /* PerekrestokView.swift */; };
8921D4F71CA425C0000D28E3 /* PerekrestokView.xib in Resources */ = {isa = PBXBuildFile; fileRef = 8921D4F61CA425C0000D28E3 /* PerekrestokView.xib */; };
8952BE3E1CBACA1D00D94689 /* TableViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8952BE3D1CBACA1D00D94689 /* TableViewController.swift */; };
89B014751CBAE22F002AB1B7 /* Pods.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 89B014741CBAE22F002AB1B7 /* Pods.framework */; };
89B014771CBAE3D5002AB1B7 /* RMRPullToRefresh.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 89B014761CBAE3D5002AB1B7 /* RMRPullToRefresh.framework */; };
89B06BF01CBA8A4900485A08 /* BeelineView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 89B06BEF1CBA8A4900485A08 /* BeelineView.swift */; };
89B06BF21CBA8B0700485A08 /* BeelineView.xib in Resources */ = {isa = PBXBuildFile; fileRef = 89B06BF11CBA8B0700485A08 /* BeelineView.xib */; };
@ -22,11 +22,11 @@
/* End PBXBuildFile section */
/* Begin PBXFileReference section */
51A8D36C5CCC1E18D2666CD6 /* Pods-RMRPullToRefreshExample.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RMRPullToRefreshExample.debug.xcconfig"; path = "Pods/Target Support Files/Pods-RMRPullToRefreshExample/Pods-RMRPullToRefreshExample.debug.xcconfig"; sourceTree = "<group>"; };
766D53F6605D8961328E54A1 /* Pods.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = Pods.debug.xcconfig; path = "Pods/Target Support Files/Pods/Pods.debug.xcconfig"; sourceTree = "<group>"; };
8921D4F41CA425B4000D28E3 /* PerekrestokView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PerekrestokView.swift; sourceTree = "<group>"; };
8921D4F61CA425C0000D28E3 /* PerekrestokView.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = PerekrestokView.xib; sourceTree = "<group>"; };
8952BE3D1CBACA1D00D94689 /* TableViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TableViewController.swift; sourceTree = "<group>"; };
89B014741CBAE22F002AB1B7 /* Pods.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Pods.framework; path = "../../../../Library/Developer/Xcode/DerivedData/RMRPullToRefresh-fwnpioedcaituoahusazwcgryphj/Build/Products/Debug-iphonesimulator/Pods.framework"; sourceTree = "<group>"; };
89B014761CBAE3D5002AB1B7 /* RMRPullToRefresh.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = RMRPullToRefresh.framework; path = "../../../../Library/Developer/Xcode/DerivedData/RMRPullToRefresh-fwnpioedcaituoahusazwcgryphj/Build/Products/Debug-iphonesimulator/RMRPullToRefresh.framework"; sourceTree = "<group>"; };
89B06BEF1CBA8A4900485A08 /* BeelineView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BeelineView.swift; sourceTree = "<group>"; };
89B06BF11CBA8B0700485A08 /* BeelineView.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = BeelineView.xib; sourceTree = "<group>"; };
@ -37,6 +37,8 @@
89CB123E1C9DA07B00048E46 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
89CB12411C9DA07B00048E46 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = "<group>"; };
89CB12431C9DA07B00048E46 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
9373B01A0C7A0314295D05D2 /* Pods-RMRPullToRefreshExample.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RMRPullToRefreshExample.release.xcconfig"; path = "Pods/Target Support Files/Pods-RMRPullToRefreshExample/Pods-RMRPullToRefreshExample.release.xcconfig"; sourceTree = "<group>"; };
A4DF5731A80639276BB33DCA /* Pods_RMRPullToRefreshExample.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_RMRPullToRefreshExample.framework; sourceTree = BUILT_PRODUCTS_DIR; };
D48C26E126E3942BBDFD40CF /* Pods.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = Pods.release.xcconfig; path = "Pods/Target Support Files/Pods/Pods.release.xcconfig"; sourceTree = "<group>"; };
/* End PBXFileReference section */
@ -46,7 +48,7 @@
buildActionMask = 2147483647;
files = (
89B014771CBAE3D5002AB1B7 /* RMRPullToRefresh.framework in Frameworks */,
89B014751CBAE22F002AB1B7 /* Pods.framework in Frameworks */,
2CEF3E7B42820531D2D97DCC /* Pods_RMRPullToRefreshExample.framework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@ -58,6 +60,8 @@
children = (
766D53F6605D8961328E54A1 /* Pods.debug.xcconfig */,
D48C26E126E3942BBDFD40CF /* Pods.release.xcconfig */,
51A8D36C5CCC1E18D2666CD6 /* Pods-RMRPullToRefreshExample.debug.xcconfig */,
9373B01A0C7A0314295D05D2 /* Pods-RMRPullToRefreshExample.release.xcconfig */,
);
name = Pods;
sourceTree = "<group>";
@ -111,7 +115,7 @@
isa = PBXGroup;
children = (
89B014761CBAE3D5002AB1B7 /* RMRPullToRefresh.framework */,
89B014741CBAE22F002AB1B7 /* Pods.framework */,
A4DF5731A80639276BB33DCA /* Pods_RMRPullToRefreshExample.framework */,
);
name = Frameworks;
sourceTree = "<group>";
@ -123,12 +127,12 @@
isa = PBXNativeTarget;
buildConfigurationList = 89CB12461C9DA07B00048E46 /* Build configuration list for PBXNativeTarget "RMRPullToRefreshExample" */;
buildPhases = (
00D4D85E4DF2FF039A017773 /* Check Pods Manifest.lock */,
00D4D85E4DF2FF039A017773 /* [CP] Check Pods Manifest.lock */,
89CB12301C9DA07B00048E46 /* Sources */,
89CB12311C9DA07B00048E46 /* Frameworks */,
89CB12321C9DA07B00048E46 /* Resources */,
2BE863C51DEA329C1234F1B0 /* Embed Pods Frameworks */,
C137BE069515EFF1A69455DF /* Copy Pods Resources */,
2BE863C51DEA329C1234F1B0 /* [CP] Embed Pods Frameworks */,
C137BE069515EFF1A69455DF /* [CP] Copy Pods Resources */,
);
buildRules = (
);
@ -151,6 +155,7 @@
TargetAttributes = {
89CB12331C9DA07B00048E46 = {
CreatedOnToolsVersion = 7.2.1;
LastSwiftMigration = 0800;
};
};
};
@ -188,49 +193,49 @@
/* End PBXResourcesBuildPhase section */
/* Begin PBXShellScriptBuildPhase section */
00D4D85E4DF2FF039A017773 /* Check Pods Manifest.lock */ = {
00D4D85E4DF2FF039A017773 /* [CP] Check Pods Manifest.lock */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputPaths = (
);
name = "Check Pods Manifest.lock";
name = "[CP] Check Pods Manifest.lock";
outputPaths = (
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "diff \"${PODS_ROOT}/../Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [[ $? != 0 ]] ; then\n cat << EOM\nerror: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\nEOM\n exit 1\nfi\n";
shellScript = "diff \"${PODS_ROOT}/../Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n";
showEnvVarsInLog = 0;
};
2BE863C51DEA329C1234F1B0 /* Embed Pods Frameworks */ = {
2BE863C51DEA329C1234F1B0 /* [CP] Embed Pods Frameworks */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputPaths = (
);
name = "Embed Pods Frameworks";
name = "[CP] Embed Pods Frameworks";
outputPaths = (
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods/Pods-frameworks.sh\"\n";
shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-RMRPullToRefreshExample/Pods-RMRPullToRefreshExample-frameworks.sh\"\n";
showEnvVarsInLog = 0;
};
C137BE069515EFF1A69455DF /* Copy Pods Resources */ = {
C137BE069515EFF1A69455DF /* [CP] Copy Pods Resources */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputPaths = (
);
name = "Copy Pods Resources";
name = "[CP] Copy Pods Resources";
outputPaths = (
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods/Pods-resources.sh\"\n";
shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-RMRPullToRefreshExample/Pods-RMRPullToRefreshExample-resources.sh\"\n";
showEnvVarsInLog = 0;
};
/* End PBXShellScriptBuildPhase section */
@ -353,7 +358,7 @@
};
89CB12471C9DA07B00048E46 /* Debug */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = 766D53F6605D8961328E54A1 /* Pods.debug.xcconfig */;
baseConfigurationReference = 51A8D36C5CCC1E18D2666CD6 /* Pods-RMRPullToRefreshExample.debug.xcconfig */;
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
FRAMEWORK_SEARCH_PATHS = "$(inherited)";
@ -361,12 +366,13 @@
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
PRODUCT_BUNDLE_IDENTIFIER = com.redmadrobot.RMRPullToRefresh;
PRODUCT_NAME = RMRPullToRefreshExample;
SWIFT_VERSION = 3.0;
};
name = Debug;
};
89CB12481C9DA07B00048E46 /* Release */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = D48C26E126E3942BBDFD40CF /* Pods.release.xcconfig */;
baseConfigurationReference = 9373B01A0C7A0314295D05D2 /* Pods-RMRPullToRefreshExample.release.xcconfig */;
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
FRAMEWORK_SEARCH_PATHS = "$(inherited)";
@ -374,6 +380,7 @@
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
PRODUCT_BUNDLE_IDENTIFIER = com.redmadrobot.RMRPullToRefresh;
PRODUCT_NAME = RMRPullToRefreshExample;
SWIFT_VERSION = 3.0;
};
name = Release;
};