Skip to content

Commit

Permalink
Merge pull request #15 from hootsuite/artem/IOS-7181
Browse files Browse the repository at this point in the history
IOS-7181 Add ability to use framework in app extensions
  • Loading branch information
artem-goryaev-hs committed Mar 14, 2017
2 parents 9cffc9c + ef6f142 commit 254f4d1
Show file tree
Hide file tree
Showing 9 changed files with 322 additions and 7 deletions.
6 changes: 6 additions & 0 deletions OwlBanners.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,15 @@
objects = {

/* Begin PBXBuildFile section */
A09D91D41E7775A800FA27F3 /* ApplicationContext.swift in Sources */ = {isa = PBXBuildFile; fileRef = A09D91D31E7775A800FA27F3 /* ApplicationContext.swift */; };
A88E55E41DE3B66F00DA5F42 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = A88E55E31DE3B66F00DA5F42 /* Assets.xcassets */; };
AF6DE9821BC70D2A0001598E /* Banner.swift in Sources */ = {isa = PBXBuildFile; fileRef = AF6DE97F1BC70D2A0001598E /* Banner.swift */; };
AF6DE9831BC70D2A0001598E /* DefaultBannerView.swift in Sources */ = {isa = PBXBuildFile; fileRef = AF6DE9801BC70D2A0001598E /* DefaultBannerView.swift */; };
AF6DE9841BC70D2A0001598E /* DefaultBannerView.xib in Resources */ = {isa = PBXBuildFile; fileRef = AF6DE9811BC70D2A0001598E /* DefaultBannerView.xib */; };
/* End PBXBuildFile section */

