2012-05-26 50 views
5

Tôi có một lớp gọi là ToolbarView là lớp con của UIView và về cơ bản tạo UIView có thanh UIToolbar biến mất/xuất hiện lại ở trên cùng. Tôi cũng có một lớp con của ToolbarView được gọi là DraggableToolbarView cho phép người dùng kéo chế độ xem xung quanh màn hình.Đang cố gắng triển khai quyền thừa kế đại biểu

Tôi cần tạo đại biểu cho ToolbarView để có thể thông báo cho đối tượng/lớp khác khi thanh công cụ xuất hiện lại và biến mất. Tôi cũng cần tạo đại biểu cho DraggableToolbarView để tôi có thể thông báo cho đối tượng/lớp khác khi chế độ xem được kéo. DraggableToolbarViews delegate cũng sẽ cần thông báo cho một đối tượng/lớp khác khi thanh công cụ xuất hiện lại và biến mất.

Vì vậy, tôi quyết định thực hiện ToolbarViewDelegate, và đã DraggableToolbarViewDelegate kế thừa từ nó và có phương pháp riêng của nó như sau:

ToolbarView.h

#import <UIKit/UIKit.h> 

@protocol ToolbarViewDelegate; 

@interface ToolbarView : UIView <UIGestureRecognizerDelegate> 
{ 
    id <ToolbarViewDelegate> _toolbarViewDelegate; 
} 

@property(nonatomic, assign) id <ToolbarViewDelegate> toolbarViewDelegate; 

@end 

ToolbarView.m

#import "ToolbarView.h" 
#import "ToolbarViewDelegate.h" 

... 

- (void) showBars 
{  
     ... 
     if (self.toolbarViewDelegate) 
     { 
      [self.toolbarViewDelegate toolbarViewWillShowToolbar:self]; 
     } 

     ... 
} 

- (void) hideBars 
{ 
     ... 
     if (self.toolbarViewDelegate) 
     { 
      [self.toolbarViewDelegate toolbarViewWillHideToolbar:self]; 
     } 

     ... 
} 

Toolb arViewDelegate.h

@class ToolbarView; 

@protocol ToolbarViewDelegate 

@required 

- (void) toolBarViewWillShowToolbar:(ToolbarView *)toolbarView; 
- (void) toolBarViewWillHideToolbar:(ToolbarView *)toolbarView; 

@end 

DraggableToolbarView.h

#import "ToolbarView.h"

@protocol DraggableToolbarViewDelegate; 

@interface DraggableToolbarView : ToolbarView 
{ 
    id <DraggableToolbarViewDelegate> _draggableToolbarViewDelegate; 
} 

@property(nonatomic, assign) id <DraggableToolbarViewDelegate> draggableToolbarViewDelegate; 

@end 

DraggableToolbarView.m

#import "DraggableToolbarView.h" 
#import "DraggableToolbarViewDelegate.h" 

... 

- (void)drag:(UIPanGestureRecognizer *)sender 
{ 
    ... 
     if (self.draggableToolbarViewDelegate) 
     { 
      [self.draggableToolbarViewDelegate draggableToolbarViewWillDrag:self]; 
     } 

    ... 

} 

... 

DraggableToolbarViewDelegate.h

#import "ToolbarViewDelegate.h" 

@class DraggableToolbarView; 

@protocol DraggableToolbarViewDelegate <ToolbarViewDelegate> 

@required 

- (void) draggableToolbarViewWillDrag:(DraggableToolbarView *)draggableToolbarView; 

@end 

SomeViewController.h

#import <UIKit/UIKit.h> 
#import "ToolbarViewDelegate.h" 
#import "DraggableToolbarViewDelegate.h" 

@interface SomeViewController : UIViewController <ToolbarViewDelegate, DraggableToolbarViewDelegate> 
{ 

} 
@end 

SomeViewController.m

#import "DraggableToolbarView.h" 
... 
- (void) toolbarViewWillShowToolbar:(ToolbarView*)toolbarView 
{ 
    //NSLog(@"Toolbar Showed"); 
} 

- (void) toolbarViewWillHideToolbar:(ToolbarView*)toolbarView 
{ 
    //NSLog(@"Toolbar Hidden"); 
} 

- (void) draggableToolbarViewWillDrag:(DraggableToolbarView*)draggableToolbarView 
{ 
    //NSLog(@"Dragged"); 
} 

... 

[draggableToolbarView setDraggableToolbarViewDelegate:self]; 

... 

Khi tôi làm điều này chỉ DraggableToolbarDelegate phương pháp được đáp ứng. Tuy nhiên khi tôi cũng làm [drabbleToolbarView setToolbarViewDelegate:self] nó hoạt động. Tôi đã cố gắng làm cho mỗi đại biểu một cách riêng biệt mà không có thừa kế và nó hoạt động tốt vì vậy tôi tin rằng vấn đề không phải là trong bất kỳ phần nào khác của mã.

Bất cứ ai cũng có thể biết tại sao? Tôi đã tìm ra bằng cách làm cho các giao thức kế thừa, tôi cũng sẽ không phải đặt ToolbarViewDelegate cho một đối tượng DraggableToolbar.

