All Projects → dmytro-anokhin → Url Image

dmytro-anokhin / Url Image

Licence: mit
Asynchronous image loading in SwiftUI. Lightweight, pure SwiftUI Image view, that displays an image downloaded from URL, with auxiliary views and local cache.

Programming Languages

swift
15916 projects

Projects that are alternatives of or similar to Url Image

Lightning
A Swift Multiplatform Single-threaded Non-blocking Web and Networking Framework
Stars: ✭ 312 (-58.23%)
Mutual labels:  swift-package-manager
Komondor
Git Hooks for Swift projects 🐩
Stars: ✭ 450 (-39.76%)
Mutual labels:  swift-package-manager
Mongokitten
Native MongoDB driver for Swift, written in Swift
Stars: ✭ 605 (-19.01%)
Mutual labels:  swift-package-manager
Ice
❄️ A developer friendly package manager for Swift; 100% compatible with Swift Package Manager
Stars: ✭ 344 (-53.95%)
Mutual labels:  swift-package-manager
Swiftsunburstdiagram
SwiftUI library to easily render diagrams given a tree of objects. Similar to ring chart, sunburst chart, multilevel pie chart.
Stars: ✭ 400 (-46.45%)
Mutual labels:  swift-package-manager
Keyboardshortcuts
Add user-customizable global keyboard shortcuts to your macOS app in minutes
Stars: ✭ 500 (-33.07%)
Mutual labels:  swift-package-manager
Functionkit
A framework for functional types and operations designed to fit naturally into Swift.
Stars: ✭ 302 (-59.57%)
Mutual labels:  swift-package-manager
Zephyr
Effortlessly synchronize UserDefaults over iCloud.
Stars: ✭ 722 (-3.35%)
Mutual labels:  swift-package-manager
Tweetextfield
Lightweight set of text fields with nice animation and functionality. 🚀 Inspired by https://uimovement.com/ui/2524/input-field-help/
Stars: ✭ 421 (-43.64%)
Mutual labels:  swift-package-manager
Sablurimageview
You can use blur effect and it's animation easily to call only two methods.
Stars: ✭ 538 (-27.98%)
Mutual labels:  swift-package-manager
Xcbeautify
A little beautifier tool for xcodebuild
Stars: ✭ 372 (-50.2%)
Mutual labels:  swift-package-manager
Siren
Siren checks a user's currently installed version of your iOS app against the version that is currently available in the App Store.
Stars: ✭ 3,892 (+421.02%)
Mutual labels:  swift-package-manager
Openssl
OpenSSL package for SPM, CocoaPod, and Carthage, for iOS and macOS
Stars: ✭ 515 (-31.06%)
Mutual labels:  swift-package-manager
Swift5 Module Template
An opinionated starting point for awesome, reusable Swift 5 modules
Stars: ✭ 331 (-55.69%)
Mutual labels:  swift-package-manager
Guitar
A Cross-Platform String and Regular Expression Library written in Swift.
Stars: ✭ 641 (-14.19%)
Mutual labels:  swift-package-manager
Swiftweekly.github.io
A community-driven weekly newsletter about Swift.org
Stars: ✭ 305 (-59.17%)
Mutual labels:  swift-package-manager
Brisk
A proof of concept scripting library for Swift
Stars: ✭ 478 (-36.01%)
Mutual labels:  swift-package-manager
Defaults
Swifty and modern UserDefaults
Stars: ✭ 734 (-1.74%)
Mutual labels:  swift-package-manager
Mapbox Navigation Ios
Turn-by-turn navigation logic and UI in Swift on iOS
Stars: ✭ 677 (-9.37%)
Mutual labels:  swift-package-manager
Swiftframeworktemplate
A template for new Swift iOS / macOS / tvOS / watchOS Framework project ready with travis-ci, cocoapods, Carthage, SwiftPM and a Readme file
Stars: ✭ 527 (-29.45%)
Mutual labels:  swift-package-manager

