Convert Figma logo to code with AI

pinterest logoPINRemoteImage

A thread safe, performant, feature rich image fetcher

4,007
510
4,007
57

Top Related Projects

Asynchronous image downloader with cache support as a UIImageView category

A lightweight, pure-Swift library for downloading and caching images from the web.

AlamofireImage is an image component library for Alamofire

8,040

Image loading system

Promises for Swift & ObjC.

A delightful networking framework for iOS, macOS, watchOS, and tvOS.

Quick Overview

PINRemoteImage is a powerful image downloading, processing, and caching library for iOS and macOS. It provides a simple, fast, and memory-efficient solution for handling remote images in applications, with support for progressive image loading and animated GIFs.

Pros

  • High performance and memory efficiency
  • Supports progressive image loading and animated GIFs
  • Extensive customization options and filters
  • Thread-safe and optimized for multi-core devices

Cons

  • Primarily focused on Apple platforms (iOS and macOS)
  • Learning curve for advanced features and customizations
  • Limited documentation for some less common use cases
  • Dependency on PINCache for caching functionality

Code Examples

  1. Basic image download and display:
imageView.pin_setImage(from: URL(string: "https://example.com/image.jpg"))
  1. Setting a placeholder image and custom processor:
imageView.pin_setImage(from: URL(string: "https://example.com/image.jpg"), placeholderImage: UIImage(named: "placeholder"), processor: { result in
    return result.image.applying(someFilter)
})
  1. Prefetching images:
PINRemoteImageManager.shared().prefetchImages(with: [URL(string: "https://example.com/image1.jpg")!, URL(string: "https://example.com/image2.jpg")!])
  1. Cancelling an image download:
imageView.pin_cancelImageDownload()

Getting Started

  1. Install PINRemoteImage using CocoaPods by adding the following to your Podfile:
pod 'PINRemoteImage'
  1. Import the library in your Swift file:
import PINRemoteImage
  1. Use PINRemoteImage to download and display an image:
let imageView = UIImageView()
imageView.pin_setImage(from: URL(string: "https://example.com/image.jpg"))
  1. For more advanced usage, refer to the library's documentation and examples on GitHub.

Competitor Comparisons

Asynchronous image downloader with cache support as a UIImageView category

Pros of SDWebImage

  • More mature and widely adopted project with a larger community
  • Supports a broader range of image formats, including GIF and WebP
  • Offers more extensive caching options and customization

Cons of SDWebImage

  • Slightly larger library size, which may impact app size
  • Can be more complex to set up and configure for advanced use cases

Code Comparison

SDWebImage:

let imageView = UIImageView()
imageView.sd_setImage(with: URL(string: "https://example.com/image.jpg"))

PINRemoteImage:

let imageView = UIImageView()
imageView.pin_setImage(from: URL(string: "https://example.com/image.jpg"))

Both libraries offer similar ease of use for basic image loading, with nearly identical syntax. The main differences lie in their advanced features and customization options.

SDWebImage provides more built-in functionality for complex scenarios, while PINRemoteImage focuses on simplicity and performance. SDWebImage's larger feature set comes at the cost of a slightly larger library size, which may be a consideration for projects with strict size constraints.

Ultimately, the choice between these libraries depends on the specific requirements of your project, such as supported image formats, caching needs, and desired level of customization.

A lightweight, pure-Swift library for downloading and caching images from the web.

Pros of Kingfisher

  • Written in Swift, providing better performance and type safety for Swift projects
  • More extensive caching options, including memory and disk caching with customizable expiration times
  • Supports image processing and filtering out of the box

Cons of Kingfisher

  • Limited support for older iOS versions compared to PINRemoteImage
  • May have a steeper learning curve for developers new to Swift

Code Comparison

Kingfisher:

let url = URL(string: "https://example.com/image.jpg")
imageView.kf.setImage(with: url)

PINRemoteImage:

