ฉันจะสร้างผู้รับมอบสิทธิ์ใน Objective-C ได้อย่างไร


738

ฉันรู้ว่าผู้ได้รับมอบหมายทำงานอย่างไรและฉันรู้ว่าฉันจะใช้มันอย่างไร

แต่ฉันจะสร้างพวกเขาได้อย่างไร


คำตอบ:


889

ผู้รับมอบอำนาจ -C เป็นวัตถุที่ได้รับมอบหมายให้delegateทรัพย์สินวัตถุอื่น ในการสร้างคลาสคุณกำหนดคลาสที่ใช้วิธีการมอบสิทธิ์ที่คุณสนใจและทำเครื่องหมายคลาสนั้นว่าเป็นการใช้โปรโตคอลตัวแทน

UIWebViewตัวอย่างเช่นสมมติว่าคุณมี หากคุณต้องการใช้webViewDidStartLoad:วิธีการของผู้รับมอบสิทธิ์คุณสามารถสร้างคลาสแบบนี้ได้:

@interface MyClass<UIWebViewDelegate>
// ...
@end

@implementation MyClass
- (void)webViewDidStartLoad:(UIWebView *)webView { 
    // ... 
}
@end

จากนั้นคุณสามารถสร้างอินสแตนซ์ของ MyClass และกำหนดเป็นผู้รับมอบสิทธิ์ของมุมมองเว็บ:

MyClass *instanceOfMyClass = [[MyClass alloc] init];
myWebView.delegate = instanceOfMyClass;

ทางUIWebViewด้านข้างอาจมีรหัสคล้ายกันนี้เพื่อดูว่าผู้ร่วมประชุมตอบกลับwebViewDidStartLoad:ข้อความโดยใช้respondsToSelector:และส่งตามความเหมาะสมหรือไม่

if([self.delegate respondsToSelector:@selector(webViewDidStartLoad:)]) {
    [self.delegate webViewDidStartLoad:self];
}

โดยทั่วไปแล้วคุณสมบัติผู้รับมอบสิทธิ์จะประกาศweak(ใน ARC) หรือassign(pre-ARC) เพื่อหลีกเลี่ยงการวนซ้ำเนื่องจากผู้รับมอบสิทธิ์ของวัตถุมักจะมีการอ้างอิงที่แข็งแกร่งกับวัตถุนั้น (ตัวอย่างเช่นตัวควบคุมมุมมองมักจะเป็นตัวแทนของมุมมองที่มีอยู่)

การมอบสิทธิ์ให้แก่ชั้นเรียนของคุณ

เพื่อกำหนดผู้ได้รับมอบหมายของคุณเองคุณจะต้องประกาศวิธีการของพวกเขาอยู่ที่ไหนสักแห่งตามที่กล่าวไว้ในแอปเปิ้ลเอกสารบนโปรโตคอล คุณมักจะประกาศโปรโตคอลอย่างเป็นทางการ การประกาศถอดความจาก UIWebView.h จะมีลักษณะเช่นนี้:

@protocol UIWebViewDelegate <NSObject>
@optional
- (void)webViewDidStartLoad:(UIWebView *)webView;
// ... other methods here
@end

นี่คล้ายกับอินเทอร์เฟซหรือคลาสพื้นฐานที่เป็นนามธรรมเนื่องจากมันสร้างชนิดพิเศษสำหรับผู้รับมอบสิทธิ์ของคุณUIWebViewDelegateในกรณีนี้ ผู้ดำเนินการตัวแทนจะต้องนำโปรโตคอลนี้ไปใช้:

@interface MyClass <UIWebViewDelegate>
// ...
@end

จากนั้นใช้วิธีการในโปรโตคอล สำหรับวิธีการที่ประกาศในโปรโตคอลเป็น@optional(เช่นวิธีการมอบสิทธิ์ส่วนใหญ่) คุณจะต้องตรวจสอบ-respondsToSelector:ก่อนเรียกวิธีการเฉพาะ

การตั้งชื่อ

โดยทั่วไปวิธีการมอบหมายจะตั้งชื่อโดยเริ่มต้นด้วยชื่อคลาสที่มอบหมายและนำวัตถุมอบหมายเป็นพารามิเตอร์แรก พวกเขายังมักจะใช้รูปแบบที่ควรหรือควรทำ ดังนั้นwebViewDidStartLoad:(พารามิเตอร์แรกคือมุมมองเว็บ) แทนที่จะเป็นloadStarted(ไม่มีพารามิเตอร์) ตัวอย่างเช่น

การเพิ่มประสิทธิภาพความเร็ว

แทนที่จะตรวจสอบว่าผู้รับมอบสิทธิ์ตอบสนองต่อตัวเลือกทุกครั้งที่เราต้องการส่งข้อความคุณสามารถแคชข้อมูลนั้นเมื่อตั้งค่าผู้ได้รับมอบหมาย วิธีหนึ่งที่สะอาดมากในการทำเช่นนี้คือการใช้บิตฟิลด์ดังนี้:

@protocol SomethingDelegate <NSObject>
@optional
- (void)something:(id)something didFinishLoadingItem:(id)item;
- (void)something:(id)something didFailWithError:(NSError *)error;
@end

@interface Something : NSObject
@property (nonatomic, weak) id <SomethingDelegate> delegate;
@end

@implementation Something {
  struct {
    unsigned int didFinishLoadingItem:1;
    unsigned int didFailWithError:1;
  } delegateRespondsTo;
}
@synthesize delegate;

- (void)setDelegate:(id <SomethingDelegate>)aDelegate {
  if (delegate != aDelegate) {
    delegate = aDelegate;

    delegateRespondsTo.didFinishLoadingItem = [delegate respondsToSelector:@selector(something:didFinishLoadingItem:)];
    delegateRespondsTo.didFailWithError = [delegate respondsToSelector:@selector(something:didFailWithError:)];
  }
}
@end

จากนั้นในร่างกายเราสามารถตรวจสอบว่าผู้ได้รับมอบหมายของเราจัดการข้อความโดยเข้าถึงdelegateRespondsTostruct ของเราแทนที่จะส่ง-respondsToSelector:ซ้ำแล้วซ้ำอีก

ผู้แทนอย่างไม่เป็นทางการ

ก่อนโปรโตคอลที่มีอยู่มันเป็นเรื่องธรรมดาที่จะใช้หมวดหมู่ในNSObjectการประกาศวิธีการที่เป็นตัวแทนสามารถใช้ ตัวอย่างเช่นCALayerยังคงทำสิ่งนี้:

