diff --git a/.DS_Store b/.DS_Store deleted file mode 100644 index 777396d..0000000 Binary files a/.DS_Store and /dev/null differ diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..e43b0f9 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +.DS_Store diff --git a/.swift-version b/.swift-version index 9f55b2c..819e07a 100644 --- a/.swift-version +++ b/.swift-version @@ -1 +1 @@ -3.0 +5.0 diff --git a/AlertOnboarding.podspec b/AlertOnboarding.podspec index e2a819d..b83e932 100755 --- a/AlertOnboarding.podspec +++ b/AlertOnboarding.podspec @@ -7,7 +7,7 @@ s.homepage = "https://github.com/PhilippeBoisney/AlertOnboarding" s.license = 'MIT' s.author = { "PhilippeBoisney" => "phil.boisney@gmail.com" } s.source = { :git => "https://github.com/PhilippeBoisney/AlertOnboarding.git", :tag => s.version } -s.platform = :ios, '8.0' +s.platform = :ios, '9.0' s.requires_arc = true # If more than one source file: https://guides.cocoapods.org/syntax/podspec.html#source_files diff --git a/AlertOnboarding.xcodeproj/project.pbxproj b/AlertOnboarding.xcodeproj/project.pbxproj index 4fb1e79..35ea132 100644 --- a/AlertOnboarding.xcodeproj/project.pbxproj +++ b/AlertOnboarding.xcodeproj/project.pbxproj @@ -12,10 +12,11 @@ 37845A6E1D994CBA009B3734 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 37845A6C1D994CBA009B3734 /* Main.storyboard */; }; 37845A701D994CBA009B3734 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 37845A6F1D994CBA009B3734 /* Assets.xcassets */; }; 37845A731D994CBA009B3734 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 37845A711D994CBA009B3734 /* LaunchScreen.storyboard */; }; - 37845A7C1D994D65009B3734 /* AlertOnboarding.swift in Sources */ = {isa = PBXBuildFile; fileRef = 37845A7B1D994D65009B3734 /* AlertOnboarding.swift */; }; - 37845A7E1D994D87009B3734 /* AlertChildPageViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 37845A7D1D994D87009B3734 /* AlertChildPageViewController.swift */; }; - 37845A801D994DA6009B3734 /* AlertPageViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 37845A7F1D994DA6009B3734 /* AlertPageViewController.swift */; }; 37845A821D994DE6009B3734 /* AlertChildPageViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 37845A811D994DE6009B3734 /* AlertChildPageViewController.xib */; }; + 568AB1512298215E00C06C37 /* Alert.swift in Sources */ = {isa = PBXBuildFile; fileRef = 568AB14D2298215E00C06C37 /* Alert.swift */; }; + 568AB1522298215E00C06C37 /* AlertChildPageViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 568AB14E2298215E00C06C37 /* AlertChildPageViewController.swift */; }; + 568AB1532298215E00C06C37 /* AlertPageViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 568AB14F2298215E00C06C37 /* AlertPageViewController.swift */; }; + 568AB1542298215E00C06C37 /* AlertOnboarding.swift in Sources */ = {isa = PBXBuildFile; fileRef = 568AB1502298215E00C06C37 /* AlertOnboarding.swift */; }; /* End PBXBuildFile section */ /* Begin PBXFileReference section */ @@ -26,10 +27,11 @@ 37845A6F1D994CBA009B3734 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 37845A721D994CBA009B3734 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; 37845A741D994CBA009B3734 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; - 37845A7B1D994D65009B3734 /* AlertOnboarding.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AlertOnboarding.swift; sourceTree = ""; }; - 37845A7D1D994D87009B3734 /* AlertChildPageViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AlertChildPageViewController.swift; sourceTree = ""; }; - 37845A7F1D994DA6009B3734 /* AlertPageViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AlertPageViewController.swift; sourceTree = ""; }; 37845A811D994DE6009B3734 /* AlertChildPageViewController.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = AlertChildPageViewController.xib; sourceTree = ""; }; + 568AB14D2298215E00C06C37 /* Alert.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Alert.swift; sourceTree = ""; }; + 568AB14E2298215E00C06C37 /* AlertChildPageViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AlertChildPageViewController.swift; sourceTree = ""; }; + 568AB14F2298215E00C06C37 /* AlertPageViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AlertPageViewController.swift; sourceTree = ""; }; + 568AB1502298215E00C06C37 /* AlertOnboarding.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AlertOnboarding.swift; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -62,7 +64,7 @@ 37845A671D994CBA009B3734 /* AlertOnboarding */ = { isa = PBXGroup; children = ( - 37845A7A1D994D51009B3734 /* Alert */, + 568AB14C2298215E00C06C37 /* Classes */, 37845A681D994CBA009B3734 /* AppDelegate.swift */, 37845A6A1D994CBA009B3734 /* ViewController.swift */, 37845A6C1D994CBA009B3734 /* Main.storyboard */, @@ -74,15 +76,17 @@ path = AlertOnboarding; sourceTree = ""; }; - 37845A7A1D994D51009B3734 /* Alert */ = { + 568AB14C2298215E00C06C37 /* Classes */ = { isa = PBXGroup; children = ( - 37845A7B1D994D65009B3734 /* AlertOnboarding.swift */, - 37845A7D1D994D87009B3734 /* AlertChildPageViewController.swift */, - 37845A7F1D994DA6009B3734 /* AlertPageViewController.swift */, + 568AB14D2298215E00C06C37 /* Alert.swift */, + 568AB14E2298215E00C06C37 /* AlertChildPageViewController.swift */, + 568AB14F2298215E00C06C37 /* AlertPageViewController.swift */, + 568AB1502298215E00C06C37 /* AlertOnboarding.swift */, ); - name = Alert; - sourceTree = ""; + name = Classes; + path = Pod/Classes; + sourceTree = SOURCE_ROOT; }; /* End PBXGroup section */ @@ -111,18 +115,19 @@ isa = PBXProject; attributes = { LastSwiftUpdateCheck = 0800; - LastUpgradeCheck = 0800; + LastUpgradeCheck = 1020; ORGANIZATIONNAME = CookMinute; TargetAttributes = { 37845A641D994CBA009B3734 = { CreatedOnToolsVersion = 8.0; + LastSwiftMigration = 1020; ProvisioningStyle = Automatic; }; }; }; buildConfigurationList = 37845A601D994CBA009B3734 /* Build configuration list for PBXProject "AlertOnboarding" */; compatibilityVersion = "Xcode 3.2"; - developmentRegion = English; + developmentRegion = en; hasScannedForEncodings = 0; knownRegions = ( en, @@ -157,10 +162,11 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - 37845A801D994DA6009B3734 /* AlertPageViewController.swift in Sources */, + 568AB1532298215E00C06C37 /* AlertPageViewController.swift in Sources */, + 568AB1542298215E00C06C37 /* AlertOnboarding.swift in Sources */, + 568AB1512298215E00C06C37 /* Alert.swift in Sources */, + 568AB1522298215E00C06C37 /* AlertChildPageViewController.swift in Sources */, 37845A6B1D994CBA009B3734 /* ViewController.swift in Sources */, - 37845A7E1D994D87009B3734 /* AlertChildPageViewController.swift in Sources */, - 37845A7C1D994D65009B3734 /* AlertOnboarding.swift in Sources */, 37845A691D994CBA009B3734 /* AppDelegate.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; @@ -196,15 +202,24 @@ 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_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_DOCUMENTATION_COMMENTS = YES; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INFINITE_RECURSION = YES; CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; CLANG_WARN_SUSPICIOUS_MOVES = YES; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; @@ -247,15 +262,24 @@ 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_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_DOCUMENTATION_COMMENTS = YES; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INFINITE_RECURSION = YES; CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; CLANG_WARN_SUSPICIOUS_MOVES = YES; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; @@ -291,7 +315,7 @@ LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = com.cookminute.AlertOnboarding; PRODUCT_NAME = "$(TARGET_NAME)"; - SWIFT_VERSION = 4.0; + SWIFT_VERSION = 5.0; }; name = Debug; }; @@ -304,7 +328,7 @@ LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = com.cookminute.AlertOnboarding; PRODUCT_NAME = "$(TARGET_NAME)"; - SWIFT_VERSION = 4.0; + SWIFT_VERSION = 5.0; }; name = Release; }; diff --git a/AlertOnboarding.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/AlertOnboarding.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100644 index 0000000..18d9810 --- /dev/null +++ b/AlertOnboarding.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/AlertOnboarding.xcodeproj/project.xcworkspace/xcuserdata/gabmarfer.xcuserdatad/UserInterfaceState.xcuserstate b/AlertOnboarding.xcodeproj/project.xcworkspace/xcuserdata/gabmarfer.xcuserdatad/UserInterfaceState.xcuserstate new file mode 100644 index 0000000..3860f49 Binary files /dev/null and b/AlertOnboarding.xcodeproj/project.xcworkspace/xcuserdata/gabmarfer.xcuserdatad/UserInterfaceState.xcuserstate differ diff --git a/AlertOnboarding.xcodeproj/xcuserdata/gabmarfer.xcuserdatad/xcschemes/xcschememanagement.plist b/AlertOnboarding.xcodeproj/xcuserdata/gabmarfer.xcuserdatad/xcschemes/xcschememanagement.plist new file mode 100644 index 0000000..70c6f4d --- /dev/null +++ b/AlertOnboarding.xcodeproj/xcuserdata/gabmarfer.xcuserdatad/xcschemes/xcschememanagement.plist @@ -0,0 +1,14 @@ + + + + + SchemeUserState + + AlertOnboarding.xcscheme_^#shared#^_ + + orderHint + 0 + + + + diff --git a/AlertOnboarding/AlertChildPageViewController.swift b/AlertOnboarding/AlertChildPageViewController.swift deleted file mode 100644 index 435722e..0000000 --- a/AlertOnboarding/AlertChildPageViewController.swift +++ /dev/null @@ -1,26 +0,0 @@ -// -// AlertChildPageViewController.swift -// AlertOnboarding -// -// Created by Philippe on 26/09/2016. -// Copyright © 2016 CookMinute. All rights reserved. -// - -import UIKit - -class AlertChildPageViewController: UIViewController { - - var pageIndex: Int! - - @IBOutlet weak var image: UIImageView! - @IBOutlet weak var labelMainTitle: UILabel! - @IBOutlet weak var labelDescription: UILabel! - - override func viewDidLoad() { - super.viewDidLoad() - } - - override func didReceiveMemoryWarning() { - super.didReceiveMemoryWarning() - } -} diff --git a/AlertOnboarding/AlertChildPageViewController.xib b/AlertOnboarding/AlertChildPageViewController.xib index a004aca..46bd6af 100644 --- a/AlertOnboarding/AlertChildPageViewController.xib +++ b/AlertOnboarding/AlertChildPageViewController.xib @@ -1,8 +1,11 @@ - - + + + + + - + @@ -19,38 +22,38 @@ - - + + - - - - - - - + + + + + + + - - + + - - + + @@ -85,17 +88,17 @@ - + - + - + diff --git a/AlertOnboarding/AlertOnboarding.swift b/AlertOnboarding/AlertOnboarding.swift deleted file mode 100644 index 060b91e..0000000 --- a/AlertOnboarding/AlertOnboarding.swift +++ /dev/null @@ -1,251 +0,0 @@ -// -// AlertOnboarding.swift -// AlertOnboarding -// -// Created by Philippe on 26/09/2016. -// Copyright © 2016 CookMinute. All rights reserved. -// - -import UIKit - -public protocol AlertOnboardingDelegate { - func alertOnboardingSkipped(_ currentStep: Int, maxStep: Int) - func alertOnboardingCompleted() - func alertOnboardingNext(_ nextStep: Int) -} - -open class AlertOnboarding: UIView, AlertPageViewDelegate { - - //FOR DATA ------------------------ - fileprivate var arrayOfImage = [String]() - fileprivate var arrayOfTitle = [String]() - fileprivate var arrayOfDescription = [String]() - - //FOR DESIGN ------------------------ - open var buttonBottom: UIButton! - fileprivate var container: AlertPageViewController! - open var background: UIView! - - - //PUBLIC VARS ------------------------ - open var colorForAlertViewBackground: UIColor = UIColor.white - - open var colorButtonBottomBackground: UIColor = UIColor(red: 226/255, green: 237/255, blue: 248/255, alpha: 1.0) - open var colorButtonText: UIColor = UIColor(red: 118/255, green: 125/255, blue: 152/255, alpha: 1.0) - - open var colorTitleLabel: UIColor = UIColor(red: 171/255, green: 177/255, blue: 196/255, alpha: 1.0) - open var colorDescriptionLabel: UIColor = UIColor(red: 171/255, green: 177/255, blue: 196/255, alpha: 1.0) - - open var colorPageIndicator = UIColor(red: 171/255, green: 177/255, blue: 196/255, alpha: 1.0) - open var colorCurrentPageIndicator = UIColor(red: 118/255, green: 125/255, blue: 152/255, alpha: 1.0) - - open var heightForAlertView: CGFloat! - open var widthForAlertView: CGFloat! - - open var percentageRatioHeight: CGFloat = 0.8 - open var percentageRatioWidth: CGFloat = 0.8 - - open var titleSkipButton = "SKIP" - open var titleGotItButton = "GOT IT !" - - open var delegate: AlertOnboardingDelegate? - - - public init (arrayOfImage: [String], arrayOfTitle: [String], arrayOfDescription: [String]) { - super.init(frame: CGRect(x: 0,y: 0,width: 0,height: 0)) - self.configure(arrayOfImage, arrayOfTitle: arrayOfTitle, arrayOfDescription: arrayOfDescription) - self.arrayOfImage = arrayOfImage - self.arrayOfTitle = arrayOfTitle - self.arrayOfDescription = arrayOfDescription - - self.interceptOrientationChange() - } - - override public init(frame: CGRect) { - super.init(frame: frame) - } - - required public init?(coder aDecoder: NSCoder) { - fatalError("init(coder:) has not been implemented") - } - - override open func layoutSubviews() { - super.layoutSubviews() - } - - //----------------------------------------------------------------------------------------- - // MARK: PUBLIC FUNCTIONS -------------------------------------------------------------- - //----------------------------------------------------------------------------------------- - - open func show() { - - //Update Color - self.buttonBottom.backgroundColor = colorButtonBottomBackground - self.backgroundColor = colorForAlertViewBackground - self.buttonBottom.setTitleColor(colorButtonText, for: UIControlState()) - self.buttonBottom.setTitle(self.titleSkipButton, for: UIControlState()) - - self.container = AlertPageViewController(arrayOfImage: arrayOfImage, arrayOfTitle: arrayOfTitle, arrayOfDescription: arrayOfDescription, alertView: self) - self.container.delegate = self - self.insertSubview(self.container.view, aboveSubview: self) - self.insertSubview(self.buttonBottom, aboveSubview: self) - - // Only show once - if self.superview != nil { - return - } - - // Find current stop viewcontroller - if let topController = getTopViewController() { - let superView: UIView = topController.view - superView.addSubview(self.background) - superView.addSubview(self) - self.configureConstraints(topController.view) - self.animateForOpening() - } - } - - //Hide onboarding with animation - open func hide(){ - self.checkIfOnboardingWasSkipped() - DispatchQueue.main.async { () -> Void in - self.animateForEnding() - } - } - - - //------------------------------------------------------------------------------------------ - // MARK: PRIVATE FUNCTIONS -------------------------------------------------------------- - //------------------------------------------------------------------------------------------ - - //MARK: Check if onboarding was skipped - fileprivate func checkIfOnboardingWasSkipped(){ - let currentStep = self.container.currentStep - if currentStep < (self.container.arrayOfImage.count - 1) && !self.container.isCompleted{ - self.delegate?.alertOnboardingSkipped(currentStep, maxStep: self.container.maxStep) - } - else { - self.delegate?.alertOnboardingCompleted() - } - } - - - //MARK: FOR CONFIGURATION -------------------------------------- - fileprivate func configure(_ arrayOfImage: [String], arrayOfTitle: [String], arrayOfDescription: [String]) { - - self.buttonBottom = UIButton(frame: CGRect(x: 0,y: 0, width: 0, height: 0)) - self.buttonBottom.titleLabel?.font = UIFont(name: "Avenir-Black", size: 15) - self.buttonBottom.addTarget(self, action: #selector(AlertOnboarding.onClick), for: .touchUpInside) - - self.background = UIView(frame: CGRect(x: 0,y: 0, width: 0, height: 0)) - self.background.backgroundColor = UIColor.black - self.background.alpha = 0.5 - - - self.clipsToBounds = true - self.layer.cornerRadius = 10 - } - - - fileprivate func configureConstraints(_ superView: UIView) { - - self.translatesAutoresizingMaskIntoConstraints = false - self.buttonBottom.translatesAutoresizingMaskIntoConstraints = false - self.container.view.translatesAutoresizingMaskIntoConstraints = false - self.background.translatesAutoresizingMaskIntoConstraints = false - - self.removeConstraints(self.constraints) - self.buttonBottom.removeConstraints(self.buttonBottom.constraints) - self.container.view.removeConstraints(self.container.view.constraints) - - heightForAlertView = UIScreen.main.bounds.height*percentageRatioHeight - widthForAlertView = UIScreen.main.bounds.width*percentageRatioWidth - - //Constraints for alertview - let horizontalContraintsAlertView = NSLayoutConstraint(item: self, attribute: .centerXWithinMargins, relatedBy: .equal, toItem: superView, attribute: .centerXWithinMargins, multiplier: 1.0, constant: 0) - let verticalContraintsAlertView = NSLayoutConstraint(item: self, attribute:.centerYWithinMargins, relatedBy: .equal, toItem: superView, attribute: .centerYWithinMargins, multiplier: 1.0, constant: 0) - let heightConstraintForAlertView = NSLayoutConstraint.init(item: self, attribute: .height, relatedBy: .equal, toItem: nil, attribute: .notAnAttribute, multiplier: 1, constant: heightForAlertView) - let widthConstraintForAlertView = NSLayoutConstraint.init(item: self, attribute: .width, relatedBy: .equal, toItem: nil, attribute: .notAnAttribute, multiplier: 1, constant: widthForAlertView) - - //Constraints for button - let verticalContraintsButtonBottom = NSLayoutConstraint(item: self.buttonBottom, attribute:.centerXWithinMargins, relatedBy: .equal, toItem: self, attribute: .centerXWithinMargins, multiplier: 1.0, constant: 0) - let heightConstraintForButtonBottom = NSLayoutConstraint.init(item: self.buttonBottom, attribute: .height, relatedBy: .equal, toItem: nil, attribute: .notAnAttribute, multiplier: 1, constant: heightForAlertView*0.1) - let widthConstraintForButtonBottom = NSLayoutConstraint.init(item: self.buttonBottom, attribute: .width, relatedBy: .equal, toItem: nil, attribute: .notAnAttribute, multiplier: 1, constant: widthForAlertView) - let pinContraintsButtonBottom = NSLayoutConstraint(item: self.buttonBottom, attribute: .bottom, relatedBy: .equal, toItem: self, attribute: .bottom, multiplier: 1.0, constant: 0) - - //Constraints for container - let verticalContraintsForContainer = NSLayoutConstraint(item: self.container.view, attribute:.centerXWithinMargins, relatedBy: .equal, toItem: self, attribute: .centerXWithinMargins, multiplier: 1.0, constant: 0) - let heightConstraintForContainer = NSLayoutConstraint.init(item: self.container.view, attribute: .height, relatedBy: .equal, toItem: nil, attribute: .notAnAttribute, multiplier: 1, constant: heightForAlertView*0.9) - let widthConstraintForContainer = NSLayoutConstraint.init(item: self.container.view, attribute: .width, relatedBy: .equal, toItem: nil, attribute: .notAnAttribute, multiplier: 1, constant: widthForAlertView) - let pinContraintsForContainer = NSLayoutConstraint(item: self.container.view, attribute: .top, relatedBy: .equal, toItem: self, attribute: .top, multiplier: 1.0, constant: 0) - - - //Constraints for background - let widthContraintsForBackground = NSLayoutConstraint(item: self.background, attribute:.width, relatedBy: .equal, toItem: superView, attribute: .width, multiplier: 1, constant: 0) - let heightConstraintForBackground = NSLayoutConstraint.init(item: self.background, attribute: .height, relatedBy: .equal, toItem: superView, attribute: .height, multiplier: 1, constant: 0) - - NSLayoutConstraint.activate([horizontalContraintsAlertView, verticalContraintsAlertView,heightConstraintForAlertView, widthConstraintForAlertView, - verticalContraintsButtonBottom, heightConstraintForButtonBottom, widthConstraintForButtonBottom, pinContraintsButtonBottom, - verticalContraintsForContainer, heightConstraintForContainer, widthConstraintForContainer, pinContraintsForContainer, - widthContraintsForBackground, heightConstraintForBackground]) - } - - //MARK: FOR ANIMATIONS --------------------------------- - fileprivate func animateForOpening(){ - self.alpha = 1.0 - self.transform = CGAffineTransform(scaleX: 0.3, y: 0.3) - UIView.animate(withDuration: 1, delay: 0.0, usingSpringWithDamping: 0.5, initialSpringVelocity: 0.5, options: [], animations: { - self.transform = CGAffineTransform(scaleX: 1, y: 1) - }, completion: nil) - } - - fileprivate func animateForEnding(){ - UIView.animate(withDuration: 0.2, delay: 0.0, options: UIViewAnimationOptions.curveEaseOut, animations: { - self.alpha = 0.0 - }, completion: { - (finished: Bool) -> Void in - // On main thread - DispatchQueue.main.async { - () -> Void in - self.background.removeFromSuperview() - self.removeFromSuperview() - self.container.removeFromParentViewController() - self.container.view.removeFromSuperview() - } - }) - } - - //MARK: BUTTON ACTIONS --------------------------------- - - @objc func onClick(){ - self.hide() - } - - //MARK: ALERTPAGEVIEWDELEGATE -------------------------------------- - - func nextStep(_ step: Int) { - self.delegate?.alertOnboardingNext(step) - } - - //MARK: OTHERS -------------------------------------- - fileprivate func getTopViewController() -> UIViewController? { - var topController: UIViewController? = UIApplication.shared.keyWindow?.rootViewController - while topController?.presentedViewController != nil { - topController = topController?.presentedViewController - } - return topController - } - - //MARK: NOTIFICATIONS PROCESS ------------------------------------------ - fileprivate func interceptOrientationChange(){ - UIDevice.current.beginGeneratingDeviceOrientationNotifications() - NotificationCenter.default.addObserver(self, selector: #selector(AlertOnboarding.onOrientationChange), name: NSNotification.Name.UIDeviceOrientationDidChange, object: nil) - } - - @objc func onOrientationChange(){ - if let superview = self.superview { - self.configureConstraints(superview) - self.container.configureConstraintsForPageControl() - } - } -} diff --git a/AlertOnboarding/AlertPageViewController.swift b/AlertOnboarding/AlertPageViewController.swift deleted file mode 100644 index 06611a0..0000000 --- a/AlertOnboarding/AlertPageViewController.swift +++ /dev/null @@ -1,201 +0,0 @@ -// -// AlertPageViewController.swift -// AlertOnboarding -// -// Created by Philippe on 26/09/2016. -// Copyright © 2016 CookMinute. All rights reserved. -// - -import UIKit - -protocol AlertPageViewDelegate { - func nextStep(_ step: Int) -} - -class AlertPageViewController: UIViewController, UIPageViewControllerDataSource, UIPageViewControllerDelegate { - - //FOR DESIGN - var pageController: UIPageViewController! - var pageControl: UIPageControl! - var alertview: AlertOnboarding! - - //FOR DATA - var arrayOfImage: [String]! - var arrayOfTitle: [String]! - var arrayOfDescription: [String]! - var viewControllers = [UIViewController]() - - //FOR TRACKING USER USAGE - var currentStep = 0 - var maxStep = 0 - var isCompleted = false - var delegate: AlertPageViewDelegate? - - - init (arrayOfImage: [String], arrayOfTitle: [String], arrayOfDescription: [String], alertView: AlertOnboarding) { - super.init(nibName: nil, bundle: nil) - self.arrayOfImage = arrayOfImage - self.arrayOfTitle = arrayOfTitle - self.arrayOfDescription = arrayOfDescription - self.alertview = alertView - } - - required init(coder: NSCoder) { - fatalError("NSCoding not supported") - } - - override func viewDidLoad() { - super.viewDidLoad() - - self.configurePageViewController() - self.configurePageControl() - - self.view.backgroundColor = UIColor.clear - self.view.addSubview(self.pageController.view) - self.view.addSubview(self.pageControl) - self.pageController.didMove(toParentViewController: self) - } - - override func viewWillAppear(_ animated: Bool) { - super.viewWillAppear(animated) - } - - override func viewDidLayoutSubviews() { - super.viewDidLayoutSubviews() - } - override func didReceiveMemoryWarning() { - super.didReceiveMemoryWarning() - } - - - func pageViewController(_ pageViewController: UIPageViewController, viewControllerAfter viewController: UIViewController) -> UIViewController? { - - var index = (viewController as! AlertChildPageViewController).pageIndex! - - if(index == 0){ - return nil - } - - index -= 1 - return self.viewControllerAtIndex(index) - } - - func pageViewController(_ pageViewController: UIPageViewController, viewControllerBefore viewController: UIViewController) -> UIViewController? { - - var index = (viewController as! AlertChildPageViewController).pageIndex! - - index += 1 - - if(index == arrayOfImage.count){ - return nil - } - - return self.viewControllerAtIndex(index) - } - - - func viewControllerAtIndex(_ index : Int) -> UIViewController? { - - var pageContentViewController: AlertChildPageViewController! - let podBundle = Bundle(for: self.classForCoder) - - //FROM COCOAPOD - if let bundleURL = podBundle.url(forResource: "AlertOnboardingXib", withExtension: "bundle") { - if let bundle = Bundle(url: bundleURL) { - pageContentViewController = UINib(nibName: "AlertChildPageViewController", bundle: bundle).instantiate(withOwner: nil, options: nil)[0] as! AlertChildPageViewController - } else { - assertionFailure("Could not load the bundle.. Please re-install AlertOnboarding via Cocoapod or install it manually.") - } - //FROM MANUAL INSTALL - }else { - pageContentViewController = UINib(nibName: "AlertChildPageViewController", bundle: nil).instantiate(withOwner: nil, options: nil)[0] as! AlertChildPageViewController - } - - pageContentViewController.pageIndex = index // 0 - - let realIndex = arrayOfImage.count - index - 1 - - pageContentViewController.image.image = UIImage(named: arrayOfImage[realIndex]) - pageContentViewController.labelMainTitle.text = arrayOfTitle[realIndex] - pageContentViewController.labelMainTitle.textColor = alertview.colorTitleLabel - pageContentViewController.labelDescription.text = arrayOfDescription[realIndex] - pageContentViewController.labelDescription.textColor = alertview.colorDescriptionLabel - - return pageContentViewController - } - - func pageViewController(_ pageViewController: UIPageViewController, didFinishAnimating finished: Bool, previousViewControllers: [UIViewController], transitionCompleted completed: Bool) { - let pageContentViewController = pageViewController.viewControllers![0] as! AlertChildPageViewController - let index = pageContentViewController.pageIndex - self.currentStep = (arrayOfImage.count - index! - 1) - self.delegate?.nextStep(self.currentStep) - //Check if user watching the last step - if currentStep == arrayOfImage.count - 1 { - self.isCompleted = true - } - //Remember the last screen user have seen - if currentStep > self.maxStep { - self.maxStep = currentStep - } - if pageControl != nil { - pageControl.currentPage = arrayOfImage.count - index! - 1 - if pageControl.currentPage == arrayOfImage.count - 1 { - self.alertview.buttonBottom.setTitle(alertview.titleGotItButton, for: UIControlState()) - } else { - self.alertview.buttonBottom.setTitle(alertview.titleSkipButton, for: UIControlState()) - } - } - } - - - func presentationCount(for pageViewController: UIPageViewController) -> Int { - return arrayOfImage.count - } - - func presentationIndex(for pageViewController: UIPageViewController) -> Int { - return 0 - } - - //MARK: CONFIGURATION --------------------------------------------------------------------------------- - fileprivate func configurePageControl() { - self.pageControl = UIPageControl(frame: CGRect(x: 0,y: 0,width: 0,height: 0)) - self.pageControl.backgroundColor = UIColor.clear - self.pageControl.pageIndicatorTintColor = alertview.colorPageIndicator - self.pageControl.currentPageIndicatorTintColor = alertview.colorCurrentPageIndicator - self.pageControl.numberOfPages = arrayOfImage.count - self.pageControl.currentPage = 0 - self.pageControl.isEnabled = false - - self.configureConstraintsForPageControl() - } - - fileprivate func configurePageViewController(){ - self.pageController = UIPageViewController(transitionStyle: UIPageViewControllerTransitionStyle.scroll, navigationOrientation: UIPageViewControllerNavigationOrientation.horizontal, options: nil) - self.pageController.view.backgroundColor = UIColor.clear - - if #available(iOS 9.0, *) { - let pageControl = UIPageControl.appearance(whenContainedInInstancesOf: [AlertPageViewController.self]) - pageControl.pageIndicatorTintColor = UIColor.clear - pageControl.currentPageIndicatorTintColor = UIColor.clear - - } else { - // Fallback on earlier versions - } - - self.pageController.dataSource = self - self.pageController.delegate = self - - let initialViewController = self.viewControllerAtIndex(arrayOfImage.count-1) - self.viewControllers = [initialViewController!] - self.pageController.setViewControllers(viewControllers, direction: .forward, animated: false, completion: nil) - - self.addChildViewController(self.pageController) - } - - //MARK: Called after notification orientation changement - func configureConstraintsForPageControl() { - let alertViewSizeHeight = UIScreen.main.bounds.height*alertview.percentageRatioHeight - let positionX = alertViewSizeHeight - (alertViewSizeHeight * 0.1) - 50 - self.pageControl.frame = CGRect(x: 0, y: positionX, width: self.view.bounds.width, height: 50) - } -} diff --git a/AlertOnboarding/AppDelegate.swift b/AlertOnboarding/AppDelegate.swift index 4d7a9c2..20366b2 100644 --- a/AlertOnboarding/AppDelegate.swift +++ b/AlertOnboarding/AppDelegate.swift @@ -14,7 +14,7 @@ class AppDelegate: UIResponder, UIApplicationDelegate { var window: UIWindow? - func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool { + func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { // Override point for customization after application launch. return true } diff --git a/AlertOnboarding/ViewController.swift b/AlertOnboarding/ViewController.swift index 8420cc2..bb6333a 100644 --- a/AlertOnboarding/ViewController.swift +++ b/AlertOnboarding/ViewController.swift @@ -12,15 +12,17 @@ class ViewController: UIViewController, AlertOnboardingDelegate { var alertView: AlertOnboarding! - var arrayOfImage = ["image1", "image2", "image3"] - var arrayOfTitle = ["CREATE ACCOUNT", "CHOOSE THE PLANET", "DEPARTURE"] - var arrayOfDescription = ["In your profile, you can view the statistics of its operations and the recommandations of friends", - "Purchase tickets on hot tours to your favorite planet and fly to the most comfortable intergalactic spaceships of best companies", - "In the process of flight you will be in cryogenic sleep and supply the body with all the necessary things for life"] + var arrayOfAlerts = [Alert]() + + let alert1 = Alert(image: UIImage(named: "image1")!, title: "CREATE ACCOUNT", text: "In your profile, you can view the statistics of its operations and the recommandations of friends") + let alert2 = Alert(image: UIImage(named: "image2")!, title: "CHOOSE THE PLANET", text: "Purchase tickets on hot tours to your favorite planet and fly to the most comfortable intergalactic spaceships of best companies") + let alert3 = Alert(image: UIImage(named: "image3")!, title: "DEPARTURE", text: "In the process of flight you will be in cryogenic sleep and supply the body with all the necessary things for life bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla bla XXX") + override func viewDidLoad() { super.viewDidLoad() - alertView = AlertOnboarding(arrayOfImage: arrayOfImage, arrayOfTitle: arrayOfTitle, arrayOfDescription: arrayOfDescription) + arrayOfAlerts = [alert1, alert2, alert3] + alertView = AlertOnboarding(arrayOfAlerts: arrayOfAlerts) alertView.delegate = self } @@ -44,7 +46,7 @@ class ViewController: UIViewController, AlertOnboardingDelegate { */ - + self.alertView.imageContentMode = .scaleAspectFit self.alertView.show() } diff --git a/Pod/Assets/AlertChildPageViewController.xib b/Pod/Assets/AlertChildPageViewController.xib index a004aca..806e50f 100644 --- a/Pod/Assets/AlertChildPageViewController.xib +++ b/Pod/Assets/AlertChildPageViewController.xib @@ -1,10 +1,11 @@ - - + + + + + - - - + @@ -19,45 +20,47 @@ - - + + - - - - - - - + + + + + + + - - + + - - + + + + + - @@ -85,17 +88,19 @@ - + - + + + - + diff --git a/Pod/Classes/Alert.swift b/Pod/Classes/Alert.swift new file mode 100644 index 0000000..670ce35 --- /dev/null +++ b/Pod/Classes/Alert.swift @@ -0,0 +1,21 @@ +// +// Alert.swift +// AlertOnboarding +// +// Created by Anthony Perozzo on 26/08/18. +// Copyright © 2018 CookMinute. All rights reserved. +// + +import UIKit + +@objc public class Alert: NSObject { + public var image: UIImage + public var title: String + public var text: String + + @objc public init(image: UIImage, title: String, text: String) { + self.image = image + self.title = title + self.text = text + } +} diff --git a/Pod/Classes/AlertChildPageViewController.swift b/Pod/Classes/AlertChildPageViewController.swift index 435722e..d13c93d 100644 --- a/Pod/Classes/AlertChildPageViewController.swift +++ b/Pod/Classes/AlertChildPageViewController.swift @@ -8,19 +8,43 @@ import UIKit -class AlertChildPageViewController: UIViewController { +@objc public class AlertChildPageViewController: UIViewController { var pageIndex: Int! - @IBOutlet weak var image: UIImageView! - @IBOutlet weak var labelMainTitle: UILabel! - @IBOutlet weak var labelDescription: UILabel! + @objc @IBOutlet public private(set) weak var image: UIImageView! + @objc @IBOutlet public private(set) weak var labelMainTitle: UILabel! + @objc @IBOutlet public private(set) weak var labelDescription: UITextView! + // Default to 80% (0.8) of container view. Adjust multiplier to desired value + @objc @IBOutlet weak var imageAspectRatio: NSLayoutConstraint! + @objc @IBOutlet weak var imageContainerView: UIView! - override func viewDidLoad() { + override public func viewDidLoad() { super.viewDidLoad() } - override func didReceiveMemoryWarning() { + override public func didReceiveMemoryWarning() { super.didReceiveMemoryWarning() } + + func setImageAspectRatio(_ ratio: CGFloat) { + let newConstraint = imageAspectRatio.constraintWithMultiplier(ratio) + imageContainerView.removeConstraint(imageAspectRatio) + imageContainerView.addConstraint(newConstraint) + imageContainerView.layoutIfNeeded() + } +} + +extension NSLayoutConstraint { + + func constraintWithMultiplier(_ multiplier: CGFloat) -> NSLayoutConstraint { + return NSLayoutConstraint(item: firstItem!, + attribute: firstAttribute, + relatedBy: relation, + toItem: secondItem, + attribute: secondAttribute, + multiplier: multiplier, + constant: constant) + } + } diff --git a/Pod/Classes/AlertOnboarding.swift b/Pod/Classes/AlertOnboarding.swift index 060b91e..c672361 100644 --- a/Pod/Classes/AlertOnboarding.swift +++ b/Pod/Classes/AlertOnboarding.swift @@ -8,55 +8,62 @@ import UIKit -public protocol AlertOnboardingDelegate { +@objc public protocol AlertOnboardingDelegate { func alertOnboardingSkipped(_ currentStep: Int, maxStep: Int) func alertOnboardingCompleted() func alertOnboardingNext(_ nextStep: Int) + + @objc optional func alertOnboardingDidDisplayStep(alertOnboarding: AlertOnboarding, alertChildPageViewController: AlertChildPageViewController, step: Int) } open class AlertOnboarding: UIView, AlertPageViewDelegate { //FOR DATA ------------------------ - fileprivate var arrayOfImage = [String]() - fileprivate var arrayOfTitle = [String]() - fileprivate var arrayOfDescription = [String]() + fileprivate var arrayOfAlerts = [Alert]() //FOR DESIGN ------------------------ open var buttonBottom: UIButton! fileprivate var container: AlertPageViewController! open var background: UIView! - //PUBLIC VARS ------------------------ - open var colorForAlertViewBackground: UIColor = UIColor.white + @objc open var colorForAlertViewBackground: UIColor = UIColor.white + + @objc open var colorButtonBottomBackground: UIColor = UIColor(red: 226/255, green: 237/255, blue: 248/255, alpha: 1.0) + @objc open var colorButtonText: UIColor = UIColor(red: 118/255, green: 125/255, blue: 152/255, alpha: 1.0) + + @objc open var colorTitleLabel: UIColor = UIColor(red: 171/255, green: 177/255, blue: 196/255, alpha: 1.0) + @objc open var colorDescriptionLabel: UIColor = UIColor(red: 171/255, green: 177/255, blue: 196/255, alpha: 1.0) - open var colorButtonBottomBackground: UIColor = UIColor(red: 226/255, green: 237/255, blue: 248/255, alpha: 1.0) - open var colorButtonText: UIColor = UIColor(red: 118/255, green: 125/255, blue: 152/255, alpha: 1.0) + @objc open var fontTitleLabel: UIFont? = UIFont(name: "Avenir-Heavy", size: 17); + @objc open var fontDescriptionLabel: UIFont? = UIFont(name: "Avenir-Book", size: 13); + @objc open var fontButtonText: UIFont? = UIFont(name: "Avenir-Black", size: 15); - open var colorTitleLabel: UIColor = UIColor(red: 171/255, green: 177/255, blue: 196/255, alpha: 1.0) - open var colorDescriptionLabel: UIColor = UIColor(red: 171/255, green: 177/255, blue: 196/255, alpha: 1.0) + @objc open var colorPageIndicator = UIColor(red: 171/255, green: 177/255, blue: 196/255, alpha: 1.0) + @objc open var colorCurrentPageIndicator = UIColor(red: 118/255, green: 125/255, blue: 152/255, alpha: 1.0) - open var colorPageIndicator = UIColor(red: 171/255, green: 177/255, blue: 196/255, alpha: 1.0) - open var colorCurrentPageIndicator = UIColor(red: 118/255, green: 125/255, blue: 152/255, alpha: 1.0) + @objc open var imageContentMode: UIView.ContentMode = .scaleToFill + /// Defines proportion between imageView and its containerView. Default is 80% (0.8) + open var imageAspectRatio: CGFloat? open var heightForAlertView: CGFloat! open var widthForAlertView: CGFloat! - open var percentageRatioHeight: CGFloat = 0.8 - open var percentageRatioWidth: CGFloat = 0.8 + @objc open var percentageRatioHeight: CGFloat = 0.8 + @objc open var percentageRatioWidth: CGFloat = 0.8 - open var titleSkipButton = "SKIP" - open var titleGotItButton = "GOT IT !" + @objc open var nextInsteadOfSkip = false - open var delegate: AlertOnboardingDelegate? + @objc open var titleNextButton = "NEXT" + @objc open var titleSkipButton = "SKIP" + @objc open var titleGotItButton = "GOT IT !" + @objc open var delegate: AlertOnboardingDelegate? - public init (arrayOfImage: [String], arrayOfTitle: [String], arrayOfDescription: [String]) { + @objc public init (arrayOfAlerts: [Alert]) { super.init(frame: CGRect(x: 0,y: 0,width: 0,height: 0)) - self.configure(arrayOfImage, arrayOfTitle: arrayOfTitle, arrayOfDescription: arrayOfDescription) - self.arrayOfImage = arrayOfImage - self.arrayOfTitle = arrayOfTitle - self.arrayOfDescription = arrayOfDescription + self.configure() + self.arrayOfAlerts = arrayOfAlerts self.interceptOrientationChange() } @@ -77,15 +84,15 @@ open class AlertOnboarding: UIView, AlertPageViewDelegate { // MARK: PUBLIC FUNCTIONS -------------------------------------------------------------- //----------------------------------------------------------------------------------------- - open func show() { + @objc open func show() { //Update Color self.buttonBottom.backgroundColor = colorButtonBottomBackground self.backgroundColor = colorForAlertViewBackground - self.buttonBottom.setTitleColor(colorButtonText, for: UIControlState()) - self.buttonBottom.setTitle(self.titleSkipButton, for: UIControlState()) + self.buttonBottom.setTitleColor(colorButtonText, for: UIControl.State()) + self.buttonBottom.setTitle(self.titleSkipButton, for: UIControl.State()) - self.container = AlertPageViewController(arrayOfImage: arrayOfImage, arrayOfTitle: arrayOfTitle, arrayOfDescription: arrayOfDescription, alertView: self) + self.container = AlertPageViewController(arrayOfAlerts: arrayOfAlerts, alertView: self) self.container.delegate = self self.insertSubview(self.container.view, aboveSubview: self) self.insertSubview(self.buttonBottom, aboveSubview: self) @@ -106,7 +113,7 @@ open class AlertOnboarding: UIView, AlertPageViewDelegate { } //Hide onboarding with animation - open func hide(){ + @objc open func hide(){ self.checkIfOnboardingWasSkipped() DispatchQueue.main.async { () -> Void in self.animateForEnding() @@ -121,7 +128,7 @@ open class AlertOnboarding: UIView, AlertPageViewDelegate { //MARK: Check if onboarding was skipped fileprivate func checkIfOnboardingWasSkipped(){ let currentStep = self.container.currentStep - if currentStep < (self.container.arrayOfImage.count - 1) && !self.container.isCompleted{ + if currentStep < (self.container.arrayOfAlerts.count - 1) && !self.container.isCompleted { self.delegate?.alertOnboardingSkipped(currentStep, maxStep: self.container.maxStep) } else { @@ -131,63 +138,40 @@ open class AlertOnboarding: UIView, AlertPageViewDelegate { //MARK: FOR CONFIGURATION -------------------------------------- - fileprivate func configure(_ arrayOfImage: [String], arrayOfTitle: [String], arrayOfDescription: [String]) { - + fileprivate func configure() { self.buttonBottom = UIButton(frame: CGRect(x: 0,y: 0, width: 0, height: 0)) - self.buttonBottom.titleLabel?.font = UIFont(name: "Avenir-Black", size: 15) + self.buttonBottom.titleLabel?.font = fontButtonText self.buttonBottom.addTarget(self, action: #selector(AlertOnboarding.onClick), for: .touchUpInside) self.background = UIView(frame: CGRect(x: 0,y: 0, width: 0, height: 0)) self.background.backgroundColor = UIColor.black self.background.alpha = 0.5 - self.clipsToBounds = true self.layer.cornerRadius = 10 } fileprivate func configureConstraints(_ superView: UIView) { + removeConstraints(constraints) + buttonBottom.removeConstraints(buttonBottom.constraints) + container.view.removeConstraints(container.view.constraints) - self.translatesAutoresizingMaskIntoConstraints = false - self.buttonBottom.translatesAutoresizingMaskIntoConstraints = false - self.container.view.translatesAutoresizingMaskIntoConstraints = false - self.background.translatesAutoresizingMaskIntoConstraints = false - - self.removeConstraints(self.constraints) - self.buttonBottom.removeConstraints(self.buttonBottom.constraints) - self.container.view.removeConstraints(self.container.view.constraints) + equal(width: superView.widthAnchor, widthMultiplier: percentageRatioWidth, + height: superView.heightAnchor, heightMultiplier: percentageRatioHeight) + anchorCenterSuperview() - heightForAlertView = UIScreen.main.bounds.height*percentageRatioHeight - widthForAlertView = UIScreen.main.bounds.width*percentageRatioWidth - - //Constraints for alertview - let horizontalContraintsAlertView = NSLayoutConstraint(item: self, attribute: .centerXWithinMargins, relatedBy: .equal, toItem: superView, attribute: .centerXWithinMargins, multiplier: 1.0, constant: 0) - let verticalContraintsAlertView = NSLayoutConstraint(item: self, attribute:.centerYWithinMargins, relatedBy: .equal, toItem: superView, attribute: .centerYWithinMargins, multiplier: 1.0, constant: 0) - let heightConstraintForAlertView = NSLayoutConstraint.init(item: self, attribute: .height, relatedBy: .equal, toItem: nil, attribute: .notAnAttribute, multiplier: 1, constant: heightForAlertView) - let widthConstraintForAlertView = NSLayoutConstraint.init(item: self, attribute: .width, relatedBy: .equal, toItem: nil, attribute: .notAnAttribute, multiplier: 1, constant: widthForAlertView) - - //Constraints for button - let verticalContraintsButtonBottom = NSLayoutConstraint(item: self.buttonBottom, attribute:.centerXWithinMargins, relatedBy: .equal, toItem: self, attribute: .centerXWithinMargins, multiplier: 1.0, constant: 0) - let heightConstraintForButtonBottom = NSLayoutConstraint.init(item: self.buttonBottom, attribute: .height, relatedBy: .equal, toItem: nil, attribute: .notAnAttribute, multiplier: 1, constant: heightForAlertView*0.1) - let widthConstraintForButtonBottom = NSLayoutConstraint.init(item: self.buttonBottom, attribute: .width, relatedBy: .equal, toItem: nil, attribute: .notAnAttribute, multiplier: 1, constant: widthForAlertView) - let pinContraintsButtonBottom = NSLayoutConstraint(item: self.buttonBottom, attribute: .bottom, relatedBy: .equal, toItem: self, attribute: .bottom, multiplier: 1.0, constant: 0) + buttonBottom.equal(width: widthAnchor, height: heightAnchor, heightMultiplier: 0.1) + buttonBottom.anchor(bottom: bottomAnchor) + buttonBottom.anchorCenterXToSuperview() //Constraints for container - let verticalContraintsForContainer = NSLayoutConstraint(item: self.container.view, attribute:.centerXWithinMargins, relatedBy: .equal, toItem: self, attribute: .centerXWithinMargins, multiplier: 1.0, constant: 0) - let heightConstraintForContainer = NSLayoutConstraint.init(item: self.container.view, attribute: .height, relatedBy: .equal, toItem: nil, attribute: .notAnAttribute, multiplier: 1, constant: heightForAlertView*0.9) - let widthConstraintForContainer = NSLayoutConstraint.init(item: self.container.view, attribute: .width, relatedBy: .equal, toItem: nil, attribute: .notAnAttribute, multiplier: 1, constant: widthForAlertView) - let pinContraintsForContainer = NSLayoutConstraint(item: self.container.view, attribute: .top, relatedBy: .equal, toItem: self, attribute: .top, multiplier: 1.0, constant: 0) - + container.view.equal(width: widthAnchor, height: heightAnchor, heightMultiplier: 0.9) + container.view.anchor(top: topAnchor) + container.view.anchorCenterXToSuperview() //Constraints for background - let widthContraintsForBackground = NSLayoutConstraint(item: self.background, attribute:.width, relatedBy: .equal, toItem: superView, attribute: .width, multiplier: 1, constant: 0) - let heightConstraintForBackground = NSLayoutConstraint.init(item: self.background, attribute: .height, relatedBy: .equal, toItem: superView, attribute: .height, multiplier: 1, constant: 0) - - NSLayoutConstraint.activate([horizontalContraintsAlertView, verticalContraintsAlertView,heightConstraintForAlertView, widthConstraintForAlertView, - verticalContraintsButtonBottom, heightConstraintForButtonBottom, widthConstraintForButtonBottom, pinContraintsButtonBottom, - verticalContraintsForContainer, heightConstraintForContainer, widthConstraintForContainer, pinContraintsForContainer, - widthContraintsForBackground, heightConstraintForBackground]) + background.fillSuperview() } //MARK: FOR ANIMATIONS --------------------------------- @@ -200,7 +184,7 @@ open class AlertOnboarding: UIView, AlertPageViewDelegate { } fileprivate func animateForEnding(){ - UIView.animate(withDuration: 0.2, delay: 0.0, options: UIViewAnimationOptions.curveEaseOut, animations: { + UIView.animate(withDuration: 0.2, delay: 0.0, options: UIView.AnimationOptions.curveEaseOut, animations: { self.alpha = 0.0 }, completion: { (finished: Bool) -> Void in @@ -209,7 +193,7 @@ open class AlertOnboarding: UIView, AlertPageViewDelegate { () -> Void in self.background.removeFromSuperview() self.removeFromSuperview() - self.container.removeFromParentViewController() + self.container.removeFromParent() self.container.view.removeFromSuperview() } }) @@ -218,6 +202,16 @@ open class AlertOnboarding: UIView, AlertPageViewDelegate { //MARK: BUTTON ACTIONS --------------------------------- @objc func onClick(){ + if (nextInsteadOfSkip) { + if let viewController = self.container.viewControllerAtIndex((self.container.pageController.viewControllers?[0] as! AlertChildPageViewController).pageIndex!-1) + { + self.container.pageController.setViewControllers([viewController], direction: UIPageViewController.NavigationDirection.forward, animated: true, completion: nil) + self.container.didMoveToPageIndex(pageIndex: (viewController as! AlertChildPageViewController).pageIndex) + + return; + } + } + self.hide() } @@ -239,7 +233,7 @@ open class AlertOnboarding: UIView, AlertPageViewDelegate { //MARK: NOTIFICATIONS PROCESS ------------------------------------------ fileprivate func interceptOrientationChange(){ UIDevice.current.beginGeneratingDeviceOrientationNotifications() - NotificationCenter.default.addObserver(self, selector: #selector(AlertOnboarding.onOrientationChange), name: NSNotification.Name.UIDeviceOrientationDidChange, object: nil) + NotificationCenter.default.addObserver(self, selector: #selector(AlertOnboarding.onOrientationChange), name: UIDevice.orientationDidChangeNotification, object: nil) } @objc func onOrientationChange(){ @@ -249,3 +243,85 @@ open class AlertOnboarding: UIView, AlertPageViewDelegate { } } } + +extension UIView { + + func fillSuperview() { + translatesAutoresizingMaskIntoConstraints = false + if let superview = superview { + leftAnchor.constraint(equalTo: superview.leftAnchor).isActive = true + rightAnchor.constraint(equalTo: superview.rightAnchor).isActive = true + topAnchor.constraint(equalTo: superview.topAnchor).isActive = true + bottomAnchor.constraint(equalTo: superview.bottomAnchor).isActive = true + } + } + + func anchorCenterXToSuperview(constant: CGFloat = 0) { + translatesAutoresizingMaskIntoConstraints = false + if let anchor = superview?.centerXAnchor { + centerXAnchor.constraint(equalTo: anchor, constant: constant).isActive = true + } + } + + func anchorCenterYToSuperview(constant: CGFloat = 0) { + translatesAutoresizingMaskIntoConstraints = false + if let anchor = superview?.centerYAnchor { + centerYAnchor.constraint(equalTo: anchor, constant: constant).isActive = true + } + } + + func anchorCenterSuperview() { + anchorCenterXToSuperview() + anchorCenterYToSuperview() + } + + func anchor(top: NSLayoutYAxisAnchor? = nil, left: NSLayoutXAxisAnchor? = nil, bottom: NSLayoutYAxisAnchor? = nil, right: NSLayoutXAxisAnchor? = nil, topConstant: CGFloat = 0, leftConstant: CGFloat = 0, bottomConstant: CGFloat = 0, rightConstant: CGFloat = 0, widthConstant: CGFloat = 0, heightConstant: CGFloat = 0) { + translatesAutoresizingMaskIntoConstraints = false + + _ = anchorWithReturnAnchors(top, left: left, bottom: bottom, right: right, topConstant: topConstant, leftConstant: leftConstant, bottomConstant: bottomConstant, rightConstant: rightConstant, widthConstant: widthConstant, heightConstant: heightConstant) + } + + func anchorWithReturnAnchors(_ top: NSLayoutYAxisAnchor? = nil, left: NSLayoutXAxisAnchor? = nil, bottom: NSLayoutYAxisAnchor? = nil, right: NSLayoutXAxisAnchor? = nil, topConstant: CGFloat = 0, leftConstant: CGFloat = 0, bottomConstant: CGFloat = 0, rightConstant: CGFloat = 0, widthConstant: CGFloat = 0, heightConstant: CGFloat = 0) -> [NSLayoutConstraint] { + translatesAutoresizingMaskIntoConstraints = false + + var anchors = [NSLayoutConstraint]() + + if let top = top { + anchors.append(topAnchor.constraint(equalTo: top, constant: topConstant)) + } + + if let left = left { + anchors.append(leftAnchor.constraint(equalTo: left, constant: leftConstant)) + } + + if let bottom = bottom { + anchors.append(bottomAnchor.constraint(equalTo: bottom, constant: -bottomConstant)) + } + + if let right = right { + anchors.append(rightAnchor.constraint(equalTo: right, constant: -rightConstant)) + } + + if widthConstant > 0 { + anchors.append(widthAnchor.constraint(equalToConstant: widthConstant)) + } + + if heightConstant > 0 { + anchors.append(heightAnchor.constraint(equalToConstant: heightConstant)) + } + + anchors.forEach({$0.isActive = true}) + + return anchors + } + + func equal(width: NSLayoutDimension? = nil, widthMultiplier: CGFloat? = 1.0, height: NSLayoutDimension? = nil, heightMultiplier: CGFloat? = 1.0) { + translatesAutoresizingMaskIntoConstraints = false + if let width = width { + widthAnchor.constraint(equalTo: width, multiplier: widthMultiplier!).isActive = true + } + if let height = height { + heightAnchor.constraint(equalTo: height, multiplier: heightMultiplier!).isActive = true + } + } +} diff --git a/Pod/Classes/AlertPageViewController.swift b/Pod/Classes/AlertPageViewController.swift index 06611a0..e6973a4 100644 --- a/Pod/Classes/AlertPageViewController.swift +++ b/Pod/Classes/AlertPageViewController.swift @@ -20,9 +20,7 @@ class AlertPageViewController: UIViewController, UIPageViewControllerDataSource, var alertview: AlertOnboarding! //FOR DATA - var arrayOfImage: [String]! - var arrayOfTitle: [String]! - var arrayOfDescription: [String]! + var arrayOfAlerts: [Alert]! var viewControllers = [UIViewController]() //FOR TRACKING USER USAGE @@ -32,11 +30,9 @@ class AlertPageViewController: UIViewController, UIPageViewControllerDataSource, var delegate: AlertPageViewDelegate? - init (arrayOfImage: [String], arrayOfTitle: [String], arrayOfDescription: [String], alertView: AlertOnboarding) { + init (arrayOfAlerts: [Alert], alertView: AlertOnboarding) { super.init(nibName: nil, bundle: nil) - self.arrayOfImage = arrayOfImage - self.arrayOfTitle = arrayOfTitle - self.arrayOfDescription = arrayOfDescription + self.arrayOfAlerts = arrayOfAlerts self.alertview = alertView } @@ -47,13 +43,17 @@ class AlertPageViewController: UIViewController, UIPageViewControllerDataSource, override func viewDidLoad() { super.viewDidLoad() + if (alertview.nextInsteadOfSkip) { + self.alertview.buttonBottom.setTitle(alertview.titleNextButton, for: UIControl.State()) + } + self.configurePageViewController() self.configurePageControl() self.view.backgroundColor = UIColor.clear self.view.addSubview(self.pageController.view) self.view.addSubview(self.pageControl) - self.pageController.didMove(toParentViewController: self) + self.pageController.didMove(toParent: self) } override func viewWillAppear(_ animated: Bool) { @@ -85,8 +85,7 @@ class AlertPageViewController: UIViewController, UIPageViewControllerDataSource, var index = (viewController as! AlertChildPageViewController).pageIndex! index += 1 - - if(index == arrayOfImage.count){ + if (index == arrayOfAlerts.count) { return nil } @@ -95,6 +94,9 @@ class AlertPageViewController: UIViewController, UIPageViewControllerDataSource, func viewControllerAtIndex(_ index : Int) -> UIViewController? { + if (index<0 || index>=arrayOfAlerts.count) { + return nil; + } var pageContentViewController: AlertChildPageViewController! let podBundle = Bundle(for: self.classForCoder) @@ -102,35 +104,44 @@ class AlertPageViewController: UIViewController, UIPageViewControllerDataSource, //FROM COCOAPOD if let bundleURL = podBundle.url(forResource: "AlertOnboardingXib", withExtension: "bundle") { if let bundle = Bundle(url: bundleURL) { - pageContentViewController = UINib(nibName: "AlertChildPageViewController", bundle: bundle).instantiate(withOwner: nil, options: nil)[0] as! AlertChildPageViewController + pageContentViewController = UINib(nibName: "AlertChildPageViewController", bundle: bundle).instantiate(withOwner: nil, options: nil)[0] as? AlertChildPageViewController } else { assertionFailure("Could not load the bundle.. Please re-install AlertOnboarding via Cocoapod or install it manually.") } //FROM MANUAL INSTALL }else { - pageContentViewController = UINib(nibName: "AlertChildPageViewController", bundle: nil).instantiate(withOwner: nil, options: nil)[0] as! AlertChildPageViewController + pageContentViewController = UINib(nibName: "AlertChildPageViewController", bundle: nil).instantiate(withOwner: nil, options: nil)[0] as? AlertChildPageViewController } pageContentViewController.pageIndex = index // 0 - let realIndex = arrayOfImage.count - index - 1 + let realIndex = arrayOfAlerts.count - index - 1 - pageContentViewController.image.image = UIImage(named: arrayOfImage[realIndex]) - pageContentViewController.labelMainTitle.text = arrayOfTitle[realIndex] + pageContentViewController.image.image = arrayOfAlerts[realIndex].image + pageContentViewController.image.contentMode = alertview.imageContentMode + if let imageAspectRatio = alertview.imageAspectRatio { + pageContentViewController.setImageAspectRatio(imageAspectRatio) + } + pageContentViewController.image.layer.minificationFilter = CALayerContentsFilter.trilinear + pageContentViewController.labelMainTitle.font = alertview.fontTitleLabel + pageContentViewController.labelMainTitle.text = arrayOfAlerts[realIndex].title pageContentViewController.labelMainTitle.textColor = alertview.colorTitleLabel - pageContentViewController.labelDescription.text = arrayOfDescription[realIndex] + pageContentViewController.labelDescription.font = alertview.fontDescriptionLabel + pageContentViewController.labelDescription.text = arrayOfAlerts[realIndex].text pageContentViewController.labelDescription.textColor = alertview.colorDescriptionLabel return pageContentViewController } func pageViewController(_ pageViewController: UIPageViewController, didFinishAnimating finished: Bool, previousViewControllers: [UIViewController], transitionCompleted completed: Bool) { - let pageContentViewController = pageViewController.viewControllers![0] as! AlertChildPageViewController - let index = pageContentViewController.pageIndex - self.currentStep = (arrayOfImage.count - index! - 1) + didMoveToPageIndex(pageIndex: (pageViewController.viewControllers![0] as! AlertChildPageViewController).pageIndex) + } + + func didMoveToPageIndex(pageIndex: Int) { + self.currentStep = (arrayOfAlerts.count - pageIndex - 1) self.delegate?.nextStep(self.currentStep) //Check if user watching the last step - if currentStep == arrayOfImage.count - 1 { + if currentStep == arrayOfAlerts.count - 1 { self.isCompleted = true } //Remember the last screen user have seen @@ -138,18 +149,26 @@ class AlertPageViewController: UIViewController, UIPageViewControllerDataSource, self.maxStep = currentStep } if pageControl != nil { - pageControl.currentPage = arrayOfImage.count - index! - 1 - if pageControl.currentPage == arrayOfImage.count - 1 { - self.alertview.buttonBottom.setTitle(alertview.titleGotItButton, for: UIControlState()) + pageControl.currentPage = arrayOfAlerts.count - pageIndex - 1 + if pageControl.currentPage == arrayOfAlerts.count - 1 { + self.alertview.buttonBottom.setTitle(alertview.titleGotItButton, for: UIControl.State()) + } else if (alertview.nextInsteadOfSkip) { + self.alertview.buttonBottom.setTitle(alertview.titleNextButton, for: UIControl.State()) } else { - self.alertview.buttonBottom.setTitle(alertview.titleSkipButton, for: UIControlState()) + self.alertview.buttonBottom.setTitle(alertview.titleSkipButton, for: UIControl.State()) } } + + if self.alertview.delegate?.alertOnboardingDidDisplayStep != nil { + (self.alertview.delegate?.alertOnboardingDidDisplayStep)!(self.alertview, (self.pageController.viewControllers?.first)! as! AlertChildPageViewController, self.currentStep) + + } + } func presentationCount(for pageViewController: UIPageViewController) -> Int { - return arrayOfImage.count + return arrayOfAlerts.count } func presentationIndex(for pageViewController: UIPageViewController) -> Int { @@ -162,7 +181,7 @@ class AlertPageViewController: UIViewController, UIPageViewControllerDataSource, self.pageControl.backgroundColor = UIColor.clear self.pageControl.pageIndicatorTintColor = alertview.colorPageIndicator self.pageControl.currentPageIndicatorTintColor = alertview.colorCurrentPageIndicator - self.pageControl.numberOfPages = arrayOfImage.count + self.pageControl.numberOfPages = arrayOfAlerts.count self.pageControl.currentPage = 0 self.pageControl.isEnabled = false @@ -170,7 +189,7 @@ class AlertPageViewController: UIViewController, UIPageViewControllerDataSource, } fileprivate func configurePageViewController(){ - self.pageController = UIPageViewController(transitionStyle: UIPageViewControllerTransitionStyle.scroll, navigationOrientation: UIPageViewControllerNavigationOrientation.horizontal, options: nil) + self.pageController = UIPageViewController(transitionStyle: UIPageViewController.TransitionStyle.scroll, navigationOrientation: UIPageViewController.NavigationOrientation.horizontal, options: nil) self.pageController.view.backgroundColor = UIColor.clear if #available(iOS 9.0, *) { @@ -185,11 +204,13 @@ class AlertPageViewController: UIViewController, UIPageViewControllerDataSource, self.pageController.dataSource = self self.pageController.delegate = self - let initialViewController = self.viewControllerAtIndex(arrayOfImage.count-1) + let initialViewController = self.viewControllerAtIndex(arrayOfAlerts.count-1) self.viewControllers = [initialViewController!] self.pageController.setViewControllers(viewControllers, direction: .forward, animated: false, completion: nil) - self.addChildViewController(self.pageController) + didMoveToPageIndex(pageIndex: arrayOfAlerts.count-1) + + self.addChild(self.pageController) } //MARK: Called after notification orientation changement diff --git a/README.md b/README.md index 80952e5..bd8efa4 100755 --- a/README.md +++ b/README.md @@ -106,6 +106,7 @@ func alertOnboardingNext(nextStep: Int) { - [x] Tracking Events ## Version +2.0 ## Author Philippe BOISNEY (phil.boisney(@)gmail.com)