Я знаю, как работают делегаты, и я знаю, как я могу их использовать.
Но как создать их?
Я знаю, как работают делегаты, и я знаю, как я могу их использовать.
Но как создать их?
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;
На UIWebViewстороне, он , вероятно , имеет код , подобный этому , чтобы увидеть , если делегат отвечает на webViewDidStartLoad:сообщения , используя respondsToSelector:и отправить его в случае необходимости.
if([self.delegate respondsToSelector:@selector(webViewDidStartLoad:)]) {
[self.delegate webViewDidStartLoad:self];
}
Само свойство , как правило , делегат объявлена weak(в АРК) или assign(предварительно АРК) , чтобы избежать удержаний петли, так как делегат объекта часто содержит сильную ссылку на этот объект. (Например, контроллер представления часто делегат вида он содержит.)
Для того, чтобы определить свои собственные делегаты, вы должны декларировать свои методы где - то, как обсуждалось в Apple , Документах по протоколам . Обычно объявить официальный протокол. Декларация, перефразировать от UIWebView.h, будет выглядеть следующим образом :
@protocol UIWebViewDelegate <NSObject>
@optional
- (void)webViewDidStartLoad:(UIWebView *)webView;
// ... other methods here
@end
Это аналогично интерфейс или абстрактный базовый класс, так как он создает особый тип для вашего делегата, UIWebViewDelegateв этом случае. Делегирование реализаторы должны принять этот протокол:
@interface MyClass <UIWebViewDelegate>
// ...
@end
А затем реализовать методы в протоколе. Для методов , объявленных в протоколе в качестве @optional(как и большинство методов делегата), вы должны проверить с -respondsToSelector:перед вызовом определенного метода на нем.
Методы делегата , как правило , с именем , начиная с именем класса делегирования и принять объект делегирующего в качестве первого параметра. Они также часто используют will-, SHOULD- или did- форму. Таким образом, webViewDidStartLoad:(первый параметр является веб - вид) , а не loadStarted(не принимая никаких параметров), например.
Вместо того, чтобы проверить, отвечает ли делегат селектор каждый раз, когда мы хотим, чтобы сообщения, вы можете кэшировать эту информацию, когда делегаты установлены. Один очень чистый способ сделать это состоит в использовании битового, следующим образом:
@protocol SomethingDelegate <NSObject>
@optional
- (void)something:(id)something didFinishLoadingItem:(id)item;
- (void)something:(id)something didFailWithError:(NSError *)error;
@end
@interface Something : NSObject
@property (nonatomic, weak) id <SomethingDelegate> delegate;
@end
@implementation Something {
struct {
unsigned int didFinishLoadingItem:1;
unsigned int didFailWithError:1;
} delegateRespondsTo;
}
@synthesize delegate;
- (void)setDelegate:(id <SomethingDelegate>)aDelegate {
if (delegate != aDelegate) {
delegate = aDelegate;
delegateRespondsTo.didFinishLoadingItem = [delegate respondsToSelector:@selector(something:didFinishLoadingItem:)];
delegateRespondsTo.didFailWithError = [delegate respondsToSelector:@selector(something:didFailWithError:)];
}
}
@end
Затем, в теле, мы можем проверить , что наш делегат обрабатывает сообщения от доступа к нашей - delegateRespondsToструктуре, а не посылать -respondsToSelector:снова и снова.
До появления протоколов, было принято использовать категорию на NSObjectдекларировать методы делегат мог бы осуществить. Например, до CALayerсих пор делает это:
@interface NSObject(CALayerDelegate)
- (void)displayLayer:(CALayer *)layer;
// ... other methods here
@end
В сущности , это говорит компилятор , что любой объект может реализовать displayLayer:.
Затем вы должны использовать тот же -respondsToSelector:подход , как описано выше , чтобы вызвать этот метод. Делегаты просто реализовать этот метод и присвоить delegateсвойство, и это все (нет объявляя это будет соответствовать протоколу). Этот метод является общим в библиотеках Apple, но новый код должен использовать более современный подход протокола выше, так как этот подход загрязняет NSObject(что делает автозаполнение менее полезным) и делает это трудно для компилятора , чтобы предупредить вас об опечатках и подобных ошибках.
Одобренный ответ велик, но если вы ищете 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хочет назвать свой объект - это просто использует Objective-C в respondsToSelectorметод , чтобы определить , если ваш объект хочет этот метод под названием, а затем вызывает его. Вот как работает Objective-C - методы ищутся по требованию.
Это совершенно тривиально , чтобы сделать это с вашими собственными объектами, нет ничего особенного не происходит, вы могли бы, например , иметь NSArray27 объектов, все различные виды объектов, только 18 некоторые из них имеют метод -(void)setToBue;Другой 9 нет. Таким образом , чтобы позвонить setToBlueна все 18 , что это нужно сделать, что - то вроде этого:
for (id anObject in myArray)
{
if ([anObject respondsToSelector:@selector(@"setToBlue")])
[anObject setToBlue];
}
Другая вещь , о делегатах в том , что они не сохраняются, так что вы всегда должны установить делегат nilв вашем MyClass deallocметоде.
Пожалуйста! проверьте ниже простой шаг за шагом учебник, чтобы понять, как делегаты работает в IOS.
Я создал два ViewControllers (для отправки данных от одного к другому)
Как хорошая практика , рекомендованный 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если вид (то есть в соответствии с вашим делегатом) фактически реализован ваш факультативный метод (ы) или нет.
Я думаю, что все эти ответы делают много смысла, как только вы понимаете делегат. Лично я пришел из земли C / C ++ и до этого процедурных языков, как Fortran и т.д., так вот моя 2 мин взять на поиск подобных аналогов в парадигме C ++.
Если бы я объяснить делегатов на C ++ / Java программист я бы сказал,
Какие делегаты? Это статические указатели на классы внутри другого класса. После назначения указателя, вы можете вызвать функции / методы в этом классе. Поэтому некоторые функции вашего класса «делегировал» (В мире C ++ - указатель на указатель на объект класса) к другому классу.
Какие протоколы? Концептуально она служит той же цели, как в заголовочный файл класса вы присваивающей как класс делегата. Протокол является явным способом определения того, что должно быть реализовано в классе кто есть указатель был установлен в качестве делегата в классе метода.
Как я могу сделать что-то подобное в C ++? Если вы пытались сделать это в C ++, вы бы определяя указатели на классы (объекты) в определении класса, а затем проводку их к другим классам, которые будут предоставлять дополнительные функции в качестве делегатов базового класса. Но эта проводка должна быть maitained в коде и будет неуклюжим и подвержен ошибкам. Objective C просто предполагает, что программисты не лучше в поддержании этого decipline и предусматривают ограничения компилятора для обеспечения чистой реализации.
Делегат это просто класс, который делает некоторую работу для другого класса. Прочитайте следующий код несколько глупого (но, надеюсь, поучительный) пример Playground, который показывает, как это делается в 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!"
}
В реальной практике делегаты часто используются в следующих ситуациях
Эти классы не должны ничего знать друг о друге заранее исключением того, что класс делегата соответствует требуемому протоколу.
Я настоятельно рекомендую прочитать следующие две статьи. Они помогли мне понять делегат даже лучше , чем документация сделала.
позволяет сказать, что у вас есть класс, который был разработан и хотите объявить свойство делегата, чтобы иметь возможность уведомить его, когда происходит какое-либо событие:
@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>) , что означает любой объективный класс С , который соответствует протокол MyClassDelegate, вы заметите , что свойство делегата объявлен как слабый, это очень важно для предотвращения сохранения цикла (чаще всего делегат сохраняет MyClassэкземпляр , если вы объявили делегат , как сохранить, оба они будут сохранять друг друга и ни из них никогда не будет выпущен).
Вы заметите также , что методы протокола передает MyClassэкземпляр делегата в качестве параметра, это лучшая практика в случае , если делегат хочет вызвать некоторые методы , MyClassнапример , а также помогает , когда делегат объявляет себя MyClassDelegateв нескольких MyClassслучаев, например , когда у вас есть несколько UITableView'sслучаи в вашей ViewControllerи заявляет о себе , как UITableViewDelegateко всем из них.
и внутри ваши MyClassвы сообщаете делегат с объявленными событиями следующим образом :
if([_delegate respondsToSelector:@selector(myClass: requiredEventHandlerWithParameter:)])
{
[_delegate myClass:self requiredEventHandlerWithParameter:(ParamType*)param];
}
вы сначала проверить, если ваш делегат отвечает на метод протокола, который вы собираетесь звонить в случае, если делегат не реализует его, и приложение будет врезаться тогда (даже если требуется метод протокола).
Хорошо, это не совсем ответ на этот вопрос, но если вы отрываясь, как сделать свой собственный делегат, возможно, что-то гораздо проще, может быть лучшим решением для вас.
Я вряд ли реализовать мои делегат, потому что я редко нужен. Я могу иметь только один делегат для объекта делегата. Так что если вы хотите, чтобы ваш делегат одной двусторонней связи / передачи данных, чем вы гораздо лучше вместе с уведомлениями.
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];
}
Вот простой способ создания делегатов
Создание протокола в файле .h. Убедитесь в том, что определяется до протокола с использованием @class с последующим именем UIViewController< As the protocol I am going to use is UIViewController class>.
Шаг: 1: Создать новый протокол класса под названием «YourViewController» , который будет подклассом класса UIViewController и назначить этот класс второго ViewController.
Шаг: 2: Перейти к файлу «YourViewController» и изменить его , как показано ниже:
#import <UIKit/UIkit.h>
@class YourViewController;
@protocol YourViewController Delegate <NSObject>
@optional
-(void)defineDelegateMethodName: (YourViewController *) controller;
@required
-(BOOL)delegateMethodReturningBool: (YourViewController *) controller;
@end
@interface YourViewController : UIViewController
//Since the property for the protocol could be of any class, then it will be marked as a type of id.
@property (nonatomic, weak) id< YourViewController Delegate> delegate;
@end
Методы, определенные в поведении протокола можно контролировать с помощью @optional и @required как часть определения протокола.
Шаг: 3: Реализация делегата
#import "delegate.h"
@interface YourDelegateUser ()
<YourViewControllerDelegate>
@end
@implementation YourDelegateUser
- (void) variousFoo {
YourViewController *controller = [[YourViewController alloc] init];
controller.delegate = self;
}
-(void)defineDelegateMethodName: (YourViewController *) controller {
// handle the delegate being called here
}
-(BOOL)delegateMethodReturningBool: (YourViewController *) controller {
// handle the delegate being called here
return YES;
}
@end
// проверить, является ли метод был определен, прежде чем назвать его
- (void) someMethodToCallDelegate {
if ([[self delegate] respondsToSelector:@selector(defineDelegateMethodName:)]) {
[self.delegate delegateMethodName:self];
}
}
Для того, чтобы создать свой собственный делегат, сначала нужно создать протокол и объявить необходимые методы, без реализации. А затем реализовать этот протокол в свой класс заголовка, где вы хотите, чтобы выполнить делегат или делегировать методы.
Протокол должен быть объявлен, как показано ниже:
@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.
Итак, что делегаты? ... в разработке программного обеспечения, существуют общие многоразовые архитектуры решения, которые помогают решать часто возникающие проблемы в данном контексте, эти «шаблоны», так сказать, лучше всего известны как шаблоны проектирования. Делегаты шаблон проектирования, что позволяет один объект для отправки сообщений на другой объект, когда происходит определенное событие. Представьте себе, объект А вызывает объект B, чтобы выполнить действие. После завершения действия, объект А должен знать, что B выполнила задачу и принять необходимые меры, это может быть достигнуто с помощью делегатов!
Для лучшего объяснения, я собираюсь показать вам , как создать пользовательский делегат , который передает данные между классами, с Swift в простом приложении, начать загрузку или клонировать этот проект стартера и запустить его!
Вы можете увидеть приложение с двумя классами, ViewController Aи ViewController B. B имеет две точки зрения , что на кране изменяет цвет фона ViewController, ничего слишком сложного права? а теперь давайте думать легкий способ также изменить цвет фона класса А , когда отношение к классу B прослушиваются.
Проблема заключается в том, что эти взгляды являются частью класса B и не имеют ни малейшего представления о классе А, так что нам нужно найти способ общения между этими двумя классами, и именно там делегация блестит. Я разделил реализацию на 6 шагов, так что вы можете использовать это в качестве шпаргалки, когда вам это нужно.
шаг 1: Посмотрите на шаг Прагма марки 1 в ClassBVC файл и добавить
//MARK: step 1 Add Protocol here.
protocol ClassBVCDelegate: class {
func changeBackgroundColor(_ color: UIColor?)
}
Первый шаг заключается в создании protocol, в этом случае мы будем создавать протокол в классе B, внутри протокола вы можете создать множество функций , которые вы хотите , основанные на требованиях вашей реализации. В этом случае мы просто имеем одну простую функцию , которая принимает необязательный в UIColorкачестве аргумента. Это хорошая практика , чтобы назвать свои протоколы , добавив слово delegateв конце имени класса, в данном случае ClassBVCDelegate.
шаг 2: Посмотрите на шаг Прагма марки 2 в ClassVBCи добавить
//MARK: step 2 Create a delegate property here.
weak var delegate: ClassBVCDelegate?
Здесь мы просто создать свойство делегата для класса, это свойство должно принять protocolвид, и это должно быть факультативным. Кроме того , следует добавить слабое ключевое слово перед тем свойством , чтобы избежать сохранения циклов и потенциальные утечки памяти, если вы не знаете , что это значит , не волнуйтесь , сейчас, только не забудьте добавить это ключевое слово.
шаг 3: Посмотрите на шаг Прагма марки 3 внутри handleTap methodв ClassBVCи добавить
//MARK: step 3 Add the delegate method call here.
delegate?.changeBackgroundColor(tapGesture.view?.backgroundColor)
Одна вещь , которую вы должны знать, запустить приложение и нажмите на любой точки зрения, вы не увидите каких - либо новое поведение , и это правильно , но то , что я хочу отметить, что приложение это не сбой , когда делегат называется, и это потому , что мы создаем его в качестве дополнительного значения , и поэтому он не будет врезаться даже делегированы еще не существует. Давайте теперь перейдем к ClassAVCфайлу и сделать его, делегированные.
шаг 4: Посмотрите на шаг Прагма марки 4 внутри метода handleTap в ClassAVCи добавить рядом с типом класса , как это.
//MARK: step 4 conform the protocol here.
class ClassAVC: UIViewController, ClassBVCDelegate {
}
Теперь ClassAVC приняла ClassBVCDelegateпротокол, вы можете увидеть , что ваш компилятор дает вам ошибку , которая говорит «Тип«ClassAVC не соответствует протоколу „ClassBVCDelegate“ , и это только означает , что вы не использовали методы протокола еще, представьте , что когда класс а принимает протокол, как подписать контракт с классом B , и этот контракт говорит : «Любой класс принимая меня должен использовать свои функции!»
Краткое примечание: Если вы приехали из Objective-Cфона вы , вероятно , думаете , что вы также можете заткнуться эту ошибку делает этот метод не обязательно, но для моего удивления, и , вероятно , ваш, Swiftязык не поддерживает необязательный protocols, если вы хотите сделать это вы можете создать расширение для вашего protocolили использовать @objc ключевое слово в вашей protocolреализации.
Лично Если я должен создать протокол с различными дополнительными методами я предпочел бы , чтобы разбить его на разные protocols, таким образом я буду следовать концепции предоставления одной единой ответственности моих объектов, но она может варьироваться в зависимости от конкретной реализации.
вот хорошая статья о дополнительных методах.
шаг 5: Посмотрите на шаг Прагма марки 5 внутри подготовки к методу 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и назначить его делегатом на себя, но что само здесь? ну, сам является , ClassAVCкоторый был делегирован!
шаг 6: Наконец, обратите внимание на шаг прагма 6 в ClassAVCи будем использовать функции из protocol, начните вводить Func changeBackgroundColor , и вы увидите , что это авто-завершения его для вас. Вы можете добавить любую реализацию внутри него, в этом примере, мы просто изменить цвет фона, добавьте это.
//MARK: step 6 finally use the method of the contract
func changeBackgroundColor(_ color: UIColor?) {
view.backgroundColor = color
}
Теперь запустите приложение!
Delegatesвезде , и вы , вероятно , использовать их даже не заметит, если вы создаете tableviewв прошлом вы использовали делегации, многие классы UIKITработ вокруг них и многих других frameworksтоже, они решают эти основные проблемы.
Поздравляем, вы только реализовать пользовательский делегат, я знаю , что вы, вероятно , думаете, так много хлопот , только для этого? хорошо, делегация очень важный шаблон дизайна , чтобы понять , если вы хотите стать iOSразработчиком, и всегда иметь в виду , что у них есть один на один отношения между объектами.
Вы можете увидеть оригинальный учебник здесь
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{
}
Ответ на самом деле ответил, но я хотел бы дать вам «шпаргалку» для создания делегата:
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
Давайте начнем с примером, если мы покупаем продукт онлайн, он проходит через процесс, как перевозку груза / поставки обрабатываются различным teams.So, если доставка будет завершена, доставка команда должна уведомить команду доставки и это должно быть один к одному коммуникации как вещание этой информации будет накладными расходами для других людей / продавца может понадобиться передать эту информацию только для необходимых людей.
Так что, если мы думаем, что с точки зрения нашего приложения, событие может быть онлайн заказ и различные команды могут быть как несколько представлений.
Вот код считают ShippingView в команде Shipping & 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
//
}
}
С моей точки зрения создать отдельный класс для этого метод делегата, и вы можете использовать, где вы хотите.
в моей пользовательской DropDownClass.h
typedef enum
{
DDSTATE,
DDCITY
}DropDownType;
@protocol DropDownListDelegate <NSObject>
@required
- (void)dropDownDidSelectItemWithString:(NSString*)itemString DropDownType:(DropDownType)dropDownType;
@end
@interface DropDownViewController : UIViewController
{
BOOL isFiltered;
}
@property (nonatomic, assign) DropDownType dropDownType;
@property (weak) id <DropDownListDelegate> delegate;
@property (strong, nonatomic) NSMutableArray *array1DropDown;
@property (strong, nonatomic) NSMutableArray *array2DropDown;
после этого in.m файла создать массив с объектами,
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath{
CGFloat rowHeight = 44.0f;
return rowHeight;
}
-(NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
return isFiltered?[self.array1DropDown count]:[self.array2DropDown count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *simpleTableIdentifier = @"TableCell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:simpleTableIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:simpleTableIdentifier];
}
if (self.delegate) {
if (self.dropDownType == DDCITY) {
cell.textLabel.text = [self.array1DropDown objectAtIndex:indexPath.row];
}
else if (self.dropDownType == DDSTATE) {
cell.textLabel.text = [self.array2DropDown objectAtIndex:indexPath.row];
}
}
return cell;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
[self dismissViewControllerAnimated:YES completion:^{
if(self.delegate){
if(self.dropDownType == DDCITY){
[self.delegate dropDownDidSelectItemWithString:[self.array1DropDown objectAtIndex:indexPath.row] DropDownType:self.dropDownType];
}
else if (self.dropDownType == DDSTATE) {
[self.delegate dropDownDidSelectItemWithString:[self.array2DropDown objectAtIndex:indexPath.row] DropDownType:self.dropDownType];
}
}
}];
}
Здесь все установлены для пользовательского делегата class.after, что вы можете использовать этот метод делегата, где вы want.for пример ...
в моем другом импорте 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;
}
}
//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 - (недействительными) didRemoveCellWithTag: (NSInteger) тег {NSLog @ ( "Метка% d", тег);
}
Делегирование: - Создать
@protocol addToCartDelegate <NSObject>
-(void)addToCartAction:(ItemsModel *)itemsModel isAdded:(BOOL)added;
@end
Отправка и назначьте делегат для просмотра вы отправляете данные
[self.delegate addToCartAction:itemsModel isAdded:YES];