[imageView pin_setImageFromURL:[NSURL URLWithString:@"https://example.com/image.jpg"]];

Both libraries offer simple one-line methods for setting images from URLs, but Kingfisher's Swift syntax is more concise and type-safe.

Additional Considerations

  • PINRemoteImage is written in Objective-C, making it more suitable for projects with legacy code or requiring Objective-C compatibility
  • Kingfisher has a more active community and frequent updates
  • PINRemoteImage offers better support for animated GIFs and progressive image loading
  • Kingfisher provides easier integration with SwiftUI through its KFImage view

When choosing between these libraries, consider your project's language requirements, target iOS versions, and specific image loading needs.

AlamofireImage is an image component library for Alamofire

Pros of AlamofireImage

  • Seamless integration with Alamofire networking library
  • Built-in support for image filters and transformations
  • Extensive documentation and active community support

Cons of AlamofireImage

  • Limited to iOS and macOS platforms
  • Requires Alamofire as a dependency, which may increase app size
  • May have slightly higher memory usage for large image sets

Code Comparison

PINRemoteImage:

imageView.pin_setImage(from: URL(string: "https://example.com/image.jpg"))

AlamofireImage:

imageView.af.setImage(withURL: URL(string: "https://example.com/image.jpg"))

Both libraries offer simple one-line methods for setting images from URLs. PINRemoteImage uses the pin_setImage method, while AlamofireImage uses the af.setImage method.

PINRemoteImage provides a more platform-agnostic solution, supporting iOS, macOS, and tvOS. It also offers features like progressive image loading and a robust caching system. On the other hand, AlamofireImage excels in its tight integration with Alamofire and provides built-in image manipulation capabilities.

Choose PINRemoteImage for a versatile, cross-platform solution with advanced features like progressive loading. Opt for AlamofireImage if you're already using Alamofire in your project and need seamless integration with powerful image processing capabilities.

8,040

Image loading system

Pros of Nuke

  • Written in Swift, providing better performance and type safety for Swift projects
  • Offers a more modern API with support for SwiftUI and Combine
  • Smaller codebase, making it easier to maintain and integrate

Cons of Nuke

  • Less mature compared to PINRemoteImage, which may result in fewer edge cases being handled
  • Lacks some advanced features like progressive image loading and WebP support out of the box

Code Comparison

PINRemoteImage:

[imageView pin_setImageFromURL:url];

Nuke:

Nuke.loadImage(with: url, into: imageView)

Both libraries offer simple one-line methods for loading images, but Nuke's API is more Swift-friendly and integrates better with modern iOS development practices.

PINRemoteImage provides more granular control over the image loading process, while Nuke focuses on simplicity and ease of use. Nuke's integration with SwiftUI makes it a strong choice for newer projects, while PINRemoteImage's maturity and extensive feature set may be preferred for larger, more complex applications.

Promises for Swift & ObjC.

Pros of PromiseKit

  • Provides a more general-purpose asynchronous programming solution
  • Offers a cleaner and more readable syntax for handling complex asynchronous operations
  • Supports a wide range of use cases beyond image loading

Cons of PromiseKit

  • May have a steeper learning curve for developers unfamiliar with promises
  • Potentially higher overhead for simple tasks like image loading
  • Less specialized for image-specific optimizations

Code Comparison

PINRemoteImage:

imageView.pin_setImage(from: URL(string: "https://example.com/image.jpg"))

PromiseKit:

firstly {
    URLSession.shared.dataTask(.promise, with: URL(string: "https://example.com/image.jpg")!)
}.map { data, _ in
    UIImage(data: data)!
}.done { image in
    imageView.image = image
}.catch { error in
    print("Error: \(error)")
}

PINRemoteImage is more concise for simple image loading tasks, while PromiseKit offers a more flexible approach for handling complex asynchronous operations. PINRemoteImage is specifically optimized for image loading and caching, whereas PromiseKit provides a general-purpose solution for managing asynchronous code. The choice between the two depends on the specific requirements of your project and the complexity of the tasks you need to perform.

