Saya tahu cara kerja delegasi, dan saya tahu bagaimana saya bisa menggunakannya.
Tapi bagaimana cara membuatnya?
Saya tahu cara kerja delegasi, dan saya tahu bagaimana saya bisa menggunakannya.
Tapi bagaimana cara membuatnya?
Jawaban:
Delegasi Objective-C adalah objek yang telah ditugaskan ke delegate
properti objek lain. Untuk membuatnya, Anda mendefinisikan kelas yang mengimplementasikan metode delegasi yang Anda minati, dan menandai kelas itu sebagai mengimplementasikan protokol delegasi.
Misalnya, anggap Anda memiliki UIWebView
. Jika Anda ingin menerapkan webViewDidStartLoad:
metode pendelegasiannya , Anda dapat membuat kelas seperti ini:
@interface MyClass<UIWebViewDelegate>
// ...
@end
@implementation MyClass
- (void)webViewDidStartLoad:(UIWebView *)webView {
// ...
}
@end
Kemudian Anda bisa membuat instance dari MyClass dan menetapkannya sebagai delegasi tampilan web:
MyClass *instanceOfMyClass = [[MyClass alloc] init];
myWebView.delegate = instanceOfMyClass;
Di UIWebView
samping itu, mungkin memiliki kode yang mirip dengan ini untuk melihat apakah delegasi menanggapi webViewDidStartLoad:
pesan menggunakan respondsToSelector:
dan mengirimkannya jika perlu.
if([self.delegate respondsToSelector:@selector(webViewDidStartLoad:)]) {
[self.delegate webViewDidStartLoad:self];
}
Properti delegate itu sendiri biasanya dinyatakan weak
(dalam ARC) atau assign
(pra-ARC) untuk menghindari loop mempertahankan, karena delegasi suatu objek sering memegang referensi yang kuat untuk objek itu. (Misalnya, pengontrol tampilan seringkali merupakan delegasi dari tampilan yang dikandungnya.)
Untuk menentukan delegasi Anda sendiri, Anda harus mendeklarasikan metode mereka di suatu tempat, seperti yang dibahas dalam Apple Documents tentang protokol . Anda biasanya mendeklarasikan protokol formal. Deklarasi, diparafrasekan dari UIWebView.h, akan terlihat seperti ini:
@protocol UIWebViewDelegate <NSObject>
@optional
- (void)webViewDidStartLoad:(UIWebView *)webView;
// ... other methods here
@end
Ini analog dengan antarmuka atau kelas dasar abstrak, karena ini membuat jenis khusus untuk delegasi Anda, UIWebViewDelegate
dalam hal ini. Delegasi pelaksana harus mengadopsi protokol ini:
@interface MyClass <UIWebViewDelegate>
// ...
@end
Dan kemudian mengimplementasikan metode dalam protokol. Untuk metode yang dinyatakan dalam protokol sebagai @optional
(seperti kebanyakan metode delegasi), Anda perlu memeriksa -respondsToSelector:
sebelum memanggil metode tertentu di dalamnya.
Metode delegasi biasanya dinamai dimulai dengan nama kelas pendelegasian, dan mengambil objek pendelegasian sebagai parameter pertama. Mereka juga sering menggunakan kemauan, harus-, atau melakukan. Jadi, webViewDidStartLoad:
(parameter pertama adalah tampilan web) daripada loadStarted
(tanpa parameter) misalnya.
Alih-alih memeriksa apakah seorang delegasi merespons pemilih setiap kali kami ingin mengirimkannya, Anda dapat menyimpan informasi tersebut ketika delegasi ditetapkan. Salah satu cara yang sangat bersih untuk melakukan ini adalah dengan menggunakan bitfield, sebagai berikut:
@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
Kemudian, di dalam tubuh, kita dapat memeriksa bahwa delegasi kita menangani pesan dengan mengakses delegateRespondsTo
struct kita , daripada dengan mengirim -respondsToSelector:
berulang-ulang.
Sebelum protokol ada, itu adalah umum untuk menggunakan kategori pada NSObject
untuk menyatakan metode delegasi bisa melaksanakan. Misalnya, CALayer
masih melakukan ini:
@interface NSObject(CALayerDelegate)
- (void)displayLayer:(CALayer *)layer;
// ... other methods here
@end
Ini memberitahu kompiler bahwa objek apa pun mungkin menerapkan displayLayer:
.
Anda kemudian akan menggunakan -respondsToSelector:
pendekatan yang sama seperti yang dijelaskan di atas untuk memanggil metode ini. Delegasi mengimplementasikan metode ini dan menetapkan delegate
properti, dan hanya itu (tidak ada yang menyatakan Anda mematuhi protokol). Metode ini umum di perpustakaan Apple, tetapi kode baru harus menggunakan pendekatan protokol yang lebih modern di atas, karena pendekatan ini mencemari NSObject
(yang membuat autocomplete kurang berguna) dan menyulitkan kompiler untuk memperingatkan Anda tentang kesalahan ketik dan kesalahan serupa.
unsigned int
tipe BOOL
sebagai nilai pengembalian delegate respondsToSelector
tipe BOOL
.
Jawaban yang disetujui bagus, tetapi jika Anda mencari jawaban 1 menit coba ini:
File MyClass.h akan terlihat seperti ini (tambahkan baris delegasi dengan komentar!)
#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
File MyClass.m akan terlihat seperti ini
#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
Untuk menggunakan delegasi Anda di kelas lain (UIViewController disebut MyVC dalam kasus ini) 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
Terapkan metode delegasi
- (void) myClassDelegateMethod: (MyClass *) sender {
NSLog(@"Delegates are great!");
}
myClass
instantiated di dalam MyVC.m?
Saat menggunakan metode protokol formal untuk membuat dukungan delegasi, saya telah menemukan bahwa Anda dapat memastikan pemeriksaan tipe yang tepat (meskipun, runtime, bukan waktu kompilasi) dengan menambahkan sesuatu seperti:
if (![delegate conformsToProtocol:@protocol(MyDelegate)]) {
[NSException raise:@"MyDelegate Exception"
format:@"Parameter does not conform to MyDelegate protocol at line %d", (int)__LINE__];
}
dalam kode pengakses delegasi Anda (setDelegate). Ini membantu meminimalkan kesalahan.
Silahkan! periksa tutorial langkah demi langkah di bawah ini untuk memahami cara kerja Delegasi di iOS.
Saya telah membuat dua ViewControllers (untuk mengirim data dari satu ke yang lain)
Mungkin ini lebih sesuai dengan apa yang Anda lewatkan:
Jika Anda datang dari sudut pandang C ++ seperti, delegasi mengambil sedikit membiasakan diri - tetapi pada dasarnya 'mereka hanya bekerja'.
Cara kerjanya adalah bahwa Anda menetapkan beberapa objek yang Anda tulis sebagai delegasi ke NSWindow, tetapi objek Anda hanya memiliki implementasi (metode) untuk satu atau beberapa dari banyak metode delegasi yang mungkin. Jadi sesuatu terjadi, dan NSWindow
ingin memanggil objek Anda - ia hanya menggunakan respondsToSelector
metode Objective-c untuk menentukan apakah objek Anda ingin metode itu dipanggil, dan kemudian menyebutnya. Beginilah cara obyektif-c bekerja - metode dicari sesuai permintaan.
Sangat sepele untuk melakukan ini dengan objek Anda sendiri, tidak ada yang istimewa terjadi, Anda dapat misalnya memiliki NSArray
27 objek, semua jenis objek yang berbeda, hanya 18 di antaranya memiliki metode -(void)setToBue;
9 lainnya tidak. Jadi untuk memanggil setToBlue
semua 18 yang perlu dilakukan, sesuatu seperti ini:
for (id anObject in myArray)
{
if ([anObject respondsToSelector:@selector(@"setToBlue")])
[anObject setToBlue];
}
Hal lain tentang delegasi adalah bahwa mereka tidak disimpan, jadi Anda harus selalu mengatur delegasi nil
dalam MyClass dealloc
metode Anda .
Sebagai praktik bagus yang direkomendasikan oleh Apple, ada baiknya bagi delegasi (yang merupakan protokol, menurut definisi), untuk menyesuaikan diri dengan NSObject
protokol.
@protocol MyDelegate <NSObject>
...
@end
& untuk membuat metode opsional dalam delegasi Anda (yaitu metode yang tidak perlu diimplementasikan), Anda dapat menggunakan @optional
anotasi seperti ini:
@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
Jadi ketika menggunakan metode yang Anda tentukan sebagai opsional, Anda perlu (di kelas Anda) memeriksa respondsToSelector
apakah tampilan (yang sesuai dengan delegasi Anda) telah benar-benar menerapkan metode opsional Anda atau tidak.
Saya pikir semua jawaban ini masuk akal begitu Anda memahami delegasi. Secara pribadi saya datang dari tanah C / C ++ dan sebelum itu bahasa prosedural seperti Fortran dll jadi di sini saya 2 menit mengambil menemukan analog serupa dalam paradigma C ++.
Jika saya menjelaskan delegasi ke seorang programmer C ++ / Java saya akan mengatakan
Apa itu delegasi? Ini adalah pointer statis ke kelas dalam kelas lain. Setelah Anda menetapkan pointer, Anda dapat memanggil fungsi / metode di kelas itu. Karenanya beberapa fungsi kelas Anda "didelegasikan" (Dalam dunia C ++ pointer - ke oleh objek pointer kelas) ke kelas lain.
Apa itu protokol? Secara konseptual ini berfungsi sebagai tujuan yang sama dengan file header kelas yang Anda tetapkan sebagai kelas delegasi. Protokol adalah cara eksplisit untuk mendefinisikan metode apa yang perlu diimplementasikan di kelas yang penunjuknya ditetapkan sebagai delegasi dalam kelas.
Bagaimana saya bisa melakukan hal serupa di C ++? Jika Anda mencoba melakukan ini di C ++, Anda akan dengan mendefinisikan pointer ke kelas (objek) dalam definisi kelas dan kemudian menghubungkannya ke kelas lain yang akan menyediakan fungsi tambahan sebagai delegasi ke kelas dasar Anda. Tetapi kabel ini perlu dipertahankan dalam kode dan akan menjadi canggung dan rentan kesalahan. Objective C hanya mengasumsikan bahwa programmer tidak terbaik dalam mempertahankan decipline ini dan memberikan batasan compiler untuk menegakkan implementasi yang bersih.
Delegasi hanyalah kelas yang melakukan beberapa pekerjaan untuk kelas lain. Baca kode berikut untuk contoh Playground yang agak konyol (tapi mudah-mudahan mencerahkan) yang menunjukkan bagaimana hal ini dilakukan di 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!"
}
Dalam praktik sebenarnya, delegasi sering digunakan dalam situasi berikut
Kelas-kelas tidak perlu tahu apa-apa tentang satu sama lain sebelumnya kecuali kelas delegasi sesuai dengan protokol yang diperlukan.
Saya sangat merekomendasikan membaca dua artikel berikut. Mereka membantu saya memahami delegasi bahkan lebih baik daripada dokumentasi .
Ok, ini sebenarnya bukan jawaban untuk pertanyaan itu, tetapi jika Anda mencari cara untuk membuat delegasi Anda sendiri, mungkin sesuatu yang jauh lebih sederhana bisa menjadi jawaban yang lebih baik untuk Anda.
Saya hampir tidak mengimplementasikan delegasi saya karena saya jarang membutuhkannya. Saya dapat meminta HANYA SATU delegasi untuk objek delegasi. Jadi, jika Anda ingin delegasi Anda untuk komunikasi satu arah / data yang lewat daripada Anda jauh lebih baik dengan pemberitahuan.
NSNotification dapat meneruskan objek ke lebih dari satu penerima dan sangat mudah digunakan. Ini berfungsi seperti ini:
File MyClass.m akan terlihat seperti ini
#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
Untuk menggunakan pemberitahuan Anda di kelas lain: Tambahkan kelas sebagai pengamat:
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(otherClassUpdatedItsData:) name:@"myClassUpdatedData" object:nil];
Terapkan pemilih:
- (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
}
Jangan lupa untuk menghapus kelas Anda sebagai pengamat jika
- (void)dealloc
{
[[NSNotificationCenter defaultCenter] removeObserver:self];
}
katakanlah Anda memiliki kelas yang Anda kembangkan dan ingin mendeklarasikan properti delegasi untuk dapat memberitahukannya ketika beberapa peristiwa terjadi:
@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
jadi Anda mendeklarasikan protokol dalam MyClass
file header (atau file header terpisah), dan mendeklarasikan penangan event yang diperlukan / opsional yang harus / harus diimplementasikan oleh delegasi Anda, kemudian mendeklarasikan properti dalam MyClass
tipe ( id< MyClassDelegate>
) yang berarti setiap kelas objektif c yang sesuai dengan protokol MyClassDelegate
, Anda akan melihat bahwa properti delegasi dinyatakan lemah, ini sangat penting untuk mencegah siklus mempertahankan (paling sering delegasi mempertahankan MyClass
instance jadi jika Anda menyatakan delegasi sebagai mempertahankan, keduanya akan mempertahankan satu sama lain dan tidak satu pun) dari mereka akan pernah dirilis).
Anda juga akan melihat bahwa metode protokol meneruskan MyClass
instance ke delegate sebagai parameter, ini adalah praktik terbaik jika delegasi ingin memanggil beberapa metode secara MyClass
instan dan juga membantu ketika delegasi menyatakan sendiri tentang MyClassDelegate
beberapa MyClass
instance, seperti ketika Anda memiliki banyak UITableView's
contoh di Anda ViewController
dan menyatakan dirinya sebagai UITableViewDelegate
untuk mereka semua.
dan di dalam Anda, MyClass
Anda memberi tahu delegasi dengan acara yang dinyatakan sebagai berikut:
if([_delegate respondsToSelector:@selector(myClass: requiredEventHandlerWithParameter:)])
{
[_delegate myClass:self requiredEventHandlerWithParameter:(ParamType*)param];
}
Anda pertama kali memeriksa apakah delegasi Anda merespons metode protokol yang akan Anda panggil seandainya delegasi tidak mengimplementasikannya dan aplikasi akan macet (bahkan jika metode protokol diperlukan).
Berikut adalah metode sederhana untuk membuat delegasi
Buat Protokol dalam file .h. Pastikan itu didefinisikan sebelum protokol menggunakan @class diikuti dengan nama UIViewController< As the protocol I am going to use is UIViewController class>.
Langkah: 1: Buat Protokol kelas baru bernama "YourViewController" yang akan menjadi subkelas dari kelas UIViewController dan tetapkan kelas ini ke ViewController kedua.
Langkah: 2: Buka file "YourViewController" dan modifikasi seperti di bawah ini:
#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
Metode yang didefinisikan dalam perilaku protokol dapat dikontrol dengan @optional dan @required sebagai bagian dari definisi protokol.
Langkah: 3: Implementasi Delegasi
#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
// uji apakah metode telah ditentukan sebelum Anda menyebutnya
- (void) someMethodToCallDelegate {
if ([[self delegate] respondsToSelector:@selector(defineDelegateMethodName:)]) {
[self.delegate delegateMethodName:self];
}
}
Untuk membuat delegasi Anda sendiri, pertama-tama Anda perlu membuat protokol dan mendeklarasikan metode yang diperlukan, tanpa menerapkan. Dan kemudian mengimplementasikan protokol ini ke kelas header Anda di mana Anda ingin menerapkan metode delegate atau delegate.
Protokol harus dinyatakan sebagai berikut:
@protocol ServiceResponceDelegate <NSObject>
- (void) serviceDidFailWithRequestType:(NSString*)error;
- (void) serviceDidFinishedSucessfully:(NSString*)success;
@end
Ini adalah kelas layanan di mana beberapa tugas harus dilakukan. Ini menunjukkan cara mendefinisikan delegasi dan cara mengatur delegasi. Di kelas implementasi setelah tugas selesai delegasi metode dipanggil.
@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
Ini adalah kelas tampilan utama dari mana kelas layanan dipanggil dengan mengatur delegasi ke dirinya sendiri. Dan juga protokol diimplementasikan di kelas header.
@interface viewController: UIViewController <ServiceResponceDelegate>
{
ServiceClass* _service;
}
- (void) go;
@end
@implementation viewController
//
//some methods
//
- (void) go
{
_service = [[ServiceClass alloc] init];
[_service setDelegate:self];
[_service someTask];
}
Itu saja, dan dengan menerapkan metode delegasi di kelas ini, kontrol akan kembali setelah operasi / tugas selesai.
Penafian: ini adalah Swift
versi cara membuat delegate
.
Jadi, apa yang dimaksud dengan delegasi? ... dalam pengembangan perangkat lunak, ada arsitektur solusi umum yang dapat digunakan kembali yang membantu untuk memecahkan masalah yang biasa terjadi dalam konteks yang diberikan, "template" ini, demikian, dikenal sebagai pola desain. Delegasi adalah pola desain yang memungkinkan satu objek untuk mengirim pesan ke objek lain ketika peristiwa tertentu terjadi. Bayangkan sebuah objek A memanggil objek B untuk melakukan suatu tindakan. Setelah tindakan selesai, objek A harus tahu bahwa B telah menyelesaikan tugas dan mengambil tindakan yang diperlukan, ini dapat dicapai dengan bantuan delegasi!
Untuk penjelasan yang lebih baik, saya akan menunjukkan kepada Anda cara membuat delegasi khusus yang mengirimkan data antar kelas, dengan Swift dalam aplikasi sederhana, mulai dengan mengunduh atau mengkloning proyek pemula ini dan menjalankannya!
Anda dapat melihat aplikasi dengan dua kelas, ViewController A
dan ViewController B
. B memiliki dua tampilan yang di tekan mengubah warna latar belakang ViewController
, tidak ada yang terlalu rumit kan? nah sekarang mari kita berpikir dengan cara yang mudah untuk juga mengubah warna latar belakang kelas A ketika pandangan tentang kelas B diketuk.
Masalahnya adalah bahwa pandangan ini adalah bagian dari kelas B dan tidak tahu tentang kelas A, jadi kita perlu menemukan cara untuk berkomunikasi antara dua kelas ini, dan di situlah delegasi bersinar. Saya membagi implementasi menjadi 6 langkah sehingga Anda dapat menggunakan ini sebagai lembar contekan saat Anda membutuhkannya.
langkah 1: Cari tanda pragma langkah 1 dalam file ClassBVC dan tambahkan ini
//MARK: step 1 Add Protocol here.
protocol ClassBVCDelegate: class {
func changeBackgroundColor(_ color: UIColor?)
}
Langkah pertama adalah membuat protocol
, dalam hal ini, kami akan membuat protokol di kelas B, di dalam protokol Anda dapat membuat banyak fungsi yang Anda inginkan berdasarkan persyaratan implementasi Anda. Dalam hal ini, kami hanya memiliki satu fungsi sederhana yang menerima opsi UIColor
sebagai argumen. Merupakan praktik yang baik untuk memberi nama protokol Anda dengan menambahkan kata delegate
di akhir nama kelas, dalam hal ini ClassBVCDelegate
,.
langkah 2: Cari tanda pragma langkah 2 ClassVBC
dan tambahkan ini
//MARK: step 2 Create a delegate property here.
weak var delegate: ClassBVCDelegate?
Di sini kita hanya membuat properti delegasi untuk kelas, properti ini harus mengadopsi protocol
tipe, dan itu harus opsional. Selain itu, Anda harus menambahkan kata kunci yang lemah sebelum properti untuk menghindari siklus penyimpanan dan kebocoran memori potensial, jika Anda tidak tahu apa artinya itu jangan khawatir untuk saat ini, ingatlah untuk menambahkan kata kunci ini.
Langkah 3: Carilah tanda pragma langkah 3 dalam handleTap method
di ClassBVC
dan menambahkan ini
//MARK: step 3 Add the delegate method call here.
delegate?.changeBackgroundColor(tapGesture.view?.backgroundColor)
Satu hal yang harus Anda ketahui, jalankan aplikasi dan ketuk pada tampilan apa pun, Anda tidak akan melihat perilaku baru dan itu benar tetapi hal yang ingin saya tunjukkan adalah aplikasi itu tidak macet ketika delegasi dipanggil, dan itu karena kita membuatnya sebagai nilai opsional dan itulah mengapa itu tidak akan crash bahkan yang didelegasikan belum ada. Sekarang mari kita pergi ke ClassAVC
file dan membuatnya, yang didelegasikan.
langkah 4: Cari tanda pragma langkah 4 di dalam metode handleTap ClassAVC
dan tambahkan ini di sebelah tipe kelas Anda seperti ini.
//MARK: step 4 conform the protocol here.
class ClassAVC: UIViewController, ClassBVCDelegate {
}
Sekarang ClassAVC mengadopsi ClassBVCDelegate
protokol, Anda dapat melihat bahwa kompiler Anda memberi Anda kesalahan yang mengatakan "Ketik 'ClassAVC tidak sesuai dengan protokol' ClassBVCDelegate 'dan ini hanya berarti bahwa Anda belum menggunakan metode protokol, bayangkan bahwa ketika kelas A mengadopsi protokol itu seperti menandatangani kontrak dengan kelas B dan kontrak ini mengatakan "Setiap kelas yang mengadopsi saya HARUS menggunakan fungsi saya!"
Catatan cepat: Jika Anda berasal dari Objective-C
latar belakang, Anda mungkin berpikir bahwa Anda juga dapat menutup kesalahan itu dengan membuat metode itu opsional, tetapi yang mengejutkan saya, dan mungkin milik Anda, Swift
bahasa tidak mendukung opsional protocols
, jika Anda ingin melakukannya, Anda dapat membuat ekstensi untuk Anda protocol
atau gunakan kata kunci @objc dalam protocol
implementasi Anda .
Secara pribadi, Jika saya harus membuat protokol dengan metode opsional yang berbeda, saya lebih suka memecahnya menjadi berbeda protocols
, dengan cara itu saya akan mengikuti konsep memberikan satu tanggung jawab tunggal ke objek saya, tetapi dapat bervariasi berdasarkan pada implementasi spesifik.
di sini ada artikel bagus tentang metode opsional.
langkah 5: Cari tanda pragma langkah 5 di dalam metode persiapan untuk segue dan tambahkan ini
//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
}
Di sini kita hanya membuat instance ClassBVC
dan menugaskan delegasinya untuk diri sendiri, tetapi apa itu diri di sini? yah, diri adalah ClassAVC
yang telah didelegasikan!
langkah 6: Akhirnya, cari langkah pragma 6 ClassAVC
dan mari kita gunakan fungsi protocol
, mulai mengetik func changeBackgroundColor dan Anda akan melihat bahwa itu melengkapinya secara otomatis untuk Anda. Anda dapat menambahkan implementasi di dalamnya, dalam contoh ini, kami hanya akan mengubah warna latar belakang, tambahkan ini.
//MARK: step 6 finally use the method of the contract
func changeBackgroundColor(_ color: UIColor?) {
view.backgroundColor = color
}
Sekarang jalankan aplikasinya!
Delegates
ada di mana-mana dan Anda mungkin menggunakannya tanpa pemberitahuan, jika Anda membuat tableview
delegasi di masa lalu yang Anda gunakan, banyak kelas UIKIT
pekerjaan di sekitar mereka dan banyak lainnya frameworks
juga, mereka memecahkan masalah utama ini.
Selamat, Anda baru saja mengimplementasikan delegasi khusus, saya tahu Anda mungkin berpikir, begitu banyak masalah hanya untuk ini? baik, delegasi adalah pola desain yang sangat penting untuk dipahami jika Anda ingin menjadi iOS
pengembang, dan selalu ingat bahwa mereka memiliki hubungan satu lawan satu antara objek.
Anda dapat melihat tutorial aslinya di sini
Jawaban sebenarnya dijawab, tetapi saya ingin memberi Anda "lembar contekan" untuk membuat delegasi:
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
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;
Metode:
-(void)delegateMEthod: (ArgType) arg{
}
Dalam pandangan saya buat kelas terpisah untuk metode delegasi itu dan Anda dapat menggunakan di mana Anda inginkan.
di DropDownClass.h Kustom saya
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;
setelah itu file.m membuat array dengan objek,
- (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];
}
}
}];
}
Di sini semua diatur untuk kelas delegasi Kustom. Setelah itu Anda dapat menggunakan metode delegasi ini di mana Anda inginkan. Misalnya ...
di impor viewcontroller saya yang lain setelah itu
buat tindakan untuk memanggil metode delegasi seperti ini
- (IBAction)dropDownBtn1Action:(id)sender {
DropDownViewController *vehicleModelDropView = [[DropDownViewController alloc]init];
vehicleModelDropView.dropDownType = DDCITY;
vehicleModelDropView.delegate = self;
[self presentViewController:vehicleModelDropView animated:YES completion:nil];
}
setelah itu panggil metode delegate seperti ini
- (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;
}
}
Delegasi: - Buat
@protocol addToCartDelegate <NSObject>
-(void)addToCartAction:(ItemsModel *)itemsModel isAdded:(BOOL)added;
@end
Kirim dan tolong tetapkan delegasi untuk melihat Anda mengirim data
[self.delegate addToCartAction:itemsModel isAdded:YES];
//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. Menerapkan metode di kelas .m - (void) didRemoveCellWithTag: (NSInteger) tag {NSLog @ ("Tag% d", tag);
}
Mari kita mulai dengan sebuah contoh, jika kita membeli suatu produk secara online, ia akan melalui proses seperti pengiriman / pengiriman yang ditangani oleh tim yang berbeda. akan menjadi overhead untuk orang lain / vendor mungkin ingin meneruskan informasi ini hanya kepada orang-orang yang diperlukan.
Jadi jika kita berpikir dalam hal aplikasi kita, sebuah acara dapat menjadi pesanan online & tim yang berbeda bisa seperti banyak tampilan.
Berikut ini kode yang menganggap ShippingView sebagai tim Pengiriman & DeliveryView sebagai tim pengiriman:
//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
//
}
}