У меня есть класс, который извлекает JSON из URL-адреса и возвращает данные через шаблон протокола/делегата.
MRDelegateClass.h
#import <Foundation/Foundation.h>
@protocol MRDelegateClassProtocol
@optional
- (void)dataRetrieved:(NSDictionary *)json;
- (void)dataFailed:(NSError *)error;
@end
@interface MRDelegateClass : NSObject
@property (strong) id <MRDelegateClassProtocol> delegate;
- (void)getJSONData;
@end
Обратите внимание, что я использую strong
для моего свойства делегата. Подробнее об этом позже...
Я пытаюсь написать класс 'wrapper', который реализует getJSONData в блочном формате.
MRBlockWrapperClassForDelegate.h
#import <Foundation/Foundation.h>
typedef void(^SuccessBlock)(NSDictionary *json);
typedef void(^ErrorBlock)(NSError *error);
@interface MRBlockWrapperClassForDelegate : NSObject
+ (void)getJSONWithSuccess:(SuccessBlock)success orError:(ErrorBlock)error;
@end
MRBlockWrapperClassForDelegate.m
#import "MRBlockWrapperClassForDelegate.h"
#import "MRDelegateClass.h"
@interface DelegateBlock:NSObject <MRDelegateClassProtocol>
@property (nonatomic, copy) SuccessBlock successBlock;
@property (nonatomic, copy) ErrorBlock errorBlock;
@end
@implementation DelegateBlock
- (id)initWithSuccessBlock:(SuccessBlock)aSuccessBlock andErrorBlock:(ErrorBlock)aErrorBlock {
self = [super init];
if (self) {
_successBlock = aSuccessBlock;
_errorBlock = aErrorBlock;
}
return self;
}
#pragma mark - <MRDelegateClass> protocols
- (void)dataRetrieved:(NSDictionary *)json {
self.successBlock(json);
}
- (void)dataFailed:(NSError *)error {
self.errorBlock(error);
}
@end
// main class
@interface MRBlockWrapperClassForDelegate()
@end
@implementation MRBlockWrapperClassForDelegate
+ (void)getJSONWithSuccess:(SuccessBlock)success orError:(ErrorBlock)error {
MRDelegateClass *delegateClassInstance = [MRDelegateClass new];
DelegateBlock *delegateBlock = [[DelegateBlock alloc] initWithSuccessBlock:success andErrorBlock:error];
delegateClassInstance.delegate = delegateBlock; // set the delegate as the new delegate block
[delegateClassInstance getJSONData];
}
@end
Я пришел в мир objective-c сравнительно недавно (жил только в ARC раз и все еще соглашался с блоками), и, по общему признанию, мое понимание управления памятью на тонкой стороне вещей.
Этот код работает нормально, но только если у меня есть мой делегат как strong
. Я понимаю, что мой делегат должен быть weak
, чтобы избежать потенциальных циклов удержания. Глядя на инструменты, я нахожу, что ассигнования не продолжают расти с продолжающимися вызовами. Однако я считаю, что "лучшая практика" состоит в том, чтобы иметь делегатов weak
.
Вопросы
Q1) всегда ли "хорошо" иметь делегатов strong
Q2), как я мог реализовать оболочку на основе блока, оставив делегата базового класса в качестве weak
делегировать (т.е. предотвратить освобождение * delegateBlock * до того, как он получит методы протокола)?