27 changed files with 4323 additions and 186 deletions
-
74kplayer.xcodeproj/project.pbxproj
-
13kplayer/AppDelegate.swift
-
2kplayer/Base.lproj/Main.storyboard
-
28kplayer/core/MediaItem.swift
-
128kplayer/core/NetworkManager.swift
-
116kplayer/detail/DetailViewController.swift
-
5kplayer/detail/ItemCell.swift
-
5kplayer/detail/VideoPlayerController.swift
-
1419kplayer/exswift/Array.swift
-
18kplayer/exswift/Bool.swift
-
21kplayer/exswift/Character.swift
-
421kplayer/exswift/Dictionary.swift
-
93kplayer/exswift/Double.swift
-
19kplayer/exswift/ExSwift.h
-
282kplayer/exswift/ExSwift.swift
-
83kplayer/exswift/Float.swift
-
256kplayer/exswift/Int.swift
-
64kplayer/exswift/NSArray.swift
-
318kplayer/exswift/NSDate.swift
-
80kplayer/exswift/Range.swift
-
244kplayer/exswift/Sequence.swift
-
403kplayer/exswift/String.swift
-
108kplayer/master/MasterViewController.swift
-
203kplayer/photo/MediaPhotoController.swift
-
32kplayer/util/HanekeFetchOperation.swift
-
46kplayer/util/ImageLoadOperation.swift
-
28kplayer/util/alamoimage.swift
1419
kplayer/exswift/Array.swift
File diff suppressed because it is too large
View File
File diff suppressed because it is too large
View File
@ -0,0 +1,18 @@ |
|||||
|
// |
||||
|
// Bool.swift |
||||
|
// ExSwift |
||||
|
// |
||||
|
// Created by Hernandez Alvarez, David on 2/10/15. |
||||
|
// Copyright (c) 2015 pNre. All rights reserved. |
||||
|
// |
||||
|
|
||||
|
import Foundation |
||||
|
|
||||
|
extension Bool { |
||||
|
|
||||
|
mutating func toggle() -> Bool { |
||||
|
self = !self |
||||
|
return self |
||||
|
} |
||||
|
|
||||
|
} |
||||
@ -0,0 +1,21 @@ |
|||||
|
// |
||||
|
// Character.swift |
||||
|
// ExSwift |
||||
|
// |
||||
|
// Created by Cenny Davidsson on 2014-12-08. |
||||
|
// Copyright (c) 2014 pNre. All rights reserved. |
||||
|
// |
||||
|
|
||||
|
import Foundation |
||||
|
|
||||
|
public extension Character { |
||||
|
|
||||
|
/** |
||||
|
If the character represents an integer that fits into an Int, returns |
||||
|
the corresponding integer. |
||||
|
*/ |
||||
|
public func toInt () -> Int? { |
||||
|
return String(self).toInt() |
||||
|
} |
||||
|
|
||||
|
} |
||||
@ -0,0 +1,421 @@ |
|||||
|
// |
||||
|
// Dictionary.swift |
||||
|
// ExSwift |
||||
|
// |
||||
|
// Created by pNre on 04/06/14. |
||||
|
// Copyright (c) 2014 pNre. All rights reserved. |
||||
|
// |
||||
|
|
||||
|
import Foundation |
||||
|
import Swift |
||||
|
|
||||
|
internal extension Dictionary { |
||||
|
|
||||
|
/** |
||||
|
Difference of self and the input dictionaries. |
||||
|
Two dictionaries are considered equal if they contain the same [key: value] pairs. |
||||
|
|
||||
|
:param: dictionaries Dictionaries to subtract |
||||
|
:returns: Difference of self and the input dictionaries |
||||
|
*/ |
||||
|
func difference <V: Equatable> (dictionaries: [Key: V]...) -> [Key: V] { |
||||
|
|
||||
|
var result = [Key: V]() |
||||
|
|
||||
|
each { |
||||
|
if let item = $1 as? V { |
||||
|
result[$0] = item |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
// Difference |
||||
|
for dictionary in dictionaries { |
||||
|
for (key, value) in dictionary { |
||||
|
if result.has(key) && result[key] == value { |
||||
|
result.removeValueForKey(key) |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
return result |
||||
|
|
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
Union of self and the input dictionaries. |
||||
|
|
||||
|
:param: dictionaries Dictionaries to join |
||||
|
:returns: Union of self and the input dictionaries |
||||
|
*/ |
||||
|
func union (dictionaries: Dictionary...) -> Dictionary { |
||||
|
|
||||
|
var result = self |
||||
|
|
||||
|
dictionaries.each { (dictionary) -> Void in |
||||
|
dictionary.each { (key, value) -> Void in |
||||
|
_ = result.updateValue(value, forKey: key) |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
return result |
||||
|
|
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
Intersection of self and the input dictionaries. |
||||
|
Two dictionaries are considered equal if they contain the same [key: value] copules. |
||||
|
|
||||
|
:param: values Dictionaries to intersect |
||||
|
:returns: Dictionary of [key: value] couples contained in all the dictionaries and self |
||||
|
*/ |
||||
|
func intersection <K, V where K: Equatable, V: Equatable> (dictionaries: [K: V]...) -> [K: V] { |
||||
|
|
||||
|
// Casts self from [Key: Value] to [K: V] |
||||
|
let filtered = mapFilter { (item, value) -> (K, V)? in |
||||
|
if (item is K) && (value is V) { |
||||
|
return (item as! K, value as! V) |
||||
|
} |
||||
|
|
||||
|
return nil |
||||
|
} |
||||
|
|
||||
|
// Intersection |
||||
|
return filtered.filter({ (key: K, value: V) -> Bool in |
||||
|
// check for [key: value] in all the dictionaries |
||||
|
dictionaries.all { $0.has(key) && $0[key] == value } |
||||
|
}) |
||||
|
|
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
Checks if a key exists in the dictionary. |
||||
|
|
||||
|
:param: key Key to check |
||||
|
:returns: true if the key exists |
||||
|
*/ |
||||
|
func has (key: Key) -> Bool { |
||||
|
return indexForKey(key) != nil |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
Creates an Array with values generated by running |
||||
|
each [key: value] of self through the mapFunction. |
||||
|
|
||||
|
:param: mapFunction |
||||
|
:returns: Mapped array |
||||
|
*/ |
||||
|
func toArray <V> (map: (Key, Value) -> V) -> [V] { |
||||
|
|
||||
|
var mapped = [V]() |
||||
|
|
||||
|
each { |
||||
|
mapped.append(map($0, $1)) |
||||
|
} |
||||
|
|
||||
|
return mapped |
||||
|
|
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
Creates a Dictionary with the same keys as self and values generated by running |
||||
|
each [key: value] of self through the mapFunction. |
||||
|
|
||||
|
:param: mapFunction |
||||
|
:returns: Mapped dictionary |
||||
|
*/ |
||||
|
func mapValues <V> (map: (Key, Value) -> V) -> [Key: V] { |
||||
|
|
||||
|
var mapped = [Key: V]() |
||||
|
|
||||
|
each { |
||||
|
mapped[$0] = map($0, $1) |
||||
|
} |
||||
|
|
||||
|
return mapped |
||||
|
|
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
Creates a Dictionary with the same keys as self and values generated by running |
||||
|
each [key: value] of self through the mapFunction discarding nil return values. |
||||
|
|
||||
|
:param: mapFunction |
||||
|
:returns: Mapped dictionary |
||||
|
*/ |
||||
|
func mapFilterValues <V> (map: (Key, Value) -> V?) -> [Key: V] { |
||||
|
|
||||
|
var mapped = [Key: V]() |
||||
|
|
||||
|
each { |
||||
|
if let value = map($0, $1) { |
||||
|
mapped[$0] = value |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
return mapped |
||||
|
|
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
Creates a Dictionary with keys and values generated by running |
||||
|
each [key: value] of self through the mapFunction discarding nil return values. |
||||
|
|
||||
|
:param: mapFunction |
||||
|
:returns: Mapped dictionary |
||||
|
*/ |
||||
|
func mapFilter <K, V> (map: (Key, Value) -> (K, V)?) -> [K: V] { |
||||
|
|
||||
|
var mapped = [K: V]() |
||||
|
|
||||
|
each { |
||||
|
if let value = map($0, $1) { |
||||
|
mapped[value.0] = value.1 |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
return mapped |
||||
|
|
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
Creates a Dictionary with keys and values generated by running |
||||
|
each [key: value] of self through the mapFunction. |
||||
|
|
||||
|
:param: mapFunction |
||||
|
:returns: Mapped dictionary |
||||
|
*/ |
||||
|
func map <K, V> (map: (Key, Value) -> (K, V)) -> [K: V] { |
||||
|
|
||||
|
var mapped = [K: V]() |
||||
|
|
||||
|
self.each({ |
||||
|
let (_key, _value) = map($0, $1) |
||||
|
mapped[_key] = _value |
||||
|
}) |
||||
|
|
||||
|
return mapped |
||||
|
|
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
Loops trough each [key: value] pair in self. |
||||
|
|
||||
|
:param: eachFunction Function to inovke on each loop |
||||
|
*/ |
||||
|
func each (each: (Key, Value) -> ()) { |
||||
|
|
||||
|
for (key, value) in self { |
||||
|
each(key, value) |
||||
|
} |
||||
|
|
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
Constructs a dictionary containing every [key: value] pair from self |
||||
|
for which testFunction evaluates to true. |
||||
|
|
||||
|
:param: testFunction Function called to test each key, value |
||||
|
:returns: Filtered dictionary |
||||
|
*/ |
||||
|
func filter (test: (Key, Value) -> Bool) -> Dictionary { |
||||
|
|
||||
|
var result = Dictionary() |
||||
|
|
||||
|
for (key, value) in self { |
||||
|
if test(key, value) { |
||||
|
result[key] = value |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
return result |
||||
|
|
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
Creates a dictionary composed of keys generated from the results of |
||||
|
running each element of self through groupingFunction. The corresponding |
||||
|
value of each key is an array of the elements responsible for generating the key. |
||||
|
|
||||
|
:param: groupingFunction |
||||
|
:returns: Grouped dictionary |
||||
|
*/ |
||||
|
func groupBy <T> (group: (Key, Value) -> T) -> [T: [Value]] { |
||||
|
|
||||
|
var result = [T: [Value]]() |
||||
|
|
||||
|
for (key, value) in self { |
||||
|
|
||||
|
let groupKey = group(key, value) |
||||
|
|
||||
|
// If element has already been added to dictionary, append to it. If not, create one. |
||||
|
if result.has(groupKey) { |
||||
|
result[groupKey]! += [value] |
||||
|
} else { |
||||
|
result[groupKey] = [value] |
||||
|
} |
||||
|
|
||||
|
} |
||||
|
|
||||
|
return result |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
Similar to groupBy. Doesn't return a list of values, but the number of values for each group. |
||||
|
|
||||
|
:param: groupingFunction Function called to define the grouping key |
||||
|
:returns: Grouped dictionary |
||||
|
*/ |
||||
|
func countBy <T> (group: (Key, Value) -> (T)) -> [T: Int] { |
||||
|
|
||||
|
var result = [T: Int]() |
||||
|
|
||||
|
for (key, value) in self { |
||||
|
|
||||
|
let groupKey = group(key, value) |
||||
|
|
||||
|
// If element has already been added to dictionary, append to it. If not, create one. |
||||
|
if result.has(groupKey) { |
||||
|
result[groupKey]!++ |
||||
|
} else { |
||||
|
result[groupKey] = 1 |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
return result |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
Checks if test evaluates true for all the elements in self. |
||||
|
|
||||
|
:param: test Function to call for each element |
||||
|
:returns: true if test returns true for all the elements in self |
||||
|
*/ |
||||
|
func all (test: (Key, Value) -> (Bool)) -> Bool { |
||||
|
|
||||
|
for (key, value) in self { |
||||
|
if !test(key, value) { |
||||
|
return false |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
return true |
||||
|
|
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
Checks if test evaluates true for any element of self. |
||||
|
|
||||
|
:param: test Function to call for each element |
||||
|
:returns: true if test returns true for any element of self |
||||
|
*/ |
||||
|
func any (test: (Key, Value) -> (Bool)) -> Bool { |
||||
|
|
||||
|
for (key, value) in self { |
||||
|
if test(key, value) { |
||||
|
return true |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
return false |
||||
|
|
||||
|
} |
||||
|
|
||||
|
|
||||
|
/** |
||||
|
Returns the number of elements which meet the condition |
||||
|
|
||||
|
:param: test Function to call for each element |
||||
|
:returns: the number of elements meeting the condition |
||||
|
*/ |
||||
|
func countWhere (test: (Key, Value) -> (Bool)) -> Int { |
||||
|
|
||||
|
var result = 0 |
||||
|
|
||||
|
for (key, value) in self { |
||||
|
if test(key, value) { |
||||
|
result++ |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
return result |
||||
|
} |
||||
|
|
||||
|
|
||||
|
/** |
||||
|
Recombines the [key: value] couples in self trough combine using initial as initial value. |
||||
|
|
||||
|
:param: initial Initial value |
||||
|
:param: combine Function that reduces the dictionary |
||||
|
:returns: Resulting value |
||||
|
*/ |
||||
|
func reduce <U> (initial: U, combine: (U, Element) -> U) -> U { |
||||
|
return Swift.reduce(self, initial, combine) |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
Returns a copy of self, filtered to only have values for the whitelisted keys. |
||||
|
|
||||
|
:param: keys Whitelisted keys |
||||
|
:returns: Filtered dictionary |
||||
|
*/ |
||||
|
func pick (keys: [Key]) -> Dictionary { |
||||
|
return filter { (key: Key, _) -> Bool in |
||||
|
return keys.contains(key) |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
Returns a copy of self, filtered to only have values for the whitelisted keys. |
||||
|
|
||||
|
:param: keys Whitelisted keys |
||||
|
:returns: Filtered dictionary |
||||
|
*/ |
||||
|
func pick (keys: Key...) -> Dictionary { |
||||
|
return pick(unsafeBitCast(keys, [Key].self)) |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
Returns a copy of self, filtered to only have values for the whitelisted keys. |
||||
|
|
||||
|
:param: keys Keys to get |
||||
|
:returns: Dictionary with the given keys |
||||
|
*/ |
||||
|
func at (keys: Key...) -> Dictionary { |
||||
|
return pick(keys) |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
Removes a (key, value) pair from self and returns it as tuple. |
||||
|
If the dictionary is empty returns nil. |
||||
|
|
||||
|
:returns: (key, value) tuple |
||||
|
*/ |
||||
|
mutating func shift () -> (Key, Value)? { |
||||
|
if let key = keys.first { |
||||
|
return (key, removeValueForKey(key)!) |
||||
|
} |
||||
|
|
||||
|
return nil |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
Difference operator |
||||
|
*/ |
||||
|
public func - <K, V: Equatable> (first: [K: V], second: [K: V]) -> [K: V] { |
||||
|
return first.difference(second) |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
Intersection operator |
||||
|
*/ |
||||
|
public func & <K, V: Equatable> (first: [K: V], second: [K: V]) -> [K: V] { |
||||
|
return first.intersection(second) |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
Union operator |
||||
|
*/ |
||||
|
public func | <K: Hashable, V> (first: [K: V], second: [K: V]) -> [K: V] { |
||||
|
return first.union(second) |
||||
|
} |
||||
@ -0,0 +1,93 @@ |
|||||
|
// |
||||
|
// Double.swift |
||||
|
// ExSwift |
||||
|
// |
||||
|
// Created by pNre on 10/07/14. |
||||
|
// Copyright (c) 2014 pNre. All rights reserved. |
||||
|
// |
||||
|
|
||||
|
import Foundation |
||||
|
|
||||
|
public extension Double { |
||||
|
|
||||
|
/** |
||||
|
Absolute value. |
||||
|
|
||||
|
:returns: fabs(self) |
||||
|
*/ |
||||
|
func abs () -> Double { |
||||
|
return Foundation.fabs(self) |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
Squared root. |
||||
|
|
||||
|
:returns: sqrt(self) |
||||
|
*/ |
||||
|
func sqrt () -> Double { |
||||
|
return Foundation.sqrt(self) |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
Rounds self to the largest integer <= self. |
||||
|
|
||||
|
:returns: floor(self) |
||||
|
*/ |
||||
|
func floor () -> Double { |
||||
|
return Foundation.floor(self) |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
Rounds self to the smallest integer >= self. |
||||
|
|
||||
|
:returns: ceil(self) |
||||
|
*/ |
||||
|
func ceil () -> Double { |
||||
|
return Foundation.ceil(self) |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
Rounds self to the nearest integer. |
||||
|
|
||||
|
:returns: round(self) |
||||
|
*/ |
||||
|
func round () -> Double { |
||||
|
return Foundation.round(self) |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
Clamps self to a specified range. |
||||
|
|
||||
|
:param: min Lower bound |
||||
|
:param: max Upper bound |
||||
|
:returns: Clamped value |
||||
|
*/ |
||||
|
func clamp (min: Double, _ max: Double) -> Double { |
||||
|
return Swift.max(min, Swift.min(max, self)) |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
Just like round(), except it supports rounding to an arbitrary number, not just 1 |
||||
|
Be careful about rounding errors |
||||
|
|
||||
|
:params: increment the increment to round to |
||||
|
*/ |
||||
|
func roundToNearest(increment: Double) -> Double { |
||||
|
let remainder = self % increment |
||||
|
return remainder < increment / 2 ? self - remainder : self - remainder + increment |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
Random double between min and max (inclusive). |
||||
|
|
||||
|
:params: min |
||||
|
:params: max |
||||
|
:returns: Random number |
||||
|
*/ |
||||
|
static func random(min: Double = 0, max: Double) -> Double { |
||||
|
let diff = max - min; |
||||
|
let rand = Double(arc4random() % (UInt32(RAND_MAX) + 1)) |
||||
|
return ((rand / Double(RAND_MAX)) * diff) + min; |
||||
|
} |
||||
|
|
||||
|
} |
||||
@ -0,0 +1,19 @@ |
|||||
|
// |
||||
|
// ExSwift.h |
||||
|
// ExSwift |
||||
|
// |
||||
|
// Created by pNre on 07/06/14. |
||||
|
// Copyright (c) 2014 pNre. All rights reserved. |
||||
|
// |
||||
|
|
||||
|
#import <Foundation/Foundation.h> |
||||
|
|
||||
|
//! Project version number for ExSwift. |
||||
|
FOUNDATION_EXPORT double ExSwiftVersionNumber; |
||||
|
|
||||
|
//! Project version string for ExSwift. |
||||
|
FOUNDATION_EXPORT const unsigned char ExSwiftVersionString[]; |
||||
|
|
||||
|
// In this header, you should import all the public headers of your framework using statements like #import <ExSwift/PublicHeader.h> |
||||
|
|
||||
|
|
||||
@ -0,0 +1,282 @@ |
|||||
|
// |
||||
|
// ExSwift.swift |
||||
|
// ExSwift |
||||
|
// |
||||
|
// Created by pNre on 07/06/14. |
||||
|
// Copyright (c) 2014 pNre. All rights reserved. |
||||
|
// |
||||
|
|
||||
|
import Foundation |
||||
|
|
||||
|
infix operator =~ {} |
||||
|
infix operator |~ {} |
||||
|
infix operator .. {} |
||||
|
infix operator <=> {} |
||||
|
|
||||
|
public typealias Ex = ExSwift |
||||
|
|
||||
|
public class ExSwift { |
||||
|
|
||||
|
/** |
||||
|
Creates a wrapper that, executes function only after being called n times. |
||||
|
|
||||
|
:param: n No. of times the wrapper has to be called before function is invoked |
||||
|
:param: function Function to wrap |
||||
|
:returns: Wrapper function |
||||
|
*/ |
||||
|
public class func after <P, T> (n: Int, function: (P...) -> T) -> ((P...) -> T?) { |
||||
|
|
||||
|
typealias Function = [P] -> T |
||||
|
|
||||
|
var times = n |
||||
|
|
||||
|
return { |
||||
|
(params: P...) -> T? in |
||||
|
|
||||
|
// Workaround for the now illegal (T...) type. |
||||
|
let adaptedFunction = unsafeBitCast(function, Function.self) |
||||
|
|
||||
|
if times-- <= 0 { |
||||
|
return adaptedFunction(params) |
||||
|
} |
||||
|
|
||||
|
return nil |
||||
|
} |
||||
|
|
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
Creates a wrapper that, executes function only after being called n times |
||||
|
|
||||
|
:param: n No. of times the wrapper has to be called before function is invoked |
||||
|
:param: function Function to wrap |
||||
|
:returns: Wrapper function |
||||
|
*/ |
||||
|
public class func after <T> (n: Int, function: Void -> T) -> (Void -> T?) { |
||||
|
func callAfter (args: Any?...) -> T { |
||||
|
return function() |
||||
|
} |
||||
|
|
||||
|
let f = ExSwift.after(n, function: callAfter) |
||||
|
|
||||
|
return { f([nil]) } |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
Creates a wrapper function that invokes function once. |
||||
|
Repeated calls to the wrapper function will return the value of the first call. |
||||
|
|
||||
|
:param: function Function to wrap |
||||
|
:returns: Wrapper function |
||||
|
*/ |
||||
|
public class func once <P, T> (function: (P...) -> T) -> ((P...) -> T) { |
||||
|
|
||||
|
typealias Function = [P] -> T |
||||
|
|
||||
|
var returnValue: T? = nil |
||||
|
|
||||
|
return { (params: P...) -> T in |
||||
|
|
||||
|
if returnValue != nil { |
||||
|
return returnValue! |
||||
|
} |
||||
|
|
||||
|
let adaptedFunction = unsafeBitCast(function, Function.self) |
||||
|
returnValue = adaptedFunction(params) |
||||
|
|
||||
|
return returnValue! |
||||
|
|
||||
|
} |
||||
|
|
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
Creates a wrapper function that invokes function once. |
||||
|
Repeated calls to the wrapper function will return the value of the first call. |
||||
|
|
||||
|
:param: function Function to wrap |
||||
|
:returns: Wrapper function |
||||
|
*/ |
||||
|
public class func once <T> (function: Void -> T) -> (Void -> T) { |
||||
|
let f = ExSwift.once { |
||||
|
(params: Any?...) -> T in |
||||
|
return function() |
||||
|
} |
||||
|
|
||||
|
return { f([nil]) } |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
Creates a wrapper that, when called, invokes function with any additional |
||||
|
partial arguments prepended to those provided to the new function. |
||||
|
|
||||
|
:param: function Function to wrap |
||||
|
:param: parameters Arguments to prepend |
||||
|
:returns: Wrapper function |
||||
|
*/ |
||||
|
public class func partial <P, T> (function: (P...) -> T, _ parameters: P...) -> ((P...) -> T) { |
||||
|
typealias Function = [P] -> T |
||||
|
|
||||
|
return { (params: P...) -> T in |
||||
|
let adaptedFunction = unsafeBitCast(function, Function.self) |
||||
|
return adaptedFunction(parameters + params) |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
Creates a wrapper (without any parameter) that, when called, invokes function |
||||
|
automatically passing parameters as arguments. |
||||
|
|
||||
|
:param: function Function to wrap |
||||
|
:param: parameters Arguments to pass to function |
||||
|
:returns: Wrapper function |
||||
|
*/ |
||||
|
public class func bind <P, T> (function: (P...) -> T, _ parameters: P...) -> (Void -> T) { |
||||
|
typealias Function = [P] -> T |
||||
|
|
||||
|
return { Void -> T in |
||||
|
let adaptedFunction = unsafeBitCast(function, Function.self) |
||||
|
return adaptedFunction(parameters) |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
Creates a wrapper for function that caches the result of function's invocations. |
||||
|
|
||||
|
:param: function Function with one parameter to cache |
||||
|
:returns: Wrapper function |
||||
|
*/ |
||||
|
public class func cached <P: Hashable, R> (function: P -> R) -> (P -> R) { |
||||
|
var cache = [P:R]() |
||||
|
|
||||
|
return { (param: P) -> R in |
||||
|
let key = param |
||||
|
|
||||
|
if let cachedValue = cache[key] { |
||||
|
return cachedValue |
||||
|
} else { |
||||
|
let value = function(param) |
||||
|
cache[key] = value |
||||
|
return value |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
Creates a wrapper for function that caches the result of function's invocations. |
||||
|
|
||||
|
:param: function Function to cache |
||||
|
:param: hash Parameters based hashing function that computes the key used to store each result in the cache |
||||
|
:returns: Wrapper function |
||||
|
*/ |
||||
|
public class func cached <P: Hashable, R> (function: (P...) -> R, hash: ((P...) -> P)) -> ((P...) -> R) { |
||||
|
typealias Function = [P] -> R |
||||
|
typealias Hash = [P] -> P |
||||
|
|
||||
|
var cache = [P:R]() |
||||
|
|
||||
|
return { (params: P...) -> R in |
||||
|
let adaptedFunction = unsafeBitCast(function, Function.self) |
||||
|
let adaptedHash = unsafeBitCast(hash, Hash.self) |
||||
|
|
||||
|
let key = adaptedHash(params) |
||||
|
|
||||
|
if let cachedValue = cache[key] { |
||||
|
return cachedValue |
||||
|
} else { |
||||
|
let value = adaptedFunction(params) |
||||
|
cache[key] = value |
||||
|
return value |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
Creates a wrapper for function that caches the result of function's invocations. |
||||
|
|
||||
|
:param: function Function to cache |
||||
|
:returns: Wrapper function |
||||
|
*/ |
||||
|
public class func cached <P: Hashable, R> (function: (P...) -> R) -> ((P...) -> R) { |
||||
|
return cached(function, hash: { (params: P...) -> P in return params[0] }) |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
Utility method to return an NSRegularExpression object given a pattern. |
||||
|
|
||||
|
:param: pattern Regex pattern |
||||
|
:param: ignoreCase If true the NSRegularExpression is created with the NSRegularExpressionOptions.CaseInsensitive flag |
||||
|
:returns: NSRegularExpression object |
||||
|
*/ |
||||
|
internal class func regex (pattern: String, ignoreCase: Bool = false) -> NSRegularExpression? { |
||||
|
|
||||
|
var options = NSRegularExpressionOptions.DotMatchesLineSeparators.rawValue |
||||
|
|
||||
|
if ignoreCase { |
||||
|
options = NSRegularExpressionOptions.CaseInsensitive.rawValue | options |
||||
|
} |
||||
|
|
||||
|
var error: NSError? = nil |
||||
|
let regex = NSRegularExpression(pattern: pattern, options: NSRegularExpressionOptions(rawValue: options), error: &error) |
||||
|
|
||||
|
return (error == nil) ? regex : nil |
||||
|
|
||||
|
} |
||||
|
|
||||
|
} |
||||
|
|
||||
|
func <=> <T: Comparable>(lhs: T, rhs: T) -> Int { |
||||
|
if lhs < rhs { |
||||
|
return -1 |
||||
|
} else if lhs > rhs { |
||||
|
return 1 |
||||
|
} else { |
||||
|
return 0 |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* Internal methods |
||||
|
*/ |
||||
|
extension ExSwift { |
||||
|
|
||||
|
/** |
||||
|
* Converts, if possible, and flattens an object from its Objective-C |
||||
|
* representation to the Swift one. |
||||
|
* @param object Object to convert |
||||
|
* @returns Flattenend array of converted values |
||||
|
*/ |
||||
|
internal class func bridgeObjCObject <T, S> (object: S) -> [T] { |
||||
|
var result = [T]() |
||||
|
let reflection = reflect(object) |
||||
|
|
||||
|
// object has an Objective-C type |
||||
|
if let obj = object as? T { |
||||
|
// object has type T |
||||
|
result.append(obj) |
||||
|
} else if reflection.disposition == .ObjCObject { |
||||
|
|
||||
|
var bridgedValue: T!? |
||||
|
|
||||
|
// If it is an NSArray, flattening will produce the expected result |
||||
|
if let array = object as? NSArray { |
||||
|
result += array.flatten() |
||||
|
} else if let bridged = reflection.value as? T { |
||||
|
result.append(bridged) |
||||
|
} |
||||
|
} else if reflection.disposition == .IndexContainer { |
||||
|
// object is a native Swift array |
||||
|
|
||||
|
// recursively convert each item |
||||
|
(0..<reflection.count).each { |
||||
|
let ref = reflection[$0].1 |
||||
|
|
||||
|
result += Ex.bridgeObjCObject(ref.value) |
||||
|
} |
||||
|
|
||||
|
} |
||||
|
|
||||
|
return result |
||||
|
} |
||||
|
|
||||
|
} |
||||
@ -0,0 +1,83 @@ |
|||||
|
// |
||||
|
// Float.swift |
||||
|
// ExSwift |
||||
|
// |
||||
|
// Created by pNre on 04/06/14. |
||||
|
// Copyright (c) 2014 pNre. All rights reserved. |
||||
|
// |
||||
|
|
||||
|
import Foundation |
||||
|
|
||||
|
public extension Float { |
||||
|
|
||||
|
/** |
||||
|
Absolute value. |
||||
|
|
||||
|
:returns: fabs(self) |
||||
|
*/ |
||||
|
func abs () -> Float { |
||||
|
return fabsf(self) |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
Squared root. |
||||
|
|
||||
|
:returns: sqrtf(self) |
||||
|
*/ |
||||
|
func sqrt () -> Float { |
||||
|
return sqrtf(self) |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
Rounds self to the largest integer <= self. |
||||
|
|
||||
|
:returns: floorf(self) |
||||
|
*/ |
||||
|
func floor () -> Float { |
||||
|
return floorf(self) |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
Rounds self to the smallest integer >= self. |
||||
|
|
||||
|
:returns: ceilf(self) |
||||
|
*/ |
||||
|
func ceil () -> Float { |
||||
|
return ceilf(self) |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
Rounds self to the nearest integer. |
||||
|
|
||||
|
:returns: roundf(self) |
||||
|
*/ |
||||
|
func round () -> Float { |
||||
|
return roundf(self) |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
Clamps self to a specified range. |
||||
|
|
||||
|
:param: min Lower bound |
||||
|
:param: max Upper bound |
||||
|
:returns: Clamped value |
||||
|
*/ |
||||
|
func clamp (min: Float, _ max: Float) -> Float { |
||||
|
return Swift.max(min, Swift.min(max, self)) |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
Random float between min and max (inclusive). |
||||
|
|
||||
|
:param: min |
||||
|
:param: max |
||||
|
:returns: Random number |
||||
|
*/ |
||||
|
static func random(min: Float = 0, max: Float) -> Float { |
||||
|
let diff = max - min; |
||||
|
let rand = Float(arc4random() % (UInt32(RAND_MAX) + 1)) |
||||
|
return ((rand / Float(RAND_MAX)) * diff) + min; |
||||
|
} |
||||
|
|
||||
|
} |
||||
|
|
||||
@ -0,0 +1,256 @@ |
|||||
|
// |
||||
|
// Int.swift |
||||
|
// ExSwift |
||||
|
// |
||||
|
// Created by pNre on 03/06/14. |
||||
|
// Copyright (c) 2014 pNre. All rights reserved. |
||||
|
// |
||||
|
|
||||
|
import Foundation |
||||
|
|
||||
|
public extension Int { |
||||
|
|
||||
|
/** |
||||
|
Calls function self times. |
||||
|
|
||||
|
:param: function Function to call |
||||
|
*/ |
||||
|
func times <T> (function: Void -> T) { |
||||
|
(0..<self).each { _ in function(); return } |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
Calls function self times. |
||||
|
|
||||
|
:param: function Function to call |
||||
|
*/ |
||||
|
func times (function: Void -> Void) { |
||||
|
(0..<self).each { _ in function(); return } |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
Calls function self times passing a value from 0 to self on each call. |
||||
|
|
||||
|
:param: function Function to call |
||||
|
*/ |
||||
|
func times <T> (function: (Int) -> T) { |
||||
|
(0..<self).each { index in function(index); return } |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
Checks if a number is even. |
||||
|
|
||||
|
:returns: true if self is even |
||||
|
*/ |
||||
|
func isEven () -> Bool { |
||||
|
return (self % 2) == 0 |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
Checks if a number is odd. |
||||
|
|
||||
|
:returns: true if self is odd |
||||
|
*/ |
||||
|
func isOdd () -> Bool { |
||||
|
return !isEven() |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
Iterates function, passing in integer values from self up to and including limit. |
||||
|
|
||||
|
:param: limit Last value to pass |
||||
|
:param: function Function to invoke |
||||
|
*/ |
||||
|
func upTo (limit: Int, function: (Int) -> ()) { |
||||
|
if limit < self { |
||||
|
return |
||||
|
} |
||||
|
|
||||
|
(self...limit).each(function) |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
Iterates function, passing in integer values from self down to and including limit. |
||||
|
|
||||
|
:param: limit Last value to pass |
||||
|
:param: function Function to invoke |
||||
|
*/ |
||||
|
func downTo (limit: Int, function: (Int) -> ()) { |
||||
|
if limit > self { |
||||
|
return |
||||
|
} |
||||
|
|
||||
|
Array(limit...self).reverse().each(function) |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
Clamps self to a specified range. |
||||
|
|
||||
|
:param: range Clamping range |
||||
|
:returns: Clamped value |
||||
|
*/ |
||||
|
func clamp (range: Range<Int>) -> Int { |
||||
|
return clamp(range.startIndex, range.endIndex - 1) |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
Clamps self to a specified range. |
||||
|
|
||||
|
:param: min Lower bound |
||||
|
:param: max Upper bound |
||||
|
:returns: Clamped value |
||||
|
*/ |
||||
|
func clamp (min: Int, _ max: Int) -> Int { |
||||
|
return Swift.max(min, Swift.min(max, self)) |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
Checks if self is included a specified range. |
||||
|
|
||||
|
:param: range Range |
||||
|
:param: strict If true, "<" is used for comparison |
||||
|
:returns: true if in range |
||||
|
*/ |
||||
|
func isIn (range: Range<Int>, strict: Bool = false) -> Bool { |
||||
|
if strict { |
||||
|
return range.startIndex < self && self < range.endIndex - 1 |
||||
|
} |
||||
|
|
||||
|
return range.startIndex <= self && self <= range.endIndex - 1 |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
Checks if self is included in a closed interval. |
||||
|
|
||||
|
:param: interval Interval to check |
||||
|
:returns: true if in the interval |
||||
|
*/ |
||||
|
func isIn (interval: ClosedInterval<Int>) -> Bool { |
||||
|
return interval.contains(self) |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
Checks if self is included in an half open interval. |
||||
|
|
||||
|
:param: interval Interval to check |
||||
|
:returns: true if in the interval |
||||
|
*/ |
||||
|
func isIn (interval: HalfOpenInterval<Int>) -> Bool { |
||||
|
return interval.contains(self) |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
Returns an [Int] containing the digits in self. |
||||
|
|
||||
|
:return: Array of digits |
||||
|
*/ |
||||
|
func digits () -> [Int] { |
||||
|
var result = [Int]() |
||||
|
|
||||
|
for char in String(self) { |
||||
|
let string = String(char) |
||||
|
if let toInt = string.toInt() { |
||||
|
result.append(toInt) |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
return result |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
Absolute value. |
||||
|
|
||||
|
:returns: abs(self) |
||||
|
*/ |
||||
|
func abs () -> Int { |
||||
|
return Swift.abs(self) |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
Greatest common divisor of self and n. |
||||
|
|
||||
|
:param: n |
||||
|
:returns: GCD |
||||
|
*/ |
||||
|
func gcd (n: Int) -> Int { |
||||
|
return n == 0 ? self : n.gcd(self % n) |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
Least common multiple of self and n |
||||
|
|
||||
|
:param: n |
||||
|
:returns: LCM |
||||
|
*/ |
||||
|
func lcm (n: Int) -> Int { |
||||
|
return (self * n).abs() / gcd(n) |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
Computes the factorial of self |
||||
|
|
||||
|
:returns: Factorial |
||||
|
*/ |
||||
|
func factorial () -> Int { |
||||
|
return self == 0 ? 1 : self * (self - 1).factorial() |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
Random integer between min and max (inclusive). |
||||
|
|
||||
|
:param: min Minimum value to return |
||||
|
:param: max Maximum value to return |
||||
|
:returns: Random integer |
||||
|
*/ |
||||
|
static func random(min: Int = 0, max: Int) -> Int { |
||||
|
return Int(arc4random_uniform(UInt32((max - min) + 1))) + min |
||||
|
} |
||||
|
|
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
NSTimeInterval conversion extensions |
||||
|
*/ |
||||
|
public extension Int { |
||||
|
|
||||
|
var years: NSTimeInterval { |
||||
|
return 365 * self.days |
||||
|
} |
||||
|
|
||||
|
var year: NSTimeInterval { |
||||
|
return self.years |
||||
|
} |
||||
|
|
||||
|
var days: NSTimeInterval { |
||||
|
return 24 * self.hours |
||||
|
} |
||||
|
|
||||
|
var day: NSTimeInterval { |
||||
|
return self.days |
||||
|
} |
||||
|
|
||||
|
var hours: NSTimeInterval { |
||||
|
return 60 * self.minutes |
||||
|
} |
||||
|
|
||||
|
var hour: NSTimeInterval { |
||||
|
return self.hours |
||||
|
} |
||||
|
|
||||
|
var minutes: NSTimeInterval { |
||||
|
return 60 * self.seconds |
||||
|
} |
||||
|
|
||||
|
var minute: NSTimeInterval { |
||||
|
return self.minutes |
||||
|
} |
||||
|
|
||||
|
var seconds: NSTimeInterval { |
||||
|
return NSTimeInterval(self) |
||||
|
} |
||||
|
|
||||
|
var second: NSTimeInterval { |
||||
|
return self.seconds |
||||
|
} |
||||
|
|
||||
|
} |
||||
@ -0,0 +1,64 @@ |
|||||
|
// |
||||
|
// NSArray.swift |
||||
|
// ExSwift |
||||
|
// |
||||
|
// Created by pNre on 10/06/14. |
||||
|
// Copyright (c) 2014 pNre. All rights reserved. |
||||
|
// |
||||
|
|
||||
|
import Foundation |
||||
|
|
||||
|
public extension NSArray { |
||||
|
|
||||
|
/** |
||||
|
Converts an NSArray object to an OutType[] array containing the items in the NSArray of type OutType. |
||||
|
|
||||
|
:returns: Array of Swift objects |
||||
|
*/ |
||||
|
func cast <OutType> () -> [OutType] { |
||||
|
var result = [OutType]() |
||||
|
|
||||
|
for item : AnyObject in self { |
||||
|
result += Ex.bridgeObjCObject(item) as [OutType] |
||||
|
} |
||||
|
|
||||
|
return result |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
Flattens a multidimensional NSArray to an OutType[] array |
||||
|
containing the items in the NSArray that can be bridged from their ObjC type to OutType. |
||||
|
|
||||
|
:returns: Flattened array |
||||
|
*/ |
||||
|
func flatten <OutType> () -> [OutType] { |
||||
|
var result = [OutType]() |
||||
|
let reflection = reflect(self) |
||||
|
|
||||
|
for i in 0..<reflection.count { |
||||
|
result += Ex.bridgeObjCObject(reflection[i].1.value) as [OutType] |
||||
|
} |
||||
|
|
||||
|
return result |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
Flattens a multidimensional NSArray to a [AnyObject]. |
||||
|
|
||||
|
:returns: Flattened array |
||||
|
*/ |
||||
|
func flattenAny () -> [AnyObject] { |
||||
|
var result = [AnyObject]() |
||||
|
|
||||
|
for item in self { |
||||
|
if let array = item as? NSArray { |
||||
|
result += array.flattenAny() |
||||
|
} else { |
||||
|
result.append(item) |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
return result |
||||
|
} |
||||
|
|
||||
|
} |
||||
@ -0,0 +1,318 @@ |
|||||
|
// |
||||
|
// File.swift |
||||
|
// ExSwift |
||||
|
// |
||||
|
// Created by Piergiuseppe Longo on 23/11/14. |
||||
|
// Copyright (c) 2014 pNre. All rights reserved. |
||||
|
// |
||||
|
|
||||
|
import Foundation |
||||
|
|
||||
|
public extension NSDate { |
||||
|
|
||||
|
// MARK: NSDate Manipulation |
||||
|
|
||||
|
/** |
||||
|
Returns a new NSDate object representing the date calculated by adding the amount specified to self date |
||||
|
|
||||
|
:param: seconds number of seconds to add |
||||
|
:param: minutes number of minutes to add |
||||
|
:param: hours number of hours to add |
||||
|
:param: days number of days to add |
||||
|
:param: weeks number of weeks to add |
||||
|
:param: months number of months to add |
||||
|
:param: years number of years to add |
||||
|
:returns: the NSDate computed |
||||
|
*/ |
||||
|
public func add(seconds: Int = 0, minutes: Int = 0, hours: Int = 0, days: Int = 0, weeks: Int = 0, months: Int = 0, years: Int = 0) -> NSDate { |
||||
|
var calendar = NSCalendar.currentCalendar() |
||||
|
|
||||
|
let version = floor(NSFoundationVersionNumber) |
||||
|
|
||||
|
if version <= NSFoundationVersionNumber10_9_2 { |
||||
|
var component = NSDateComponents() |
||||
|
component.setValue(seconds, forComponent: .CalendarUnitSecond) |
||||
|
|
||||
|
var date : NSDate! = calendar.dateByAddingComponents(component, toDate: self, options: nil)! |
||||
|
component = NSDateComponents() |
||||
|
component.setValue(minutes, forComponent: .CalendarUnitMinute) |
||||
|
date = calendar.dateByAddingComponents(component, toDate: date, options: nil)! |
||||
|
|
||||
|
component = NSDateComponents() |
||||
|
component.setValue(hours, forComponent: .CalendarUnitHour) |
||||
|
date = calendar.dateByAddingComponents(component, toDate: date, options: nil)! |
||||
|
|
||||
|
component = NSDateComponents() |
||||
|
component.setValue(days, forComponent: .CalendarUnitDay) |
||||
|
date = calendar.dateByAddingComponents(component, toDate: date, options: nil)! |
||||
|
|
||||
|
component = NSDateComponents() |
||||
|
component.setValue(weeks, forComponent: .CalendarUnitWeekOfMonth) |
||||
|
date = calendar.dateByAddingComponents(component, toDate: date, options: nil)! |
||||
|
|
||||
|
component = NSDateComponents() |
||||
|
component.setValue(months, forComponent: .CalendarUnitMonth) |
||||
|
date = calendar.dateByAddingComponents(component, toDate: date, options: nil)! |
||||
|
|
||||
|
component = NSDateComponents() |
||||
|
component.setValue(years, forComponent: .CalendarUnitYear) |
||||
|
date = calendar.dateByAddingComponents(component, toDate: date, options: nil)! |
||||
|
return date |
||||
|
} |
||||
|
|
||||
|
var date : NSDate! = calendar.dateByAddingUnit(.CalendarUnitSecond, value: seconds, toDate: self, options: nil) |
||||
|
date = calendar.dateByAddingUnit(.CalendarUnitMinute, value: minutes, toDate: date, options: nil) |
||||
|
date = calendar.dateByAddingUnit(.CalendarUnitDay, value: days, toDate: date, options: nil) |
||||
|
date = calendar.dateByAddingUnit(.CalendarUnitHour, value: hours, toDate: date, options: nil) |
||||
|
date = calendar.dateByAddingUnit(.CalendarUnitWeekOfMonth, value: weeks, toDate: date, options: nil) |
||||
|
date = calendar.dateByAddingUnit(.CalendarUnitMonth, value: months, toDate: date, options: nil) |
||||
|
date = calendar.dateByAddingUnit(.CalendarUnitYear, value: years, toDate: date, options: nil) |
||||
|
return date |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
Returns a new NSDate object representing the date calculated by adding an amount of seconds to self date |
||||
|
|
||||
|
:param: seconds number of seconds to add |
||||
|
:returns: the NSDate computed |
||||
|
*/ |
||||
|
public func addSeconds (seconds: Int) -> NSDate { |
||||
|
return add(seconds: seconds) |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
Returns a new NSDate object representing the date calculated by adding an amount of minutes to self date |
||||
|
|
||||
|
:param: minutes number of minutes to add |
||||
|
:returns: the NSDate computed |
||||
|
*/ |
||||
|
public func addMinutes (minutes: Int) -> NSDate { |
||||
|
return add(minutes: minutes) |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
Returns a new NSDate object representing the date calculated by adding an amount of hours to self date |
||||
|
|
||||
|
:param: hours number of hours to add |
||||
|
:returns: the NSDate computed |
||||
|
*/ |
||||
|
public func addHours(hours: Int) -> NSDate { |
||||
|
return add(hours: hours) |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
Returns a new NSDate object representing the date calculated by adding an amount of days to self date |
||||
|
|
||||
|
:param: days number of days to add |
||||
|
:returns: the NSDate computed |
||||
|
*/ |
||||
|
public func addDays(days: Int) -> NSDate { |
||||
|
return add(days: days) |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
Returns a new NSDate object representing the date calculated by adding an amount of weeks to self date |
||||
|
|
||||
|
:param: weeks number of weeks to add |
||||
|
:returns: the NSDate computed |
||||
|
*/ |
||||
|
public func addWeeks(weeks: Int) -> NSDate { |
||||
|
return add(weeks: weeks) |
||||
|
} |
||||
|
|
||||
|
|
||||
|
/** |
||||
|
Returns a new NSDate object representing the date calculated by adding an amount of months to self date |
||||
|
|
||||
|
:param: months number of months to add |
||||
|
:returns: the NSDate computed |
||||
|
*/ |
||||
|
|
||||
|
public func addMonths(months: Int) -> NSDate { |
||||
|
return add(months: months) |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
Returns a new NSDate object representing the date calculated by adding an amount of years to self date |
||||
|
|
||||
|
:param: years number of year to add |
||||
|
:returns: the NSDate computed |
||||
|
*/ |
||||
|
public func addYears(years: Int) -> NSDate { |
||||
|
return add(years: years) |
||||
|
} |
||||
|
|
||||
|
// MARK: Date comparison |
||||
|
|
||||
|
/** |
||||
|
Checks if self is after input NSDate |
||||
|
|
||||
|
:param: date NSDate to compare |
||||
|
:returns: True if self is after the input NSDate, false otherwise |
||||
|
*/ |
||||
|
public func isAfter(date: NSDate) -> Bool{ |
||||
|
return (self.compare(date) == NSComparisonResult.OrderedDescending) |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
Checks if self is before input NSDate |
||||
|
|
||||
|
:param: date NSDate to compare |
||||
|
:returns: True if self is before the input NSDate, false otherwise |
||||
|
*/ |
||||
|
public func isBefore(date: NSDate) -> Bool{ |
||||
|
return (self.compare(date) == NSComparisonResult.OrderedAscending) |
||||
|
} |
||||
|
|
||||
|
|
||||
|
// MARK: Getter |
||||
|
|
||||
|
/** |
||||
|
Date year |
||||
|
*/ |
||||
|
public var year : Int { |
||||
|
get { |
||||
|
return getComponent(.CalendarUnitYear) |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
Date month |
||||
|
*/ |
||||
|
public var month : Int { |
||||
|
get { |
||||
|
return getComponent(.CalendarUnitMonth) |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
Date weekday |
||||
|
*/ |
||||
|
public var weekday : Int { |
||||
|
get { |
||||
|
return getComponent(.CalendarUnitWeekday) |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
Date weekMonth |
||||
|
*/ |
||||
|
public var weekMonth : Int { |
||||
|
get { |
||||
|
return getComponent(.CalendarUnitWeekOfMonth) |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
|
||||
|
/** |
||||
|
Date days |
||||
|
*/ |
||||
|
public var days : Int { |
||||
|
get { |
||||
|
return getComponent(.CalendarUnitDay) |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
Date hours |
||||
|
*/ |
||||
|
public var hours : Int { |
||||
|
|
||||
|
get { |
||||
|
return getComponent(.CalendarUnitHour) |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
Date minuts |
||||
|
*/ |
||||
|
public var minutes : Int { |
||||
|
get { |
||||
|
return getComponent(.CalendarUnitMinute) |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
Date seconds |
||||
|
*/ |
||||
|
public var seconds : Int { |
||||
|
get { |
||||
|
return getComponent(.CalendarUnitSecond) |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
Returns the value of the NSDate component |
||||
|
|
||||
|
:param: component NSCalendarUnit |
||||
|
:returns: the value of the component |
||||
|
*/ |
||||
|
|
||||
|
public func getComponent (component : NSCalendarUnit) -> Int { |
||||
|
let calendar = NSCalendar.currentCalendar() |
||||
|
let components = calendar.components(component, fromDate: self) |
||||
|
|
||||
|
return components.valueForComponent(component) |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
extension NSDate: Strideable { |
||||
|
public func distanceTo(other: NSDate) -> NSTimeInterval { |
||||
|
return other - self |
||||
|
} |
||||
|
|
||||
|
public func advancedBy(n: NSTimeInterval) -> Self { |
||||
|
return self.dynamicType(timeIntervalSinceReferenceDate: self.timeIntervalSinceReferenceDate + n) |
||||
|
} |
||||
|
} |
||||
|
// MARK: Arithmetic |
||||
|
|
||||
|
func +(date: NSDate, timeInterval: Int) -> NSDate { |
||||
|
return date + NSTimeInterval(timeInterval) |
||||
|
} |
||||
|
|
||||
|
func -(date: NSDate, timeInterval: Int) -> NSDate { |
||||
|
return date - NSTimeInterval(timeInterval) |
||||
|
} |
||||
|
|
||||
|
func +=(inout date: NSDate, timeInterval: Int) { |
||||
|
date = date + timeInterval |
||||
|
} |
||||
|
|
||||
|
func -=(inout date: NSDate, timeInterval: Int) { |
||||
|
date = date - timeInterval |
||||
|
} |
||||
|
|
||||
|
func +(date: NSDate, timeInterval: Double) -> NSDate { |
||||
|
return date.dateByAddingTimeInterval(NSTimeInterval(timeInterval)) |
||||
|
} |
||||
|
|
||||
|
func -(date: NSDate, timeInterval: Double) -> NSDate { |
||||
|
return date.dateByAddingTimeInterval(NSTimeInterval(-timeInterval)) |
||||
|
} |
||||
|
|
||||
|
func +=(inout date: NSDate, timeInterval: Double) { |
||||
|
date = date + timeInterval |
||||
|
} |
||||
|
|
||||
|
func -=(inout date: NSDate, timeInterval: Double) { |
||||
|
date = date - timeInterval |
||||
|
} |
||||
|
|
||||
|
func -(date: NSDate, otherDate: NSDate) -> NSTimeInterval { |
||||
|
return date.timeIntervalSinceDate(otherDate) |
||||
|
} |
||||
|
|
||||
|
extension NSDate: Equatable { |
||||
|
} |
||||
|
|
||||
|
public func ==(lhs: NSDate, rhs: NSDate) -> Bool { |
||||
|
return lhs.compare(rhs) == NSComparisonResult.OrderedSame |
||||
|
} |
||||
|
|
||||
|
extension NSDate: Comparable { |
||||
|
} |
||||
|
|
||||
|
public func <(lhs: NSDate, rhs: NSDate) -> Bool { |
||||
|
return lhs.compare(rhs) == NSComparisonResult.OrderedAscending |
||||
|
} |
||||
@ -0,0 +1,80 @@ |
|||||
|
// |
||||
|
// Range.swift |
||||
|
// ExSwift |
||||
|
// |
||||
|
// Created by pNre on 04/06/14. |
||||
|
// Copyright (c) 2014 pNre. All rights reserved. |
||||
|
// |
||||
|
|
||||
|
import Foundation |
||||
|
|
||||
|
internal extension Range { |
||||
|
|
||||
|
/** |
||||
|
For each element in the range invokes function. |
||||
|
|
||||
|
:param: function Function to call |
||||
|
*/ |
||||
|
func times (function: () -> ()) { |
||||
|
each { (current: T) -> () in |
||||
|
function() |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
For each element in the range invokes function passing the element as argument. |
||||
|
|
||||
|
:param: function Function to invoke |
||||
|
*/ |
||||
|
func times (function: (T) -> ()) { |
||||
|
each (function) |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
For each element in the range invokes function passing the element as argument. |
||||
|
|
||||
|
:param: function Function to invoke |
||||
|
*/ |
||||
|
func each (function: (T) -> ()) { |
||||
|
for i in self { |
||||
|
function(i) |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
Returns each element of the range in an array |
||||
|
|
||||
|
:returns: Each element of the range in an array |
||||
|
*/ |
||||
|
func toArray () -> [T] { |
||||
|
var result: [T] = [] |
||||
|
for i in self { |
||||
|
result.append(i) |
||||
|
} |
||||
|
return result |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
Range of Int with random bounds between from and to (inclusive). |
||||
|
|
||||
|
:param: from Lower bound |
||||
|
:param: to Upper bound |
||||
|
:returns: Random range |
||||
|
*/ |
||||
|
static func random (from: Int, to: Int) -> Range<Int> { |
||||
|
let lowerBound = Int.random(min: from, max: to) |
||||
|
let upperBound = Int.random(min: lowerBound, max: to) |
||||
|
|
||||
|
return lowerBound...upperBound |
||||
|
} |
||||
|
|
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* Operator == to compare 2 ranges first, second by start & end indexes. If first.startIndex is equal to |
||||
|
* second.startIndex and first.endIndex is equal to second.endIndex the ranges are considered equal. |
||||
|
*/ |
||||
|
public func == <U: ForwardIndexType> (first: Range<U>, second: Range<U>) -> Bool { |
||||
|
return first.startIndex == second.startIndex && |
||||
|
first.endIndex == second.endIndex |
||||
|
} |
||||
@ -0,0 +1,244 @@ |
|||||
|
// |
||||
|
// Sequence.swift |
||||
|
// ExSwift |
||||
|
// |
||||
|
// Created by Colin Eberhardt on 24/06/2014. |
||||
|
// Copyright (c) 2014 pNre. All rights reserved. |
||||
|
// |
||||
|
|
||||
|
import Foundation |
||||
|
|
||||
|
internal extension SequenceOf { |
||||
|
|
||||
|
/** |
||||
|
First element of the sequence. |
||||
|
|
||||
|
:returns: First element of the sequence if present |
||||
|
*/ |
||||
|
var first: T? { |
||||
|
var generator = self.generate() |
||||
|
return generator.next() |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
Checks if call returns true for any element of self. |
||||
|
|
||||
|
:param: call Function to call for each element |
||||
|
:returns: True if call returns true for any element of self |
||||
|
*/ |
||||
|
func any (call: (T) -> Bool) -> Bool { |
||||
|
var generator = self.generate() |
||||
|
while let nextItem = generator.next() { |
||||
|
if call(nextItem) { |
||||
|
return true |
||||
|
} |
||||
|
} |
||||
|
return false |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
Object at the specified index if exists. |
||||
|
|
||||
|
:param: index |
||||
|
:returns: Object at index in sequence, nil if index is out of bounds |
||||
|
*/ |
||||
|
func get (index: Int) -> T? { |
||||
|
var generator = self.generate() |
||||
|
for _ in 0..<(index - 1) { |
||||
|
generator.next() |
||||
|
} |
||||
|
return generator.next() |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
Objects in the specified range. |
||||
|
|
||||
|
:param: range |
||||
|
:returns: Subsequence in range |
||||
|
*/ |
||||
|
func get (range: Range<Int>) -> SequenceOf<T> { |
||||
|
return self.skip(range.startIndex).take(range.endIndex - range.startIndex) |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
Index of the first occurrence of item, if found. |
||||
|
|
||||
|
:param: item The item to search for |
||||
|
:returns: Index of the matched item or nil |
||||
|
*/ |
||||
|
func indexOf <U: Equatable> (item: U) -> Int? { |
||||
|
var index = 0 |
||||
|
for current in self { |
||||
|
if let equatable = current as? U { |
||||
|
if equatable == item { |
||||
|
return index |
||||
|
} |
||||
|
} |
||||
|
index++ |
||||
|
} |
||||
|
return nil |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
Subsequence from n to the end of the sequence. |
||||
|
|
||||
|
:param: n Number of elements to skip |
||||
|
:returns: Sequence from n to the end |
||||
|
*/ |
||||
|
func skip (n: Int) -> SequenceOf<T> { |
||||
|
var generator = self.generate() |
||||
|
for _ in 0..<n { |
||||
|
generator.next() |
||||
|
} |
||||
|
return SequenceOf(generator) |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
Filters the sequence only including items that match the test. |
||||
|
|
||||
|
:param: include Function invoked to test elements for inclusion in the sequence |
||||
|
:returns: Filtered sequence |
||||
|
*/ |
||||
|
func filter(include: (T) -> Bool) -> SequenceOf<T> { |
||||
|
return SequenceOf(lazy(self).filter(include)) |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
Opposite of filter. |
||||
|
|
||||
|
:param: exclude Function invoked to test elements for exlcusion from the sequence |
||||
|
:returns: Filtered sequence |
||||
|
*/ |
||||
|
func reject (exclude: (T -> Bool)) -> SequenceOf<T> { |
||||
|
return self.filter { |
||||
|
return !exclude($0) |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
Skips the elements in the sequence up until the condition returns false. |
||||
|
|
||||
|
:param: condition A function which returns a boolean if an element satisfies a given condition or not |
||||
|
:returns: Elements of the sequence starting with the element which does not meet the condition |
||||
|
*/ |
||||
|
func skipWhile(condition:(T) -> Bool) -> SequenceOf<T> { |
||||
|
var generator = self.generate() |
||||
|
var checkingGenerator = self.generate() |
||||
|
|
||||
|
var keepSkipping = true |
||||
|
|
||||
|
while keepSkipping { |
||||
|
var nextItem = checkingGenerator.next() |
||||
|
keepSkipping = nextItem != nil ? condition(nextItem!) : false |
||||
|
|
||||
|
if keepSkipping { |
||||
|
generator.next() |
||||
|
} |
||||
|
} |
||||
|
return SequenceOf(generator) |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
Checks if self contains the item object. |
||||
|
|
||||
|
:param: item The item to search for |
||||
|
:returns: true if self contains item |
||||
|
*/ |
||||
|
func contains<T:Equatable> (item: T) -> Bool { |
||||
|
var generator = self.generate() |
||||
|
while let nextItem = generator.next() { |
||||
|
if nextItem as! T == item { |
||||
|
return true |
||||
|
} |
||||
|
} |
||||
|
return false |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
Returns the first n elements from self. |
||||
|
|
||||
|
:param: n Number of elements to take |
||||
|
:returns: First n elements |
||||
|
*/ |
||||
|
func take (n: Int) -> SequenceOf<T> { |
||||
|
return SequenceOf(TakeSequence(self, n)) |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
Returns the elements of the sequence up until an element does not meet the condition. |
||||
|
|
||||
|
:param: condition A function which returns a boolean if an element satisfies a given condition or not. |
||||
|
:returns: Elements of the sequence up until an element does not meet the condition |
||||
|
*/ |
||||
|
func takeWhile (condition:(T?) -> Bool) -> SequenceOf<T> { |
||||
|
return SequenceOf(TakeWhileSequence(self, condition)) |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
Returns each element of the sequence in an array |
||||
|
|
||||
|
:returns: Each element of the sequence in an array |
||||
|
*/ |
||||
|
func toArray () -> [T] { |
||||
|
var result: [T] = [] |
||||
|
for item in self { |
||||
|
result.append(item) |
||||
|
} |
||||
|
return result |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
A sequence adapter that implements the 'take' functionality |
||||
|
*/ |
||||
|
public struct TakeSequence<S: SequenceType>: SequenceType { |
||||
|
private let sequence: S |
||||
|
private let n: Int |
||||
|
|
||||
|
public init(_ sequence: S, _ n: Int) { |
||||
|
self.sequence = sequence |
||||
|
self.n = n |
||||
|
} |
||||
|
|
||||
|
public func generate() -> GeneratorOf<S.Generator.Element> { |
||||
|
var count = 0 |
||||
|
var generator = self.sequence.generate() |
||||
|
return GeneratorOf<S.Generator.Element> { |
||||
|
count++ |
||||
|
if count > self.n { |
||||
|
return nil |
||||
|
} else { |
||||
|
return generator.next() |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
a sequence adapter that implements the 'takeWhile' functionality |
||||
|
*/ |
||||
|
public struct TakeWhileSequence<S: SequenceType>: SequenceType { |
||||
|
private let sequence: S |
||||
|
private let condition: (S.Generator.Element?) -> Bool |
||||
|
|
||||
|
public init(_ sequence:S, _ condition:(S.Generator.Element?) -> Bool) { |
||||
|
self.sequence = sequence |
||||
|
self.condition = condition |
||||
|
} |
||||
|
|
||||
|
public func generate() -> GeneratorOf<S.Generator.Element> { |
||||
|
var generator = self.sequence.generate() |
||||
|
var endConditionMet = false |
||||
|
return GeneratorOf<S.Generator.Element> { |
||||
|
let next: S.Generator.Element? = generator.next() |
||||
|
if !endConditionMet { |
||||
|
endConditionMet = !self.condition(next) |
||||
|
} |
||||
|
if endConditionMet { |
||||
|
return nil |
||||
|
} else { |
||||
|
return next |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,403 @@ |
|||||
|
// |
||||
|
// String.swift |
||||
|
// ExSwift |
||||
|
// |
||||
|
// Created by pNre on 03/06/14. |
||||
|
// Copyright (c) 2014 pNre. All rights reserved. |
||||
|
// |
||||
|
|
||||
|
import Foundation |
||||
|
|
||||
|
public extension String { |
||||
|
|
||||
|
/** |
||||
|
String length |
||||
|
*/ |
||||
|
var length: Int { return count(self) } |
||||
|
|
||||
|
/** |
||||
|
self.capitalizedString shorthand |
||||
|
*/ |
||||
|
var capitalized: String { return capitalizedString } |
||||
|
|
||||
|
/** |
||||
|
Returns the substring in the given range |
||||
|
|
||||
|
:param: range |
||||
|
:returns: Substring in range |
||||
|
*/ |
||||
|
subscript (range: Range<Int>) -> String? { |
||||
|
if range.startIndex < 0 || range.endIndex > self.length { |
||||
|
return nil |
||||
|
} |
||||
|
|
||||
|
let range = Range(start: advance(startIndex, range.startIndex), end: advance(startIndex, range.endIndex)) |
||||
|
|
||||
|
return self[range] |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
Equivalent to at. Takes a list of indexes and returns an Array |
||||
|
containing the elements at the given indexes in self. |
||||
|
|
||||
|
:param: firstIndex |
||||
|
:param: secondIndex |
||||
|
:param: restOfIndexes |
||||
|
:returns: Charaters at the specified indexes (converted to String) |
||||
|
*/ |
||||
|
subscript (firstIndex: Int, secondIndex: Int, restOfIndexes: Int...) -> [String] { |
||||
|
return at([firstIndex, secondIndex] + restOfIndexes) |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
Gets the character at the specified index as String. |
||||
|
If index is negative it is assumed to be relative to the end of the String. |
||||
|
|
||||
|
:param: index Position of the character to get |
||||
|
:returns: Character as String or nil if the index is out of bounds |
||||
|
*/ |
||||
|
subscript (index: Int) -> String? { |
||||
|
if let char = Array(self).get(index) { |
||||
|
return String(char) |
||||
|
} |
||||
|
|
||||
|
return nil |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
Takes a list of indexes and returns an Array containing the elements at the given indexes in self. |
||||
|
|
||||
|
:param: indexes Positions of the elements to get |
||||
|
:returns: Array of characters (as String) |
||||
|
*/ |
||||
|
func at (indexes: Int...) -> [String] { |
||||
|
return indexes.map { self[$0]! } |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
Takes a list of indexes and returns an Array containing the elements at the given indexes in self. |
||||
|
|
||||
|
:param: indexes Positions of the elements to get |
||||
|
:returns: Array of characters (as String) |
||||
|
*/ |
||||
|
func at (indexes: [Int]) -> [String] { |
||||
|
return indexes.map { self[$0]! } |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
Returns an array of strings, each of which is a substring of self formed by splitting it on separator. |
||||
|
|
||||
|
:param: separator Character used to split the string |
||||
|
:returns: Array of substrings |
||||
|
*/ |
||||
|
func explode (separator: Character) -> [String] { |
||||
|
return split(self, isSeparator: { (element: Character) -> Bool in |
||||
|
return element == separator |
||||
|
}) |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
Finds any match in self for pattern. |
||||
|
|
||||
|
:param: pattern Pattern to match |
||||
|
:param: ignoreCase true for case insensitive matching |
||||
|
:returns: Matches found (as [NSTextCheckingResult]) |
||||
|
*/ |
||||
|
func matches (pattern: String, ignoreCase: Bool = false) -> [NSTextCheckingResult]? { |
||||
|
|
||||
|
if let regex = ExSwift.regex(pattern, ignoreCase: ignoreCase) { |
||||
|
// Using map to prevent a possible bug in the compiler |
||||
|
return regex.matchesInString(self, options: nil, range: NSMakeRange(0, length)).map { $0 as! NSTextCheckingResult } |
||||
|
} |
||||
|
|
||||
|
return nil |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
Check is string with this pattern included in string |
||||
|
|
||||
|
:param: pattern Pattern to match |
||||
|
:param: ignoreCase true for case insensitive matching |
||||
|
:returns: true if contains match, otherwise false |
||||
|
*/ |
||||
|
func containsMatch (pattern: String, ignoreCase: Bool = false) -> Bool? { |
||||
|
if let regex = ExSwift.regex(pattern, ignoreCase: ignoreCase) { |
||||
|
let range = NSMakeRange(0, count(self)) |
||||
|
return regex.firstMatchInString(self, options: .allZeros, range: range) != nil |
||||
|
} |
||||
|
|
||||
|
return nil |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
Replace all pattern matches with another string |
||||
|
|
||||
|
:param: pattern Pattern to match |
||||
|
:param: replacementString string to replace matches |
||||
|
:param: ignoreCase true for case insensitive matching |
||||
|
:returns: true if contains match, otherwise false |
||||
|
*/ |
||||
|
func replaceMatches (pattern: String, withString replacementString: String, ignoreCase: Bool = false) -> String? { |
||||
|
if let regex = ExSwift.regex(pattern, ignoreCase: ignoreCase) { |
||||
|
let range = NSMakeRange(0, count(self)) |
||||
|
return regex.stringByReplacingMatchesInString(self, options: .allZeros, range: range, withTemplate: replacementString) |
||||
|
} |
||||
|
|
||||
|
return nil |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
Inserts a substring at the given index in self. |
||||
|
|
||||
|
:param: index Where the new string is inserted |
||||
|
:param: string String to insert |
||||
|
:returns: String formed from self inserting string at index |
||||
|
*/ |
||||
|
func insert (var index: Int, _ string: String) -> String { |
||||
|
// Edge cases, prepend and append |
||||
|
if index > length { |
||||
|
return self + string |
||||
|
} else if index < 0 { |
||||
|
return string + self |
||||
|
} |
||||
|
|
||||
|
return self[0..<index]! + string + self[index..<length]! |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
Strips the specified characters from the beginning of self. |
||||
|
|
||||
|
:returns: Stripped string |
||||
|
*/ |
||||
|
func trimmedLeft (characterSet set: NSCharacterSet = NSCharacterSet.whitespaceAndNewlineCharacterSet()) -> String { |
||||
|
if let range = rangeOfCharacterFromSet(set.invertedSet) { |
||||
|
return self[range.startIndex..<endIndex] |
||||
|
} |
||||
|
|
||||
|
return "" |
||||
|
} |
||||
|
|
||||
|
@availability(*, unavailable, message="use 'trimmedLeft' instead") func ltrimmed (set: NSCharacterSet = NSCharacterSet.whitespaceAndNewlineCharacterSet()) -> String { |
||||
|
return trimmedLeft(characterSet: set) |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
Strips the specified characters from the end of self. |
||||
|
|
||||
|
:returns: Stripped string |
||||
|
*/ |
||||
|
func trimmedRight (characterSet set: NSCharacterSet = NSCharacterSet.whitespaceAndNewlineCharacterSet()) -> String { |
||||
|
if let range = rangeOfCharacterFromSet(set.invertedSet, options: NSStringCompareOptions.BackwardsSearch) { |
||||
|
return self[startIndex..<range.endIndex] |
||||
|
} |
||||
|
|
||||
|
return "" |
||||
|
} |
||||
|
|
||||
|
@availability(*, unavailable, message="use 'trimmedRight' instead") func rtrimmed (set: NSCharacterSet = NSCharacterSet.whitespaceAndNewlineCharacterSet()) -> String { |
||||
|
return trimmedRight(characterSet: set) |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
Strips whitespaces from both the beginning and the end of self. |
||||
|
|
||||
|
:returns: Stripped string |
||||
|
*/ |
||||
|
func trimmed () -> String { |
||||
|
return trimmedLeft().trimmedRight() |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
Costructs a string using random chars from a given set. |
||||
|
|
||||
|
:param: length String length. If < 1, it's randomly selected in the range 0..16 |
||||
|
:param: charset Chars to use in the random string |
||||
|
:returns: Random string |
||||
|
*/ |
||||
|
static func random (var length len: Int = 0, charset: String = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789") -> String { |
||||
|
|
||||
|
if len < 1 { |
||||
|
len = Int.random(max: 16) |
||||
|
} |
||||
|
|
||||
|
var result = String() |
||||
|
let max = charset.length - 1 |
||||
|
|
||||
|
len.times { |
||||
|
result += charset[Int.random(min: 0, max: max)]! |
||||
|
} |
||||
|
|
||||
|
return result |
||||
|
|
||||
|
} |
||||
|
|
||||
|
|
||||
|
/** |
||||
|
Parses a string containing a double numerical value into an optional double if the string is a well formed number. |
||||
|
|
||||
|
:returns: A double parsed from the string or nil if it cannot be parsed. |
||||
|
*/ |
||||
|
func toDouble() -> Double? { |
||||
|
|
||||
|
let scanner = NSScanner(string: self) |
||||
|
var double: Double = 0 |
||||
|
|
||||
|
if scanner.scanDouble(&double) { |
||||
|
return double |
||||
|
} |
||||
|
|
||||
|
return nil |
||||
|
|
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
Parses a string containing a float numerical value into an optional float if the string is a well formed number. |
||||
|
|
||||
|
:returns: A float parsed from the string or nil if it cannot be parsed. |
||||
|
*/ |
||||
|
func toFloat() -> Float? { |
||||
|
|
||||
|
let scanner = NSScanner(string: self) |
||||
|
var float: Float = 0 |
||||
|
|
||||
|
if scanner.scanFloat(&float) { |
||||
|
return float |
||||
|
} |
||||
|
|
||||
|
return nil |
||||
|
|
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
Parses a string containing a non-negative integer value into an optional UInt if the string is a well formed number. |
||||
|
|
||||
|
:returns: A UInt parsed from the string or nil if it cannot be parsed. |
||||
|
*/ |
||||
|
func toUInt() -> UInt? { |
||||
|
if let val = self.trimmed().toInt() { |
||||
|
if val < 0 { |
||||
|
return nil |
||||
|
} |
||||
|
return UInt(val) |
||||
|
} |
||||
|
|
||||
|
return nil |
||||
|
} |
||||
|
|
||||
|
|
||||
|
/** |
||||
|
Parses a string containing a boolean value (true or false) into an optional Bool if the string is a well formed. |
||||
|
|
||||
|
:returns: A Bool parsed from the string or nil if it cannot be parsed as a boolean. |
||||
|
*/ |
||||
|
func toBool() -> Bool? { |
||||
|
let text = self.trimmed().lowercaseString |
||||
|
if text == "true" || text == "false" || text == "yes" || text == "no" { |
||||
|
return (text as NSString).boolValue |
||||
|
} |
||||
|
|
||||
|
return nil |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
Parses a string containing a date into an optional NSDate if the string is a well formed. |
||||
|
The default format is yyyy-MM-dd, but can be overriden. |
||||
|
|
||||
|
:returns: A NSDate parsed from the string or nil if it cannot be parsed as a date. |
||||
|
*/ |
||||
|
func toDate(format : String? = "yyyy-MM-dd") -> NSDate? { |
||||
|
let text = self.trimmed().lowercaseString |
||||
|
var dateFmt = NSDateFormatter() |
||||
|
dateFmt.timeZone = NSTimeZone.defaultTimeZone() |
||||
|
if let fmt = format { |
||||
|
dateFmt.dateFormat = fmt |
||||
|
} |
||||
|
return dateFmt.dateFromString(text) |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
Parses a string containing a date and time into an optional NSDate if the string is a well formed. |
||||
|
The default format is yyyy-MM-dd hh-mm-ss, but can be overriden. |
||||
|
|
||||
|
:returns: A NSDate parsed from the string or nil if it cannot be parsed as a date. |
||||
|
*/ |
||||
|
func toDateTime(format : String? = "yyyy-MM-dd hh-mm-ss") -> NSDate? { |
||||
|
return toDate(format: format) |
||||
|
} |
||||
|
|
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
Repeats the string first n times |
||||
|
*/ |
||||
|
public func * (first: String, n: Int) -> String { |
||||
|
|
||||
|
var result = String() |
||||
|
|
||||
|
n.times { |
||||
|
result += first |
||||
|
} |
||||
|
|
||||
|
return result |
||||
|
|
||||
|
} |
||||
|
|
||||
|
// Pattern matching using a regular expression |
||||
|
public func =~ (string: String, pattern: String) -> Bool { |
||||
|
|
||||
|
let regex = ExSwift.regex(pattern, ignoreCase: false)! |
||||
|
let matches = regex.numberOfMatchesInString(string, options: nil, range: NSMakeRange(0, string.length)) |
||||
|
|
||||
|
return matches > 0 |
||||
|
|
||||
|
} |
||||
|
|
||||
|
// Pattern matching using a regular expression |
||||
|
public func =~ (string: String, regex: NSRegularExpression) -> Bool { |
||||
|
|
||||
|
let matches = regex.numberOfMatchesInString(string, options: nil, range: NSMakeRange(0, string.length)) |
||||
|
|
||||
|
return matches > 0 |
||||
|
|
||||
|
} |
||||
|
|
||||
|
// This version also allowes to specify case sentitivity |
||||
|
public func =~ (string: String, options: (pattern: String, ignoreCase: Bool)) -> Bool { |
||||
|
|
||||
|
if let matches = ExSwift.regex(options.pattern, ignoreCase: options.ignoreCase)?.numberOfMatchesInString(string, options: nil, range: NSMakeRange(0, string.length)) { |
||||
|
return matches > 0 |
||||
|
} |
||||
|
|
||||
|
return false |
||||
|
|
||||
|
} |
||||
|
|
||||
|
// Match against all the alements in an array of String |
||||
|
public func =~ (strings: [String], pattern: String) -> Bool { |
||||
|
|
||||
|
let regex = ExSwift.regex(pattern, ignoreCase: false)! |
||||
|
|
||||
|
return strings.all { $0 =~ regex } |
||||
|
|
||||
|
} |
||||
|
|
||||
|
public func =~ (strings: [String], options: (pattern: String, ignoreCase: Bool)) -> Bool { |
||||
|
|
||||
|
return strings.all { $0 =~ options } |
||||
|
|
||||
|
} |
||||
|
|
||||
|
// Match against any element in an array of String |
||||
|
public func |~ (strings: [String], pattern: String) -> Bool { |
||||
|
|
||||
|
let regex = ExSwift.regex(pattern, ignoreCase: false)! |
||||
|
|
||||
|
return strings.any { $0 =~ regex } |
||||
|
|
||||
|
} |
||||
|
|
||||
|
public func |~ (strings: [String], options: (pattern: String, ignoreCase: Bool)) -> Bool { |
||||
|
|
||||
|
return strings.any { $0 =~ options } |
||||
|
|
||||
|
} |
||||
@ -0,0 +1,32 @@ |
|||||
|
// |
||||
|
// Created by Marco Schmickler on 21.03.15. |
||||
|
// Copyright (c) 2015 Marco Schmickler. All rights reserved. |
||||
|
// |
||||
|
|
||||
|
import Foundation |
||||
|
import Haneke |
||||
|
|
||||
|
class HanekeFetchOperation: NSOperation { |
||||
|
let baseUrl: NSURL |
||||
|
let succeeder: Fetch<UIImage>.Succeeder |
||||
|
let index: Int |
||||
|
|
||||
|
init(baseUrl: NSURL, succeeder: Fetch<UIImage>.Succeeder, index: Int) { |
||||
|
self.baseUrl = baseUrl |
||||
|
self.succeeder = succeeder |
||||
|
self.index = index |
||||
|
} |
||||
|
|
||||
|
override func main() { |
||||
|
if self.cancelled { |
||||
|
return |
||||
|
} |
||||
|
|
||||
|
Shared.imageCache.fetch(URL: baseUrl).onSuccess { i in |
||||
|
|
||||
|
dispatch_async(dispatch_get_main_queue(), { self.succeeder(i) }) |
||||
|
|
||||
|
} |
||||
|
} |
||||
|
|
||||
|
} |
||||
@ -0,0 +1,46 @@ |
|||||
|
// |
||||
|
// Created by Marco Schmickler on 21.03.15. |
||||
|
// Copyright (c) 2015 Marco Schmickler. All rights reserved. |
||||
|
// |
||||
|
|
||||
|
import Foundation |
||||
|
import Alamofire |
||||
|
import Darwin |
||||
|
|
||||
|
class ImageLoadOperation: NSOperation { |
||||
|
public typealias Succeeder = (UIImage) -> () |
||||
|
|
||||
|
let imageURL: NSURL |
||||
|
let succeeder: Succeeder |
||||
|
let index: Int |
||||
|
|
||||
|
|
||||
|
init(imageURL: NSURL, succeeder: Succeeder, index: Int) { |
||||
|
self.imageURL = imageURL |
||||
|
self.succeeder = succeeder |
||||
|
self.index = index |
||||
|
} |
||||
|
|
||||
|
override func main() { |
||||
|
if self.cancelled { |
||||
|
return |
||||
|
} |
||||
|
|
||||
|
usleep(100000) |
||||
|
|
||||
|
if self.cancelled { |
||||
|
return |
||||
|
} |
||||
|
|
||||
|
Alamofire.request(.GET, imageURL).validate().responseImage() { |
||||
|
(request, _, image, error) in |
||||
|
|
||||
|
if error == nil { |
||||
|
// if request.URLString.isEqual(self.imageURL) { |
||||
|
self.succeeder(image!) |
||||
|
// } |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
} |
||||
@ -0,0 +1,28 @@ |
|||||
|
// |
||||
|
// Created by Marco Schmickler on 22.06.15. |
||||
|
// Copyright (c) 2015 Marco Schmickler. All rights reserved. |
||||
|
// |
||||
|
|
||||
|
import Foundation |
||||
|
import Alamofire |
||||
|
|
||||
|
extension Alamofire.Request { |
||||
|
class func imageResponseSerializer() -> Serializer { |
||||
|
return { request, response, data in |
||||
|
if data == nil { |
||||
|
return (nil, nil) |
||||
|
} |
||||
|
|
||||
|
let i = UIImage(data: data!) |
||||
|
// let image = i.hnk_decompressedImage() |
||||
|
|
||||
|
return (i, nil) |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
func responseImage(completionHandler: (NSURLRequest, NSHTTPURLResponse?, UIImage?, NSError?) -> Void) -> Self { |
||||
|
return response(serializer: Request.imageResponseSerializer(), completionHandler: { (request, response, image, error) in |
||||
|
completionHandler(request, response, image as? UIImage, error) |
||||
|
}) |
||||
|
} |
||||
|
} |
||||
Write
Preview
Loading…
Cancel
Save
Reference in new issue