How to have stored properties in Swift, the same way I had on Objective-C?

IosSwiftAssociated Object

Ios Problem Overview


I am switching an application from Objective-C to Swift, which I have a couple of categories with stored properties, for example:

@interface UIView (MyCategory)

- (void)alignToView:(UIView *)view
          alignment:(UIViewRelativeAlignment)alignment;
- (UIView *)clone;

@property (strong) PFObject *xo;
@property (nonatomic) BOOL isAnimating;

@end

As Swift extensions don't accept stored properties like these, I don't know how to maintain the same structure as the Objc code. Stored properties are really important for my app and I believe Apple must have created some solution for doing it in Swift.

As said by jou, what I was looking for was actually using associated objects, so I did (in another context):

import Foundation
import QuartzCore
import ObjectiveC

extension CALayer {
    var shapeLayer: CAShapeLayer? {
        get {
            return objc_getAssociatedObject(self, "shapeLayer") as? CAShapeLayer
        }
        set(newValue) {
            objc_setAssociatedObject(self, "shapeLayer", newValue, UInt(OBJC_ASSOCIATION_RETAIN))
        }
    }

    var initialPath: CGPathRef! {
        get {
            return objc_getAssociatedObject(self, "initialPath") as CGPathRef
        }
        set {
            objc_setAssociatedObject(self, "initialPath", newValue, UInt(OBJC_ASSOCIATION_RETAIN))
        }
    }
}

But I get an EXC_BAD_ACCESS when doing:

class UIBubble : UIView {
    required init(coder aDecoder: NSCoder) {
        ...
        self.layer.shapeLayer = CAShapeLayer()
        ...
    }
}

Any ideas?

Ios Solutions


Solution 1 - Ios

As in Objective-C, you can't add stored property to existing classes. If you're extending an Objective-C class (UIView is definitely one), you can still use Associated Objects to emulate stored properties:

for Swift 1

import ObjectiveC

private var xoAssociationKey: UInt8 = 0

extension UIView {
    var xo: PFObject! {
        get {
            return objc_getAssociatedObject(self, &xoAssociationKey) as? PFObject
        }
        set(newValue) {
            objc_setAssociatedObject(self, &xoAssociationKey, newValue, objc_AssociationPolicy(OBJC_ASSOCIATION_RETAIN))
        }
    }
}

The association key is a pointer that should be the unique for each association. For that, we create a private global variable and use it's memory address as the key with the & operator. See the Using Swift with Cocoa and Objective-C on more details how pointers are handled in Swift.

UPDATED for Swift 2 and 3

import ObjectiveC

private var xoAssociationKey: UInt8 = 0

extension UIView {
    var xo: PFObject! {
        get {
            return objc_getAssociatedObject(self, &xoAssociationKey) as? PFObject
        }
        set(newValue) {
            objc_setAssociatedObject(self, &xoAssociationKey, newValue, objc_AssociationPolicy.OBJC_ASSOCIATION_RETAIN)
        }
    }
}

UPDATED for Swift 4

In Swift 4, it's much more simple. The Holder struct will contain the private value that our computed property will expose to the world, giving the illusion of a stored property behaviour instead.

Source

extension UIViewController {
    struct Holder {
        static var _myComputedProperty:Bool = false
    }
    var myComputedProperty:Bool {
        get {
            return Holder._myComputedProperty
        }
        set(newValue) {
            Holder._myComputedProperty = newValue
        }
    }
}

Solution 2 - Ios

Associated objects API is a bit cumbersome to use. You can remove most of the boilerplate with a helper class.

public final class ObjectAssociation<T: AnyObject> {
    
    private let policy: objc_AssociationPolicy
    
    /// - Parameter policy: An association policy that will be used when linking objects.
    public init(policy: objc_AssociationPolicy = .OBJC_ASSOCIATION_RETAIN_NONATOMIC) {
        
        self.policy = policy
    }
    
    /// Accesses associated object.
    /// - Parameter index: An object whose associated object is to be accessed.
    public subscript(index: AnyObject) -> T? {
        
        get { return objc_getAssociatedObject(index, Unmanaged.passUnretained(self).toOpaque()) as! T? }
        set { objc_setAssociatedObject(index, Unmanaged.passUnretained(self).toOpaque(), newValue, policy) }
    }
}

Provided that you can "add" a property to objective-c class in a more readable manner:

extension SomeType {

    private static let association = ObjectAssociation<NSObject>()
    
