2009-07-30 14 views
15

Apple thực sự hài hước. Ý tôi là, họ nói rằng tác phẩm này hoạt động:Bí quyết nào để truyền sự kiện cho người trả lời tiếp theo trong chuỗi phản hồi?

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event { 
    UITouch* touch = [touches anyObject]; 
    NSUInteger numTaps = [touch tapCount]; 
    if (numTaps < 2) { 
     [self.nextResponder touchesBegan:touches withEvent:event]; 
    } else { 
     [self handleDoubleTap:touch]; 
    } 
} 

Tôi có bộ điều khiển chế độ xem. Như bạn biết, Xem bộ điều khiển kế thừa từ UIResponder. Điều đó xem điều khiển tạo ra một đối tượng MyView kế thừa từ UIView, và thêm nó như là một subview để xem riêng của nó.

Vì vậy, chúng tôi có:

Xem bộ điều khiển> có Chế độ xem (tự động)> có MyView (là UIView).

Bây giờ bên trong MyView tôi đặt mã như trên với NSLog in "chạm MyView". Nhưng tôi chuyển tiếp sự kiện cho người trả lời tiếp theo, giống như ở trên. Và bên trong ViewController tôi có phương thức touchesBegan khác chỉ in NSLog a la "bộ điều khiển xem cảm động".

Bây giờ hãy đoán điều gì: Khi tôi chạm vào MyView, nó in "chạm MyView". Khi tôi chạm vào bên ngoài của MyView, đó là quan điểm của VC sau đó, tôi nhận được một "bộ điều khiển xem cảm động". Vì vậy, cả hai công việc! Nhưng những gì không hoạt động là chuyển tiếp sự kiện. Bởi vì bây giờ, thực sự là phần trả lời tiếp theo nên là bộ điều khiển khung nhìn, vì không có gì khác trong số này. Nhưng phương thức xử lý sự kiện của VC không bao giờ được gọi khi tôi chuyển tiếp nó.

% $ &! § !!

Ý tưởng?

Đã tìm ra những thứ kỳ lạ Trả lời tiếp theo của MyView là chế độ xem của bộ điều khiển chế độ xem. Điều đó có ý nghĩa, bởi vì MyView là một tiểu thuyết về điều đó. Nhưng tôi đã không sửa đổi UIView này từ bộ điều khiển xem. nó không có gì tùy chỉnh. Và nó không thực hiện bất kỳ xử lý sự kiện cảm ứng nào. Không phải thông báo sẽ được chuyển sang bộ điều khiển chế độ xem? Làm thế nào tôi có thể để nó vượt qua? Nếu tôi loại bỏ mã xử lý sự kiện trong MyView, thì sự kiện sẽ đến độc đáo trong trình điều khiển khung nhìn.

Trả lời

5

Theo similar question, phương pháp của bạn sẽ hoạt động.

Điều này khiến tôi nghĩ rằng chế độ xem của bạn là nextResponderkhông thực sự là ViewController, như bạn nghi ngờ.

tôi sẽ thêm một cách nhanh chóng NSLog trong mã chuyển tiếp của bạn để kiểm tra những gì nextResponder của bạn thực sự chỉ ra:

if (numTaps < 2) { 
    NSLog(@"nextResponder = %@", self.nextResponder); 
    [self.nextResponder touchesBegan:touches withEvent:event]; 
} 

Bạn cũng có thể thay đổi các thông điệp NSLog khác của bạn để họ ra loại và thông tin địa chỉ:

NSLog(@"touched %@", self); 

touched <UIView 0x12345678>

Điều này sẽ giúp bạn bắt đầu chẩn đoán sự cố.

+0

