
UIView hierarchy. The tasks of each view : to create elements, set up, decompose into places, animate. This is evident from the methods that are in the UIView: addSubview(), drawRect(), layoutSubviews(). class UIView: addSubview(), drawRect(), layoutSubviews().UIViewController class, you can see that he is in control of view: loads, reacts to screen loading and user actions, shows new screens. Often the code that needs to be in a UIView is written in subclasses of UIViewController , which makes it too large. Separate it.UIViewController life cycle begins with loadView() . A simplified implementation looks like this: // CustomViewController.swift func loadView() { self.view = UIView() } super.loadView() no need to call! // CustomViewController.swift override func loadView() { self.view = CustomView() } // CustomView.swift final class CustomView { let square: UIView = UIView() init() { super.init() square.backgroundColor = .red addSubview(square) } } CustomView, add it to the hierarchy, set the .frame . The .view property will be the class we need: // CustomViewController.swift print(view) // CustomView UIView . Let's fix this with a type conversion: // CustomViewController.swift func view() -> CustomView { return self.view as! CustomView } CustomView variables: // CustomViewController.swift func viewDidLoad() { super.viewDidLoad() view().square // } Ruslan Kavetsky proposed to remove code duplication using protocol extension:protocol ViewSpecificController { associatedtype RootView: UIView } extension ViewSpecificController where Self: UIViewController { func view() -> RootView { return self.view as! RootView } }
For each new controller, you only need to specify the protocol and subclass for itsUIViewthroughtypealias:// CustomViewController.swift final class CustomViewController: UIViewController, ViewSpecificController { typealias RootView = CustomView func viewDidLoad() { super.viewDidLoad() view().square // } }
// CustomView.swift init() { super.init() backgroundColor = .lightGray addSubview(square) } layoutSubviews() method. It is called every time the view size changes, so you can rely on the bounds size for correct calculations: // CustomView.swift override func layoutSubviews() { super.layoutSubviews() square.frame = CGRect(x: 0, y: 0: width: 200, height: 200) square.center = CGPoint(x: bounds.width / 2, y: bounds.height / 2) } property controls private, but I manage them through public variables or “in the knowledge” functions. Easier by example: // CustomView.swift private let square = UIView() var squarePositionIsValid: Bool { didSet { square.backgroundColor = squarePositionIsValid? .green : .red } } func moveSquare(to newCenter: CGPoint) { square.center = newCenter } viewDidLoad() empty. If you create a view in code, then you need to bind their actions through the target-action pattern, add a UIGestureRecognizer or associate delegates.view can be configured through Interface Builder (hereinafter IB).view object (not the controller) and set its class. Write your own loadView() not necessary, the controller will do it himself. But UIView still have to UIView type.
view , the Assistant Editor will recognize the UIView class and offer it as the second file in Automatic mode. So you can transfer IBOutlet to view .
CustomView class manually, write IBOutlet . You can now drag the marker and hover over an item in IB.
init() , but when working with IB, access to IBOutlet appears only after loading the interface from the UIStoryboard in the awakeFromNib() method: // CustomView.swift func awakeFromNib() { super.awakeFromNib() square.layer.cornerRadius = 8 } UIViewControllerNotification responseUIViewController controls only the interface. Everything related to business logic should be taken out of the controller, but this is a choice: MVP, VIPER, etc.UIView type. To do this, declare a property with the required class, override setter and getter , specifying the class: // CustomViewController.m @interface CustomViewController @property (nonatomic) CustomView *customView; @end @implementation - (void)setView:(CustomView *)view{ [super setView:view]; } - (CustomView *)view { return (CustomView *)super.view; } @end view , but encapsulation makes it easy to interact and read the code. Sometimes the view can be reused with another controller. For example, different controllers for the iPhone and iPad react differently to the appearance of the keyboard, but this does not change the view code in any way.UIViewController !Source: https://habr.com/ru/post/432718/
All Articles