操作の最後に関連するメッセージを表示するには、複数のファイルをアップロードし、それらの進行状況を追跡し、完了ブロックと失敗ブロックにサブスクライブする必要があります。
独自の AFHTTPClient ラッパーを作成し、次のメソッドを作成しました。
- (void) uploadFiles:(NSArray*)files
path:(NSString*)path
parameters:(NSDictionary*)parameters
progressBlock:(void (^)(NSUInteger bytesWritten, long long totalBytesWritten, long long totalBytesExpectedToWrite))block
success:(void (^)(AFHTTPRequestOperation *, id))success failure:(void (^)(AFHTTPRequestOperation *, NSError *))failure
{
NSMutableURLRequest *request =
[self multipartFormRequestWithMethod:@"POST"
path:path
parameters:parameters
constructingBodyWithBlock:
^(id <AFMultipartFormData>formData) {
for (CRLMultiPartFile *file in files) {
NSAssert(file.name, @"Name cannot be nil");
NSAssert(file.file, @"Nothing found to upload");
NSAssert(file.filename, @"FileName cannot be nil");
NSAssert(file.mimeType, @"Must set Mime-Type for %@", file.filename);
[formData appendPartWithFileData:file.file name:file.name fileName:file.filename mimeType:file.typeString];
}
}];
AFHTTPRequestOperation *operation = [[AFHTTPRequestOperation alloc] initWithRequest:request];
[operation setUploadProgressBlock:block];
[operation setCompletionBlockWithSuccess:success failure:failure];
[self enqueueHTTPRequestOperation:operation];
}
このメソッドを呼び出すView Controllerは割り当て解除されないため、含まれているすべての画像もメモリに保持され、メモリリークが発生し、最終的にメモリ警告が発生します。
プロファイリングを実行すると、操作全体の最後に、View Controller の値がrefCount
1 であることがわかります。
ファイルをアップロードする呼び出しをコメントアウトすると、すべて正常に動作します。
これがコントローラーのコードです。プログレス ブロックを使用して、UI の要素を更新します。
NSMutableDictionary *params = [[NSMutableDictionary alloc] init];
ContactModel *model = (ContactModel*)[self.contacts lastObject];
[params setObject:model.phone forKey:@"receiver"];
__block typeof(self) sSelf = self;
[[JMClient sharedClient] uploadFiles:files
path:@"picture_share/"
parameters:params
progressBlock:^(NSUInteger bytesWritten, long long totalBytesWritten, long long totalBytesExpectedToWrite) {
CGFloat progPercent = ceilf(((CGFloat)totalBytesWritten / (CGFloat)totalBytesExpectedToWrite) * 100);
CGFloat widthToCut = (progPercent * sSelf.progWidth) / 100;
CGRect frame = sSelf.progresViewBG.frame;
frame.size.width = (sSelf.progWidth - widthToCut);
frame.origin.x = (sSelf.progOrigin + widthToCut);
sSelf.progresViewBG.frame = frame;
sSelf.progLabel.text = [NSString stringWithFormat:@"%i%%", (int)progPercent];
frame = sSelf.progTipView.frame;
frame.origin.x = (sSelf.progresViewBG.frame.origin.x - frame.size.width/2);
sSelf.progTipView.frame = frame;
frame = sSelf.progLabel.frame;
frame.origin.x = (sSelf.progresViewBG.frame.origin.x - frame.size.width/2);
sSelf.progLabel.frame = frame;
} success:^(AFHTTPRequestOperation *success, id reponse) {
CGRect frame = sSelf.progresViewBG.frame;
frame.size.width = 0;
frame.origin.x = sSelf.progOrigin;
sSelf.progresViewBG.frame = frame;
[sSelf.cancelButton setImage:[UIImage imageNamed:@"trnsfr_prgss_complt.png"] forState:UIControlStateNormal];
[sSelf performSelector:@selector(hideAwayProgressBars) withObject:nil afterDelay:3];
} failure:^(AFHTTPRequestOperation *failure, NSError *error) {
[Mediator showMessage:TGLocalizedString(kMessageKeyForUploadingFailed)];
[sSelf performSelector:@selector(hideAwayProgressBars) withObject:nil afterDelay:3];
}];
self.operation = [[self.client.sharedClient.operationQueue operations] lastObject];
- (void) hideAwayProgressBars
{
[[NSNotificationCenter defaultCenter] postNotificationName:kNotifcationKeyForPhotoUploadComplete object:nil];
}
通知は親コントローラーによって受信され、このコントローラーのビューがスーパービューから削除され、nil に設定されます。
PS CRLMultiPartFile は、アップロードするファイルの属性を保持するカスタム クラスです。