我想做以下事情: 在一个类(共享实例)中,我将有一个方法,它将数据对象(nsstring)和委托作为参数。这将创建一个新的后台线程并在该线程上调度一些计算。问题是该方法可能被调用数百次,具有不同的数据并且可能传入不同的委托。我希望结果转到正确的委托(我需要将代理保留在数组中吗?或者我可以将它们传递给后台线程,因为它们来了,当该线程完成时它会将结果仅发送给代表?)。
还有一件事......所有这些方法都将使用一个非常大的数据结构(一个包含10000个nsstring对象的数组,它们只需要从中读取)。如何确保每个线程不重复?并且仅在需要时分配并在没有线程使用时释放?
以下是我决定使用的代码:
if (!self.dictPasswords) {
// read everything from text
NSString* fileContents = [NSString stringWithContentsOfFile:fileRoot
encoding:NSUTF8StringEncoding error:nil];
// separate by new line
self.dictPasswords = [fileContents componentsSeparatedByCharactersInSet:
[NSCharacterSet newlineCharacterSet]];
}
__weak id<PSPasswordDictionaryVerificationDelegate> wdelegate = delegate;
dispatch_async(dispatch_get_global_queue(0, 0), ^{
[wdelegate willBeginPasswordVerificationForPassword:password];
for (NSString *posiblePass in self.dictPasswords) {
if ([password isEqualToString:posiblePass]) {
dispatch_async(dispatch_get_main_queue(), ^{
[wdelegate password:password isInDictionary:YES];
});
return;
}
}
dispatch_async(dispatch_get_main_queue(), ^{
[wdelegate password:password isInDictionary:NO];
});
});
然而......在此次运行之后,我将永久性的24MB添加到已用内存中。我想检测何时没有线程使用self.DIctPasswords数组并释放它。如果有人再次调用此方法,它将在稍后再次从文件中读取... 谢谢你的帮助。
答案 0 :(得分:2)
让块捕获委托。 不需要等待
#import <Foundation/Foundation.h>
@protocol ProcessorDelegate;
@interface Processor
- (void)process:(id)data forDelegate:(id<ProcessorDelegate>)delegate;
+ (Processor*)sharedInstance;
@end
@protocol ProcessorDelegate
- (void)processor:(Processor*)processor didProcess:(id)data withResult:(id)result;
@end
@implementation Processor
- (void)process:(id)data forDelegate:(id<ProcessorDelegate>)delegate {
__weak id<ProcessorDelegate> wdelegate = delegate; //capture weak to counter potential cycles
__weak id wself = self;
dispatch_async(dispatch_get_global_queue(0,0), ^{
NSLog(@"WORK");
id result = data; //TODO
[wdelegate processor:wself didProcess:data withResult:result];
});
}
+ (Processor*)sharedInstance {
static Processor *p = nil;
if(!p) {
p = [[Processor alloc] init];
}
return p;
}
@end
@interface Demo : NSObject <ProcessorDelegate>
- (void)doIt;
@end
@implementation Demo
- (void)doIt {
[Processor sharedInstance] process:@"TEST" forDelegate:self];
}
@end
int main(int argc, char *argv[]) {
@autoreleasepool {
Demo *d1 = [[Demo alloc] init];
Demo *d2 = [[Demo alloc] init];
Demo *d3 = [[Demo alloc] init];
Demo *d4 = [[Demo alloc] init];
[d1 doIt];
[d2 doIt];
[d3 doIt];
[d4 doIt];
[[NSRunLoop currentRunLoop] run];
}
}
答案 1 :(得分:1)
将计算加上数据和委托封装在自己的类中似乎更合适。然后你可以在你的单身人士中拥有这些对象的数组。您可以考虑在此处使用NSOperation。
OMT:如果您正在使用任何属性,只需将此大型数组作为指针传递给每个计算对象并使用常规strong
属性(而非copy
),从而保存对使用ivar也很好。一个问题是这个数据结构必须是只读的;否则(当你在每个线程中修改它时),你需要一些数据锁定。
答案 2 :(得分:0)
我用块完成了它:一个拥有你需要的所有函数的单例(如API)和一个委托类
// singleton.h
typedef void (^request_handler_t)(NSData* data);
- (void) foo:(NSString *)str withBlock:(request_handler_t)callback;
// singleton.m
- (void) foo:(NSString *)str withBlock:(request_handler_t)callback;{
MyDelegate *delegate = [MyDelegate delegateWithBlock:callback];
[yourMethodThatNeedDelegate:delegate];
}
// MyDelegate.h
+ (MyDelegate*) delegateWithBlock:(api_request_handler_t)block;
- (void)delegateMethod1;
//Delegate.m
+ (MyDelegate*) requestWithBlock:(api_request_handler_t)block;{
//... alloc init
_callback = block;
}
- (void)delegateMethod1;{
// delegate finished the job
block(myResultingData);
}
// Usage :
[MySingleton singleton] foo:(NSString *)str withBlock:^(NSData *data){
//do something with the async data
}];