1

I suddenly found that UIKit use weak attribute instead of assign in 9.3, it may already changed for a long time but I didn't notice that, feeling shamed.

@property(nullable,nonatomic,weak) id<UIScrollViewDelegate>        delegate;

I noticed that because of a question. In the old days, we need set the delegate of UIScrollView or UITableView's delegate to nil in dealloc method in case of crashing.

Now since SDK 9.3 has use weak attribute for delegate, I think if we build our apps using the newest SDK and deployment to any devices which system version are above iOS5 (weak attribute is involved at iOS5), we don't need to set the delegate to nil in dealloc method.

However in the question I mentioned above, I have left a comment: "I'm curious to know if it would crash when you use the newest SDK to build and deploy to devices which are below iOS 9. Can you have a try? " and the answer is "Yes, the base SDK is "Latest iOS (iOS 9.3)". And it still crash if I doesn't set delegate to nil in dealloc method. ". I'm confused.

My question is if we build with 9.3 SDK and deploy to the device which system version is below 9.3 (I mean the SDK which use assign rather than weak attribute), is the delegate weak ?

Hmm there is another question, if we build with 9.3 SDK, can we deploy to devices which system version is below iOS 5.0 (says 4.3, it don't support weak attribute) ?

Community
  • 1
  • 1
KudoCC
  • 6,912
  • 1
  • 24
  • 53
  • It's impractical to target iOS 4.x when building with iOS 9.3 SDK. The minimum target you can set is 6.0. And if you want to write code supporting iOS versions that far back, the `nil`ing of the `UITableView` `delegate` pointer would be the least of your problems. And as Duncan says, you shouldn't need to nil the delegate of the table view (in what scenario is the table view out-living its delegate). It feels like there's some deeper design problem here... – Rob May 26 '16 at 01:35
  • @Rob I still can force to set the target to 4.3 and build successfully, but I don't have a device with iOS 4.3 version, not sure if there is any problem there. – KudoCC May 26 '16 at 01:51
  • You miss my point: But why would you target iOS 4.3, which considerably complicates your project, increases your development time and effort, only to capture a fraction of a percent of market share? (As of May 9 2016, 84% of purchasers on app store are iOS 9, 11% iOS 8, and 5% for anything before iOS 8 ... I hate to guess what that fraction is for iOS 4.3.) You're worried about the `nil`ing this delegate (which, btw, I suspect is a manifestation of some different problem in the code), and there are much bigger issues involved in supporting iOS 4.3 thru 9.3. – Rob May 26 '16 at 04:51
  • BTW, Apple's counsel at one of their WWDC sessions was that developer's support back one major iOS release, where feasible. Clearly, go as far back as you want, but do so with full knowledge of the challenges and costs that entails. – Rob May 26 '16 at 04:59
  • Thanks for your advice. I just curious to know the challenges. My apps won't support 4.3, I like `__weak` rather than `__unsafe_unretained` : ) – KudoCC May 26 '16 at 06:08
  • No storyboards, cell prototypes, segues, auto-layout, dynamic type, NSURLSession, UIAppearance protocol, visual effect views. You have to deal with views getting unloaded in low memory pressure and rebuilding them when presented again. No contacts, photos or social frameworks. No extensions. No Swift. Etc. Even lots of basic API has changed. Just watch the what's new in Cocoa Touch WWDC videos for 2012, 13, 14, and 15 for an inventory of all the stuff we take for granted nowadays that you can't use. It can be done but entails lots of tiresome runtime checks. – Rob May 26 '16 at 07:44
  • Thanks very much @Rob !!! – KudoCC May 26 '16 at 08:04

2 Answers2

3

As you say, the weak attribute has been available since iOS 5. If you declare a variable as weak, it gets set to nil when the object it points to is deallocated.

If you make a delegate property assign rather than weak it's a good habit to set it to nil in your dealloc method, but it should not cause a crash if you fail to do so.

It doesn't usually cause a crash because at the completion of the dealloc method, the object in question is freed, so the value in that property is irrelevant.

Setting an assign property to nil is much more important in the case where the object it points to is deallocated, but the object doing the pointing is not being deallocated. In that case failing to set the property to weak can lead to a zombie.

EDIT:

OK, I just followed the link to the question you referred to. I get it now. That link was talking about a UITableView's delegate property. In some older iOS version (not sure when it changed) the tableView's delegate property was assign, not weak. Thus, when you have a view controller that serves as a table view's delegate, you should set the TABLE VIEW'S delegate property to nil in the view controller's dealloc method, to avoid cases where the table view tries to make a call to it's delegate (your view controller) after it's been deallocated.

I'm not sure if this is a real problem though, since the only thing that should have a strong reference to the table view is the view controller's view hierarchy, and when the view controller is deallocated, so is it's entire view hierarchy.

In answer to your question, what would matter is the OS version you are running on. UITableView is a system class, and the version of UITableView compiled into the OS determines the memory management rules for it's delegate. If UITableView declares it's delegate as assign on a given OS version, then it won't get set to nil when the object is deallocated.

Community
  • 1
  • 1
Duncan C
  • 128,072
  • 22
  • 173
  • 272
1

Today I've faced the same problem. In addition to Duncan answer:

To check is table view delegate weak or not, I've used following code:

#import <objc/runtime.h>

objc_property_t delegateProperty = class_getProperty([self.tableView class], "delegate");
unsigned int count = 0;
objc_property_attribute_t *list = property_copyAttributeList(delegateProperty, &count);
for (unsigned int i = 0; i<count; i++) {
    NSLog(@"%s", ((objc_property_attribute_t)list[i]).name);
    NSLog(@"%s", ((objc_property_attribute_t)list[i]).value);
}

Output on iOS 9:

T
@"<UITableViewDelegate>"
W
N

On iOS 8:

T
@"<UITableViewDelegate>"
N

So, it's clearly visible that on iOS 8 delegate is not weak. In both cases I've used application, compiled with 9.3 SDK.

Borys Verebskyi
  • 4,160
  • 6
  • 28
  • 42