    var simulatedProperty: NSObject? {

        get { return SomeType.association[self] }
        set { SomeType.association[self] = newValue }
    }
}

As for the solution:

extension CALayer {
    
    private static let initialPathAssociation = ObjectAssociation<CGPath>()
    private static let shapeLayerAssociation = ObjectAssociation<CAShapeLayer>()
    
    var initialPath: CGPath! {
        get { return CALayer.initialPathAssociation[self] }
        set { CALayer.initialPathAssociation[self] = newValue }
    }
    
    var shapeLayer: CAShapeLayer? {
        get { return CALayer.shapeLayerAssociation[self] }
        set { CALayer.shapeLayerAssociation[self] = newValue }
    }
}

Solution 3 - Ios

So I think I found a method that works cleaner than the ones above because it doesn't require any global variables. I got it from here: http://nshipster.com/swift-objc-runtime/

The gist is that you use a struct like so:

extension UIViewController {
    private struct AssociatedKeys {
        static var DescriptiveName = "nsh_DescriptiveName"
    }

    var descriptiveName: String? {
        get {
            return objc_getAssociatedObject(self, &AssociatedKeys.DescriptiveName) as? String
        }
        set {
            if let newValue = newValue {
                objc_setAssociatedObject(
                    self,
                    &AssociatedKeys.DescriptiveName,
                    newValue as NSString?,
                    UInt(OBJC_ASSOCIATION_RETAIN_NONATOMIC)
                )
            }
        }
    }
}

UPDATE for Swift 2

private struct AssociatedKeys {
	static var displayed = "displayed"
}

//this lets us check to see if the item is supposed to be displayed or not
var displayed : Bool {
	get {
		guard let number = objc_getAssociatedObject(self, &AssociatedKeys.displayed) as? NSNumber else {
			return true
		}
		return number.boolValue
	}
	
	set(value) {
		objc_setAssociatedObject(self,&AssociatedKeys.displayed,NSNumber(bool: value),objc_AssociationPolicy.OBJC_ASSOCIATION_RETAIN_NONATOMIC)
	}
}

Solution 4 - Ios

The solution pointed out by jou doesn't support value types, this works fine with them as well

Wrappers

import ObjectiveC

final class Lifted<T> {
    let value: T
    init(_ x: T) {
        value = x
    }
}

private func lift<T>(x: T) -> Lifted<T>  {
    return Lifted(x)
}

func setAssociatedObject<T>(object: AnyObject, value: T, associativeKey: UnsafePointer<Void>, policy: objc_AssociationPolicy) {
    if let v: AnyObject = value as? AnyObject {
        objc_setAssociatedObject(object, associativeKey, v,  policy)
    }
    else {
        objc_setAssociatedObject(object, associativeKey, lift(value),  policy)
    }
}

func getAssociatedObject<T>(object: AnyObject, associativeKey: UnsafePointer<Void>) -> T? {
    if let v = objc_getAssociatedObject(object, associativeKey) as? T {
        return v
    }
    else if let v = objc_getAssociatedObject(object, associativeKey) as? Lifted<T> {
        return v.value
    }
    else {
        return nil
    }
}

A possible Class extension (Example of usage):

extension UIView {
    
    private struct AssociatedKey {
        static var viewExtension = "viewExtension"
    }

    var referenceTransform: CGAffineTransform? {
        get {
            return getAssociatedObject(self, associativeKey: &AssociatedKey.viewExtension)
        }
        
        set {
            if let value = newValue {
                setAssociatedObject(self, value: value, associativeKey: &AssociatedKey.viewExtension, policy: objc_AssociationPolicy.OBJC_ASSOCIATION_RETAIN_NONATOMIC)
            }
        }
    }
}

This is really such a great solution, I wanted to add another usage example that included structs and values that are not optionals. Also, the AssociatedKey values can be simplified.

struct Crate {
    var name: String
}

class Box {
    var name: String
    
    init(name: String) {
        self.name = name
    }
}

extension UIViewController {
    
    private struct AssociatedKey {
        static var displayed:   UInt8 = 0
        static var box:         UInt8 = 0
        static var crate:       UInt8 = 0
    }
    
    var displayed: Bool? {
        get {
            return getAssociatedObject(self, associativeKey: &AssociatedKey.displayed)
        }
        
        set {
            if let value = newValue {
                setAssociatedObject(self, value: value, associativeKey: &AssociatedKey.displayed, policy: objc_AssociationPolicy.OBJC_ASSOCIATION_RETAIN_NONATOMIC)
            }
        }
    }
    
