From 90360a7a4e273d9a001aeca81d2a114d28ed9009 Mon Sep 17 00:00:00 2001 From: Bartosz Dolewski Date: Sun, 16 Jun 2019 09:55:13 +0200 Subject: [PATCH 01/16] Updated to Xcode 10.2 --- SSFadingScrollView.xcodeproj/project.pbxproj | 47 +++++++++++++++++-- .../xcschemes/SSFadingScrollView.xcscheme | 2 +- .../xcschemes/SSFadingScrollViewDemo.xcscheme | 2 +- .../MainStoryboard.storyboard | 0 4 files changed, 45 insertions(+), 6 deletions(-) rename SSFadingScrollViewDemo/{en.lproj => Base.lproj}/MainStoryboard.storyboard (100%) diff --git a/SSFadingScrollView.xcodeproj/project.pbxproj b/SSFadingScrollView.xcodeproj/project.pbxproj index 155d582..389e916 100644 --- a/SSFadingScrollView.xcodeproj/project.pbxproj +++ b/SSFadingScrollView.xcodeproj/project.pbxproj @@ -48,6 +48,7 @@ /* End PBXCopyFilesBuildPhase section */ /* Begin PBXFileReference section */ + 15BEF56A22B62D2500CFB6CF /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/MainStoryboard.storyboard; sourceTree = ""; }; 82630F641B63A4EE003B4CCA /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = ""; }; 82B3A68D1C031A13000024C3 /* SSFadingScrollView.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = SSFadingScrollView.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 82B3A68F1C031A13000024C3 /* SSFadingScrollView.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SSFadingScrollView.h; sourceTree = ""; }; @@ -63,7 +64,6 @@ 970FDD7E17A7A512008DC2FB /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; 970FDD8117A7A512008DC2FB /* SSAppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SSAppDelegate.h; sourceTree = ""; }; 970FDD8217A7A512008DC2FB /* SSAppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SSAppDelegate.m; sourceTree = ""; }; - 970FDD8B17A7A512008DC2FB /* en */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = en; path = en.lproj/MainStoryboard.storyboard; sourceTree = ""; }; 970FDD9B17A7A5B9008DC2FB /* QuartzCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = QuartzCore.framework; path = System/Library/Frameworks/QuartzCore.framework; sourceTree = SDKROOT; }; /* End PBXFileReference section */ @@ -211,7 +211,7 @@ isa = PBXProject; attributes = { CLASSPREFIX = SS; - LastUpgradeCheck = 0710; + LastUpgradeCheck = 1020; ORGANIZATIONNAME = "Stephanie Sharp"; TargetAttributes = { 82B3A68C1C031A13000024C3 = { @@ -221,10 +221,11 @@ }; buildConfigurationList = 970FDD2217A7A4DC008DC2FB /* Build configuration list for PBXProject "SSFadingScrollView" */; compatibilityVersion = "Xcode 6.3"; - developmentRegion = English; + developmentRegion = en; hasScannedForEncodings = 0; knownRegions = ( en, + Base, ); mainGroup = 970FDD1E17A7A4DC008DC2FB; productRefGroup = 970FDD2817A7A4DC008DC2FB /* Products */; @@ -298,7 +299,7 @@ 970FDD8A17A7A512008DC2FB /* MainStoryboard.storyboard */ = { isa = PBXVariantGroup; children = ( - 970FDD8B17A7A512008DC2FB /* en */, + 15BEF56A22B62D2500CFB6CF /* Base */, ); name = MainStoryboard.storyboard; sourceTree = ""; @@ -314,6 +315,7 @@ CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_UNREACHABLE_CODE = YES; + CODE_SIGN_IDENTITY = ""; CURRENT_PROJECT_VERSION = 1; DEBUG_INFORMATION_FORMAT = dwarf; DEFINES_MODULE = YES; @@ -348,6 +350,7 @@ CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_UNREACHABLE_CODE = YES; + CODE_SIGN_IDENTITY = ""; COPY_PHASE_STRIP = NO; CURRENT_PROJECT_VERSION = 1; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; @@ -380,27 +383,45 @@ isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES; CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_CXX_LIBRARY = "libc++"; 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_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 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_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + 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; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; COPY_PHASE_STRIP = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; ENABLE_TESTABILITY = YES; GCC_C_LANGUAGE_STANDARD = gnu99; GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; GCC_OPTIMIZATION_LEVEL = 0; GCC_PREPROCESSOR_DEFINITIONS = ( "DEBUG=1", "$(inherited)", ); GCC_SYMBOLS_PRIVATE_EXTERN = NO; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES; + GCC_WARN_UNDECLARED_SELECTOR = YES; GCC_WARN_UNINITIALIZED_AUTOS = YES; + GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; IPHONEOS_DEPLOYMENT_TARGET = 8.0; ONLY_ACTIVE_ARCH = YES; @@ -412,19 +433,37 @@ isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES; CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_CXX_LIBRARY = "libc++"; 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_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 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_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + 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; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; COPY_PHASE_STRIP = YES; + ENABLE_STRICT_OBJC_MSGSEND = YES; GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES; + GCC_WARN_UNDECLARED_SELECTOR = YES; GCC_WARN_UNINITIALIZED_AUTOS = YES; + GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; IPHONEOS_DEPLOYMENT_TARGET = 8.0; OTHER_CFLAGS = "-DNS_BLOCK_ASSERTIONS=1"; diff --git a/SSFadingScrollView.xcodeproj/xcshareddata/xcschemes/SSFadingScrollView.xcscheme b/SSFadingScrollView.xcodeproj/xcshareddata/xcschemes/SSFadingScrollView.xcscheme index d7d627d..2547d03 100644 --- a/SSFadingScrollView.xcodeproj/xcshareddata/xcschemes/SSFadingScrollView.xcscheme +++ b/SSFadingScrollView.xcodeproj/xcshareddata/xcschemes/SSFadingScrollView.xcscheme @@ -1,6 +1,6 @@ Date: Mon, 17 Jun 2019 14:00:13 +0200 Subject: [PATCH 02/16] SSFadingScrollView rewriten in Swift --- SSFadingScrollView.podspec | 4 +- SSFadingScrollView.xcodeproj/project.pbxproj | 22 +- SSFadingScrollView/SSFadingScrollView.h | 105 ---- SSFadingScrollView/SSFadingScrollView.m | 467 ------------------ SSFadingScrollView/SSFadingScrollView.swift | 338 +++++++++++++ .../Base.lproj/MainStoryboard.storyboard | 111 +++-- 6 files changed, 407 insertions(+), 640 deletions(-) delete mode 100644 SSFadingScrollView/SSFadingScrollView.h delete mode 100644 SSFadingScrollView/SSFadingScrollView.m create mode 100644 SSFadingScrollView/SSFadingScrollView.swift diff --git a/SSFadingScrollView.podspec b/SSFadingScrollView.podspec index 5e9905b..894e2de 100644 --- a/SSFadingScrollView.podspec +++ b/SSFadingScrollView.podspec @@ -1,11 +1,11 @@ Pod::Spec.new do |s| s.name = "SSFadingScrollView" - s.version = "1.1.0" + s.version = "2.0.0" s.summary = "A UIScrollView subclass that fades the leading and/or trailing edges of a scroll view to transparent" s.homepage = "https://github.com/stephsharp/SSFadingScrollView/" s.license = { :type => "MIT", :file => "LICENSE" } s.author = "Stephanie Sharp" - s.platform = :ios, "8.0" + s.platform = :ios, "10.3" s.source = { :git => "https://github.com/stephsharp/SSFadingScrollView.git", :tag => "v#{s.version}" } s.source_files = "SSFadingScrollView" s.public_header_files = [ "SSFadingScrollView/SSFadingScrollView.h" ] diff --git a/SSFadingScrollView.xcodeproj/project.pbxproj b/SSFadingScrollView.xcodeproj/project.pbxproj index 389e916..1eb382b 100644 --- a/SSFadingScrollView.xcodeproj/project.pbxproj +++ b/SSFadingScrollView.xcodeproj/project.pbxproj @@ -7,11 +7,10 @@ objects = { /* Begin PBXBuildFile section */ + 15BEF56C22B62DBA00CFB6CF /* SSFadingScrollView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 15BEF56B22B62DBA00CFB6CF /* SSFadingScrollView.swift */; }; 82630F651B63A4EE003B4CCA /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 82630F641B63A4EE003B4CCA /* Images.xcassets */; }; - 82B3A6901C031A13000024C3 /* SSFadingScrollView.h in Headers */ = {isa = PBXBuildFile; fileRef = 82B3A68F1C031A13000024C3 /* SSFadingScrollView.h */; settings = {ATTRIBUTES = (Public, ); }; }; 82B3A6941C031A13000024C3 /* SSFadingScrollView.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 82B3A68D1C031A13000024C3 /* SSFadingScrollView.framework */; }; 82B3A6951C031A13000024C3 /* SSFadingScrollView.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 82B3A68D1C031A13000024C3 /* SSFadingScrollView.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; - 82B3A69B1C031AE4000024C3 /* SSFadingScrollView.m in Sources */ = {isa = PBXBuildFile; fileRef = 82B3A69A1C031AE4000024C3 /* SSFadingScrollView.m */; }; 82B3A69F1C031FB6000024C3 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 82B3A69E1C031FB6000024C3 /* LaunchScreen.storyboard */; }; 970FDD7517A7A512008DC2FB /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 970FDD2A17A7A4DC008DC2FB /* UIKit.framework */; }; 970FDD7617A7A512008DC2FB /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 970FDD2C17A7A4DC008DC2FB /* Foundation.framework */; }; @@ -49,11 +48,10 @@ /* Begin PBXFileReference section */ 15BEF56A22B62D2500CFB6CF /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/MainStoryboard.storyboard; sourceTree = ""; }; + 15BEF56B22B62DBA00CFB6CF /* SSFadingScrollView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SSFadingScrollView.swift; sourceTree = ""; }; 82630F641B63A4EE003B4CCA /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = ""; }; 82B3A68D1C031A13000024C3 /* SSFadingScrollView.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = SSFadingScrollView.framework; sourceTree = BUILT_PRODUCTS_DIR; }; - 82B3A68F1C031A13000024C3 /* SSFadingScrollView.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SSFadingScrollView.h; sourceTree = ""; }; 82B3A6911C031A13000024C3 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; - 82B3A69A1C031AE4000024C3 /* SSFadingScrollView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SSFadingScrollView.m; sourceTree = ""; }; 82B3A69E1C031FB6000024C3 /* LaunchScreen.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; path = LaunchScreen.storyboard; sourceTree = ""; }; 970FDD2A17A7A4DC008DC2FB /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = System/Library/Frameworks/UIKit.framework; sourceTree = SDKROOT; }; 970FDD2C17A7A4DC008DC2FB /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; }; @@ -93,8 +91,7 @@ 82B3A68E1C031A13000024C3 /* SSFadingScrollView */ = { isa = PBXGroup; children = ( - 82B3A68F1C031A13000024C3 /* SSFadingScrollView.h */, - 82B3A69A1C031AE4000024C3 /* SSFadingScrollView.m */, + 15BEF56B22B62DBA00CFB6CF /* SSFadingScrollView.swift */, 82B3A6911C031A13000024C3 /* Info.plist */, ); path = SSFadingScrollView; @@ -160,7 +157,6 @@ isa = PBXHeadersBuildPhase; buildActionMask = 2147483647; files = ( - 82B3A6901C031A13000024C3 /* SSFadingScrollView.h in Headers */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -216,6 +212,7 @@ TargetAttributes = { 82B3A68C1C031A13000024C3 = { CreatedOnToolsVersion = 7.1; + LastSwiftMigration = 1020; }; }; }; @@ -264,7 +261,7 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - 82B3A69B1C031AE4000024C3 /* SSFadingScrollView.m in Sources */, + 15BEF56C22B62DBA00CFB6CF /* SSFadingScrollView.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -336,6 +333,8 @@ PRODUCT_BUNDLE_IDENTIFIER = com.ssharp.SSFadingScrollView; PRODUCT_NAME = SSFadingScrollView; SKIP_INSTALL = YES; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_VERSION = 5.0; TARGETED_DEVICE_FAMILY = "1,2"; VERSIONING_SYSTEM = "apple-generic"; VERSION_INFO_PREFIX = ""; @@ -373,6 +372,7 @@ PRODUCT_BUNDLE_IDENTIFIER = com.ssharp.SSFadingScrollView; PRODUCT_NAME = SSFadingScrollView; SKIP_INSTALL = YES; + SWIFT_VERSION = 5.0; TARGETED_DEVICE_FAMILY = "1,2"; VERSIONING_SYSTEM = "apple-generic"; VERSION_INFO_PREFIX = ""; @@ -423,7 +423,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 8.0; + IPHONEOS_DEPLOYMENT_TARGET = 10.3; ONLY_ACTIVE_ARCH = YES; SDKROOT = iphoneos; }; @@ -465,7 +465,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 8.0; + IPHONEOS_DEPLOYMENT_TARGET = 10.3; OTHER_CFLAGS = "-DNS_BLOCK_ASSERTIONS=1"; SDKROOT = iphoneos; VALIDATE_PRODUCT = YES; @@ -475,6 +475,7 @@ 970FDD9117A7A512008DC2FB /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { + ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; GCC_PRECOMPILE_PREFIX_HEADER = YES; INFOPLIST_FILE = "$(SRCROOT)/SSFadingScrollViewDemo/SSFadingScrollViewDemo-Info.plist"; @@ -488,6 +489,7 @@ 970FDD9217A7A512008DC2FB /* Release */ = { isa = XCBuildConfiguration; buildSettings = { + ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; GCC_PRECOMPILE_PREFIX_HEADER = YES; INFOPLIST_FILE = "$(SRCROOT)/SSFadingScrollViewDemo/SSFadingScrollViewDemo-Info.plist"; diff --git a/SSFadingScrollView/SSFadingScrollView.h b/SSFadingScrollView/SSFadingScrollView.h deleted file mode 100644 index 9559682..0000000 --- a/SSFadingScrollView/SSFadingScrollView.h +++ /dev/null @@ -1,105 +0,0 @@ -// -// SSFadingScrollView.h -// Created by Stephanie Sharp on 1/06/13. -// - -#import - -//! Project version number for SSFadingScrollView. -FOUNDATION_EXPORT double SSFadingScrollViewVersionNumber; - -//! Project version string for SSFadingScrollView. -FOUNDATION_EXPORT const unsigned char SSFadingScrollViewVersionString[]; - -typedef NS_ENUM(NSUInteger, SSScrollViewFadeAxis) { - SSScrollViewFadeAxisVertical = 0, - SSScrollViewFadeAxisHorizontal = 1, -}; - -typedef NS_ENUM(NSUInteger, FadeEdges) { - FadeEdgesTopAndBottom __attribute__((deprecated("Use the fadeLeadingEdge and fadeTrailingEdge properties instead."))), - FadeEdgesTop __attribute__((deprecated("Use the fadeLeadingEdge property instead."))), - FadeEdgesBottom __attribute__((deprecated("Use the fadeTrailingEdge property instead."))), -}; - -/** - * This scrollview subclass is meant to only scroll in one direction (horizontal or vertical). - * On the chosen axis, either or both the leading and trailing edges can be faded. - */ -@interface SSFadingScrollView : UIScrollView - -/** - * Designated initializer. - */ -- (instancetype)initWithFadeSize:(CGFloat)fadeSize axis:(SSScrollViewFadeAxis)fadeAxis; - -/** - * Initializer that fades the top and bottom of the scroll view. - */ -- (instancetype)initWithFadeSize:(CGFloat)fadeSize; - -/** - * Initializer that fades the top and bottom of the scroll view with default fade height. - */ -- (instancetype)init; - -#if TARGET_INTERFACE_BUILDER -@property (nonatomic) IBInspectable NSUInteger fadeAxis; -#else -@property (nonatomic) SSScrollViewFadeAxis fadeAxis; -#endif - -/** - * Fade leading edge of fade axis. Default is YES. - */ -@property (nonatomic) IBInspectable BOOL fadeLeadingEdge; - -/** - * Fade trailing edge of fade axis. Default is YES. - */ -@property (nonatomic) IBInspectable BOOL fadeTrailingEdge; - -/** - * Size of gradient. Default is 30. - */ -@property (nonatomic) IBInspectable CGFloat fadeSize; - -/** - * Duration of fade in & out. Default is 0.3 seconds. - */ -@property (nonatomic) IBInspectable double fadeDuration; - -/** - * Default is YES. Scroll bars are masked so they don't fade with the scroll view content. - * Set to NO to fade out the scroll bars along with the content. - */ -@property (nonatomic) IBInspectable BOOL maskScrollBars; - -#pragma mark - Deprecated - -/** - * Deprecated initializer. - */ -- (instancetype)initWithFadeHeight:(CGFloat)fadeHeight edges:(FadeEdges)fadeEdges __attribute__((deprecated("Use initWithFadeSize: and the fadeLeadingEdge/fadeTrailingEdge properties instead."))); - -/** - * Initializer that fades the top and bottom of the scroll view. - */ -- (instancetype)initWithFadeHeight:(CGFloat)fadeHeight __attribute__((deprecated("Use initWithFadeSize: instead."))); - -/** - * Fade top of scroll view. Default is YES. - */ -@property (nonatomic) BOOL fadeTop __attribute__((deprecated("Use the fadeLeadingEdge property instead."))); - -/** - * Fade bottom of scroll view. Default is YES. - */ -@property (nonatomic) BOOL fadeBottom __attribute__((deprecated("Use the fadeTrailingEdge property instead."))); - -/** - * Height of gradient. Default is 30. - */ -@property (nonatomic) CGFloat fadeHeight __attribute__((deprecated("Use the fadeSize property instead."))); - -@end diff --git a/SSFadingScrollView/SSFadingScrollView.m b/SSFadingScrollView/SSFadingScrollView.m deleted file mode 100644 index 5aaf45a..0000000 --- a/SSFadingScrollView/SSFadingScrollView.m +++ /dev/null @@ -1,467 +0,0 @@ -// -// SSFadingScrollView.m -// Created by Stephanie Sharp on 1/06/13. -// - -#import "SSFadingScrollView.h" -#import - -static CGFloat const SSDefaultFadeSize = 30.0; -static CFTimeInterval const SSDefaultFadeDuration = 0.3; -static void *SSContext = &SSContext; - -@interface SSFadingScrollView () - -@property (nonatomic) CALayer *maskLayer; -@property (nonatomic) CAGradientLayer *gradientLayer; - -@property (nonatomic) UIImageView *verticalScrollBar; -@property (nonatomic) UIImageView *horizontalScrollBar; -@property (nonatomic) CALayer *verticalScrollBarLayer; -@property (nonatomic) CALayer *horizontalScrollBarLayer; - -@end - -@implementation SSFadingScrollView - -#pragma mark - Initializers - -- (instancetype)initWithFadeSize:(CGFloat)fadeSize axis:(SSScrollViewFadeAxis)fadeAxis -{ - self = [super initWithFrame:CGRectZero]; - if (self) { - [self setDefaults]; - _fadeSize = fadeSize; - _fadeAxis = fadeAxis; - } - return self; -} - -- (instancetype)initWithFadeSize:(CGFloat)fadeSize -{ - return [self initWithFadeSize:fadeSize axis:SSScrollViewFadeAxisVertical]; -} - -- (instancetype)init -{ - return [self initWithFadeSize:SSDefaultFadeSize]; -} - -- (instancetype)initWithFrame:(CGRect)frame -{ - self = [self init]; - if (self) { - [self setDefaults]; - self.frame = frame; - } - return self; -} - -- (instancetype)initWithCoder:(NSCoder *)coder -{ - self = [super initWithCoder:coder]; - if (self) { - [self setDefaults]; - } - return self; -} - -- (void)setDefaults -{ - _fadeAxis = SSScrollViewFadeAxisVertical; - _fadeLeadingEdge = YES; - _fadeTrailingEdge = YES; - _fadeSize = SSDefaultFadeSize; - _fadeDuration = SSDefaultFadeDuration; - _maskScrollBars = YES; -} - -- (void)dealloc -{ - if (_verticalScrollBar) { - [_verticalScrollBar removeObserver:self forKeyPath:@"alpha" context:SSContext]; - } - if (_horizontalScrollBar) { - [_horizontalScrollBar removeObserver:self forKeyPath:@"alpha" context:SSContext]; - } -} - -#pragma mark - Layout - -- (void)layoutSubviews -{ - [super layoutSubviews]; - [self updateMask]; -} - -- (void)updateMask -{ - [CATransaction begin]; - [CATransaction setDisableActions:YES]; - self.maskLayer.frame = self.bounds; - [CATransaction commit]; - - [self updateGradients]; - [self updateScrollBarMasks]; -} - -- (void)updateGradients -{ - self.gradientLayer.frame = self.maskLayer.bounds; - NSInteger contentOffset = roundf(self.isVertical ? self.contentOffset.y : self.contentOffset.x); - - if (self.fadeLeadingEdge) { - if (!self.leadingGradientIsHidden && contentOffset <= 0) { - [self animateLeadingGradientToColor:[SSFadingScrollView opaqueColor]]; // fade out - } - else if (self.leadingGradientIsHidden && contentOffset > 0) { - [self animateLeadingGradientToColor:[SSFadingScrollView transparentColor]]; // fade in - } - } - if (self.fadeTrailingEdge) { - NSInteger maxContentOffset; - if (self.isVertical) { - maxContentOffset = roundf(self.contentSize.height - CGRectGetHeight(self.bounds)); - } - else { - maxContentOffset = roundf(self.contentSize.width - CGRectGetWidth(self.bounds)); - } - - if (!self.trailingGradientIsHidden && contentOffset >= maxContentOffset) { - [self animateTrailingGradientToColor:[SSFadingScrollView opaqueColor]]; - } - else if (self.trailingGradientIsHidden && contentOffset < maxContentOffset) { - [self animateTrailingGradientToColor:[SSFadingScrollView transparentColor]]; - } - } -} - -#pragma mark - Properties - -- (BOOL)isVertical -{ - return self.fadeAxis == SSScrollViewFadeAxisVertical; -} - -- (CALayer *)maskLayer -{ - if (!_maskLayer) { - _maskLayer = [self setupMaskLayer]; - } - return _maskLayer; -} - -- (CALayer *)verticalScrollBarLayer -{ - if (!_verticalScrollBarLayer) { - _verticalScrollBarLayer = [self setupVerticalScrollBarLayer]; - } - - return _verticalScrollBarLayer; -} - -- (CALayer *)horizontalScrollBarLayer -{ - if (!_horizontalScrollBarLayer) { - _horizontalScrollBarLayer = [self setupHorizontalScrollBarLayer]; - } - - return _horizontalScrollBarLayer; -} - -- (BOOL)leadingGradientIsHidden -{ - CGColorRef firstColor = (__bridge CGColorRef)self.gradientLayer.colors.firstObject; - return CGColorEqualToColor(firstColor, [SSFadingScrollView opaqueColor]); -} - -- (BOOL)trailingGradientIsHidden -{ - CGColorRef lastColor = (__bridge CGColorRef)self.gradientLayer.colors.lastObject; - return CGColorEqualToColor(lastColor, [SSFadingScrollView opaqueColor]); -} - -#pragma mark - Mask - -- (CALayer *)setupMaskLayer -{ - CALayer *maskLayer = [CALayer layer]; - maskLayer.frame = self.bounds; - - self.gradientLayer = [self setupGradientLayer]; - [maskLayer addSublayer:self.gradientLayer]; - - if (self.maskScrollBars) { - [maskLayer addSublayer:self.verticalScrollBarLayer]; - [maskLayer addSublayer:self.horizontalScrollBarLayer]; - } - - self.layer.mask = maskLayer; - - return maskLayer; -} - -#pragma mark Mask colors - -+ (CGColorRef)opaqueColor -{ - return [UIColor blackColor].CGColor; -} - -+ (CGColorRef)transparentColor -{ - return [UIColor clearColor].CGColor; -} - -#pragma mark - Gradient mask - -- (CAGradientLayer *)setupGradientLayer -{ - id transparent = (id)[SSFadingScrollView transparentColor]; - id opaque = (id)[SSFadingScrollView opaqueColor]; - - CAGradientLayer *gradientLayer = [CAGradientLayer layer]; - CGRect frame = self.bounds; - frame.origin = CGPointZero; - gradientLayer.frame = frame; - - NSArray *colors = [NSArray new]; - NSArray *locations = [NSArray new]; - - CGFloat fadePercentage = [self percentageForFadeSize]; - - if (self.fadeLeadingEdge) { - colors = @[transparent, opaque]; - locations = @[@(0), @(fadePercentage)]; - } - if (self.fadeTrailingEdge) { - colors = [colors arrayByAddingObjectsFromArray:@[opaque, transparent]]; - locations = [locations arrayByAddingObjectsFromArray:@[@(1.0 - fadePercentage), @(1)]]; - } - - gradientLayer.colors = colors; - gradientLayer.locations = locations; - - if (self.isVertical) { - gradientLayer.startPoint = CGPointMake(0.5, 0); - gradientLayer.endPoint = CGPointMake(0.5, 1); - } - else { - gradientLayer.startPoint = CGPointMake(0, 0.5); - gradientLayer.endPoint = CGPointMake(1, 0.5); - } - - return gradientLayer; -} - -- (CGFloat)percentageForFadeSize -{ - CGFloat size = self.isVertical ? CGRectGetHeight(self.bounds) : CGRectGetWidth(self.bounds); - - if (size <= 0) { - return 0; - } - - CGFloat maxFadePercentage = (self.fadeLeadingEdge && self.fadeTrailingEdge) ? 0.5 : 1.0; - return fminf(self.fadeSize / size, maxFadePercentage); -} - -#pragma mark Gradient animation - -- (void)animateLeadingGradientToColor:(CGColorRef)color -{ - NSArray *colours = [self colorsArrayByReplacingObjectAtIndex:0 withColor:color]; - [self animateGradientColours:colours]; -} - -- (void)animateTrailingGradientToColor:(CGColorRef)color -{ - NSUInteger lastIndex = self.gradientLayer.colors.count - 1; - NSArray *colours = [self colorsArrayByReplacingObjectAtIndex:lastIndex withColor:color]; - [self animateGradientColours:colours]; -} - -- (NSArray *)colorsArrayByReplacingObjectAtIndex:(NSUInteger)index withColor:(CGColorRef)color -{ - NSMutableArray *mutableColours = [self.gradientLayer.colors mutableCopy]; - mutableColours[index] = (__bridge id)color; - - return [mutableColours copy]; -} - -- (void)animateGradientColours:(NSArray *)colours -{ - CABasicAnimation *animation; - animation = [CABasicAnimation animationWithKeyPath:@"colors"]; - animation.fromValue = ((CAGradientLayer *)self.gradientLayer.presentationLayer).colors; - animation.toValue = colours; - animation.duration = self.fadeDuration; - animation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseOut]; - - [CATransaction begin]; - [CATransaction setDisableActions:YES]; - self.gradientLayer.colors = colours; // update the model value - [CATransaction commit]; - - [self.gradientLayer addAnimation:animation forKey:@"animateGradient"]; -} - -#pragma mark - Scroll bar mask - -- (CALayer *)setupVerticalScrollBarLayer -{ - if (!self.verticalScrollBar) { - [self findScrollBars]; - - if (!self.verticalScrollBar) { - return nil; - } - } - - [self.verticalScrollBar addObserver:self forKeyPath:@"alpha" options:0 context:SSContext]; - - return [self scrollBarLayerWithFrame:self.verticalScrollBar.frame]; -} - -- (CALayer *)setupHorizontalScrollBarLayer -{ - if (!self.horizontalScrollBar) { - [self findScrollBars]; - - if (!self.horizontalScrollBar) { - return nil; - } - } - - [self.horizontalScrollBar addObserver:self forKeyPath:@"alpha" options:0 context:SSContext]; - - return [self scrollBarLayerWithFrame:self.horizontalScrollBar.frame]; -} - -- (void)findScrollBars -{ - for (UIView *subview in self.subviews) { - if ([subview isKindOfClass:[UIImageView class]] && subview.tag == 0) { - UIImageView *imageView = (UIImageView *)subview; - - if (imageView.frame.size.width == 3.5 || - imageView.frame.size.width == 2.5 || - (imageView.frame.size.width < 2.4 && imageView.frame.size.width > 2.3)) - { - self.verticalScrollBar = imageView; - } - else if (imageView.frame.size.height == 3.5 || - imageView.frame.size.height == 2.5 || - (imageView.frame.size.height < 2.4 && imageView.frame.size.height > 2.3)) - { - self.horizontalScrollBar = imageView; - } - } - } -} - -- (CALayer *)scrollBarLayerWithFrame:(CGRect)frame -{ - CALayer *scrollBarLayer = [CALayer layer]; - scrollBarLayer.backgroundColor = [SSFadingScrollView opaqueColor]; - scrollBarLayer.frame = frame; - - return scrollBarLayer; -} - -- (void)updateScrollBarMasks -{ - if (self.maskScrollBars) { - [CATransaction begin]; - [CATransaction setDisableActions:YES]; - - CGRect verticalScrollBarFrame = [self.layer convertRect:self.verticalScrollBar.frame - toLayer:self.maskLayer]; - self.verticalScrollBarLayer.frame = verticalScrollBarFrame; - self.verticalScrollBarLayer.opacity = self.verticalScrollBar.alpha; - - CGRect horizontalScrollBarFrame = [self.layer convertRect:self.horizontalScrollBar.frame - toLayer:self.maskLayer]; - self.horizontalScrollBarLayer.frame = horizontalScrollBarFrame; - self.horizontalScrollBarLayer.opacity = self.horizontalScrollBar.alpha; - - [CATransaction commit]; - } -} - -- (void)observeValueForKeyPath:(NSString *)keyPath - ofObject:(id)object - change:(NSDictionary *)change - context:(void *)context -{ - if (context != SSContext) { - return; - } - - if([keyPath isEqualToString:@"alpha"] && [object valueForKeyPath:keyPath] != [NSNull null]) { - [self layoutSubviews]; - } -} - -#pragma mark - Deprecated - -- (instancetype)initWithFadeHeight:(CGFloat)fadeHeight edges:(FadeEdges)fadeEdges -{ - self = [self initWithFadeSize:fadeHeight]; - if (self) { - switch (fadeEdges) { - case FadeEdgesTopAndBottom: - _fadeLeadingEdge = YES; - _fadeTrailingEdge = YES; - break; - case FadeEdgesTop: - _fadeLeadingEdge = YES; - _fadeTrailingEdge = NO; - break; - case FadeEdgesBottom: - _fadeLeadingEdge = NO; - _fadeTrailingEdge = YES; - break; - default: - break; - } - } - return self; -} - -- (instancetype)initWithFadeHeight:(CGFloat)fadeHeight -{ - return [self initWithFadeSize:fadeHeight]; -} - -- (BOOL)fadeTop; -{ - return self.fadeLeadingEdge; -} - -- (void)setFadeTop:(BOOL)fade; -{ - self.fadeLeadingEdge = fade; -} - -- (BOOL)fadeBottom; -{ - return self.fadeTrailingEdge; -} - -- (void)setFadeBottom:(BOOL)fade; -{ - self.fadeTrailingEdge = fade; -} - -- (CGFloat)fadeHeight; -{ - return self.fadeSize; -} - -- (void)setFadeHeight:(CGFloat)height; -{ - self.fadeSize = height; -} - -@end diff --git a/SSFadingScrollView/SSFadingScrollView.swift b/SSFadingScrollView/SSFadingScrollView.swift new file mode 100644 index 0000000..f4dc1c2 --- /dev/null +++ b/SSFadingScrollView/SSFadingScrollView.swift @@ -0,0 +1,338 @@ +// +// SSFadingScrollView.swift +// SSFadingScrollView +// +// Created by Bartosz Dolewski on 16/06/2019. +// Copyright © 2019 Stephanie Sharp. All rights reserved. +// + +import UIKit +import QuartzCore + +@objc enum FadeAxis: Int { + case vertical = 0 + case horizontal = 1 +} + +@objc enum FadeEdges: Int { + case FadeEdgesTopAndBottom + case FadeEdgesTop + case FadeEdgesBottom +} + +private let SSDefaultFadeSize: CGFloat = 30.0 +private let SSDefaultFadeDuration: CFTimeInterval = 0.3 + +@IBDesignable +class SSFadingScrollView: UIScrollView { + /** + * Fade leading edge of fade axis. Default is YES. + */ + @IBInspectable var fadeLeadingEdge = false + /** + * Fade trailing edge of fade axis. Default is YES. + */ + @IBInspectable var fadeTrailingEdge = false + /** + * Size of gradient. Default is 30. + */ + @IBInspectable var fadeSize: CGFloat = 0.0 + /** + * Duration of fade in & out. Default is 0.3 seconds. + */ + @IBInspectable var fadeDuration = 0.0 + /** + * Default is YES. Scroll bars are masked so they don't fade with the scroll view content. + * Set to NO to fade out the scroll bars along with the content. + */ + @IBInspectable var maskScrollBars = false + + @available(*, unavailable, message: "This property is reserved for Interface Builder. Use 'fadeAxis' instead.") + @IBInspectable var axisIB: FadeAxis.RawValue { + set { fadeAxis = FadeAxis(rawValue: newValue) ?? .vertical } + get { return fadeAxis.rawValue } + } + + var fadeAxis: FadeAxis = .vertical + + private lazy var maskLayer: CALayer = { + return setupMaskLayer() + }() + + private lazy var verticalScrollBarLayer: CALayer = { + return setupVerticalScrollBarLayer() + }() + + private lazy var horizontalScrollBarLayer: CALayer = { + return setupHorizontalScrollBarLayer() + }() + + private lazy var gradientLayer: CAGradientLayer = { + return setupGradientLayer() + }() + + private var verticalScrollBar: UIImageView? + private var horizontalScrollBar: UIImageView? + + private var verticalScrollObservation: NSKeyValueObservation? + private var horizontalScrollObservation: NSKeyValueObservation? + + // MARK: - Initializers + init(fadeSize: CGFloat, axis fadeAxis: FadeAxis) { + super.init(frame: CGRect.zero) + setDefaults() + self.fadeSize = fadeSize + self.fadeAxis = fadeAxis + + verticalScrollObservation = verticalScrollBar?.observe(\.alpha) { [weak self] object, change in + self?.layoutSubviews() + } + + horizontalScrollObservation = horizontalScrollBar?.observe(\.alpha) { [weak self] object, change in + self?.layoutSubviews() + } + } + + convenience init(fadeSize: CGFloat) { + self.init(fadeSize: fadeSize, axis: .vertical) + } + + convenience init() { + self.init(fadeSize: SSDefaultFadeSize) + } + + convenience override init(frame: CGRect) { + self.init() + setDefaults() + self.frame = frame + } + + required init?(coder: NSCoder) { + super.init(coder: coder) + setDefaults() + } + + func setDefaults() { + fadeAxis = .vertical + fadeLeadingEdge = true + fadeTrailingEdge = true + fadeSize = SSDefaultFadeSize + fadeDuration = SSDefaultFadeDuration + maskScrollBars = true + } +} + +extension SSFadingScrollView { + override func layoutSubviews() { + super.layoutSubviews() + updateMask() + } + + func setupMaskLayer() -> CALayer { + let maskLayer = CALayer() + maskLayer.frame = bounds + + gradientLayer = setupGradientLayer() + maskLayer.addSublayer(gradientLayer) + + if maskScrollBars { + maskLayer.addSublayer(verticalScrollBarLayer) + maskLayer.addSublayer(horizontalScrollBarLayer) + } + + layer.mask = maskLayer + + return maskLayer + } + + func setupVerticalScrollBarLayer() -> CALayer { + findScrollBars() + return scrollBar(with: verticalScrollBar?.frame ?? .zero) + } + + func setupHorizontalScrollBarLayer() -> CALayer { + findScrollBars() + return scrollBar(with: horizontalScrollBar?.frame ?? .zero) + } + + func updateMask() { + CATransaction.begin() + CATransaction.setDisableActions(true) + maskLayer.frame = bounds + CATransaction.commit() + + updateGradients() + updateScrollBarMasks() + } + + func updateGradients() { + gradientLayer.frame = maskLayer.bounds + let contentOffset = Int(roundf(Float(isVertical ? self.contentOffset.y : self.contentOffset.x))) + + if fadeLeadingEdge { + if !leadingGradientIsHidden && contentOffset <= 0 { + animateLeadingGradient(to: opaqueColor) // fade out + } else if leadingGradientIsHidden && contentOffset > 0 { + animateLeadingGradient(to: transparentColor) // fade in + } + } + if fadeTrailingEdge { + var maxContentOffset: Int + if isVertical { + maxContentOffset = Int(roundf(Float(contentSize.height - bounds.height))) + } else { + maxContentOffset = Int(roundf(Float(contentSize.width - bounds.width))) + } + + if !trailingGradientIsHidden && contentOffset >= maxContentOffset { + animateTrailingGradient(to: opaqueColor) + } else if trailingGradientIsHidden && contentOffset < maxContentOffset { + animateTrailingGradient(to: transparentColor) + } + } + } + + func setupGradientLayer() -> CAGradientLayer { + let gradientLayer = CAGradientLayer() + gradientLayer.frame = self.bounds + gradientLayer.frame.origin = .zero + + var colors: [CGColor] = [] + var locations: [NSNumber] = [] + + let fadePercentage = percentageForFadeSize + + if fadeLeadingEdge { + colors = [transparentColor, opaqueColor] + locations = [NSNumber(value: 0), NSNumber(value: Float(fadePercentage))] + } + if fadeTrailingEdge { + colors = colors + [opaqueColor, transparentColor] + locations = locations + [NSNumber(value: Float(1.0 - fadePercentage)), NSNumber(value: 1)] + } + + gradientLayer.colors = colors + gradientLayer.locations = locations + + gradientLayer.startPoint = isVertical ? CGPoint(x: 0.5, y: 0.0) : CGPoint(x: 0.0, y: 0.5) + gradientLayer.endPoint = isVertical ? CGPoint(x: 0.5, y: 1.0) : CGPoint(x: 1.0, y: 0.5) + + return gradientLayer + } + + func updateScrollBarMasks() { + guard maskScrollBars else { return } + guard let verticalScrollBar = verticalScrollBar, + let horizontalScrollBar = horizontalScrollBar else { return } + + CATransaction.begin() + CATransaction.setDisableActions(true) + + let verticalScrollBarFrame = layer.convert(verticalScrollBar.frame, to: maskLayer) + verticalScrollBarLayer.frame = verticalScrollBarFrame + verticalScrollBarLayer.opacity = Float(verticalScrollBar.alpha) + + let horizontalScrollBarFrame = layer.convert(horizontalScrollBar.frame, to: maskLayer) + horizontalScrollBarLayer.frame = horizontalScrollBarFrame + horizontalScrollBarLayer.opacity = Float(horizontalScrollBar.alpha) + + CATransaction.commit() + } + + func scrollBar(with frame: CGRect) -> CALayer { + let scrollBarLayer = CALayer() + scrollBarLayer.backgroundColor = opaqueColor + scrollBarLayer.frame = frame + + return scrollBarLayer + } + + fileprivate func isScrollBar(_ dimension: CGFloat) -> Bool { + return dimension == 3.5 || dimension == 2.5 || ((dimension) < 2.4 && (dimension ) > 2.3) + } + + func findScrollBars() { + subviews + .filter { ($0 is UIImageView) && $0.tag == 0 } + .compactMap { $0 as? UIImageView } + .forEach { imageView in + if isScrollBar(imageView.frame.size.width) { + verticalScrollBar = imageView + } else if isScrollBar(imageView.frame.size.height) { + horizontalScrollBar = imageView + } + } + } +} + +// MARK: - Properties +extension SSFadingScrollView { + var isVertical: Bool { + return fadeAxis == .vertical + } + + var leadingGradientIsHidden: Bool { + let firstColor = gradientLayer.colors?.first as! CGColor + return firstColor == opaqueColor + } + + var trailingGradientIsHidden: Bool { + let lastColor = gradientLayer.colors?.last as! CGColor + return lastColor == opaqueColor + } + + var opaqueColor: CGColor { + return UIColor.black.cgColor + } + + var transparentColor: CGColor { + return UIColor.clear.cgColor + } + + var percentageForFadeSize: CGFloat { + let size = isVertical ? bounds.height : bounds.width + + if size <= 0 { + return 0 + } + + let maxFadePercentage: CGFloat = (fadeLeadingEdge && fadeTrailingEdge) ? 0.5 : 1.0 + return CGFloat(fminf(Float(fadeSize / size), Float(maxFadePercentage))) + } +} + +// MARK: - Gradient animation +extension SSFadingScrollView { + func animateLeadingGradient(to color: CGColor) { + let colours = colorsArrayByReplacingObject(at: 0, with: color) + animateGradientColours(colours) + } + + func animateTrailingGradient(to color: CGColor) { + let lastIndex = gradientLayer.colors!.count - 1 + let colours = colorsArrayByReplacingObject(at: lastIndex, with: color) + animateGradientColours(colours) + } + + func colorsArrayByReplacingObject(at index: Int, with color: CGColor) -> [CGColor] { + var mutableColours = gradientLayer.colors as! [CGColor] + mutableColours[index] = color + + return mutableColours + } + + func animateGradientColours(_ colours: [Any]?) { + let animation = CABasicAnimation(keyPath: #keyPath(CAGradientLayer.colors)) + animation.fromValue = (gradientLayer.presentation())?.colors + animation.toValue = colours + animation.duration = fadeDuration + animation.timingFunction = CAMediaTimingFunction(name: .easeOut) + + CATransaction.begin() + CATransaction.setDisableActions(true) + gradientLayer.colors = colours // update the model value + CATransaction.commit() + + gradientLayer.add(animation, forKey: "animateGradient") + } +} diff --git a/SSFadingScrollViewDemo/Base.lproj/MainStoryboard.storyboard b/SSFadingScrollViewDemo/Base.lproj/MainStoryboard.storyboard index 110c56e..9859314 100644 --- a/SSFadingScrollViewDemo/Base.lproj/MainStoryboard.storyboard +++ b/SSFadingScrollViewDemo/Base.lproj/MainStoryboard.storyboard @@ -1,36 +1,35 @@ - - + + - - - + + - - + + - + - + - + - + - + - + - + - + - + - + - + - + @@ -126,15 +125,15 @@ - - + + - - + + - + @@ -174,7 +173,7 @@ Maecenas sagittis eu felis sed pellentesque. Integer varius justo sem, sed viver - + @@ -188,7 +187,7 @@ Maecenas sagittis eu felis sed pellentesque. Integer varius justo sem, sed viver - + @@ -198,12 +197,12 @@ Maecenas sagittis eu felis sed pellentesque. Integer varius justo sem, sed viver - - + + - - + + @@ -242,7 +241,7 @@ Maecenas sagittis eu felis sed pellentesque. Integer varius justo sem, sed viver - + @@ -257,7 +256,7 @@ Maecenas sagittis eu felis sed pellentesque. Integer varius justo sem, sed viver - + @@ -265,7 +264,7 @@ Maecenas sagittis eu felis sed pellentesque. Integer varius justo sem, sed viver - + @@ -275,7 +274,7 @@ Maecenas sagittis eu felis sed pellentesque. Integer varius justo sem, sed viver - + @@ -285,15 +284,15 @@ Maecenas sagittis eu felis sed pellentesque. Integer varius justo sem, sed viver - - + + - - + + @@ -365,26 +364,26 @@ Maecenas sagittis eu felis sed pellentesque. Integer varius justo sem, sed viver - + - - + + - + - + - + @@ -403,16 +402,16 @@ Maecenas sagittis eu felis sed pellentesque. Integer varius justo sem, sed viver - - - + + + - + @@ -426,7 +425,7 @@ Maecenas sagittis eu felis sed pellentesque. Integer varius justo sem, sed viver - + From 9f2a582d4161111da10c94f37720ff5fbe09e329 Mon Sep 17 00:00:00 2001 From: Bartosz Dolewski Date: Sat, 6 Jul 2019 18:16:15 +0200 Subject: [PATCH 03/16] Changed colours -> colors --- SSFadingScrollView/SSFadingScrollView.swift | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/SSFadingScrollView/SSFadingScrollView.swift b/SSFadingScrollView/SSFadingScrollView.swift index f4dc1c2..88fd61c 100644 --- a/SSFadingScrollView/SSFadingScrollView.swift +++ b/SSFadingScrollView/SSFadingScrollView.swift @@ -321,16 +321,16 @@ extension SSFadingScrollView { return mutableColours } - func animateGradientColours(_ colours: [Any]?) { + func animateGradientColors(_ colors: [CGColor]) { let animation = CABasicAnimation(keyPath: #keyPath(CAGradientLayer.colors)) animation.fromValue = (gradientLayer.presentation())?.colors - animation.toValue = colours + animation.toValue = colors animation.duration = fadeDuration animation.timingFunction = CAMediaTimingFunction(name: .easeOut) CATransaction.begin() CATransaction.setDisableActions(true) - gradientLayer.colors = colours // update the model value + gradientLayer.colors = colors // update the model value CATransaction.commit() gradientLayer.add(animation, forKey: "animateGradient") From f3e3c968095a5911ef8621456cf5b24ce4f62bd3 Mon Sep 17 00:00:00 2001 From: Bartosz Dolewski Date: Sat, 6 Jul 2019 18:16:54 +0200 Subject: [PATCH 04/16] Further changes --- SSFadingScrollView/SSFadingScrollView.swift | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/SSFadingScrollView/SSFadingScrollView.swift b/SSFadingScrollView/SSFadingScrollView.swift index 88fd61c..03bf0bc 100644 --- a/SSFadingScrollView/SSFadingScrollView.swift +++ b/SSFadingScrollView/SSFadingScrollView.swift @@ -304,21 +304,21 @@ extension SSFadingScrollView { // MARK: - Gradient animation extension SSFadingScrollView { func animateLeadingGradient(to color: CGColor) { - let colours = colorsArrayByReplacingObject(at: 0, with: color) - animateGradientColours(colours) + let colors = colorsWithReplacement(at: 0, with: color) + animateGradientColors(colors) } func animateTrailingGradient(to color: CGColor) { let lastIndex = gradientLayer.colors!.count - 1 - let colours = colorsArrayByReplacingObject(at: lastIndex, with: color) - animateGradientColours(colours) + let colors = colorsWithReplacement(at: lastIndex, with: color) + animateGradientColors(colors) } - func colorsArrayByReplacingObject(at index: Int, with color: CGColor) -> [CGColor] { - var mutableColours = gradientLayer.colors as! [CGColor] - mutableColours[index] = color + func colorsWithReplacement(at index: Int, with color: CGColor) -> [CGColor] { + var mutableColors = gradientLayer.colors as! [CGColor] + mutableColors[index] = color - return mutableColours + return mutableColors } func animateGradientColors(_ colors: [CGColor]) { From 40c952c02c40692ff0e4894af246fb81ee02ba15 Mon Sep 17 00:00:00 2001 From: Bartosz Dolewski Date: Sat, 6 Jul 2019 18:18:45 +0200 Subject: [PATCH 05/16] Removed redundant variable --- SSFadingScrollView/SSFadingScrollView.swift | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/SSFadingScrollView/SSFadingScrollView.swift b/SSFadingScrollView/SSFadingScrollView.swift index 03bf0bc..025d742 100644 --- a/SSFadingScrollView/SSFadingScrollView.swift +++ b/SSFadingScrollView/SSFadingScrollView.swift @@ -200,15 +200,14 @@ extension SSFadingScrollView { var colors: [CGColor] = [] var locations: [NSNumber] = [] - let fadePercentage = percentageForFadeSize - if fadeLeadingEdge { colors = [transparentColor, opaqueColor] - locations = [NSNumber(value: 0), NSNumber(value: Float(fadePercentage))] + locations = [NSNumber(value: 0), NSNumber(value: Float(percentageForFadeSize))] } + if fadeTrailingEdge { colors = colors + [opaqueColor, transparentColor] - locations = locations + [NSNumber(value: Float(1.0 - fadePercentage)), NSNumber(value: 1)] + locations = locations + [NSNumber(value: Float(1.0 - percentageForFadeSize)), NSNumber(value: 1)] } gradientLayer.colors = colors From bc9efcc169e01c31426c751338bf8422aaf1b770 Mon Sep 17 00:00:00 2001 From: Bartosz Dolewski Date: Sat, 6 Jul 2019 18:23:42 +0200 Subject: [PATCH 06/16] Fading refactored --- SSFadingScrollView/SSFadingScrollView.swift | 37 +++++++++++---------- 1 file changed, 20 insertions(+), 17 deletions(-) diff --git a/SSFadingScrollView/SSFadingScrollView.swift b/SSFadingScrollView/SSFadingScrollView.swift index 025d742..28008e8 100644 --- a/SSFadingScrollView/SSFadingScrollView.swift +++ b/SSFadingScrollView/SSFadingScrollView.swift @@ -165,30 +165,33 @@ extension SSFadingScrollView { updateScrollBarMasks() } + fileprivate func updateLeadingFade(_ contentOffset: Int) { + if !leadingGradientIsHidden && contentOffset <= 0 { + animateLeadingGradient(to: opaqueColor) // fade out + } else if leadingGradientIsHidden && contentOffset > 0 { + animateLeadingGradient(to: transparentColor) // fade in + } + } + + fileprivate func updateTrailingFade(_ contentOffset: Int) { + let maxContentOffset = isVertical ? Float(contentSize.height - bounds.height) : Float(contentSize.width - bounds.width) + + if !trailingGradientIsHidden && contentOffset >= Int(roundf(maxContentOffset)) { + animateTrailingGradient(to: opaqueColor) + } else if trailingGradientIsHidden && contentOffset < Int(roundf(maxContentOffset)) { + animateTrailingGradient(to: transparentColor) + } + } + func updateGradients() { gradientLayer.frame = maskLayer.bounds let contentOffset = Int(roundf(Float(isVertical ? self.contentOffset.y : self.contentOffset.x))) if fadeLeadingEdge { - if !leadingGradientIsHidden && contentOffset <= 0 { - animateLeadingGradient(to: opaqueColor) // fade out - } else if leadingGradientIsHidden && contentOffset > 0 { - animateLeadingGradient(to: transparentColor) // fade in - } + updateLeadingFade(contentOffset) } if fadeTrailingEdge { - var maxContentOffset: Int - if isVertical { - maxContentOffset = Int(roundf(Float(contentSize.height - bounds.height))) - } else { - maxContentOffset = Int(roundf(Float(contentSize.width - bounds.width))) - } - - if !trailingGradientIsHidden && contentOffset >= maxContentOffset { - animateTrailingGradient(to: opaqueColor) - } else if trailingGradientIsHidden && contentOffset < maxContentOffset { - animateTrailingGradient(to: transparentColor) - } + updateTrailingFade(contentOffset) } } From dcd6ee4e2ca3cef7b80426ce7dcd80bde59651a3 Mon Sep 17 00:00:00 2001 From: Bartosz Dolewski Date: Sat, 6 Jul 2019 18:35:10 +0200 Subject: [PATCH 07/16] Reorganised code --- SSFadingScrollView/SSFadingScrollView.swift | 87 +++++++++++---------- 1 file changed, 47 insertions(+), 40 deletions(-) diff --git a/SSFadingScrollView/SSFadingScrollView.swift b/SSFadingScrollView/SSFadingScrollView.swift index 28008e8..6f1f485 100644 --- a/SSFadingScrollView/SSFadingScrollView.swift +++ b/SSFadingScrollView/SSFadingScrollView.swift @@ -112,6 +112,14 @@ class SSFadingScrollView: UIScrollView { setDefaults() } + override func layoutSubviews() { + super.layoutSubviews() + updateMask() + } +} + +// MARK: - Setup helpers +private extension SSFadingScrollView { func setDefaults() { fadeAxis = .vertical fadeLeadingEdge = true @@ -120,13 +128,6 @@ class SSFadingScrollView: UIScrollView { fadeDuration = SSDefaultFadeDuration maskScrollBars = true } -} - -extension SSFadingScrollView { - override func layoutSubviews() { - super.layoutSubviews() - updateMask() - } func setupMaskLayer() -> CALayer { let maskLayer = CALayer() @@ -155,6 +156,36 @@ extension SSFadingScrollView { return scrollBar(with: horizontalScrollBar?.frame ?? .zero) } + func setupGradientLayer() -> CAGradientLayer { + let gradientLayer = CAGradientLayer() + gradientLayer.frame = self.bounds + gradientLayer.frame.origin = .zero + + var colors: [CGColor] = [] + var locations: [NSNumber] = [] + + if fadeLeadingEdge { + colors = [transparentColor, opaqueColor] + locations = [NSNumber(value: 0), NSNumber(value: Float(percentageForFadeSize))] + } + + if fadeTrailingEdge { + colors = colors + [opaqueColor, transparentColor] + locations = locations + [NSNumber(value: Float(1.0 - percentageForFadeSize)), NSNumber(value: 1)] + } + + gradientLayer.colors = colors + gradientLayer.locations = locations + + gradientLayer.startPoint = isVertical ? CGPoint(x: 0.5, y: 0.0) : CGPoint(x: 0.0, y: 0.5) + gradientLayer.endPoint = isVertical ? CGPoint(x: 0.5, y: 1.0) : CGPoint(x: 1.0, y: 0.5) + + return gradientLayer + } +} + +// MARK: - Update helpers +private extension SSFadingScrollView { func updateMask() { CATransaction.begin() CATransaction.setDisableActions(true) @@ -165,7 +196,7 @@ extension SSFadingScrollView { updateScrollBarMasks() } - fileprivate func updateLeadingFade(_ contentOffset: Int) { + func updateLeadingFade(_ contentOffset: Int) { if !leadingGradientIsHidden && contentOffset <= 0 { animateLeadingGradient(to: opaqueColor) // fade out } else if leadingGradientIsHidden && contentOffset > 0 { @@ -173,7 +204,7 @@ extension SSFadingScrollView { } } - fileprivate func updateTrailingFade(_ contentOffset: Int) { + func updateTrailingFade(_ contentOffset: Int) { let maxContentOffset = isVertical ? Float(contentSize.height - bounds.height) : Float(contentSize.width - bounds.width) if !trailingGradientIsHidden && contentOffset >= Int(roundf(maxContentOffset)) { @@ -195,33 +226,6 @@ extension SSFadingScrollView { } } - func setupGradientLayer() -> CAGradientLayer { - let gradientLayer = CAGradientLayer() - gradientLayer.frame = self.bounds - gradientLayer.frame.origin = .zero - - var colors: [CGColor] = [] - var locations: [NSNumber] = [] - - if fadeLeadingEdge { - colors = [transparentColor, opaqueColor] - locations = [NSNumber(value: 0), NSNumber(value: Float(percentageForFadeSize))] - } - - if fadeTrailingEdge { - colors = colors + [opaqueColor, transparentColor] - locations = locations + [NSNumber(value: Float(1.0 - percentageForFadeSize)), NSNumber(value: 1)] - } - - gradientLayer.colors = colors - gradientLayer.locations = locations - - gradientLayer.startPoint = isVertical ? CGPoint(x: 0.5, y: 0.0) : CGPoint(x: 0.0, y: 0.5) - gradientLayer.endPoint = isVertical ? CGPoint(x: 0.5, y: 1.0) : CGPoint(x: 1.0, y: 0.5) - - return gradientLayer - } - func updateScrollBarMasks() { guard maskScrollBars else { return } guard let verticalScrollBar = verticalScrollBar, @@ -240,7 +244,10 @@ extension SSFadingScrollView { CATransaction.commit() } - +} + +// MARK: - ScrollBars +extension SSFadingScrollView { func scrollBar(with frame: CGRect) -> CALayer { let scrollBarLayer = CALayer() scrollBarLayer.backgroundColor = opaqueColor @@ -249,7 +256,7 @@ extension SSFadingScrollView { return scrollBarLayer } - fileprivate func isScrollBar(_ dimension: CGFloat) -> Bool { + func isScrollBar(_ dimension: CGFloat) -> Bool { return dimension == 3.5 || dimension == 2.5 || ((dimension) < 2.4 && (dimension ) > 2.3) } @@ -268,7 +275,7 @@ extension SSFadingScrollView { } // MARK: - Properties -extension SSFadingScrollView { +private extension SSFadingScrollView { var isVertical: Bool { return fadeAxis == .vertical } @@ -304,7 +311,7 @@ extension SSFadingScrollView { } // MARK: - Gradient animation -extension SSFadingScrollView { +private extension SSFadingScrollView { func animateLeadingGradient(to color: CGColor) { let colors = colorsWithReplacement(at: 0, with: color) animateGradientColors(colors) From 667f1e89cba30fe342672d29d746caff519d3fdb Mon Sep 17 00:00:00 2001 From: Bartosz Dolewski Date: Sat, 6 Jul 2019 18:47:01 +0200 Subject: [PATCH 08/16] Removed unnecessary casting Float <-> CGFloat --- SSFadingScrollView/SSFadingScrollView.swift | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/SSFadingScrollView/SSFadingScrollView.swift b/SSFadingScrollView/SSFadingScrollView.swift index 6f1f485..d47b5d3 100644 --- a/SSFadingScrollView/SSFadingScrollView.swift +++ b/SSFadingScrollView/SSFadingScrollView.swift @@ -166,12 +166,12 @@ private extension SSFadingScrollView { if fadeLeadingEdge { colors = [transparentColor, opaqueColor] - locations = [NSNumber(value: 0), NSNumber(value: Float(percentageForFadeSize))] + locations = [NSNumber(value: 0), NSNumber(value: percentageForFadeSize)] } if fadeTrailingEdge { colors = colors + [opaqueColor, transparentColor] - locations = locations + [NSNumber(value: Float(1.0 - percentageForFadeSize)), NSNumber(value: 1)] + locations = locations + [NSNumber(value: 1.0 - percentageForFadeSize), NSNumber(value: 1)] } gradientLayer.colors = colors @@ -298,15 +298,15 @@ private extension SSFadingScrollView { return UIColor.clear.cgColor } - var percentageForFadeSize: CGFloat { + var percentageForFadeSize: Float { let size = isVertical ? bounds.height : bounds.width if size <= 0 { return 0 } - let maxFadePercentage: CGFloat = (fadeLeadingEdge && fadeTrailingEdge) ? 0.5 : 1.0 - return CGFloat(fminf(Float(fadeSize / size), Float(maxFadePercentage))) + let maxFadePercentage = (fadeLeadingEdge && fadeTrailingEdge) ? Float(0.5) : Float(1.0) + return fminf(Float(fadeSize / size), maxFadePercentage) } } @@ -318,7 +318,9 @@ private extension SSFadingScrollView { } func animateTrailingGradient(to color: CGColor) { - let lastIndex = gradientLayer.colors!.count - 1 + guard let endIndex = gradientLayer.colors?.endIndex else { return } + + let lastIndex = endIndex - 1 let colors = colorsWithReplacement(at: lastIndex, with: color) animateGradientColors(colors) } From 1fa80b79f37c101d5a0f7cc0179102b6ca31254c Mon Sep 17 00:00:00 2001 From: Bartosz Dolewski Date: Sat, 6 Jul 2019 18:58:03 +0200 Subject: [PATCH 09/16] Fixed documentation in code --- SSFadingScrollView/SSFadingScrollView.swift | 43 ++++++++++----------- 1 file changed, 20 insertions(+), 23 deletions(-) diff --git a/SSFadingScrollView/SSFadingScrollView.swift b/SSFadingScrollView/SSFadingScrollView.swift index d47b5d3..e235d60 100644 --- a/SSFadingScrollView/SSFadingScrollView.swift +++ b/SSFadingScrollView/SSFadingScrollView.swift @@ -25,36 +25,33 @@ private let SSDefaultFadeDuration: CFTimeInterval = 0.3 @IBDesignable class SSFadingScrollView: UIScrollView { - /** - * Fade leading edge of fade axis. Default is YES. - */ - @IBInspectable var fadeLeadingEdge = false - /** - * Fade trailing edge of fade axis. Default is YES. - */ - @IBInspectable var fadeTrailingEdge = false - /** - * Size of gradient. Default is 30. - */ - @IBInspectable var fadeSize: CGFloat = 0.0 - /** - * Duration of fade in & out. Default is 0.3 seconds. - */ - @IBInspectable var fadeDuration = 0.0 - /** - * Default is YES. Scroll bars are masked so they don't fade with the scroll view content. - * Set to NO to fade out the scroll bars along with the content. - */ - @IBInspectable var maskScrollBars = false + /// Fade leading edge of fade axis. Default is YES. + @IBInspectable public var fadeLeadingEdge = false + + /// Fade trailing edge of fade axis. Default is YES. + @IBInspectable public var fadeTrailingEdge = false + + /// Size of gradient. Default is 30. + @IBInspectable public var fadeSize: CGFloat = 0.0 + + /// Duration of fade in & out. Default is 0.3 seconds. + @IBInspectable public var fadeDuration = 0.0 + + /// Default is YES. Scroll bars are masked so they don't fade with the scroll view content. + /// Set to NO to fade out the scroll bars along with the content. + @IBInspectable public var maskScrollBars = false + + /// Set up the axis of fading + public var fadeAxis: FadeAxis = .vertical + + /// Set up the axis of fading in Interface Builder @available(*, unavailable, message: "This property is reserved for Interface Builder. Use 'fadeAxis' instead.") @IBInspectable var axisIB: FadeAxis.RawValue { set { fadeAxis = FadeAxis(rawValue: newValue) ?? .vertical } get { return fadeAxis.rawValue } } - var fadeAxis: FadeAxis = .vertical - private lazy var maskLayer: CALayer = { return setupMaskLayer() }() From 0f0fa70ed3a2654f0366c9312f9c84e78b228082 Mon Sep 17 00:00:00 2001 From: Bartosz Dolewski Date: Sat, 6 Jul 2019 19:01:05 +0200 Subject: [PATCH 10/16] Removed deprecated code --- SSFadingScrollView/SSFadingScrollView.swift | 6 ------ 1 file changed, 6 deletions(-) diff --git a/SSFadingScrollView/SSFadingScrollView.swift b/SSFadingScrollView/SSFadingScrollView.swift index e235d60..fd7b654 100644 --- a/SSFadingScrollView/SSFadingScrollView.swift +++ b/SSFadingScrollView/SSFadingScrollView.swift @@ -14,12 +14,6 @@ import QuartzCore case horizontal = 1 } -@objc enum FadeEdges: Int { - case FadeEdgesTopAndBottom - case FadeEdgesTop - case FadeEdgesBottom -} - private let SSDefaultFadeSize: CGFloat = 30.0 private let SSDefaultFadeDuration: CFTimeInterval = 0.3 From e42dd5a114c77369a4bb072436b492429742a21d Mon Sep 17 00:00:00 2001 From: Bartosz Dolewski Date: Sat, 6 Jul 2019 19:39:26 +0200 Subject: [PATCH 11/16] Updated for Xcode 10 --- SSFadingScrollView.xcodeproj/project.pbxproj | 47 +++++++++- .../xcschemes/SSFadingScrollView.xcscheme | 2 +- .../xcschemes/SSFadingScrollViewDemo.xcscheme | 2 +- .../MainStoryboard.storyboard | 91 ++++++++++--------- .../LaunchScreen.storyboard | 28 +++--- 5 files changed, 106 insertions(+), 64 deletions(-) rename SSFadingScrollViewDemo/{en.lproj => Base.lproj}/MainStoryboard.storyboard (92%) diff --git a/SSFadingScrollView.xcodeproj/project.pbxproj b/SSFadingScrollView.xcodeproj/project.pbxproj index 155d582..eae6061 100644 --- a/SSFadingScrollView.xcodeproj/project.pbxproj +++ b/SSFadingScrollView.xcodeproj/project.pbxproj @@ -48,6 +48,7 @@ /* End PBXCopyFilesBuildPhase section */ /* Begin PBXFileReference section */ + 152EDF8422D113810082A3BA /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/MainStoryboard.storyboard; sourceTree = ""; }; 82630F641B63A4EE003B4CCA /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = ""; }; 82B3A68D1C031A13000024C3 /* SSFadingScrollView.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = SSFadingScrollView.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 82B3A68F1C031A13000024C3 /* SSFadingScrollView.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SSFadingScrollView.h; sourceTree = ""; }; @@ -63,7 +64,6 @@ 970FDD7E17A7A512008DC2FB /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; 970FDD8117A7A512008DC2FB /* SSAppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SSAppDelegate.h; sourceTree = ""; }; 970FDD8217A7A512008DC2FB /* SSAppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SSAppDelegate.m; sourceTree = ""; }; - 970FDD8B17A7A512008DC2FB /* en */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = en; path = en.lproj/MainStoryboard.storyboard; sourceTree = ""; }; 970FDD9B17A7A5B9008DC2FB /* QuartzCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = QuartzCore.framework; path = System/Library/Frameworks/QuartzCore.framework; sourceTree = SDKROOT; }; /* End PBXFileReference section */ @@ -211,7 +211,7 @@ isa = PBXProject; attributes = { CLASSPREFIX = SS; - LastUpgradeCheck = 0710; + LastUpgradeCheck = 1020; ORGANIZATIONNAME = "Stephanie Sharp"; TargetAttributes = { 82B3A68C1C031A13000024C3 = { @@ -221,10 +221,11 @@ }; buildConfigurationList = 970FDD2217A7A4DC008DC2FB /* Build configuration list for PBXProject "SSFadingScrollView" */; compatibilityVersion = "Xcode 6.3"; - developmentRegion = English; + developmentRegion = en; hasScannedForEncodings = 0; knownRegions = ( en, + Base, ); mainGroup = 970FDD1E17A7A4DC008DC2FB; productRefGroup = 970FDD2817A7A4DC008DC2FB /* Products */; @@ -298,7 +299,7 @@ 970FDD8A17A7A512008DC2FB /* MainStoryboard.storyboard */ = { isa = PBXVariantGroup; children = ( - 970FDD8B17A7A512008DC2FB /* en */, + 152EDF8422D113810082A3BA /* Base */, ); name = MainStoryboard.storyboard; sourceTree = ""; @@ -314,6 +315,7 @@ CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_UNREACHABLE_CODE = YES; + CODE_SIGN_IDENTITY = ""; CURRENT_PROJECT_VERSION = 1; DEBUG_INFORMATION_FORMAT = dwarf; DEFINES_MODULE = YES; @@ -348,6 +350,7 @@ CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_UNREACHABLE_CODE = YES; + CODE_SIGN_IDENTITY = ""; COPY_PHASE_STRIP = NO; CURRENT_PROJECT_VERSION = 1; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; @@ -380,27 +383,45 @@ isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES; CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_CXX_LIBRARY = "libc++"; 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_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 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_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + 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; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; COPY_PHASE_STRIP = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; ENABLE_TESTABILITY = YES; GCC_C_LANGUAGE_STANDARD = gnu99; GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; GCC_OPTIMIZATION_LEVEL = 0; GCC_PREPROCESSOR_DEFINITIONS = ( "DEBUG=1", "$(inherited)", ); GCC_SYMBOLS_PRIVATE_EXTERN = NO; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES; + GCC_WARN_UNDECLARED_SELECTOR = YES; GCC_WARN_UNINITIALIZED_AUTOS = YES; + GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; IPHONEOS_DEPLOYMENT_TARGET = 8.0; ONLY_ACTIVE_ARCH = YES; @@ -412,19 +433,37 @@ isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES; CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_CXX_LIBRARY = "libc++"; 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_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 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_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + 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; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; COPY_PHASE_STRIP = YES; + ENABLE_STRICT_OBJC_MSGSEND = YES; GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES; + GCC_WARN_UNDECLARED_SELECTOR = YES; GCC_WARN_UNINITIALIZED_AUTOS = YES; + GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; IPHONEOS_DEPLOYMENT_TARGET = 8.0; OTHER_CFLAGS = "-DNS_BLOCK_ASSERTIONS=1"; diff --git a/SSFadingScrollView.xcodeproj/xcshareddata/xcschemes/SSFadingScrollView.xcscheme b/SSFadingScrollView.xcodeproj/xcshareddata/xcschemes/SSFadingScrollView.xcscheme index d7d627d..2547d03 100644 --- a/SSFadingScrollView.xcodeproj/xcshareddata/xcschemes/SSFadingScrollView.xcscheme +++ b/SSFadingScrollView.xcodeproj/xcshareddata/xcschemes/SSFadingScrollView.xcscheme @@ -1,6 +1,6 @@ - + + + + + - - + + @@ -11,26 +14,26 @@ - + - + - + - + - + - + - + - + - + - + - + - + - + @@ -127,14 +130,14 @@ - + - + - + @@ -174,7 +177,7 @@ Maecenas sagittis eu felis sed pellentesque. Integer varius justo sem, sed viver - + @@ -188,7 +191,7 @@ Maecenas sagittis eu felis sed pellentesque. Integer varius justo sem, sed viver - + @@ -199,11 +202,11 @@ Maecenas sagittis eu felis sed pellentesque. Integer varius justo sem, sed viver - + - + @@ -242,7 +245,7 @@ Maecenas sagittis eu felis sed pellentesque. Integer varius justo sem, sed viver - + @@ -257,7 +260,7 @@ Maecenas sagittis eu felis sed pellentesque. Integer varius justo sem, sed viver - + @@ -265,7 +268,7 @@ Maecenas sagittis eu felis sed pellentesque. Integer varius justo sem, sed viver - + @@ -275,7 +278,7 @@ Maecenas sagittis eu felis sed pellentesque. Integer varius justo sem, sed viver - + @@ -286,14 +289,14 @@ Maecenas sagittis eu felis sed pellentesque. Integer varius justo sem, sed viver - + - + @@ -365,26 +368,26 @@ Maecenas sagittis eu felis sed pellentesque. Integer varius justo sem, sed viver - + - + - + - + - + @@ -412,7 +415,7 @@ Maecenas sagittis eu felis sed pellentesque. Integer varius justo sem, sed viver - + @@ -426,7 +429,7 @@ Maecenas sagittis eu felis sed pellentesque. Integer varius justo sem, sed viver - + diff --git a/SSFadingScrollViewDemo/LaunchScreen.storyboard b/SSFadingScrollViewDemo/LaunchScreen.storyboard index d29eb3e..a5cd9bc 100644 --- a/SSFadingScrollViewDemo/LaunchScreen.storyboard +++ b/SSFadingScrollViewDemo/LaunchScreen.storyboard @@ -1,9 +1,12 @@ - - + + + + + - - + + @@ -15,26 +18,23 @@ - + - - - + From 9f12e7a2c97c5a0ab8dc92abd7e075e7077d8eb8 Mon Sep 17 00:00:00 2001 From: Bartosz Dolewski Date: Sun, 14 Jul 2019 20:51:52 +0200 Subject: [PATCH 12/16] Don't bump up the version Deployment target to iOS 9 --- SSFadingScrollView.podspec | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/SSFadingScrollView.podspec b/SSFadingScrollView.podspec index 894e2de..5f70ba0 100644 --- a/SSFadingScrollView.podspec +++ b/SSFadingScrollView.podspec @@ -1,11 +1,11 @@ Pod::Spec.new do |s| s.name = "SSFadingScrollView" - s.version = "2.0.0" + s.version = "1.1.0" s.summary = "A UIScrollView subclass that fades the leading and/or trailing edges of a scroll view to transparent" s.homepage = "https://github.com/stephsharp/SSFadingScrollView/" s.license = { :type => "MIT", :file => "LICENSE" } s.author = "Stephanie Sharp" - s.platform = :ios, "10.3" + s.platform = :ios, "9.3" s.source = { :git => "https://github.com/stephsharp/SSFadingScrollView.git", :tag => "v#{s.version}" } s.source_files = "SSFadingScrollView" s.public_header_files = [ "SSFadingScrollView/SSFadingScrollView.h" ] From be7147a2f94f5e0f78342d9760268182ab735d42 Mon Sep 17 00:00:00 2001 From: Bartosz Dolewski Date: Sat, 12 Oct 2019 09:43:50 +0200 Subject: [PATCH 13/16] Updated to Xcode 11.1 recommended settings --- SSFadingScrollView.xcodeproj/project.pbxproj | 3 ++- .../xcshareddata/xcschemes/SSFadingScrollView.xcscheme | 6 +----- .../xcschemes/SSFadingScrollViewDemo.xcscheme | 10 +++------- 3 files changed, 6 insertions(+), 13 deletions(-) diff --git a/SSFadingScrollView.xcodeproj/project.pbxproj b/SSFadingScrollView.xcodeproj/project.pbxproj index f94dbf6..5026699 100644 --- a/SSFadingScrollView.xcodeproj/project.pbxproj +++ b/SSFadingScrollView.xcodeproj/project.pbxproj @@ -207,7 +207,7 @@ isa = PBXProject; attributes = { CLASSPREFIX = SS; - LastUpgradeCheck = 1020; + LastUpgradeCheck = 1110; ORGANIZATIONNAME = "Stephanie Sharp"; TargetAttributes = { 82B3A68C1C031A13000024C3 = { @@ -468,6 +468,7 @@ IPHONEOS_DEPLOYMENT_TARGET = 10.3; OTHER_CFLAGS = "-DNS_BLOCK_ASSERTIONS=1"; SDKROOT = iphoneos; + SWIFT_COMPILATION_MODE = wholemodule; VALIDATE_PRODUCT = YES; }; name = Release; diff --git a/SSFadingScrollView.xcodeproj/xcshareddata/xcschemes/SSFadingScrollView.xcscheme b/SSFadingScrollView.xcodeproj/xcshareddata/xcschemes/SSFadingScrollView.xcscheme index 2547d03..2fc0979 100644 --- a/SSFadingScrollView.xcodeproj/xcshareddata/xcschemes/SSFadingScrollView.xcscheme +++ b/SSFadingScrollView.xcodeproj/xcshareddata/xcschemes/SSFadingScrollView.xcscheme @@ -1,6 +1,6 @@ - - - - - - - - + + - - Date: Sat, 12 Oct 2019 09:55:57 +0200 Subject: [PATCH 14/16] Added support for Swift Package Manager --- Package.swift | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) create mode 100644 Package.swift diff --git a/Package.swift b/Package.swift new file mode 100644 index 0000000..b092d08 --- /dev/null +++ b/Package.swift @@ -0,0 +1,21 @@ +// swift-tools-version:5.1 +// The swift-tools-version declares the minimum version of Swift required to build this package. + +import PackageDescription + +let package = Package( + name: "SSFadingScrollView", + platforms: [.iOS(.v9)], + products: [ + .library( + name: "SSFadingScrollView", + targets: ["SSFadingScrollView"]), + ], + dependencies: [], + targets: [ + .target( + name: "SSFadingScrollView", + dependencies: [], + path: "SSFadingScrollView") + ] +) From 686dc7fbba1210b278bfc4cd62a5492b61f1b00a Mon Sep 17 00:00:00 2001 From: Bartosz Dolewski Date: Sat, 12 Oct 2019 09:57:52 +0200 Subject: [PATCH 15/16] Ignore SPM related files --- .gitignore | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.gitignore b/.gitignore index 9b9088f..fef22fd 100644 --- a/.gitignore +++ b/.gitignore @@ -22,3 +22,6 @@ build/ # Backup files *~.nib + +# Swift Package Manager +.swiftpm From d552315484dac3d59666aed2118150ab4d9a0e33 Mon Sep 17 00:00:00 2001 From: Bartosz Dolewski Date: Sat, 12 Oct 2019 10:00:32 +0200 Subject: [PATCH 16/16] Support for Travis CI --- .travis.yml | 9 +++++++++ 1 file changed, 9 insertions(+) create mode 100644 .travis.yml diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000..a01a9c5 --- /dev/null +++ b/.travis.yml @@ -0,0 +1,9 @@ +os: + - osx +language: swift +osx_image: xcode11 +env: + - PROJECT_NAME=SSFadingScrollView +install: swift package update +script: + - xcodebuild build -sdk iphoneos -scheme $PROJECT_NAME