2012-02-28 31 views
14

Tôi có một NSObject là một singleton. Có vấn đề gì về việc có một đại biểu cho lớp singleton này không? Tôi lo lắng rằng nó sẽ thất bại cho một loại singleton.ủy quyền cho một đối tượng đơn lẻ

Đây là kịch bản của tôi. Tôi có một chức năng (bên trong lớp singleton này) mà thực hiện một yêu cầu async để rút ra một NSDictionary từ một API. Về cơ bản khi yêu cầu này được thực hiện, tôi muốn thông báo cho một lớp rằng yêu cầu đã hoàn thành.

+2

Tại sao đại biểu không thành công? Thay vào đó, bạn có thể cân nhắc sử dụng 'NSNotificationCenter' cho nhiều người nghe. –

+0

Tôi chỉ có một lớp mà tôi muốn thông báo, cập nhật ngữ cảnh câu hỏi ở trên – adit

Trả lời

30

Không, một đại biểu sẽ không thất bại, nhưng xem xét sử dụng NSNotificationCenter thay vì:

static NSString *const kMyClassNotificationName = @"myClassNotificationName"; 

// where you would call a delegate method (e.g. [self.delegate doSomething]) 
[[NSNotificationCenter defaultCenter] postNotificationName:kMyClassNotificationName object:self userInfo: /* dictionary containing variables to pass to the delegate */]; 

// where you would set up a delegate (e.g. [Singleton instance].delegate = self) 
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(doSomething) name:kMyClassNotificationName object:[Singleton instance]]; 
+3

+1 cho đề xuất 'NSNOtificationCenter' – HelmiB

+1

@adit Nếu bạn cần tăng tốc độ tra cứu người quan sát, bạn có thể sử dụng một trường hợp đặc biệt của' NSNotificationCenter' trong singleton của bạn. Trong trường hợp đó chỉ cần biến nó trở thành tài sản chỉ đọc của singleton của bạn để người quan sát có thể đăng ký trực tiếp với nó. – Costique

+3

Đây thực sự là hình thức xấu. Tại sao bất cứ ai cố ý khai thác mã như thế này? Xem câu trả lời của vikingosegundo cho 2 giải pháp tốt hơn với đại biểu hoặc chặn – PostCodeism

17

Bạn có cơ bản ba lựa chọn:

  • Sử dụng một đại biểu. Một singelton là một objetct, do đó, của couse nó có thể có một đại biểu. Nếu một số đối tượng muốn sử dụng nó và cần phải đặt mình là đại biểu, bạn có thể đặt lại chúng mỗi lần, nhưng điều đó có thể bị lông.

  • Sử dụng thông báo, như được minh họa bởi Richard J. Ross III, nhưng nghiêm túc: Có vẻ lạ với tôi, nếu bạn có một singleton, cần thông báo cho một đại biểu, nhưng bạn sẽ sử dụng công nghệ phát sóng .

  • sử dụng các khối hoàn thành, trong đó các đối tượng gọi qua một khối tới singleton, được thực thi, khi singleton hoàn thành một nhiệm vụ. Xem [NSURLConnection sendAsynchronousRequest:queue:completionHandler:] (ok, đây không phải là singleton, mà là một phương thức lớp. Nguyên tắc giống nhau), sử dụng một khối hoàn thành hoặc AFNetworking tuyệt vời, sử dụng khối thành công và lỗi.
    Từ đó là mã số ví dụ:

    [[AFGowallaAPIClient sharedClient] getPath:urlString 
               parameters:mutableParameters 
                success:^(__unused AFHTTPRequestOperation 
                  *operation, 
                  id JSON) 
        { 
         NSMutableArray *mutableRecords = [NSMutableArray array]; 
         for (NSDictionary *attributes in [JSON valueForKeyPath:@"spots"]) { 
          Spot *spot = [[[Spot alloc] initWithAttributes:attributes] autorelease]; 
          [mutableRecords addObject:spot]; 
         } 
    
         if (block) { 
          block([NSArray arrayWithArray:mutableRecords]); 
         } 
        } failure:^(__unused AFHTTPRequestOperation *operation, NSError *error) { 
         if (block) { 
          block([NSArray array]); 
         } 
    }]; 
    
+3

Kính gửi người đánh giá: Chỉnh sửa bài đăng để sửa lỗi chính tả là ok và được đánh giá cao. Nhưng thêm liên kết đến thư viện tôi thậm chí không biết là không. – vikingosegundo

6

Không có gì sai với việc có một đại biểu cho một singleton là, nhưng nó tạo ra rất nhiều trường hợp cạnh đó bạn cần phải xử lý. Chẳng hạn như:

  • Nếu đối tượng A gọi setDelegate :, ngay sau đó setDelegate gọi đối tượng B: sau đó đối tượng A sẽ không bao giờ nhận cuộc gọi đại biểu.

  • Bạn cần kiểm tra xem bạn có phải là người được ủy quyền trước khi hủy ủy quyền của singleton hay không. Thông thường, trong số dealloc, bạn gọi số singleton.delegate = nil;. Nếu một đối tượng khác xảy ra để trở thành đại biểu sau khi bạn đã làm, sau đó bạn chỉ gây ra khiến họ bất ngờ ngừng được đại biểu.

Các đơn vị có đại biểu không phải là mẫu được thiết lập tốt. Giải pháp của bạn sẽ thay đổi tùy thuộc vào mức độ sử dụng của bạn. Dưới đây là một số giải pháp (theo thứ tự đơn giản nhất -> mạnh mẽ nhất).

Giữ nó đơn giản

Thiết kế ứng dụng của bạn để không bao giờ có nhiều đối tượng là đại biểu của singleton cùng một lúc (điều này có thể là không thể).

NSNotification

Sử dụng NSNotificationCenter để báo hiệu sự kiện thay vì đoàn. Xem một số câu trả lời khác được đăng trong chủ đề này.

Nhiều đại biểu

Mở rộng singleton của bạn để hỗ trợ nhiều đại biểu. Thay setDelegate: với: addDelegate:removeDelegate:

@property (atomic) NSMutableArray *delegates; 

- (void)addDelegate:(NSObject * <YourProtocol>)foo { 
    [self.delegates addObject:foo]; 
} 
- (void)removeDelegate:(NSObject * <YourProtocol>)foo { 
    [self.delegates removeObject:foo]; 
} 
- (void)signalDelegateEvent { 
    [self.delegates enumerateObjectsUsingBlock:^(id<YourProtocol> obj, 
               NSUInteger idx, 
               BOOL *stop) { 
     // call delegate method `foo` on each delegate 
     if ([obj respondsToSelector:@selector(foo)]) { 
      [obj foo]; 
     } 
    }]; 
} 

Tôi đã sử dụng mô hình đa đại biểu thành công trong nhiều ứng dụng. Hãy cẩn thận để suy nghĩ về cách đa luồng hiệu ứng mọi thứ nếu bạn chọn cách tiếp cận này.

+0

Tôi không bao giờ nghĩ đến việc sử dụng một giải pháp đa đại biểu, cảm ơn cho ý tưởng. Tốt để có một biến thể của mô hình đại biểu trong tâm trí – Chris

+0

Làm thế nào về việc có một yêu cầu gọi lại để thông báo cho các đối tượng đại biểu mà họ sắp sửa được thay thế? – psobko

+1

Giải pháp này có thể sử dụng một NSSet thay vì NSArray để thu thập các đại biểu để đảm bảo không có gì nhận được nhiều thư. –

Các vấn đề liên quan