我正在尝试在后台线程中加载UIImages,然后在iPad上显示它们.但是,当我将imageViews的视图属性设置为图像时,会出现断断续续的情况.我很快发现iOS上的图像加载是懒惰的,并且在这个问题中找到了部分解决方案:
在UI线程上懒洋洋地加载CGImage/UIImage会导致口吃
这实际上会强制图像加载到线程中,但在显示图像时仍然存在断断续续的情况.
你可以在这里找到我的示例项目:http://www.jasamer.com/files/SwapTest.zip(编辑:修复版),检查SwapTestViewController.尝试拖动图片以查看口吃.
我创建的测试代码是断断续续的(forceLoad方法是我从上面发布的堆栈溢出问题中获取的方法):
NSArray* imagePaths = [NSArray arrayWithObjects:
[[NSBundle mainBundle] pathForResource: @"a.png" ofType: nil],
[[NSBundle mainBundle] pathForResource: @"b.png" ofType: nil], nil];
NSOperationQueue* queue = [[NSOperationQueue alloc] init];
[queue addOperationWithBlock: ^(void) {
int imageIndex = 0;
while (true) {
UIImage* image = [[UIImage alloc] initWithContentsOfFile: [imagePaths objectAtIndex: imageIndex]];
imageIndex = (imageIndex+1)%2;
[image forceLoad];
//What's missing here?
[self performSelectorOnMainThread: @selector(setImage:) withObject: image waitUntilDone: YES];
[image release];
}
}];
Run Code Online (Sandbox Code Playgroud)
我知道可以避免口吃的原因有两个:
(1)Apple可以在照片应用中加载图像而不会出现断断续续的情况
(2)在上述代码的此修改版本中,placeholder1和placeholder2已显示一次后,此代码不会导致断断续续:
UIImage* placeholder1 = …Run Code Online (Sandbox Code Playgroud) 在我目前正在处理的应用程序中,有一个嵌套的集合视图设置.外部集合视图包含可垂直滚动的大单元格,每个单元格包含另一个具有较小单元格的集合视图(子集合视图中的布局不同,这就是为什么有多个单元格).
在视觉上,一切正常,但我遇到了Voice Over的一个问题:当我到达第一个子集合视图中的最后一个项目(即外部集合视图的第一个单元格的最后一项)时,我不能通过滑动选择下一个项目.相反,iOS会将声音视为最后一个项目.
我可以用三指滑动向下滚动,然后选择下一个元素,但这显然不是必需的.选择最后一个元素并按相反顺序返回可以按预期工作.
只有当一个单元格(外部集合视图)最初可见时,才会出现这个问题.如果可以看到多个单元格,一切正常.但是,我无法更改外部单元格的大小,因为这会完全改变布局.
我在下面创建了一个示例视图控制器来演示该问题.除了单元格的大小之外,项目中的两个集合视图是相同的.具有较小单元格的第一个集合视图按预期工作.第二个没有(当选择下一个单元格时,iOS会在选择最后一个可见单元格时播放"嘟嘟"声,即使有更多单元格进一步向下).
所以,我的问题是:
我到目前为止尝试的解决方案:
编辑:演示此问题的ViewController的完整代码:
class ViewController: UIViewController, UICollectionViewDataSource {
let outerCollectionView = UICollectionView(frame: CGRect(x: 0, y: 40, width: 320, height: 250), collectionViewLayout: UICollectionViewFlowLayout())
override func viewDidLoad() {
super.viewDidLoad()
view.backgroundColor = .green
outerCollectionView.backgroundColor = .blue
(outerCollectionView.collectionViewLayout as! UICollectionViewFlowLayout).itemSize = CGSize(width: 250, height: 300)
outerCollectionView.register(OuterCell.self, forCellWithReuseIdentifier: "outerCell")
view.addSubview(outerCollectionView)
outerCollectionView.dataSource = self
}
func numberOfSections(in collectionView: UICollectionView) -> Int { return 1 }
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int { …Run Code Online (Sandbox Code Playgroud)