2012-01-25 62 views
15

我有一個UIScrollView,我需要子類和子類內我需要附加UIScrollViewDelegate,所以我可以實現viewForZoomingInScrollView方法。每個對象有多個代表?

然後,我有一個UIViewController,我需要實例,我創造了這個UIScrollView子類的對象,我也想使一個的UIViewController爲UIScrollViewDelegate這個對象,所以我可以在這個UIViewController類實現scrollViewDidZoom

如何才能使一個對象有兩個代表? (我知道我可以很容易地只有一個委託,只是在那裏實現這兩種方法,但出於設計的目的,我想按照我提到的方式來做)。

+0

你爲什麼要這樣做?爲什麼你不能只將消息從你的customScrollView傳遞給你的VC(有第二個(自定義)委託)? –

+0

也許這就是我需要做的,所以如果我在我的SV子類中實現了scrollViewDidZoom,那麼每當觸發它時我怎麼能發送一條消息給VC? @totumus maximus –

+0

你將不得不在你的自定義視圖中創建一個自定義的委託(協議),並讓你的VC委託它。在你的scrollview委託被調用的那一刻,你也可以調用自定義委託中的一個自定義委託方法。這樣scrollview保持自己的責任,你的父視圖會對特定的滾動函數作出反應。我會把它解釋爲對的答案。 –

回答

7

你不想要一個包含2個代表的對象。你想讓你的customScrollView保留自己的UIScrollViewDelegate函數的責任。

爲了讓您的父VC對UIScrollView的委託方法做出響應,您還必須在customScrollView中創建一個自定義委託。

在調用UIScrollViewDelegate函數的同時,您還將調用您的自定義委託中的一個委託函數。這樣你的父VC就會在你想要的時候做出迴應。

它看起來有點像這樣。

CustomScrollView.h

@protocol CustomDelegate <NSObject> 

//custom delegate methods 
-(void)myCustomDelegateMethod; 

@end 

@interface CustomScrollView : UIScrollView <UIScrollViewDelegate> 
{ 
    id<CustomDelegate> delegate 
    //the rest of the stuff 

CustomScrollView.m

-(void) viewForZoomingInScrollView 
{ 
    [self.delegate myCustomDelegateMethod]; 
    //rest of viewForZoomingInScrollView code 

ParentVC。^ h

@interface CustomScrollView : UIViewController <CustomDelegate> 
{ 
    //stuff 

ParentVC.m

-(void)makeCustomScrollView 
{ 
    CustomScrollView *csv = [[CustomScrollView alloc] init]; 
    csv.delegate = self; 
    //other stuff 

} 

-(void)myCustomDelegateMethod 
{ 
    //respond to viewForZoomingInScrollView 
} 

我希望這完全覆蓋你的問題。 祝你好運。

+0

謝謝你的寫作。 –

+0

總是樂於幫忙^^ –

+2

@TotumusMaximus一個ScrollView已經有一個名爲「delegate」的屬性,在這裏你嘗試聲明一個屬性名稱相同,這是BAD – onmyway133

2

我不認爲你可以有兩個UIScrollViewDelegate代表直接連接到同一個對象。

你可以做的是讓兩個代表鏈式連接。也就是說,你將一個代表連接到另一個代表,然後當它不能直接處理它們時,將前一個代理連接到另一個代理。

在任何情況下,我認爲我缺少一點點來完全建議解決方案,即您爲什麼需要第二個委託並且無法始終通過一個委託進行操作。換句話說,我認爲可能會有其他設計避免需要兩名代表。

3

簡答:你沒有。代表們通常是一個很脆弱的一對一關係:

@property (nonatomic, weak /*or assign*/) id<MyViewDelegate> delegate; 

有時你會看到一個「監聽器」設計模式,這是一個一對多的形式代表:

- (void) addListener:(id<MyViewListener>)listener; 
- (void) removeListener:(id<MyViewListener>)listener; 

在你的情況,在UIScrollView中看起來並不是一個很好的公共覆蓋點,允許子類指定viewForZoomingInScrollView。如果可能的話,我會避免讓UIScrollView成爲它自己的代表。你可以讓UIViewController成爲UIScrollViewDelegate並讓它提供viewForZooming。或者你可以創建一個使用UIScrollView的中間視圖子類,提供viewForZooming,並向上轉發其他委託方法。

12

有時將多個代表附加到滾動視圖是有意義的。在這種情況下,你可以建立一個簡單的代表團分路器:

// Public interface 
@interface CCDelegateSplitter : NSObject 

- (void) addDelegate: (id) delegate; 
- (void) addDelegates: (NSArray*) delegates; 

@end 

// Private interface 
@interface CCDelegateSplitter() 
@property(strong) NSMutableSet *delegates; 
@end 

@implementation CCDelegateSplitter 

- (id) init 
{ 
    self = [super init]; 
    _delegates = [NSMutableSet set]; 
    return self; 
} 

- (void) addDelegate: (id) delegate 
{ 
    [_delegates addObject:delegate]; 
} 

- (void) addDelegates: (NSArray*) delegates 
{ 
    [_delegates addObjectsFromArray:delegates]; 
} 

- (void) forwardInvocation: (NSInvocation*) invocation 
{ 
    for (id delegate in _delegates) { 
     [invocation invokeWithTarget:delegate]; 
    } 
} 

- (NSMethodSignature*) methodSignatureForSelector: (SEL) selector 
{ 
    NSMethodSignature *our = [super methodSignatureForSelector:selector]; 
    NSMethodSignature *delegated = [(NSObject *)[_delegates anyObject] methodSignatureForSelector:selector]; 
    return our ? our : delegated; 
} 

- (BOOL) respondsToSelector: (SEL) selector 
{ 
    return [[_delegates anyObject] respondsToSelector:selector]; 
} 

@end 

然後,只需設置此分路器的實例作爲滾動視圖的委託和附加任何數量的代表到分離器。他們都會收到代表團的活動。有些注意事項適用,例如所有代表被假定爲同一類型,否則在執行天真respondsToSelector時會遇到問題。這不是一個大問題,很容易將實現更改爲僅向支持它們的人發送委派事件。

+0

應該聲明爲 @property(assign)CCDelegateSplitter *代表? –

+2

而不是[NSMutableSet集合];使用[NSHashTable hashTableWithOptions:NSPointerFunctionsWeakMemory];因爲它將對委託對象持有較弱的參考,並且會避免對它們的保留週期 – Nav

+0

不要使用此解決方案,因爲參考,代理不能被釋放。使用Nav建議的內容,NSNotification或其他內容。只是不是... –

0

這裏涉及2個代表一個優雅的解決方案:

  • 自定義滾動視圖類LTInfiniteScrollViewUIView(不UIScrollView),並增加了一個UIScrollView作爲一個孩子。 LTInfiniteScrollView將自己設置爲UIScrollView的代表。

  • LTInfiniteScrollView定義了自己的delegate屬性和協議。因爲LTInfiniteScrollView沒有子類UIScrollView,所以沒有現有的delegate屬性發生衝突。