Delegelerin nasıl çalıştığını biliyorum ve onları nasıl kullanabileceğimi biliyorum.
Ama onları nasıl yaratırım?
Delegelerin nasıl çalıştığını biliyorum ve onları nasıl kullanabileceğimi biliyorum.
Ama onları nasıl yaratırım?
Yanıtlar:
Objective-C delegesi, delegate
özelliğe başka bir nesne atanmış bir nesnedir. Bir tane oluşturmak için, ilgilendiğiniz temsilci yöntemlerini uygulayan bir sınıf tanımlarsınız ve bu sınıfı temsilci protokolünü uygularken olarak işaretlersiniz.
Örneğin, varsayalım UIWebView
. Temsilcinin webViewDidStartLoad:
yöntemini uygulamak isterseniz, şöyle bir sınıf oluşturabilirsiniz:
@interface MyClass<UIWebViewDelegate>
// ...
@end
@implementation MyClass
- (void)webViewDidStartLoad:(UIWebView *)webView {
// ...
}
@end
Daha sonra bir MyClass örneği oluşturabilir ve bunu web görünümünün temsilcisi olarak atayabilirsiniz:
MyClass *instanceOfMyClass = [[MyClass alloc] init];
myWebView.delegate = instanceOfMyClass;
Tarafta, UIWebView
muhtemelen temsilcinin webViewDidStartLoad:
iletiyi kullanarak yanıt verip vermediğini görmek respondsToSelector:
ve buna uygun olarak göndermek için buna benzer bir kodu vardır .
if([self.delegate respondsToSelector:@selector(webViewDidStartLoad:)]) {
[self.delegate webViewDidStartLoad:self];
}
Temsilci özelliğinin kendisi, döngüleri korumaktan kaçınmak için genellikle weak
(ARC'de) veya assign
(ARC öncesi ) bildirilir , çünkü bir nesnenin temsilcisi genellikle bu nesneye güçlü bir başvuruda bulunur. (Örneğin, bir görünüm denetleyicisi genellikle içerdiği bir görünümün temsilcisidir.)
Kendi delegelerinizi tanımlamak için , protokollerle ilgili Apple Dokümanlar'da tartışıldığı gibi yöntemlerini bir yerde bildirmeniz gerekir . Genellikle resmi bir protokol beyan edersiniz. UIWebView.h'den başka sözcüklerle açıklanan bildirim şöyle görünür:
@protocol UIWebViewDelegate <NSObject>
@optional
- (void)webViewDidStartLoad:(UIWebView *)webView;
// ... other methods here
@end
Bu, bir temsilci veya soyut temel sınıfa benzer, çünkü UIWebViewDelegate
bu durumda temsilciniz için özel bir tür oluşturur . Temsilci uygulayıcıların bu protokolü benimsemesi gerekir:
@interface MyClass <UIWebViewDelegate>
// ...
@end
Ve sonra protokolde yöntemleri uygulayın. Protokolde @optional
(çoğu delege yöntemi gibi) bildirilen yöntemler için, -respondsToSelector:
belirli bir yöntemi çağırmadan önce kontrol etmeniz gerekir .
Temsilci yöntemleri genellikle temsilci sınıf adıyla başlayarak adlandırılır ve temsilci nesneyi ilk parametre olarak alır. Ayrıca çoğu zaman bir irade, bir zorunluluk ya da bir yapı kullanırlar. Yani, webViewDidStartLoad:
(ilk parametre web görünümüdür) yerine loadStarted
(parametre almayan ) yerine .
Bir temsilci seçiciye her mesaj göndermek istediğimizde yanıt verip vermediğini kontrol etmek yerine, temsilciler ayarlandığında bu bilgileri önbelleğe alabilirsiniz. Bunu yapmanın çok temiz bir yolu, aşağıdaki gibi bir bitfield kullanmaktır:
@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
Daha sonra, vücutta, temsilcisimizin mesajları tekrar tekrar delegateRespondsTo
göndermek yerine yapımıza erişerek kontrol ettiğini kontrol edebiliriz -respondsToSelector:
.
Protokoller var önce, bir kullanımı yaygındı kategorisini üzerinde NSObject
bir temsilci uygulamak yöntemlerini ilan etmek. Örneğin, CALayer
yine de bunu yapar:
@interface NSObject(CALayerDelegate)
- (void)displayLayer:(CALayer *)layer;
// ... other methods here
@end
Bu derleyiciye herhangi bir nesnenin uygulayabileceğini söyler displayLayer:
.
Daha sonra -respondsToSelector:
bu yöntemi çağırmak için yukarıda açıklananla aynı yaklaşımı kullanırsınız . Delegeler bu yöntemi uygular ve delegate
özelliği atarlar ve hepsi budur (bir protokole uyduğunuzu beyan etmek yoktur). Bu yöntem Apple'ın kitaplıklarında yaygındır, ancak yeni kod yukarıdaki daha modern protokol yaklaşımını kullanmalıdır, çünkü bu yaklaşım NSObject
(otomatik tamamlamayı daha az kullanışlı hale getirir) kirletir ve derleyicinin yazım hataları ve benzer hatalar konusunda sizi uyarmasını zorlaştırır.
unsigned int
türünü BOOL
dönüş değeri olarak delegate respondsToSelector
tiptedir BOOL
.
Onaylanan cevap harika, ancak 1 dakikalık bir cevap arıyorsanız şunu deneyin:
MyClass.h dosyası şöyle görünmelidir (açıklamalara delege satırları ekleyin!)
#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 dosyası şöyle görünmelidir
#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
Temsilcinizi başka bir sınıfta kullanmak için (bu durumda MyVC olarak adlandırılan UIViewController) 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
Delege yöntemini uygulama
- (void) myClassDelegateMethod: (MyClass *) sender {
NSLog(@"Delegates are great!");
}
myClass
MyVC.m içinde nereden somutlaştırılır?
Temsilci desteği oluşturmak için resmi protokol yöntemini kullanırken, gibi bir şey ekleyerek uygun tür denetleme (zaman olsa da, derleme değil zaman) sağlayabilirsiniz buldum:
if (![delegate conformsToProtocol:@protocol(MyDelegate)]) {
[NSException raise:@"MyDelegate Exception"
format:@"Parameter does not conform to MyDelegate protocol at line %d", (int)__LINE__];
}
delege erişimci (setDelegate) kodunuzda. Bu, hataları en aza indirmeye yardımcı olur.
Lütfen! Temsilcilerin iOS'ta nasıl çalıştığını anlamak için basit adım adım öğreticiyi kontrol edin.
İki ViewControllers oluşturdum (birinden diğerine veri göndermek için)
Belki de bu daha çok eksik olduğunuz şeylerdir:
C ++ benzeri bir bakış açısıyla geliyorsanız, delegeler biraz alışmaya başlar - ama temelde 'sadece çalışırlar'.
Çalışma şekli, NSWindow'a delege olarak yazdığınız bir nesneyi ayarlamanızdır, ancak nesnenizde birçok olası temsilci yönteminden yalnızca bir veya birkaçına yönelik uygulamalar (yöntemler) vardır. Bir şey olur ve NSWindow
nesnenizi çağırmak ister - respondsToSelector
nesnenizin bu yöntemin çağrılmasını isteyip istemediğini belirlemek için Objective-c yöntemini kullanır ve sonra çağırır. Objektif-c böyle çalışır - talep üzerine yöntemler araştırılır.
Bunu kendi nesnelerinizle yapmak tamamen önemsizdir, özel bir şey yoktur, örneğin NSArray
27 nesneden birine, her türlü nesneye sahip olabilirsiniz, sadece 18'inde -(void)setToBue;
diğer 9'un yöntemi yoktur. setToBlue
Yapılması gereken 18'in tümünü çağırmak için, şöyle bir şey:
for (id anObject in myArray)
{
if ([anObject respondsToSelector:@selector(@"setToBlue")])
[anObject setToBlue];
}
Delegelerle ilgili diğer bir şey, alıkonulmamasıdır, bu nedenle her zaman temsilci yönteminize ayarlamanız nil
gerekir MyClass dealloc
.
Apple tarafından önerilen iyi bir uygulama olarak, temsilcinin (tanım gereği bir protokol olan) NSObject
protokole uyması iyidir .
@protocol MyDelegate <NSObject>
...
@end
& temsilciniz içinde isteğe bağlı yöntemler oluşturmak için (yani mutlaka uygulanması gerekmeyen yöntemler), @optional
ek açıklamayı şu şekilde kullanabilirsiniz :
@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
Bu nedenle, isteğe bağlı olarak belirttiğiniz yöntemleri kullanırken, (sınıfınızda) respondsToSelector
görünümün (temsilcinize uygun olan) gerçekten isteğe bağlı yöntem (ler) inizi uygulayıp uygulamadığını kontrol etmeniz gerekir.
Temsilcileri anladıktan sonra tüm bu cevapların çok anlamlı olduğunu düşünüyorum. Şahsen C / C ++ ülkesinden geldim ve Fortran vb. Gibi prosedürel dillerden önce C ++ paradigmasında benzer analogları bulmak için 2 dakikam.
Bir C ++ / Java programcısına delegeleri açıklayacak olsaydım
Delege nedir? Bunlar başka bir sınıf içindeki sınıflara statik işaretçilerdir. Bir işaretçi atadıktan sonra, o sınıftaki işlevleri / yöntemleri çağırabilirsiniz. Bu nedenle, sınıfınızın bazı işlevleri başka bir sınıfa "temsil edilir" (C ++ dünyasında - bir sınıf nesnesi işaretçisiyle işaretçi).
Protokoller nelerdir? Kavramsal olarak, delege sınıfı olarak atadığınız sınıfın başlık dosyasına benzer bir amaca hizmet eder. Protokol, sınıfta hangi yöntemlerin uygulanması gerektiğini tanımlamanın açık bir yoludur. İşaretçi sınıf içinde temsilci olarak ayarlanmıştır.
C ++ 'da benzer bir şeyi nasıl yapabilirim? Bunu C ++ 'da yapmaya çalışırsanız, sınıf tanımında sınıflara (nesnelere) işaretçiler tanımlayıp daha sonra bunları temel sınıfınıza delege olarak ek işlevler sağlayacak diğer sınıflara bağlayabilirsiniz. Ancak bu kablolamanın kod içinde düzeltilmesi gerekir ve beceriksiz ve hataya eğilimli olacaktır. Hedef C, programcıların bu dezavantajı sürdürmede en iyi olmadığını varsayar ve temiz bir uygulamayı uygulamak için derleyici kısıtlamaları sağlar.
Bir temsilci sadece başka bir sınıf için çalışan bir sınıftır. Swift'te bunun nasıl yapıldığını gösteren biraz aptalca (ancak umarım aydınlatıcı) bir Oyun Alanı örneği için aşağıdaki kodu okuyun.
// 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!"
}
Gerçek uygulamada, delegeler aşağıdaki durumlarda sıklıkla kullanılır
Sınıfların önceden delege sınıfının gerekli protokole uyması dışında birbirleri hakkında hiçbir şey bilmeleri gerekmez.
Aşağıdaki iki makaleyi okumanızı tavsiye ederim. Delegeleri belgelere göre daha iyi anlamama yardımcı oldular .
Tamam, bu gerçekten sorunun cevabı değil, ancak kendi delegenizi nasıl yapacağınızı arıyorsanız belki daha basit bir şey sizin için daha iyi bir cevap olabilir.
Delegelerimi zor uyguladım çünkü nadiren ihtiyacım var. Bir temsilci nesnesi için SADECE bir temsilci olabilir. Bu nedenle, temsilcinizin tek yönlü iletişim / veri iletmesini istiyorsanız, bildirimlerden çok daha iyidir.
NSNotification nesneleri birden fazla alıcıya aktarabilir ve kullanımı çok kolaydır. Şöyle çalışır:
MyClass.m dosyası şöyle görünmelidir
#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
Bildiriminizi başka bir sınıfta kullanmak için: Sınıfı gözlemci olarak ekleyin:
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(otherClassUpdatedItsData:) name:@"myClassUpdatedData" object:nil];
Seçiciyi uygulayın:
- (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
}
Eğer bir gözlemci olarak sınıfınızı kaldırmayı unutmayın
- (void)dealloc
{
[[NSNotificationCenter defaultCenter] removeObserver:self];
}
diyelim ki geliştirdiğiniz bir sınıfınız var ve bir etkinlik gerçekleştiğinde bunu bildirmek için bir temsilci özelliği bildirmek istiyorsunuz:
@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
böylece MyClass
üstbilgi dosyasında (veya ayrı bir üstbilgi dosyasında) bir protokol bildirir ve temsilcinizin uygulaması / uygulaması gereken gerekli / isteğe bağlı olay işleyicilerini bildirirsiniz, sonra MyClass
tür ( id< MyClassDelegate>
) türünde bir özellik bildirir. protokol MyClassDelegate
, temsilci özelliğinin zayıf olarak bildirildiğini fark edeceksiniz, bu tutma döngüsünü önlemek için çok önemlidir (çoğu zaman temsilci MyClass
örneği korur, bu nedenle temsilci tutma olarak beyan ederseniz, her ikisi de birbirini korur ve hiçbiri bunlardan hiç çıkmayacak).
Ayrıca protokol yöntemlerinin MyClass
örneği parametre olarak delegee geçirdiğini göreceksiniz. Bu, delegenin MyClass
örnek olarak bazı yöntemleri çağırmak istemesi durumunda en iyi uygulamadır ve aynı zamanda temsilci, MyClassDelegate
birden çok MyClass
örneğiniz gibi, UITableView's
sizin durumunuzda ViewController
kendini UITableViewDelegate
gösterir ve hepsini hepsine bir olarak ilan eder .
ve MyClass
bildirdiğiniz olayları temsilci ile aşağıdaki şekilde bilgilendirirsiniz:
if([_delegate respondsToSelector:@selector(myClass: requiredEventHandlerWithParameter:)])
{
[_delegate myClass:self requiredEventHandlerWithParameter:(ParamType*)param];
}
ilk önce temsilci uygulamanız gereken protokol yöntemine yanıt verip vermediğini kontrol edersiniz ve temsilci uygulamadığı takdirde uygulama çökecektir (protokol yöntemi gerekli olsa bile).
İşte temsilci oluşturmak için basit bir yöntem
.H dosyasında Protokol oluşturun. @Class ve ardından UIViewController adının kullanıldığı protokolden önce tanımlandığından emin olun< As the protocol I am going to use is UIViewController class>.
Adım: 1: UIViewController sınıfının alt sınıfı olacak "YourViewController" adlı yeni bir sınıf Protokolü oluşturun ve bu sınıfı ikinci ViewController'a atayın.
Adım: 2: "YourViewController" dosyasına gidin ve aşağıdaki gibi değiştirin:
#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
Protokol davranışında tanımlanan yöntemler, protokol tanımının bir parçası olarak @optional ve @required ile kontrol edilebilir.
Adım: 3: Delege Uygulaması
#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
// yöntem çağrılmadan önce tanımlanıp tanımlanmadığını test edin
- (void) someMethodToCallDelegate {
if ([[self delegate] respondsToSelector:@selector(defineDelegateMethodName:)]) {
[self.delegate delegateMethodName:self];
}
}
Kendi temsilcinizi oluşturmak için, önce bir protokol oluşturmanız ve uygulama yapmadan gerekli yöntemleri bildirmeniz gerekir. Daha sonra bu protokolü, temsilci veya temsilci yöntemlerini uygulamak istediğiniz başlık sınıfınıza uygulayın.
Bir protokol aşağıdaki gibi beyan edilmelidir:
@protocol ServiceResponceDelegate <NSObject>
- (void) serviceDidFailWithRequestType:(NSString*)error;
- (void) serviceDidFinishedSucessfully:(NSString*)success;
@end
Bu, bazı görevlerin yapılması gereken hizmet sınıfıdır. Temsilcinin nasıl tanımlanacağını ve temsilcinin nasıl ayarlanacağını gösterir. Uygulama sınıfında görev tamamlandıktan sonra delege yöntemleri çağrılır.
@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
Bu, temsilci kendisine ayarlanarak hizmet sınıfının çağrıldığı ana görünüm sınıfıdır. Ayrıca protokol başlık sınıfında uygulanır.
@interface viewController: UIViewController <ServiceResponceDelegate>
{
ServiceClass* _service;
}
- (void) go;
@end
@implementation viewController
//
//some methods
//
- (void) go
{
_service = [[ServiceClass alloc] init];
[_service setDelegate:self];
[_service someTask];
}
Bu kadar ve bu sınıfta delege yöntemleri uygulayarak, işlem / görev tamamlandığında kontrol geri gelecektir.
Feragatname: Bu, Swift
nasıl oluşturulacağının sürümüdür delegate
.
Delegeler nelerdir? … Yazılım geliştirmede, belirli bir bağlamda yaygın olarak ortaya çıkan sorunların çözülmesine yardımcı olan genel yeniden kullanılabilir çözüm mimarileri vardır, bu “şablonlar” tabiri caizse, en iyi tasarım modelleri olarak bilinir. Temsilciler, belirli bir olay gerçekleştiğinde bir nesnenin başka bir nesneye mesaj göndermesine izin veren bir tasarım modelidir. A nesnesinin bir eylemi gerçekleştirmek için B nesnesini çağırdığını düşünün. Eylem tamamlandığında, A nesnesi B'nin görevi tamamladığını bilmeli ve gerekli eylemi gerçekleştirmelidir, bu delegelerin yardımıyla gerçekleştirilebilir!
Daha iyi bir açıklama için, basit bir uygulamada Swift ile sınıflar arasında veri ileten özel bir temsilci oluşturmayı göstereceğim, bu başlangıç projesini indirerek veya klonlayarak başlayın ve çalıştırın!
İki sınıflı bir uygulama görebilirsiniz ViewController A
ve ViewController B
. B, dokunduğunda arka plan rengini değiştiren iki görünüm var, ViewController
çok karmaşık bir şey değil mi? şimdi de B sınıfına ilişkin görünümlere dokunulduğunda A sınıfının arka plan rengini değiştirmenin kolay bir yolunu düşünelim.
Sorun şu ki, bu görüşler B sınıfının bir parçası ve A sınıfı hakkında hiçbir fikre sahip değiller, bu yüzden bu iki sınıf arasında iletişim kurmanın bir yolunu bulmamız gerekiyor ve bu da delegasyonun parladığı yer. Uygulamayı 6 adıma böldüm, böylece ihtiyacınız olduğunda bunu bir hile sayfası olarak kullanabilirsiniz.
adım 1: ClassBVC dosyasında pragma işareti adım 1'i bulun ve ekleyin
//MARK: step 1 Add Protocol here.
protocol ClassBVCDelegate: class {
func changeBackgroundColor(_ color: UIColor?)
}
İlk adım, protocol
bu durumda, B sınıfında protokolü oluşturacağız, protokolün içinde, uygulamanızın gereksinimlerine göre istediğiniz kadar işlev oluşturabilirsiniz. Bu durumda, isteğe bağlı UIColor
olarak argüman olarak kabul eden basit bir fonksiyonumuz var . delegate
Sınıf isminin sonuna sözcük ekleyerek protokollerinizi adlandırmak için iyi bir uygulamadır , bu durumda ClassBVCDelegate
,.
2. adım: 2. adımdaki pragma işaretini arayın ClassVBC
ve ekleyin
//MARK: step 2 Create a delegate property here.
weak var delegate: ClassBVCDelegate?
Burada sadece sınıf için bir temsilci özelliği oluşturuyoruz, bu özellik protocol
türü benimsemeli ve isteğe bağlı olmalıdır. Ayrıca, koruma döngülerini ve potansiyel bellek sızıntılarını önlemek için mülkün önüne zayıf anahtar kelimeyi eklemelisiniz, bunun ne anlama geldiğini bilmiyorsanız, bu anahtar kelimeyi eklemeyi unutmayın.
3. adım: handleTap içindeki Pragma işareti 3. adımda için bak method
içinde ClassBVC
ve bu ekleme
//MARK: step 3 Add the delegate method call here.
delegate?.changeBackgroundColor(tapGesture.view?.backgroundColor)
Bilmeniz gereken bir şey, uygulamayı çalıştırın ve herhangi bir görünüme dokunun, yeni bir davranış görmeyeceksiniz ve bu doğru ama işaret etmek istediğim şey, temsilci çağrıldığında uygulamanın çökmediği ve çünkü bunu isteğe bağlı bir değer olarak yaratıyoruz ve bu yüzden yetki verilenler bile çökmeyecek. Şimdi ClassAVC
dosyaya gidip delege yapalım .
adim 4: handleTap yönteminin içindeki pragma işareti adımı 4'ü arayın ClassAVC
ve bunu böyle sınıf türünüzün yanına ekleyin.
//MARK: step 4 conform the protocol here.
class ClassAVC: UIViewController, ClassBVCDelegate {
}
Şimdi ClassAVC ClassBVCDelegate
protokolü kabul etti, derleyicinizin size “Type 'ClassAVC' ClassBVCDelegate 'protokolüne uymadığını söyleyen bir hata verdiğini görebilirsiniz ve bu sadece protokol yöntemlerini henüz kullanmadığınız anlamına gelir, A sınıfı protokolü kabul ettiğinde, B sınıfı ile bir sözleşme imzalamak gibidir ve bu sözleşme “Beni kabul eden herhangi bir sınıfın işlevlerimi KULLANMASI GEREKİR!” der.
Kısa not: Bir Objective-C
arka plandan gelirseniz, muhtemelen bu yöntemi isteğe bağlı hale getiren bir hatayı da kapatabileceğinizi düşünüyorsunuz, ancak sürprizim ve muhtemelen sizin Swift
diliniz için dil isteğe bağlı olarak desteklenmiyor protocols
, eğer yapmak istiyorsanız oluşturabilirsiniz için bir uzantı protocol
veya protocol
uygulamanızda @objc anahtar sözcüğünü kullanın .
Şahsen, farklı isteğe bağlı yöntemlerle bir protokol oluşturmak zorunda kalırsam, onu farklı hale getirmeyi tercih ederim protocols
, bu şekilde nesnelerime tek bir sorumluluk verme kavramını takip edeceğim, ancak belirli uygulamaya bağlı olarak değişebilir.
İşte isteğe bağlı yöntemler hakkında iyi bir makale.
adım 5: segue yöntemine hazırlanmanın içindeki pragma işareti adım 5'i arayın ve ekleyin
//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
}
Burada sadece bir örneğini oluşturup ClassBVC
temsilcisini kendimize atarız, ama burada benlik nedir? Eh, ClassAVC
delege edilen kendiliktir !
adım 6: Son olarak, pragma adım 6'yı arayın ClassAVC
ve işlevlerini kullanalım, protocol
func changeBackgroundColor yazmaya başlayın ve bunun sizin için otomatik olarak tamamlandığını göreceksiniz. İçine herhangi bir uygulama ekleyebilirsiniz, bu örnekte, sadece arka plan rengini değiştireceğiz, bunu ekleyeceğiz.
//MARK: step 6 finally use the method of the contract
func changeBackgroundColor(_ color: UIColor?) {
view.backgroundColor = color
}
Şimdi uygulamayı çalıştırın!
Delegates
her yerde ve muhtemelen haber vermeden kullanırsınız tableview
, geçmişte bir delegasyon kullandıysanız, UIKIT
etraflarında birçok çalışma sınıfı ve daha birçoğu oluşturursanız frameworks
, bu ana sorunları çözerler.
Tebrikler, sadece özel bir delege uyguluyorsunuz, muhtemelen düşündüğünüzü biliyorum, sadece bunun için çok fazla sorun mu var? temsilci, iOS
geliştirici olmak isteyip istemediğinizi anlamak için çok önemli bir tasarım modelidir ve nesneler arasında bire bir ilişkilerinin olduğunu her zaman aklınızda bulundurun.
Orijinal öğreticiyi burada görebilirsiniz
Cevap aslında cevaplandı, ancak bir temsilci oluşturmak için size bir "hile sayfası" vermek istiyorum:
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;
Yöntem:
-(void)delegateMEthod: (ArgType) arg{
}
Benim açımdan o temsilci yöntemi için ayrı bir sınıf oluşturun ve istediğiniz yerde kullanabilirsiniz.
Özel DropDownClass.h dosyamda
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;
bundan sonra in.m dosyasında nesnelerle dizi oluşturma,
- (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];
}
}
}];
}
Tümü Özel temsilci sınıfı için ayarlanmıştır. Bundan sonra istediğiniz yerde bu temsilci yöntemini kullanabilirsiniz. Örneğin ...
ondan sonra başka bir viewcontroller ithalat benim
delege yöntemini çağırmak için eylem oluştur
- (IBAction)dropDownBtn1Action:(id)sender {
DropDownViewController *vehicleModelDropView = [[DropDownViewController alloc]init];
vehicleModelDropView.dropDownType = DDCITY;
vehicleModelDropView.delegate = self;
[self presentViewController:vehicleModelDropView animated:YES completion:nil];
}
bundan sonra delege yöntemini şöyle çağır
- (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;
}
}
Temsilci: - Oluştur
@protocol addToCartDelegate <NSObject>
-(void)addToCartAction:(ItemsModel *)itemsModel isAdded:(BOOL)added;
@end
Gönder ve lütfen veri gönderdiğinizi görüntülemek için temsilci atayın
[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. Yöntemi sınıfında uygulayın. M - (void) didRemoveCellWithTag: (NSInteger) etiketi {NSLog @ ("Etiket% d", etiket);
}
Çevrimiçi olarak bir ürün satın alırsak, bir örnekle başlayalım, farklı ekipler tarafından taşınan nakliye / teslimat gibi bir süreçten geçer.Gönderim tamamlanırsa, nakliye ekibi teslimat ekibini bilgilendirmeli ve bu bilgileri yayınlayan birebir iletişim olmalıdır. başkaları için ek yük / satıcı bu bilgileri sadece gerekli kişilere iletmek isteyebilir.
Uygulamamız açısından düşünürsek, bir etkinlik çevrimiçi sipariş olabilir ve farklı ekipler birden çok görüntüleme gibi olabilir.
İşte kodu ShippingView'i Nakliye ekibi olarak düşünün ve DeliveryView'u dağıtım ekibi olarak düşünün:
//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
//
}
}