0

我的应用程序的功能是在两个 iDevices 之间传输图片。

用户可以选择很多图片发送。但是由于发送过程需要时间,所以现在我只是将尚未发送的图片放入一个数组中,当用户从照片库中选择它时。

我现在的问题是,如果用户一次选择太多图片,我的应用程序将被突然终止。我现在的解决方案是,如果用户一次选择太多图片,我只会在一些图片上放置标记,但将它们留在照片库中,同时将它们放入数组中。然后我有另一个线程在发送操作发生的同时从库中加载图片。所以我的观点是我怀疑一次将这么多图片放入数组中是应用程序终止的原因,所以我想缓存一些图片然后将其他一些图片留在磁盘中,我的代码:

- (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];
};

这将正确管理您的线程池。

您的主要问题是您在没有任何锁定的情况下访问您的 ivars。NSMutableArray不是线程安全的。您不能只在任何线程上修改它。GCD 在这里也有帮助。Mike Ash 写了一篇很好的文章,名为What's New in GCD。您可以使用dispatch_sync读取和dispatch_barrier_async写入。

综上所述,请确保您确实需要此后台线程。什么需要这么长时间load?当您可以避免线程时,您通常应该这样做。

于 2012-05-10T05:45:55.750 回答