Не могу настроить кастомный @protocol, работающий на iOS - PullRequest
5 голосов
/ 21 июля 2011

Примечание: ниже используется iOS с включенным автоматическим подсчетом ссылок (ARC).Я думаю, что ARC может иметь много общего с тем, почему он не работает, поскольку это настроено в соответствии с примерами, которые я нашел через Google.

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

FileListViewController.h

@protocol FileListDelegate <NSObject>
- (void)didSelectFileName:(NSString *)fileName;

@end

@interface FileListViewController : UITableViewController
{
    @private
        NSArray *fileList;
        id <FileListDelegate> delegate;
}
@property (nonatomic, retain) NSArray *fileList;
@property (nonatomic, assign) id <FileListDelegate> delegate;

@end

FileListViewController.m

#import "FileListViewController.h"

@implementation FileListViewController

@synthesize fileList;
@synthesize delegate;

Это дает ошибку в

@synthesize delegate;

строка «FileListViewController.m: ошибка: проблема с автоматическим подсчетом ссылок»: существующий «делегат» ивара для свойства unsafe_unretained «делегат» должен быть __unsafe_unretained »

Если я изменяю FileListViewController.h, добавляя __ слабый и (слабый)) затем он запустится.

@protocol FileListDelegate <NSObject>
- (void)didSelectFileName:(NSString *)fileName;

@end

@interface FileListViewController : UITableViewController
{
    @private
        NSArray *fileList;
        __weak id <FileListDelegate> delegate;
}
@property (nonatomic, retain) NSArray *fileList;
@property (weak) id <FileListDelegate> delegate;

@end

Но когда я пытаюсь установить делегат, приложение вылетает.Представление с именем «ImportViewController» создает представление из «FileListViewController» и устанавливает для себя делегата (ImportViewController), чтобы я мог реализовать свой собственный протокол «didSelectFileName».Я получаю ошибку:

* Завершение приложения из-за необработанного исключения «NSInvalidArgumentException», причина: '- [ImportViewController setDelegate:]: нераспознанный селектор, отправленный экземпляру 0x6c7d430'

Код, который я запускаю, является:

ImportViewController.m

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
    FileListViewController *fileListViewController = [self.storyboard instantiateViewControllerWithIdentifier:@"filelist"];

    [fileListViewController setDelegate:self];
    [self.navigationController pushViewController:fileListViewController animated:YES];

}

Мои вопросы:

  • Почему в make (слабый) и __weak в makeэто работает?Я не понимаю, почему это работает, поскольку я нашел это, гуглял, и не было никакого объяснения.
  • Почему я не могу установить свой делегат с помощью этого '[fileListViewController setDelegate: self];'?Похоже, что компилятор не знает, что «делегат» существует.

Ответы [ 3 ]

13 голосов
/ 22 сентября 2011

Для ARC ivars по умолчанию установлено значение strong.Таким образом, ошибка

Automatic Reference Counting Issue: Existing ivar 'delegate' for unsafe_unretained property 'delegate' must be __unsafe_unretained"

говорит вам, что вы объявили свойство с __unsafe_unretained (назначить) владение, где базовый ivar имеет __strong владение, что является незаконным.Чтобы избежать ошибки, у вас есть 3 варианта:

  1. Пропустить ивар.Нет необходимости объявлять ивар для синтезированного свойства.Ivar будет объявлен неявно с владельцем, соответствующим вашей собственности.
  2. Определите ivar, чтобы соответствовать объявлению (присваивать) свойства: __unsafe_unretained id <FileListDelegate> delegate;
  3. Определите свойство, чтобы соответствовать неявному __strong владению ivar:@property (weak) id <FileListDelegate> delegate;

Лично я опущу декларацию ivar, чтобы у вас была семантика владения в одном месте, в декларации свойства.

4 голосов
/ 21 июля 2011

Кажется, что с:

FileListViewController *fileListViewController =
    [self.storyboard instantiateViewControllerWithIdentifier:@"filelist"];

вы не получили FileListViewController объект. Посмотрите на сообщение, в котором написано:

-[ImportViewController setDelegate:]: unrecognized selector sent to instance 0x6c7d430

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

1 голос
/ 04 августа 2011

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

Также попробуйте определить свойство сохранения, а не просто присваивать, если делегат освобожден в другом местеваше приложение не рухнет.

Чтобы пояснить приведенную выше цитату из ответа пользователя 756245, основываясь на моем прочтении, я не думаю, что iOS 5 изменила лучшую практику, которую вы не должны 'не оставляйте своего делегата, так как это хороший способ просочиться.Я думаю, что __weak и (слабые) токены - это аннотации для компилятора, чтобы иметь возможность правильно работать с генерацией кода для делегата.

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