Commit 365c3cda by Demid Merzlyakov

InApp Purchase flow.

parent da0f8907
......@@ -15,7 +15,7 @@ protocol OLInAppStoreManagerUIDelegate: class {
func viewControllerForPresentation() -> UIViewController
}
protocol OLInAppStoreManagerDelegate: NSObjectProtocol {
protocol OLInAppStoreManagerDelegate: class {
func inAppStoreManager(_ inAppStoreManager: OLInAppStoreManager, purchaseCompletedForProductId productId: String)
func inAppStoreManager(_ inAppStoreManager: OLInAppStoreManager, purchaseWillBeAdded payment: SKPayment)
......@@ -38,31 +38,39 @@ class OLInAppStoreManager: NSObject {
private override init() {
super.init()
}
var currentRequest: SKProductsRequest?
// MARK: - public methods
func attemptPurchase(forProductId productId: String) {
log.info("purchase: attempt")
if SKPaymentQueue.canMakePayments() {
productIds.append(productId)
let request = SKProductsRequest(productIdentifiers: Set<String>([productId]))
request.delegate = self
request.start()
currentRequest = SKProductsRequest(productIdentifiers: Set<String>([productId]))
currentRequest?.delegate = self
log.debug("purchase: start request")
currentRequest?.start()
} else {
log.error("purchase: prohibited")
showAlert("inapp.alert.prohibited.title".localized(), message: "inapp.error.parental.control.cant.make.purchase".localized())
}
}
func attemptRestore(forProductId productId: String) {
log.info("restore: attempt")
if SKPaymentQueue.canMakePayments() {
SKPaymentQueue.default().add(self)
log.info("restore: restoring...")
SKPaymentQueue.default().restoreCompletedTransactions()
} else {
log.error("restore: prohibited")
showAlert("inapp.alert.prohibited.title".localized(), message: "inapp.error.parental.control.cant.store".localized())
}
}
public func showAlert(_ title: String?, message: String?) -> Void {
let alert = UIAlertController(title: title, message: message, preferredStyle: .alert)
alert.addAction(UIAlertAction(title: "inapp.alert.ok".localized(), style: .default, handler: nil))
alert.addAction(UIAlertAction(title: "general.ok".localized(), style: .default, handler: nil))
self.uiDelegate?.viewControllerForPresentation().present(alert, animated: true, completion: nil)
}
......
......@@ -11,6 +11,9 @@
"general.more" = "more";
"general.search" = "search";
"general.add" = "add";
"general.ok" = "Ok";
"general.cancel" = "Cancel";
"general.continue" = "Continue";
//Alert
"today.alert.infoTemplate.oneAlert" = "#ALERT_DESCRIPTION";
......@@ -169,7 +172,7 @@
//Menu
"menu.goPremium" = "Go premium";
"menu.premium.desc" = "Experience app without ads @ $8.99 a year";
"menu.premium.desc" = "Experience app without ads";
"menu.tv" = "1Weather TV";
"menu.radar" = "Radar";
"menu.buyNow" = "Buy now";
......@@ -212,4 +215,5 @@
"inapp.alert.product.not.available.title" = "Product Not Available";
"inapp.alert.product.not.available.text" = "Please contact support.";
"inapp.restoration.error.no.purchases" = "There are no purchases to restore";
"inapp.alert.ok" = "Ok";
"inapp.upgrade.to.pro.title" = "1Weather Pro";
"inapp.upgrade.to.pro.text" = "The same great experience without the ads for only $1.99!";
......@@ -39,8 +39,7 @@ class MenuBuyButton: UIControl {
}
override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
super.touchesBegan(touches, with: event)
super.touchesEnded(touches, with: event)
UIView.performWithoutAnimation {
self.alpha = 1
}
......
......@@ -18,6 +18,8 @@ class MenuHeaderView: UIView {
private let tvButton = MenuHeaderButton(image: UIImage(named: "menu_tv"), text: "menu.tv".localized())
private let radarButton = MenuHeaderButton(image: UIImage(named: "menu_radar"), text: "menu.radar".localized())
public var onTapBuy: (() -> ())?
init() {
super.init(frame: .zero)
......@@ -58,7 +60,7 @@ class MenuHeaderView: UIView {
}
@objc private func handleBuyButton() {
onTapBuy?()
}
@objc private func handleButton(button:MenuHeaderButton) {
......
......@@ -20,6 +20,7 @@ class MenuViewController: UIViewController {
self.viewModel = menuViewModel
self.menuCellFactory = MenuCellFactory(viewModel: menuViewModel)
super.init(nibName: nil, bundle: nil)
self.viewModel.delegate = self
}
required init?(coder: NSCoder) {
......@@ -30,6 +31,7 @@ class MenuViewController: UIViewController {
super.viewDidLoad()
prepareController()
prepareTableViewHeader()
prepareTableView()
updateUI()
}
......@@ -49,6 +51,10 @@ class MenuViewController: UIViewController {
view.backgroundColor = ThemeManager.currentTheme.baseBackgroundColor
tableView.backgroundColor = ThemeManager.currentTheme.baseBackgroundColor
}
private func upgradeToPro() {
viewModel.updateToPro()
}
}
//MARK:- Prepare
......@@ -57,6 +63,14 @@ private extension MenuViewController {
navigationController?.setNavigationBarHidden(true, animated: false)
}
func prepareTableViewHeader() {
menuHeaderView.onTapBuy = { [weak self] in
#warning("Not implemented!")
//TODO: Implement!
self?.viewModel.updateToPro()
}
}
func prepareTableView() {
menuCellFactory.registerCells(on: tableView)
tableView.showsVerticalScrollIndicator = false
......@@ -118,3 +132,13 @@ extension MenuViewController: UITableViewDelegate {
}
}
}
extension MenuViewController: MenuViewModelDelegate {
func viewModelDidChange<P: ViewModelProtocol>(model:P) {
tableView.reloadData()
}
func viewControllerForPresentation() -> UIViewController {
return self
}
}
......@@ -6,7 +6,141 @@
//
import UIKit
import StoreKit
import PKHUD
protocol MenuViewModelDelegate: ViewModelDelegate {
func viewControllerForPresentation() -> UIViewController
}
class MenuViewModel: ViewModelProtocol {
private var proVersionPurchaseInProgress = false
private let log = Logger(componentName: "MenuViewModel")
private var upgradeAlert: UIAlertController?
public weak var delegate: MenuViewModelDelegate?
public func showAlert(_ title: String?, message: String?) -> Void {
let alert = UIAlertController(title: title, message: message, preferredStyle: .alert)
alert.addAction(UIAlertAction(title: "general.ok".localized(), style: .default, handler: nil))
self.delegate?.viewControllerForPresentation().present(alert, animated: true, completion: nil)
}
public func updateToPro() {
upgradeAlert = UIAlertController(title: "inapp.upgrade.to.pro.title".localized(), message: "inapp.upgrade.to.pro.text".localized(), preferredStyle: .alert)
if let alertView = upgradeAlert {
alertView.addAction(UIAlertAction(title: "general.cancel".localized(), style: .cancel, handler: { [weak self] (alertAction) -> Void in
self?.log.debug("inapp: cancel")
}))
alertView.addAction(UIAlertAction(title: "general.continue".localized(), style: .default, handler: { [weak self] (alertAction) -> Void in
guard let self = self else { return }
#if DEBUG_NO
self.log.debug("inapp: upgrade to Pro automatically")
self.updateToProCompleted()
#else
// buy
self.log.debug("inapp: buy")
OLInAppStoreManager.shared.delegate = self
OLInAppStoreManager.shared.uiDelegate = self
OLInAppStoreManager.shared.attemptPurchase(forProductId: kInAppOneWeatherProId)
#endif
}))
alertView.addAction(UIAlertAction(title: "Already Purchased".localized, style: .default, handler: { [weak self] (alertAction) -> Void in
// already purchased
self?.log.debug("inapp: already purchased")
OLInAppStoreManager.shared.delegate = self
OLInAppStoreManager.shared.attemptRestore(forProductId: kInAppOneWeatherProId)
}))
self.delegate?.viewControllerForPresentation().present(alertView, animated: true, completion: nil)
proVersionPurchaseInProgress = true
}
}
private let kOLAppMetricsCountKey: String = "count"
private let kOLAppMetricsDateKey: String = "date"
private func logEventToUserDefaults(forKey eventKey: String) {
let userDefaults = UserDefaults.standard
var updatedCount: Int = 1
var metricsLog = userDefaults.dictionary(forKey: kOLAppMetricsKey) ?? [String : Any]()
if let countEvent = metricsLog[eventKey] as? [String : Any], let count = countEvent[kOLAppMetricsCountKey] as? Int {
updatedCount = count + 1
}
let updateEvent = [kOLAppMetricsCountKey: updatedCount, kOLAppMetricsDateKey: Date()] as [String : Any]
metricsLog[eventKey] = updateEvent
userDefaults.set(metricsLog, forKey: kOLAppMetricsKey)
}
private func updateToProCompleted() {
logEventToUserDefaults(forKey: kEventInAppPurchasedCompleted)
NotificationCenter.default.post(name: Notification.Name(rawValue: kEventInAppPurchasedCompleted), object: nil)
analytics(log: .ANALYTICS_GO_PRO)
delegate?.viewModelDidChange(model: self)
}
}
extension MenuViewModel: OLInAppStoreManagerDelegate {
func inAppStoreManager(_ inAppStoreManager: OLInAppStoreManager, purchaseCompletedForProductId productId: String) {
onMain {
PKHUD.sharedHUD.hide(animated: true)
self.showAlert("Purchase Complete. Thank You!".localized, message: nil)
self.updateToProCompleted()
self.proVersionPurchaseInProgress = false
}
}
func inAppStoreManager(_ inAppStoreManager: OLInAppStoreManager, purchaseFailedFor transaction: SKPaymentTransaction) {
onMain {
PKHUD.sharedHUD.hide(animated: true)
self.showAlert("Purchase Failed with error: \(transaction.error?.localizedDescription ?? "Unknown error")".localized, message:nil)
self.proVersionPurchaseInProgress = false
}
}
func inAppStoreManager(_ inAppStoreManager: OLInAppStoreManager, purchaseWillBeAdded payment: SKPayment) {
onMain {
PKHUD.sharedHUD.contentView = PKHUDProgressView()
PKHUD.sharedHUD.show()
self.proVersionPurchaseInProgress = false
}
}
func inAppStoreManager(_ inAppStoreManager: OLInAppStoreManager, restoredCompletedForProductId productId: String) {
onMain {
PKHUD.sharedHUD.hide(animated: true)
self.showAlert("Purchase Restored. Thank You!".localized, message:nil)
self.updateToProCompleted()
self.proVersionPurchaseInProgress = false
}
}
func inAppStoreManager(_ inAppStoreManager: OLInAppStoreManager, restoreFailedWithError error: Error) {
onMain {
PKHUD.sharedHUD.hide(animated: true)
self.showAlert("Restored Failed with error: \(error.localizedDescription)".localized, message:nil)
self.proVersionPurchaseInProgress = false
}
}
func inAppStoreManager(_ inAppStoreManager: OLInAppStoreManager, restoreFailedWithMessage message: String) {
onMain {
PKHUD.sharedHUD.hide(animated: true)
self.showAlert(nil, message:message)
self.proVersionPurchaseInProgress = false
}
}
}
extension MenuViewModel: OLInAppStoreManagerUIDelegate {
func viewControllerForPresentation() -> UIViewController {
guard let delegate = delegate else {
assertionFailure("Delegate not set!")
return UIViewController()
}
return delegate.viewControllerForPresentation()
}
}
......@@ -15,6 +15,7 @@ class NWSAlertViewModel: ViewModelProtocol {
deinit {
alertsManager.delegates.remove(delegate: self)
NotificationCenter.default.removeObserver(self)
}
public init(alert: NWSAlert, alertsManager: NWSAlertsManager = LocationManager.shared.nwsAlertsManager) {
......@@ -22,6 +23,14 @@ class NWSAlertViewModel: ViewModelProtocol {
self.alertsManager = alertsManager
cellFactory = NWSAlertCellFactory(alert: alert)
alertsManager.delegates.add(delegate: self)
NotificationCenter.default.addObserver(self, selector: #selector(handlePremiumStateChange), name: Notification.Name(rawValue: kEventInAppPurchasedCompleted), object: nil)
}
@objc
private func handlePremiumStateChange() {
onMain {
self.delegate?.viewModelDidChange(model: self)
}
}
}
......
......@@ -28,12 +28,22 @@ class TodayViewModel: ViewModelProtocol {
deinit {
locationManager.remove(delegate: self)
Settings.shared.delegate.remove(delegate: self)
NotificationCenter.default.removeObserver(self)
}
public init() {
self.location = LocationManager.shared.selectedLocation
locationManager.add(delegate: self)
Settings.shared.delegate.add(delegate: self)
NotificationCenter.default.addObserver(self, selector: #selector(handlePremiumStateChange), name: Notification.Name(rawValue: kEventInAppPurchasedCompleted), object: nil)
}
@objc
private func handlePremiumStateChange() {
onMain {
self.todayCellFactory.setNeedsUpdate()
self.delegate?.viewModelDidChange(model: self)
}
}
public func updateWeather() {
......
......@@ -30,6 +30,8 @@ target '1Weather' do
pod 'GoogleMobileAdsMediationFacebook'
pod 'GoogleMobileAdsMediationFyber'
pod 'GoogleMobileAdsMediationMoPub'
pod 'PKHUD', '~> 5.0'
end
......
......@@ -157,6 +157,7 @@ PODS:
- nanopb/encode (= 2.30908.0)
- nanopb/decode (2.30908.0)
- nanopb/encode (2.30908.0)
- PKHUD (5.3.0)
- PromisesObjC (1.2.12)
- SnapKit (5.0.1)
- Swarm (1.0.7)
......@@ -178,6 +179,7 @@ DEPENDENCIES:
- Localize-Swift
- MoEngage-iOS-SDK
- MORichNotification
- PKHUD (~> 5.0)
- SnapKit
- "Swarm (from `git@gitlab.pinsightmedia.com:oneweather/wdt-skywisetilekit-ios.git`, branch `develop`)"
- XMLCoder (~> 0.12.0)
......@@ -213,6 +215,7 @@ SPEC REPOS:
- mopub-ios-sdk
- MORichNotification
- nanopb
- PKHUD
- PromisesObjC
- SnapKit
- XMLCoder
......@@ -263,11 +266,12 @@ SPEC CHECKSUMS:
mopub-ios-sdk: ce5aa12abe59d42cb8866b1297bdff7b6a42e273
MORichNotification: abf1f1aaed3a9366dc8e966c55652bff7716b3b8
nanopb: a0ba3315591a9ae0a16a309ee504766e90db0c96
PKHUD: 98f3e4bc904b9c916f1c5bb6d765365b5357291b
PromisesObjC: 3113f7f76903778cf4a0586bd1ab89329a0b7b97
SnapKit: 97b92857e3df3a0c71833cce143274bf6ef8e5eb
Swarm: 95393cd52715744c94e3a8475bc20b4de5d79f35
XMLCoder: f884dfa894a6f8b7dce465e4f6c02963bf17e028
PODFILE CHECKSUM: 911325f9e6868ad8b16116a7a9f009c256432c0c
PODFILE CHECKSUM: db1a9a5a6b6eb02f99846fd69b40292acf0356bc
COCOAPODS: 1.10.1
......@@ -157,6 +157,7 @@ PODS:
- nanopb/encode (= 2.30908.0)
- nanopb/decode (2.30908.0)
- nanopb/encode (2.30908.0)
- PKHUD (5.3.0)
- PromisesObjC (1.2.12)
- SnapKit (5.0.1)
- Swarm (1.0.7)
......@@ -178,6 +179,7 @@ DEPENDENCIES:
- Localize-Swift
- MoEngage-iOS-SDK
- MORichNotification
- PKHUD (~> 5.0)
- SnapKit
- "Swarm (from `git@gitlab.pinsightmedia.com:oneweather/wdt-skywisetilekit-ios.git`, branch `develop`)"
- XMLCoder (~> 0.12.0)
......@@ -213,6 +215,7 @@ SPEC REPOS:
- mopub-ios-sdk
- MORichNotification
- nanopb
- PKHUD
- PromisesObjC
- SnapKit
- XMLCoder
......@@ -263,11 +266,12 @@ SPEC CHECKSUMS:
mopub-ios-sdk: ce5aa12abe59d42cb8866b1297bdff7b6a42e273
MORichNotification: abf1f1aaed3a9366dc8e966c55652bff7716b3b8
nanopb: a0ba3315591a9ae0a16a309ee504766e90db0c96
PKHUD: 98f3e4bc904b9c916f1c5bb6d765365b5357291b
PromisesObjC: 3113f7f76903778cf4a0586bd1ab89329a0b7b97
SnapKit: 97b92857e3df3a0c71833cce143274bf6ef8e5eb
Swarm: 95393cd52715744c94e3a8475bc20b4de5d79f35
XMLCoder: f884dfa894a6f8b7dce465e4f6c02963bf17e028
PODFILE CHECKSUM: 911325f9e6868ad8b16116a7a9f009c256432c0c
PODFILE CHECKSUM: db1a9a5a6b6eb02f99846fd69b40292acf0356bc
COCOAPODS: 1.10.1
The MIT License (MIT)
Copyright (c) 2014 Philip Kluz (Philip.Kluz@gmail.com)
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
\ No newline at end of file
//
// HUDView.swift
// PKHUD
//
// Created by Philip Kluz on 6/16/14.
// Copyright (c) 2016 NSExceptional. All rights reserved.
// Licensed under the MIT license.
//
import UIKit
/// Provides the general look and feel of the PKHUD, into which the eventual content is inserted.
internal class FrameView: UIVisualEffectView {
internal init() {
super.init(effect: UIBlurEffect(style: .light))
DispatchQueue.main.async {
self.commonInit()
}
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
DispatchQueue.main.async {
self.commonInit()
}
}
private func commonInit() {
backgroundColor = UIColor(white: 0.8, alpha: 0.36)
layer.cornerRadius = 9.0
layer.masksToBounds = true
contentView.addSubview(content)
let offset = 20.0
let motionEffectsX = UIInterpolatingMotionEffect(keyPath: "center.x", type: .tiltAlongHorizontalAxis)
motionEffectsX.maximumRelativeValue = offset
motionEffectsX.minimumRelativeValue = -offset
let motionEffectsY = UIInterpolatingMotionEffect(keyPath: "center.y", type: .tiltAlongVerticalAxis)
motionEffectsY.maximumRelativeValue = offset
motionEffectsY.minimumRelativeValue = -offset
let group = UIMotionEffectGroup()
group.motionEffects = [motionEffectsX, motionEffectsY]
addMotionEffect(group)
}
private var _content = UIView()
internal var content: UIView {
get {
return _content
}
set {
_content.removeFromSuperview()
_content = newValue
_content.alpha = 0.85
_content.clipsToBounds = true
_content.contentMode = .center
frame.size = _content.bounds.size
contentView.addSubview(_content)
}
}
}
//
// HUD.swift
// PKHUD
//
// Created by Eugene Tartakovsky on 29/01/16.
// Copyright © 2016 Eugene Tartakovsky, NSExceptional. All rights reserved.
// Licensed under the MIT license.
//
import UIKit
public enum HUDContentType {
case success
case error
case progress
case image(UIImage?)
case rotatingImage(UIImage?)
case labeledSuccess(title: String?, subtitle: String?)
case labeledError(title: String?, subtitle: String?)
case labeledProgress(title: String?, subtitle: String?)
case labeledImage(image: UIImage?, title: String?, subtitle: String?)
case labeledRotatingImage(image: UIImage?, title: String?, subtitle: String?)
case label(String?)
case systemActivity
case customView(view: UIView)
}
public final class HUD {
// MARK: Properties
public static var dimsBackground: Bool {
get { return PKHUD.sharedHUD.dimsBackground }
set { PKHUD.sharedHUD.dimsBackground = newValue }
}
public static var allowsInteraction: Bool {
get { return PKHUD.sharedHUD.userInteractionOnUnderlyingViewsEnabled }
set { PKHUD.sharedHUD.userInteractionOnUnderlyingViewsEnabled = newValue }
}
public static var leadingMargin: CGFloat {
get { return PKHUD.sharedHUD.leadingMargin }
set { PKHUD.sharedHUD.leadingMargin = newValue }
}
public static var trailingMargin: CGFloat {
get { return PKHUD.sharedHUD.trailingMargin }
set { PKHUD.sharedHUD.trailingMargin = newValue }
}
public static var isVisible: Bool { return PKHUD.sharedHUD.isVisible }
// MARK: Public methods, PKHUD based
public static func show(_ content: HUDContentType, onView view: UIView? = nil) {
PKHUD.sharedHUD.contentView = contentView(content)
PKHUD.sharedHUD.show(onView: view)
}
public static func hide(_ completion: ((Bool) -> Void)? = nil) {
PKHUD.sharedHUD.hide(animated: false, completion: completion)
}
public static func hide(animated: Bool, completion: ((Bool) -> Void)? = nil) {
PKHUD.sharedHUD.hide(animated: animated, completion: completion)
}
public static func hide(afterDelay delay: TimeInterval, completion: ((Bool) -> Void)? = nil) {
PKHUD.sharedHUD.hide(afterDelay: delay, completion: completion)
}
// MARK: Public methods, HUD based
public static func flash(_ content: HUDContentType, onView view: UIView? = nil) {
HUD.show(content, onView: view)
HUD.hide(animated: true, completion: nil)
}
public static func flash(_ content: HUDContentType, onView view: UIView? = nil, delay: TimeInterval, completion: ((Bool) -> Void)? = nil) {
HUD.show(content, onView: view)
HUD.hide(afterDelay: delay, completion: completion)
}
// MARK: Keyboard Methods
public static func registerForKeyboardNotifications() {
PKHUD.sharedHUD.registerForKeyboardNotifications()
}
public static func deregisterFromKeyboardNotifications() {
PKHUD.sharedHUD.deregisterFromKeyboardNotifications()
}
// MARK: Private methods
fileprivate static func contentView(_ content: HUDContentType) -> UIView {
switch content {
case .success:
return PKHUDSuccessView()
case .error:
return PKHUDErrorView()
case .progress:
return PKHUDProgressView()
case let .image(image):
return PKHUDSquareBaseView(image: image)
case let .rotatingImage(image):
return PKHUDRotatingImageView(image: image)
case let .labeledSuccess(title, subtitle):
return PKHUDSuccessView(title: title, subtitle: subtitle)
case let .labeledError(title, subtitle):
return PKHUDErrorView(title: title, subtitle: subtitle)
case let .labeledProgress(title, subtitle):
return PKHUDProgressView(title: title, subtitle: subtitle)
case let .labeledImage(image, title, subtitle):
return PKHUDSquareBaseView(image: image, title: title, subtitle: subtitle)
case let .labeledRotatingImage(image, title, subtitle):
return PKHUDRotatingImageView(image: image, title: title, subtitle: subtitle)
case let .label(text):
return PKHUDTextView(text: text)
case .systemActivity:
return PKHUDSystemActivityIndicatorView()
case let .customView(view):
return view
}
}
}
{
"info" : {
"version" : 1,
"author" : "xcode"
}
}
\ No newline at end of file
{
"images" : [
{
"idiom" : "universal",
"filename" : "checkmark.pdf"
}
],
"info" : {
"version" : 1,
"author" : "xcode"
}
}
\ No newline at end of file
{
"images" : [
{
"idiom" : "universal",
"filename" : "cross.pdf"
}
],
"info" : {
"version" : 1,
"author" : "xcode"
}
}
\ No newline at end of file
{
"images" : [
{
"idiom" : "universal",
"filename" : "progress.pdf"
}
],
"info" : {
"version" : 1,
"author" : "xcode"
}
}
\ No newline at end of file
{
"images" : [
{
"idiom" : "universal",
"filename" : "progress_circular.pdf"
}
],
"info" : {
"version" : 1,
"author" : "xcode"
},
"properties" : {
"template-rendering-intent" : "original"
}
}
\ No newline at end of file
//
// PKHUD.h
// PKHUD
//
// Created by Philip Kluz on 6/17/14.
// Copyright (c) 2016 NSExceptional. All rights reserved.
// Licensed under the MIT license.
//
@import UIKit;
//! Project version number for PKHUD.
FOUNDATION_EXPORT double PKHUDVersionNumber;
//! Project version string for PKHUD.
FOUNDATION_EXPORT const unsigned char PKHUDVersionString[];
//
// HUD.swift
// PKHUD
//
// Created by Philip Kluz on 6/13/14.
// Copyright (c) 2016 NSExceptional. All rights reserved.
// Licensed under the MIT license.
//
import UIKit
/// The PKHUD object controls showing and hiding of the HUD, as well as its contents and touch response behavior.
open class PKHUD: NSObject {
fileprivate struct Constants {
static let sharedHUD = PKHUD()
}
public var viewToPresentOn: UIView?
fileprivate let container = ContainerView()
fileprivate var hideTimer: Timer?
public typealias TimerAction = (Bool) -> Void
fileprivate var timerActions = [String: TimerAction]()
/// Grace period is the time (in seconds) that the invoked method may be run without
/// showing the HUD. If the task finishes before the grace time runs out, the HUD will
/// not be shown at all.
/// This may be used to prevent HUD display for very short tasks.
/// Defaults to 0 (no grace time).
@available(*, deprecated, message: "Will be removed with Swift4 support, use gracePeriod instead")
public var graceTime: TimeInterval {
get {
return gracePeriod
}
set(newPeriod) {
gracePeriod = newPeriod
}
}
/// Grace period is the time (in seconds) that the invoked method may be run without
/// showing the HUD. If the task finishes before the grace time runs out, the HUD will
/// not be shown at all.
/// This may be used to prevent HUD display for very short tasks.
/// Defaults to 0 (no grace time).
public var gracePeriod: TimeInterval = 0
fileprivate var graceTimer: Timer?
// MARK: Public
open class var sharedHUD: PKHUD {
return Constants.sharedHUD
}
public override init () {
super.init()
#if swift(>=4.2)
let notificationName = UIApplication.willEnterForegroundNotification
#else
let notificationName = NSNotification.Name.UIApplicationWillEnterForeground
#endif
NotificationCenter.default.addObserver(self,
selector: #selector(PKHUD.willEnterForeground(_:)),
name: notificationName,
object: nil)
userInteractionOnUnderlyingViewsEnabled = false
container.frameView.autoresizingMask = [ .flexibleLeftMargin,
.flexibleRightMargin,
.flexibleTopMargin,
.flexibleBottomMargin ]
self.container.isAccessibilityElement = true
self.container.accessibilityIdentifier = "PKHUD"
}
public convenience init(viewToPresentOn view: UIView) {
self.init()
viewToPresentOn = view
}
deinit {
NotificationCenter.default.removeObserver(self)
}
open var dimsBackground = true
open var userInteractionOnUnderlyingViewsEnabled: Bool {
get {
return !container.isUserInteractionEnabled
}
set {
container.isUserInteractionEnabled = !newValue
}
}
open var isVisible: Bool {
return !container.isHidden
}
open var contentView: UIView {
get {
return container.frameView.content
}
set {
container.frameView.content = newValue
startAnimatingContentView()
}
}
open var effect: UIVisualEffect? {
get {
return container.frameView.effect
}
set {
container.frameView.effect = newValue
}
}
open var leadingMargin: CGFloat = 0
open var trailingMargin: CGFloat = 0
open func show(onView view: UIView? = nil) {
let view: UIView = view ?? viewToPresentOn ?? UIApplication.shared.keyWindow!
if !view.subviews.contains(container) {
view.addSubview(container)
container.frame.origin = CGPoint.zero
container.frame.size = view.frame.size
container.autoresizingMask = [ .flexibleHeight, .flexibleWidth ]
container.isHidden = true
}
if dimsBackground {
container.showBackground(animated: true)
}
// If the grace time is set, postpone the HUD display
if gracePeriod > 0.0 {
let timer = Timer(timeInterval: gracePeriod, target: self, selector: #selector(PKHUD.handleGraceTimer(_:)), userInfo: nil, repeats: false)
#if swift(>=4.2)
RunLoop.current.add(timer, forMode: .common)
#else
RunLoop.current.add(timer, forMode: .commonModes)
#endif
graceTimer = timer
} else {
showContent()
}
}
func showContent() {
graceTimer?.invalidate()
container.showFrameView()
startAnimatingContentView()
}
open func hide(animated anim: Bool = true, completion: TimerAction? = nil) {
graceTimer?.invalidate()
container.hideFrameView(animated: anim, completion: completion)
stopAnimatingContentView()
}
open func hide(_ animated: Bool, completion: TimerAction? = nil) {
hide(animated: animated, completion: completion)
}
open func hide(afterDelay delay: TimeInterval, completion: TimerAction? = nil) {
let key = UUID().uuidString
let userInfo = ["timerActionKey": key]
if let completion = completion {
timerActions[key] = completion
}
hideTimer?.invalidate()
hideTimer = Timer.scheduledTimer(timeInterval: delay,
target: self,
selector: #selector(PKHUD.performDelayedHide(_:)),
userInfo: userInfo,
repeats: false)
}
// MARK: Internal
@objc internal func willEnterForeground(_ notification: Notification?) {
self.startAnimatingContentView()
}
internal func startAnimatingContentView() {
if let animatingContentView = contentView as? PKHUDAnimating, isVisible {
animatingContentView.startAnimation()
}
}
internal func stopAnimatingContentView() {
if let animatingContentView = contentView as? PKHUDAnimating {
animatingContentView.stopAnimation?()
}
}
internal func registerForKeyboardNotifications() {
container.registerForKeyboardNotifications()
}
internal func deregisterFromKeyboardNotifications() {
container.deregisterFromKeyboardNotifications()
}
// MARK: Timer callbacks
@objc internal func performDelayedHide(_ timer: Timer? = nil) {
let userInfo = timer?.userInfo as? [String: AnyObject]
let key = userInfo?["timerActionKey"] as? String
var completion: TimerAction?
if let key = key, let action = timerActions[key] {
completion = action
timerActions[key] = nil
}
hide(animated: true, completion: completion)
}
@objc internal func handleGraceTimer(_ timer: Timer? = nil) {
// Show the HUD only if the task is still running
if (graceTimer?.isValid)! {
showContent()
}
}
}
//
// PKHUDAnimatingContentView.swift
// PKHUD
//
// Created by Philip Kluz on 9/27/15.
// Copyright (c) 2016 NSExceptional. All rights reserved.
// Licensed under the MIT license.
//
import UIKit
@objc public protocol PKHUDAnimating {
func startAnimation()
@objc optional func stopAnimation()
}
//
// PKHUDAnimation.swift
// PKHUD
//
// Created by Piergiuseppe Longo on 06/01/16.
// Copyright © 2016 Piergiuseppe Longo, NSExceptional. All rights reserved.
// Licensed under the MIT license.
//
import Foundation
import QuartzCore
public final class PKHUDAnimation {
public static let discreteRotation: CAAnimation = {
let animation = CAKeyframeAnimation(keyPath: "transform.rotation.z")
animation.values = [
NSNumber(value: 0.0),
NSNumber(value: 1.0 * .pi / 6.0),
NSNumber(value: 2.0 * .pi / 6.0),
NSNumber(value: 3.0 * .pi / 6.0),
NSNumber(value: 4.0 * .pi / 6.0),
NSNumber(value: 5.0 * .pi / 6.0),
NSNumber(value: 6.0 * .pi / 6.0),
NSNumber(value: 7.0 * .pi / 6.0),
NSNumber(value: 8.0 * .pi / 6.0),
NSNumber(value: 9.0 * .pi / 6.0),
NSNumber(value: 10.0 * .pi / 6.0),
NSNumber(value: 11.0 * .pi / 6.0),
NSNumber(value: 2.0 * .pi)
]
animation.keyTimes = [
NSNumber(value: 0.0),
NSNumber(value: 1.0 / 12.0),
NSNumber(value: 2.0 / 12.0),
NSNumber(value: 3.0 / 12.0),
NSNumber(value: 4.0 / 12.0),
NSNumber(value: 5.0 / 12.0),
NSNumber(value: 0.5),
NSNumber(value: 7.0 / 12.0),
NSNumber(value: 8.0 / 12.0),
NSNumber(value: 9.0 / 12.0),
NSNumber(value: 10.0 / 12.0),
NSNumber(value: 11.0 / 12.0),
NSNumber(value: 1.0)
]
animation.duration = 1.2
#if swift(>=4.2)
animation.calculationMode = .discrete
#else
animation.calculationMode = "discrete"
#endif
animation.repeatCount = Float(INT_MAX)
return animation
}()
static let continuousRotation: CAAnimation = {
let animation = CABasicAnimation(keyPath: "transform.rotation.z")
animation.fromValue = 0
animation.toValue = 2.0 * .pi
animation.duration = 1.2
animation.repeatCount = Float(INT_MAX)
return animation
}()
}
//
// PKHUD.Assets.swift
// PKHUD
//
// Created by Philip Kluz on 6/18/14.
// Copyright (c) 2016 NSExceptional. All rights reserved.
// Licensed under the MIT license.
//
import UIKit
/// PKHUDAssets provides a set of default images, that can be supplied to the PKHUD's content views.
open class PKHUDAssets: NSObject {
open class var crossImage: UIImage { return PKHUDAssets.bundledImage(named: "cross") }
open class var checkmarkImage: UIImage { return PKHUDAssets.bundledImage(named: "checkmark") }
open class var progressActivityImage: UIImage { return PKHUDAssets.bundledImage(named: "progress_activity") }
open class var progressCircularImage: UIImage { return PKHUDAssets.bundledImage(named: "progress_circular") }
internal class func bundledImage(named name: String) -> UIImage {
let primaryBundle = Bundle(for: PKHUDAssets.self)
if let image = UIImage(named: name, in: primaryBundle, compatibleWith: nil) {
// Load image in cases where PKHUD is directly integrated
return image
} else if
let subBundleUrl = primaryBundle.url(forResource: "PKHUDResources", withExtension: "bundle"),
let subBundle = Bundle(url: subBundleUrl),
let image = UIImage(named: name, in: subBundle, compatibleWith: nil)
{
// Load image in cases where PKHUD is integrated via cocoapods as a dynamic or static framework with a separate resource bundle
return image
}
return UIImage()
}
}
//
// PKHUDErrorAnimation.swift
// PKHUD
//
// Created by Philip Kluz on 9/27/15.
// Copyright (c) 2016 NSExceptional. All rights reserved.
// Licensed under the MIT license.
//
import UIKit
/// PKHUDErrorView provides an animated error (cross) view.
open class PKHUDErrorView: PKHUDSquareBaseView, PKHUDAnimating {
var dashOneLayer = PKHUDErrorView.generateDashLayer()
var dashTwoLayer = PKHUDErrorView.generateDashLayer()
class func generateDashLayer() -> CAShapeLayer {
let dash = CAShapeLayer()
dash.frame = CGRect(x: 0.0, y: 0.0, width: 88.0, height: 88.0)
dash.path = {
let path = UIBezierPath()
path.move(to: CGPoint(x: 0.0, y: 44.0))
path.addLine(to: CGPoint(x: 88.0, y: 44.0))
return path.cgPath
}()
#if swift(>=4.2)
dash.lineCap = .round
dash.lineJoin = .round
dash.fillMode = .forwards
#else
dash.lineCap = kCALineCapRound
dash.lineJoin = kCALineJoinRound
dash.fillMode = kCAFillModeForwards
#endif
dash.fillColor = nil
dash.strokeColor = UIColor(red: 0.15, green: 0.15, blue: 0.15, alpha: 1.0).cgColor
dash.lineWidth = 6
return dash
}
public init(title: String? = nil, subtitle: String? = nil) {
super.init(title: title, subtitle: subtitle)
layer.addSublayer(dashOneLayer)
layer.addSublayer(dashTwoLayer)
dashOneLayer.position = layer.position
dashTwoLayer.position = layer.position
}
public required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
layer.addSublayer(dashOneLayer)
layer.addSublayer(dashTwoLayer)
dashOneLayer.position = layer.position
dashTwoLayer.position = layer.position
}
func rotationAnimation(_ angle: CGFloat) -> CABasicAnimation {
var animation: CABasicAnimation
if #available(iOS 9.0, *) {
let springAnimation = CASpringAnimation(keyPath: "transform.rotation.z")
springAnimation.damping = 1.5
springAnimation.mass = 0.22
springAnimation.initialVelocity = 0.5
animation = springAnimation
} else {
animation = CABasicAnimation(keyPath: "transform.rotation.z")
}
animation.fromValue = 0.0
animation.toValue = angle * CGFloat(.pi / 180.0)
animation.duration = 1.0
#if swift(>=4.2)
let timingFunctionName = CAMediaTimingFunctionName.easeInEaseOut
#else
let timingFunctionName = kCAMediaTimingFunctionEaseInEaseOut
#endif
animation.timingFunction = CAMediaTimingFunction(name: timingFunctionName)
return animation
}
public func startAnimation() {
let dashOneAnimation = rotationAnimation(-45.0)
let dashTwoAnimation = rotationAnimation(45.0)
dashOneLayer.transform = CATransform3DMakeRotation(-45 * CGFloat(.pi / 180.0), 0.0, 0.0, 1.0)
dashTwoLayer.transform = CATransform3DMakeRotation(45 * CGFloat(.pi / 180.0), 0.0, 0.0, 1.0)
dashOneLayer.add(dashOneAnimation, forKey: "dashOneAnimation")
dashTwoLayer.add(dashTwoAnimation, forKey: "dashTwoAnimation")
}
public func stopAnimation() {
dashOneLayer.removeAnimation(forKey: "dashOneAnimation")
dashTwoLayer.removeAnimation(forKey: "dashTwoAnimation")
}
}
//
// PKHUDProgressVIew.swift
// PKHUD
//
// Created by Philip Kluz on 6/12/15.
// Copyright (c) 2016 NSExceptional. All rights reserved.
// Licensed under the MIT license.
//
import UIKit
import QuartzCore
/// PKHUDProgressView provides an indeterminate progress view.
open class PKHUDProgressView: PKHUDSquareBaseView, PKHUDAnimating {
public init(title: String? = nil, subtitle: String? = nil) {
super.init(image: PKHUDAssets.progressActivityImage, title: title, subtitle: subtitle)
}
public required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
}
public func startAnimation() {
imageView.layer.add(PKHUDAnimation.discreteRotation, forKey: "progressAnimation")
}
public func stopAnimation() {
}
}
//
// PKHUDRotatingImageView.swift
// PKHUD
//
// Created by Mark Koh on 1/14/16.
// Copyright © 2016 NSExceptional. All rights reserved.
// Licensed under the MIT license.
//
import UIKit
import QuartzCore
/// PKHUDRotatingImageView provides a content view that rotates the supplied image automatically.
open class PKHUDRotatingImageView: PKHUDSquareBaseView, PKHUDAnimating {
public func startAnimation() {
imageView.layer.add(PKHUDAnimation.continuousRotation, forKey: "progressAnimation")
}
public func stopAnimation() {
}
}
//
// PKHUDSquareBaseView.swift
// PKHUD
//
// Created by Philip Kluz on 6/12/15.
// Copyright (c) 2016 NSExceptional. All rights reserved.
// Licensed under the MIT license.
//
import UIKit
/// PKHUDSquareBaseView provides a square view, which you can subclass and add additional views to.
open class PKHUDSquareBaseView: UIView {
static let defaultSquareBaseViewFrame = CGRect(origin: CGPoint.zero, size: CGSize(width: 156.0, height: 156.0))
public override init(frame: CGRect) {
super.init(frame: frame)
}
public required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
}
public init(image: UIImage? = nil, title: String? = nil, subtitle: String? = nil) {
super.init(frame: PKHUDSquareBaseView.defaultSquareBaseViewFrame)
self.imageView.image = image
titleLabel.text = title
subtitleLabel.text = subtitle
addSubview(imageView)
addSubview(titleLabel)
addSubview(subtitleLabel)
}
public let imageView: UIImageView = {
let imageView = UIImageView()
imageView.alpha = 0.85
imageView.clipsToBounds = true
imageView.contentMode = .center
return imageView
}()
public let titleLabel: UILabel = {
let label = UILabel()
label.textAlignment = .center
label.font = UIFont.boldSystemFont(ofSize: 17.0)
label.textColor = UIColor.black.withAlphaComponent(0.85)
label.adjustsFontSizeToFitWidth = true
label.minimumScaleFactor = 0.25
return label
}()
public let subtitleLabel: UILabel = {
let label = UILabel()
label.textAlignment = .center
label.font = UIFont.systemFont(ofSize: 14.0)
label.textColor = UIColor.black.withAlphaComponent(0.7)
label.adjustsFontSizeToFitWidth = true
label.numberOfLines = 2
label.adjustsFontSizeToFitWidth = true
label.minimumScaleFactor = 0.25
return label
}()
open override func layoutSubviews() {
super.layoutSubviews()
let margin: CGFloat = PKHUD.sharedHUD.leadingMargin + PKHUD.sharedHUD.trailingMargin
let originX: CGFloat = margin > 0 ? margin : 0.0
let viewWidth = bounds.size.width - 2 * margin
let viewHeight = bounds.size.height
let halfHeight = CGFloat(ceilf(CFloat(viewHeight / 2.0)))
let quarterHeight = CGFloat(ceilf(CFloat(viewHeight / 4.0)))
let threeQuarterHeight = CGFloat(ceilf(CFloat(viewHeight / 4.0 * 3.0)))
titleLabel.frame = CGRect(origin: CGPoint(x: originX, y: 0.0), size: CGSize(width: viewWidth, height: quarterHeight))
imageView.frame = CGRect(origin: CGPoint(x: originX, y: quarterHeight), size: CGSize(width: viewWidth, height: halfHeight))
subtitleLabel.frame = CGRect(origin: CGPoint(x: originX, y: threeQuarterHeight), size: CGSize(width: viewWidth, height: quarterHeight))
}
}
//
// PKHUDCheckmarkView.swift
// PKHUD
//
// Created by Philip Kluz on 9/27/15.
// Copyright (c) 2016 NSExceptional. All rights reserved.
// Licensed under the MIT license.
//
import UIKit
/// PKHUDCheckmarkView provides an animated success (checkmark) view.
open class PKHUDSuccessView: PKHUDSquareBaseView, PKHUDAnimating {
var checkmarkShapeLayer: CAShapeLayer = {
let checkmarkPath = UIBezierPath()
checkmarkPath.move(to: CGPoint(x: 4.0, y: 27.0))
checkmarkPath.addLine(to: CGPoint(x: 34.0, y: 56.0))
checkmarkPath.addLine(to: CGPoint(x: 88.0, y: 0.0))
let layer = CAShapeLayer()
layer.frame = CGRect(x: 3.0, y: 3.0, width: 88.0, height: 56.0)
layer.path = checkmarkPath.cgPath
#if swift(>=4.2)
layer.fillMode = .forwards
layer.lineCap = .round
layer.lineJoin = .round
#else
layer.fillMode = kCAFillModeForwards
layer.lineCap = kCALineCapRound
layer.lineJoin = kCALineJoinRound
#endif
layer.fillColor = nil
layer.strokeColor = UIColor(red: 0.15, green: 0.15, blue: 0.15, alpha: 1.0).cgColor
layer.lineWidth = 6.0
return layer
}()
public init(title: String? = nil, subtitle: String? = nil) {
super.init(title: title, subtitle: subtitle)
layer.addSublayer(checkmarkShapeLayer)
checkmarkShapeLayer.position = layer.position
}
public required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
layer.addSublayer(checkmarkShapeLayer)
checkmarkShapeLayer.position = layer.position
}
open func startAnimation() {
let checkmarkStrokeAnimation = CAKeyframeAnimation(keyPath: "strokeEnd")
checkmarkStrokeAnimation.values = [0, 1]
checkmarkStrokeAnimation.keyTimes = [0, 1]
checkmarkStrokeAnimation.duration = 0.35
checkmarkShapeLayer.add(checkmarkStrokeAnimation, forKey: "checkmarkStrokeAnim")
}
open func stopAnimation() {
checkmarkShapeLayer.removeAnimation(forKey: "checkmarkStrokeAnimation")
}
}
//
// PKHUDSystemActivityIndicatorView.swift
// PKHUD
//
// Created by Philip Kluz on 6/12/15.
// Copyright (c) 2016 NSExceptional. All rights reserved.
// Licensed under the MIT license.
//
import UIKit
/// PKHUDSystemActivityIndicatorView provides the system UIActivityIndicatorView as an alternative.
public final class PKHUDSystemActivityIndicatorView: PKHUDSquareBaseView, PKHUDAnimating {
public init() {
super.init(frame: PKHUDSquareBaseView.defaultSquareBaseViewFrame)
commonInit()
}
public override init(frame: CGRect) {
super.init(frame: frame)
commonInit()
}
public required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
commonInit()
}
func commonInit () {
backgroundColor = UIColor.clear
alpha = 0.8
self.addSubview(activityIndicatorView)
}
public override func layoutSubviews() {
super.layoutSubviews()
activityIndicatorView.center = self.center
}
let activityIndicatorView: UIActivityIndicatorView = {
#if swift(>=4.2)
let activity = UIActivityIndicatorView(style: .whiteLarge)
#else
let activity = UIActivityIndicatorView(activityIndicatorStyle: .whiteLarge)
#endif
activity.color = UIColor.black
return activity
}()
public func startAnimation() {
activityIndicatorView.startAnimating()
}
}
//
// PKHUDTextView.swift
// PKHUD
//
// Created by Philip Kluz on 6/12/15.
// Copyright (c) 2016 NSExceptional. All rights reserved.
// Licensed under the MIT license.
//
import UIKit
/// PKHUDTextView provides a wide, three line text view, which you can use to display information.
open class PKHUDTextView: PKHUDWideBaseView {
public init(text: String?) {
super.init()
commonInit(text)
}
public required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
commonInit("")
}
func commonInit(_ text: String?) {
titleLabel.text = text
addSubview(titleLabel)
}
open override func layoutSubviews() {
super.layoutSubviews()
let padding: CGFloat = 10.0
titleLabel.frame = bounds.insetBy(dx: padding, dy: padding)
}
public let titleLabel: UILabel = {
let label = UILabel()
label.textAlignment = .center
label.font = UIFont.boldSystemFont(ofSize: 17.0)
label.textColor = UIColor.black.withAlphaComponent(0.85)
label.adjustsFontSizeToFitWidth = true
label.numberOfLines = 3
return label
}()
}
//
// PKHUDWideBaseView.swift
// PKHUD
//
// Created by Philip Kluz on 6/12/15.
// Copyright (c) 2016 NSExceptional. All rights reserved.
// Licensed under the MIT license.
//
import UIKit
/// PKHUDWideBaseView provides a wide base view, which you can subclass and add additional views to.
open class PKHUDWideBaseView: UIView {
static let defaultWideBaseViewFrame = CGRect(origin: CGPoint.zero, size: CGSize(width: 265.0, height: 90.0))
public init() {
super.init(frame: PKHUDWideBaseView.defaultWideBaseViewFrame)
}
public override init(frame: CGRect) {
super.init(frame: frame)
}
public required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
}
}
//
// HUDWindow.swift
// PKHUD
//
// Created by Philip Kluz on 6/16/14.
// Copyright (c) 2016 NSExceptional. All rights reserved.
// Licensed under the MIT license.
//
import UIKit
/// The window used to display the PKHUD within. Placed atop the applications main window.
internal class ContainerView: UIView {
private var keyboardIsVisible = false
private var keyboardHeight: CGFloat = 0.0
internal let frameView: FrameView
internal init(frameView: FrameView = FrameView()) {
self.frameView = frameView
super.init(frame: CGRect.zero)
commonInit()
}
required init?(coder aDecoder: NSCoder) {
frameView = FrameView()
super.init(coder: aDecoder)
commonInit()
}
fileprivate func commonInit() {
backgroundColor = UIColor.clear
isHidden = true
addSubview(backgroundView)
addSubview(frameView)
}
internal override func layoutSubviews() {
super.layoutSubviews()
frameView.center = calculateHudCenter()
backgroundView.frame = bounds
}
internal func showFrameView() {
layer.removeAllAnimations()
frameView.center = calculateHudCenter()
frameView.alpha = 1.0
isHidden = false
}
fileprivate var willHide = false
internal func hideFrameView(animated anim: Bool, completion: ((Bool) -> Void)? = nil) {
let finalize: (_ finished: Bool) -> Void = { finished in
self.isHidden = true
self.removeFromSuperview()
self.willHide = false
completion?(finished)
}
if isHidden {
return
}
willHide = true
if anim {
UIView.animate(withDuration: 0.8, animations: {
self.frameView.alpha = 0.0
self.hideBackground(animated: false)
}, completion: { _ in finalize(true) })
} else {
self.frameView.alpha = 0.0
finalize(true)
}
}
fileprivate let backgroundView: UIView = {
let view = UIView()
view.backgroundColor = UIColor(white: 0.0, alpha: 0.25)
view.alpha = 0.0
return view
}()
internal func showBackground(animated anim: Bool) {
if anim {
UIView.animate(withDuration: 0.175, animations: {
self.backgroundView.alpha = 1.0
})
} else {
backgroundView.alpha = 1.0
}
}
internal func hideBackground(animated anim: Bool) {
if anim {
UIView.animate(withDuration: 0.65, animations: {
self.backgroundView.alpha = 0.0
})
} else {
backgroundView.alpha = 0.0
}
}
// MARK: Notifications
internal func registerForKeyboardNotifications() {
NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillShow(notification:)), name: UIResponder.keyboardDidShowNotification, object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillBeHidden(notification:)), name: UIResponder.keyboardWillHideNotification, object: nil)
}
internal func deregisterFromKeyboardNotifications() {
NotificationCenter.default.removeObserver(self, name: UIResponder.keyboardWillShowNotification, object: nil)
NotificationCenter.default.removeObserver(self, name: UIResponder.keyboardWillHideNotification, object: nil)
}
// MARK: Triggered Functions
@objc private func keyboardWillShow(notification: NSNotification) {
keyboardIsVisible = true
guard let userInfo = notification.userInfo else {
return
}
if let keyboardHeight = (userInfo[UIResponder.keyboardFrameBeginUserInfoKey] as? NSValue)?.cgRectValue.height {
self.keyboardHeight = keyboardHeight
}
if !self.isHidden {
if let duration = userInfo[UIResponder.keyboardAnimationDurationUserInfoKey] as? NSNumber,
let curve = userInfo[UIResponder.keyboardAnimationCurveUserInfoKey] as? NSNumber {
animateHUDWith(duration: duration.doubleValue,
curve: UIView.AnimationCurve(rawValue: curve.intValue) ?? UIView.AnimationCurve.easeInOut,
toLocation: calculateHudCenter())
}
}
}
@objc private func keyboardWillBeHidden(notification: NSNotification) {
keyboardIsVisible = false
if !self.isHidden {
guard let userInfo = notification.userInfo else {
return
}
if let duration = userInfo[UIResponder.keyboardAnimationDurationUserInfoKey] as? NSNumber,
let curve = userInfo[UIResponder.keyboardAnimationCurveUserInfoKey] as? NSNumber {
animateHUDWith(duration: duration.doubleValue,
curve: UIView.AnimationCurve(rawValue: curve.intValue) ?? UIView.AnimationCurve.easeInOut,
toLocation: calculateHudCenter())
}
}
}
// MARK: - Helpers
private func animateHUDWith(duration: Double, curve: UIView.AnimationCurve, toLocation location: CGPoint) {
UIView.beginAnimations(nil, context: nil)
UIView.setAnimationDuration(TimeInterval(duration))
UIView.setAnimationCurve(curve)
frameView.center = location
UIView.commitAnimations()
}
private func calculateHudCenter() -> CGPoint {
if !keyboardIsVisible {
return center
} else {
let yLocation = (frame.height - keyboardHeight) / 2
return CGPoint(x: center.x, y: yLocation)
}
}
}
//
// PKHUD.WindowRootViewController.swift
// PKHUD
//
// Created by Philip Kluz on 6/18/14.
// Copyright (c) 2016 NSExceptional. All rights reserved.
// Licensed under the MIT license.
//
import UIKit
/// Serves as a configuration relay controller, tapping into the main window's rootViewController settings.
internal class WindowRootViewController: UIViewController {
internal override var supportedInterfaceOrientations: UIInterfaceOrientationMask {
if let rootViewController = UIApplication.shared.delegate?.window??.rootViewController {
return rootViewController.supportedInterfaceOrientations
} else {
return UIInterfaceOrientationMask.portrait
}
}
internal override var preferredStatusBarStyle: UIStatusBarStyle {
return self.presentingViewController?.preferredStatusBarStyle ?? UIApplication.shared.statusBarStyle
}
internal override var prefersStatusBarHidden: Bool {
return self.presentingViewController?.prefersStatusBarHidden ?? UIApplication.shared.isStatusBarHidden
}
internal override var preferredStatusBarUpdateAnimation: UIStatusBarAnimation {
if let rootViewController = UIApplication.shared.delegate?.window??.rootViewController {
return rootViewController.preferredStatusBarUpdateAnimation
} else {
return .none
}
}
internal override var shouldAutorotate: Bool {
if let rootViewController = UIApplication.shared.delegate?.window??.rootViewController {
return rootViewController.shouldAutorotate
} else {
return false
}
}
}
[![Build Status](https://travis-ci.org/pkluz/PKHUD.svg?branch=master)](https://travis-ci.org/pkluz/PKHUD)
[![License](https://img.shields.io/cocoapods/l/PKHUD.svg?style=flat)](https://cocoapods.org/pods/PKHUD)
[![Platform](https://img.shields.io/cocoapods/p/PKHUD.svg?style=flat)](http://cocoadocs.org/docsets/PKHUD/3.2.1/)
[![CocoaPod](https://img.shields.io/cocoapods/v/PKHUD.svg?style=flat)](https://cocoapods.org/pods/PKHUD)
[![Carthage compatible](https://img.shields.io/badge/Carthage-compatible-4BC51D.svg?style=flat)](https://github.com/Carthage/Carthage)
![PKHUD - Swift and easy](https://raw.githubusercontent.com/pkluz/PKHUD/master/README_hero.png)
A **Swift** based reimplementation of the Apple HUD (Volume, Ringer, Rotation,…) **for iOS 8** and up.
## Features
- Official iOS 8 blur effect via **UIVisualEffectsView**.
- Proper **rotation support**.
- Size / **Device agnostic**.
- Works on top of presented view controllers, alerts,...
- Comes with several *free* resources - Checkmark, Cross, Progress Indicator,…
- …as well as **animated** ones.
- Builds as an **iOS 8 framework**.
![PKHUD.gif](https://cloud.githubusercontent.com/assets/1275218/10124182/09f4c406-654f-11e5-9cab-0f2e6f470887.gif)
## Installation
**The recommended way is to use CocoaPods.**
### CocoaPods
To install PKHUD for Swift 2 using CocoaPods, include the following in your Podfile
```ruby
pod 'PKHUD', '~> 3.0'
```
To install PKHUD for Swift 3.x using CocoaPods, include the following in your Podfile
```ruby
pod 'PKHUD', '~> 4.0'
```
To install PKHUD for Swift 4.x, include the following in your Podfile
```ruby
pod 'PKHUD', '~> 5.0'
```
### Carthage
[Carthage](https://github.com/Carthage/Carthage) is a decentralized dependency manager that builds your dependencies and provides you with binary frameworks.
You can install Carthage with [Homebrew](http://brew.sh/) using the following command:
```bash
$ brew update
$ brew install carthage
```
To integrate PKHUD into your Xcode project using Carthage, specify it in your `Cartfile`:
```ogdl
github "pkluz/PKHUD" ~> 4.0
```
Run `carthage update` to build the framework and drag the built `PKHUD.framework` into your Xcode project.
## How To
After adding the framework to your project, you need to import the module
```swift
import PKHUD
```
Now, you can proceed to show an arbitrary HUD (and have it automatically disappear a second later) like this:
```swift
HUD.flash(.success, delay: 1.0)
```
_or_ with a completion handler:
```swift
HUD.flash(.success, delay: 1.0) { finished in
// Completion Handler
}
```
alternatively, you can use the more verbose and flexible “plumbing” API:
```swift
PKHUD.sharedHUD.contentView = PKHUDSuccessView()
PKHUD.sharedHUD.show()
PKHUD.sharedHUD.hide(afterDelay: 1.0) { success in
// Completion Handler
}
```
You can also hot-swap content views - this can prove useful if you want to display a progress HUD first and transform it into a success or error HUD after an asynchronous operation has finished.
```swift
HUD.show(.progress)
// Now some long running task starts...
DispatchQueue.main.asyncAfter(deadline: .now() + 2) {
// ...and once it finishes we flash the HUD for a second.
HUD.flash(.success, delay: 1.0)
}
```
Please note that there are _multiple_ types of content views that ship with PKHUD. You can find them as separate files in the project folder as well as in the `ContentViews` group in Xcode.
## Communication _(Hat Tip AlamoFire)_
- If you **need help**, use [Stack Overflow](http://stackoverflow.com/questions/tagged/pkhud). (Tag 'pkhud')
- If you'd like to **ask a general question**, use [Stack Overflow](http://stackoverflow.com/questions/tagged/pkhud).
- If you **found a bug**, open an issue.
- If you **have a feature request**, open an issue.
- If you **want to contribute**, submit a pull request.
## Customization
There are two properties at your disposal to customize general behavior.
- `PKHUD.sharedHUD.dimsBackground: Bool` defines whether the background is slightly dimmed when the HUD is shown.
- `PKHUD.sharedHUD.userInteractionOnUnderlyingViewsEnabled: Bool` defines whether the underlying views respond to touches while the HUD is shown.
Additionally you are free to create you own custom content views. They can descend from any `UIView` type or the predefined base classes `PKHUDSquareBaseView` and `PKHUDWideBaseView`.
**Note**: It's neither possible to customize the general look and feel, nor do I plan to add that feature. You are free to provide any content views you wish but the blurring, corner radius and shading will remain the same.
## Credits
PKHUD is owned and maintained by Philip Kluz. Other mantainers are:
- Piergiuseppe Longo [twitter](https://twitter.com/pglongo)
## Xamarin
If you are Xamarin developer you can use this [port](https://github.com/Prin53/Xamarin.iOS.PKHUD).
## License
The MIT License (MIT)
Copyright (c) 2015 Philip Kluz (Philip.Kluz@gmail.com)
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
This source diff could not be displayed because it is too large. You can view the blob instead.
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>en</string>
<key>CFBundleExecutable</key>
<string>${EXECUTABLE_NAME}</string>
<key>CFBundleIdentifier</key>
<string>${PRODUCT_BUNDLE_IDENTIFIER}</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>${PRODUCT_NAME}</string>
<key>CFBundlePackageType</key>
<string>FMWK</string>
<key>CFBundleShortVersionString</key>
<string>5.3.0</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
<string>${CURRENT_PROJECT_VERSION}</string>
<key>NSPrincipalClass</key>
<string></string>
</dict>
</plist>
#import <Foundation/Foundation.h>
@interface PodsDummy_PKHUD : NSObject
@end
@implementation PodsDummy_PKHUD
@end
#ifdef __OBJC__
#import <UIKit/UIKit.h>
#else
#ifndef FOUNDATION_EXPORT
#if defined(__cplusplus)
#define FOUNDATION_EXPORT extern "C"
#else
#define FOUNDATION_EXPORT extern
#endif
#endif
#endif
#ifdef __OBJC__
#import <UIKit/UIKit.h>
#else
#ifndef FOUNDATION_EXPORT
#if defined(__cplusplus)
#define FOUNDATION_EXPORT extern "C"
#else
#define FOUNDATION_EXPORT extern
#endif
#endif
#endif
#import "PKHUD.h"
FOUNDATION_EXPORT double PKHUDVersionNumber;
FOUNDATION_EXPORT const unsigned char PKHUDVersionString[];
CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = NO
CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/PKHUD
GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1
OTHER_SWIFT_FLAGS = $(inherited) -D COCOAPODS
PODS_BUILD_DIR = ${BUILD_DIR}
PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)
PODS_ROOT = ${SRCROOT}
PODS_TARGET_SRCROOT = ${PODS_ROOT}/PKHUD
PODS_XCFRAMEWORKS_BUILD_DIR = $(PODS_CONFIGURATION_BUILD_DIR)/XCFrameworkIntermediates
PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier}
SKIP_INSTALL = YES
USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES
framework module PKHUD {
umbrella header "PKHUD-umbrella.h"
export *
module * { export * }
}
CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = NO
CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/PKHUD
GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1
OTHER_SWIFT_FLAGS = $(inherited) -D COCOAPODS
PODS_BUILD_DIR = ${BUILD_DIR}
PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)
PODS_ROOT = ${SRCROOT}
PODS_TARGET_SRCROOT = ${PODS_ROOT}/PKHUD
PODS_XCFRAMEWORKS_BUILD_DIR = $(PODS_CONFIGURATION_BUILD_DIR)/XCFrameworkIntermediates
PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier}
SKIP_INSTALL = YES
USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>en</string>
<key>CFBundleIdentifier</key>
<string>${PRODUCT_BUNDLE_IDENTIFIER}</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>${PRODUCT_NAME}</string>
<key>CFBundlePackageType</key>
<string>BNDL</string>
<key>CFBundleShortVersionString</key>
<string>5.3.0</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
<string>1</string>
<key>NSPrincipalClass</key>
<string></string>
</dict>
</plist>
......@@ -2423,6 +2423,30 @@ All rights reserved.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
## PKHUD
The MIT License (MIT)
Copyright (c) 2014 Philip Kluz (Philip.Kluz@gmail.com)
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
## PromisesObjC
......
......@@ -2604,6 +2604,36 @@ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
</dict>
<dict>
<key>FooterText</key>
<string>The MIT License (MIT)
Copyright (c) 2014 Philip Kluz (Philip.Kluz@gmail.com)
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.</string>
<key>License</key>
<string>MIT</string>
<key>Title</key>
<string>PKHUD</string>
<key>Type</key>
<string>PSGroupSpecifier</string>
</dict>
<dict>
<key>FooterText</key>
<string>
Apache License
Version 2.0, January 2004
......
......@@ -19,6 +19,7 @@ ${PODS_ROOT}/MoEngage-iOS-SDK/Frameworks/MoEngage.framework
${PODS_ROOT}/MoEngage-iOS-SDK/Frameworks/MoEngageCore.framework
${PODS_ROOT}/MoEngage-iOS-SDK/Frameworks/MOAnalytics.framework
${PODS_ROOT}/MoEngage-iOS-SDK/Frameworks/MOMessaging.framework
${BUILT_PRODUCTS_DIR}/PKHUD/PKHUD.framework
${BUILT_PRODUCTS_DIR}/PromisesObjC/FBLPromises.framework
${BUILT_PRODUCTS_DIR}/SnapKit/SnapKit.framework
${BUILT_PRODUCTS_DIR}/Swarm/Swarm.framework
......
......@@ -18,6 +18,7 @@ ${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/MoEngage.framework
${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/MoEngageCore.framework
${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/MOAnalytics.framework
${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/MOMessaging.framework
${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/PKHUD.framework
${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/FBLPromises.framework
${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/SnapKit.framework
${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/Swarm.framework
......
......@@ -19,6 +19,7 @@ ${PODS_ROOT}/MoEngage-iOS-SDK/Frameworks/MoEngage.framework
${PODS_ROOT}/MoEngage-iOS-SDK/Frameworks/MoEngageCore.framework
${PODS_ROOT}/MoEngage-iOS-SDK/Frameworks/MOAnalytics.framework
${PODS_ROOT}/MoEngage-iOS-SDK/Frameworks/MOMessaging.framework
${BUILT_PRODUCTS_DIR}/PKHUD/PKHUD.framework
${BUILT_PRODUCTS_DIR}/PromisesObjC/FBLPromises.framework
${BUILT_PRODUCTS_DIR}/SnapKit/SnapKit.framework
${BUILT_PRODUCTS_DIR}/Swarm/Swarm.framework
......
......@@ -18,6 +18,7 @@ ${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/MoEngage.framework
${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/MoEngageCore.framework
${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/MOAnalytics.framework
${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/MOMessaging.framework
${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/PKHUD.framework
${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/FBLPromises.framework
${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/SnapKit.framework
${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/Swarm.framework
......
......@@ -195,6 +195,7 @@ if [[ "$CONFIGURATION" == "Debug" ]]; then
install_framework "${PODS_ROOT}/MoEngage-iOS-SDK/Frameworks/MoEngageCore.framework"
install_framework "${PODS_ROOT}/MoEngage-iOS-SDK/Frameworks/MOAnalytics.framework"
install_framework "${PODS_ROOT}/MoEngage-iOS-SDK/Frameworks/MOMessaging.framework"
install_framework "${BUILT_PRODUCTS_DIR}/PKHUD/PKHUD.framework"
install_framework "${BUILT_PRODUCTS_DIR}/PromisesObjC/FBLPromises.framework"
install_framework "${BUILT_PRODUCTS_DIR}/SnapKit/SnapKit.framework"
install_framework "${BUILT_PRODUCTS_DIR}/Swarm/Swarm.framework"
......@@ -224,6 +225,7 @@ if [[ "$CONFIGURATION" == "Release" ]]; then
install_framework "${PODS_ROOT}/MoEngage-iOS-SDK/Frameworks/MoEngageCore.framework"
install_framework "${PODS_ROOT}/MoEngage-iOS-SDK/Frameworks/MOAnalytics.framework"
install_framework "${PODS_ROOT}/MoEngage-iOS-SDK/Frameworks/MOMessaging.framework"
install_framework "${BUILT_PRODUCTS_DIR}/PKHUD/PKHUD.framework"
install_framework "${BUILT_PRODUCTS_DIR}/PromisesObjC/FBLPromises.framework"
install_framework "${BUILT_PRODUCTS_DIR}/SnapKit/SnapKit.framework"
install_framework "${BUILT_PRODUCTS_DIR}/Swarm/Swarm.framework"
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment