Ios GCD和OSS销锁

Ios GCD和OSS销锁,ios,objective-c,nsmutablearray,grand-central-dispatch,freeze,Ios,Objective C,Nsmutablearray,Grand Central Dispatch,Freeze,我可能问错了问题,可能会被stackoverflow完全阻止。我有阿斯伯格综合症,没有社交技能,所以我很抱歉问我最后一个问题(因为这样的系统只为没有残疾的人设计) 我正在使用GCD从Instagram加载图像和视频。我在一个用户界面非常“繁忙”的应用程序中这样做,我想让它平稳运行,所以我在后台加载Instagram媒体 下面的代码(我可能格式化错误,所以我先道歉)运行良好,并且完全符合我的要求。它在后台加载图像(为了简单起见,我把视频放在了外面),加载图像时,我的主要UI是响应。我在两次加载之间

我可能问错了问题,可能会被stackoverflow完全阻止。我有阿斯伯格综合症,没有社交技能,所以我很抱歉问我最后一个问题(因为这样的系统只为没有残疾的人设计)

我正在使用GCD从Instagram加载图像和视频。我在一个用户界面非常“繁忙”的应用程序中这样做,我想让它平稳运行,所以我在后台加载Instagram媒体

下面的代码(我可能格式化错误,所以我先道歉)运行良好,并且完全符合我的要求。它在后台加载图像(为了简单起见,我把视频放在了外面),加载图像时,我的主要UI是响应。我在两次加载之间显示它们,而且效果也很好

不过

10分钟后,有时20分钟,有时30分钟,甚至有时两小时后,我的应用程序会冻结。如果我删除下面的代码,我就不会得到媒体,但应用程序永远不会冻结

我已经在网上搜索了好几天关于做这项工作的替代方法,并找到了关于OSSpinLockLock的解释。不走运。我发现的唯一一件事是,使用GCD不会导致OSSpinLockLock。我已经使用了我所有的仪器知识(我必须承认这比我想象的要有限),但我找不到故障

dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0ul);
    dispatch_async(queue, ^(void) {
        [[InstagramEngine sharedEngine] getMediaAtLocation:location count:kInstagramLocationBufferSize maxId:nil withSuccess:^(NSArray* media, InstagramPaginationInfo* paginationInfo) {
            if (media && media.count>0) {
                for (InstagramMedia* mediaObject in media) {
                    NSData* data = [[NSData alloc] initWithContentsOfURL:mediaObject.standardResolutionImageURL];
                    if (data) {
                        UIImage* img = [UIImage imageWithData:data];
                        if (img)
                            [self.locationBuffer addObject:img];
                        data = nil;
                    }
                }
            }
         } failure:^(NSError *error) {
             ;
         }];
    });
如果您查看这段代码,您是否看到任何可能导致锁定的因素?因为我肯定不会

self.locationBuffer在.h中声明为

@property (nonatomic,strong) NSMutableArray* locationBuffer;
并且被正确地分配和初始化(否则问题就很清楚了)。我也试着不把UIImage放在数组中,而是把NSData放在数组中,但这没有任何区别

例如,在我的iPad mini retina上,CPU负载达到195%,并在很长一段时间内保持在这个数字附近。最终,有时几个小时后,应用程序崩溃

欢迎提出任何建议


