如何优雅地将UICollectionViewCell/UITableViewCell属性设为只读?
优雅实现UITableViewCell只读属性的方案
嘿,这个场景我太熟悉了!之前做Cell和父VC交互的时候也踩过类似的坑,其实不用搞两个属性那么繁琐,有更简洁的方式来解决,下面给你两种靠谱的方案:
方案一:类扩展重写为readwrite(最推荐)
核心思路是:对外暴露readonly属性,在内部的类扩展里把它改成readwrite,这样编译器就会自动生成带下划线的成员变量_targetMyProductsVC,你就能直接用懒加载的方式实现了。
具体代码实现:
- 在
.h文件里声明对外的只读属性:
@interface ProductsCell : UITableViewCell @property (nonatomic, strong, readonly) MyProductsVC *targetMyProductsVC; @end
- 在
.m文件的类扩展里重写属性为可写:
@interface ProductsCell () // 这里把readonly改成readwrite,内部可以赋值/使用成员变量 @property (nonatomic, strong, readwrite) MyProductsVC *targetMyProductsVC; @end
- 实现你的懒加载getter方法(和你原来的逻辑一样,但现在不会报错了):
- (MyProductsVC *)targetMyProductsVC { if (!_targetMyProductsVC) { UIResponder *target = self.nextResponder; do { target = target.nextResponder; // 注意:这里要保持类名一致,你代码里的ZBMyProductsVC和MyProductsVC要统一哦 } while (![target isKindOfClass:MyProductsVC.class] && target != nil); _targetMyProductsVC = (MyProductsVC *)target; } return _targetMyProductsVC; }
这种方式的好处是:对外完全是只读属性,外部代码无法修改;内部又能正常使用成员变量缓存结果,逻辑清晰又简洁。
方案二:手动合成成员变量(适合老版本编译器)
如果你的项目用的是比较老的Xcode版本,类扩展的方式可能有兼容问题,那可以手动合成成员变量:
在.m文件顶部直接声明成员变量:
@implementation ProductsCell { MyProductsVC *_targetMyProductsVC; }
然后实现getter方法,和你原来的逻辑一样,这样即使属性是readonly,也能直接使用_targetMyProductsVC了。
小提醒:关于responder链的优化
你当前的getter逻辑是对的,第一次找到父VC后就缓存起来,避免每次调用都遍历responder链。不过要注意:如果Cell被复用后,父VC可能发生变化(比如同一个Cell被放到不同的VC里),这时候最好在prepareForReuse方法里清空缓存:
- (void)prepareForReuse { [super prepareForReuse]; _targetMyProductsVC = nil; }
这样下次调用targetMyProductsVC时会重新遍历responder链,保证拿到的是当前的父VC。
内容的提问来源于stack exchange,提问作者dengApro
相关产品推荐
相关产品推荐