    var box: Box {
        get {
            if let result:Box = getAssociatedObject(self, associativeKey: &AssociatedKey.box) {
                return result
            } else {
                let result = Box(name: "")
                self.box = result
                return result
            }
        }
        
        set {
            setAssociatedObject(self, value: newValue, associativeKey: &AssociatedKey.box, policy: objc_AssociationPolicy.OBJC_ASSOCIATION_RETAIN_NONATOMIC)
        }
    }
    
    var crate: Crate {
        get {
            if let result:Crate = getAssociatedObject(self, associativeKey: &AssociatedKey.crate) {
                return result
            } else {
                let result = Crate(name: "")
                self.crate = result
                return result
            }
        }
        
        set {
            setAssociatedObject(self, value: newValue, associativeKey: &AssociatedKey.crate, policy: objc_AssociationPolicy.OBJC_ASSOCIATION_RETAIN_NONATOMIC)
        }
    }
}

Solution 5 - Ios

You can't define categories (Swift extensions) with new storage; any additional properties must be computed rather than stored. The syntax works for Objective C because @property in a category essentially means "I'll provide the getter and setter". In Swift, you'll need to define these yourself to get a computed property; something like:

extension String {
    public var Foo : String {
        get
        {
            return "Foo"
        }
        
        set
        {
            // What do you want to do here?
        }
    }
}

Should work fine. Remember, you can't store new values in the setter, only work with the existing available class state.

Solution 6 - Ios

My $0.02. This code is written in Swift 2.0

extension CALayer {
    private struct AssociatedKeys {
        static var shapeLayer:CAShapeLayer?
    }

    var shapeLayer: CAShapeLayer? {
        get {
            return objc_getAssociatedObject(self, &AssociatedKeys.shapeLayer) as? CAShapeLayer
        }
        set {
            if let newValue = newValue {
                objc_setAssociatedObject(self, &AssociatedKeys.shapeLayer, newValue as CAShapeLayer?, objc_AssociationPolicy.OBJC_ASSOCIATION_RETAIN_NONATOMIC)
            }
        }
    }
}

I have tried many solutions, and found this is the only way to actually extend a class with extra variable parameters.

Solution 7 - Ios

Why relying on objc runtime? I don't get the point. By using something like the following you will achieve almost the identical behaviour of a stored property, by using only a pure Swift approach:

extension UIViewController {
    private static var _myComputedProperty = [String:Bool]()
    
    var myComputedProperty:Bool {
        get {
            let tmpAddress = String(format: "%p", unsafeBitCast(self, to: Int.self))
            return UIViewController._myComputedProperty[tmpAddress] ?? false
        }
        set(newValue) {
            let tmpAddress = String(format: "%p", unsafeBitCast(self, to: Int.self))
            UIViewController._myComputedProperty[tmpAddress] = newValue
        }
    }
}

Solution 8 - Ios

I prefer doing code in pure Swift and not rely on Objective-C heritage. Because of this I wrote pure Swift solution with two advantages and two disadvantages.

Advantages:

  1. Pure Swift code

  2. Works on classes and completions or more specifically on Any object

Disadvantages:

  1. Code should call method willDeinit() to release objects linked to specific class instance to avoid memory leaks

  2. You cannot make extension directly to UIView for this exact example because var frame is extension to UIView, not part of class.

EDIT:

import UIKit

var extensionPropertyStorage: [NSObject: [String: Any]] = [:]

var didSetFrame_ = "didSetFrame"

extension UILabel {

    override public var frame: CGRect {

        get {
            return didSetFrame ?? CGRectNull
        }
            
        set {
            didSetFrame = newValue
        }
    }

    var didSetFrame: CGRect? {
        
        get {
            return extensionPropertyStorage[self]?[didSetFrame_] as? CGRect
        }
        
        set {
            var selfDictionary = extensionPropertyStorage[self] ?? [String: Any]()
            
            selfDictionary[didSetFrame_] = newValue
            
            extensionPropertyStorage[self] = selfDictionary
        }
    }
    
    func willDeinit() {
        extensionPropertyStorage[self] = nil
    }
}

Solution 9 - Ios

With Obj-c Categories you can only add methods, not instance variables.

In you example you have used @property as a shortcut to adding getter and setter method declarations. You still need to implement those methods.

