From 31ce278dc69fa0ad9df90b6ecaaa74926325a091 Mon Sep 17 00:00:00 2001 From: Josip Cavar Date: Sat, 23 Sep 2017 18:33:50 +0200 Subject: [PATCH 1/9] Update to Xcode 9 recommended settings --- PullToRefresh.xcodeproj/project.pbxproj | 14 +++++++++++++- .../xcshareddata/xcschemes/PullToRefresh.xcscheme | 4 +++- .../xcshareddata/xcschemes/Refresher.xcscheme | 4 +++- 3 files changed, 19 insertions(+), 3 deletions(-) diff --git a/PullToRefresh.xcodeproj/project.pbxproj b/PullToRefresh.xcodeproj/project.pbxproj index c289c0a..3350805 100644 --- a/PullToRefresh.xcodeproj/project.pbxproj +++ b/PullToRefresh.xcodeproj/project.pbxproj @@ -296,7 +296,7 @@ isa = PBXProject; attributes = { LastSwiftUpdateCheck = 0700; - LastUpgradeCheck = 0800; + LastUpgradeCheck = 0900; ORGANIZATIONNAME = "Josip Cavar"; TargetAttributes = { C7AC6CCB19A7FE6D007107DF = { @@ -523,14 +523,20 @@ CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INFINITE_RECURSION = YES; CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; CLANG_WARN_SUSPICIOUS_MOVE = YES; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; @@ -570,14 +576,20 @@ CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INFINITE_RECURSION = YES; CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; CLANG_WARN_SUSPICIOUS_MOVE = YES; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; diff --git a/PullToRefresh.xcodeproj/xcshareddata/xcschemes/PullToRefresh.xcscheme b/PullToRefresh.xcodeproj/xcshareddata/xcschemes/PullToRefresh.xcscheme index 16de955..0ce1411 100644 --- a/PullToRefresh.xcodeproj/xcshareddata/xcschemes/PullToRefresh.xcscheme +++ b/PullToRefresh.xcodeproj/xcshareddata/xcschemes/PullToRefresh.xcscheme @@ -1,6 +1,6 @@ Date: Sat, 23 Sep 2017 18:35:57 +0200 Subject: [PATCH 2/9] Change M_PI to Double.pi --- PullToRefreshDemo/PacmanAnimator.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/PullToRefreshDemo/PacmanAnimator.swift b/PullToRefreshDemo/PacmanAnimator.swift index 9a3f5bb..7d48ebc 100644 --- a/PullToRefreshDemo/PacmanAnimator.swift +++ b/PullToRefreshDemo/PacmanAnimator.swift @@ -88,7 +88,7 @@ class PacmanAnimator: UIView, PullToRefreshViewDelegate { superview.layer.addSublayer(layerLoader) } let center = CGPoint(x: 30, y: superview.frame.size.height / 2) - let bezierPathLoader = UIBezierPath(arcCenter: center, radius: CGFloat(10), startAngle: CGFloat(0), endAngle: CGFloat(2 * M_PI), clockwise: true) + let bezierPathLoader = UIBezierPath(arcCenter: center, radius: CGFloat(10), startAngle: CGFloat(0), endAngle: CGFloat(2 * Double.pi), clockwise: true) let bezierPathSeparator = UIBezierPath() bezierPathSeparator.move(to: CGPoint(x: 0, y: superview.frame.height - 1)) bezierPathSeparator.addLine(to: CGPoint(x: superview.frame.width, y: superview.frame.height - 1)) From 017e45202dda4125a0af3a4441de29474228e12f Mon Sep 17 00:00:00 2001 From: Josip Cavar Date: Sat, 23 Sep 2017 18:55:07 +0200 Subject: [PATCH 3/9] Move to new observation API in Swift 4 --- PullToRefresh.xcodeproj/project.pbxproj | 18 +++--- .../PullToRefreshViewController.swift | 4 +- Refresher/PullToRefreshView.swift | 59 ++++++------------- 3 files changed, 30 insertions(+), 51 deletions(-) diff --git a/PullToRefresh.xcodeproj/project.pbxproj b/PullToRefresh.xcodeproj/project.pbxproj index 3350805..d612ddd 100644 --- a/PullToRefresh.xcodeproj/project.pbxproj +++ b/PullToRefresh.xcodeproj/project.pbxproj @@ -301,16 +301,16 @@ TargetAttributes = { C7AC6CCB19A7FE6D007107DF = { CreatedOnToolsVersion = 6.0; - LastSwiftMigration = 0800; + LastSwiftMigration = 0900; }; C7AC6CD519A7FE6D007107DF = { CreatedOnToolsVersion = 6.0; - LastSwiftMigration = 0800; + LastSwiftMigration = 0900; TestTargetID = C7D1CF8E199BB3C8009FD485; }; C7D1CF8E199BB3C8009FD485 = { CreatedOnToolsVersion = 6.0; - LastSwiftMigration = 0800; + LastSwiftMigration = 0900; }; }; }; @@ -451,7 +451,7 @@ PRODUCT_NAME = "$(TARGET_NAME)"; SKIP_INSTALL = YES; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; - SWIFT_VERSION = 3.0; + SWIFT_VERSION = 4.0; VERSIONING_SYSTEM = "apple-generic"; VERSION_INFO_PREFIX = ""; }; @@ -473,7 +473,7 @@ PRODUCT_BUNDLE_IDENTIFIER = "JCA.$(PRODUCT_NAME:rfc1034identifier)"; PRODUCT_NAME = "$(TARGET_NAME)"; SKIP_INSTALL = YES; - SWIFT_VERSION = 3.0; + SWIFT_VERSION = 4.0; VERSIONING_SYSTEM = "apple-generic"; VERSION_INFO_PREFIX = ""; }; @@ -494,7 +494,7 @@ LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = "JCA.$(PRODUCT_NAME:rfc1034identifier)"; PRODUCT_NAME = "$(TARGET_NAME)"; - SWIFT_VERSION = 3.0; + SWIFT_VERSION = 4.0; TEST_HOST = "$(BUILT_PRODUCTS_DIR)/PullToRefreshDemo.app/PullToRefreshDemo"; }; name = Debug; @@ -510,7 +510,7 @@ LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = "JCA.$(PRODUCT_NAME:rfc1034identifier)"; PRODUCT_NAME = "$(TARGET_NAME)"; - SWIFT_VERSION = 3.0; + SWIFT_VERSION = 4.0; TEST_HOST = "$(BUILT_PRODUCTS_DIR)/PullToRefreshDemo.app/PullToRefreshDemo"; }; name = Release; @@ -624,7 +624,7 @@ LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = "JCA.${PRODUCT_NAME:rfc1034identifier}"; PRODUCT_NAME = "$(TARGET_NAME)"; - SWIFT_VERSION = 3.0; + SWIFT_VERSION = 4.0; }; name = Debug; }; @@ -638,7 +638,7 @@ LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = "JCA.${PRODUCT_NAME:rfc1034identifier}"; PRODUCT_NAME = "$(TARGET_NAME)"; - SWIFT_VERSION = 3.0; + SWIFT_VERSION = 4.0; }; name = Release; }; diff --git a/PullToRefreshDemo/PullToRefreshViewController.swift b/PullToRefreshDemo/PullToRefreshViewController.swift index a6b6899..a5295b1 100644 --- a/PullToRefreshDemo/PullToRefreshViewController.swift +++ b/PullToRefreshDemo/PullToRefreshViewController.swift @@ -93,11 +93,11 @@ class PullToRefreshViewController: UIViewController { // Dispose of any resources that can be recreated. } - func tableView(_ tableView: UITableView!, numberOfRowsInSection section: Int) -> Int { + @objc func tableView(_ tableView: UITableView!, numberOfRowsInSection section: Int) -> Int { return 50 } - func tableView(_ tableView: UITableView!, cellForRowAtIndexPath indexPath: IndexPath!) -> UITableViewCell! { + @objc func tableView(_ tableView: UITableView!, cellForRowAtIndexPath indexPath: IndexPath!) -> UITableViewCell! { let cell = UITableViewCell(style: .default, reuseIdentifier: "Cell") cell.textLabel?.text = "Row " + String(indexPath.row + 1) return cell diff --git a/Refresher/PullToRefreshView.swift b/Refresher/PullToRefreshView.swift index aafb850..3d4b226 100644 --- a/Refresher/PullToRefreshView.swift +++ b/Refresher/PullToRefreshView.swift @@ -24,9 +24,6 @@ import UIKit import QuartzCore -private var KVOContext = "RefresherKVOContext" -private let ContentOffsetKeyPath = "contentOffset" - public enum PullToRefreshViewState { case loading @@ -43,7 +40,7 @@ public protocol PullToRefreshViewDelegate { } open class PullToRefreshView: UIView { - + private var observation: NSKeyValueObservation? private var scrollViewBouncesDefaultValue: Bool = false private var scrollViewInsetsDefaultValue: UIEdgeInsets = UIEdgeInsets.zero @@ -101,51 +98,33 @@ open class PullToRefreshView: UIView { // Currently it is not supported to load view from nib } - deinit { - let scrollView = superview as? UIScrollView - scrollView?.removeObserver(self, forKeyPath: ContentOffsetKeyPath, context: &KVOContext) - } - //MARK: UIView methods open override func willMove(toSuperview newSuperview: UIView!) { - superview?.removeObserver(self, forKeyPath: ContentOffsetKeyPath, context: &KVOContext) + self.observation?.invalidate() if let scrollView = newSuperview as? UIScrollView { - scrollView.addObserver(self, forKeyPath: ContentOffsetKeyPath, options: .initial, context: &KVOContext) - scrollViewBouncesDefaultValue = scrollView.bounces - scrollViewInsetsDefaultValue = scrollView.contentInset - } - } - - - //MARK: KVO methods - - open override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) { - if (context == &KVOContext) { - if let scrollView = superview as? UIScrollView , object as? NSObject == scrollView { - if keyPath == ContentOffsetKeyPath { - let offsetWithoutInsets = previousOffset + scrollViewInsetsDefaultValue.top - if (offsetWithoutInsets < -self.frame.size.height) { - if (scrollView.isDragging == false && loading == false) { - loading = true - } else if (loading) { - self.animator.pullToRefresh(self, stateDidChange: .loading) - } else { - self.animator.pullToRefresh(self, stateDidChange: .releaseToRefresh) - animator.pullToRefresh(self, progressDidChange: -offsetWithoutInsets / self.frame.size.height) - } - } else if (loading) { + self.observation = scrollView.observe(\.contentOffset, options: [.initial]) { [unowned self] (scrollView, change) in + let offsetWithoutInsets = self.previousOffset + self.scrollViewInsetsDefaultValue.top + if (offsetWithoutInsets < -self.frame.size.height) { + if (scrollView.isDragging == false && self.loading == false) { + self.loading = true + } else if (self.loading) { self.animator.pullToRefresh(self, stateDidChange: .loading) - } else if (offsetWithoutInsets < 0) { - self.animator.pullToRefresh(self, stateDidChange: .pullToRefresh) - animator.pullToRefresh(self, progressDidChange: -offsetWithoutInsets / self.frame.size.height) + } else { + self.animator.pullToRefresh(self, stateDidChange: .releaseToRefresh) + self.animator.pullToRefresh(self, progressDidChange: -offsetWithoutInsets / self.frame.size.height) } - previousOffset = scrollView.contentOffset.y + } else if (self.loading) { + self.animator.pullToRefresh(self, stateDidChange: .loading) + } else if (offsetWithoutInsets < 0) { + self.animator.pullToRefresh(self, stateDidChange: .pullToRefresh) + self.animator.pullToRefresh(self, progressDidChange: -offsetWithoutInsets / self.frame.size.height) } + self.previousOffset = scrollView.contentOffset.y } - } else { - super.observeValue(forKeyPath: keyPath, of: object, change: change, context: context) + scrollViewBouncesDefaultValue = scrollView.bounces + scrollViewInsetsDefaultValue = scrollView.contentInset } } From fdc552532aeab72a09704b8b5e503c229a15e9c7 Mon Sep 17 00:00:00 2001 From: Josip Cavar Date: Sat, 23 Sep 2017 18:57:58 +0200 Subject: [PATCH 4/9] Update swift-version to 4.0 --- .swift-version | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.swift-version b/.swift-version index 9f55b2c..5186d07 100644 --- a/.swift-version +++ b/.swift-version @@ -1 +1 @@ -3.0 +4.0 From 9527cf498bc88ac86bbc5a82e7227a4107eec730 Mon Sep 17 00:00:00 2001 From: Josip Cavar Date: Sat, 23 Sep 2017 18:59:11 +0200 Subject: [PATCH 5/9] Minor code refactorings --- Refresher/Animator.swift | 3 --- Refresher/PullToRefreshView.swift | 10 ++++------ 2 files changed, 4 insertions(+), 9 deletions(-) diff --git a/Refresher/Animator.swift b/Refresher/Animator.swift index 55eb5b9..10fadf9 100644 --- a/Refresher/Animator.swift +++ b/Refresher/Animator.swift @@ -26,13 +26,11 @@ import QuartzCore import UIKit internal class AnimatorView: UIView { - fileprivate let titleLabel: UILabel = { let label = UILabel() label.translatesAutoresizingMaskIntoConstraints = false return label }() - fileprivate let activityIndicatorView: UIActivityIndicatorView = { let activity = UIActivityIndicatorView(activityIndicatorStyle: .gray) activity.translatesAutoresizingMaskIntoConstraints = false @@ -60,7 +58,6 @@ internal class AnimatorView: UIView { } class Animator: PullToRefreshViewDelegate { - internal let animatorView: AnimatorView init(frame: CGRect) { diff --git a/Refresher/PullToRefreshView.swift b/Refresher/PullToRefreshView.swift index 3d4b226..53c4d8b 100644 --- a/Refresher/PullToRefreshView.swift +++ b/Refresher/PullToRefreshView.swift @@ -25,14 +25,12 @@ import UIKit import QuartzCore public enum PullToRefreshViewState { - case loading case pullToRefresh case releaseToRefresh } public protocol PullToRefreshViewDelegate { - func pullToRefreshAnimationDidStart(_ view: PullToRefreshView) func pullToRefreshAnimationDidEnd(_ view: PullToRefreshView) func pullToRefresh(_ view: PullToRefreshView, progressDidChange progress: CGFloat) @@ -63,7 +61,7 @@ open class PullToRefreshView: UIView { } - //MARK: Object lifecycle methods + // MARK: Object lifecycle methods convenience init(action :@escaping (() -> ()), frame: CGRect) { var bounds = frame @@ -99,7 +97,7 @@ open class PullToRefreshView: UIView { } - //MARK: UIView methods + // MARK: UIView methods open override func willMove(toSuperview newSuperview: UIView!) { self.observation?.invalidate() @@ -129,14 +127,14 @@ open class PullToRefreshView: UIView { } - //MARK: PullToRefreshView methods + // MARK: PullToRefreshView methods private func startAnimating() { let scrollView = superview as! UIScrollView var insets = scrollView.contentInset insets.top += self.frame.size.height - // we need to restore previous offset because we will animate scroll view insets and regular scroll view animating is not applied then + // We need to restore previous offset because we will animate scroll view insets and regular scroll view animating is not applied then scrollView.contentOffset.y = previousOffset scrollView.bounces = false UIView.animate(withDuration: 0.3, delay: 0, options: UIViewAnimationOptions(), animations: { From 025fad51a6e582aa2e7098402678bbdf91a736e4 Mon Sep 17 00:00:00 2001 From: Josip Cavar Date: Sat, 23 Sep 2017 19:03:11 +0200 Subject: [PATCH 6/9] Update travis to new infrastructure --- .travis.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.travis.yml b/.travis.yml index 0087270..50b07c6 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,3 +1,3 @@ -language: objective-c -osx_image: xcode8 -script: xcodebuild test -scheme Refresher -sdk iphonesimulator -destination 'platform=iOS Simulator,name=iPhone 6,OS=9.3' +language: swift +osx_image: xcode9 +script: xcodebuild test -scheme Refresher -sdk iphonesimulator -destination 'platform=iOS Simulator,name=iPhone 6,OS=11.0' From adf6e8768755416a6ffdfa883a399d0a27bdc027 Mon Sep 17 00:00:00 2001 From: Josip Cavar Date: Sat, 23 Sep 2017 19:06:39 +0200 Subject: [PATCH 7/9] Tidy up tests --- RefresherTests/BouncesTests.swift | 10 ++----- RefresherTests/FrameTests.swift | 50 +++++++++---------------------- RefresherTests/LoadingTests.swift | 32 +++++++------------- 3 files changed, 26 insertions(+), 66 deletions(-) diff --git a/RefresherTests/BouncesTests.swift b/RefresherTests/BouncesTests.swift index 58039d2..c330abc 100644 --- a/RefresherTests/BouncesTests.swift +++ b/RefresherTests/BouncesTests.swift @@ -27,21 +27,17 @@ import XCTest class BouncesTests: XCTestCase { override func setUp() { - super.setUp() } override func tearDown() { - super.tearDown() } func testScrollViewBouncesWhenFalse() { - let scrollView = UIScrollView() scrollView.bounces = false; - scrollView.addPullToRefreshWithAction({ () -> () in - }) + scrollView.addPullToRefreshWithAction { } scrollView.startPullToRefresh() XCTAssertTrue(!scrollView.bounces, "bounces should be false") scrollView.stopPullToRefresh() @@ -49,11 +45,9 @@ class BouncesTests: XCTestCase { } func testScrollViewBouncesWhenTrue() { - let scrollView = UIScrollView() scrollView.bounces = true; - scrollView.addPullToRefreshWithAction({ () -> () in - }) + scrollView.addPullToRefreshWithAction { } scrollView.startPullToRefresh() XCTAssertTrue(!scrollView.bounces, "bounces should be false") scrollView.stopPullToRefresh() diff --git a/RefresherTests/FrameTests.swift b/RefresherTests/FrameTests.swift index 06b778e..f732bb6 100644 --- a/RefresherTests/FrameTests.swift +++ b/RefresherTests/FrameTests.swift @@ -27,65 +27,43 @@ import XCTest class FrameTests: XCTestCase { override func setUp() { - super.setUp() } override func tearDown() { - super.tearDown() } func testPullToRefreshViewFrame() { - let scrollView = UIScrollView(frame: CGRect(x: 0, y: 0, width: 100, height: 500)) - scrollView.addPullToRefreshWithAction({ () -> () in - }) - if (scrollView.pullToRefreshView != nil) { - XCTAssertEqual(scrollView.pullToRefreshView!.frame.width, scrollView.frame.width, "scrollView and pullToRefreshView should have same width") - XCTAssertGreaterThan(scrollView.pullToRefreshView!.frame.height, CGFloat(0), "height should be grater than zero") - } else { - XCTAssertNotNil(scrollView.pullToRefreshView, "pullToRefreshView should not be nil") - } + scrollView.addPullToRefreshWithAction { } + XCTAssertNotNil(scrollView.pullToRefreshView, "pullToRefreshView should not be nil") + XCTAssertEqual(scrollView.pullToRefreshView!.frame.width, scrollView.frame.width, "scrollView and pullToRefreshView should have same width") + XCTAssertGreaterThan(scrollView.pullToRefreshView!.frame.height, CGFloat(0), "height should be grater than zero") } func testPullToRefreshViewFrameWithInsets() { - let scrollView = UIScrollView(frame: CGRect(x: 0, y: 0, width: 100, height: 500)) scrollView.contentInset = UIEdgeInsets(top: 40, left: 0, bottom: 0, right: 0) - scrollView.addPullToRefreshWithAction({ () -> () in - }) - if (scrollView.pullToRefreshView != nil) { - XCTAssertEqual(scrollView.pullToRefreshView!.frame.width, scrollView.frame.width, "scrollView and pullToRefreshView should have same width") - XCTAssertGreaterThan(scrollView.pullToRefreshView!.frame.height, CGFloat(0), "height should be grater than zero") - } else { - XCTAssertNotNil(scrollView.pullToRefreshView, "pullToRefreshView should not be nil") - } + scrollView.addPullToRefreshWithAction { } + XCTAssertNotNil(scrollView.pullToRefreshView, "pullToRefreshView should not be nil") + XCTAssertEqual(scrollView.pullToRefreshView!.frame.width, scrollView.frame.width, "scrollView and pullToRefreshView should have same width") + XCTAssertGreaterThan(scrollView.pullToRefreshView!.frame.height, CGFloat(0), "height should be grater than zero") } func testPullToRefreshViewFrameWhenStarted() { - let scrollView = UIScrollView(frame: CGRect(x: 0, y: 0, width: 100, height: 500)) - scrollView.addPullToRefreshWithAction({ () -> () in - }) + scrollView.addPullToRefreshWithAction { } scrollView.startPullToRefresh() - if (scrollView.pullToRefreshView != nil) { - XCTAssertEqual(scrollView.pullToRefreshView!.frame.height, scrollView.contentInset.top, "height should be equal to inset when animating") - } else { - XCTAssertNotNil(scrollView.pullToRefreshView, "pullToRefreshView should not be nil") - } + XCTAssertNotNil(scrollView.pullToRefreshView, "pullToRefreshView should not be nil") + XCTAssertEqual(scrollView.pullToRefreshView!.frame.height, scrollView.contentInset.top, "height should be equal to inset when animating") } func testPullToRefreshViewOffsetWhenStarted() { - let scrollView = UIScrollView(frame: CGRect(x: 0, y: 0, width: 100, height: 500)) - scrollView.addPullToRefreshWithAction({ () -> () in - }) + scrollView.addPullToRefreshWithAction { } scrollView.startPullToRefresh() - if (scrollView.pullToRefreshView != nil) { - XCTAssertEqual(-scrollView.contentInset.top, scrollView.contentOffset.y, "content offset should be equal to content inset") - } else { - XCTAssertNotNil(scrollView.pullToRefreshView, "pullToRefreshView should not be nil") - } + XCTAssertNotNil(scrollView.pullToRefreshView, "pullToRefreshView should not be nil") + XCTAssertEqual(-scrollView.contentInset.top, scrollView.contentOffset.y, "content offset should be equal to content inset") } } diff --git a/RefresherTests/LoadingTests.swift b/RefresherTests/LoadingTests.swift index 9434804..0e9940c 100644 --- a/RefresherTests/LoadingTests.swift +++ b/RefresherTests/LoadingTests.swift @@ -27,44 +27,32 @@ import XCTest class LoadingTests: XCTestCase { override func setUp() { - super.setUp() } override func tearDown() { - super.tearDown() } func testPullToRefreshViewLoading() { - let scrollView = UIScrollView() - scrollView.addPullToRefreshWithAction({ () -> () in - }) + scrollView.addPullToRefreshWithAction { } scrollView.startPullToRefresh() - if (scrollView.pullToRefreshView != nil) { - XCTAssertTrue(scrollView.pullToRefreshView!.loading, "loading should be true") - scrollView.stopPullToRefresh() - XCTAssertFalse(scrollView.pullToRefreshView!.loading, "loading should be false") - } else { - XCTAssertNotNil(scrollView.pullToRefreshView, "pullToRefreshView should not be nil") - } + XCTAssertNotNil(scrollView.pullToRefreshView, "pullToRefreshView should not be nil") + XCTAssertTrue(scrollView.pullToRefreshView!.loading, "loading should be true") + scrollView.stopPullToRefresh() + XCTAssertFalse(scrollView.pullToRefreshView!.loading, "loading should be false") } func testPullToRefreshViewLoadingWithInsets() { - let scrollView = UIScrollView(frame: CGRect(x: 0, y: 0, width: 100, height: 500)) scrollView.contentInset = UIEdgeInsets(top: 40, left: 0, bottom: 0, right: 0) - scrollView.addPullToRefreshWithAction({ () -> () in - }) + scrollView.addPullToRefreshWithAction { } scrollView.startPullToRefresh() - if (scrollView.pullToRefreshView != nil) { - XCTAssertTrue(scrollView.pullToRefreshView!.loading, "loading should be true") - scrollView.stopPullToRefresh() - XCTAssertFalse(scrollView.pullToRefreshView!.loading, "loading should be false") - } else { - XCTAssertNotNil(scrollView.pullToRefreshView, "pullToRefreshView should not be nil") - } + XCTAssertNotNil(scrollView.pullToRefreshView, "pullToRefreshView should not be nil") + XCTAssertTrue(scrollView.pullToRefreshView!.loading, "loading should be true") + scrollView.stopPullToRefresh() + XCTAssertFalse(scrollView.pullToRefreshView!.loading, "loading should be false") } } From 6f6be78cb2d4c8d29a2d83b4c895a657e517e3cc Mon Sep 17 00:00:00 2001 From: Josip Cavar Date: Sat, 23 Sep 2017 19:20:55 +0200 Subject: [PATCH 8/9] Minor code refactorings --- Refresher/PullToRefreshExtension.swift | 6 +++--- Refresher/PullToRefreshView.swift | 8 ++++---- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/Refresher/PullToRefreshExtension.swift b/Refresher/PullToRefreshExtension.swift index bc11cf3..461025f 100644 --- a/Refresher/PullToRefreshExtension.swift +++ b/Refresher/PullToRefreshExtension.swift @@ -38,14 +38,14 @@ extension UIScrollView { } // If you want to add pull to refresh functionality to your UIScrollView just call this method and pass action closure you want to execute while pull to refresh is animating. If you want to stop pull to refresh you must do that manually calling stopPullToRefreshView methods on your scroll view - public func addPullToRefreshWithAction(_ action:@escaping (() -> ())) { + public func addPullToRefreshWithAction(_ action: @escaping (() -> ())) { let pullToRefreshView = PullToRefreshView(action: action, frame: CGRect(x: 0, y: -pullToRefreshDefaultHeight, width: self.frame.size.width, height: pullToRefreshDefaultHeight)) pullToRefreshView.tag = pullToRefreshTag addSubview(pullToRefreshView) } // If you want to use your custom animation and custom subview when pull to refresh is animating, you should call this method and pass your animator and view objects. - public func addPullToRefreshWithAction(_ action:@escaping (() -> ()), withAnimator animator: PullToRefreshViewDelegate, withSubview subview: UIView) { + public func addPullToRefreshWithAction(_ action: @escaping (() -> ()), withAnimator animator: PullToRefreshViewDelegate, withSubview subview: UIView) { let height = subview.frame.height let pullToRefreshView = PullToRefreshView(action: action, frame: CGRect(x: 0, y: -height, width: self.frame.size.width, height: height), animator: animator, subview: subview) pullToRefreshView.tag = pullToRefreshTag @@ -53,7 +53,7 @@ extension UIScrollView { } // - public func addPullToRefreshWithAction(_ action:@escaping (() -> ()), withAnimator animator: T) where T: PullToRefreshViewDelegate { + public func addPullToRefreshWithAction(_ action: @escaping (() -> ()), withAnimator animator: T) where T: PullToRefreshViewDelegate { let height = animator.frame.height let pullToRefreshView = PullToRefreshView(action: action, frame: CGRect(x: 0, y: -height, width: self.frame.size.width, height: height), animator: animator, subview: animator) pullToRefreshView.tag = pullToRefreshTag diff --git a/Refresher/PullToRefreshView.swift b/Refresher/PullToRefreshView.swift index 53c4d8b..91a4569 100644 --- a/Refresher/PullToRefreshView.swift +++ b/Refresher/PullToRefreshView.swift @@ -63,7 +63,7 @@ open class PullToRefreshView: UIView { // MARK: Object lifecycle methods - convenience init(action :@escaping (() -> ()), frame: CGRect) { + convenience init(action: @escaping (() -> ()), frame: CGRect) { var bounds = frame bounds.origin.y = 0 let animator = Animator(frame: bounds) @@ -72,14 +72,14 @@ open class PullToRefreshView: UIView { addSubview(animator.animatorView) } - convenience init(action :@escaping (() -> ()), frame: CGRect, animator: PullToRefreshViewDelegate, subview: UIView) { + convenience init(action: @escaping (() -> ()), frame: CGRect, animator: PullToRefreshViewDelegate, subview: UIView) { self.init(frame: frame, animator: animator) self.action = action; subview.frame = self.bounds addSubview(subview) } - convenience init(action :@escaping (() -> ()), frame: CGRect, animator: PullToRefreshViewDelegate) { + convenience init(action: @escaping (() -> ()), frame: CGRect, animator: PullToRefreshViewDelegate) { self.init(frame: frame, animator: animator) self.action = action; } @@ -93,7 +93,7 @@ open class PullToRefreshView: UIView { public required init?(coder aDecoder: NSCoder) { self.animator = Animator(frame: CGRect.zero) super.init(coder: aDecoder) - // Currently it is not supported to load view from nib + // It is not currently supported to load view from nib } From 824a713aac8515c141f6270afcdc3124f6b8c18e Mon Sep 17 00:00:00 2001 From: Josip Cavar Date: Sat, 23 Sep 2017 20:04:28 +0200 Subject: [PATCH 9/9] Bump version number --- Refresher.podspec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Refresher.podspec b/Refresher.podspec index 25bed73..105627b 100644 --- a/Refresher.podspec +++ b/Refresher.podspec @@ -1,7 +1,7 @@ Pod::Spec.new do |s| s.name = 'Refresher' - s.version = '0.6.1' + s.version = '0.7.0' s.summary = 'Pull to refresh in Swift' s.description = <<-DESC