Вопрос

Я знаю, как работают делегаты, и я знаю, как я могу их использовать.

Но как мне их создать?

Это было полезно?

Решение

Делегат Objective-C - это объект, который был назначен свойству delegate другого объекта. Чтобы создать его, вы просто определяете класс, который реализует интересующие вас методы делегата, и помечаете этот класс как реализующий протокол делегата.

Например, предположим, у вас есть UIWebView. Если вы хотите реализовать webViewDidStartLoad: , вы можете создать такой класс:

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

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

Затем вы можете создать экземпляр MyClass и назначить его делегатом веб-представления:

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

Со стороны respondsToSelector: он, вероятно, имеет код, подобный этому, чтобы увидеть, отвечает ли делегат на сообщение weak, используя assign и при необходимости отправьте его.

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

Само свойство делегата обычно объявляется UIWebViewDelegate (в ARC) или @optional (до ARC), чтобы избежать циклов сохранения, поскольку делегат объекта часто содержит строгую ссылку на этот объект. (Например, контроллер представления часто является делегатом представления, которое он содержит.)

Создание делегатов для ваших классов

Чтобы определить своих собственных делегатов, вам нужно где-то объявить их методы, как описано в Документы Apple по протоколам . Вы обычно объявляете официальный протокол. Объявление, перефразированное из UIWebView.h, будет выглядеть так:

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

Это аналог интерфейса или абстрактного базового класса, поскольку он создает специальный тип для вашего делегата, в данном случае -respondsToSelector:. Делегатам-разработчикам придется принять этот протокол:

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

А затем реализовать методы в протоколе. Для методов, объявленных в протоколе как loadStarted (как и большинство методов делегатов), вам необходимо проверить с помощью delegateRespondsTo перед вызовом определенного метода для него.

Нейминг

Методы делегирования обычно называются, начиная с имени класса делегирования, и принимают делегирующий объект в качестве первого параметра. Они также часто используют волю, следует или сделали. Так, например, NSObject (первый параметр - веб-представление), а не CALayer (без параметров).

Оптимизация скорости

Вместо того, чтобы проверять, отвечает ли делегат на селектор каждый раз, когда мы хотим отправить его, вы можете кэшировать эту информацию, когда установлены делегаты. Один из самых простых способов сделать это - использовать битовое поле следующим образом:

@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

Затем в теле мы можем проверить, что наш делегат обрабатывает сообщения, обращаясь к нашей displayLayer: структуре, а не отправляя <=> снова и снова.

Неофициальные делегаты

До появления протоколов было обычным делом использовать категория в <=> для объявления методов, которые может реализовать делегат. Например, <=> все еще делает это:

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

Это, по сути, говорит компилятору, что любой объект может реализовывать <=>.

Затем вы бы использовали тот же <=> подход, как описано выше, для вызова этого метода. Делегаты просто реализуют этот метод и присваивают свойство <=>, и все (нет заявления о том, что вы соответствуете протоколу). Этот метод распространен в библиотеках Apple, но новый код должен использовать более современный протоколный подход, описанный выше, так как этот подход загрязняет <=> (что делает автозаполнение менее полезным) и затрудняет компилятору предупреждение вас о опечатках и подобных ошибках.

Другие советы

Одобренный ответ - это здорово, но если вы ищете ответ продолжительностью в 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!");
}

При использовании метода формального протокола для создания поддержки делегатов я обнаружил, что вы можете обеспечить правильную проверку типов (пусть и во время выполнения, а не во время компиляции), добавив что-то вроде:

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

в вашем коде доступа делегата (setDelegate). Это помогает минимизировать ошибки.

Может быть, это больше похоже на то, чего вам не хватает:

Если вы исходите из точки зрения, подобной C ++, делегатам нужно немного привыкнуть, но в основном «они просто работают».

Способ работает так, что вы устанавливаете некоторый объект, который вы написали в качестве делегата в NSWindow, но ваш объект имеет только реализации (методы) для одного или нескольких из множества возможных методов делегата. Итак, что-то происходит, и NSWindow хочет вызвать ваш объект - он просто использует метод responsedsToSelector Objective-c, чтобы определить, хочет ли ваш объект вызвать этот метод, а затем вызывает его. Вот как работает target-c - методы ищутся по требованию.

Совершенно тривиально сделать это с вашими собственными объектами, ничего особенного не происходит, например, вы можете иметь NSArray из 27 объектов, объектов различного типа, только 18 из которых у них есть метод - (void) setToBue; Остальные 9 - нет. Итак, чтобы вызвать setToBlue для всех 18, которые нуждаются в этом, что-то вроде этого:

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

Еще одна вещь, связанная с делегатами, заключается в том, что они не сохраняются, поэтому вы всегда должны устанавливать для делегата значение nil в вашем методе MyClass dealloc .

