1

According to class references of UICollectionView and UICollectionViewLayout, UICollectionView holds a strong reference to its collectionViewLayout property, and UICollectionViewLayout also holds a strong reference to its collectionView property.

In UICollectionView,

@property(nonatomic, strong) UICollectionViewLayout *collectionViewLayout

In UICollectionViewLayout, (strong is a default property attribute).

@property(nonatomic, readonly) UICollectionView *collectionView   

Looks like a retain cycle here. Why doesn't UICollectionViewLayout hold a weak reference to collectionView instead?

Zack Zhu
  • 378
  • 4
  • 8
  • 1
    `strong` is never the default attribute for a readonly property as readonly properties doesn't have any backing ivar and `strong` or `weak` only applies to backing ivars. `UICollectionViewLayout` possibly keeps a `weak` reference of its parent `UICollectionView` and returns it from the getter of the readonly property, thus avoiding retain cycle. – Ayan Sengupta Aug 17 '16 at 23:21

2 Answers2

1

As stated in the answer to Does Objective-C readonly property need to specify retain or copy?, strong and weak don't apply to a read-only property - at least not based on the public declaration of the property.

What actually matters with a read-only property is how it is actually implemented. It's quite likely that the property is redeclared in the private class extension as:

@property (nonatomic, weak, readwrite) UICollectionView *collectionView;

This would avoid a retain cycle between the collection view and its layout.

Community
  • 1
  • 1
rmaddy
  • 314,917
  • 42
  • 532
  • 579
  • Good answer! So if the readonly property doesn't have a getter and is not redeclared as readwrite internally, strong should apply to the property too because it has an ivar now, is this correct? – Zack Zhu Aug 18 '16 at 00:21
  • A read-only property only has a getter, not a setter. An ivar is strong by default. – rmaddy Aug 18 '16 at 00:29
  • I mean its getter is not implemented so the complier will synthesize an ivar for it. – Zack Zhu Aug 18 '16 at 00:32
1

In UICollectionViewLayout, (strong is a default property attribute).

@property(nonatomic, readonly) UICollectionView *collectionView

It is the default but a readonly property has no storage, it is just a getter. Internally the layout must have a weak reference to the collection view. I don't have any knowledge of its actual source code but it could look like this:

@interface UICollectionViewLayout ()
@property(nonatomic, weak, readwrite) UICollectionView *collectionView;
@end

But if you ran Instruments and actually found a leak you should filed a radar because it is definitely a bug in my book.

Felipe Cypriano
  • 2,727
  • 22
  • 32
  • Good answer! But does readonly property always have no storage? if the readonly property's getter is not implemented and the property is not redeclared as readwrite internally, it will have an ivar, right? – Zack Zhu Aug 18 '16 at 00:24
  • Oh I was about to answer "no" but it looks like the compiler does auto synthesize a `readonly` property with an ivar. I'll try to find a something in the runtime to inspect the ivar to see if it is strong, I'm curious now too. I'll update the answer if I find anything. – Felipe Cypriano Aug 18 '16 at 00:31
  • Thanks! I think it should be strong. – Zack Zhu Aug 18 '16 at 00:36
  • I think you are right. I did find a `class_getWeakIvarLayout` but not an easy way to actually use it, I'll leave it there if anyone wants to dig deeper. – Felipe Cypriano Aug 18 '16 at 00:45