2016-09-15 28 views
2

比方說,我有一個名爲MyCustomView的UIView的自定義子類。我們還要說,我在UIView上有一個名爲UIView+Dictionary的類別,它爲每個UIView添加一個名爲dictionary的NSDictionary屬性。任何只將Objective-C類別應用到當前類(或同等效果)的方法?

如果我是進口UIView+Dictionary.hMyCustomView.m然後內MyCustomView.m引用的每個觀點將有這樣的添加dictionary屬性,它在很多情況下是完全需要的行爲。

但是,如果我想UIView+Dictionary僅適用於MyCustomView本身,而不適用於MyCustomView.m中引用的每個UIView,是否有辦法這樣做(或實現類似效果)?

我想避免MyCustomView另一個自定義子類的子類(如MyViewWithDictionary),因爲我非常希望能夠導入多個類別的東西,類似於多重繼承(例如,UIView+DictionaryUIView+BorderUIView+CustomAnimations)。

在我實際的自己的場景中,我寫了一個類別來自動實現一個視圖控制器中的自定義UINavigationBar,但我希望該類別只適用於我導入類別的視圖控制器,而不是該文件中可能引用的任何其他視圖控制器。

任何和所有的見解都被讚賞!我很抱歉,因爲我相當確定上述效果有更正確的術語。

回答

0

正如Josh指出的那樣,除非您打電話給他們,否則添加在類別中的任何方法基本上都是惰性的。我遇到的問題是生成的屬性和類別中混雜的方法(因爲Josh也指出Objective-C中沒有混入)。

我能夠通過在我的類別中添加一個自定義BOOL來解決此問題,該類別默認爲NO,並充當我要指定的任何類別方法和屬性的「開關」。

E.g.,如果我想懶洋洋地實例化我dictionary財產,但只在MyCustomView,我能做到以下幾點:

// UIView+Dictionary.h 

@interface UIView (Dictionary) 
@property (nonatomic) BOOL enableDictionary; 
@property (nonatomic, strong) NSDictionary *dictionary; 
@end 

// UIView+Dictionary.m 

#import "UIViewController+CustomNavigationBar.h" 
#import <objc/runtime.h> 

@implementation UIView (Dictionary) 

- (void)setEnableDictionary:(BOOL)enableDictionary { 
    objc_setAssociatedObject(self, @selector(enableDictionary), @(enableDictionary), OBJC_ASSOCIATION_RETAIN_NONATOMIC); 
} 

- (BOOL)enableDictionary { 
    NSNumber *enableDictionaryValue = objc_getAssociatedObject(self, @selector(enableDictionary)); 
    if (enableDictionaryValue) { 
     return enableDictionaryValue.boolValue; 
    } 

    objc_setAssociatedObject(self, @selector(enableDictionary), @NO, OBJC_ASSOCIATION_RETAIN_NONATOMIC); 
    return self.enableDictionary; 
} 

- (void)setDictionary:(NSDictionary *)dictionary { 
    objc_setAssociatedObject(self, @selector(dictionary), dictionary, OBJC_ASSOCIATION_RETAIN_NONATOMIC); 
} 

- (NSDictionary *)dictionary { 
    if (!self.enableDictionary) { 
     return nil; 
    } 

    NSDictionary *dictionary = objc_getAssociatedObject(self, @selector(dictionary)); 
    if (dictionary) { 
     return dictionary; 
    } 

    objc_setAssociatedObject(self, @selector(dictionary), @{}, OBJC_ASSOCIATION_RETAIN_NONATOMIC); 
    return self.dictionary; 
} 

@end 

然後內-[MyCustomView viewDidLoad]我可以簡單地叫self.enableDictionary = YES。這樣,只有MyCustomView的實例纔會有非零的延遲實例化的NSDictionary。 (需要注意的是,在這個例子中,UIViews的所有實例仍然會迴應選擇@selector(dictionary),但我們的行爲會有所不同基於enableDictionaryYESNO。)

雖然這是一個簡單的例子,同樣的策略可以用於在類別中混用的方法。 (同樣,類別內的混合方法可能是不好的形式,但在某些情況下是必要的惡魔。)

2

但是,如果我想UIView + Dictionary只應用於MyCustomView本身[...]有沒有辦法做到這一點[...]?

只有將類別更改爲MyCustomView而不是UIView。

標題與任何給定實例上的類別的方法目前的無關。如果類別被編譯到您的程序中,那麼方法就在那裏,無論實例在哪裏創建。這就是前綴對添加到框架類中的方法非常重要的原因:類別具有全局效應,並且名稱衝突是未定義的行爲。

就編譯器而言,標題只會影響方法的可見性。無論如何,您都可以使用常規技巧在運行時調用它們。

該類別在類本身上生效,當啓動時初始化運行時。如果您希望類別的方法僅在某個類別上可用,則該類別必須在該類別上定義。

+0

謝謝,這是我懷疑的。我想我必須複製粘貼整個類別實現爲每個特定的類,然後我想要它應用?例如,如果我有'MyUIViewSubclassOne'和'MyUIViewSubclassTwo'(因爲類別不是可繼承的AFAIK)。 –

+0

是的,ObjC中沒有混入,所以如果你不能識別一個超類來放置類別,你必須明確地將它添加到它們中。但是,可以只在一個地方定義方法,並使用運行時庫將它們添加到類中。我也想知道爲什麼這些方法不適用於UIView是非常重要的:它們基本上是惰性的,除非您專門使用它們。雖然它們存在,但只有你的代碼知道這一點。 –

+0

攪拌方法x_x –

相關問題