Swift Lazy and Optional properties

大憨熊 提交于 2020-01-01 05:45:14

问题


What is the difference between a Lazy or Optional property in Swift?

For example, if someone is building a navigation bar that comes in from the side, I think that should all be within one UIViewController. The user might never open the menu but sometimes they will.

var menu: NavigationBar?
lazy var menu: NavigationBar = NavigationBar.initialize()

Both of the optional I think are good code, because they don't create the view unless its needed. I understand Optional means there might be a value it might be nil. I also understand Lazy means don't worry about it until I need it.

Specific Question

My question is are their performance patterns (safety and speed) that say optionals are faster and safer or vise versa?


回答1:


OK, this is an interesting question, and I don't want to imply that the existing answers aren't good, but I thought I'd offer my take on things.

lazy variables are great for things that need to be setup once, then never re-set. It's a variable, so you could change it to be something else, but that kind of defeats the purpose of a lazy variable (which is to set itself up upon demand).

Optionals are more for things that might go away (and might come back again). They need to be set up each time.

So let's look at two scenarios for your side menu: one where it stays around while it's not visible, and another for when it is deallocated.

lazy var sideMenu = SideMenu()

So the first time the sideMenu property is accessed, SideMenu() is called and it is assigned to the property. The instance stays around forever, even when you're not using it.

Now let's see another approach.

var _sideMenu: SideMenu?
var sideMenu: SideMenu! {
    get {
        if let sm = _sideMenu {
            return sm
        } else {
            let sm = SideMenu()
            _sideMenu = sm
            return sm
        }
    }
    set(newValue) {
        _sideMenu = newValue
    }
}

(Note this only works for classes, not structs.)

OK so what does this do? Well it behaves very similarly to the lazy var, but it let's you re-set it to nil. So if you try to access sideMenu, you are guaranteed to get an instance (either the one that was stored in _sideMenu or a new one). This is a similar pattern in that it lazily loads SideMenu() but this one can create many SideMenu() instances, where the previous example can only create one once.

Now, most view controllers are small enough that you should probably just use lazy from earlier.

So two different approaches to the same problem. Both have benefits and drawbacks, and work better or worse in different situations.




回答2:


They're actually pretty different.

Optional means that the value could possibly be nil, and the user isn't guaranteeing that it won't be. In your example, var menu: NavigationBar? could be nil for the entire lifetime of the class, unless something explicitly assigns it.

Lazy on the other hand means that the assignment will not be called until it is first accessed, meaning that somewhere in code someone tries to use your object. Note however that it is STILL promised to not be nil if you declare it like you have here lazy var menu: NavigationBar = NavigationBar.initialize(), so no need to do optional chaining.

And actually, a variable can be BOTH Lazy AND Optional, which means that it's value will be loaded when it is first accessed, and that value might be nil at the point it's initialized or at any future point. For example:

lazy var menu: NavigationBar? = NavigationBar.initialize()

That NavigationBar.initialize() is now allowed to return nil, or someone in the future could set the menu to be nil without the compiler/runtime throwing errors!

Does that make the difference clear?

Edit: As to which is BETTER that's really a case by case thing. Lazy variables take a performance hit on first initialization, so the first access will be a slow one if the initialization process is long. Otherwise, they're nearly identical in terms of safety/performance. Optional variables you have to unwrap before using and so there is a very minor performance cost with that (one machine instruction, not worth the time to think about)




回答3:


Optional and lazy properties are not the same

  • An optional property is used when there are chances that the value might not be available(i.e can be nil). But in your scenario, the navigation bar will always be available, its just that the user might not open it.
  • So using a lazy property serves your purpose. The NavigationBar will only be initialised if the user taps on it.

I do not see any performance issues except that if you use an optional, there is an additional overhead of checking if the value is nil each time before accessing it.



来源:https://stackoverflow.com/questions/34816203/swift-lazy-and-optional-properties

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!