URLImage

Follow me on Twitter

URLImage is a SwiftUI view that displays an image downloaded from provided URL. URLImage manages downloading remote image and caching it locally, both in memory and on disk, for you.

Using URLImage is dead simple:

URLImage(url: url) { image in
    image
        .resizable()
        .aspectRatio(contentMode: .fit)
}

Take a look at some examples in the demo app.

Table of Contents

Features

  • SwiftUI image view for remote images;
  • Local image cache;
  • Fully customizable including placeholder, progress indication, error, and the image view;
  • Control over various download aspects for better performance.

Installation

URLImage can be installed using Swift Package Manager or CocoaPods.

Using Swift Package Manager

Use the package URL to search for the URLImage package: https://github.com/dmytro-anokhin/url-image.

For how-to integrate package dependencies refer to Adding Package Dependencies to Your App documentation.

Using Cocoa Pods

Add the URLImage pod to your Podfile:

pod 'URLImage'

Refer to https://cocoapods.org for information on setup Cocoa Pods for your project.

Usage

Basics

URLImage expects URL of the image and the content view:

import URLImage // Import the package module

URLImage(url: url,
         content: { image in
             image
                 .resizable()
                 .aspectRatio(contentMode: .fit)
         })

States

URLImage transitions between 4 states:

  • Empty state, when download has not started yet, or there is nothing to display;
  • In Progress state to indicate download process;
  • Failure state in case there is an error;
  • Content to display the image.

Each of this states has a separate view that can be provided using closures. You can also customize certain settings, like cache policy and expiry interval, using URLImageOptions.

struct MyView: View {

    let url: URL
    let id: UUID

    init(url: URL, id: UUID) {
        self.url = url
        self.id = id

        formatter = NumberFormatter()
        formatter.numberStyle = .percent
    }
    
    private let formatter: NumberFormatter // Used to format download progress as percentage. Note: this is only for example, better use shared formatter to avoid creating it for every view.
    
    var body: some View {
        URLImage(url: url,
                 options: URLImageOptions(
                    identifier: id.uuidString,      // Custom identifier
                    expireAfter: 300.0,             // Expire after 5 minutes
                    cachePolicy: .returnCacheElseLoad(cacheDelay: nil, downloadDelay: 0.25) // Return cached image or download after delay 
                 ),
                 empty: {
                    Text("Nothing here")            // This view is displayed before download starts
                 },
                 inProgress: { progress -> Text in  // Display progress
                    if let progress = progress {
                        return Text(formatter.string(from: progress as NSNumber) ?? "Loading...")
                    }
                    else {
                        return Text("Loading...")
                    }
                 },
                 failure: { error, retry in         // Display error and retry button
                    VStack {
                        Text(error.localizedDescription)
                        Button("Retry", action: retry)
                    }
                 },
                 content: { image in                // Content view
                    image
                        .resizable()
                        .aspectRatio(contentMode: .fit)
                 })
    }
}

Image Information

You can use init(url: URL, content: @escaping (_ image: Image, _ info: ImageInfo) -> Content) initializer if you need information about an image, like size, or access the underlying CGImage object.

Cache

URLImage uses two caches:

  • In memory cache for quick access;
  • Local disk cache.

Downloaded images stored in user caches folder. This allows OS to take care of cleaning up files. It is also a good idea to perform manual cleanup time to time.

You can remove expired images by calling cleanup as a part of your startup routine. This will also remove image files from the previous URLImage version if you used it.

URLImageService.shared.cleanup()

Downloaded images expire after some time. Expired images removed in cleanup routine. Expiry interval can be set using expiryInterval property of URLImageOptions.

You can also remove individual or all cached images using URLImageService.

Using URLCache

Alternatively you can use URLCache. You can configure the package globally and also per view.

URLImageService.shared.defaultOptions.cachePolicy = .useProtocol

// Download using `URLSessionDataTask` 
URLImageService.shared.defaultOptions.loadOptions.formUnion(.inMemory)