@interface NSObject(CALayerDelegate)
- (void)displayLayer:(CALayer *)layer;
// ... other methods here
@end

นี้จะบอกคอมไพเลอร์ที่วัตถุใด ๆ displayLayer:ที่อาจใช้

จากนั้นคุณจะใช้-respondsToSelector:วิธีการเดียวกับที่อธิบายไว้ข้างต้นเพื่อเรียกวิธีนี้ ผู้รับมอบสิทธิ์ใช้วิธีนี้และกำหนดdelegateคุณสมบัติและนั่นคือ (ไม่มีการประกาศว่าคุณเป็นไปตามโปรโตคอล) วิธีนี้เป็นเรื่องปกติในห้องสมุดของ Apple แต่รหัสใหม่ควรใช้วิธีการโปรโตคอลที่ทันสมัยกว่าด้านบนเนื่องจากวิธีการนี้ทำให้เกิดมลพิษNSObject(ซึ่งทำให้การเติมข้อความอัตโนมัติมีประโยชน์น้อยกว่า) และทำให้ยากสำหรับคอมไพเลอร์ที่จะเตือนคุณเกี่ยวกับ


ฉันคิดว่าคุณต้องโยนunsigned intประเภทเพื่อBOOLเป็นค่าตอบแทนในการเป็นประเภทdelegate respondsToSelector BOOL
Roland

ตัวแทนสามารถใช้สำหรับ Polymorphism ได้ใน C ++ หรือไม่

@ ใช่แน่นอน โปรโตคอลโดยทั่วไปจะใช้สำหรับความหลากหลาย
Jesse Rusak

@JesseRusak ฉันคิดว่า "JSSomethingDelegate" ควรเป็น "SomethingDelegate" เพื่อความมั่นคง :)
Hans Knöchel

382

คำตอบที่ได้รับการอนุมัตินั้นดีมาก แต่ถ้าคุณกำลังมองหาคำตอบ 1 นาทีลองทำดังนี้:

ไฟล์ MyClass.h ควรมีลักษณะเช่นนี้ (เพิ่มบรรทัดผู้รับมอบสิทธิ์พร้อมความคิดเห็น!)

#import <BlaClass/BlaClass.h>

@class MyClass;             //define class, so protocol can see MyClass
@protocol MyClassDelegate <NSObject>   //define delegate protocol
    - (void) myClassDelegateMethod: (MyClass *) sender;  //define delegate method to be implemented within another class
@end //end protocol

@interface MyClass : NSObject {
}
@property (nonatomic, weak) id <MyClassDelegate> delegate; //define MyClassDelegate as delegate

@end

ไฟล์ MyClass.m ควรมีลักษณะเช่นนี้

#import "MyClass.h"
@implementation MyClass 
@synthesize delegate; //synthesise  MyClassDelegate delegate

- (void) myMethodToDoStuff {
    [self.delegate myClassDelegateMethod:self]; //this will call the method implemented in your other class    
}

@end

ในการใช้ผู้รับมอบสิทธิ์ของคุณในคลาสอื่น (UIViewController ชื่อ MyVC ในกรณีนี้) MyVC.h

#import "MyClass.h"
@interface MyVC:UIViewController <MyClassDelegate> { //make it a delegate for MyClassDelegate
}

MyVC.m:

myClass.delegate = self;          //set its delegate to self somewhere

ใช้วิธีการมอบหมาย

- (void) myClassDelegateMethod: (MyClass *) sender {
    NSLog(@"Delegates are great!");
}

4
เหมาะที่จะใช้คำตอบนี้เป็นข้อมูลอ้างอิงอย่างรวดเร็ว แต่ทำไมคุณสมบัติตัวแทนใน MyClass.h ของคุณถูกทำเครื่องหมายเป็น 'IBOutlet'
Arno van der Meer

4
@ArnovanderMeer ดีจับ! ฉันจำไม่ได้ว่าทำไม ฉันต้องการมันในโครงการของฉัน แต่ไม่ใช่ในตัวอย่างนี้ฉันลบมันออก ขอบคุณ
Tibidabo

ขอบคุณ ดีและทั่วถึงตามคำตอบที่ยอมรับได้ฉันเรียนรู้ได้ดีที่สุดจากโค้ดตัวอย่างขนาดกะทัดรัด มันดีที่มีสองคำตอบ
sudo

@Tibidabo ยอดเยี่ยมโดยสิ้นเชิง ฉันหวังว่าทุกคนจะสามารถอธิบายแนวคิดการเขียนโปรแกรมเช่นนี้ได้ ฉันเคยเห็นคำอธิบายหลายร้อยเรื่อง 'ผู้ได้รับมอบหมาย' มาหลายปีแล้วและไม่เคยเข้าใจทฤษฎีนี้มาก่อนเลย! ขอบคุณมาก ...
Charles Robertson

5
อยู่ที่ไหนmyClassinstantiated ภายใน MyVC.m?
Lane Rettig

18

เมื่อใช้วิธีโปรโตคอลอย่างเป็นทางการสำหรับการสร้างการสนับสนุนผู้แทนฉันพบว่าคุณสามารถตรวจสอบประเภทที่เหมาะสม (แม้ว่ารันไทม์ไม่ใช่เวลารวบรวม) โดยการเพิ่มสิ่งที่ชอบ:

if (![delegate conformsToProtocol:@protocol(MyDelegate)]) {
    [NSException raise:@"MyDelegate Exception"
                format:@"Parameter does not conform to MyDelegate protocol at line %d", (int)__LINE__];
}

ในรหัสผู้รับมอบสิทธิ์ accessor (setDelegate) ของคุณ สิ่งนี้จะช่วยลดข้อผิดพลาด


18

โปรด! ตรวจสอบด้านล่างนี้ทีละขั้นตอนการสอนเพื่อทำความเข้าใจว่าผู้ได้รับมอบหมายทำงานอย่างไรใน iOS

มอบหมายใน iOS

ฉันสร้าง ViewControllers สองรายการ (สำหรับการส่งข้อมูลจากที่หนึ่งไปยังอีก)

  1. FirstViewController ใช้ตัวแทน (ซึ่งให้ข้อมูล)
  2. SecondViewController ประกาศผู้รับมอบสิทธิ์ (ซึ่งจะรับข้อมูล)

17

บางทีนี่อาจเป็นไปตามแนวทางของสิ่งที่คุณขาดไป:

