1

A system class is subclassed with the delegate referencing itself.

class MyScrollView: UIScrollView {
   convenience init() {
     delegate = self
   }

   // Is this necessary?
   deinit {
      delegate = nil
   }
}

Does the UIScrollView.delegate property have to be set to nil when deallocating the instance?

Manuel
  • 14,274
  • 6
  • 57
  • 130

2 Answers2

2

Only strong references can keep and instance alive. A weak reference, such as this delegate member isn't sufficient to cause a strong reference cycle. That would require... strong references.

On another note, putting delegate = nil in the deinit wouldn't make much sense. Even if the delegate member was keeping this instance alive, (it isn't), then this deinit wouldn't be getting called in the first place.

Alexander
  • 59,041
  • 12
  • 98
  • 151
  • Hi, to be honest I had a similar question and I'm now quite confused, because in that documentation from Apple (MapKit)(https://developer.apple.com/documentation/mapkit/mkmapviewdelegate if found the strong advise from Apple to set delegate to nil – Hardy_Germany Nov 11 '17 at 11:24
  • @Hardy_Germany Well firstly, Apple is talking about the general case, and not in the case where `self` is the `delegate`. Also, there *is* a subtle benefit for setting `nil` to a delegate field. With the current implementation, objects that aren't strongly referenced but have existing weak references remain alive until the next access to them via a weak reference. Manually setting them to `nil` might expedite this deallocation process – Alexander Nov 11 '17 at 15:45
1
// Is this necessary?
deinit {
   delegate = nil
}

Setting values to nil in Swift's deinit is never, ever necessary (anything you think it's doing would be automatically done by ARC anyway). There are lots of other reason this isn't necessary in this specific case, but the fact that this deinit is never correct Swift trumps them all.

This has nothing to do with the title to your question; I'm not sure why that's the title.

Rob Napier
  • 286,113
  • 34
  • 456
  • 610
  • Where would I then set the delegate of a `UIScrollView` to nil when deallocating the instance that holds the `UIScrollView`, e.g. a `UIViewController`? – Manuel Sep 16 '17 at 20:26
  • I don't understand why you would do that. Do you mean when the delegate itself goes away? (That can be the object that holds the scroll view, but it doesn't have to be.) If the owner of the scrollview is the delegate, then it is correct to call `scrollView.delegate = nil` in the delegate's `deinit` (but it makes no sense in the scroll view's `deinit`) – Rob Napier Sep 16 '17 at 20:28
  • The delegate of a `UIScrollView` is `unsafe_unretained`, it should be set to nil manually despite ARC when deallocating the delegate object. – Manuel Sep 16 '17 at 20:29
  • That's not correct. It should be set to nil manually when deallocate the delegate. But it never makes sense to do so in the deallocation of the scroll view. When the scroll view goes away, the `delegate` pointer goes away too. – Rob Napier Sep 16 '17 at 20:29
  • In modern versions of iOS, I'm pretty sure `UIScrollView.delegate` is weak not unsafe_unretained anyway. What version of iOS is this? – Rob Napier Sep 16 '17 at 20:32
  • (I haven't looked at in a few years; I'm just looking at the current docs: https://developer.apple.com/documentation/uikit/uiscrollview/1619430-delegate?language=objc) – Rob Napier Sep 16 '17 at 20:33
  • iOS 10.3, an Apple Developer told me that due to compatibility reasons the delegates of system objects (UITableView, etc) are not the modern `weak` but still `unsafe_retained`. So according to the doc above it is weak, am confused now. – Manuel Sep 16 '17 at 20:34
  • I know the compatibility issue they're talking about, but I'm pretty certain it is weak in Swift. It's a testable question. Have you demonstrated that it's actually unretained? – Rob Napier Sep 16 '17 at 20:35
  • 1
    This is what the current header says: `weak open var delegate: UIScrollViewDelegate? // default nil. weak reference` – Rob Napier Sep 16 '17 at 20:36
  • Thanks, that means I actually don't have to set the delegates to nil? So the accepted answer there is wrong or only applies to ObjC? https://stackoverflow.com/questions/46249377/do-system-object-delegates-in-arc-need-to-be-set-to-nil/46249438?noredirect=1#comment79464120_46249438 – Manuel Sep 16 '17 at 20:40
  • 1
    If you have a very recent DTS indicating that the objects violate the header definitions, I would definitely do some testing to verify. It is possible for that to be true, but it would be contrary to the docs and the headers. There was a time when some `delegate` properties were still `unsafe_unowned` for historical reasons, but I don't think that's been true for a long time. The ObjC header also says weak: `@property(nullable,nonatomic,weak) id delegate; // default nil. weak reference` – Rob Napier Sep 16 '17 at 20:58
  • 1
    The answer you link to is basically saying "given what you've told me, you would need to clear it in the delegate's `deinit`". But (a) I don't believe what you've said there is currently true (and would like to see a demonstration that it is), and (b) isn't related to this question, which is the reverse situation and has never been required. – Rob Napier Sep 16 '17 at 20:59
  • The DTS is a week old, so I assume their answer is still true today for other delegates which are still not weak (e.g. AVAudioPlayer.delegate), but the example of UITableView.delegate in their answer template is presumably outdated. Thanks for shedding some light into this. – Manuel Sep 16 '17 at 21:18