编辑:正如我现在在iPad本身的ips文件中看到的(出于某种神秘的原因,我无法将其粘贴到这个网页(stackoverflow是否仍处于实验阶段?),我看到iPad在NSURLConnection上花费了16.000多秒…

我的想法是,某些超时或故障会在太长时间内阻塞gcd队列。尝试使用
NSOperationQueue
重写该代码,这样您就可以在出现错误时停止队列或查看/控制器消失

更新1:

这是我对你的代码的试用,我添加了队列和日志,检查它们,还检查了超时值。这样,如果请求没有完成(很可能),您可以跟踪它。所有请求都是串行的,因此如果其中一个停止,您应该立即注意到它。 您可以创建多个队列并按顺序(循环)访问它们,以便同时有多个请求。我不会使用超过4个队列,这也是大多数桌面internet浏览器的默认设置

// keep the same queue for all request (class member?), don't put it in the same block
NSOperationQueue* queue= [[NSOperationQueue alloc] init];

// keep this in another code block from queue
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0ul), ^(void) {
 [[InstagramEngine sharedEngine] getMediaAtLocation:location count:kInstagramLocationBufferSize maxId:nil withSuccess:^(NSArray* media, InstagramPaginationInfo* paginationInfo) {
     if (media && media.count>0) {
         for (InstagramMedia* mediaObject in media) {
             NSURL* url= mediaObject.standardResolutionImageURL;
             NSLog(@"Start loading from %@", url);
             NSURLRequest* req= [NSURLRequest requestWithURL:mediaObject.standardResolutionImageURL
                                                                                     cachePolicy:NSURLRequestUseProtocolCachePolicy
                                                                             timeoutInterval:30]; // 30 seconds timeout
             [NSURLConnection sendAsynchronousRequest:req queue:queue completionHandler:^(NSURLResponse *response, NSData *data, NSError *connectionError) {
                 NSLog(@"Stop loading from %@ %@ %@", url, response, connectionError);
                 if (data != nil && connectionError == nil) {
                     UIImage* img = [UIImage imageWithData:data];
                     if (img) {
                         // if you are triggering some ui update run on main thread
                         // [self.locationBuffer addObject:img];
                         [self.locationBuffer performSelectorOnMainThread:@selector(addObject:)
                                                                                                     withObject:img
                                                                                                waitUntilDone:NO];
                     }
                 }
             }];
         }
     }
 } failure:^(NSError *error) {
     NSLog(@"Error getting media list: %@", error);
 }];
});

OSSpinLocks在iOS8.3+上有错误:
,从而导致此类冻结。

我认为你应该用其他东西来替换OSSpinLocks,以在你的应用程序中解决这个问题(也许可以创建你自己的自旋锁实现——搜索OSSpinLock)

不知道,但也许这会有所帮助:你应该发布实际的回溯。仅仅知道你挂断了OSSpinLockLock并不能给我们提供任何实质性的线索来了解到底发生了什么——自旋锁在操作系统和框架中随处可见。好的。我将很快发布一条来自Instruments的跟踪信息,也许你能从中得到比我更多的信息。我有第一款iPad迷你机型,刚刚完成了5个小时的课程。相同的代码,完全没有问题。那台机器运行的是iOS 7而不是iOS 8。这两个“参数”中的任何一个与此有关吗?不可能排除,但这里的信息确实不够。谢谢你的提示。我对它不熟悉,但我找到了Ray Wenderlich的教程。谢谢。我已经完成了,虽然这是一种不同的方法,但它不能解释我的应用程序中发生了什么。无论如何,谢谢。我认为某些进程停止队列(调度队列优先级默认值)的时间太长,操作系统会抛出旋转锁。如果您使用了一个新的
NSOperationQueue
,它只需创建一个新线程,仅用于该“操作队列”,并为您提供更多控制。顺便说一句,为什么投反对票?对不起,我不知道我投了反对票。我不理解NSOperationQueue(我的错,我知道),所以我尝试不再使用
[[NSData alloc]initWithContentsOfURL:mediaObject.standardResolutionImageURL]
,而是使用
NSURLConnectionLegate
。我不知道这是否会带来一个好的解决方案,但至少我了解这件事。吉安卢卡:看来你是对的
initWithContentsOfURL
有时会阻塞。现在我使用
NSOperationQueue
并每次分配一个新队列。我的前两次测试进行得很顺利,但OSSpinLockLock发生在最奇怪的时刻。我必须进行更多的测试,看看它是否真的是解决方案。[我没有投反对票,顺便说一句,我甚至投了赞成票,但肯定有其他人投了反对票,使差额为0]。