懶加載宏
在創建各種子視圖時,我們習慣將這些子視圖定義爲對象屬性,然後通過屬性的獲取(getter)方法實現子視圖的懶加載。比如在控制器中我們需要創建一個自定會的子視圖,經常會這樣寫:
- (UIView *)wrapperView {
if (!_wrapperView) {
_wrapperView = [[CustomView alloc] init];
}
return _wrapperView;
}
當需要創建多個自定義的子視圖時,就需要重複寫類似代碼,我們可以通過定義一個宏來實現懶加載。
#ifndef JKLazyLoading
#define JKLazyLoading(_type_, _ivar_) \
- (_type_ *)_ivar_ { \
if (! _##_ivar_) { \
_##_ivar_ = [[_type_ alloc] init]; \
} \
return _##_ivar_; \
}
#endif
相應的上面通過宏可以如下調用:
JKLazyLoading(UIView, wrapperView)
self弱引用和強引用
在使用block時候,容易引起循環引用問題,爲了打破循環引用,我們經常在進入block前先對self做一個弱引用,在block裏爲防止引用的弱self釋放,進而對該弱引用的對象做一個強引用,如下:
__weak __typeof(self) weak_self = self;
[self doSomething:^{
__typeof(self) strong_self = weak_self;
...
}];
爲了簡化上面代碼的書寫,可以定義如下宏,
#ifndef weakify
#if DEBUG
#if __has_feature(objc_arc)
#define weakify(object) autoreleasepool{} __weak __typeof__(object) weak##_##object = object;
#else
#define weakify(object) autoreleasepool{} __block __typeof__(object) block##_##object = object;
#endif
#else
#if __has_feature(objc_arc)
#define weakify(object) try{} @finally{} {} __weak __typeof__(object) weak##_##object = object;
#else
#define weakify(object) try{} @finally{} {} __block __typeof__(object) block##_##object = object;
#endif
#endif
#endif
#ifndef strongify
#if DEBUG
#if __has_feature(objc_arc)
#define strongify(object) autoreleasepool{} __typeof__(object) object = weak##_##object;
#else
#define strongify(object) autoreleasepool{} __typeof__(object) object = block##_##object;
#endif
#else
#if __has_feature(objc_arc)
#define strongify(object) try{} @finally{} __typeof__(object) object = weak##_##object;
#else
#define strongify(object) try{} @finally{} __typeof__(object) object = block##_##object;
#endif
#endif
#endif
通過這個宏,上面代碼可以簡寫爲:
@weakify(self)
[self doSomething:^{
@strongify(self)
...
}];
關聯對象宏
有時候我們會通過關聯對象的方式爲已有類添加屬性,爲避免記憶這些API的使用方式,這裏給出一組宏可以簡化動態屬性的實現方式:
#ifndef JKDynamicProperty
#define JKDynamicProperty(_getter_, _setter_, _association_, _type_) \
- (void)_setter_ : (_type_ *)object { \
[self willChangeValueForKey:@#_getter_]; \
objc_setAssociatedObject(self, _cmd, object, OBJC_ASSOCIATION_ ## _association_); \
[self didChangeValueForKey:@#_getter_]; \
} \
- (_type_ *)_getter_ { \
return objc_getAssociatedObject(self, @selector(_setter_:)); \
}
#endif
按照如下方式使用該宏:
JKDynamicProperty(propetyName, setPropertyName, RETAIN_NONATOMIC, PropertyClass);