Пожалуйста!ознакомьтесь с приведенным ниже простым пошаговым руководством, чтобы понять, как работают делегаты в iOS.

Делегирование в iOS

Я создал два ViewControllers (для отправки данных от одного к другому)

  1. FirstViewController реализует делегат (который предоставляет данные).
  2. SecondViewController объявляет делегат (который будет получать данные).

В качестве хорошей практики, рекомендованной 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 если представление (соответствующее вашему делегату) действительно реализовало ваш необязательный метод (ы) или нет.

Я думаю, что все эти ответы имеют большой смысл, когда вы понимаете делегатов. Лично я пришел из страны Си / Си ++, и до этого процедурные языки, такие как Фортран и т. Д., Вот мои 2 минуты, чтобы найти похожие аналоги в парадигме Си ++.

Если бы я объяснил делегатов программисту на C ++ / Java, я бы сказал

Что такое делегаты? Это статические указатели на классы внутри другого класса. Как только вы назначите указатель, вы можете вызывать функции / методы в этом классе. Следовательно, некоторые функции вашего класса являются «делегированными». (В мире C ++ - указатель на указатель объекта класса) на другой класс.

Что такое протоколы? Концептуально это служит аналогичным назначением для файла заголовка класса, который вы назначаете в качестве класса делегата. Протокол - это явный способ определения того, какие методы должны быть реализованы в классе, указатель которого был задан как делегат внутри класса.

Как я могу сделать что-то подобное в C ++? Если бы вы попытались сделать это в C ++, вы должны определить указатели на классы (объекты) в определении класса, а затем связать их с другими классами, которые предоставят дополнительные функции в качестве делегатов вашему базовому классу. Но эта проводка должна поддерживаться в коде и будет неуклюжей и подверженной ошибкам. Цель C просто предполагает, что программисты не лучше всего поддерживают эту дешифровку, и предоставляет ограничения компилятора для обеспечения чистой реализации.

Быстрая версия

Делегат - это просто класс, который выполняет некоторую работу для другого класса.Прочтите следующий код для получения несколько глупого (но, надеюсь, поучительного) Примера игровой площадки, который показывает, как это делается в 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. Когда класс хочет разрешить другому классу настраивать его

Классам не нужно ничего знать друг о друге заранее, за исключением того, что класс делегата соответствует требуемому протоколу.

Я настоятельно рекомендую прочитать следующие две статьи.Они помогли мне понять делегатов даже лучше, чем Документация сделал.

Хорошо, это не совсем ответ на вопрос, но если вы ищете, как сделать свой собственный делегат, возможно, что-то гораздо более простое может быть лучшим ответом для вас.

Я с трудом реализую своих делегатов, потому что мне это редко нужно. Я могу иметь ТОЛЬКО ОДИН делегат для объекта делегата. Так что, если вы хотите, чтобы ваш делегат для односторонней связи / передачи данных, вам гораздо лучше с уведомлениями.

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];
}

Допустим, у вас есть класс, который вы разработали, и вы хотите объявить свойство делегата, чтобы иметь возможность уведомлять его, когда происходит какое-то событие:

@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 в вашем ViewController и объявляет себя как UITableViewDelegate всем им.

и внутри вашего MyClass вы уведомляете делегата о объявленных событиях следующим образом:

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

вы сначала проверяете, отвечает ли ваш делегат на метод протокола, который вы собираетесь вызвать, в случае, если делегат не реализует его, а затем приложение завершит работу (даже если метод протокола требуется).

Вот простой способ создания делегатов

Создать протокол в .h файле. Убедитесь, что он определен перед протоколом с использованием @class, за которым следует имя UIViewController < В качестве протокола, который я собираюсь использовать, используется класс UIViewController >.

Шаг: 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]; 
     }
  }

Чтобы создать свой собственный делегат, сначала вам нужно создать протокол и объявить необходимые методы без реализации. А затем внедрите этот протокол в свой класс заголовка, где вы хотите реализовать методы делегата или делегата.

Протокол должен быть объявлен как показано ниже:

@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];
}

Вот и все, и, реализуя методы делегата в этом классе, управление вернется после выполнения операции / задачи.

Отказ от ответственности:это и есть тот самый Swift версия о том, как создать delegate.

Итак, что же такое делегаты?... в разработке программного обеспечения существуют общие архитектуры решений многократного использования, которые помогают решать часто возникающие проблемы в рамках данного контекста, эти, так сказать, “шаблоны” наиболее известны как шаблоны проектирования.Делегаты - это шаблон проектирования, который позволяет одному объекту отправлять сообщения другому объекту при возникновении определенного события.Представьте, что объект A вызывает объект B для выполнения некоторого действия.Как только действие завершено, объект A должен знать, что B выполнил задачу, и предпринять необходимые действия, этого можно добиться с помощью делегатов!

Для лучшего объяснения я собираюсь показать вам, как создать пользовательский делегат, который передает данные между классами, с помощью Swift в простом приложении,начните с загрузки или клонирования этого начального проекта и запустите его!

