zoukankan      html  css  js  c++  java
  • Lazy Initialization with Swift

    Lazy initialization (also sometimes called lazy instantiation, or lazy loading) is a technique for delaying the creation of an object or some other expensive process until it’s needed. When programming for iOS, this is helpful to make sure you utilize only the memory you need when you need it.

    This technique is so helpful, in fact, that Swift added direct support for it with the lazyattribute.

    To understand why this is useful, let’s first go over the old way of creating lazy properties.


    The Old Way

    In Objective-C, if you had a mutable array property you wanted lazily initialized, you’d have to write this:

    @property (nonatomic, strong) NSMutableArray *players;
    
    - (NSMutableArray *)players {
        if (!_players) {
            _players = [[NSMutableArray alloc] init];
        }
        return _players;
    }
    

    To people new to Objective-C, this presents a few different learning curves. First of all, you need to know that the method name has to exactly match the property name. If you misspelled the method name, this would silently fail and players would be nil when you tried to access it.

    You also need to know the _players instance variable was created for you automatically when your property was synthesized. Before Xcode 4.4, you had to manually synthesize your variable using the @synthesize keyword, like so:

    @synthesize players;
    // - or -
    @synthesize players = _players;
    

    Which would tell you that the instance variable used for the players property is _players. Nowadays Xcode handles synthesizing your properties for you. If you didn’t know that, then using the underscore before the property name might not be immediately obvious.


    The Swift Way

    Now in Swift, this can all be simplified down to one line:

    lazy var players = [String]()
    

    Simple, concise, and straight to the point.

    Keep in mind you do need to declare your lazy property using the var keyword, not the letkeyword, because constants must always have a value before initialization completes.

    If you wanted to add logic to your lazy initialization, Swift makes this easy by letting you define a closure after your lazy property:

    lazy var players: [String] = {
            var temporaryPlayers = [String]()
            temporaryPlayers.append("John Doe")
            return temporaryPlayers
            }()
    

    If you prefer, you can also lazily initiate your property using an instance method:

    lazy var players: [String] = self.initialPlayers()
        
    func initialPlayers() -> [String] {
        var players = ["John Doe"]
        return players
    }
    

    Or a class method:

    class TestClass {
        lazy var players = TestClass.initialPlayers()
        
        class func initialPlayers() -> [String] {
            var players = ["John Doe"]
            return players
        }
        
    }
    

    But people will most likely prefer using the new closure mechanic, as it keeps the logic near the property declaration.


    When should I use lazy initialization?

    One example of when to use lazy initialization is when the initial value for a property is not known until after the object is initialized.

    For example, if you have a Person class and a personalizedGreeting property. The personalizedGreeting property can be lazily instantiated after the object is created so it can contain the name of the person. Here’s a quick example:

    class Person {
            
        var name: String
        
        lazy var personalizedGreeting: String = {
            [unowned self] in
            return "Hello, (self.name)!"
            }()
        
        init(name: String) {
            self.name = name
        }
    }
    

    (Note that we had to say [unowned self] in here to prevent a strong reference cycle)

    When you initialize a person, their personal greeting hasn’t been created yet:

    let person = Person(name: "John Doe")
    // person.personalizedGreeting is nil
    

    But when you attempt to print out the personalized greeting, it’s calculated on-the-fly:

    NSLog(person.personalizedGreeting)
    // personalizedGreeting is calculated when used
    // and now contains the value "Hello, John Doe!"
    

    Another good time to use lazy initialization is when the initial value for a property is computationally intensive.

    For example, if you have an object that performs some really intense algorithm to determine the number of faces in a picture, make the numberOfFaces property lazily initialized.

    Or if you had a class that calculates several different large numbers, you would want to make sure they’re only calculated on-demand:

    class MathHelper {
       
        lazy var pi: Double = {
            // Calculate pi to a crazy number of digits
            return resultOfCalculation
            }()
    
    }
    

    Conclusion

    Direct support for lazy property initialization is just one of the many great features of Swift. In the next few months, I’ll cover more great features and shortcuts. Stay tuned!

    Updated 7/23/14: Updated to reflect the @lazy attribute being changed to lazy. Also updated to the new Array declaration syntax.

    http://mikebuss.com/2014/06/22/lazy-initialization-swift/

  • 相关阅读:
    vs中nodejs代码 resharper 提示 ECMAScript2015 Feature. your Current language level is ECMAScript5的解决办法
    port: ${SERVER_PORT:9190} #首先取环境变量,如果环境变量中没有,就取 9190 这个固定值
    SpringbBoot之JPA批量更新
    Linq To Object多字段组合唯一校验
    LINQ获取两个List的交集
    Linq实现分组后取最大(小)值
    Maven:浅析依赖(dependency)关系中 scope 的含义
    Source roots (or source folders) Test source roots (or test source folders; shown as rootTest)Resource rootsTest resource roots
    Parameter 0 of method sqlSessionTemplate in org.mybatis.spring.boot.autoconfigure.MybatisAutoConfiguration required a single bean, but 2 were found:
    sping boot/cloud配置文件 on 读取为true
  • 原文地址:https://www.cnblogs.com/feng9exe/p/9044789.html
Copyright © 2011-2022 走看看