Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions Podyfied/SnowGlobe/Pod/Classes/Numbers+Extentios.swift
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,13 @@

import Foundation

protocol Summable { func +(lhs: Self, rhs: Self) -> Self }
protocol Multiplicable { func *(lhs: Self, rhs: Self) -> Self }
protocol Summable { static func +(lhs: Self, rhs: Self) -> Self }
protocol Multiplicable { static func *(lhs: Self, rhs: Self) -> Self }

extension Int: Summable, Multiplicable {}
extension Double: Summable, Multiplicable {}
extension Float: Summable, Multiplicable {}

func sq<T: Multiplicable>(x: T) -> T {
func sq<T: Multiplicable>(_ x: T) -> T {
return x * x
}
104 changes: 48 additions & 56 deletions Podyfied/SnowGlobe/Pod/Classes/SnowGlobeView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import AudioToolbox

private let lifetimeKey = "lifetime"

public class SnowGlobeView: UIView {
open class SnowGlobeView: UIView {

//MARK: - Initializers

Expand All @@ -31,7 +31,7 @@ public class SnowGlobeView: UIView {
When true, Creates CMMotionManager, monitors accelerometer and starts emitting snow flakes upon shaking.
When set to flase emits snow flakes upon view's appearance on screen.
*/
public var shakeToSnow: Bool = false {
open var shakeToSnow: Bool = false {
didSet {
if oldValue != shakeToSnow {
shouldShakeToSnow(shakeToSnow)
Expand All @@ -40,7 +40,7 @@ public class SnowGlobeView: UIView {
}

/// When set to true snow fall is ligther, less dense.
public var lighterSnowMode: Bool = false {
open var lighterSnowMode: Bool = false {
didSet {
if (oldValue != lighterSnowMode) {
emitterCell = SnowGlobeView.newEmitterCell(lighterSnowMode, image: snowFlakeImage)
Expand All @@ -50,10 +50,10 @@ public class SnowGlobeView: UIView {
}

/// Snow flake image, recomended size 74 X 74 pixels @2x.
public var snowFlakeImage: UIImage? {
open var snowFlakeImage: UIImage? {
get {
if let image: AnyObject = emitterCell.contents {
return UIImage(CGImage: image as! CGImage)
if let image: Any = emitterCell.contents {
return UIImage(cgImage: image as! CGImage)
}
return nil
}
Expand All @@ -63,18 +63,18 @@ public class SnowGlobeView: UIView {
}
}

public var soundEffectsEnabled: Bool = true
open var soundEffectsEnabled: Bool = true

/// default ligth snow flake image
public class func lightSnowFlakeImage() -> (UIImage?) {
open class func lightSnowFlakeImage() -> (UIImage?) {
if let image = UIImage(named: "flake") {
return image;
}
return SnowGlobeView.frameworkImage(named: "flake@2x")
}

/// default dark snow flake image
public class func darkSnowFlakeImage() -> (UIImage?) {
open class func darkSnowFlakeImage() -> (UIImage?) {
if let image = UIImage(named: "flake2") {
return image;
}
Expand All @@ -83,18 +83,18 @@ public class SnowGlobeView: UIView {

//MARK: -

public override class func layerClass() -> AnyClass {
open override class var layerClass: AnyClass {
return CAEmitterLayer.self
}

public override func layoutSubviews() {
open override func layoutSubviews() {
super.layoutSubviews()
emitter.emitterSize = CGSizeMake(bounds.size.width, bounds.size.height)
emitter.position = CGPointMake(bounds.size.width, bounds.size.height / 2)
emitter.emitterSize = CGSize(width: bounds.size.width, height: bounds.size.height)
emitter.position = CGPoint(x: bounds.size.width, y: bounds.size.height / 2)
}

public override func willMoveToWindow(newWindow: UIWindow?) {
super.willMoveToWindow(newWindow)
open override func willMove(toWindow newWindow: UIWindow?) {
super.willMove(toWindow: newWindow)
if newWindow != nil && shakeToSnow == false && isAnimating == false {
startAnimating()
} else {
Expand All @@ -112,91 +112,91 @@ public class SnowGlobeView: UIView {
/**
Animates emitter's lifetime property to 1, causing emitter to start emitting
*/
public func startAnimating () {
func startAnimating () {
playSoundIfNeeded()
let animDuration = 0.1
let anim = CABasicAnimation(keyPath: lifetimeKey)
anim.fromValue = emitter.presentationLayer()?.lifetime
anim.fromValue = emitter.presentation()?.lifetime
anim.toValue = 1
anim.setValue(animDuration, forKeyPath: "duration")
emitter.removeAnimationForKey(lifetimeKey)
emitter.addAnimation(anim, forKey: lifetimeKey)
emitter.removeAnimation(forKey: lifetimeKey)
emitter.add(anim, forKey: lifetimeKey)
emitter.lifetime = 1
}

/**
Animates emitter's lifetime property to 0, causing emitter to stop emitting
*/
public func stopAnimating () {
if emitter.presentationLayer() == nil {
func stopAnimating () {
if emitter.presentation() == nil {
return
}
let animDuration = 4.0
let anim = CAKeyframeAnimation(keyPath: lifetimeKey)
anim.values = [emitter.presentationLayer()!.lifetime, emitter.presentationLayer()!.lifetime, 0.0]
anim.values = [emitter.presentation()!.lifetime, emitter.presentation()!.lifetime, 0.0]
anim.keyTimes = [0.0, 0.5, 1.0]
anim.setValue(animDuration, forKeyPath: "duration")
emitter.addAnimation(anim, forKey: lifetimeKey)
emitter.add(anim, forKey: lifetimeKey)
emitter.lifetime = 0.0
dispatch_after( dispatch_time( DISPATCH_TIME_NOW, Int64(animDuration * Double(NSEC_PER_SEC))),dispatch_get_main_queue(), {[weak self] ()->() in
DispatchQueue.main.asyncAfter( deadline: DispatchTime.now() + Double(Int64(animDuration * Double(NSEC_PER_SEC))) / Double(NSEC_PER_SEC), execute: {[weak self] ()->() in
self?.shouldPlaySound = true
})

}

/// Queue that recieves accelerometer updates from CMMotionManager
private lazy var queue = NSOperationQueue()
private lazy var emitterCell: CAEmitterCell = SnowGlobeView.newEmitterCell()
private var emitter: CAEmitterLayer { get { return layer as! CAEmitterLayer } }
public var isAnimating : Bool {
fileprivate lazy var queue = OperationQueue()
fileprivate lazy var emitterCell: CAEmitterCell = SnowGlobeView.newEmitterCell()
fileprivate var emitter: CAEmitterLayer { get { return layer as! CAEmitterLayer } }
fileprivate var isAnimating : Bool {
get { return self.emitter.lifetime == 1.0 }
}

private func initialSetup() {
backgroundColor = UIColor.clearColor()
autoresizingMask = [UIViewAutoresizing.FlexibleWidth, UIViewAutoresizing.FlexibleHeight]
userInteractionEnabled = false
fileprivate func initialSetup() {
backgroundColor = UIColor.clear
autoresizingMask = [UIViewAutoresizing.flexibleWidth, UIViewAutoresizing.flexibleHeight]
isUserInteractionEnabled = false
emitter.emitterCells = [emitterCell]
emitter.emitterShape = kCAEmitterLayerLine
emitter.renderMode = kCAEmitterLayerOldestLast
emitter.lifetime = 0
}

private func shouldShakeToSnow(shakeToSnow: Bool) {
fileprivate func shouldShakeToSnow(_ shakeToSnow: Bool) {
let motionManager = CMMotionManager.sharedManager
motionManager.accelerometerUpdateInterval = 0.15
if motionManager.accelerometerActive || !shakeToSnow {
if motionManager.isAccelerometerActive || !shakeToSnow {
motionManager.stopAccelerometerUpdates()
}
motionManager.startAccelerometerUpdatesToQueue(queue) { [weak self] accelerometerData, error in
motionManager.startAccelerometerUpdates(to: queue) { [weak self] accelerometerData, error in
let data = accelerometerData!.acceleration
var magnitude = sqrt( sq(data.x) + sq(data.y) + sq(data.z) )
magnitude = (magnitude < 3.0) ? 0.0 : magnitude
if (magnitude == 0.0 && self?.isAnimating == false) {
return
}
if let welf = self {
dispatch_async(dispatch_get_main_queue()) { welf.animate(toLifetime: magnitude) }
DispatchQueue.main.async { welf.animate(toLifetime: magnitude) }
}
}
}

private func animate(toLifetime rate:Double) {
fileprivate func animate(toLifetime rate:Double) {
if rate <= 0.0 && self.emitter.lifetime != 0.0 {
stopAnimating()
} else if rate > 0.0 && isAnimating == false {
startAnimating()
}
}

private class func newEmitterCell(slowSnow:Bool = false, image: UIImage? = nil) -> CAEmitterCell {
fileprivate class func newEmitterCell(_ slowSnow:Bool = false, image: UIImage? = nil) -> CAEmitterCell {
let cell = CAEmitterCell()
var currentImage = image
if currentImage == nil {
currentImage = SnowGlobeView.lightSnowFlakeImage()
}

cell.contents = currentImage?.CGImage
cell.contents = currentImage?.cgImage
cell.birthRate = 60
cell.lifetime = 25
cell.scale = 0.2
Expand All @@ -215,38 +215,30 @@ public class SnowGlobeView: UIView {

class func frameworkImage(named name: String?) -> (UIImage? ) {
var image: UIImage? = nil
let frameworkBundle = NSBundle(identifier: "uk.co.stringCode.SnowGlobe")
if let imagePath = frameworkBundle?.pathForResource(name, ofType: "png") {
let frameworkBundle = Bundle(identifier: "uk.co.stringCode.SnowGlobe")
if let imagePath = frameworkBundle?.path(forResource: name, ofType: "png") {
image = UIImage(contentsOfFile: imagePath)
} else if let cocoaPodBundlePath = NSBundle(forClass: SnowGlobeView.self).pathForResource("SnowGlobe", ofType: "bundle") {
if let imagePath = NSBundle(path: cocoaPodBundlePath)?.pathForResource(name, ofType: "png") {
image = UIImage(contentsOfFile: imagePath)
}
}
return image
}

//MARK: Sound effects

private var shouldPlaySound:Bool = true
fileprivate var shouldPlaySound:Bool = true

private func playSoundIfNeeded() {
fileprivate func playSoundIfNeeded() {
if shouldPlaySound && soundEffectsEnabled {
shouldPlaySound = false
AudioServicesPlaySystemSound(sleighBellsSoundId);
}
}

private lazy var sleighBellsSoundId: SystemSoundID = {
fileprivate lazy var sleighBellsSoundId: SystemSoundID = {
var soundId: SystemSoundID = 0
if let url = NSBundle.mainBundle().URLForResource("SleighBells", withExtension: "mp3") {
AudioServicesCreateSystemSoundID(url, &soundId)
} else if let url = NSBundle(identifier: "uk.co.stringCode.SnowGlobe")?.URLForResource("SleighBells", withExtension: "mp3") {
AudioServicesCreateSystemSoundID(url, &soundId)
} else if let cocoaPodBundlePath = NSBundle(forClass: SnowGlobeView.self).pathForResource("SnowGlobe", ofType: "bundle") {
if let url = NSBundle(path: cocoaPodBundlePath)?.URLForResource("SleighBells", withExtension: "mp3") {
AudioServicesCreateSystemSoundID(url, &soundId)
}
if let url = Bundle.main.url(forResource: "SleighBells", withExtension: "mp3") {
AudioServicesCreateSystemSoundID(url as CFURL, &soundId)
} else if let url = Bundle(identifier: "uk.co.stringCode.SnowGlobe")?.url(forResource: "SleighBells", withExtension: "mp3") {
AudioServicesCreateSystemSoundID(url as CFURL, &soundId)
}
return soundId
}()
Expand Down
File renamed without changes.
17 changes: 16 additions & 1 deletion SnowGlobe/SnowGlobe.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -186,14 +186,16 @@
attributes = {
LastSwiftMigration = 0710;
LastSwiftUpdateCheck = 0710;
LastUpgradeCheck = 0710;
LastUpgradeCheck = 0800;
ORGANIZATIONNAME = stringCode;
TargetAttributes = {
9FDC70BB1A2FBFAB0033F371 = {
CreatedOnToolsVersion = 6.1.1;
LastSwiftMigration = 0800;
};
9FDC70C61A2FBFAB0033F371 = {
CreatedOnToolsVersion = 6.1.1;
LastSwiftMigration = 0800;
};
};
};
Expand Down Expand Up @@ -278,8 +280,10 @@
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INFINITE_RECURSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_SUSPICIOUS_MOVE = YES;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
Expand All @@ -289,6 +293,7 @@
ENABLE_TESTABILITY = YES;
GCC_C_LANGUAGE_STANDARD = gnu99;
GCC_DYNAMIC_NO_PIC = NO;
GCC_NO_COMMON_BLOCKS = YES;
GCC_OPTIMIZATION_LEVEL = 0;
GCC_PREPROCESSOR_DEFINITIONS = (
"DEBUG=1",
Expand Down Expand Up @@ -325,8 +330,10 @@
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INFINITE_RECURSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_SUSPICIOUS_MOVE = YES;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
Expand All @@ -335,6 +342,7 @@
ENABLE_NS_ASSERTIONS = NO;
ENABLE_STRICT_OBJC_MSGSEND = YES;
GCC_C_LANGUAGE_STANDARD = gnu99;
GCC_NO_COMMON_BLOCKS = YES;
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
GCC_WARN_UNDECLARED_SELECTOR = YES;
Expand All @@ -344,6 +352,7 @@
IPHONEOS_DEPLOYMENT_TARGET = 8.1;
MTL_ENABLE_DEBUG_INFO = NO;
SDKROOT = iphoneos;
SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule";
TARGETED_DEVICE_FAMILY = "1,2";
VALIDATE_PRODUCT = YES;
VERSIONING_SYSTEM = "apple-generic";
Expand All @@ -355,6 +364,7 @@
isa = XCBuildConfiguration;
buildSettings = {
CODE_SIGN_IDENTITY = "iPhone Developer";
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "";
DEFINES_MODULE = YES;
DYLIB_COMPATIBILITY_VERSION = 1;
DYLIB_CURRENT_VERSION = 1;
Expand All @@ -366,13 +376,15 @@
PRODUCT_BUNDLE_IDENTIFIER = "uk.co.stringCode.$(PRODUCT_NAME:rfc1034identifier)";
PRODUCT_NAME = "$(TARGET_NAME)";
SKIP_INSTALL = YES;
SWIFT_VERSION = 3.0;
};
name = Debug;
};
9FDC70D41A2FBFAB0033F371 /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
CODE_SIGN_IDENTITY = "iPhone Developer";
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "";
DEFINES_MODULE = YES;
DYLIB_COMPATIBILITY_VERSION = 1;
DYLIB_CURRENT_VERSION = 1;
Expand All @@ -383,6 +395,7 @@
PRODUCT_BUNDLE_IDENTIFIER = "uk.co.stringCode.$(PRODUCT_NAME:rfc1034identifier)";
PRODUCT_NAME = "$(TARGET_NAME)";
SKIP_INSTALL = YES;
SWIFT_VERSION = 3.0;
};
name = Release;
};
Expand All @@ -398,6 +411,7 @@
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
PRODUCT_BUNDLE_IDENTIFIER = "uk.co.stringCode.$(PRODUCT_NAME:rfc1034identifier)";
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_VERSION = 3.0;
};
name = Debug;
};
Expand All @@ -409,6 +423,7 @@
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
PRODUCT_BUNDLE_IDENTIFIER = "uk.co.stringCode.$(PRODUCT_NAME:rfc1034identifier)";
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_VERSION = 3.0;
};
name = Release;
};
Expand Down
6 changes: 3 additions & 3 deletions SnowGlobe/SnowGlobe/Numbers+Extentios.swift
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,13 @@

import Foundation

protocol Summable { func +(lhs: Self, rhs: Self) -> Self }
protocol Multiplicable { func *(lhs: Self, rhs: Self) -> Self }
protocol Summable { static func +(lhs: Self, rhs: Self) -> Self }
protocol Multiplicable { static func *(lhs: Self, rhs: Self) -> Self }

extension Int: Summable, Multiplicable {}
extension Double: Summable, Multiplicable {}
extension Float: Summable, Multiplicable {}

func sq<T: Multiplicable>(x: T) -> T {
func sq<T: Multiplicable>(_ x: T) -> T {
return x * x
}
Loading