我有一個自定義容器視圖控制器,用於管理我的應用程序的視圖層次結構。我知道每個控制器都是這個容器控制器的某個孩子。我認爲在UIViewController上有一個允許我訪問容器控制器的類別會很好,不管我在層次結構中的哪個位置。objc_setAssociatedObject在所有子類的類別集中
這涉及遞歸控制器層次結構,所以我認爲這將是一個很好的嘗試,只有這樣做,每個控制器走一次。因此,通過objc_setAssociatedObject,我找到容器並設置了一個標誌,以便我知道是否需要在隨後的調用中遍歷層次結構(如果viewcontroller曾經移動過,我計劃使其無效),但這可能會過度,我沒有那麼遠)。
無論如何,除了我的標誌是否已經走過層次似乎是附加到UIViewController,而不是UIViewController的特定子類,大部分工作正常。
我嘗試在我的關聯對象上設置默認值無效,我試了一下+ load。
任何想法?如何獲取類別中的關聯對象以與該類別定義的類的子類關聯?
這裏是我的代碼,很好的衡量。
#import "UIViewController+LMPullMenuContainer.h"
#import <objc/runtime.h>
static char const * const CachedKey = "__LM__CachedBoolPullMenuAssociatedObjectKey";
static char const * const PullMenuKey = "__LM__PullMenuAssociatedObjectKey";
@implementation UIViewController (LMPullMenuContainer)
+ (void)load {
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
SEL initSelector = @selector(initWithCoder:);
SEL pullViewInitSelector = @selector(init__LM__Swizzled__WithCoder:);
Method originalMethod = class_getInstanceMethod(self, initSelector);
Method newMethod = class_getInstanceMethod(self, pullViewInitSelector);
BOOL methodAdded = class_addMethod([self class],
initSelector,
method_getImplementation(newMethod),
method_getTypeEncoding(newMethod));
if (methodAdded) {
class_replaceMethod([self class],
pullViewInitSelector,
method_getImplementation(originalMethod),
method_getTypeEncoding(originalMethod));
} else {
method_exchangeImplementations(originalMethod, newMethod);
}
});
}
- (instancetype)init__LM__Swizzled__WithCoder:(NSCoder *)coder {
self = [self init__LM__Swizzled__WithCoder:coder];
if (self != nil)
{
objc_setAssociatedObject(self, CachedKey, [NSNumber numberWithBool:NO], OBJC_ASSOCIATION_RETAIN_NONATOMIC);
objc_setAssociatedObject(self, PullMenuKey, nil, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
return self;
}
- (LMPullMenuContainerViewController*)pullMenuContainerController {
BOOL isCached = [objc_getAssociatedObject(self, CachedKey) boolValue];
if (isCached) {
return objc_getAssociatedObject(self, PullMenuKey);
} else {
return [self pullMenuParentOf:self];
}
}
- (LMPullMenuContainerViewController *)pullMenuParentOf:(UIViewController *)controller {
if (controller.parentViewController) {
if ([controller.parentViewController isKindOfClass:[LMPullMenuContainerViewController class]]) {
objc_setAssociatedObject(self, CachedKey, [NSNumber numberWithBool:YES], OBJC_ASSOCIATION_RETAIN_NONATOMIC);
objc_setAssociatedObject(self, PullMenuKey, controller.parentViewController, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
return (LMPullMenuContainerViewController *)(controller.parentViewController);
} else {
return [self pullMenuParentOf:controller.parentViewController];
}
} else {
objc_setAssociatedObject(self, CachedKey, [NSNumber numberWithBool:YES], OBJC_ASSOCIATION_RETAIN_NONATOMIC);
objc_setAssociatedObject(self, PullMenuKey, nil, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
return nil;
}
}
現在我已經辭職了,在必要時手動設置屬性。
你是什麼意思的標誌是*「附加到UIViewController,而不是特定的UIViewController子類」*?關聯的對象附加到(子)類的實例,而不是類。 –
這就是我的想法和預期,但是,當我逐步瀏覽它時,我發現'isCached'在特定的子類上設置之前返回了'YES'(但是在其他子類上設置之後)。 –
也許不相關,但是不應該將結果緩存在'return [self pullMenuParentOf:controller.parentViewController]; case? –