หากคุณมาจากมุมมอง C ++ ผู้ได้รับมอบหมายจะคุ้นเคยเล็กน้อย แต่โดยทั่วไปแล้วพวกเขาแค่ทำงาน

วิธีการทำงานคือคุณตั้งค่าวัตถุบางอย่างที่คุณเขียนเป็นผู้รับมอบสิทธิ์ไปยัง NSWindow แต่วัตถุของคุณมีการใช้งาน (วิธีการ) สำหรับวิธีการมอบหมายอย่างใดอย่างหนึ่งหรือไม่กี่วิธี มีบางสิ่งเกิดขึ้นและNSWindowต้องการเรียกวัตถุของคุณ - เพียงแค่ใช้respondsToSelectorวิธีการของ Objective-c เพื่อตรวจสอบว่าวัตถุของคุณต้องการวิธีการที่เรียกว่าหรือไม่แล้วเรียกมันว่า นี่คือวิธีการทำงานของวัตถุประสงค์ - วิธีการค้นหาตามความต้องการ

การทำสิ่งนี้กับวัตถุของคุณเองไม่มีอะไรพิเศษเกิดขึ้นคุณสามารถมีNSArrayวัตถุ 27 ชนิดวัตถุต่าง ๆ ทั้งหมดมีเพียง 18 ชิ้นเท่านั้นที่มีวิธี-(void)setToBue;ส่วนอีก 9 ไม่มี ดังนั้นเมื่อต้องการเรียกsetToBlueทั้งหมด 18 ที่จำเป็นต้องทำบางสิ่งเช่นนี้:

for (id anObject in myArray)
{
  if ([anObject respondsToSelector:@selector(@"setToBlue")])
     [anObject setToBlue]; 
}

สิ่งอื่น ๆ เกี่ยวกับผู้ได้รับมอบหมายคือพวกเขาจะไม่ถูกเก็บไว้ดังนั้นคุณต้องตั้งผู้รับมอบสิทธิ์nilในMyClass deallocวิธีการของคุณ


15

ตามแนวทางปฏิบัติที่ดีที่ Apple แนะนำให้ใช้สำหรับผู้รับมอบสิทธิ์ (ซึ่งเป็นโปรโตคอลตามข้อกำหนด) เพื่อให้สอดคล้องกับNSObjectโปรโตคอล

@protocol MyDelegate <NSObject>
    ...
@end

& เพื่อสร้างวิธีเลือกเพิ่มเติมภายในผู้รับมอบสิทธิ์ของคุณ (เช่นวิธีที่ไม่จำเป็นต้องนำมาใช้) คุณสามารถใช้@optionalคำอธิบายประกอบดังนี้:

@protocol MyDelegate <NSObject>
    ...
    ...
      // Declaration for Methods that 'must' be implemented'
    ...
    ...
    @optional
    ...
      // Declaration for Methods that 'need not necessarily' be implemented by the class conforming to your delegate
    ...
@end

ดังนั้นเมื่อใช้วิธีการที่คุณระบุว่าเป็นตัวเลือกคุณจำเป็นต้องตรวจสอบ (ในชั้นเรียนของคุณ) respondsToSelectorว่ามุมมอง (ที่สอดคล้องกับผู้รับมอบสิทธิ์ของคุณ) ได้ใช้วิธีการที่เป็นตัวเลือกของคุณจริงหรือไม่


11

ฉันคิดว่าคำตอบทั้งหมดนี้สมเหตุสมผลมากเมื่อคุณเข้าใจผู้ได้รับมอบหมาย โดยส่วนตัวฉันมาจากดินแดนแห่ง C / C ++ และก่อนหน้าภาษาขั้นตอนเช่น Fortran ฯลฯ ดังนั้นนี่คือ 2 นาทีของฉันในการหา analogues ที่คล้ายกันในกระบวนทัศน์ C ++

ถ้าฉันจะอธิบายผู้ได้รับมอบหมายให้โปรแกรมเมอร์ C ++ / Java ฉันจะบอกว่า

ผู้ได้รับมอบหมายคืออะไร? เหล่านี้เป็นตัวชี้คงที่ไปยังคลาสภายในคลาสอื่น เมื่อคุณกำหนดพอยน์เตอร์คุณสามารถเรียกใช้ฟังก์ชัน / เมธอดในคลาสนั้นได้ ดังนั้นฟังก์ชั่นบางอย่างของคลาสของคุณคือ "มอบหมาย" (ใน C ++ world - ตัวชี้ไปยังโดยตัวชี้วัตถุคลาส) ไปยังคลาสอื่น

โปรโตคอลคืออะไร โดยทั่วไปแล้วมันมีจุดประสงค์คล้ายกับไฟล์ส่วนหัวของคลาสที่คุณกำหนดให้เป็นคลาสตัวแทน โปรโตคอลเป็นวิธีที่ชัดเจนในการกำหนดว่าจะต้องใช้วิธีใดในคลาสที่ตัวชี้ถูกตั้งเป็นผู้รับมอบสิทธิ์ภายในคลาส

ฉันจะทำสิ่งที่คล้ายกันใน C ++ ได้อย่างไร หากคุณพยายามทำสิ่งนี้ใน C ++ คุณจะทำได้โดยการกำหนดพอยน์เตอร์ไปยังคลาส (วัตถุ) ในการกำหนดคลาสและจากนั้นเชื่อมโยงพวกเขาไปยังคลาสอื่น ๆ ที่จะให้ฟังก์ชันเพิ่มเติมในฐานะตัวแทนของคลาสพื้นฐาน แต่การเดินสายนี้จะต้องมีการจัดการภายในรหัสและจะเงอะงะและข้อผิดพลาดได้ง่าย วัตถุประสงค์ C เพิ่งสันนิษฐานว่าโปรแกรมเมอร์ไม่ดีที่สุดในการรักษา decipline นี้และให้ข้อ จำกัด ของคอมไพเลอร์เพื่อบังคับใช้การใช้งานที่สะอาด


สิ่งที่คุณกำลังพูดถึงคือความหมายในขณะที่ฉันกำลังพูดถึงสัญชาตญาณ สิ่งที่คุณกำลังพูดถึงคือฟังก์ชั่นเสมือนจริง - แต่การคุ้นเคยกับศัพท์ใหม่อาจเป็นเรื่องที่ท้าทาย คำตอบที่ให้บริการอาหาร Beginers ที่ต้องการที่จะคิดว่าขนานใน C ++ / ซี
DrBug