A delightful networking framework for iOS, macOS, watchOS, and tvOS.

Pros of AFNetworking

  • More comprehensive networking library, offering features beyond image loading
  • Well-established and widely adopted in the iOS development community
  • Supports a broader range of networking tasks, including RESTful API interactions

Cons of AFNetworking

  • Larger and more complex, which may lead to increased app size
  • Not specifically optimized for image loading and caching
  • May require more setup and configuration for image-specific tasks

Code Comparison

AFNetworking:

[imageView setImageWithURL:[NSURL URLWithString:@"http://example.com/image.jpg"]
          placeholderImage:[UIImage imageNamed:@"placeholder"]];

PINRemoteImage:

[imageView pin_setImageFromURL:[NSURL URLWithString:@"http://example.com/image.jpg"]];

Summary

AFNetworking is a more comprehensive networking library suitable for various tasks, while PINRemoteImage focuses specifically on efficient image loading and caching. AFNetworking offers broader functionality but may be overkill for projects primarily concerned with image handling. PINRemoteImage provides a simpler, more targeted solution for image-related tasks, potentially offering better performance in this specific area. The choice between the two depends on the project's requirements and the developer's preference for a specialized tool versus a more general-purpose library.

Convert Figma logo designs to code with AI

Visual Copilot

Introducing Visual Copilot: A new AI model to turn Figma designs to high quality code using your components.

Try Visual Copilot

README

PINRemoteImage

Fast, non-deadlocking parallel image downloader and cache for iOS

CocoaPods compatible Carthage compatible Build status

PINRemoteImageManager is an image downloading, processing and caching manager. It uses the concept of download and processing tasks to ensure that even if multiple calls to download or process an image are made, it only occurs one time (unless an item is no longer in the cache). PINRemoteImageManager is backed by GCD and safe to access from multiple threads simultaneously. It ensures that images are decoded off the main thread so that animation performance isn't affected. None of its exposed methods allow for synchronous access. However, it is optimized to call completions on the calling thread if an item is in its memory cache.

PINRemoteImage supports downloading many types of files. It, of course, supports both PNGs and JPGs. It also supports decoding WebP images if Google's library is available. It even supports GIFs and Animated WebP via PINAnimatedImageView.

PINRemoteImage also has two methods to improve the experience of downloading images on slow network connections. The first is support for progressive JPGs. This isn't any old support for progressive JPGs though: PINRemoteImage adds an attractive blur to progressive scans before returning them.

Progressive JPG with Blur

PINRemoteImageCategoryManager defines a protocol which UIView subclasses can implement and provide easy access to PINRemoteImageManager's methods. There are built-in categories on UIImageView, PINAnimatedImageView and UIButton, and it's very easy to implement a new category. See [UIImageView+PINRemoteImage](/Pod/Classes/Image Categories/UIImageView+PINRemoteImage.h) of the existing categories for reference.

Download an image and set it on an image view:

Objective-C

UIImageView *imageView = [[UIImageView alloc] init];
[imageView pin_setImageFromURL:[NSURL URLWithString:@"http://pinterest.com/kitten.jpg"]];

Swift

let imageView = UIImageView()
imageView.pin_setImage(from: URL(string: "https://pinterest.com/kitten.jpg")!)

Download a progressive jpeg and get attractive blurred updates:

Objective-C

UIImageView *imageView = [[UIImageView alloc] init];
[imageView setPin_updateWithProgress:YES];
[imageView pin_setImageFromURL:[NSURL URLWithString:@"http://pinterest.com/progressiveKitten.jpg"]];

Swift

let imageView = UIImageView()
imageView.pin_updateWithProgress = true
imageView.pin_setImage(from: URL(string: "https://pinterest.com/progressiveKitten.jpg")!)

Download a WebP file

Objective-C