// Set your `NSURLRequest.CachePolicy`
URLImageService.shared.defaultOptions.urlRequestConfiguration.cachePolicy = .returnCacheDataElseLoad

Using URLCache adds support for Cache-Control header. As a trade-off you lose some control, like in-memory caching, download delays, expiry intervals (you get it with Cache-Control header). It also only works for in-memory downloads (using URLSessionDataTask).

Options

URLImage allows controlling various aspects of download and cache using URLImageOptions structure. You can set default options using URLImageService.shared.defaultOptions property. Here are the main settings:

identifier: String?

By default an image is identified by its URL. Alternatively, you can provide a string identifier to override this.

expiryInterval: TimeInterval?

Time interval after which the cached image expires and can be deleted. Images are deleted as part of cleanup routine described in Cache paragraph.

maxPixelSize: CGSize?

Maximum size of a decoded image in pixels. If this property is not specified, the width and height of a decoded is not limited and may be as big as the image itself.

cachePolicy: CachePolicy

The cache policy controls how the image loaded from cache.

Cache Policy

Cache policy, URLImageOptions.CachePolicy type, allows to specify how URLImage utilizes it's cache, similar to NSURLRequest.CachePolicy. This type also allows to specify delays for accessing disk cache and starting download.

returnCacheElseLoad

Return an image from cache or download it.

returnCacheDontLoad

Return an image from cache, do not download it.

ignoreCache

Ignore cached image and download remote one.


Some options are can be set globally using URLImageService.shared.defaultOptions property. Those are set by default:

  • expireAfter to 24 hours;
  • cachePolicy to returnCacheElseLoad without delays;
  • maxPixelSize to 1000 by 1000 pixels (300 by 300 pixels for watchOS).

Fetching an Image

You may want to download an image without a view. This is possible using the RemoteImagePublisher object. The RemoteImagePublisher can cache images for future use by the URLImage view.

Download an image as CGImage and ignore any errors:

cancellable = URLImageService.shared.remoteImagePublisher(url)
    .tryMap { $0.cgImage }
    .catch { _ in
        Just(nil)
    }
    .sink { image in
        // image is CGImage or nil
    }

Download multiple images as an array of [CGImage?]:

let publishers = urls.map { URLImageService.shared.remoteImagePublisher($0) }

cancellable = Publishers.MergeMany(publishers)
    .tryMap { $0.cgImage }
    .catch { _ in
        Just(nil)
    }
    .collect()
    .sink { images in
        // images is [CGImage?]
    }

When downloading image using the RemoteImagePublisher object all options apply as they do for the URLImage object. Be default downloaded image will be cached on the disk. This can speedup displaying images on later stage of your app. Also, this is currently the only supported way to display images in iOS 14 widgets.

Download an Image in iOS 14 Widget

Unfortunately views in WidgetKit can not run asynchronous operations: https://developer.apple.com/forums/thread/652581. The recommended way is to load your content, including images, in TimelineProvider.

You can still use URLImage for this. The idea is that you load image in TimelineProvider using the RemoteImagePublisher object, and display it in the URLImage view.

Reporting a Bug

Use GitHub issues to report a bug. Include this information when possible:

Summary and/or background; OS and what device you are using; Version of URLImage library; What you expected would happen; What actually happens; Additional information: Screenshots or video demonstrating a bug; Crash log; Sample code, try isolating it so it compiles without dependancies; Test data: if you use public resource provide URLs of the images.

Please make sure there is a reproducible scenario. Ideally provide a sample code. And if you submit a sample code - make sure it compiles ;)

Requesting a Feature

Use GitHub issues to request a feature.

Contributing

Contributions are welcome. Please create a GitHub issue before submitting a pull request to plan and discuss implementation.

Note that the project description data, including the texts, logos, images, and/or trademarks, for each open source project belongs to its rightful owner. If you wish to add or remove any projects, please contact us at [email protected].