/* Begin PBXFileReference section */
A09D91D31E7775A800FA27F3 /* ApplicationContext.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ApplicationContext.swift; sourceTree = "<group>"; };
A88E55E31DE3B66F00DA5F42 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
A8B767881E5B999F006A2670 /* LICENSE.md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; path = LICENSE.md; sourceTree = "<group>"; };
A8B767891E5B999F006A2670 /* README.md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; path = README.md; sourceTree = "<group>"; };
Expand Down Expand Up @@ -56,6 +58,7 @@
AF6DE9351BC70CB40001598E /* OwlBanners */ = {
isa = PBXGroup;
children = (
A09D91D31E7775A800FA27F3 /* ApplicationContext.swift */,
AF6DE97F1BC70D2A0001598E /* Banner.swift */,
AF6DE9801BC70D2A0001598E /* DefaultBannerView.swift */,
AF6DE9811BC70D2A0001598E /* DefaultBannerView.xib */,
Expand Down Expand Up @@ -164,6 +167,7 @@
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
A09D91D41E7775A800FA27F3 /* ApplicationContext.swift in Sources */,
AF6DE9831BC70D2A0001598E /* DefaultBannerView.swift in Sources */,
AF6DE9821BC70D2A0001598E /* Banner.swift in Sources */,
);
Expand Down Expand Up @@ -269,6 +273,7 @@
AF6DE93C1BC70CB40001598E /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
APPLICATION_EXTENSION_API_ONLY = YES;
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "";
CURRENT_PROJECT_VERSION = 1;
DEFINES_MODULE = YES;
Expand All @@ -290,6 +295,7 @@
AF6DE93D1BC70CB40001598E /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
APPLICATION_EXTENSION_API_ONLY = YES;
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "";
CURRENT_PROJECT_VERSION = 1;
DEFINES_MODULE = YES;
Expand Down
20 changes: 20 additions & 0 deletions OwlBanners/ApplicationContext.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
// Copyright 2017 HootSuite Media Inc.
//
// This file is part of OwlBanners. The full OwlBanners copyright notice,
// including terms governing use, modification, and redistribution, is
// contained in the file LICENSE.md at the root of the source code distribution
// tree.

import UIKit

/// Protocol that proxies required information for the banner to appear. These properties are present in `UIApplication`
/// but in case when the framework is used within an app extension you will need to provide custom object that conforms
/// to this protocol. See `OwlBannerDemo` app and `OwlBannerShareDemo` app extension for example usage.
@objc public protocol ApplicationContext {

var keyWindow: UIWindow? { get }
var statusBarFrame: CGRect { get }
var preferredContentSizeCategory: UIContentSizeCategory { get }
var statusBarStyle: UIStatusBarStyle { get set }

}
28 changes: 22 additions & 6 deletions OwlBanners/Banner.swift
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,10 @@ open class Banner: NSObject {
/// Determines whether the banner requires the user to dismiss it.
open var requiresUserDismissal = false

/// Application proxy that enables the access to required `UIApplication` methods and properties. It used instead of
/// directly accessing the `UIApplication.shared` to be able to use the framework in app extensions.
static open var application: ApplicationContext?

// MARK: Private Properties

fileprivate let style: BannerStyle
Expand All @@ -98,7 +102,7 @@ open class Banner: NSObject {
}

fileprivate var keyWindow: UIWindow? {
return UIApplication.shared.keyWindow
return Banner.application?.keyWindow
}

fileprivate var topConstraint: NSLayoutConstraint?
Expand All @@ -108,7 +112,12 @@ open class Banner: NSObject {
}

fileprivate var topConstraintConstantWhenDisplayed: CGFloat {
return -style.bannerConfiguration.bufferHeight + UIApplication.shared.statusBarFrame.size.height
guard let application = Banner.application else {
printApplicationError()
return -style.bannerConfiguration.bufferHeight
}

return -style.bannerConfiguration.bufferHeight + application.statusBarFrame.size.height
}

// MARK: Initializers
Expand Down Expand Up @@ -166,6 +175,7 @@ open class Banner: NSObject {
guard let keyWindow = keyWindow else {
return
}

keyWindow.addSubview(bannerView)
bannerView.translatesAutoresizingMaskIntoConstraints = false

Expand Down Expand Up @@ -195,9 +205,11 @@ open class Banner: NSObject {
fileprivate func present() {
bannerView.superview?.layoutIfNeeded()

currentStatusBarStyle = UIApplication.shared.statusBarStyle
if let statusBarStyle = style.bannerConfiguration.preferredStatusBarStyle {
UIApplication.shared.statusBarStyle = statusBarStyle
if let statusBarStyle = Banner.application?.statusBarStyle {
currentStatusBarStyle = statusBarStyle
if let preferredStatusBarStyle = style.bannerConfiguration.preferredStatusBarStyle {
Banner.application?.statusBarStyle = preferredStatusBarStyle
}
}

UIView.animate(withDuration: displayMetrics.presentDuration, delay: 0, usingSpringWithDamping: Constants.presentAnimationDamping,
Expand Down Expand Up @@ -229,7 +241,7 @@ open class Banner: NSObject {
return
}
isDismissing = true
UIApplication.shared.statusBarStyle = currentStatusBarStyle
Banner.application?.statusBarStyle = currentStatusBarStyle

UIView.animate(withDuration: displayMetrics.dismissDuration, delay: 0, usingSpringWithDamping: Constants.dismissAnimationDamping,
initialSpringVelocity: Constants.dismissAnimationVelocity,
Expand All @@ -252,6 +264,10 @@ open class Banner: NSObject {
return false
}

fileprivate func printApplicationError() {
print("Error - Application not found. Make sure you set `Banner.application` property before presenting a banner.")
}

// MARK: User Actions

@objc fileprivate func bannerDismissed(_ sender: AnyObject?) {
Expand Down
2 changes: 1 addition & 1 deletion OwlBanners/DefaultBannerView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ class DefaultBannerView: UIView, BannerView {

override func awakeFromNib() {
super.awakeFromNib()
let contentSize = UIApplication.shared.preferredContentSizeCategory
let contentSize = Banner.application?.preferredContentSizeCategory ?? .medium
let descriptor = UIFontDescriptor.preferredFontDescriptor(withTextStyle: UIFontTextStyle.body)
titleLabel.font = UIFont(descriptor: descriptor.withSize(DefaultBannerView.fontSizes[contentSize] ?? 17), size: 0)
}
Expand Down
Loading

0 comments on commit 254f4d1

Please sign in to comment.