UPDATE: Thêm nhiều nhiều mã

Trả lời

6

Trong code của bạn, bất kỳ trao DraggableToolbarView dụ có hai tính để kết nối với các đại biểu, người ta gọi là toolbarViewDelegate mà nó kế thừa từ lớp cha của nó, và một gọi là draggableToolbarViewDelegate được định nghĩa trong DraggableToolbarView riêng của mình. Bạn phải thiết lập cả hai thứ đó nếu bạn muốn bộ điều khiển nhận tất cả các tin nhắn đại biểu.

Tuy nhiên, điều bạn đang cố làm là có thể. Bạn cần sử dụng cùng một tên thuộc tính trong cả hai lớp khung nhìn của bạn, để chỉ có một kết nối đại biểu cho bất kỳ cá thể nào.

Đầu tiên, thay đổi tên của người được ủy quyền trong siêu lớp. (Lưu ý rằng bạn không cần, và thực sự không nên bận tâm, để khai báo một Ivar cho tài sản - nó được tạo ra bởi @synthesize.)

@interface ToolbarView : UIView <UIGestureRecognizerDelegate> 
@property (nonatomic, assign) id <ToolbarViewDelegate> delegate; 
@end 

Bạn sẽ sử dụng tên tài sản tương tự trong lớp con.

@interface DraggableToolbarView : ToolbarView 
@property (nonatomic, assign) id <DraggableToolbarViewDelegate> delegate; 
@end 

này được phép miễn là tên của Ivar ủng hộ trong phân lớp là khác nhau hơn so với các lớp cha, ví dụ:

// In superclass 
@synthesize delegate; 
// In subclass 
@synthesize delegate = delegate_; 

Bây giờ thay đổi tất cả những thông điệp đại biểu trong hai lớp xem sử dụng một thuộc tính này:

- (void)showBars 
{ 

    if (self.delegate) 
    { 
     [self.delegate ... 

- (void)drag:(UIPanGestureRecognizer *)sender 
{ 
    //... 
    if (self.delegate) 
    { 
     [self.delegate ... 

Bây giờ bạn có thể gửi setDelegate: đến một DraggableToolbarView và nó sẽ sử dụng các đại biểu tương tự cho các phương pháp kéo và chương trình/hi de phương pháp.

Cuối cùng, một thuật ngữ/chú thích giải thích. Đáp lại your previous question, Caleb đã sử dụng thuật ngữ chính xác cho các giao thức "xếp chồng lên nhau", và Richard thì không. Giao thức không được kế thừa từ mỗi khác, nhưng một giao thức có thể áp dụng số khác. Mối quan hệ tương tự, nhưng khác biệt. Khi một đối tượng tuân thủ đến một giao thức, nó hứa hẹn sẽ triển khai các phương thức được khai báo trong giao thức đó. Không có triển khai nào đi kèm với giao thức. Điều tương tự cũng đúng với một giao thức thông qua giao thức kia - các phương thức được khai báo là tồn tại trong cả hai.Khi bạn viết:

@protocol DraggableToolbarViewDelegate <ToolbarViewDelegate> 

bạn đang nói rằng bất kỳ đối tượng mà hứa hẹn sẽ thực hiện phương pháp DraggableToolbarViewDelegate 's cũng sẽ thực hiện các phương pháp từ ToolbarViewDelegate. Đó là tất cả những gì nó có nghĩa là. Một lần nữa, không có triển khai nào đi kèm với lời hứa đó.

Trong trường hợp này, điều đó có nghĩa là DraggableToolbarView có thể mong đợi đại biểu của mình triển khai các phương thức trong ToolbarViewDelegate.

+0

Đánh giá cao bài đăng tuyệt vời đó. Hãy suy nghĩ tôi có thể chỉ cần giữ cho các đại biểu riêng biệt, không phải là một fan hâm mộ lớn của việc đặt tên. Bạn thường làm gì hoặc khuyên bạn nên làm gì? –

+0

Vui vì tôi có thể giúp. Tôi không thấy bất cứ điều gì sai trái với việc ghi đè tài sản của đại biểu; nó làm cho cả hai mặt của trình dọn dẹp mã. –

1

Bạn đã không cho toàn bộ mã, nhưng từ bất cứ thứ gì ra khỏi đây, Hãy chắc chắn rằng

  1. ToolBarView của bạn và lớp con của nó có một đại biểu id <ToolBarViewDelegate> như một tài sản.
  2. DraggableToolbarViewDelegate của bạn mở rộng giao thức NSObject.
  3. và đối tượng ViewController khác của bạn tuân theo giao thức đại biểu chứ không phải thanh công cụ. Sau khi bộ điều khiển của bạn cho phép thực hiện các phương thức đại biểu và phù hợp với giao thức, hãy đặt đối tượng của khung nhìn đó thành self và sau đó sử dụng thuộc tính delegate được đặt trong khung nhìn để gọi các phương thức giao thức này.
Các vấn đề liên quan