-1

For example, there is a class

@interface Person: NSObject {
    @property (weak) NSString *str;
@end

@implementation
    - (void) init {
      str = @"XYZ";
    }
@end
  • Is it safe to declare all properties to weak to avoid reference count overhead?
  • If not safe then why it's not safe?
  • What will be the reference count of str?
rmaddy
  • 314,917
  • 42
  • 532
  • 579
rishu1992
  • 1,414
  • 3
  • 14
  • 33

2 Answers2

2

Is it safe to declare all properties to weak to avoid reference count overhead?

This is problematic on two counts. First, weak doesn't avoid reference counting. It actually performs more bookkeeping than strong. See Lots of overhead for weak property? for a good discussion of that.

Next, this is wrong because weak and strong mean different things that cannot be interchanged. As MartinM notes, if you make your properties weak, they'll just disappear as soon as you assign them if nothing else is holding onto them.

If not safe then why it's not safe?

It is totally safe. It just won't work. Your program will have well defined behavior, and shouldn't crash due to marking all your properties weak. Most of your properties will just be nil. If you used unsafe_unretained instead of weak, then you would avoid some reference counting overhead, and your program would typically crash (because the objects would still be destroyed, the pointers would just become invalid).

What will be the reference count of str?

That is not a meaningful question, even though it feels like one. In this particular case the answer is 9,223,372,036,854,775,807 because that's always the retain count of a static string, because static strings cannot be destroyed and ignore retain/release calls. (That value is NSNotFound in ObjC. I believe this used to return 1,152,921,504,606,846,975, but my tests indicate it's changed.)

But in the general case, it could be anything at this point in time. And what it is at this point in time versus at the end of the event loop (when the autoreleasepool drains) could be dramatically different. Do not chase retain count values. They will always lie to you. Create strong references to things you care about. Create weak references only when you need them for their specialized purposes.

Retain counts are an internal implementation detail. Before ARC, they were misleading to the point of uselessness. Since ARC, they're like asking "what assembly instructions will this compile to." It's important, but it depends on everything else about the program and how it's compiled.

If you have a specific performance problem related to memory management, then there are techniques for dealing with that in a case-by-case basis, and StackOverflow can help you. But ARC is extremely good at optimizing memory management. Let it do its job.

Rob Napier
  • 286,113
  • 34
  • 456
  • 610
  • After reading your answer, I have got one more question. So if I assign weak _str to another strong property, will the reference count increase to 2? See, even if the _str is weak, when I alloc/int it should have ref count as 1. Now assigning it to another strong var will it increase ref count to 2? – rishu1992 Jan 17 '19 at 04:40
  • Sometimes. In this case, no, because the string is static, so its retain count is never going to change (it's always going to be some enormous number, `NSNotFound` in my latest tests, but don't bet on that). Depending on how the string is generated and how many autoreleases are attached to it, it might have an arbitrarily high retain count at the point that you assign it. If ARC can optimize out the assignment, then it might only have a retain count of 1. Assigning to a strong variable creates a strong reference; that's all that's promised. No specific retain count is promised. – Rob Napier Jan 17 '19 at 14:03
  • If you want to dig into the what parts of the implementation details are promised, see http://clang.llvm.org/docs/AutomaticReferenceCounting.html. Also: https://mikeash.com/pyblog/friday-qa-2011-09-30-automatic-reference-counting.html and https://mikeash.com/pyblog/friday-qa-2010-07-16-zeroing-weak-references-in-objective-c.html But specific retain counts were meaningless even before ARC came along. See the docs for `-retainCount`: https://developer.apple.com/documentation/objectivec/1418956-nsobject/1571952-retaincount?language=objc# – Rob Napier Jan 17 '19 at 14:05
  • For the correct way to think about pre-ARC memory management: https://developer.apple.com/library/archive/documentation/Cocoa/Conceptual/MemoryMgmt/Articles/mmRules.html#//apple_ref/doc/uid/20000994 (especially "Practical Memory Management"). For the ARC transition: https://developer.apple.com/library/archive/releasenotes/ObjectiveC/RN-TransitioningToARC/Introduction/Introduction.html. For modern ObjC: https://developer.apple.com/library/archive/documentation/Cocoa/Conceptual/ProgrammingWithObjectiveC/EncapsulatingData/EncapsulatingData.html#//apple_ref/doc/uid/TP40011210-CH5-SW3 – Rob Napier Jan 17 '19 at 14:14
1

You should know which properties should be weak and which strong. It is a common practice declaring for example all IBOutlets as weak because they are being retained by the view that comes from the storyboard, so it is not necessary to keep a strong reference in the viewcontroller.

Another example would be a delegate that should always be weak, or it will prevent the delegate (mostly another viewcontroller) from being deallocated because the delegate's holder is still alive.

In your case, str will be nil after init, because there are no other references to its content. You should actually get a compiler warning if you do this.

Take a look at this thread with more detailed explanation: Weak and strong property setter attributes in Objective-C

MartinM
  • 832
  • 6
  • 12