Similarly in Swift you can add use extensions to add instance methods, computed properties etc. but not stored properties.

Solution 10 - Ios

Notice: after further analyzing, the code below works fine, but does not release the view object, so if I can find a way around it I'll edit the answer. meanwhile, read the comments.

How about storing static map to class that is extending like this :

extension UIView {
    
    struct Holder {
        static var _padding:[UIView:UIEdgeInsets] = [:]
    }
   
    var padding : UIEdgeInsets {
        get{ return UIView.Holder._padding[self] ?? .zero}
        set { UIView.Holder._padding[self] = newValue }
    }

}

Solution 11 - Ios

I also get an EXC_BAD_ACCESS problem.The value in objc_getAssociatedObject() and objc_setAssociatedObject() should be an Object. And the objc_AssociationPolicy should match the Object.

Solution 12 - Ios

I tried using objc_setAssociatedObject as mentioned in a few of the answers here, but after failing with it a few times I stepped back and realized there is no reason I need that. Borrowing from a few of the ideas here, I came up with this code which simply stores an array of whatever my extra data is (MyClass in this example) indexed by the object I want to associate it with:

class MyClass {
    var a = 1
    init(a: Int)
    {
        self.a = a
    }
}

extension UIView
{
    static var extraData = [UIView: MyClass]()
    
    var myClassData: MyClass? {
        get {
            return UIView.extraData[self]
        }
        set(value) {
            UIView.extraData[self] = value
        }
    }
}

// Test Code: (Ran in a Swift Playground)
var view1 = UIView()
var view2 = UIView()

view1.myClassData = MyClass(a: 1)
view2.myClassData = MyClass(a: 2)
print(view1.myClassData?.a)
print(view2.myClassData?.a)

Solution 13 - Ios

Here is simplified and more expressive solution. It works for both value and reference types. The approach of lifting is taken from @HepaKKes answer.

Association code:

import ObjectiveC

final class Lifted<T> {
    let value: T
    init(_ x: T) {
        value = x
    }
}

private func lift<T>(_ x: T) -> Lifted<T>  {
    return Lifted(x)
}

func associated<T>(to base: AnyObject,
                key: UnsafePointer<UInt8>,
                policy: objc_AssociationPolicy = .OBJC_ASSOCIATION_RETAIN,
                initialiser: () -> T) -> T {
    if let v = objc_getAssociatedObject(base, key) as? T {
        return v
    }
    
    if let v = objc_getAssociatedObject(base, key) as? Lifted<T> {
        return v.value
    }
    
    let lifted = Lifted(initialiser())
    objc_setAssociatedObject(base, key, lifted, policy)
    return lifted.value
}

func associate<T>(to base: AnyObject, key: UnsafePointer<UInt8>, value: T, policy: objc_AssociationPolicy = .OBJC_ASSOCIATION_RETAIN) {
    if let v: AnyObject = value as AnyObject? {
        objc_setAssociatedObject(base, key, v, policy)
    }
    else {
        objc_setAssociatedObject(base, key, lift(value), policy)
    }
}

Example of usage:

  1. Create extension and associate properties to it. Let's use both value and reference type properties.

    extension UIButton {

     struct Keys {
         static fileprivate var color: UInt8 = 0
         static fileprivate var index: UInt8 = 0
     }
     
     var color: UIColor {
         get {
             return associated(to: self, key: &Keys.color) { .green }
         }
         set {
             associate(to: self, key: &Keys.color, value: newValue)
         }
     }
     
     var index: Int {
         get {
             return associated(to: self, key: &Keys.index) { -1 }
         }
         set {
             associate(to: self, key: &Keys.index, value: newValue)
         }
     }
     
    

    }

  2. Now you can use just as regular properties:

     let button = UIButton()
     print(button.color) // UIExtendedSRGBColorSpace 0 1 0 1 == green
     button.color = .black
     print(button.color) // UIExtendedGrayColorSpace 0 1 == black
     
     print(button.index) // -1
     button.index = 3
     print(button.index) // 3
    

More details:

  1. Lifting is needed for wrapping value types.
  2. Default associated object behavior is retain. If you want to learn more about associated objects, I'd recommend checking this article.

Solution 14 - Ios

if you are looking to set a custom string attribute to a UIView, this is how I did it on Swift 4

Create a UIView extension

extension UIView {

    func setStringValue(value: String, key: String) {
        layer.setValue(value, forKey: key)
    }

