First phone interview

Print 1 to 100 in sequence with no less than one thread

Var lock = os_unfair_lock() dispatchqueue.global ().async {self.action()} dispatchqueue.global ().async { Self. action(){os_unfair_lock_lock(&lock) if num >= 100{ os_unfair_lock_unlock(&lock) return } num += 1 print("\(num)----\(Thread.current)") os_unfair_lock_unlock(&lock) } }Copy the code

The global concurrent queue prints 1 to 10000 final results

  • It’s going to be less than 10,000 because it’s going to take num and add one

MVVM View and ViewModel and Model

  • The viewModel holds the Model view holds the viewModel and binds the View to the Model in both directions

How to implement MVVM without RAC

  • KVO is used to achieve bidirectional binding

Uiview.animate. During Listens for changes from alpha 0 to 1

let normalView = UIView(frame: CGRect(x: 0, y: 0, width: 100, height: 100)) normalView.backgroundColor = UIColor.red normalView.alpha = 0 view.addSubview(normalView) let timer = The Timer. ScheduledTimer (withTimeInterval: 0.01, repeats: true) { (time) in let layer = normalView.layer.presentation() print(layer? .opacity) } RunLoop.current.add(timer, forMode: RunLoopMode.commonModes) UIView.animate(withDuration: 2) { normalView.alpha = 1 }Copy the code

SetNeedlayout layouSubViews etc.

  • Call time of layouSubViews
    • Init initialization does not trigger layoutSubviews.
    • AddSubview triggers layoutSubviews (init twice if frame is set and once if frame is not set)
    • Setting the Frame of a view triggers layoutSubviews (if the value of the Frame changes before and after setting it). The x value alone will not change, but the Y value will change, strange)
    • Scrolling through a UIScrollView triggers layoutSubviews.
    • Rotating the screen triggers a layoutSubviews event on the parent UIView. (We often encounter this in development, for example, when the screen rotates, we need to modify the frame of the subview for the sake of the beautiful interface, then we will do the corresponding operation in layoutSubview)
    • Changing the size of a UIView also triggers the layoutSubviews event on the parent UIView
    • Call setLayoutSubviews directly. (Apple doesn’t recommend this.)
  • DrawRect call timing
    • If the RECt size is not set at UIView initialization, drawRect will not be called automatically. DrawRect is dropped after Controller->loadView and Controller->viewDidLoad. So don’t worry about in the controller, the drawRect of these views starts drawing. This allows you to set some value in the controller to the View(if the View draw requires some variable value).

    • This method is called after sizeToFit is called, so you can calculate size by calling sizeToFit first. The system then automatically calls the drawRect: method.

    • By setting the contentMode property to UIViewContentModeRedraw. DrawRect: is automatically called every time a frame is set or changed.

    • Call setNeedsDisplay directly, or setNeedsDisplayInRect: to trigger drawRect:, but only if rect cannot be zero.

The merits and demerits of componentized value transfer componentization scheme

  • Generally speaking, forward transmission means direct transmission, and reverse transmission uses block, etc
    • MGJRouter
      [MGJRouter openURL:@"MGJ://Test2/PushMainVC" WithUserInfo: @ {@ "navigationVC" : the self. The navigationController, @ "text" : @ "to pass the value before"} completion: nil]; / / reverse [MGJRouter openURL: @ "MGJ: / / Test3 / PushMainVC withUserInfo: @ {@" navigationVC ": the self navigationController, @"block":^(NSString *text){ NSLog(@"%@",text); }} completion:nil];Copy the code
    • CTMediator
      @objc public func A_showSwift(param:[AnyHashable:Any], callback:@escaping (String) -> Void) -> UIViewController? {var params = param / / forward params [" callback "] = callback / / reverse params [kCTMediatorParamsKeySwiftTargetModuleName] = "DYLCWithDrawKit" if let viewController = self.performTarget("DYLCWithDrawKit", action: "Extension_ViewController", params: params, shouldCacheTarget: false) as? UIViewController { return viewController } return nil } @objc func Action_Extension_ViewController(_ Params :NSDictionary) -> UIViewController {let num = params["keggg"]// let aViewController = SHWithDrawHomeViewController() aViewController.num = num as! CallBack = {(STR) in if let callBack = params[" callBack "] as? (String) -> Void {callback(STR)// reverse}} return aViewController}Copy the code
  • The pros and cons of componentization
    • Comparison of iOS componentization schemes

Download 100 large images to combine

  • Queue group
  • NSOperationQueue thread dependency

Singleton destruction

  • So we have an onceToken variable in our code, onceToken = 0 before the singleton generation, onceToken = -1 after the singleton generation, and then it stays -1, and when it’s destroyed, we set the singleton class to nil and we set the onceToken to 0

Practical application of the factory model

  • Practical application of iOS Factory mode

How do I check for memory leaks

  • MFinderLeaks, Instrement dynamic check, static analysis

How does AutoLayout implement the interface layout

  • AutoLayout uses the Cassowary algorithm and a set of Layout Engine Layout Engine

  • Before each view gets its Layout, the Layout Engine computationally translates views, constraints, priorities, and fixed sizes into final positions and sizes.

  • Specific working process:

    • When a constraint changes, adding or deleting views and setting constant and priority trigger the constraint change
    • The Layout Engine recalculates the Layout when constraints change
    • After getting the new constraint, call superview.setNeedLayout()
    • Then you go to the Deferred Layout Pass, which basically does some fault tolerance. For example, if there’s a constraint missing or there’s no certainty, it’s going to be fault-tolerant here
    • The Layout Engine then uses layoutSubviews() from top to bottom, calculates the position of each subview through Cassowary algorithm, and copies the frames of each subview from the Layout Engine
    • Finally, when the runloop arrives, redraw the operation (this step is the same as the manual layout)