我的应用程序想要获取 iphone的专辑列表和某些专辑中的所有照片.

在应用程序中,我列举了iphone的一张专辑中的照片.
由于某些专辑可能有很多照片,考虑到性能,我使用GCD:dispatch_async.但是当KVO调用的tableview单元格更新时,它总是崩溃.
我不知道我是否以错误的方式使用KVO或GCD.

现在,我使用performSelectorInBackground:替换dispatch_async.现在应用程序没有崩溃,但应用程序的性能很差:只有当你触摸它时才会显示单元格的标题,或者当有很多照片时滚动桌面视图.换句话说,必须阻止主线程.

附件是代码,核心代码在AlbumListViewController.m中.

任何人都可以帮我检查一下吗?

我只是想知道:
1如果使用dispatch_async,应用程序崩溃的原因
2如果有很多照片,我怎样才能提高性能.

谢谢.

以下是我的代码:

//
//  RootViewController.h
//  AlbumDemo


#import 

@interface RootViewController : UITableViewController {
    NSMutableArray *_listArray;
}

@property (nonatomic,retain) NSMutableArray *listArray;

@end


//  RootViewController.m


#import "RootViewController.h"
#import 
#import "AlbumListViewController.h"
Nsstring *thumnail   = @"thumnail";
Nsstring *albumName  = @"albumName";
Nsstring *albumNum   = @"albumNum";
Nsstring *albumGroup = @"albumGroup";
@implementation RootViewController
@synthesize listArray = _listArray;

#pragma -
#pragma Function
- (void)setUp
{
    _listArray = [[NSMutableArray alloc] initWithCapacity:1];
    self.title = @"Albums";
}
- (void)fetchAlbumList
{
    ALAssetsLibrary *assetLib = [[[ALAssetsLibrary alloc] init] autorelease];
    ALAssetsFilter *fileter = [ALAssetsFilter allPhotos];
    [assetLib enumerateGroupsWithTypes:ALAssetsGroupAll 
                            usingBlock:^(ALAssetsGroup *group,BOOL *stop)
     {
         if (group)
         {
             [group setAssetsFilter:fileter];
             Nsstring *_groupName = [group valueForProperty:ALAssetsGroupPropertyName];
             NSNumber *_groupNum = [NSNumber numberWithInteger:[group numberOfAssets]];
             UIImage *_groupImage = [UIImage imageWithCGImage:[group posterImage]];

             NSDictionary *dic = [NSDictionary dictionaryWithObjectsAndKeys:_groupName,albumName,_groupNum,albumNum,_groupImage,thumnail,group,albumGroup,nil];

             [_listArray addobject:dic];
             [self.tableView reloadData];

         }
         else
         {
             NSLog(@"_listArray :%@",_listArray);
         }

     } 
                          failureBlock:^(NSError *error) 
     {
         NSLog(@"Error: %@",error);;
     }
     ];

}
#pragma -
#pragma ViewController lift cycle
- (void)viewDidLoad
{
    [super viewDidLoad];
    [self setUp];
    [self fetchAlbumList];

}

- (void)viewWillAppear:(BOOL)animated
{
    [super viewWillAppear:animated];
}

- (void)viewDidAppear:(BOOL)animated
{
    [super viewDidAppear:animated];
}

- (void)viewWilldisappear:(BOOL)animated
{
    [super viewWilldisappear:animated];
}

- (void)viewDiddisappear:(BOOL)animated
{
    [super viewDiddisappear:animated];
}

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
    return  50;
}
// Customize the number of sections in the table view.
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
    return 1;
}

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
    return [_listArray count];
}

