Я создаю класс, который обрабатывает запросы NSURLConnection. Чтобы разрешить другим классам использовать этот класс, я хотел бы разрешить основному классу вызывать делегата при срабатывании connectionDidFinishLoading.
Я просмотрел много документации, но не могу найти ничего, что давало бы ясные примеры, а код, который у меня есть, по какой-то причине не вызывает делегата. Код, который у меня есть до сих пор (код, не имеющий отношения к делу, удален):
Интерфейс:
@interface PDUrlHandler : NSObject {
id delegate;
}
- (void)searchForItemNamed:(NSString *)searchQuery;
@property (nonatomic, assign) id delegate;
@end
@interface NSObject (PDUrlHandlerDelegate)
- (void)urlHandler:(PDUrlhandler*)urlHandler searchResultsFinishedLoading:(NSDictionary *)resultData;
@end
Выполнение:
- (void)connectionDidFinishLoading:(NSURLConnection *)connection {
NSLog(@"Fininshed Loading...");
resultData = [self parseJSON:jsonData];
if (delegate && [delegate respondsToSelector:@selector(urlHandler:searchResultsFinishedLoading:)]) {
NSLog(@"Delegating!");
[delegate urlHandler:self searchResultsFinishedLoading:resultData];
} else {
NSLog(@"Not Delegating. I dont know why.");
}
}
Делегат в другом классе:
- (void)urlHandler:(PDUrlhandler*)urlHandler searchResultsFinishedLoading:(NSDictionary *)resultData;
{
NSLog(@"Delegating!!!!");
}





Вы на правильном пути, то, как вы реализуете шаблон делегата, выглядит нормально. Причина, по которой он не вызывается, заключается в том, что вы используете неправильную сигнатуру метода в responsedsToSelector; у вас есть humidorServer:searchResultsFinishedLoading:, когда вам действительно нужен urlHandler:searchResultsFinishedLoading:.
Может быть, это точка с запятой в конце имени метода в делегате (нижний образец кода справа)? Если делегат установлен и вызывается метод -connectionDidFinishLoading :, я не вижу ничего плохого
Оказывается, я забыл установить делегата:
[currentHandler setDelegate:self];
необходимо идти после строки, которая выполняет первоначальный вызов PDUrlHandler.
Моя первая мысль заключалась в том, что вы, возможно, не установили делегата, но вы это сделали. В остальном код выглядит правильно. Не вижу ничего плохого. Вы пытались установить точку останова в том месте, где вы проверяете, реагирует ли ваш делегат на селектор? Возможно, значение делегата не было сохранено и стало равным нулю. Убедитесь, что ваш делегат не равен нулю и имеет правильный объект.
Также вы уверены, что соединение асинхронное? Синхронные соединения не будут вызывать метод connectionDidFinishLoading.
Поскольку вы отметили это как «iphone», я предполагаю, что вы работаете над приложением для iPhone и вам не нужно поддерживать OS X до 10.5. В Objective-C 2.0 Apple предлагает вам использовать формальные протоколы (используя @protocol) с дополнительными методами вместо неформальных протоколов. Вот соответствующий текст:
Being informal, protocols declared in categories don’t receive much language support. There’s no type checking at compile time nor a check at runtime to see whether an object conforms to the protocol. To get these benefits, you must use a formal protocol. An informal protocol may be useful when all the methods are optional, such as for a delegate, but (on Mac OS X v10.5 and later) it is typically better to use a formal protocol with optional methods.
(источник)
Для всех, кто интересуется примером этого, пример приложения Apple NSURLCache реализует простой делегат вокруг NSURLConnection в NSURLCacheConnection.m
Образец приложения доступен через соединение для разработчиков Apple здесь: http://developer.apple.com/iphone/library/samplecode/URLCache/index.html
Я нашел это очень полезным.
Оставление точки с запятой в имени метода в реализации допустимо в Objective-C. Мне нравится делать это по привычке, потому что вы можете копировать и вставлять между реализацией и интерфейсом, не беспокоясь об этом.