Вы можете увидеть приложение с двумя классами, ViewController A и ViewController B.B имеет два вида, которые при нажатии меняют цвет фона экрана. ViewController, - ничего слишком сложного, верно?что ж, теперь давайте подумаем о простом способе также изменить цвет фона класса A при просмотре представлений класса B.

Проблема в том, что эти представления являются частью класса B и понятия не имеют о классе A, поэтому нам нужно найти способ взаимодействия между этими двумя классами, и именно в этом заключается преимущество делегирования.Я разделил реализацию на 6 шагов, чтобы вы могли использовать это как шпаргалку, когда вам это понадобится.

шаг 1:Найдите pragma mark step 1 в файле ClassBVC и добавьте это

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

Первым шагом является создание protocol, в этом случае мы создадим протокол в классе B, внутри протокола вы можете создать столько функций, сколько захотите, исходя из требований вашей реализации.В этом случае у нас просто есть одна простая функция, которая принимает необязательный UIColor в качестве аргумента.Хорошей практикой является давать своим протоколам названия, добавляя слово delegate в конце имени класса, в данном случае, ClassBVCDelegate.

шаг 2:Найдите pragma mark шаг 2 в ClassVBC и добавьте это

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

Здесь мы просто создаем свойство делегата для класса, это свойство должно принимать protocol введите, и это должно быть необязательно.Кроме того, вам следует добавить ключевое слово weak перед свойством, чтобы избежать циклов сохранения и потенциальных утечек памяти, если вы не знаете, что это значит, не волнуйтесь сейчас, просто не забудьте добавить это ключевое слово.

шаг 3:Найдите метку pragma step 3 внутри handleTap method в ClassBVC и добавьте это

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

Одна вещь, которую вы должны знать, запустите приложение и коснитесь любого представления, вы не увидите никакого нового поведения, и это правильно, но я хочу отметить, что приложение не завершает работу при вызове делегата, и это потому, что мы создаем его как необязательное значение, и именно поэтому оно не завершит работу, даже если делегированное значение еще не существует.Давайте теперь перейдем к ClassAVC запишите и сделайте это делегированным.

шаг 4:Найдите pragma mark step 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 mark step 5 внутри метода prepare for segue и добавьте это

//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 и назначьте его делегата self, но что здесь такое self?что ж, самость - это ClassAVC который был делегирован!

шаг 6:Наконец, найдите pragma step 6 в ClassAVC и давайте воспользуемся функциями protocol, начните вводить функцию Изменить цвет обратной основы и вы увидите, что он автоматически заполняет его за вас.Вы можете добавить любую реализацию внутри него, в этом примере мы просто изменим цвет фона, добавим это.

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

Теперь запустите приложение!

Delegates они есть везде, и вы, вероятно, используете их даже без уведомления, если создаете tableview в прошлом вы использовали делегирование, многие классы UIKIT работает вокруг них и многих других frameworks кроме того, они решают эти основные проблемы.

  • Избегайте плотного сцепления предметов.
  • Изменяйте поведение и внешний вид без необходимости создания подклассов объектов.
  • Разрешить обработку задач для любого произвольного объекта.

Поздравляю, вы только что внедрили пользовательский делегат, я знаю, что вы, вероятно, думаете, столько проблем только из-за этого?что ж, делегирование - это очень важный шаблон проектирования, который нужно понять, если вы хотите стать iOS разработчик, и всегда имейте в виду, что у них есть взаимно однозначные отношения между объектами.

Вы можете ознакомиться с оригинальным руководством здесь

Ответ на самом деле получен, но я хотел бы дать вам "шпаргалку" для создания делегата:

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;

Способ:

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

На мой взгляд, создайте отдельный класс для этого метода делегата, и вы можете использовать его там, где хотите.

в моем пользовательском 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;

после этого в файле ..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;
}
}

Делегат: - Создать

@protocol addToCartDelegate <NSObject>

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

@end

Отправьте и, пожалуйста, назначьте делегата для просмотра отправляемых вами данных.

[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.Реализуйте метод в классе .m -(void)didRemoveCellWithTag:(NSInteger)тег { NSLog@("Tag %d",тег);

}

Давайте начнем с примера: если мы покупаем продукт через Интернет, он проходит такой процесс, как доставка / доставка, осуществляемая различными командами. Так что, если доставка завершена, команда доставки должна уведомить команду доставки & amp; это должно быть общение один на один, так как передача этой информации будет непосильной, поскольку другие люди / поставщики могут захотеть передать эту информацию только нужным людям.

Итак, если мы думаем с точки зрения нашего приложения, мероприятие может быть онлайн-заказом & amp; разные команды могут быть похожи на несколько просмотров.

Вот код, который рассматривает ShippingView как команду доставки & amp; 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
        //
    }
}
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top