Skip to content

Instantly share code, notes, and snippets.

@fumoboy007
Created November 9, 2015 01:47
Show Gist options
  • Save fumoboy007/d869e66ad0466a9c246d to your computer and use it in GitHub Desktop.
Save fumoboy007/d869e66ad0466a9c246d to your computer and use it in GitHub Desktop.
A UIImageView subclass that loads images from your app bundle completely off the main thread.
public class AsyncImageView: UIImageView {
private class ImageLoadOperation {
private(set) var isCancelled: Bool = false
func cancel() {
isCancelled = true
}
}
private var imageLoadOperation: ImageLoadOperation?
private func cancel() {
if let imageLoadOperation = imageLoadOperation {
imageLoadOperation.cancel()
self.imageLoadOperation = nil
}
}
override public var image: UIImage? {
willSet {
cancel()
}
}
public func loadImageNamed(name: String) {
cancel()
let pathToImageOrNil = AsyncImageView.pathToImageNamed(name)
guard let pathToImage = pathToImageOrNil else {
super.image = nil
return
}
let imageLoadOperation = ImageLoadOperation()
self.imageLoadOperation = imageLoadOperation
dispatch_async(dispatch_get_global_queue(QOS_CLASS_USER_INTERACTIVE, 0)) {
let imageOrNil = UIImage(contentsOfFile: pathToImage)
guard let image = imageOrNil else {
return
}
let decodedImage = AsyncImageView.decodeImage(image)
dispatch_async(dispatch_get_main_queue()) {
guard !imageLoadOperation.isCancelled else {
return
}
super.image = decodedImage
}
}
}
private static func pathToImageNamed(name: String) -> String? {
let screenScale = UIScreen.mainScreen().scale
var resourceNames = [String]()
switch screenScale {
case 3:
resourceNames.append(name + "@3x")
fallthrough
case 2:
resourceNames.append(name + "@2x")
fallthrough
case 1:
resourceNames.append(name)
default:
break
}
for resourceName in resourceNames {
if let pathToImage = NSBundle.mainBundle().pathForResource(resourceName, ofType: "png") {
return pathToImage
}
}
return nil
}
private static func decodeImage(image: UIImage) -> UIImage {
UIGraphicsBeginImageContextWithOptions(image.size, false, image.scale)
defer {
UIGraphicsEndImageContext()
}
image.drawAtPoint(CGPoint.zero)
return UIGraphicsGetImageFromCurrentImageContext()
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment