저는 꽤 많은 사진 (50-200)을 표시하는 응용 프로그램에서 UICollectionView
을 사용하고 있습니다. 예를 들어 사진 응용 프로그램처럼 멋지게 보이게하는 데 문제가 있습니다.많은 이미지 (50-200)로 멋진 UICollectionView를 얻는 방법?
UICollectionViewCell
은 서브 뷰로 UIImageView
입니다. UIImage.imageWithContentsOfFile:
으로 파일 시스템의 이미지를 셀 내부의 UIImageViews에로드하고 있습니다.
지금까지 꽤 많은 접근법을 시도했지만 버그가 있거나 성능 문제가있었습니다.
참고 : RubyMotion을 사용하고 있으므로 Ruby 스타일로 코드 스 니펫을 작성합니다. 모든
먼저, 여기
def collectionView(collection_view, cellForItemAtIndexPath: index_path)
cell = collection_view.dequeueReusableCellWithReuseIdentifier(CELL_IDENTIFIER, forIndexPath: index_path)
image_path = @image_paths[index_path.row]
cell.image = UIImage.imageWithContentsOfFile(image_path)
end
는/최대 스크롤 .. 참조 내 사용자 지정 UICollectionViewCell 클래스 ...
class CustomCell < UICollectionViewCell
def initWithFrame(rect)
super
@image_view = UIImageView.alloc.initWithFrame(self.bounds).tap do |iv|
iv.contentMode = UIViewContentModeScaleAspectFill
iv.clipsToBounds = true
iv.autoresizingMask = UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleWidth
self.contentView.addSubview(iv)
end
self
end
def prepareForReuse
super
@image_view.image = nil
end
def image=(image)
@image_view.image = image
end
end
접근 # 1
간단한 일을 유지입니다 아래로 이것을 사용하여 끔찍한입니다. 그것은 불안정하고 느리다.
접근 # 2
은 ... NSCache를 통해 불안해하고 첫 번째 전체 스크롤 느린 다시def viewDidLoad
...
@images_cache = NSCache.alloc.init
...
end
def collectionView(collection_view, cellForItemAtIndexPath: index_path)
cell = collection_view.dequeueReusableCellWithReuseIdentifier(CELL_IDENTIFIER, forIndexPath: index_path)
image_path = @image_paths[index_path.row]
if cached_image = @images_cache.objectForKey(image_path)
cell.image = cached_image
else
image = UIImage.imageWithContentsOfFile(image_path)
@images_cache.setObject(image, forKey: image_path)
cell.image = image
end
end
, 캐싱의 비트를 추가하지만, 다음에서 매끄러운 항해이다.
접근 # 3
로드 이미지 비동기 (및 캐싱을 유지)
def viewDidLoad
...
@images_cache = NSCache.alloc.init
@image_loading_queue = NSOperationQueue.alloc.init
@image_loading_queue.maxConcurrentOperationCount = 3
...
end
def collectionView(collection_view, cellForItemAtIndexPath: index_path)
cell = collection_view.dequeueReusableCellWithReuseIdentifier(CELL_IDENTIFIER, forIndexPath: index_path)
image_path = @image_paths[index_path.row]
if cached_image = @images_cache.objectForKey(image_path)
cell.image = cached_image
else
@operation = NSBlockOperation.blockOperationWithBlock lambda {
@image = UIImage.imageWithContentsOfFile(image_path)
Dispatch::Queue.main.async do
return unless collectionView.indexPathsForVisibleItems.containsObject(index_path)
@images_cache.setObject(@image, forKey: image_path)
cell = collectionView.cellForItemAtIndexPath(index_path)
cell.image = @image
end
}
@image_loading_queue.addOperation(@operation)
end
end
이 유망 보았다하지만 난 추적 할 수없는 버그가 있습니다. 초기 뷰로드에서는 모든 이미지가 동일한 이미지이고 전체 블록을 다른 이미지로로드 할 때 모든 이미지가로드됩니다. 디버깅을 시도했지만 이해할 수는 없습니다.
나는 또한 Dispatch::Queue.concurrent.async { ... }
와 함께 NSOperation을 대체 해봤지만 같은 것으로 보인다.
제대로 작동하려면 올바른 방법이라고 생각합니다. 좌절에서
접근 # 4
나는이 처음에 조금 느리고 불안해 밝혀졌다
def viewDidLoad
...
@preloaded_images = @image_paths.map do |path|
UIImage.imageWithContentsOfFile(path)
end
...
end
def collectionView(collection_view, cellForItemAtIndexPath: index_path)
cell = collection_view.dequeueReusableCellWithReuseIdentifier(CELL_IDENTIFIER, forIndexPath: index_path)
cell.image = @preloaded_images[index_path.row]
end
... UIImages처럼 사전로드 이미지를 모두하기로 결정 풀 스크롤하지만 그 후 모두 좋다.
요약
사람이 올바른 방향으로 날 지점 수 있다면 그래서, 실제로 가장 감사하게 될 거라고. 사진 앱은 어떻게합니까? 이렇게 잘? 다른 사람에 대한
참고 : [허용 된] 대답은 잘못된 세포에 나타나는 이미지의 내 문제를 해결하지만, 난 여전히도 크기를 해결하기 위해 내 이미지 크기를 조정 한 후 고르지 스크롤을 얻고 있었다. 맨손으로 본질에 내 코드를 스트립 후 나는 UIImage # imageWithContentsOfFile이 범인임을 결국 발견했다. 이 메서드를 사용하여 UIImages 캐시를 미리 예열 했더라도 UIImage는 내부적으로 어떤 종류의 게으른 캐싱을 수행하는 것 같습니다. 여기에 설명 된 솔루션 - stackoverflow.com/a/10664707/71810을 사용하기 위해 캐시 온난화 코드를 업데이트 한 후 마침내 최고 60FPS의 부드러운 스크롤을 보았습니다.
예, 감사합니다. 나는 그것을 보지 못했다고 나는 믿을 수 없다.성능은 아직 스크롤에서 막혀 있지만, 테스트에서 내 이미지가 셀에 비해 너무 크기 때문이라고 생각합니다. – alistairholt
다른 사람을위한 참고 사항 :이 답변은 이미지가 잘못된 셀에 나타나는 문제를 해결했지만 크기를 맞추기 위해 이미지의 크기를 조정 한 후에도 고르지 못한 스크롤이 계속 발생했습니다. 맨손으로 본질에 내 코드를 스트립 후 나는 UIImage # imageWithContentsOfFile이 범인임을 결국 발견했다. 이 메서드를 사용하여 UIImages 캐시를 미리 예열 했더라도 UIImage는 내부적으로 어떤 종류의 게으른 캐싱을 수행하는 것 같습니다. 여기에 설명 된 솔루션을 사용하기 위해 캐시 온난화 코드를 업데이트 한 후 - http://stackoverflow.com/a/10664707/71810 - 마침내 부드러운 ~ 60FPS 스크롤이 발생했습니다. – alistairholt