Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/ios/119.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ios 准备在背景线程上有很多层的UIImage_Ios_Iphone_Objective C - Fatal编程技术网

Ios 准备在背景线程上有很多层的UIImage

Ios 准备在背景线程上有很多层的UIImage,ios,iphone,objective-c,Ios,Iphone,Objective C,我有一个问题,我有一些非常大的UIScrollView和吨的图像加载在它作为用户滚动。图像存储在设备上,但我从服务器接收到要在UIScrollView的特定部分显示的信息。当用户滚动一点时,我需要在新位置显示图像,因为我无法在启动时用图像绘制整个UIScrollView。对于背景,我有一个相对较小的图像,在整个视图中移动。但问题是,在这个背景之上,我应该画出很多UIImage对象,包括300-400,它们不是特别的波黑,而是在层上分开的,一个图像在另一个图像上,一个图像在另一个图像上,等等。。绘

我有一个问题,我有一些非常大的UIScrollView和吨的图像加载在它作为用户滚动。图像存储在设备上,但我从服务器接收到要在UIScrollView的特定部分显示的信息。当用户滚动一点时,我需要在新位置显示图像,因为我无法在启动时用图像绘制整个UIScrollView。对于背景,我有一个相对较小的图像,在整个视图中移动。但问题是,在这个背景之上,我应该画出很多UIImage对象,包括300-400,它们不是特别的波黑,而是在层上分开的,一个图像在另一个图像上,一个图像在另一个图像上,等等。。绘图时阻止滚动不是一个选项

现在我正试图决定哪种方法最适合我:

将所有需要的图像添加到背景线程上的UIView中,然后将UIView添加到主线程上的ScrollView中,希望不会花费太长时间。在这里,当滚动到某个地方时,我需要计算并创建带有对象的新UIView,并将其放置在现有UIView旁边,最终在用户继续向某个方向滚动时删除带有所有对象和图层的第一个UIView

将图像中的所有层与CoreGraphics结合起来,并将其显示为具有已确定层的对象。通过这种方式,我可以从滚动视图中删除特定的objectimage。当用户滚动时,我只需创建新对象并将它们作为完整对象添加到视图中,并且可以在用户滚动足够多而不是删除整个视图时删除对象。这里的问题是在主线程上向UIScrollView添加多个对象,但是当它们组合在一起时,它们不会超过15-20个对象

我最关心的是性能和线程。正如我所说的,我不能阻止主线程,或者说在用户会注意到的时间内不能阻止主线程,也不能在我的图形部门合并图像,因为它们有大量的变量,这些变量是在运行时决定的。这就是为什么我在想一种在后台线程上准备数据的方法,只是在主线程上快速添加数据,而不是在主线程上准备和添加数据,这样会阻塞UI

我们将非常感谢您的每一个帮助

问候,


hr.要查看如何使用CATiledLayer作为UIView背景。它就是为此而设计的


我有一个在UIScrollView中有一个UIView的地图,并且UIView的大小与整个地图的大小相同。CATiledLayer控制何时绘制视图的每个平铺

好的,我在这里写信只是想让你知道我如何解决我的问题

主要的问题是,我在滚动时移动了背景图片,所以我没有加载一个巨大的文件,而在这样做时,我从服务器获取信息,并尝试在相同的分幅上绘制,这会导致系统崩溃,并导致众所周知的崩溃:

CALayer was muted while enumerated
我依赖于performSelector方法和@synchronized,但结果证明这是无效的,有时两个线程主UI线程和后台线程试图在屏幕上更改相同的分幅。因此,基本上我所做的是更改背景提取和绘制:

[self performSelectorOnBackgroundThread]
要使用我存储引用的具体背景线程,请执行以下操作:

@property(nonatomic, strong) NSThread* backgroundThread;
现在,每次我需要加载新的磁贴或移动背景时,我都会取消此线程,并确保在开始任何其他操作之前取消它。另外,在使用此线程的视图和其他视图之间切换时出现了一个小问题,因为我的线程挂起,我需要设置一个超时:

[_backgroundThread cancel];

int currentAttempts = 0;
while( [_backgroundThread isExecuting] )
{
    if( currentAttempts == MAX_ATTEMPTS_TO_CANCEL_THREAD )
    {
        //make sure we dont hang and force background
        _backgroundThread = nil;
        return;
    }

    [_backgroundThread cancel];
    currentAttempts++;
}
然而,在我的“scrollViewDidScroll”中,我没有使用递归,因为这会导致在旧设备(如iPhone 4)上滚动时出现轻微的UI块,这是不可接受的。因此,我基本上只是取消了线程,并希望尽快取消,这与几十个测试似乎正在工作:

- (void)scrollViewDidScroll:(UIScrollView*)scrollView
{
    [_backgroundThread cancel];

    //move background around
    [self moveBackground];
}
这种方法的缺点是,您需要在后台线程中进行大量检查,因为调用“取消”实际上不会取消任何操作。根据apple docs,它只会更改线程的isCancelled状态,您有责任使该线程以与正常退出基本相同的方式退出,这样系统就有机会在您的线程之后进行清理:

if( [_backgroundThread isCancelled] )
{
    return;
}
问候,


hris.to

请不要使用堆栈溢出通过链接推广您的网站;答案应该只包括相关代码,而不是其他网站的链接。@LittleBobbyTables感谢您的提醒!我一定不会再这样做了。