    func stringValueFor(key: String) -> String? {
        return layer.value(forKey: key) as? String
    }
}

To use this extension

let key = "COLOR"

let redView = UIView() 
   
// To set
redView.setStringAttribute(value: "Red", key: key)

// To read
print(redView.stringValueFor(key: key)) // Optional("Red")

Solution 15 - Ios

In PURE SWIFT with WEAK reference handling

import Foundation
import UIKit

extension CustomView {
    
    // can make private
    static let storedProperties = WeakDictionary<UIView, Properties>()
    
    struct Properties {
        var url: String = ""
        var status = false
        var desc: String { "url: \(url), status: \(status)" }
    }
    
    var properties: Properties {
        get {
            return CustomView.storedProperties.get(forKey: self) ?? Properties()
        }
        set {
            CustomView.storedProperties.set(forKey: self, object: newValue)
        }
    }
}

var view: CustomView? = CustomView()
print("1 print", view?.properties.desc ?? "nil")
view?.properties.url = "abc"
view?.properties.status = true
print("2 print", view?.properties.desc ?? "nil")
view = nil

WeakDictionary.swift

import Foundation

private class WeakHolder<T: AnyObject>: Hashable {
    weak var object: T?
    let hash: Int

    init(object: T) {
        self.object = object
        hash = ObjectIdentifier(object).hashValue
    }

    func hash(into hasher: inout Hasher) {
        hasher.combine(hash)
    }

    static func ==(lhs: WeakHolder, rhs: WeakHolder) -> Bool {
        return lhs.hash == rhs.hash
    }
}

class WeakDictionary<T1: AnyObject, T2> {
    private var dictionary = [WeakHolder<T1>: T2]()

    func set(forKey: T1, object: T2?) {
        dictionary[WeakHolder(object: forKey)] = object
    }

    func get(forKey: T1) -> T2? {
        let obj = dictionary[WeakHolder(object: forKey)]
        return obj
    }

    func forEach(_ handler: ((key: T1, value: T2)) -> Void) {
        dictionary.forEach {
            if let object = $0.key.object, let value = dictionary[$0.key] {
                handler((object, value))
            }
        }
    }
    
    func clean() {
        var removeList = [WeakHolder<T1>]()
        dictionary.forEach {
            if $0.key.object == nil {
                removeList.append($0.key)
            }
        }
        removeList.forEach {
            dictionary[$0] = nil
        }
    }
}

Solution 16 - Ios

Another example with using Objective-C associated objects and computed properties for Swift 3 and Swift 4

import CoreLocation

extension CLLocation {

    private struct AssociatedKeys {
        static var originAddress = "originAddress"
        static var destinationAddress = "destinationAddress"
    }

    var originAddress: String? {
        get {
            return objc_getAssociatedObject(self, &AssociatedKeys.originAddress) as? String
        }
        set {
            if let newValue = newValue {
                objc_setAssociatedObject(
                    self,
                    &AssociatedKeys.originAddress,
                    newValue as NSString?,
                    .OBJC_ASSOCIATION_RETAIN_NONATOMIC
                )
            }
        }
    }

    var destinationAddress: String? {
        get {
            return objc_getAssociatedObject(self, &AssociatedKeys.destinationAddress) as? String
        }
        set {
            if let newValue = newValue {
                objc_setAssociatedObject(
                    self,
                    &AssociatedKeys.destinationAddress,
                    newValue as NSString?,
                    .OBJC_ASSOCIATION_RETAIN_NONATOMIC
                )
            }
        }
    }

}

Solution 17 - Ios

I tried to store properties by using objc_getAssociatedObject, objc_setAssociatedObject, without any luck. My goal was create extension for UITextField, to validate text input characters length. Following code works fine for me. Hope this will help someone.

private var _min: Int?
private var _max: Int?

extension UITextField {    
    @IBInspectable var minLength: Int {
        get {
            return _min ?? 0
        }
        set {
            _min = newValue
        }
    }
    
    @IBInspectable var maxLength: Int {
        get {
            return _max ?? 1000
        }
        set {
            _max = newValue
        }
    }
    