// Customize the appearance of table view cells.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    static Nsstring *CellIdentifier = @"Cell";
    UILabel *nameLab = nil;
    UILabel *numLab = nil;
    UIImageView *thumnailImage = nil;

    UIFont *font = [UIFont boldSystemFontOfSize:18];

    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
    if (cell == nil) {
        cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
         cell.accessoryType = UITableViewCellAccessorydisclosureIndicator;

        thumnailImage = [[UIImageView alloc] initWithFrame:CGRectMake(0,50,50)];
        thumnailImage.tag = 100;
        [cell.contentView addSubview:thumnailImage];
        [thumnailImage release];


        nameLab = [[UILabel alloc] initWithFrame:CGRectMake(60,10,100,30)];
        nameLab.tag = 200;
        nameLab.backgroundColor = [UIColor clearColor];
        nameLab.font = font;
        [cell.contentView addSubview:nameLab];
        [nameLab release];

        numLab = [[UILabel alloc] initWithFrame:CGRectMake(200,30)];
        numLab.tag = 300;
        numLab.backgroundColor = [UIColor clearColor];
        numLab.textColor = [UIColor grayColor];
        numLab.font = font;
        [cell.contentView addSubview:numLab];
        [numLab release];
    }
    else
    {
        thumnailImage = (UIImageView *)[cell.contentView viewWithTag:100];
        nameLab = (UILabel *)[cell.contentView viewWithTag:200];
        numLab = (UILabel *)[cell.contentView viewWithTag:300];
    }

    NSDictionary *dic = [self.listArray objectAtIndex:indexPath.row];

    thumnailImage.image = (UIImage *)[dic valueForKey:thumnail];

    Nsstring *title = [dic valueForKey:albumName];
    CGSize titleSize = [title sizeWithFont:font];
    CGRect rect = nameLab.frame;
    rect.size = titleSize;
    nameLab.frame = rect;
    nameLab.text = title;

    rect = numLab.frame;
    rect.origin.x = 60 + nameLab.frame.size.width + 10;
    numLab.frame = rect;

    numLab.text = [Nsstring stringWithFormat:@"(%d)",[[dic valueForKey:albumNum] intValue]];


    // Configure the cell.
    return cell;
}

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
    NSDictionary *dic = [self.listArray objectAtIndex:indexPath.row];

    AlbumListViewController *viewController = [[AlbumListViewController alloc] initWithAssetGroup:[dic valueForKey:albumGroup]];
    [self.navigationController pushViewController:viewController animated:YES];
    [viewController release];
    [tableView deselectRowAtIndexPath:indexPath animated:YES];
}

- (void)didReceiveMemoryWarning
{
    // Releases the view if it doesn't have a superview.
    [super didReceiveMemoryWarning];

    // Relinquish ownership any cached data,images,etc that aren't in use.
}

- (void)viewDidUnload
{
    [super viewDidUnload];

    // Relinquish ownership of anything that can be recreated in viewDidLoad or on demand.
    // For example: self.myOutlet = nil;
}

- (void)dealloc
{
    My_Release (_listArray);
    [super dealloc];
}

@end


//  AlbumListViewController.h
//  AlbumDemo

#import 
#import 

@interface AlbumListViewController : UITableViewController {
    NSMutableArray *_marr;
    ALAssetsGroup *_assetsGroup;
}

@property (nonatomic,retain) NSMutableArray *list;
@property (nonatomic,retain) ALAssetsGroup *assetsGroup;

- (id)initWithAssetGroup:(ALAssetsGroup *)group;
@end

//  AlbumListViewController.m
//  AlbumDemo

#import "AlbumListViewController.h"

@interface PhotoObj : NSObject {
    Nsstring *_name;
    UIImage *_thumbnail;
    UIImage *_fullImage;
}

@property (nonatomic,copy  ) Nsstring *name;
@property (nonatomic,retain) UIImage *thumbnail;
@property (nonatomic,retain) UIImage *fullImage;
@end

@implementation PhotoObj
@synthesize name = _name;
@synthesize thumbnail = _thumbnail,fullImage = _fullImage;
- (void)dealloc
{
    My_Release(_thumbnail);
    My_Release(_fullImage);
    My_Release(_name);
    [super dealloc];
}
@end

@interface AlbumListViewController()

- (NSMutableArray*)list;
- (NSUInteger)countOfList;
- (id)objectInListAtIndex:(NSUInteger)idx;
- (void)insertObject:(id)anObject inListAtIndex:(NSUInteger)idx;
- (id)objectInListAtIndex:(NSUInteger)idx;
- (void)removeObjectFromListAtIndex:(NSUInteger)idx;
- (void)replaceObjectInListAtIndex:(NSUInteger)idx withObject:(id)anObject;
- (void)setList:(NSMutableArray *)_arr;

@end

@implementation AlbumListViewController
@synthesize  assetsGroup = _assetsGroup;

- (id)initWithAssetGroup:(ALAssetsGroup *)group
{
    self = [self initWithStyle:UITableViewStylePlain];
    if (self )
    {
        _marr = [[NSMutableArray alloc] initWithCapacity:1];
        self.assetsGroup = group;
        self.tableView.delegate = self;
        self.tableView.dataSource = self;

    }
    return  self;
}

