2009-08-17 4 views
16

Mam zamiar napisać własną, niestandardową kontrolę, która różni się bardzo od UIButton. Jest tak bardzo odmienny, że zdecydowałem się napisać to od zera. Tak więc wszystkie podklasy I to UIControl.Jak zaimplementować mechanizm docelowego działania dla niestandardowego sterowania?

Kiedy moja kontrola dotknięciu się do środka, a następnie chcę odpalić wiadomości w drodze target-działania. Użytkownik tej klasy może utworzyć instancję, a następnie dodać niektóre cele i akcje dla tego zdarzenia.

tj. Wyobrażam sobie, że wewnętrznie wywołałbym metodę -fireTargetsForTouchUpEvent. Jak mogę utrzymać ten mechanizm działania celu w mojej klasie? Czy muszę dodać wszystkie cele i akcje do mojej własnej tablicy, a następnie po prostu wywołać selektory (akcje) na obiektach docelowych w pętli for? Czy istnieje bardziej inteligentny sposób na zrobienie tego?

Wyobrażam sobie, że dostarczę pewnych metod dodawania celów i akcji w przypadku niektórych zdarzeń, takich jak to zdarzenie dotyku (podnoszę to ręcznie, wywołując wewnętrzną metodę, gdy tak się dzieje). Dowolny pomysł?

+0

Zazwyczaj kontrole mają jeden cel, jeden selektor za zdarzenie. Chcesz więcej? –

+0

Czy mogę mieć więcej, jeśli chcę? Myślę, że tak...ale nie jestem pewna, –

Odpowiedz

5

Skoro planujesz podklasy UIControl, można po prostu użyć

- (void)addTarget:(id)target action:(SEL)action forControlEvents:(UIControlEvents)controlEvents; 

Używanie tego, każda klasa może zarejestrować się jako cel dla wszelkich zdarzeń, które chce na swoim kontrolerze niestandardowym.

13

Masz dobry pomysł. Oto w jaki sposób to zrobić:

@interface TargetActionPair : NSObject 
{ 
    id target; 
    SEL action; 
} 
@property (assign) id target; 
@property (assign) SEL action; 
+ (TargetActionPair *)pairWithTarget:(id)aTarget andAction:(SEL)selector; 
- (void)fire; 
@end 

@implementation TargetActionPair 
@synthesize target; 
@synthesize action; 

+ (TargetActionPair *)pairWithTarget:(id)aTarget andAction:(SEL)anAction 
{ 
    TargetActionPair * newSelf = [[self alloc] init]; 
    [newSelf setTarget:aTarget]; 
    [newSelf setAction:anAction]; 
    return [newSelf autorelease]; 
} 

- (void)fire 
{ 
    [target performSelector:action]; 
} 

@end 

Z tej grupy w miejscu przechowywania par cel/działanie jest bardzo proste:

MyCustomControl.h:

#import "TargetActionPair.h" 

@interface MyCustomControl : UIControl 
{ 
    NSMutableArray * touchUpEventHandlers; 
} 

- (id)init; 
- (void)dealloc; 

- (void)addHandlerForTouchUp:(TargetActionPair *)handler; 

@end 

MyCustomControl .m:

#import "TargetActionPair.h" 

@implementation MyCustomControl 

- (id)init 
{ 
    if ((self = [super init]) == nil) { return nil; } 
    touchUpEventHandlers = [[NSMutableArray alloc] initWithCapacity:0]; 
    return self; 
} 

- (void)dealloc 
{ 
    [touchUpEventHandlers release]; 
} 

- (void)addHandlerForTouchUp:(TargetActionPair *)handler 
{ 
    [touchUpEventHandlers addObject:handler]; 
} 

- (void) fireTargetsForTouchUpEvent 
{ 
    [touchUpEventHandlers makeObjectsPerformSelector:@selector(fire)]; 
} 

@end 

Po tym konfigurowania kontroli byłoby zrobić w następujący sposób:

[instanceOfMyControl addHandlerForTouchUp: 
     [TargetActionPair pairWithTarget:someController 
           andAction:@selector(touchUpEvent)]; 
+0

wow, największa odpowiedź, jaką kiedykolwiek tu miałem;) dzięki! W moim przypadku zorientowałem się, że UIControl wydaje mi się oferować to, czego potrzebuję. Ale kiedy są specjalne niestandardowe zdarzenia, które wymagają przetworzenia, twoja technika jest doskonała! –

+0

W rzeczywistości dla zdarzeń niestandardowych można użyć bitów UIControlEventApplicationReserved (16 dostępnych) i wywołać (void) sendActionsForControlEvents: (UIControlEvents) controlEvents; – Felixyz

+0

To, czego tu brakuje, to sposób na usunięcie celu/działania i być może duplikat. – pixelfreak

38

Chcę tylko wyjaśnić, co @Felixyz powiedział, ponieważ nie było dla mnie jasne, na początku.

Jeśli tworzysz podklasę UIControl, nawet jeśli planujesz wydarzenie niestandardowe, nie musisz śledzić własnych celów/działań. Funkcjonalność jest już tam, wszystko co musisz zrobić, to zadzwonić poniższy kod w swojej podklasy wyzwolić zdarzenie:

[self sendActionsForControlEvents:UIControlEventValueChanged];

Następnie w widoku lub widoku kontrolera, który instancję niestandardowego UIControl, zrób

[customControl addTarget:self action:@selector(whatever) forControlEvents:UIControlEventValueChanged];

dla niestandardowych razie tylko zdefiniować własne wyliczenia (np UIControlEventValueChanged jest równa 1 << 12). Wystarczy upewnić się, że jest w dopuszczalnym zakresie określonym przez UIControlEventApplicationReserved

+0

Tego właśnie potrzebowałem, dzięki –