UIImageView *imageView = [[UIImageView alloc] init];
[imageView pin_setImageFromURL:[NSURL URLWithString:@"http://pinterest.com/googleKitten.webp"]];

Swift

let imageView = UIImageView()
imageView.pin_setImage(from: URL(string: "https://pinterest.com/googleKitten.webp")!)

Download a GIF and display with PINAnimatedImageView

Objective-C

PINAnimatedImageView *animatedImageView = [[PINAnimatedImageView alloc] init];
[animatedImageView pin_setImageFromURL:[NSURL URLWithString:@"http://pinterest.com/flyingKitten.gif"]];

Swift

let animatedImageView = PINAnimatedImageView()
animatedImageView.pin_setImage(from: URL(string: "http://pinterest.com/flyingKitten.gif")!)

Download and process an image

Objective-C

UIImageView *imageView = [[UIImageView alloc] init];
[self.imageView pin_setImageFromURL:[NSURL URLWithString:@"https://i.pinimg.com/736x/5b/c6/c5/5bc6c5387ff6f104fd642f2b375efba3.jpg"] processorKey:@"rounded" processor:^UIImage *(PINRemoteImageManagerResult *result, NSUInteger *cost)
 {
     CGSize targetSize = CGSizeMake(200, 300);
     CGRect imageRect = CGRectMake(0, 0, targetSize.width, targetSize.height);
     UIGraphicsBeginImageContext(imageRect.size);
     UIBezierPath *bezierPath = [UIBezierPath bezierPathWithRoundedRect:imageRect cornerRadius:7.0];
     [bezierPath addClip];

     CGFloat sizeMultiplier = MAX(targetSize.width / result.image.size.width, targetSize.height / result.image.size.height);

     CGRect drawRect = CGRectMake(0, 0, result.image.size.width * sizeMultiplier, result.image.size.height * sizeMultiplier);
     if (CGRectGetMaxX(drawRect) > CGRectGetMaxX(imageRect)) {
         drawRect.origin.x -= (CGRectGetMaxX(drawRect) - CGRectGetMaxX(imageRect)) / 2.0;
     }
     if (CGRectGetMaxY(drawRect) > CGRectGetMaxY(imageRect)) {
         drawRect.origin.y -= (CGRectGetMaxY(drawRect) - CGRectGetMaxY(imageRect)) / 2.0;
     }

     [result.image drawInRect:drawRect];

     UIImage *processedImage = UIGraphicsGetImageFromCurrentImageContext();
     UIGraphicsEndImageContext();
     return processedImage;
 }];

Swift

let imageView = FLAnimatedImageView()
imageView.pin_setImage(from: URL(string: "https://i.pinimg.com/736x/5b/c6/c5/5bc6c5387ff6f104fd642f2b375efba3.jpg")!, processorKey: "rounded")  { (result, unsafePointer) -> UIImage? in

    guard let image = result.image else { return nil }

    let radius : CGFloat = 7.0
    let targetSize = CGSize(width: 200, height: 300)
    let imageRect = CGRect(x: 0, y: 0, width: targetSize.width, height: targetSize.height)

    UIGraphicsBeginImageContext(imageRect.size)

    let bezierPath = UIBezierPath(roundedRect: imageRect, cornerRadius: radius)
    bezierPath.addClip()

    let widthMultiplier : CGFloat = targetSize.width / image.size.width
    let heightMultiplier : CGFloat = targetSize.height / image.size.height
    let sizeMultiplier = max(widthMultiplier, heightMultiplier)

    var drawRect = CGRect(x: 0, y: 0, width: image.size.width * sizeMultiplier, height: image.size.height * sizeMultiplier)
    if (drawRect.maxX > imageRect.maxX) {
        drawRect.origin.x -= (drawRect.maxX - imageRect.maxX) / 2
    }
    if (drawRect.maxY > imageRect.maxY) {
        drawRect.origin.y -= (drawRect.maxY - imageRect.maxY) / 2
    }

    image.draw(in: drawRect)

    UIColor.red.setStroke()
    bezierPath.lineWidth = 5.0
    bezierPath.stroke()

    let ctx = UIGraphicsGetCurrentContext()
    ctx?.setBlendMode(CGBlendMode.overlay)
    ctx?.setAlpha(0.5)

    let logo = UIImage(named: "white-pinterest-logo")
    ctx?.scaleBy(x: 1.0, y: -1.0)
    ctx?.translateBy(x: 0.0, y: -drawRect.size.height)

    if let coreGraphicsImage = logo?.cgImage {
        ctx?.draw(coreGraphicsImage, in: CGRect(x: 90, y: 10, width: logo!.size.width, height: logo!.size.height))
    }

    let processedImage = UIGraphicsGetImageFromCurrentImageContext()
    UIGraphicsEndImageContext()

    return processedImage

}