- (id)initWithStyle:(UITableViewStyle)style
{
    self = [super initWithStyle:style];
    if (self) {
        // Custom initialization
    }
    return self;
}

- (void)dealloc
{
    My_Release(_marr);
    My_Release(_assetsGroup);
    [self removeObserver:self forKeyPath:@"list"];
    [super dealloc];
}

- (void)didReceiveMemoryWarning
{
    // Releases the view if it doesn't have a superview.
    [super didReceiveMemoryWarning];

}

#pragma mark - View lifecycle
- (void)parseAssetGroup
{
    [_marr removeAllObjects];
    [self.assetsGroup enumerateAssetsUsingBlock:^(ALAsset *result,NSUInteger index,BOOL *stop) {
        if (result)
        {
            PhotoObj *obj = [[PhotoObj alloc] init];
            obj.thumbnail = [UIImage imageWithCGImage:[result thumbnail]];
            ALAssetRepresentation *represention = [result defaultRepresentation];
            obj.fullImage = [UIImage imageWithCGImage:[represention fullScreenImage]];
            obj.name = [[represention url] absoluteString];


            [self willChangeValueForKey:@"list"];
            [self insertObject:obj inListAtIndex:[_marr count]];
            [self didChangeValueForKey:@"list"];
            My_Release(obj);
        }

    }];

}

- (void)viewDidLoad
{
    [super viewDidLoad];
    [self addobserver:self forKeyPath:@"list" options:NSkeyvalueObservingOptionNew |NSkeyvalueObservingOptionOld context:NULL];
    /*
     if performSelectorInBackground,the perofrmance is poor
     as the title of the cell will be shown in a long time and it Now seems the main thread is blocked
     */
    [self performSelectorInBackground:@selector(parseAssetGroup) withObject:nil];
    /*
     using dispatch_async it always crashes 
     as it says the sth is wrong with the tableview update

     */

//  dispatch_async(dispatch_get_main_queue(),^{
//      [self parseAssetGroup];
//  });
}

- (void)viewDidUnload
{
    [super viewDidUnload];

}

#pragma mark - Table view data source
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
    return  50;
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
    // Return the number of sections.
    return 1;
}

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
    // Return the number of rows in the section.
    return [_marr count];
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    static Nsstring *CellIdentifier = @"Cell";

    UIImageView *thumbNail = nil;
    UILabel *nameLab = nil;
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
    if (cell == nil) {
        cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
        cell.accessoryType = UITableViewCellAccessorydisclosureIndicator;

        thumbNail = [[UIImageView alloc] initWithFrame:CGRectMake(0,50)];
        thumbNail.tag = 99;
        [cell.contentView addSubview:thumbNail];
        [thumbNail release];

        nameLab = [[UILabel alloc] initWithFrame:CGRectMake(60,240,40)];
        nameLab.numberOfLines = 2;
        nameLab.font = [UIFont systemFontOfSize:16];
        nameLab.tag = 199;
        [cell.contentView addSubview:nameLab];
        [nameLab release];
    }
    else
    {
        thumbNail = (UIImageView *)[cell.contentView viewWithTag:99];
        nameLab = (UILabel *)[cell.contentView viewWithTag:199];
    }
    // Configure the cell...
    PhotoObj *obj = [_marr objectAtIndex:indexPath.row];
    nameLab.text = obj.name;
    thumbNail.image = obj.thumbnail;

    return cell;
}
#pragma mark -
- (NSUInteger)countOfList
{
    return [_marr count];
}
- (NSMutableArray*)list
{
    return _marr;
}
- (void)setList:(NSMutableArray *)_arr
{
    if (_marr != _arr)
    {
        [_marr release];
        _marr = _arr;
    } 
}

- (id)objectInListAtIndex:(NSUInteger)idx
{
    return [_marr objectAtIndex:idx];
}

- (void)insertObject:(id)anObject inListAtIndex:(NSUInteger)idx
{
    if ([NSThread isMainThread])
    {
        NSLog(@"insert main thread");
    }
    else
    {
        NSLog(@"insert not main thread");
    }
    [_marr insertObject:anObject atIndex:idx];
}


