この問題を検索しましたが、適切な解決策が得られませんでした。私のアプリケーションでは、サーバーに複数の再帰的な非同期呼び出しを行っています。ネットワーク操作を行うために MKNetworkKit を使用しています。私の実装の疑似コード:
- updateForms{
[networkcall completionblock:^(MKNetworkOperation *op){
dictionaryObject = op.responseJSON
if(moreForms)
[self updateForms] // recursive call
else
save data in db and proceed further
}
}
ただし、上記のコードを実行すると、完了ブロックでの呼び出しごとにメモリ使用量が 4 ~ 10 MB 増加します (行の DictionaryObject = op.responseJSON で考えます)。
インストゥルメントを使用した後、MKNetworkKit 関数の NSJSONSerialization JSONObjectWithData 行でメモリ リークが発生しています。
以下は、私が書いた実際のコードです。
- (void)updateForms:(int)requestCount
{
/* ====================================
* update forms from webserver
* ====================================
*
*/
__block int blockRequestCount = requestCount;
if (UIApplication.sharedApplication.applicationState != UIApplicationStateActive)
{
NSLog(@"Background time remaining = %.1f seconds", [UIApplication sharedApplication].backgroundTimeRemaining);
}
// get username and password
NSString *username = [[NSUserDefaults standardUserDefaults] valueForKey:@"username"];
NSString *userPassword = [[NSUserDefaults standardUserDefaults] valueForKey:@"password"];
NSString *signature = [NSString stringWithFormat:@"url=%@&action=forms×tamp=%@", apiBaseURL, [[Utility shareInstance] getCurrentTimeStamp]];
//signature = [[Utility shareInstance] encodeWithURL:signature];
NSString *signatures = [[NSString alloc] initWithString:[[Utility shareInstance] hmacSHA256ForKeyAndData:request_PrivateKey withData:signature]];
NSString *timestamp = [[NSString alloc] initWithString:[[Utility shareInstance] getCurrentTimeStamp]];
NSMutableDictionary *dic = [[NSMutableDictionary alloc]init];
[dic setValue:apiBaseURL forKey:@"url"];
[dic setValue:timestamp forKey:@"timestamp"];
[dic setValue:signatures forKey:@"signature"];
[dic setValue:[NSString stringWithFormat:@"%d",requestCount] forKey:@"request_no"];
NSString *urlGetForms = [NSString stringWithFormat:@"%@forms", apiBaseURL];
//[MMProgressHUD setPresentationStyle:MMProgressHUDPresentationStyleFade];
//[MMProgressHUD showWithTitle:@"iPEGS" status:@"Loading..."];
if (UIApplication.sharedApplication.applicationState != UIApplicationStateActive)
{
NSLog(@"Background time remaining = %.1f seconds", [UIApplication sharedApplication].backgroundTimeRemaining);
}
//dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{
__weak typeof(self) weakSelf = self;
//asynchronous code
[[AppRequest shareInstance] loadRequestWithURL:urlGetForms withLoadingIndicator:NO username:username password:userPassword params:dic success: ^(MKNetworkOperation *op) {
//dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{
typeof(weakSelf) strongSelf = weakSelf;
if (op != nil){
if (UIApplication.sharedApplication.applicationState != UIApplicationStateActive){
NSLog(@"Background time remaining = %.1f seconds", [UIApplication sharedApplication].backgroundTimeRemaining);
}
// code modified
NSMutableDictionary *responseDataTemp;
@autoreleasepool {
NSDictionary *dic = op.responseJSON;
responseDataTemp = [[NSMutableDictionary alloc] initWithDictionary:dic];
}
//NSLog(@"responseData:%@\n\n\n",op.responseString);
[responseDataTemp removeObjectForKey:@"message"];
[responseData addEntriesFromDictionary:responseDataTemp];
if ([[responseDataTemp objectForKey:@"form_remaining"] intValue]) {
[responseData removeObjectForKey:@"form_remaining"];
NSLog(@"Custom Forms count %lu",(unsigned long)[responseData count]);
[strongSelf updateForms:++blockRequestCount];
}else{
[responseData removeObjectForKey:@"form_remaining"];
NSLog(@"Custom Forms count %lu",(unsigned long)[responseData count]);
// Parse response data and save in database
[strongSelf parseAndSaveData:strongSelf];
if (strongSelf.backgroundTask != UIBackgroundTaskInvalid){
[[UIApplication sharedApplication] endBackgroundTask:strongSelf.backgroundTask];
strongSelf.backgroundTask = UIBackgroundTaskInvalid;
}
dispatch_async(dispatch_get_main_queue(), ^{
//synchronous code
[MMProgressHUD dismiss];
[responseData removeAllObjects];
[customFormIds removeAllObjects];
[questionnaireIds removeAllObjects];
});
if (UIApplication.sharedApplication.applicationState != UIApplicationStateActive)
{
NSLog(@"Background time remaining = %.1f seconds", [UIApplication sharedApplication].backgroundTimeRemaining);
}
}
}
} failure: ^(MKNetworkOperation *op, NSError *er) {
if (er) {
if (self.backgroundTask != UIBackgroundTaskInvalid){
[[UIApplication sharedApplication] endBackgroundTask:self.backgroundTask];
self.backgroundTask = UIBackgroundTaskInvalid;
}
dispatch_async(dispatch_get_main_queue(), ^{
//synchronous code
[MMProgressHUD dismiss];
[responseData removeAllObjects];
[customFormIds removeAllObjects];
[questionnaireIds removeAllObjects];
});
}
//NSLog(@"error:%@", er.description);
if (self.backgroundTask != UIBackgroundTaskInvalid){
[[UIApplication sharedApplication] endBackgroundTask:self.backgroundTask];
self.backgroundTask = UIBackgroundTaskInvalid;
}
if (UIApplication.sharedApplication.applicationState != UIApplicationStateActive){
NSLog(@"Background time remaining = %.1f seconds", [UIApplication sharedApplication].backgroundTimeRemaining);
}
}];
}
自己の弱い参照を追加し、 autorelease ブロックも使用していますが、問題は解決していません。
そのメモリリークを取り除くにはどうすればよいですか、または再帰的な非同期呼び出しを行っているときに何か間違ったことをしていますか?
ありがとう!