Cảm ơn eJames. MyView cho tôi biết phần trả lời tiếp theo chính xác là khung nhìn của bộ điều khiển khung nhìn. Các địa chỉ bộ nhớ phù hợp hoàn hảo. tuy nhiên, touchesBegan này sẽ không được gọi. nhưng bây giờ tôi thấy rằng phương thức này sẽ được gọi trên khung nhìn của trình điều khiển khung nhìn, nhưng không phải trên chính trình điều khiển khung nhìn. nhưng sau đó, sự kiện này sẽ không tiếp tục sủi bọt lên bộ điều khiển xem của chế độ xem không xử lý nó không? hoặc là một trường hợp đặc biệt khác bởi vì tôi gửi nó bằng tay? –

+0

Vâng, tôi cho rằng điều đó có ý nghĩa. Việc thực thi mặc định của 'touchesBegan:' không làm gì cả, vì vậy khi bạn truyền nó vào đối tượng 'UIView' tiếp theo, nó chỉ đơn giản là kết thúc. Có khả thi để chỉ cần chuyển sự kiện cảm ứng vào viewController theo cách thủ công không? –

+0

Bạn đã thử gọi '[super touchesBegan: ...]' thay vì '[self.nextResponder touchesBegan: ...]' Tôi đã thấy một số người sử dụng phương pháp đó, nhưng tôi không chắc nó làm gì. –

2

Có nên 100% hoạt động trong trường hợp phổ biến. Tôi vừa thử với dự án thử nghiệm và mọi thứ có vẻ ổn.

Tôi đã tạo Ứng dụng xem dựa trên. Sử dụng Interface Builder đặt UIView mới cho đến View hiện tại.Sau đó tạo tệp mới với lớp con của UIView và chọn lớp vừa tạo cho chế độ xem mới của tôi. (Interface Builder-> Class identity-> Class-> MyViewClass)

Thêm các chức năng xử lý chạm cho cả MyViewClass và UIViewController.

// MyViewClass

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event { 
NSLog(@"myview touches"); 
[self.nextResponder touchesBegan:touches withEvent:event]; 
} 

// ViewController

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event { 
    NSLog(@"controller touches"); 
} 

tôi nhìn thấy cả hai NSLogs khi báo chí MyViewClass. Bạn đã sử dụng tệp Trình xây dựng giao diện và XIB khi tải ViewController của bạn hoặc đặt chế độ xem theo chương trình với hàm loadView?

1

Tôi biết bài đăng này cũ nhưng tôi nghĩ rằng chia sẻ id vì tôi đã có một trải nghiệm tương tự. Tôi đã sửa nó bằng cách đặt userInteractionEnabled thành NO cho chế độ xem của bộ điều khiển xem được tạo tự động.

4

Gặp sự cố với điều này, vì chế độ xem tùy chỉnh của tôi sâu hơn trong cấu trúc phân cấp chế độ xem. Thay vào đó, tôi trèo lên chuỗi đáp ứng cho đến khi nó tìm thấy UIViewController;

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event { 
    // Pass to top of chain 
    UIResponder *responder = self; 
    while (responder.nextResponder != nil){ 
     responder = responder.nextResponder; 
     if ([responder isKindOfClass:[UIViewController class]]) { 
      // Got ViewController 
      break; 
     } 
    } 
    [responder touchesBegan:touches withEvent:event]; 
} 
2

Để tham chiếu một bộ điều khiển xem, bạn cần phải sử dụng

[[self nextResponder] nextResponder] 

[self nextResponder] nghĩa xem một cái nhìn khiển của, và [[self nextResponder] nextResponder] nghĩa là điều khiển xem bản thân, bây giờ bạn có thể nhận được các sự kiện liên lạc

+0

Có thể hoạt động tốt trong iOS9 và 10 nhưng không hoạt động trong iOS11 . Bạn thực sự cần phải leo lên chuỗi trả lời cho đến khi bạn đạt đến viewController hoặc tableViewController mà bạn đang theo dõi. – ghr

1

Hôm nay tôi đã tìm thấy một phương pháp tốt hơn để khắc phục vấn đề này hoặc câu hỏi như thế này.