สิ่งที่คุณพูดไม่ชัดเจนสำหรับฉันจริงๆ ทำไมคุณไม่เขียนคำตอบใหม่และให้ดูว่ามีคนคิดว่ามีประโยชน์หรือไม่พวกเขาจะโหวตให้หรือไม่
DrBug

9

รุ่นที่รวดเร็ว

ผู้รับมอบสิทธิ์เป็นเพียงคลาสที่ใช้งานได้กับคลาสอื่น อ่านโค้ดต่อไปนี้เพื่อดูตัวอย่างสนามเด็กเล่นที่โง่เขลา (แต่หวังว่าจะรู้แจ้ง) ที่แสดงวิธีการทำสิ่งนี้ใน Swift

// A protocol is just a list of methods (and/or properties) that must
// be used by any class that adopts the protocol.
protocol OlderSiblingDelegate: class {
    // This protocol only defines one required method
    func getYourNiceOlderSiblingAGlassOfWater() -> String
}

class BossyBigBrother {

    // The delegate is the BossyBigBrother's slave. This position can 
    // be assigned later to whoever is available (and conforms to the 
    // protocol).
    weak var delegate: OlderSiblingDelegate?

    func tellSomebodyToGetMeSomeWater() -> String? {
        // The delegate is optional because there might not be anyone
        // nearby to boss around.
        return delegate?.getYourNiceOlderSiblingAGlassOfWater()
    }
}

// PoorLittleSister conforms to the OlderSiblingDelegate protocol
class PoorLittleSister: OlderSiblingDelegate {

    // This method is repquired by the protocol, but the protocol said
    // nothing about how it needs to be implemented.
    func getYourNiceOlderSiblingAGlassOfWater() -> String {
        return "Go get it yourself!"
    }

}

// initialize the classes
let bigBro = BossyBigBrother()
let lilSis = PoorLittleSister()

// Set the delegate 
// bigBro could boss around anyone who conforms to the 
// OlderSiblingDelegate protocol, but since lilSis is here, 
// she is the unlucky choice.
bigBro.delegate = lilSis

// Because the delegate is set, there is a class to do bigBro's work for him.
// bigBro tells lilSis to get him some water.
if let replyFromLilSis = bigBro.tellSomebodyToGetMeSomeWater() {
    print(replyFromLilSis) // "Go get it yourself!"
}

ในการปฏิบัติจริงผู้ได้รับมอบหมายมักจะใช้ในสถานการณ์ต่อไปนี้

  1. เมื่อชั้นเรียนต้องการสื่อสารข้อมูลบางอย่างไปยังชั้นเรียนอื่น
  2. เมื่อคลาสต้องการอนุญาตให้คลาสอื่นปรับแต่งได้

ชั้นเรียนไม่จำเป็นต้องรู้อะไรเกี่ยวกับกันและกันก่อนยกเว้นชั้นผู้รับมอบสิทธิ์จะสอดคล้องกับโปรโตคอลที่จำเป็น

ฉันขอแนะนำให้อ่านบทความสองบทความต่อไปนี้ พวกเขาช่วยให้ฉันเข้าใจผู้ได้รับมอบหมายให้ดียิ่งขึ้นกว่าเอกสารได้


8

ตกลงนี่ไม่ใช่คำตอบสำหรับคำถาม แต่ถ้าคุณกำลังมองหาวิธีสร้างตัวแทนของคุณเองบางทีสิ่งที่ง่ายกว่าอาจเป็นคำตอบที่ดีกว่าสำหรับคุณ

ฉันแทบไม่ได้ใช้ผู้รับมอบสิทธิ์เพราะไม่ค่อยต้องการ ฉันสามารถมีผู้รับมอบสิทธิ์เพียงคนเดียวสำหรับวัตถุผู้ได้รับมอบหมาย ดังนั้นหากคุณต้องการตัวแทนของคุณสำหรับการสื่อสารทางเดียว / การส่งผ่านข้อมูลมากกว่าที่คุณทำได้ดีกว่าด้วยการแจ้งเตือน

NSNotification สามารถส่งวัตถุไปยังผู้รับมากกว่าหนึ่งคนและใช้งานง่ายมาก มันได้ผลเช่นนี้:

ไฟล์ MyClass.m ควรมีลักษณะเช่นนี้

#import "MyClass.h"
@implementation MyClass 

- (void) myMethodToDoStuff {
//this will post a notification with myClassData (NSArray in this case)  in its userInfo dict and self as an object
[[NSNotificationCenter defaultCenter] postNotificationName:@"myClassUpdatedData"
                                                    object:self
                                                  userInfo:[NSDictionary dictionaryWithObject:selectedLocation[@"myClassData"] forKey:@"myClassData"]];
}
@end

วิธีใช้การแจ้งเตือนของคุณในคลาสอื่น: เพิ่มคลาสเป็นผู้สังเกตการณ์:

[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(otherClassUpdatedItsData:) name:@"myClassUpdatedData" object:nil];

ใช้เครื่องมือเลือก:

- (void) otherClassUpdatedItsData:(NSNotification *)note {
    NSLog(@"*** Other class updated its data ***");
    MyClass *otherClass = [note object];  //the object itself, you can call back any selector if you want
    NSArray *otherClassData = [note userInfo][@"myClassData"]; //get myClass data object and do whatever you want with it
}

อย่าลืมลบชั้นเรียนของคุณในฐานะผู้สังเกตการณ์ด้วย

- (void)dealloc
{
    [[NSNotificationCenter defaultCenter] removeObserver:self];
}

8

สมมติว่าคุณมีคลาสที่คุณพัฒนาขึ้นและต้องการประกาศคุณสมบัติของผู้รับมอบสิทธิ์เพื่อให้สามารถแจ้งให้ทราบเมื่อเกิดเหตุการณ์บางอย่าง:

@class myClass;

@protocol myClassDelegate <NSObject>

-(void)myClass:(MyClass*)myObject requiredEventHandlerWithParameter:(ParamType*)param;

@optional
-(void)myClass:(MyClass*)myObject optionalEventHandlerWithParameter:(ParamType*)param;

@end


@interface MyClass : NSObject

@property(nonatomic,weak)id< MyClassDelegate> delegate;

@end