    func validation() -> (valid: Bool, error: String) {
        var valid: Bool = true
        var error: String = ""
        guard let text = self.text else { return (true, "") }
        
        if text.characters.count < minLength {
            valid = false
            error = "Textfield should contain at least \(minLength) characters"
        }
        
        if text.characters.count > maxLength {
            valid = false
            error = "Textfield should not contain more then \(maxLength) characters"
        }
        
        if (text.characters.count < minLength) && (text.characters.count > maxLength) {
            valid = false
            error = "Textfield should contain at least \(minLength) characters\n"
            error = "Textfield should not contain more then \(maxLength) characters"
        }
        
        return (valid, error)
    }
}

Solution 18 - Ios

Here is an alternative that works also

public final class Storage : AnyObject {
    
    var object:Any?
    
    public init(_ object:Any) {
        self.object = object
    }
}

extension Date {
    
    private static let associationMap = NSMapTable<NSString, AnyObject>()
    private struct Keys {
        static var Locale:NSString = "locale"
    }
    
    public var locale:Locale? {
        get {
            
            if let storage = Date.associationMap.object(forKey: Keys.Locale) {
                return (storage as! Storage).object as? Locale
            }
            return nil
        }
        set {
            if newValue != nil {
                Date.associationMap.setObject(Storage(newValue), forKey: Keys.Locale)
            }
        }
    }
}



var date = Date()
date.locale = Locale(identifier: "pt_BR")
print( date.locale )

Solution 19 - Ios

First, Associated Objects should be the best right solution for the extended stored properties, because it comes from the Objective-C runtime, this is a great powerful feature that we should use before there are other native features of Swift language.

You should always aware that the associated objects will be released after there are no other objects to retain them, including swift objects, so don't use custom containers to retain the target values which won't be released automatically.

Second, for those additional associated key structure definitions, the core functions just need a UnsafeRawPointer for that, actually there is another best choice for that, #function is a static string which generated when compiling the source code, it also has its own address to use.

So, here is it:

var status: Bool? {
    get { objc_getAssociatedObject(self, #function) as? Bool }
    set { objc_setAssociatedObject(self, #function, newValue, .OBJC_ASSOCIATION_RETAIN_NONATOMIC)}
}

> Build for swift 5.

Last, keep in mind the object type with the association policy.

Solution 20 - Ios

I found this solution more practical

UPDATED for Swift 3

extension UIColor {

    static let graySpace = UIColor.init(red: 50/255, green: 50/255, blue: 50/255, alpha: 1.0)
    static let redBlood = UIColor.init(red: 102/255, green: 0/255, blue: 0/255, alpha: 1.0)
    static let redOrange = UIColor.init(red: 204/255, green: 17/255, blue: 0/255, alpha: 1.0)

    func alpha(value : CGFloat) -> UIColor {
        var r = CGFloat(0), g = CGFloat(0), b = CGFloat(0), a = CGFloat(0)
        self.getRed(&r, green: &g, blue: &b, alpha: &a)
        return UIColor(red: r, green: g, blue: b, alpha: value)
    }

}

...then in your code

class gameController: UIViewController {

    @IBOutlet var game: gameClass!

    override func viewDidLoad() {
        self.view.backgroundColor = UIColor.graySpace
    
    }
}

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionMarcos DuarteView Question on Stackoverflow
Solution 1 - IosjouView Answer on Stackoverflow
Solution 2 - IosWojciech NagrodzkiView Answer on Stackoverflow
Solution 3 - IosAlexKView Answer on Stackoverflow
Solution 4 - IosHepaKKesView Answer on Stackoverflow
Solution 5 - IosAdam WrightView Answer on Stackoverflow
Solution 6 - IosAmr HossamView Answer on Stackoverflow
Solution 7 - IosvalvolineView Answer on Stackoverflow
Solution 8 - IosvedranoView Answer on Stackoverflow
Solution 9 - IosMike PollardView Answer on Stackoverflow
Solution 10 - IosAshkan GhodratView Answer on Stackoverflow
Solution 11 - IosRuiKQView Answer on Stackoverflow
Solution 12 - IosDanView Answer on Stackoverflow
Solution 13 - IosVadim BulavinView Answer on Stackoverflow
Solution 14 - IosKelvin FokView Answer on Stackoverflow
Solution 15 - IosChanOnly123View Answer on Stackoverflow
Solution 16 - IosabdullahselekView Answer on Stackoverflow
Solution 17 - IosVadims KrutovsView Answer on Stackoverflow
Solution 18 - IosRondinelli MoraisView Answer on Stackoverflow
Solution 19 - IosItachiView Answer on Stackoverflow
Solution 20 - IosGiuseppe MazzilliView Answer on Stackoverflow