Trong bạn UITableViewCell, bạn có thể thêm một đại biểu lắng nghe sự kiện liên lạc, như thế này:

@protocol imageViewTouchDelegate 

-(void)selectedFacialView:(NSInteger)row item:(NSInteger)rowIndex; 

@end 

@property(nonatomic,assign)id<imageViewTouchDelegate>delegate; 

Sau đó, trong bạn UITableViewController: lon bạn thực hiện như thế này:

@interface pressionTable : UITableViewController<facialViewDelegate> 

và trong .m tệp bạn có thể triển khai giao diện đại biểu này, như:

-(void)selectedFacialView:(NSInteger)row item:(NSInteger)rowIndex{ 
//TO DO WHAT YOU WANT} 

LƯU Ý: khi bạn bắt đầu tế bào, bạn phải thiết lập các đại biểu, nếu không đại biểu là không hợp lệ, bạn có thể làm như

- (UITableViewCell *)tableView:(UITableView *)tableView 
    cellForRowAtIndexPath:(NSIndexPath *)indexPath { 

static NSString *CellIdentifier = @"Cell"; 

pressionCell *cell = (pressionCell *)[tableView dequeueReusableCellWithIdentifier:CellIdentifier]; 
if (cell == nil) { 
    cell = [[pressionCell alloc]initWithFrame:CGRectMake(0, 0, 240, 40)]; 
} 

cell.delegate = self; 

}

PS này: Tôi biết DOC này là cũ, nhưng tôi vẫn thêm phương pháp của tôi để sửa chữa câu hỏi như vậy khi mọi người gặp cùng một vấn đề, họ sẽ nhận được sự giúp đỡ từ câu trả lời của tôi.

2

Nếu bạn nhìn vào tài liệu của UIResponder mô tả nói rằng theo mặc định:

UIView thực hiện phương pháp này bằng cách trả lại đối tượng UIViewController quản lý nó (nếu nó có một) hoặc SuperView của nó (nếu nó doesn 't);

Nếu chế độ xem của bạn không trả về trình điều khiển chế độ xem thì phải quay lại trình giám sát của nó (như bạn đã tìm ra).

UIApplication thực sự có một phương pháp đó là nghĩa vụ để xử lý trường hợp này sử dụng một cách chính xác:

- (BOOL)sendAction:(SEL)action 
       to:(id)target 
       from:(id)sender 
      forEvent:(UIEvent *)event 

Vì bạn không có một tham chiếu đến các mục tiêu, bạn có thể làm việc theo cách của bạn lên chuỗi trả lời bằng cách thiết lập mục tiêu có giá trị là nil kể từ khi theo tài liệu:

Nếu mục tiêu là không, ứng dụng sẽ gửi thư tới người trả lời đầu tiên, từ khi nó tiến hành chuỗi trả lời cho đến khi nó được xử lý.

Bạn có thể đương nhiên được tiếp cận với các UIApplication với phương pháp lớp học [UIApplication sharedApplication]

Thông tin thêm ở đây: UIApplication documents

Đây là phụ, nhưng nếu bạn hoàn toàn cần truy cập vào bộ điều khiển nhằm làm điều gì đó một phức tạp hơn một chút, bạn có thể làm việc theo cách của bạn lên chuỗi trả lời theo cách thủ công cho đến khi bạn tới trình điều khiển xem bằng cách gọi phương thức nextResponder cho đến khi nó trả về một bộ điều khiển xem. Ví dụ:

UIResponder *responder = self; 
while ([responder isKindOfClass:[UIView class]]) 
    responder = [responder nextResponder]; 

sau đó bạn chỉ có thể cast nó như điều khiển xem của bạn và tiến hành làm bất cứ điều gì bạn muốn làm gì với nó:

UIViewController *parentVC = (UIViewController *)responder 
Các vấn đề liên quan