ดังนั้นคุณจึงประกาศโปรโตคอลในMyClassไฟล์ส่วนหัว (หรือไฟล์ส่วนหัวที่แยกต่างหาก) และประกาศตัวจัดการเหตุการณ์ที่จำเป็น / ตัวเลือกที่ผู้รับมอบสิทธิ์ของคุณต้อง / ควรดำเนินการจากนั้นประกาศคุณสมบัติในMyClassประเภท ( id< MyClassDelegate>) ซึ่งหมายถึงคลาส c วัตถุประสงค์ใด ๆ โพรโทคอลMyClassDelegateคุณจะสังเกตเห็นว่าคุณสมบัติของผู้รับมอบสิทธิ์ถูกประกาศว่าอ่อนแอนี่เป็นสิ่งสำคัญมากในการป้องกันวงจรการเก็บรักษาMyClassอินสแตนซ์ดังนั้นหากคุณประกาศให้ผู้รับมอบสิทธิ์เป็นผู้รักษา ของพวกเขาจะถูกปล่อยออกมา)

คุณจะสังเกตเห็นได้ว่าวิธีการโปรโตคอลผ่านMyClassอินสแตนซ์ที่จะเป็นผู้รับมอบสิทธิ์เป็นพารามิเตอร์นี้เป็นวิธีที่ดีที่สุดในกรณีที่ต้องการตัวแทนไปเรียกวิธีการบางอย่างเกี่ยวกับMyClassอินสแตนซ์และยังช่วยให้เมื่อผู้ร่วมประชุมประกาศตัวเองเป็นMyClassDelegateหลายMyClassกรณีเช่นเมื่อคุณมีหลายUITableView'sอินสแตนซ์ในของคุณViewControllerและประกาศว่าตนเองเป็นUITableViewDelegateของพวกเขาทั้งหมด

และภายในของMyClassคุณคุณแจ้งผู้ได้รับมอบหมายด้วยเหตุการณ์ที่ประกาศดังต่อไปนี้:

if([_delegate respondsToSelector:@selector(myClass: requiredEventHandlerWithParameter:)])
{
     [_delegate myClass:self requiredEventHandlerWithParameter:(ParamType*)param];
}

คุณตรวจสอบก่อนว่าผู้รับมอบสิทธิ์ของคุณตอบสนองต่อวิธีการโพรโทคอลที่คุณกำลังจะโทรหาหรือไม่ในกรณีที่ผู้รับมอบสิทธิ์ไม่ได้ใช้งานและแอพจะหยุดทำงานแล้ว (แม้ว่าจำเป็นต้องใช้วิธีโพรโทคอล)


6

นี่คือวิธีการง่ายๆในการสร้างผู้รับมอบสิทธิ์

สร้างโปรโตคอลในไฟล์. h ตรวจสอบให้แน่ใจว่ามีการกำหนดไว้ก่อนหน้าโปรโตคอลที่ใช้ @class ตามด้วยชื่อของ UIViewController< As the protocol I am going to use is UIViewController class>.

ขั้นตอนที่ 1:สร้างโพรโทคอลคลาสใหม่ชื่อ "YourViewController" ซึ่งจะเป็นคลาสย่อยของคลาส UIViewController และกำหนดคลาสนี้ให้กับ ViewController ที่สอง

ขั้นตอนที่ 2:ไปที่ไฟล์ "YourViewController" และแก้ไขดังต่อไปนี้:

#import <UIKit/UIkit.h>
@class YourViewController;

@protocol YourViewController Delegate <NSObject>

 @optional
-(void)defineDelegateMethodName: (YourViewController *) controller;

@required
-(BOOL)delegateMethodReturningBool: (YourViewController *) controller;

  @end
  @interface YourViewController : UIViewController

  //Since the property for the protocol could be of any class, then it will be marked as a type of id.

  @property (nonatomic, weak) id< YourViewController Delegate> delegate;

@end

วิธีการที่กำหนดไว้ในลักษณะการทำงานของโปรโตคอลสามารถควบคุมได้ด้วย @optional และ @required เป็นส่วนหนึ่งของข้อกำหนดของโปรโตคอล

ขั้นตอนที่ 3: การนำผู้แทนไปปฏิบัติ

    #import "delegate.h"

   @interface YourDelegateUser ()
     <YourViewControllerDelegate>
   @end

   @implementation YourDelegateUser

   - (void) variousFoo {
      YourViewController *controller = [[YourViewController alloc] init];
      controller.delegate = self;
   }

   -(void)defineDelegateMethodName: (YourViewController *) controller {
      // handle the delegate being called here
   }

   -(BOOL)delegateMethodReturningBool: (YourViewController *) controller {
      // handle the delegate being called here
      return YES;
   }

   @end

// ทดสอบว่ามีการกำหนดวิธีการก่อนที่จะเรียกมันหรือไม่

 - (void) someMethodToCallDelegate {
     if ([[self delegate] respondsToSelector:@selector(defineDelegateMethodName:)]) {
           [self.delegate delegateMethodName:self]; 
     }
  }

5

ในการสร้างผู้รับมอบสิทธิ์ของคุณเองก่อนอื่นคุณต้องสร้างโปรโตคอลและประกาศวิธีการที่จำเป็นโดยไม่ต้องดำเนินการ จากนั้นใช้โปรโตคอลนี้ในคลาสส่วนหัวของคุณที่คุณต้องการใช้วิธีการมอบหมายหรือผู้รับมอบสิทธิ์

ต้องประกาศโปรโตคอลดังต่อไปนี้:

@protocol ServiceResponceDelegate <NSObject>

- (void) serviceDidFailWithRequestType:(NSString*)error;
- (void) serviceDidFinishedSucessfully:(NSString*)success;

@end

นี่คือคลาสบริการที่ควรทำภารกิจบางอย่าง มันแสดงวิธีการกำหนดผู้รับมอบสิทธิ์และวิธีการตั้งค่าผู้รับมอบสิทธิ์ ในชั้นเรียนการใช้งานหลังจากงานเสร็จสมบูรณ์ตัวแทนของวิธีการที่เรียกว่า

@interface ServiceClass : NSObject
{
id <ServiceResponceDelegate> _delegate;
}

- (void) setDelegate:(id)delegate;
- (void) someTask;

@end

@implementation ServiceClass

- (void) setDelegate:(id)delegate
{
_delegate = delegate;
}

- (void) someTask
{
/*

   perform task

*/
if (!success)
{
[_delegate serviceDidFailWithRequestType:@”task failed”];
}
else
{
[_delegate serviceDidFinishedSucessfully:@”task success”];
}
}
@end

นี่คือคลาสมุมมองหลักจากที่เรียกคลาสเซอร์วิสโดยการตั้งค่าผู้รับมอบสิทธิ์ให้กับตัวเอง และยังมีการใช้โปรโตคอลในคลาสส่วนหัว

