From 833b9d535767d67e4b7fb11b03d4cccfc1d9ad67 Mon Sep 17 00:00:00 2001 From: Danil Gontovnik Date: Tue, 20 Sep 2016 12:52:46 +0100 Subject: [PATCH] Release 1.1 --- .swift-version | 1 + DGElasticPullToRefresh.podspec | 9 +- .../UserInterfaceState.xcuserstate | Bin 0 -> 17104 bytes .../DGElasticPullToRefreshExample.xcscheme | 91 ++++++++++++++++++ .../xcschemes/xcschememanagement.plist | 22 +++++ README.md | 23 +++-- 6 files changed, 130 insertions(+), 16 deletions(-) create mode 100644 .swift-version create mode 100644 DGElasticPullToRefreshExample.xcodeproj/project.xcworkspace/xcuserdata/gontovnik.xcuserdatad/UserInterfaceState.xcuserstate create mode 100644 DGElasticPullToRefreshExample.xcodeproj/xcuserdata/gontovnik.xcuserdatad/xcschemes/DGElasticPullToRefreshExample.xcscheme create mode 100644 DGElasticPullToRefreshExample.xcodeproj/xcuserdata/gontovnik.xcuserdatad/xcschemes/xcschememanagement.plist diff --git a/.swift-version b/.swift-version new file mode 100644 index 0000000..9f55b2c --- /dev/null +++ b/.swift-version @@ -0,0 +1 @@ +3.0 diff --git a/DGElasticPullToRefresh.podspec b/DGElasticPullToRefresh.podspec index ee89b24..9de0d3a 100644 --- a/DGElasticPullToRefresh.podspec +++ b/DGElasticPullToRefresh.podspec @@ -1,16 +1,17 @@ Pod::Spec.new do |spec| spec.name = "DGElasticPullToRefresh" - spec.version = "1.0.3" + spec.version = "1.1" spec.authors = { "Danil Gontovnik" => "gontovnik.danil@gmail.com" } spec.homepage = "https://github.com/gontovnik/DGElasticPullToRefresh" spec.summary = "Elastic pull to refresh compontent developed in Swift" - spec.source = { :git => "https://github.com/gontovnik/DGElasticPullToRefresh.git" } + spec.source = { :git => "https://github.com/gontovnik/DGElasticPullToRefresh.git", + :tag => '1.1' } spec.license = { :type => "MIT", :file => "LICENSE" } - spec.platform = :ios, '7.0' + spec.platform = :ios, '8.0' spec.source_files = "DGElasticPullToRefresh/*.swift" spec.requires_arc = true - spec.ios.deployment_target = '7.0' + spec.ios.deployment_target = '8.0' spec.ios.frameworks = ['UIKit', 'Foundation'] end diff --git a/DGElasticPullToRefreshExample.xcodeproj/project.xcworkspace/xcuserdata/gontovnik.xcuserdatad/UserInterfaceState.xcuserstate b/DGElasticPullToRefreshExample.xcodeproj/project.xcworkspace/xcuserdata/gontovnik.xcuserdatad/UserInterfaceState.xcuserstate new file mode 100644 index 0000000000000000000000000000000000000000..89e201382e77cbe68f92b7c621b8fa712786e675 GIT binary patch literal 17104 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 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/DGElasticPullToRefreshExample.xcodeproj/xcuserdata/gontovnik.xcuserdatad/xcschemes/xcschememanagement.plist b/DGElasticPullToRefreshExample.xcodeproj/xcuserdata/gontovnik.xcuserdatad/xcschemes/xcschememanagement.plist new file mode 100644 index 0000000..485401d --- /dev/null +++ b/DGElasticPullToRefreshExample.xcodeproj/xcuserdata/gontovnik.xcuserdatad/xcschemes/xcschememanagement.plist @@ -0,0 +1,22 @@ + + + + + SchemeUserState + + DGElasticPullToRefreshExample.xcscheme + + orderHint + 0 + + + SuppressBuildableAutocreation + + 05CD14641BBE8FEA00AF4030 + + primary + + + + + diff --git a/README.md b/README.md index ba57f70..c0ddcb7 100644 --- a/README.md +++ b/README.md @@ -12,7 +12,7 @@ Tutorial on how this bounce effect was achieved can be found [here](http://iostu * Xcode 7 or higher * iOS 8.0 or higher (may work on previous versions, just did not test it) * ARC -* Swift 2.0 +* Swift 3.0 ## Demo @@ -38,14 +38,14 @@ let loadingView = DGElasticPullToRefreshLoadingViewCircle() loadingView.tintColor = UIColor(red: 78/255.0, green: 221/255.0, blue: 200/255.0, alpha: 1.0) tableView.dg_addPullToRefreshWithActionHandler({ [weak self] () -> Void in // Add your logic here - // Do not forget to call dg_stopLoading() at the end + // Do not forget to call dg_stopLoading() at the end self?.tableView.dg_stopLoading() }, loadingView: loadingView) tableView.dg_setPullToRefreshFillColor(UIColor(red: 57/255.0, green: 67/255.0, blue: 89/255.0, alpha: 1.0)) tableView.dg_setPullToRefreshBackgroundColor(tableView.backgroundColor!) ``` -Do not forget to remove pull to refresh on view controller deinit. It is a temporary solution. +Do not forget to remove pull to refresh on view controller deinit. It is a temporary solution. ``` swift deinit { @@ -58,21 +58,21 @@ deinit { Add pull to refresh without loading view: ``` swift -func dg_addPullToRefreshWithActionHandler(actionHandler: () -> Void) +func dg_addPullToRefreshWithActionHandler(_ actionHandler: @escaping () -> Void) ``` Add pull to refresh with loading view: ``` swift -func dg_addPullToRefreshWithActionHandler(actionHandler: () -> Void, loadingView: DGElasticPullToRefreshLoadingView?) +func dg_addPullToRefreshWithActionHandler(_ actionHandler: @escaping () -> Void, loadingView: DGElasticPullToRefreshLoadingView?) ``` You can use built-in *DGElasticPullToRefreshLoadingViewCircle* or create your own by subclassing **DGElasticPullToRefreshLoadingView** and implementing these methods: ``` swift -func setPullProgress(progress: CGFloat) { } -func startAnimating() { } -func stopLoading() { } +func setPullProgress(_ progress: CGFloat) +func startAnimating() +func stopLoading() ``` Remove pull to refresh: @@ -90,13 +90,13 @@ func dg_startLoading() Change pull to refresh background color: ``` swift -func dg_setPullToRefreshBackgroundColor(color: UIColor) +func dg_setPullToRefreshBackgroundColor(_ color: UIColor) ``` Change pull to refresh fill color: -``` swift -func dg_setPullToRefreshFillColor(color: UIColor) +``` swift +func dg_setPullToRefreshFillColor(_ color: UIColor) ``` ## Contribution @@ -111,7 +111,6 @@ Danil Gontovnik - https://twitter.com/gontovnik - http://gontovnik.com/ - danil@gontovnik.com -- http://iostuts.io/author/danil-gontovnik/ ## License