【问题标题】:Objective C model - How to download image inside a model class?Objective C 模型 - 如何在模型类中下载图像?
【发布时间】:2016-01-05 09:51:16
【问题描述】:

我有以下模型的盒子,它的目的是在后台线程中下载图像并从这个下载的图像中创建一个图像。

viewcontroller 有一个自定义的 uicollectioncell,但它只是一个 uiimageview;没什么太复杂的。

cellForItemAtIndexPath 中,我想使用模型下载的图像分配单元格的图像视图。

但是,它并不完全有效;

  1. 图像永远不会出现
  2. 如果我将背景图片下载器移动到 cellForItemAtIndexPath 并更改一些项目,则图片加载正常。

但我想要的是分离 ViewContoller 和模型;模型应该完成繁重的工作,而视图控制器只处理显示。

代码如下

// ViewController: View Did Load


- (void)viewDidLoad {
    [super viewDidLoad];

    if (!self.picturesArray) self.picturesArray = [NSMutableArray arrayWithCapacity:kNumberOfCells];

    self.collectionView.delegate = self;
    self.collectionView.dataSource = self;
    self.collectionView.backgroundColor = [UIColor clearColor];

    for (int i=0; i<kNumberOfCells; i++)
    {
        Box *box = [[Box alloc] init];
        [self.picturesArray addObject:box];
        box = nil;
    }
}


// ViewController : collectionView delegage

- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
    MyCustomCollectionViewCell *cell = (MyCustomCollectionViewCell *) [collectionView dequeueReusableCellWithReuseIdentifier:cellId forIndexPath:indexPath];

    Box *box = self.picturesArray[indexPath.row];
    cell.backgroundColor = box.bgColor;
    cell.imageView.image = box.image;

    return cell;
}

box模型如下

// Box model with an image property

- (instancetype)init
{
    self = [super init];
    if (self)
    {
        NSURL *url = [NSURL URLWithString:kUrlString];

        // Block variable to be assigned in block.
        __block NSData *imageData;
        dispatch_queue_t backgroundQueue  = dispatch_queue_create("imagegrabber.bgqueue", NULL);

        // Dispatch a background thread for download
        dispatch_async(backgroundQueue, ^(void) {
            imageData = [NSData dataWithContentsOfURL:url];
            if (imageData.length >0)
            {
// self.image is a property of the box model
                self.image  = [[UIImage alloc] initWithData:imageData];

                // Update UI on main thread
                dispatch_async(dispatch_get_main_queue(), ^(void) {


                });
            }
        });

    }
    return self;
}

我的问题是这样的:

  1. 如何让盒子模型下载图像,然后在我的 cellAtIndexPath 中使单元格的 imageView 从下载的盒子模型图像中分配其图像?

另一个不相关的问题

  1. 将模型与项目的实际下载分开不是最佳做法吗?但是,如果我不打算将它放在视图控制器中,而不是模型中,它会放在哪里,你会如何/如何称呼它?

谢谢你

【问题讨论】:

    标签: objective-c model-view-controller background uiimage


    【解决方案1】:

    将模型与其图像文件分离并使用模型的图像 URL 键将图像保存在缓存中是更好的方法。

    此外,将初始化方法放在 MyCustomCollectionViewCell 中是配置单元格的更好方法。

    我建议你使用https://github.com/rs/SDWebImage(或类似的库)来下载和缓存图片。

    MyCustomCollectionViewCell.h:

    @interface MyCustomCollectionViewCell : UITableViewCell
    
    -(void) initializeWithBox:(Box*)box;
    

    带有 SDWebImage 的 MyCustomCollectionViewCell.m:

    @implementation MyCustomCollectionViewCell
    
    -(void) initializeWithBox:(Box*)box
    {
        [self setBackgroundColor:[box bgColor]];
        [self.imageView sd_setImageWithURL:[NSURL URLWithString:[box kUrlString]] placeholderImage:nil];
    }
    

    没有库的 MyCustomCollectionViewCell.m:

    @implementation MyCustomCollectionViewCell
    
    -(void) initializeWithBox:(Box*)box
    {
        [self setBackgroundColor:[box bgColor]];
        __weak typeof(self) weakSelf = self;
        NSURLSessionTask *task = [[NSURLSession sharedSession] dataTaskWithURL:[NSURL URLWithString:[box kUrlString]] completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
            if (data) {
                UIImage *image = [UIImage imageWithData:data];
                if (image) {
                    dispatch_async(dispatch_get_main_queue(), ^{
                        typeof(self) strongSelf = weakself;
                        if(strongSelf)
                            [self.imageView setImage:image];
                    });
                }
            }
        }];
        [task resume];
    }
    

    在您的视图控制器中:

    - (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
    {
        MyCustomCollectionViewCell *cell = (MyCustomCollectionViewCell *) [collectionView dequeueReusableCellWithReuseIdentifier:cellId forIndexPath:indexPath];
    
        Box *box = self.picturesArray[indexPath.row];
        [cell initializeWithBox:box]
        return cell;
    }
    

    【讨论】:

    • 我希望在没有第三方的情况下这样做,但是好的,我会再试一次
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-09-26
    • 2021-11-07
    • 2019-08-11
    • 1970-01-01
    • 1970-01-01
    • 2013-09-19
    • 1970-01-01
    相关资源
    最近更新 更多