@interface viewController: UIViewController <ServiceResponceDelegate>
{
ServiceClass* _service;
}

- (void) go;

@end

@implementation viewController

//
//some methods
//

- (void) go
{
_service = [[ServiceClass alloc] init];
[_service setDelegate:self];
[_service someTask];
}

เพียงเท่านี้และโดยการใช้วิธีผู้ร่วมประชุมในคลาสนี้การควบคุมจะกลับมาอีกครั้งเมื่องาน / งานเสร็จสิ้น


4

คำเตือน: นี้เป็นรุ่นของวิธีการสร้างSwiftdelegate

ดังนั้นผู้ได้รับมอบหมายคืออะไร? …ในการพัฒนาซอฟต์แวร์มีสถาปัตยกรรมโซลูชันที่ใช้ซ้ำได้ทั่วไปที่ช่วยในการแก้ปัญหาที่เกิดขึ้นโดยทั่วไปในบริบทที่กำหนด“ เทมเพลต” เหล่านี้ดังนั้นการพูดจึงเป็นที่รู้จักกันดีในฐานะรูปแบบการออกแบบ ผู้รับมอบสิทธิ์เป็นรูปแบบการออกแบบที่อนุญาตให้วัตถุหนึ่งส่งข้อความไปยังวัตถุอื่นเมื่อมีเหตุการณ์เฉพาะเกิดขึ้น ลองนึกภาพวัตถุ A เรียกวัตถุ B เพื่อดำเนินการ เมื่อการดำเนินการเสร็จสิ้นแล้ววัตถุ A ควรรู้ว่า B ดำเนินงานและดำเนินการที่จำเป็นแล้วสิ่งนี้สามารถทำได้ด้วยความช่วยเหลือของผู้ได้รับมอบหมาย!

สำหรับคำอธิบายที่ดีกว่าฉันจะแสดงวิธีสร้างตัวแทนที่กำหนดเองที่ส่งผ่านข้อมูลระหว่างคลาสด้วย Swift ในแอปพลิเคชันง่ายเริ่มต้นด้วยการดาวน์โหลดหรือโคลนโครงการเริ่มต้นและเรียกใช้!

คุณสามารถเห็นแอปที่มีสองชั้นและViewController A ViewController BB มีสองมุมมองว่าการแตะเปลี่ยนสีพื้นหลังของViewControllerไม่มีอะไรซับซ้อนเกินไปใช่มั้ย ทีนี้ลองคิดวิธีง่ายๆในการเปลี่ยนสีพื้นหลังของคลาส A เมื่อมุมมองของคลาส B ถูกแตะ

ปัญหาคือว่ามุมมองนี้เป็นส่วนหนึ่งของคลาส B และไม่มีความคิดเกี่ยวกับคลาส A ดังนั้นเราจำเป็นต้องหาวิธีในการสื่อสารระหว่างสองคลาสนี้และนั่นคือสิ่งที่คณะผู้แทนเปล่งประกาย ฉันแบ่งการใช้งานเป็น 6 ขั้นตอนเพื่อให้คุณสามารถใช้สิ่งนี้เป็นแผ่นสูตรโกงเมื่อคุณต้องการ

ขั้นตอนที่ 1: ค้นหาเครื่องหมาย pragma ขั้นตอนที่ 1 ในไฟล์ ClassBVC และเพิ่มสิ่งนี้

//MARK: step 1 Add Protocol here.
protocol ClassBVCDelegate: class {
func changeBackgroundColor(_ color: UIColor?)
}

ขั้นตอนแรกคือการสร้าง a protocolในกรณีนี้เราจะสร้างโปรโตคอลในคลาส B ภายในโปรโตคอลที่คุณสามารถสร้างฟังก์ชั่นได้มากเท่าที่คุณต้องการตามความต้องการของการใช้งานของคุณ ในกรณีนี้เรามีเพียงฟังก์ชั่นง่าย ๆ ที่ยอมรับทางเลือกUIColorเป็นอาร์กิวเมนต์ เป็นวิธีปฏิบัติที่ดีในการตั้งชื่อโปรโตคอลของคุณโดยเพิ่มคำdelegateที่ท้ายชื่อคลาสในกรณีนี้ClassBVCDelegateนี้

ขั้นตอนที่ 2: ค้นหาเครื่องหมาย pragma ขั้นตอนที่ 2 ClassVBCและเพิ่มสิ่งนี้

//MARK: step 2 Create a delegate property here.
weak var delegate: ClassBVCDelegate?

ที่นี่เราเพิ่งสร้างคุณสมบัติตัวแทนสำหรับชั้นเรียนคุณสมบัตินี้จะต้องนำมาใช้protocolประเภทและมันควรจะเป็นตัวเลือก นอกจากนี้คุณควรเพิ่มคำหลักที่อ่อนแอก่อนที่จะพร็อพเพอร์ตี้เพื่อหลีกเลี่ยงการเก็บรอบและการรั่วไหลของหน่วยความจำที่อาจเกิดขึ้นหากคุณไม่ทราบว่านั่นหมายความว่าไม่ต้องกังวลตอนนี้

ขั้นตอนที่ 3: ค้นหาเครื่องหมาย pragma ขั้นตอนที่ 3 ภายใน handleTap methodในClassBVCและเพิ่มสิ่งนี้

//MARK: step 3 Add the delegate method call here.
delegate?.changeBackgroundColor(tapGesture.view?.backgroundColor)

สิ่งหนึ่งที่คุณควรรู้เรียกใช้แอพและแตะที่มุมมองใด ๆ คุณจะไม่เห็นพฤติกรรมใหม่และถูกต้อง แต่สิ่งที่ฉันต้องการชี้ให้เห็นก็คือแอปนั้นจะไม่ทำงานล้มเหลวเมื่อผู้ร่วมประชุมเรียกและ มันเป็นเพราะเราสร้างมันขึ้นมาเพื่อเป็นค่าเผื่อเลือกและนั่นเป็นเหตุผลว่าทำไมมันจึงไม่ผิดพลาดแม้จะยังไม่มีตัวแทน ตอนนี้เราไปที่ClassAVCไฟล์และทำให้มันได้รับมอบหมาย

ขั้นตอนที่ 4: มองหาเครื่องหมาย pragma ขั้นตอนที่ 4 ภายในเมธอด handleTap ClassAVCและเพิ่มสิ่งนี้ถัดจากประเภทคลาสของคุณเช่นนี้