Handle Authentication

Objective-C

[[PINRemoteImageManager sharedImageManager] setAuthenticationChallenge:^(NSURLSessionTask *task, NSURLAuthenticationChallenge *challenge, PINRemoteImageManagerAuthenticationChallengeCompletionHandler aCompletion) {
aCompletion(NSURLSessionAuthChallengePerformDefaultHandling, nil)];

Swift

PINRemoteImageManager.shared().setAuthenticationChallenge { (task, challenge, completion) in
  completion?(.performDefaultHandling, nil)
}

Support for high resolution images

Currently there are two ways PINRemoteImage is supporting high resolution images:

  1. If the URL contains an _2x. or an _3x. postfix it will be automatically handled by PINRemoteImage and the resulting image will be returned at the right scale.
  2. If it's not possible to provide an URL with an _2x. or _3x. postfix, you can also handle it with a completion handler:
NSURL *url = ...;
__weak UIImageView *weakImageView = self.imageView;
[self.imageView pin_setImageFromURL:url completion:^(PINRemoteImageManagerResult * _Nonnull result) {
  CGFloat scale = UIScreen.mainScreen.scale;
  if (scale > 1.0) {
    UIImage *image = result.image;
    weakImageView.image = [UIImage imageWithCGImage:image.CGImage scale:scale orientation:image.imageOrientation];
    }
}];

Set some limits

// cache is an instance of PINCache as long as you haven't overridden defaultImageCache
PINCache *cache = (PINCache *)[[PINRemoteImageManager sharedImageManager] cache];
// Max memory cost is based on number of pixels, we estimate the size of one hundred 600x600 images as our max memory image cache.
[[cache memoryCache] setCostLimit:600 * [[UIScreen mainScreen] scale] * 600 * [[UIScreen mainScreen] scale] * 100];

// ~50 MB
[[cache diskCache] setByteLimit:50 * 1024 * 1024];
// 30 days
[[cache diskCache] setAgeLimit:60 * 60 * 24 * 30];

Installation

CocoaPods

Add PINRemoteImage to your Podfile and run pod install.

If you'd like to use WebP images, add PINRemoteImage/WebP to your Podfile and run pod install.

Carthage

Add github "pinterest/PINRemoteImage" to your Cartfile . See Carthage's readme for more information on integrating Carthage-built frameworks into your project.

Manually

Download the latest tag and drag the Pod/Classes folder into your Xcode project. You must also manually link against PINCache.

Install the docs by double clicking the .docset file under docs/, or view them online at cocoadocs.org

Git Submodule

You can set up PINRemoteImage as a submodule of your repo instead of cloning and copying all the files into your repo. Add the submodule using the commands below and then follow the manual instructions above.

git submodule add https://github.com/pinterest/PINRemoteImage.git
git submodule update --init

Requirements

PINRemoteImage requires iOS 12.0 or greater.

Contact

Garrett Moon @garrettmoon Pinterest

License

Copyright 2015 Pinterest, Inc.

Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.