为什么NSMutableDictionary的setObjectForKey方法导致崩溃?

时间:2017-02-07 05:55:24

标签: ios objective-c nsmutabledictionary

在NSMutableDictionary对象上调用setObjectForKey方法时应用程序崩溃。 isUrlSavedWithThumbDic和url字符串具有在控制台中显示的值。

[isUrlSavedWithThumbDic setObject:[NSNumber numberWithBool:YES] forKey:url];

enter image description here

代码在UIImageView类别中运行。 isURLSavedWithThumbDic是类别中的静态变量,声明为:

static NSMutableDictionary *isUrlSavedWithThumbDic;

isURlSavedWithThumbDic在类别方法中初始化,然后在其上设置任何值。

if (isUrlSavedWithThumbDic == NULL || isUrlSavedWithThumbDic == nil){
     isUrlSavedWithThumbDic = [NSMutableDictionary new];
}

每次都不会发生崩溃,应用程序运行大多没有问题。在类别中声明静态变量是否有任何逻辑问题?

UIImageView类别方法的完整源代码:

-(void)SetThumbImageForDownloadURL:(NSString*)url  indexPath:(NSIndexPath*)indexPath  waterMarkData:(CLWaterMarkModel*)watermarkData genericUrl:(NSString*)genericUrl placeHolder:(NSString*)placeHolder WillHaveWaterMark:(BOOL)willHaveWaterMark{


    __weak __typeof__(self) weakSelf = self;
    [self setImage:nil];
    if([url isEqualToString:@""]  || ![url caseInsensitiveCompare:@"unknown"] ) {
        [self  setImage:[UIImage imageNamed:placeHolder]];
    }
    else
    {
        NSData *imageData = [CMCache getThumbImageForKey:[url MD5] withPath:CacheDir];
        if(imageData)
        {
             UIImage *image = [UIImage imageWithData:imageData];
            if(!willHaveWaterMark){
                //my projects
                 [self  setImage:image];
            }else{
                if(watermarkData == nil){
                    //don't show image if watermark data is not there. Every thumb Image should have watermark data
                   // [self  setImage:image];

                }else{
                    if (isUrlSavedWithThumbDic == NULL || isUrlSavedWithThumbDic == nil){
                        isUrlSavedWithThumbDic = [NSMutableDictionary new];
                    }@try {
                        BOOL isSavedWithThumb = [[isUrlSavedWithThumbDic objectForKey:url] boolValue];
                        if( isSavedWithThumb){
                            [self  setImage:image];
                        }else{
                            //save image with thumb this time
                            image = [UIImage renderWaterMarkImage:image withModel:watermarkData generic:genericUrl];
                            [self  setImage:image];
                            [CMCache saveThumbnailImageAndCompressIfRequired:UIImagePNGRepresentation(image) forKey:[url MD5] withNewPath:CacheDir size:self.frame.size] ;

                            [isUrlSavedWithThumbDic setObject:[NSNumber numberWithBool:YES] forKey:url];

                        }

                    } @catch (NSException *exception) {
                        DLog(@"Exception:%@",exception);

                    }
                }
            }


        }
        else
        {

            if(downloadInProgress == nil){
                downloadInProgress = [NSMutableDictionary new];
                isUrlSavedWithThumbDic = [NSMutableDictionary new];
            }

            if (downloadInProgress[url] == nil ){
                downloadInProgress[url] = url;

                [CMRestInterface asyncImageDownload:url withProgressHandler:nil andCompletionHandler:^(UIImage *image, NSUInteger errorCode)
                 {
                     [downloadInProgress removeObjectForKey:url];

                     __typeof__(self) strongSelf = weakSelf;
                     dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{

                         if (image)
                         {
                             @try {
                             //
                                 UIImage *customImage = image;
                                 if(watermarkData != nil){
                                     customImage = [UIImage renderWaterMarkImage:image withModel:watermarkData generic:genericUrl];

                                     [isUrlSavedWithThumbDic setObject:[NSNumber numberWithBool:YES] forKey:url];

                                 } else {
                                     [isUrlSavedWithThumbDic setObject:[NSNumber numberWithBool:NO] forKey:url];
                                 }
                                 [CMCache saveThumbnailImageAndCompressIfRequired:UIImagePNGRepresentation(customImage) forKey:[url MD5] withNewPath:CacheDir size:self.frame.size] ;
                                 dispatch_async(dispatch_get_main_queue(), ^{

                                UIView *parentView = strongSelf.superview;
                                while(parentView != nil && ![parentView isKindOfClass:NSClassFromString(@"UICollectionView")]
                                      && ![parentView isKindOfClass:NSClassFromString(@"UITableView")]){

                                    parentView = parentView.superview;

                                }
                                //ImageViewInsideTAbleViewCell
                                if(parentView == nil){
                                    if(willHaveWaterMark){
                                        if(watermarkData){
                                            if(!customImage){
                                                [ strongSelf setImage:[UIImage imageNamed:placeHolder]];
                                            }else{
                                                [strongSelf setImage:customImage];
                                            }
                                        }else{
                                            //[ strongSelf setImage:[UIImage imageNamed:placeHolder]];
                                        }

                                    }else{
                                        if(!customImage){
                                            [ strongSelf setImage:[UIImage imageNamed:placeHolder]];
                                        }else{
                                            [strongSelf setImage:customImage];
                                        }
                                    }

                                } else if([parentView isKindOfClass:NSClassFromString(@"UICollectionView")]){
                                    UICollectionView *cv = (UICollectionView*)parentView;


                                    UICollectionViewCell *cell = [cv cellForItemAtIndexPath:indexPath];
                                    if(cell){
                                        if(willHaveWaterMark){
                                            if(watermarkData){
                                                if(!customImage){
                                                    [ strongSelf setImage:[UIImage imageNamed:placeHolder]];
                                                }else{
                                                    [strongSelf setImage:customImage];
                                                }
                                            }else{
                                                // [ strongSelf setImage:[UIImage imageNamed:placeHolder]];
                                            }

                                        }else{
                                            if(!customImage){
                                                [ strongSelf setImage:[UIImage imageNamed:placeHolder]];
                                            }else{
                                                [strongSelf setImage:customImage];
                                            }
                                        }

                                    }



                                } else if ([parentView isKindOfClass:NSClassFromString(@"UITableView")]){
                                    UITableView *tv  = (UITableView*)parentView;

                                    //  [tv reloadRowsAtIndexPaths:[tv indexPathsForVisibleRows] withRowAnimation:UITableViewRowAnimationNone];
                                    UITableViewCell *cell = [tv cellForRowAtIndexPath:indexPath];
                                    if(cell){
                                        if(willHaveWaterMark){
                                            if(watermarkData){
                                                if(!customImage){
                                                    [ strongSelf setImage:[UIImage imageNamed:placeHolder]];
                                                }else{
                                                    [strongSelf setImage:customImage];
                                                }
                                            }else{
                                                //  [ strongSelf setImage:[UIImage imageNamed:placeHolder]];
                                            }

                                        }else{
                                            if(!customImage){
                                                [ strongSelf setImage:[UIImage imageNamed:placeHolder]];
                                            }else{
                                                [strongSelf setImage:customImage];
                                            }
                                        }

                                    }

                                }


                            });
                            }@catch (NSException *exception) {
                                 DLog(@"Exception:%@",exception);
                             }

                         }else{
                             dispatch_async(dispatch_get_main_queue(), ^{
                                [strongSelf setImage:[UIImage imageNamed:placeHolder]];
                             });

                         }

                    });


                }];

            }

        }

    }



}

1 个答案:

答案 0 :(得分:0)

我能够找出崩溃背后的原因。问题是并发问题。多个线程并行运行,每个线程都试图下载图像,下载成功后,它正在更新可变字典。当两个单独的线程试图在字典中同时写入时,应用程序崩溃,因为代码不是线程安全的。快速解决方法是在串行队列中移动共享资源,以便所有线程一次写入一个字典。