//MARK: step 4 conform the protocol here.
class ClassAVC: UIViewController, ClassBVCDelegate {
}

ขณะนี้ ClassAVC นำClassBVCDelegateโปรโตคอลมาใช้คุณจะเห็นว่าคอมไพเลอร์ของคุณกำลังให้ข้อผิดพลาดที่ระบุว่า“ ประเภท 'ClassAVC ไม่สอดคล้องกับโปรโตคอล' ClassBVCDelegate 'และนี่หมายความว่าคุณไม่ได้ใช้วิธีการของโปรโตคอลเท่านั้นลองจินตนาการว่า เมื่อคลาส A ใช้โพรโทคอลก็เหมือนกับการเซ็นสัญญากับคลาส B และสัญญานี้บอกว่า“ คลาสใดที่รับฉันต้องใช้ฟังก์ชั่นของฉัน!”

บันทึกย่อ: หากคุณมาจากObjective-Cพื้นหลังคุณอาจคิดว่าคุณสามารถปิดข้อผิดพลาดที่ทำให้วิธีการนี้เป็นตัวเลือก แต่สำหรับความประหลาดใจของฉันและอาจเป็นของคุณSwiftภาษาไม่สนับสนุนตัวเลือกprotocolsถ้าคุณต้องการที่จะทำมันคุณสามารถสร้าง ส่วนขยายสำหรับคุณprotocolหรือใช้คำหลัก @objc ในprotocolการนำไปใช้ของคุณ

โดยส่วนตัวถ้าฉันต้องสร้างโปรโตคอลด้วยวิธีการทางเลือกที่แตกต่างกันฉันต้องการที่จะแบ่งมันเป็นprotocolsวิธีที่ฉันจะทำตามแนวคิดของการให้ความรับผิดชอบหนึ่งเดียวกับวัตถุของฉัน แต่มันอาจแตกต่างกันไปขึ้นอยู่กับการใช้งานเฉพาะ

นี่เป็นบทความที่ดีเกี่ยวกับวิธีการที่เป็นทางเลือก

ขั้นตอนที่ 5: มองหาเครื่องหมาย pragma ขั้นตอนที่ 5 ภายในวิธีการเตรียมการแยกส่วนและเพิ่มสิ่งนี้

//MARK: step 5 create a reference of Class B and bind them through the `prepareforsegue` method.
if let nav = segue.destination as? UINavigationController, let classBVC = nav.topViewController as? ClassBVC {
classBVC.delegate = self
}

ที่นี่เราเพิ่งสร้างตัวอย่างของClassBVCและมอบหมายผู้แทนให้ตัวเอง แต่ตัวเองที่นี่คืออะไร? ดีตัวเองเป็นClassAVCที่ได้รับมอบหมาย!

ขั้นตอนที่ 6: สุดท้ายมองหา pragma ขั้นตอนที่ 6 ClassAVCและลองใช้ฟังก์ชั่นของprotocolเริ่มพิมพ์ func changeBackgroundColorแล้วคุณจะเห็นว่ามันกำลังเติมให้คุณโดยอัตโนมัติ คุณสามารถเพิ่มการใช้งานใด ๆ ที่อยู่ภายในตัวอย่างนี้เราจะเปลี่ยนสีพื้นหลังเพิ่มสิ่งนี้

//MARK: step 6 finally use the method of the contract
func changeBackgroundColor(_ color: UIColor?) {
view.backgroundColor = color
}

ตอนนี้รันแอพ!

Delegatesมีอยู่ทุกหนทุกแห่งและคุณอาจใช้มันโดยไม่แจ้งให้ทราบล่วงหน้าหากคุณสร้างสิ่งtableviewก่อนหน้านี้คุณใช้การมอบหมายUIKITงานที่มีอยู่รอบตัวพวกเขาและอื่น ๆ อีกมากมายframeworksพวกเขาแก้ปัญหาหลักเหล่านี้ได้

  • หลีกเลี่ยงการมีเพศสัมพันธ์อย่างแน่นหนาของวัตถุ
  • ปรับเปลี่ยนลักษณะการทำงานและลักษณะที่ปรากฏโดยไม่จำเป็นต้องใช้วัตถุคลาสย่อย
  • อนุญาตให้จัดการกับวัตถุใด ๆ โดยพลการ

ขอแสดงความยินดีคุณเพิ่งใช้ผู้รับมอบสิทธิ์ที่กำหนดเองฉันรู้ว่าคุณอาจกำลังคิดว่าจะเกิดปัญหามากขึ้นสำหรับเรื่องนี้? การมอบหมายเป็นรูปแบบการออกแบบที่สำคัญมากที่จะเข้าใจหากคุณต้องการเป็นiOSนักพัฒนาและจำไว้เสมอว่าพวกเขามีความสัมพันธ์แบบหนึ่งต่อหนึ่งระหว่างวัตถุ

คุณสามารถดูบทช่วยสอนดั้งเดิมได้ที่นี่


4

คำตอบคือคำตอบจริง แต่ฉันอยากจะให้ "สูตรชีท" แก่คุณในการสร้างผู้แทน:

DELEGATE SCRIPT

CLASS A - Where delegate is calling function

@protocol <#Protocol Name#> <NSObject>

-(void)delegateMethod;

@end

@interface <#Some ViewController#> : <#UIViewController#> 

@property (nonatomic, assign) id <<#Protocol Name#>> delegate;

@end


@implementation <#Some ViewController#> 

-(void)someMethod {
    [self.delegate methodName];
}

@end




CLASS B - Where delegate is called 

@interface <#Other ViewController#> (<#Delegate Name#>) {}
@end

@implementation <#Other ViewController#> 

-(void)otherMethod {
    CLASSA *classA = [[CLASSA alloc] init];

    [classA setDelegate:self];
}

-delegateMethod() {

}

@end

2

ViewController.h

@protocol NameDelegate <NSObject>

-(void)delegateMEthod: (ArgType) arg;

@end

@property id <NameDelegate> delegate;

ViewController.m

[self.delegate delegateMEthod: argument];

MainViewController.m

ViewController viewController = [ViewController new];
viewController.delegate = self;

วิธี:

-(void)delegateMEthod: (ArgType) arg{
}

2

ในมุมมองของฉันสร้างคลาสที่แยกต่างหากสำหรับวิธีการมอบหมายและคุณสามารถใช้ที่คุณต้องการ

ใน Custom DropDownClass.h ของฉัน

typedef enum
{
 DDSTATE,
 DDCITY
}DropDownType;

