объективные протоколы с делегатами - PullRequest
0 голосов
/ 06 сентября 2011

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

вот мой код:

Протокол определения класса> * .h

#import <Foundation/Foundation.h>
@protocol protoPerra <NSObject>

-(void) dimeTuNombre:(NSString *) s;
@end

@interface MyClassic : NSObject {
id<protoPerra> _delegate;  
}
@property (assign) id<protoPerra> delegate;
@end

Протокол реализации класса> * .m

# import "MyClassic.h"

@implementation MyClassic
@synthesize delegate = _delegate;
- (id)init
{
self = [super init];
if (self) {
    // Initialization code here.
    [[self delegate] dimeTuNombre:@"pinguete"];
 }

return self;
}
-(void) dealloc {
[_delegate release];
_delegate = nil;
[super dealloc];
}
@end

Протокол принятия класса:

# import "MyClassic.h" @interface MainViewController: UIViewController (protoPerra)

.m

#import "MainViewController.h"
  @implementation MainViewController
  -(void) dimeTuNombre {
   NSLog(@"ss9!! tkt");
   }
   - (void)viewDidLoad {
[super viewDidLoad];

UILabel *lava = [[[UILabel alloc] initWithFrame:CGRectMake(30, 100, 100, 20)] autorelease];
lava.text = @"lava ss9";
[self.view addSubview:lava];

MyClassic *pirr = [[[MyClassic alloc] init ] autorelease];
[pirr setDelegate:self];
 }
 -(void) dimeTuNombre:(NSString *)s {
   NSLog(@"%@",s);
  }
  @end

так чего не хватает в этом простом примере, чтобы он работал с моим делегатом?

спасибо большое!

Обратите внимание, что я использовал () вместо <> [в .h принимающего класса], как будто я использую шевроны, код исчезает

Ответы [ 2 ]

4 голосов
/ 19 марта 2012

Я думаю, что Пол Хегарти из Стэнфордского университета дал очень хорошее резюме о том, как использовать протокол в Уроке 9, приложения для разработки для iOS, осенняя сессия 2011 года (доступно в iTunes, проверьте блог Пола):

  1. Создать @ протокол
  2. Добавить делегата @property в открытый интерфейс делегата @ 1008 *
  3. Использовать свойство делегата внутри реализации делегатора
  4. Установить свойство делегата где-нибудь внутри делегата @ implmentation
  5. Реализация метода (ов) протокола в делегате (включая <> на @interface)

Павел также привел пример использования протокола в приложении калькулятора.

enter image description here

Сначала создается протокол:

@protocol CalculatorProgramsTableViewControllerDelegate

@optional
- (void)calculatorProgramsTableViewController:
    (CalculatorPorgramTableViewController *)sender
                                 choseProgram:(id)program;
@end

Шаг 2). В табличном представлении CalculatorProgramsTableViewController.h делегат определяется как свойство слабо связанного идентификатора:

@interface CalculatorProgramsTableViewController : UITableViewController
...
// Define a property delegate
@property (nonatomic, weak) id<CalculatorProgramsTableViewControlerDelegate>
                            delegate;
...
@end

Используя протокол, табличное представление сможет отправлять сообщение об изменении программы, но представление не знает о графическом представлении. Это делается на следующем шаге.

Шаг 3). В контроллере табличного представления делегат используется для отправки сообщения об измененной программе:

#progma mark - UITableViewDelegate
- (void)tableView:(UITableView *)tableView
    didSeelectRowAtIndexPath:(NSIndexPath *)indexPath
{
  id program = [self.programs objectAtIndex:indexPath.row];
  [self.delegate calculatorProgramsTableViewController:self
                                          choseProgram:porgram];
}

Шаг 4). Где был установлен делегат? Это устанавливается в calculatorGraphViewController (вид справа в режиме разделения). Когда программа готова выдвинуть всплывающее представление (табличное представление), она устанавливает себя в качестве делегата:

@implementation CalculatorGraphViewController
...
- (void)prepareForSegue:(UIStoryboardSegue *)segue
                 sender:(id)sender
{
  if ([segue.identifier isEqualToString:@"Show Favorite Graphics"]) {
    NSArray * programs = [[NSUserDefaults standardUserDefaults]
                         objectForKey:FAVORITES_KEY];
    [segue.destinationViewController setPrograms:programs];
    [segue.destinationViewController setDelegate:self]; // set delegate
  }
}

Графическое представление не знает о табличном представлении, канал связи построен по протоколу, прекрасно выполнен без какой-либо связи! Чтобы любой делегат мог перезвонить по этому протоколу, файл .h контроллера графического представления должен реализовывать протокол:

// .h to implement the protocol
@interface CalculatorGraphViewController :NSObject 
     <CalculatorProgramsTableViewControllerDelegate>
...
@end

И метод протокола определен в файле .m на следующем шаге.

Последний шаг. Метод протокола делегата реализован в контроллере segue. Метод протокола будет вызываться при выборе строки в табличном представлении:

// implement delegate method
- (void)calculatorProgramsTableViewController:(CalculatorProgramsTableViewController *)sender
                                chooseProgram:(id)program
{
  self.calculatorProgram = program;
}

Выше приведен типичный способ использования протокола в приложении iOS.

4 голосов
/ 06 сентября 2011

Вы вызываете метод делегата (dimeTuNombre :) в инициализации MyClassic, но делегат еще не установлен, поэтому вам нужно либо переосмыслить, когда вызывать dimeTuNombre:, либо изменить класс MyClassic, чтобы иметь конструктор, подобный

-(id)initWithDelegate:(id<protoPerra>)delegate

вместо простого init.

Чтобы уточнить, в вашем текущем коде вы устанавливаете делегат в MainViewController.h, когда вы делаете [pirr setDelegate: self]; - который устанавливает значение «делегат» свойства MyClassic для текущего экземпляра MainViewController. Обратите внимание, что когда вы вызываете init в MyClassic, делегат еще не установлен, поэтому [[self Delegate] dimeTuNombre: @ "pinguete"]; вызов ничего не делает (в этот момент делегат равен нулю).

Вы можете изменить конструктор MyClassic следующим образом:

-(id)initWithDelegate:(id<protoPerra>)aDelegate
{
self = [super init];
if (self) {
    _delegate = aDelegate;
    // Initialization code here.
    [[self delegate] dimeTuNombre:@"pinguete"];
 }

return self;

}

Тогда вместо этого:

MyClassic *pirr = [[[MyClassic alloc] init ] autorelease];
[pirr setDelegate:self];

Вы сделаете это:

MyClassic *pirr = [[[MyClassic alloc] initWithDelegate:self ] autorelease];

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

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