0

私のアプリケーションの機能は、2つのiDevice間で写真を転送することです。

ユーザーは送信する写真をたくさん選択できます。ただし、送信プロセスには時間がかかるため、ユーザーがフォトライブラリから選択したときに、まだ送信されていない写真を配列に配置します。

私の今の問題は、ユーザーが一度にあまりにも多くの写真を選択すると、私のアプリケーションが突然終了することです。私の解決策は、ユーザーが一度に選択する写真が多すぎる場合、いくつかの写真にマークを付けるだけで、それらをフォトライブラリに残し、配列に配置することです。次に、送信アクションが発生すると同時にライブラリから写真をロードするための別のスレッドがあります。だからここでの私のポイントは、一度に非常に多くの写真が配列に入れられたことがアプリケーションが終了する理由であるとは思えないので、いくつかの写真をキャッシュしてから他の写真をディスクに残したい、私のコード:

- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex
{
    if(alertView.tag == 100)
    {
        if (buttonIndex == 1)
        {
            inArray = YES;
            NSLog(@"---------%d",[self.imageArr count]);
            if ([self.imageArr count] < kCachedImages) {
                [self.imageArr addObject:thisImageObj];
                [thisImageObj release];
            }
            else
            [self.imageURLArr addObject:photoURL];

            if(!isSending)
            {
                currentPos = -1;
                [self sendImage];
            }
            [sndTableView reloadData];
        }
        else if (buttonIndex == 2)
        {
            if (inArray) {
                if ([self.imageArr count] < kCachedImages) {
                    [self.imageArr addObject:thisImageObj];
                    [thisImageObj release];
                }else {
                    [self.imageURLArr addObject:photoURL];
                }
            }else {
                [self.imageArr addObject:thisImageObj];
            }

           if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad){
               [self.popOverView dismissPopoverAnimated:YES];
            }
           else {
               [self dismissModalViewControllerAnimated:YES];
           }


            [sndTableView reloadData];
            if(!isSending)
            {
                currentPos = -1;
                [self sendImage];
            }
        }

    }

}


- (void)sendImage
{
    if(![self.imageArr count])
    {
        [[UIApplication sharedApplication] setIdleTimerDisabled:NO];
        isSending = NO;
        [self.navigationItem setHidesBackButton:NO animated:YES];
        return; //end of all sending
    }


    NSMutableData *toBeSend = [NSMutableData dataWithCapacity:sizeof(packetHeader)+kBuffer];
    imageObj *imgObj;
    if ([self.imageArr count]) {
        imgObj = [[self.imageArr objectAtIndex:0]retain];
    }

  //here created another thread to load pics from library  
    if ([self.imageURLArr count] > 0) {
                         [NSThread detachNewThreadSelector:@selector(load) toTarget:self withObject:nil];
    }


    packetHeader header;
    header.magic = 0x5577ACAC;
    header.seq = currentSeq++;

    if(currentPos < 0) //first packet
    {
        UIImage *img = [UIImage imageWithData:imgObj.pimage];
        self.currentSendingImg.image = img;

        //thumbnail
        img = [TransferViewController imageWithImage:img scaledToSize:CGSizeMake(70, 70)];
        NSData *data = UIImageJPEGRepresentation(img, 0.5);

        header.command = 16;
        header.commandData1 = imgObj.imageSize;
        header.commandData2 = (imgObj.imageWidth<<16) + imgObj.imageLength;
        header.commandData3 = [data length];
//      NSLog(@"thumbnail data length = %u", header.commandData3);
        [toBeSend appendData:[NSData dataWithBytes:&header length:sizeof(packetHeader)]];
        [toBeSend appendData:data];
        currentPos = 0;
        isSending = YES;
        [[UIApplication sharedApplication] setIdleTimerDisabled:YES];
        [self.navigationItem setHidesBackButton:YES animated:YES];
    }
    else
    {
        if(currentPos + kBuffer < imgObj.imageSize)
        {
            header.command = 19;
            header.commandData1 = kBuffer;
            [toBeSend appendData:[NSData dataWithBytes:&header length:sizeof(packetHeader)]];
            NSRange r;
            r.location = currentPos;
            r.length = kBuffer;
            [toBeSend appendData:[imgObj.pimage subdataWithRange:r]];
            currentPos += kBuffer;
        }
        else
        {//last packet
            header.command = 17;
            header.commandData1 = imgObj.imageSize - currentPos;
            [toBeSend appendData:[NSData dataWithBytes:&header length:sizeof(packetHeader)]];
            NSRange r;
            r.location = currentPos;
            r.length = header.commandData1;
            [toBeSend appendData:[imgObj.pimage subdataWithRange:r]];
            currentPos = -1;
            if ([self.imageArr count]) {
                [self.imageArr removeObjectAtIndex:0];
            }
            [self.sndTableView reloadData];
        }
    }

    [manager sendPacket:toBeSend];
    self.sendingProgess.progress = (float)currentPos / (float)imgObj.imageSize;

    [imgObj release];
}


- (void)load 
{


    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];

    if (![imageURLArr count]) {
        return;
    }        
    int imageSum = [imageURLArr count];

        NSURL *path = [self.imageURLArr objectAtIndex:0] ;

        ALAssetsLibrary *library = [[ALAssetsLibrary alloc] init];
        [library assetForURL:path resultBlock:^(ALAsset *asset)
         {
             ALAssetRepresentation *representation = [asset defaultRepresentation];
             CGImageRef ref = [representation fullResolutionImage];
             if (ref != nil) {
                 omg = [UIImage imageWithCGImage:ref];
                 [omg retain];
             }

         }
                failureBlock:^(NSError *error)
         {
             // error handling
         }];
        [library release];

        if (omg) {
            NSData *data = UIImageJPEGRepresentation(omg, kcompressionQuality);
            thisImageObj = [imageObj alloc];
            thisImageObj.imageSize = [data length];
            thisImageObj.imageWidth = omg.size.width;
            thisImageObj.imageLength = omg.size.height;
            thisImageObj.pimage = data;
            [omg release];
        }
        else {
            return;
        }


    imageSum--;

    if ([self.imageURLArr count]) {
        [self.imageURLArr removeObjectAtIndex:0];
    }

    [self.imageArr addObject:thisImageObj];
    [thisImageObj release];

    [NSThread sleepForTimeInterval:1.0];

    [pool release];

}

しかし、他のスレッドのメソッドは現在機能しており、問題はまだ終了しているので、誰かが私にどのようにできるかについていくつかの提案をすることができますか、または私は別のスレッドをまったく必要としません

4

1 に答える 1

0

ここには一見いくつかの問題があります。まず、を使用していますが detachNewThreadSelector:toTarget:withObject:、これはほとんど適切なツールではありません。これにより、無制限の数のスレッドが生成される可能性があります。これはおそらくあなたをクラッシュさせるものではありませんが、それは非常に危険な習慣です。より良い解決策は次のようなものです:

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,0), ^{
  [self load];
};

これにより、スレッドプールが正しく管理されます。

主な問題は、ロックせずにivarにアクセスしていることです。NSMutableArrayスレッドセーフではありません。どのスレッドでも変更することはできません。GCDはここでも役立ちます。Mike Ashは、GCDの新機能と呼ばれる優れた記事を作成しました。dispatch_sync読み取りとdispatch_barrier_async書き込みに使用できます。

そうは言っても、このバックグラウンドスレッドが本当に必要であることを確認してください。何がそんなに時間がかかっているのloadですか?スレッドを回避できる場合は、通常、回避する必要があります。

于 2012-05-10T05:45:55.750 に答える