- (void)removeObjectFromListAtIndex:(NSUInteger)idx
{
    [_marr removeObjectAtIndex:idx];
}
- (void)replaceObjectInListAtIndex:(NSUInteger)idx withObject:(id)anObject
{
    [_marr replaceObjectAtIndex:idx withObject:anObject];
}
- (void)observeValueForKeyPath:(Nsstring *)keyPath
                      ofObject:(id)object
                        change:(NSDictionary *)change
                       context:(void *)context
{
    NSIndexSet *indices = [change objectForKey:NSkeyvalueChangeIndexesKey];
    if (indices == nil)
        return; // nothing to do

    // Build index paths from index sets
    NSUInteger indexCount = [indices count];
    NSUInteger buffer[indexCount];
    [indices getIndexes:buffer maxCount:indexCount inIndexrange:nil];

    NSMutableArray *indexPathArray = [NSMutableArray array];
    for (int i = 0; i 

解决方法

我今天遇到了完全相同的问题.简而言之,原因是你无法从后台调度队列中执行UIKit相关任务,例如更新表,或者在我的情况下是Textview.请查看以下链接了解更多详情.

comparison GCD vs. performSelectorInBackground: dispatch_async not in background

可能的解决方案如下:不是将更新块中的新数据直接分配给导致崩溃的KVO变量,而是从更新块内部向主队列分配另一个块.如果使用dispatch_async_f函数执行此操作,则可以将指针作为上下文传递给数据.

像这样:

dispatch_async(yourQueue,^() {
  NSArray *data;
  // do stuff to alloc and fill the array
  // ...
  dispatch_async(dispatch_get_main_queue(),^() {
    myObj.data = data; // the assignment,which triggers the KVO.
  });
});

对我来说,这可以保留和释放数据.不确定,如果这是正确的.

ios – GCD和KVO问题的更多相关文章

  1. ios – UITableView和Cell Reuse

    这是我的CustomCell类的init方法解决方法如果没有要显示的图像,则必须清除图像视图:

  2. ios – fetchedResultsController.fetchedObjects.count = 0但它充满了对象

    我正在使用相当标准的fetchedResultsController实现来输出tableView.在-viewDidLoad的最后,我正在进行第一次调用:这是我的fetchedResultsController:我的tableView方法:所以,问题是:在_fetchedResultsController.fetchedobjects.count的日志中等于0,但在视觉上tableView充满了对

  3. ios – UITableView在滚动时阻止重新加载

    或者你能想象一个防止这种行为的好方法吗?解决方法抱歉,我没有足够的声誉来添加评论,因此在单独的答案中回答您的上一个问题.-performSelector:withObject:afterDelay:延迟为0.0秒不会立即执行给定的选择器,而是在当前的RunloopCycle结束后和给定的延迟之后执行它.-performSelector:withObject:添加到当前Runloop循环中并执行.这与直接调用该方法相同.因此,使用-performSelector:withObject:afterDelay:

  4. ios – 在Swift中通过标记访问UITableViewCell内部的不同视图

    我正在尝试使用swift为iOS8制作应用程序.这里的目标是制作一种新闻源.此Feed显示来自用户的帖子,其遵循特定模式.我想过使用UITableView,其中每个单元格都遵循自定义布局.当我尝试访问其中的文本标签时出现问题.我尝试通过它的标签访问它,但是当我这样做时,整个应用程序崩溃了.报告的错误是“Swift动态转换失败”,我使用以下代码访问视图:难道我做错了什么?解决方法我认为问题是标签0.所有视图都是默认值0.所以尝试另一个标签值.

  5. ios – 如何实现`prepareForReuse`?

    解决方法尝试将此添加到您的MGSwipeTableCell.m:

  6. ios – 在UITableView上轻扫以删除以使用UIPanGestureRecognizer

    我使用以下代码将UIPanGuestureRecognizer添加到整个视图中:在主视图中我有一个UITableView,它有这个代码来启用滑动删除功能:只有RUNNING1打印到日志中,并且“删除”按钮不会显示.我相信其原因是UIPanGestureRecognizer,但我不确定.如果这是正确的,我该如何解决这个问题.如果这不正确,请提供原因并解决.谢谢.解决方法从document:Ifage

  7. viewWillAppear vs Viewdidload ios

    使用iOS导航应用程序的代码时,我遇到了麻烦:我在哪里可以为UITableView设置方法“initdata”?请帮帮我.解决方法您可以根据应用程序的需求放置initData,如果您的表需要每次使用新数据加载数据,那么它应该在否则,如果表需要通过单个数据重新加载,该数据不会发生变化或者没有对数据执行任何编辑操作,则应使用

  8. ios tableView reloadRowsAtIndexPaths无效

    解决方法包裹它怎么样?希望这可以帮助.

  9. ios – 我的表视图在滚动时在SWIFT中重用所选单元格

    实例变量

  10. ios – 重新加载表动画

    因此,当用户点击我的表格中的单元格时,我实际上并没有推送到新的视图控制器,而只是重新加载该tableView中的数据.但是,我希望得到一个效果类似于我推动新视图控制器时的效果.有没有人知道我如何将旧内容从屏幕上的旧内容和新内容放到屏幕上以获取整个表格?

随机推荐

  1. iOS实现拖拽View跟随手指浮动效果

    这篇文章主要为大家详细介绍了iOS实现拖拽View跟随手指浮动,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

  2. iOS – genstrings:无法连接到输出目录en.lproj

    使用我桌面上的项目文件夹,我启动终端输入:cd然后将我的项目文件夹拖到终端,它给了我路径.然后我将这行代码粘贴到终端中找.-name*.m|xargsgenstrings-oen.lproj我在终端中收到此错误消息:genstrings:无法连接到输出目录en.lproj它多次打印这行,然后说我的项目是一个目录的路径?没有.strings文件.对我做错了什么的想法?

  3. iOS 7 UIButtonBarItem图像没有色调

    如何确保按钮图标采用全局色调?解决方法只是想将其转换为根注释,以便为“回答”复选标记提供更好的上下文,并提供更好的格式.我能想出这个!

  4. ios – 在自定义相机层的AVFoundation中自动对焦和自动曝光

    为AVFoundation定制图层相机创建精确的自动对焦和曝光的最佳方法是什么?

  5. ios – Xcode找不到Alamofire,错误:没有这样的模块’Alamofire’

    我正在尝试按照github(https://github.com/Alamofire/Alamofire#cocoapods)指令将Alamofire包含在我的Swift项目中.我创建了一个新项目,导航到项目目录并运行此命令sudogeminstallcocoapods.然后我面临以下错误:搜索后我设法通过运行此命令安装cocoapodssudogeminstall-n/usr/local/bin

  6. ios – 在没有iPhone6s或更新的情况下测试ARKit

    我在决定下载Xcode9之前.我想玩新的框架–ARKit.我知道要用ARKit运行app我需要一个带有A9芯片或更新版本的设备.不幸的是我有一个较旧的.我的问题是已经下载了新Xcode的人.在我的情况下有可能运行ARKit应用程序吗?那个或其他任何模拟器?任何想法或我将不得不购买新设备?解决方法任何iOS11设备都可以使用ARKit,但是具有高质量AR体验的全球跟踪功能需要使用A9或更高版本处理器的设备.使用iOS11测试版更新您的设备是必要的.

  7. 将iOS应用移植到Android

    我们制作了一个具有2000个目标c类的退出大型iOS应用程序.我想知道有一个最佳实践指南将其移植到Android?此外,由于我们的应用程序大量使用UINavigation和UIView控制器,我想知道在Android上有类似的模型和实现.谢谢到目前为止,guenter解决方法老实说,我认为你正在计划的只是制作难以维护的糟糕代码.我意识到这听起来像很多工作,但从长远来看它会更容易,我只是将应用程序的概念“移植”到android并从头开始编写.

  8. ios – 在Swift中覆盖Objective C类方法

    我是Swift的初学者,我正在尝试在Swift项目中使用JSONModel.我想从JSONModel覆盖方法keyMapper,但我没有找到如何覆盖模型类中的Objective-C类方法.该方法的签名是:我怎样才能做到这一点?解决方法您可以像覆盖实例方法一样执行此操作,但使用class关键字除外:

  9. ios – 在WKWebView中获取链接URL

    我想在WKWebView中获取tapped链接的url.链接采用自定义格式,可触发应用中的某些操作.例如HTTP://我的网站/帮助#深层链接对讲.我这样使用KVO:这在第一次点击链接时效果很好.但是,如果我连续两次点击相同的链接,它将不报告链接点击.是否有解决方法来解决这个问题,以便我可以检测每个点击并获取链接?任何关于这个的指针都会很棒!解决方法像这样更改addobserver在observeValue函数中,您可以获得两个值

  10. ios – 在Swift的UIView中找到UILabel

    我正在尝试在我的UIViewControllers的超级视图中找到我的UILabels.这是我的代码:这是在Objective-C中推荐的方式,但是在Swift中我只得到UIViews和CALayer.我肯定在提供给这个方法的视图中有UILabel.我错过了什么?我的UIViewController中的调用:解决方法使用函数式编程概念可以更轻松地实现这一目标.

返回
顶部