Tôi đang cố gắng gọi một phương thức trong bộ điều khiển xem gốc từ bộ điều khiển xem con như vậy khi tôi thay đổi tùy chọn, chúng sẽ tự động cập nhật chế độ xem gốc, lần lượt cập nhật một số bộ điều khiển chế độ xem khác. Đối với phần thứ hai tôi đã sử dụng thông báo, nhưng lần đầu tiên tôi đang cố gắng sử dụng một đại biểu bởi vì nó (vì vậy tôi đã được dẫn đến tin) là một thực hành lập trình tốt. Tôi gặp sự cố khi làm cho nó hoạt động và biết rằng tôi có thể thiết lập một thông báo khác dễ dàng để thực hiện công việc. Tôi có nên tiếp tục cố gắng triển khai đại biểu hoặc chỉ sử dụng thông báo không?Đại biểu Vs. Thông báo trong iPhoneOS
Trả lời
Ủy quyền là một thực hành lập trình tốt cho nhiều trường hợp nhưng điều đó không có nghĩa là bạn phải sử dụng nó nếu bạn không cảm thấy thoải mái với nó. Cả ủy nhiệm và thông báo đều giúp tách các bộ điều khiển xem với nhau, đó là một điều tốt. Thông báo có thể dễ dàng hơn để mã hóa và cung cấp lợi thế là nhiều đối tượng có thể quan sát một thông báo. Với các đại biểu, một điều như vậy không thể được thực hiện mà không sửa đổi đối tượng ủy nhiệm (và không bình thường).
Một số ưu điểm của ủy thác:
- Mối liên hệ giữa ủy thác đối tượng và đại biểu được thực hiện rõ ràng hơn, đặc biệt là nếu thực hiện các đại biểu là bắt buộc.
- Nếu nhiều hơn một loại thông điệp phải được chuyển từ người được ủy quyền sang đại biểu, ủy quyền có thể làm cho điều này rõ ràng hơn bằng cách chỉ định một phương thức đại biểu cho mỗi tin nhắn.
Đối với thông báo, bạn có thể sử dụng nhiều tên thông báo nhưng tất cả các thông báo kết thúc bằng cùng một phương pháp ở bên cạnh người quan sát (có thể yêu cầu một câu lệnh chuyển đổi khó chịu).
Chỉ bạn mới có thể quyết định mẫu nào phù hợp hơn với mình. Trong mọi trường hợp, bạn nên xem xét không có bộ điều khiển xem của bạn gửi thông báo hoặc tin nhắn đại biểu.Trong nhiều trường hợp, bộ điều khiển chế độ xem nên thay đổi mô hình và sau đó mô hình sẽ thông báo cho các quan sát viên hoặc đại diện của nó rằng nó đã bị thay đổi.
Thực hiện một mô hình đại biểu rất đơn giản:
Trong ChildViewController.h của bạn, kê khai các giao thức đại biểu rằng các đại biểu phải thực hiện sau:
@protocol ChildViewControllerDelegate <NSObject> @optional - (void)viewControllerDidChange:(ChildViewController *)controller; @end
Ở phía trên cùng của tập tin, tạo biến mẫu để giữ con trỏ tới người được ủy quyền trong ChildViewController của bạn:
@protocol ChildViewControllerDelegate; @interface ChildViewController : UIViewController { id <ChildViewControllerDelegate> delegate; ... } @property (assign) id <ChildViewControllerDelegate> delegate; ... @end
Trong RootViewController.h, làm cho lớp học của bạn phù hợp với các giao thức đại biểu:
@interface RootViewController : UIViewController <ChildViewControllerDelegate> { ...
Trong việc thực hiện RootViewController, thực hiện các phương pháp đại biểu. Ngoài ra, khi bạn tạo cá thể ChildViewController, bạn phải gán ủy nhiệm.
@implement RootViewController ... // in some method: ChildViewController *controller = [[ChildViewController alloc] initWithNibName:... controller.delegate = self; ... - (void)viewControllerDidChange:(ChildViewController *)controller { NSLog(@"Delegate method was called."); } ...
Trong việc thực hiện ChildViewController, gọi phương thức đại biểu tại thời điểm thích hợp:
@implementation ChildViewController ... // in some method: if ([self.delegate respondsToSelector:@selector(viewControllerDidChange:)]) { [self.delegate viewControllerDidChange:self]; } ...
Vậy là xong. (Lưu ý: Tôi đã viết điều này từ bộ nhớ để có thể có một số lỗi chính tả/lỗi trong đó.)
Các đại biểu khó sử dụng nhưng tôi nghĩ đó là phương pháp hay nhất và như Apple, họ chỉ hoạt động.
Tôi luôn sử dụng tuyên bố giao thức chính thức. Đó là một chút hợp lý hơn trong tâm trí của tôi, và nó rất rõ ràng trong mã. Tôi khuyên bạn nên sử dụng UIView để thay đổi tùy chọn của bạn thay vì bộ điều khiển. Tôi luôn sử dụng một bộ điều khiển chính và có rất nhiều UIViews được phân lớp mà một bộ điều khiển có thể điều khiển. (Tuy nhiên, bạn có thể sửa đổi các mã sau đây cho một bộ điều khiển, nếu bạn thực sự cần một bộ điều khiển thay vì một cái nhìn bình thường.) Trong tập tin tiêu đề của cái nhìn con, làm cho nó trông như thế này:
// ChildView.h
#import <UIKit/UIKit.h>
@protocol ChildViewDelegate; // tells the compiler that there will be a protocol definition later
@interface ChildViewController : UIView {
id <ChildViewDelegate> delegate;
// more stuff
}
// properties and class/instance methods
@end
@protocol ChildViewDelegate // this is the formal definition
- (void)childView:(ChildView *)c willDismissWithButtonIndex:(NSInteger)i; // change the part after (ChildView *)c to reflect the chosen options
@end
Phương thức giữa @protocol
và số @end
thứ hai có thể được gọi ở đâu đó trong quá trình triển khai ChildView và sau đó trình điều khiển chế độ xem gốc của bạn có thể là đại biểu nhận 'thông báo'.
Các tập tin .m nên như thế này:
// ChildView.m
#import "ChildView.h"
@implementation ChildView
- (id)initWithDelegate:(id<ChildViewDelegate>)del { // make this whatever you want
if (self = [super initWithFrame:CGRect(0, 0, 50, 50)]) { // if frame is a parameter for the init method, you can make that here, your choice
delegate = del; // this defines what class listens to the 'notification'
}
return self;
}
// other methods
// example: a method that will remove the subview
- (void)dismiss {
// tell the delegate (listener) that you're about to dismiss this view
[delegate childView:self willDismissWithButtonIndex:3];
[self removeFromSuperView];
}
@end
Sau đó, tập tin .h quan điểm điều khiển của gốc sẽ bao gồm các mã sau:
// RootViewController.h
#import "ChildView.h"
@interface RootViewController : UIViewController <ChildViewDelegate> {
// stuff
}
// stuff
@end
Và các tập tin thực thi sẽ thực hiện phương pháp này được xác định trong giao thức trong ChildView.h, vì nó sẽ chạy khi ChildView gọi nó chạy. Trong phương thức đó, hãy đặt những thứ xảy ra khi bạn nhận được thông báo.
Sự hiểu biết của tôi là nhiều lớp con của UIViewController sẽ là cách tiếp cận tốt hơn và phân lớp UIView nên được giới hạn khi một khung nhìn tùy chỉnh (ghi đè 'drawRect:') là cần thiết. – gerry3
Thông thường, nếu bạn cần cập nhật giao diện người dùng dựa trên thay đổi dữ liệu trong mô hình, bạn sẽ có bộ điều khiển chế độ xem quan sát dữ liệu mô hình có liên quan và cập nhật lượt xem của chúng khi được thông báo về các thay đổi.
tôi thấy đoàn như một chút trịnh trọng hơn và giống như sự phân biệt rằng Peter Hosey chia sẻ thời gian gần đây:
Sự khác biệt là phái đoàn là cho to-one (và hai chiều) truyền thông, trong khi thông báo là dành cho đối với nhiều người, một chiều, giao tiếp .
Ngoài ra, tôi đã thấy rằng (hoàn toàn) cập nhật chế độ xem trong viewWillAppear:
hoạt động tốt (nhưng đây không phải là giải pháp tốt nhất mà hiệu suất là mối quan tâm).
Trong trường hợp này, bạn không cần sử dụng ủy quyền hoặc thông báo vì bạn không thực sự cần liên lạc trực tiếp giữa các chế độ xem của mình. Như gerry3 đã nói, bạn cần thay đổi chính mô hình dữ liệu và sau đó cho phép tất cả các chế độ xem khác phản hồi thay đổi đó.
Mô hình dữ liệu của bạn phải là đối tượng độc lập mà tất cả các trình điều khiển chế độ xem của bạn có quyền truy cập. (Cách lười biếng là để đậu nó như là một thuộc tính của đại biểu ứng dụng.) Khi người dùng thực hiện thay đổi trong Chế độ xem A, trình điều khiển của Chế độ xem A ghi thay đổi đó vào mô hình dữ liệu. Sau đó, bất cứ khi nào Views B đến Z mở ra, bộ điều khiển của họ đọc mô hình dữ liệu và cấu hình các khung nhìn một cách thích hợp. Bằng cách này, không phải là quan điểm, cũng không phải bộ điều khiển của họ cần phải được nhận thức của nhau và tất cả các thay đổi xảy ra trong một đối tượng trung tâm để họ có thể dễ dàng theo dõi.
Thông báo là một cách hay để tránh chi phí nhiều lần liên tục bỏ phiếu vì chúng chỉ thay đổi khi cần ... –
Có, nhưng trong trường hợp này, bộ điều khiển chế độ xem nên đọc mô hình dữ liệu khi hiển thị chế độ xem. Vì chỉ có một bộ điều khiển được kích hoạt tại bất kỳ thời điểm nào, nên không có lý do gì cho bộ điều khiển thăm dò mô hình dữ liệu. Bây giờ là mô hình dữ liệu được trong thông lượng liên tục từ nói một đầu vào url, sau đó họ sẽ nhưng đó là hiếm khi trường hợp. – TechZen
Thực sự cần thiết cho bộ điều khiển chế độ xem gốc của bạn để biết về các thay đổi hay chỉ là các bản xem trước?
Nếu bộ điều khiển gốc không cần phải biết, việc cài đặt gửi thông báo mà các chế độ xem khác đang tìm kiếm có vẻ như là một câu trả lời tốt hơn cho tôi, vì nó đơn giản hóa mã. Không cần phải giới thiệu phức tạp hơn bạn phải làm.
Tôi muốn nói thêm:
đối tượng nhận thông báo có thể phản ứng chỉ sau khi sự kiện đã xảy ra . Đây là sự khác biệt đáng kể trong số từ ủy quyền. Các đại biểu được cung cấp cơ hội từ chối hoặc sửa đổi hoạt động được đề xuất bởi đối tượng ủy quyền. Quan sát đối tượng, mặt khác, không thể ảnh hưởng trực tiếp đến hoạt động sắp xảy ra.
Thông báo có thể làm cho hành vi thời gian chạy của chương trình của bạn phức tạp hơn một cách đáng kể. Hãy nghĩ về nó như một goto với nhiều điểm đến. Thứ tự của những điểm đến này không được xác định. Nếu bạn từng gặp sự cố, có rất ít thông tin theo dõi ngăn xếp.
Có những trường hợp khi sử dụng thông báo - một trường hợp điển hình là truyền đạt thay đổi mô hình hoặc thay đổi trạng thái toàn cầu sang chế độ xem của bạn. Ví dụ, mạng bị ngắt, ứng dụng sẽ từ chức, v.v.
Thật đáng giá để tìm hiểu mẫu đại biểu trong iOS. Các đại biểu cung cấp cho bạn các dấu vết ngăn xếp hoàn chỉnh khi bạn gỡ lỗi. Chúng dẫn đến hành vi thời gian chạy đơn giản hơn đáng kể trong khi vẫn đạt được mục tiêu tách các đối tượng của bạn.
Câu trả lời hay, sắp sửa viết về tôi, nhưng bạn thực sự tốt. –
Cảm ơn Oscar. –
Tuyệt vời, Điều đó đã làm các trick. Khi tôi mới bắt đầu với hệ điều hành iPhone, tôi đã đi đến một trong những cuộc hội thảo của các nhà phát triển mà Apple đã có và hầu hết không may đã đi qua đầu tôi vào thời điểm đó. Có một sơ đồ cụ thể mà họ đã trình bày về điều này và bây giờ tôi đã hiểu được nó. Cảm ơn rất nhiều. –