Home IOS Development UIKit – loadView vs viewDidLoad

UIKit – loadView vs viewDidLoad

0
UIKit – loadView vs viewDidLoad

[ad_1]

Weak, unowned or robust subviews?

I’ve obtained various emails and tweets about this subject, so I made a decision to jot down about it, as a result of it’s actually exhausting to discover a correct reply for this query on the web. There are some nice posts and programming guides, some some articles are a bit older, nonetheless many individuals are asking the weak vs robust IBOutlet query even on the official boards, however noone actually explains the explanations, even on the boards they solely advocate this WWDC session video. So what is going on on right here? 🤔

I did some research on the subject and the very very first thing that we should always state is that this: Apple eliminated the viewDidUnload technique in iOS6 and from that model the iOS view controller lifecycle modified a bit. If you do not know a lot concerning the lifecycle strategies (demystified), it’s best to learn this text. This was fairly a giant change and Apple additionally touched their inside view administration. Earlier than iOS6 it was a standard apply to outline weak subviews. As a result of they’d a powerful reference to it they usually weren’t releasing it except you eliminated it from the view hierarchy.

This was about 10 years in the past. Now why are we nonetheless afraid of robust subviews? The primary purpose was the addSubview technique. The documentation states that it will create a powerful reference, which mechanically triggered my mind and I outlined my views as weak pointers, since they are going have a powerful reference to their mother and father. Appears affordable, proper? 🧠

Weak subviews

Properly, the issue is that if you wish to outline a weak variable we’ve to make use of an non-compulsory, however I do not like the concept of utilizing an non-compulsory variable because the view goes to be at all times there, it is a part of the view hierarchy sooner or later in, it isn’t going anyplace. It is solely going to be “destroyed” when my view controller is deallocated. Ought to I declare it as an implicitly unwrapped non-compulsory?!? Possibly.

import UIKit

class ViewController: UIViewController {

    weak var foo: UILabel! 
    weak var bar: UILabel? 
    
    override func viewDidLoad() {
        tremendous.viewDidLoad()

        
        foo.removeFromSuperview()
        foo.textual content = "crash"
    }
}

Truly you may go incorrect with unwrapped weak pointers, as a result of in case you take away your view from the view hiearchy sooner or later in time earlier than the view controller deallocation then your weak pointer will likely be nil. On this case there will not be any extra robust references and your view will likely be deallocated instantly, so if it is an implicitly unwrapped non-compulsory, then we’ve a bother. Your app will crash in case you attempt to entry the property, as a result of it will have a zero worth.

So sure you should utilize implicitly unwrapped non-compulsory variables to retailer subviews, however solely if you’re certain that you’re not going to take away it from the hiearchy. This additionally implies that you do not belief Apple’s view administration system, which is okay, there could be bugs, however truthfully that is fairly a vital function and it has been round for a decade by now. 🙃

The opposite various is to make use of a daily weak non-compulsory variable, however in that case you may at all times need to examine if it is nil or not, which goes to be a ache within the ass, however not less than you are going to be protected for certain. Private opinion: it will not well worth the effort in any respect and I by no means saved views like this.

Sturdy subviews

My advice is to belief Apple and outline your subviews as robust properties. Okay, this will also be problematic you probably have different robust references to the identical stuff, however on the whole if the view controller has the one reference to that given subview you ought to be completely superb.

Since it is a robust property you additionally need to initialize the view, however that is not a giant deal. You possibly can at all times initialize a view with a .zero body and that is it. Alternatively you may create a subclass with a daily init() technique, that is even higher, becuase you’re going to use auto structure for certain and this fashion can set the translatesAutoresizingMaskIntoConstraints property in a single go.

import UIKit

class Label: UILabel {
    
    init() {
        tremendous.init(body: .zero)

        self.translatesAutoresizingMaskIntoConstraints = false
    }
    
    @obtainable(*, unavailable)
    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been applied")
    }
    
    deinit {
        print("deinit Label")
    }
}

class ViewController: UIViewController {

    
    var foo: Label = .init()
    var bar: UILabel = .init(body: .zero)
    
    override func viewDidLoad() {
        tremendous.viewDidLoad()
        
    }
    
    deinit {
        print("deinit ViewController")
    }
    
}

By implementing a customized deinit technique and even higher, by making a symbolic breakpoint you may simply detect retain cycles and repair reminiscence points. I made some exams and I can verify you do not have to be afraid of robust views, each the viewcontroller and the view goes to be deallocated if it is wanted. 👻

Unowned subviews

Unowned and weak are roughly equal, I would say that you just will not must outline views as unowned references, as a result of they are often problematic if it involves initialization. It is normally higher to have a weak reference and examine for nil values, however after all there could be some instances the place you may want an unowned subview reference.

Utilizing loadView and viewDidLoad

The loadView technique can be utilized to create your individual views manually. It is best to by no means name this technique instantly, but it surely’s save to override it. The opposite factor that you shouldn’t is that if you’re utilizing this technique to override the foundation view, you then should not name tremendous.loadView().

import UIKit

class ViewController: UIViewController {
    
    override func loadView() {
        view = UIView(body: .zero)

        
            
    }
}

In each different case whenever you simply need to add views to the view hierarchy, it is fully superb to name the tremendous technique. I am normally implementing this technique to setup views and constraints.

import UIKit 

class ViewController: UIViewController {

    var foo: Label = .init()
    
    override func loadView() {
        tremendous.loadView()
        
        view.addSubview(foo)
        
        NSLayoutConstraint.activate([
            view.centerXAnchor.constraint(equalTo: foo.centerXAnchor),
            view.leadingAnchor.constraint(equalTo: foo.leadingAnchor),
            view.trailingAnchor.constraint(equalTo: foo.trailingAnchor),
            foo.heightAnchor.constraint(equalToConstant: 44),
        ])
    }
}

This fashion I can make sure that each single view is prepared by the point the viewDidLoad technique known as. It’s potential to configure views contained in the loadView technique too, however I desire to maintain the hierarchy setup there and I place every little thing else contained in the viewDidLoad perform. I imply controller associated stuff solely, like establishing navigation bar buttons and issues like this.

As I discussed this in my earlier article, I desire to make use of subclasses to configure my views, I additionally transfer structure constraints there (as a perform that returns them primarily based on some parameters) to maintain the view controller clear. Contained in the viewDidLoad technique I can carry out further consumer interface associated actions, however that is it I do not use it for including or styling views anymore.

Conclusion

Based mostly on my present data, here’s what I like to recommend for contemporary UIKit builders:

  • Outline your subviews as robust properties
  • All the time examine for leaks, implement deinit, use breakpoints or devices
  • Use weak / unowned references if you must break retain cycles
  • Add views to the hierarchy within the loadView technique
  • Use subclasses for styling views, make them reusable
  • Outline structure constraint getters on the view subclass, activate them inside loadView
  • Carry out remaining UI associated operations within the viewDidLoad perform

That is it. I am not saying that is the right strategy, however for me it is positively the best way to go ahead with UIKit. I do know for certain that many individuals are nonetheless working with the framework and it’s right here to remain for a very long time. I hope the following pointers will show you how to to know UIKit just a bit bit higher. ☺️

[ad_2]

LEAVE A REPLY

Please enter your comment!
Please enter your name here