@protocol DropDownListDelegate <NSObject>
@required
- (void)dropDownDidSelectItemWithString:(NSString*)itemString     DropDownType:(DropDownType)dropDownType;
@end
@interface DropDownViewController : UIViewController
{
 BOOL isFiltered;
}
@property (nonatomic, assign) DropDownType dropDownType;
@property (weak) id <DropDownListDelegate> delegate;
@property (strong, nonatomic) NSMutableArray *array1DropDown;
@property (strong, nonatomic) NSMutableArray *array2DropDown;

หลังจากนั้นไฟล์ in.m จะสร้างอาร์เรย์พร้อมวัตถุ

 - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath{
CGFloat rowHeight = 44.0f;
return rowHeight;
}

-(NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
return isFiltered?[self.array1DropDown count]:[self.array2DropDown count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *simpleTableIdentifier = @"TableCell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:simpleTableIdentifier];
if (cell == nil) {
    cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:simpleTableIdentifier];
}

if (self.delegate) {
    if (self.dropDownType == DDCITY) {
        cell.textLabel.text = [self.array1DropDown objectAtIndex:indexPath.row];
    }
    else if (self.dropDownType == DDSTATE) {
        cell.textLabel.text = [self.array2DropDown objectAtIndex:indexPath.row];
    }
}
return cell;
}

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
 [self dismissViewControllerAnimated:YES completion:^{
    if(self.delegate){
        if(self.dropDownType == DDCITY){
            [self.delegate dropDownDidSelectItemWithString:[self.array1DropDown objectAtIndex:indexPath.row] DropDownType:self.dropDownType];
        }
        else if (self.dropDownType == DDSTATE) {
            [self.delegate dropDownDidSelectItemWithString:[self.array2DropDown objectAtIndex:indexPath.row] DropDownType:self.dropDownType];
        }
    }
}];
}

ที่นี่ทั้งหมดถูกตั้งค่าสำหรับคลาสผู้แทนกำหนดเองหลังจากนั้นคุณสามารถใช้วิธีการมอบหมายนี้ที่คุณต้องการตัวอย่างเช่น ...

ในการนำเข้า viewcontroller อื่นของฉันหลังจากนั้น

สร้างการดำเนินการสำหรับการเรียกวิธีมอบสิทธิ์แบบนี้

- (IBAction)dropDownBtn1Action:(id)sender {
DropDownViewController *vehicleModelDropView = [[DropDownViewController alloc]init];
vehicleModelDropView.dropDownType = DDCITY;
vehicleModelDropView.delegate = self;
[self presentViewController:vehicleModelDropView animated:YES completion:nil];
}

หลังจากวิธีการมอบหมายการโทรแบบนี้

- (void)dropDownDidSelectItemWithString:(NSString *)itemString DropDownType:(DropDownType)dropDownType {
switch (dropDownType) {
    case DDCITY:{
        if(itemString.length > 0){
            //Here i am printing the selected row
            [self.dropDownBtn1 setTitle:itemString forState:UIControlStateNormal];
        }
    }
        break;
    case DDSTATE: {
        //Here i am printing the selected row
        [self.dropDownBtn2 setTitle:itemString forState:UIControlStateNormal];
    }

    default:
        break;
}
}

0

มอบหมาย: - สร้าง

@protocol addToCartDelegate <NSObject>

-(void)addToCartAction:(ItemsModel *)itemsModel isAdded:(BOOL)added;

@end

ส่งและโปรดมอบหมายผู้แทนเพื่อดูว่าคุณกำลังส่งข้อมูล

[self.delegate addToCartAction:itemsModel isAdded:YES];

0
//1.
//Custom delegate 
@protocol TB_RemovedUserCellTag <NSObject>

-(void)didRemoveCellWithTag:(NSInteger)tag;

@end

//2.
//Create a weak reference in a class where you declared the delegate
@property(weak,nonatomic)id <TB_RemovedUserCellTag> removedCellTagDelegate;

//3. 
// use it in the class
  [self.removedCellTagDelegate didRemoveCellWithTag:self.tag];

//4. import the header file in the class where you want to conform to the protocol
@interface MyClassUsesDelegate ()<TB_RemovedUserCellTag>

@end

// 5 ใช้วิธีการในคลาส. m - (void) didRemoveCellWithTag: แท็ก (NSInteger) {NSLog @ ("แท็ก% d", แท็ก);

}


0

เริ่มจากตัวอย่างถ้าเราซื้อผลิตภัณฑ์ทางออนไลน์มันต้องผ่านกระบวนการเช่นการจัดส่ง / จัดการโดยทีมที่แตกต่างกันดังนั้นถ้าการจัดส่งเสร็จสมบูรณ์ทีมจัดส่งควรแจ้งทีมการจัดส่ง & ควรเป็นการสื่อสารแบบหนึ่งต่อหนึ่ง จะเป็นค่าใช้จ่ายสำหรับคนอื่น / ผู้ขายอาจต้องการส่งผ่านข้อมูลนี้ไปยังผู้ที่ต้องการเท่านั้น

ดังนั้นหากเราคิดว่าในแง่ของแอพของเราเหตุการณ์อาจเป็นการสั่งซื้อออนไลน์ & ทีมที่แตกต่างกันอาจเป็นหลายมุมมอง

นี่คือรหัสพิจารณา ShippingView เป็นทีมขนส่งและ DeliveryView เป็นทีมจัดส่ง:

//Declare the protocol with functions having info which needs to be communicated
protocol ShippingDelegate : class {
    func productShipped(productID : String)
}
//shippingView which shows shipping status of products
class ShippingView : UIView
{

    weak var delegate:ShippingDelegate?
    var productID : String

    @IBAction func checkShippingStatus(sender: UIButton)
    {
        // if product is shipped
        delegate?.productShipped(productID: productID)
    }
}
//Delivery view which shows delivery status & tracking info
class DeliveryView: UIView,ShippingDelegate
{
    func productShipped(productID : String)
    {
        // update status on view & perform delivery
    }
}

//Main page on app which has both views & shows updated info on product whole status
class ProductViewController : UIViewController
{
    var shippingView : ShippingView
    var deliveryView : DeliveryView

    override func viewDidLoad() {
        super.viewDidLoad()
        // as we want to update shipping info on delivery view, so assign delegate to delivery object
        // whenever shipping status gets updated it will call productShipped method in DeliveryView & update UI.
        shippingView.delegate = deliveryView
        //
    }
}
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.