๐Ÿ๐Ÿฅ“ Lightweight and fast Swift library for image downloading, caching and transformations

Overview

MapleBacon

CI codecov.io Version License Platform Carthage compatible SPM

Introduction

MapleBacon is a lightweight and fast Swift library for downloading and caching images.

Example

The folder Example contains a sample projects for you to try.

Requirements

  • Swift 5.1
  • iOS 10.0+
  • Xcode 10.2+

Installation

MapleBacon is available through CocoaPods. To install add it to your Podfile:

pod "MapleBacon"

Carthage

github "JanGorman/MapleBacon"

and Swift Package Manager.

Usage

UIImageView

The most basic usage is via an extension on UIImageView. You pass it URL:

import MapleBacon

private var imageView: UIImageView!

func someFunc() {
  let url = URL(string: "โ€ฆ")
  imageView.setImage(with: url)
}

If you want to add a placeholder while the image is downloading you specify that like this:

func someFunc() {
  let url = URL(string: "โ€ฆ")
  imageView.setImage(with: url, placeholder: UIImage(named: "placeholder"))
}

If your backend returns images that are not optimised for display, it's good practice to downsample them. MapleBacon comes with support for downsampling via displayOptions:

func someFunc() {
  let url = URL(string: "โ€ฆ")
  imageView.setImage(with: url, displayOptions: .downsampled)
}

Image Transformers

MapleBacon allows you to apply transformations to images and have the results cached so that you app doesn't need to perform the same work over and over. To make your own transformer, create a class conforming to the ImageTransforming protocol. A transform can be anything you like, let's create one that applies a Core Image sepia filter:

private class SepiaImageTransformer: ImageTransforming {

  // The identifier is used as part of the cache key. Make sure it's something unique
  let identifier = "com.schnaub.SepiaImageTransformer"

  func transform(image: UIImage) -> UIImage? {
    let filter = CIFilter(name: "CISepiaTone")!

    let ciImage = CIImage(image: image)
    filter.setValue(ciImage, forKey: kCIInputImageKey)
    filter.setValue(0.5, forKey: kCIInputIntensityKey)

    let context = CIContext()
    guard let outputImage = filter.outputImage,
          let cgImage = context.createCGImage(outputImage, from: outputImage.extent) else {
            return image
    }

    // Return the transformed image which will be cached (or used by another transformer)
    return UIImage(cgImage: cgImage)
  }

}

You then pass this filter to MapleBacon in one of the convenience methods:

let url = URL(string: "โ€ฆ")
let transformer = SepiaImageTransformer()
imageView.setImage(with: url, transformer: transformer)

If you want to apply multiple transforms to an image, you can chain your transformers:

let chainedTransformer = SepiaImageTransformer()
  .appending(transformer: DifferentTransformer())
  .appending(transformer: AnotherTransformer())

Or if you prefer, using the custom >>> operator:

let chainedTransformer = SepiaImageTransformer() >>> DifferentTransformer() >>> AnotherTransformer()

(Keep in mind that if you are using Core Image it might not be optimal to chain individual transformers but rather create one transformer that applies multiple CIFilters in one pass. See the Core Image Programming Guide.)

Caching

MapleBacon will cache your images both in memory and on disk. Disk storage is automatically pruned after a week (taking into account the last access date as well) but you can control the maximum cache time yourself too:

let oneDaySeconds: TimeInterval = 60 * 60 * 24
MapleBacon.default.maxCacheAgeSeconds = oneDaySeconds

Combine

On iOS13 and above, you can use Combine to fetch images from MapleBacon

MapleBacon.shared.image(with: url)
  .receive(on: DispatchQueue.main) // Dispatch to the right queue if updating the UI
  .sink(receiveValue: { image in
    // Do something with your image
  })
  .store(in: &subscriptions) // Hold on to and dispose your subscriptions

Migrating from 5.x

There is a small migration guide in the wiki when moving from the 5.x branch to 6.x

License

MapleBacon is available under the MIT license. See the LICENSE file for more info.

Comments
  • 2 out of 3 cells in a table view not displaying the image(same image for all 3 cells)

    2 out of 3 cells in a table view not displaying the image(same image for all 3 cells)

    Hi, I am having an issue where I have a tableview that can have many cells with same image. for some reason only the first cell loads the image and the rest of the cells dont load the same image. but if I had different images it would load them properly.

    I can't seem to find what I am doing wrong here. please help. tx.

    func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell { let cell = tableView.dequeueReusableCellWithIdentifier(cellIdentifier, forIndexPath: indexPath) as! ProductCell let productBean:ProductBean = self.listOfSearchedProductsFilteredBySectionGroup[indexPath.row] as ProductBean cell.delegate = self

        if shouldDisplayStyleImage == "t" {
            let imageFullPath = "\(URLToImages)\(productBean.ImagePath)\(productBean.ImageName).\(productBean.ImageType)"            
            if let imageURL = NSURL(string: imageFullPath) {
                 cell.imgProductImg?.setImageWithURL(imageURL) {(_, error) in
                    log("pvc cell error:\(error)")
                    if error == nil {
                        let transition = CATransition()
                        cell.imgProductImg?.layer.addAnimation(transition, forKey: "fade")
                    }
                }
    
            }
    
        }
    
        return cell
    }
    
    opened by yanko 9
  • Crash on low memory

    Crash on low memory

    We have many crashes related with MapleBacon in app. When app receive low memory warning, loading next image from cache cause to crash (as we think, maybe there are some other reasons to crash app except low memory). We can't reproduce this crash on test devices. I attach screenshots from crashlytics.

    2019-02-14 09 49 43

    2019-02-14 09 37 30 2019-02-14 10 04 59

    2019-02-14 10 05 33

    opened by keynsianets 8
  • Loading Gifs has Problems

    Loading Gifs has Problems

    Hi , I'm not gonna use this lib for loading gifs but I accidently uploaded a gif file and tried to load It and it was loaded successfully but whenever I launch another view controller the Image is gone ( like it was not loaded at all ) and it wont load again if I call the method till I close and reopen the app

    opened by Mahan3340 6
  • No such module: import MapleBacon

    No such module: import MapleBacon

    Hi there, I just updated to latest ios 9 xcode 7.0.1 and os x El Capitan. and pulled the latest MapleBacon from pods.

    it no longer sees the MapleBacon as library.

    help, please?

    tx.

    opened by yanko 6
  • Download progress

    Download progress

    It would be nice to monitor the download progress. ImageDownloadOperation seems to have a delegate for progress, but it's private and the constructor, which takes the delegate is called in ImageManager with just the url, not with any delegate. The delegate should be implemented and it should call a progress closure provided by the downloadImageAtURL caller.

    opened by tapz 4
  • Bump danger-swiftlint from 0.27.0 to 0.29.4

    Bump danger-swiftlint from 0.27.0 to 0.29.4

    Bumps danger-swiftlint from 0.27.0 to 0.29.4.

    Release notes

    Sourced from danger-swiftlint's releases.

    0.29.3

    https://github.com/ashfurrow/danger-ruby-swiftlint/releases/tag/0.29.3

    Changelog

    Sourced from danger-swiftlint's changelog.

    0.29.4

    • Fixes issues running the plugin on Linux. See #174

    0.29.3

    • Fixes Rake aborted error with status 127. See #173.

    0.29.2

    • Fixes Rake aborted error with status 127. See #173.

    0.29.1

    • Fixes Rake aborted error with status 127. See #172.

    0.29.0

    • Adds integrity verification when downloading SwiftLint. See #162.

    0.28.0

    • Fixes a crash caused by renamed files in a pull request. See #168.
    Commits
    • 209c9b6 Version bump.
    • 734cc76 Merge pull request #174 from ashfurrow/fix/specs
    • cd67dee Removed debug flag from install script.
    • 869a152 Calculate the resulting_hash beforehand
    • 08c24ee Added flag to debug md5 command
    • f3a59ef Run different hash commands depending on the OS.
    • d111764 Avoid explicitly setting the shell interpreter.
    • b18def9 Explicitly call bash in swiftlint's Rakefile
    • 6c4958a Don't rely on the swiftlint executable for tests.
    • 22883f6 Updates badge to new Travis CI. See #171.
    • Additional commits viewable in compare view

    Dependabot compatibility score

    Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting @dependabot rebase.


    Dependabot commands and options

    You can trigger Dependabot actions by commenting on this PR:

    • @dependabot rebase will rebase this PR
    • @dependabot recreate will recreate this PR, overwriting any edits that have been made to it
    • @dependabot merge will merge this PR after your CI passes on it
    • @dependabot squash and merge will squash and merge this PR after your CI passes on it
    • @dependabot cancel merge will cancel a previously requested merge and block automerging
    • @dependabot reopen will reopen this PR if it is closed
    • @dependabot close will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually
    • @dependabot ignore this major version will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself)
    • @dependabot ignore this minor version will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself)
    • @dependabot ignore this dependency will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
    dependencies stale 
    opened by dependabot[bot] 3
  • Negative frameCount in animated GIF

    Negative frameCount in animated GIF

    Some animated GIFs cause crash here. The frame count is -100 because gcd is -1 because delays[0] is -1. Other 9 delays are all +100.

    fatal error: Can't form Range with end < start

    extension UIImage {
        private class func framesFromImages(images: [CGImageRef], delays: [Int]) -> [UIImage] {
            let gcd = DivisionMath.greatestCommonDivisor(delays)
            var frames = [UIImage]()
            for i in 0..<images.count {
                let frame = UIImage(CGImage: images[Int(i)])
                let frameCount = Int(delays[Int(i)] / gcd)
    
                for _ in 0..<frameCount {  <----- EXC_BREAKPOINT
                    frames.append(frame)
                }
            }
            return frames
        }
    
    bug 
    opened by tapz 3
  • cancelDownload in UIImageView extension public

    cancelDownload in UIImageView extension public

    Could you make cancelDownload function in UIImageView extension public? Currently there is no way to cancel the download (e.g. for a recycled tableView cell).

    A better solution, which requires a bit more work would be not to cancel the download, but instead the downloaded image should not be set to the image view anymore (just put to the cache). E.g. a new function ignoreDownload() and a new "doNotCancelPreviousDownload" parameter to setImageWithURL.

    opened by tapz 3
  • Fix the bundle identifier for the library target

    Fix the bundle identifier for the library target

    When the framework was included into a project, the target could not be started causing Xcode to show the ambiguous error message:

    • When ran on a device:

      The application does not contain a valid bundle identifier.

    • When ran in the simulator:

      LaunchServicesError Code=0

    After observing the device console, the detailed error was:

    : __dispatch_source_read_socket_block_invoke:234: Failed to install application at file:///<PATH_REDACTED>/ : Error Domain=LaunchServicesError Code=0 "(null)" UserInfo={Error=MissingBundleIdentifier, ErrorDescription=Bundle at path <PATH_REDACTED>/Frameworks/MapleBacon.framework did not have a CFBundleIdentifier in its Info.plist}

    Setting the bundle identifier of the target fixes the issue.

    opened by bojan 3
  • A placeholder image

    A placeholder image

    It would be nice to have a placeholder image while the actual image is loading. Like in SDWebImage. Also, if the placeholder is a preview image then a crossfade to the actual image when it's loaded.

    enhancement 
    opened by tapz 3
  • Bump fastlane from 2.185.1 to 2.186.0

    Bump fastlane from 2.185.1 to 2.186.0

    Bumps fastlane from 2.185.1 to 2.186.0.

    Release notes

    Sourced from fastlane's releases.

    2.186.0 Improvements

    • [action]adds action for obtaining remote repo default branch (#18845) via seanmcneil
    • [spaceship] parse response body as json if not already (#18766) via Muhammet Ilendemli
    • [spaceship] adding individual_testers attribute to Build model (#18922) via gsavit
    • [match] fix nuke exception when nuking with the empty files storage (#18864) via Manish Rathi
    • [match] add git authentication methods to match import command (#18903) via rb1193
    • add builds attribute to BetaTester model (#18923) via gsavit
    • [spaceship] add missing method to individually assign beta tester to builds (#18924) via gsavit
    • [snapshot] fix Swift compiler version check for SnapshotHelper.swift (#18930) via Jorge Revuelta
    • [Fastlane.Swift] add new Swift 5.5 reserved keywords (#18928) via Jorge Revuelta
    • [fastlane_core] fix the ensure_array_type_passes_validation error message (#18927) via Manish Rathi
    • [regression][pilot] fix upload using api_key_path + apple_id CLI options (#18860) via Manish Rathi
    • [actions] remove all instances of is_string in options and use type for jazzy (#18921), ipa (#18920), installr (#18919), install_on_device (#18918), increment_build_number (#18912), import_from_git (#18911), ifttt (#18910), hockey (#18909), hipchat (#18908), hg_push (#18907), hg_commit_version_bump (#18906), gradle (#18905), github_api (#18904), git_add (#18882), git_commit (#18883), get_push_certificate (#18881), get_managed_play_store_publishing_rights (#18880), get_ipa_info_plist_value (#18879), get_build_number_repository (#18878), erb (#18877), environment_variable (#18876), ensure_xcode_version (#18875), ensure_no_debug_code (#18874), ensure_git_status_clean (#18873), ensure_git_branch (#18872), dsym_zip (#18871), download_dsyms (#18870), download_app_privacy_details_from_app_store (#18869), deploygate (#18868) via Manish Rathi
    Commits
    • 84e5b74 Version bump to 2.186.0 (#18941)
    • da1fd40 [action]Adds action for obtaining remote repo default branch (#18845)
    • 0a25f2f [spaceship] parse response body as json if not already (#18766)
    • 8fefa6b [spaceship] Adding individual_testers attribute to Build model (#18922)
    • eb602f8 [match] fix nuke exception when nuking with the empty files storage (#18864)
    • 5b62b3c [match] add git authentication methods to match import command (#18903)
    • 961289a add builds attribute to BetaTester model (#18923)
    • 75e74db [spaceship] Add missing method to individually assign beta tester to builds (...
    • 414591b [snapshot] Fix Swift compiler version check for SnapshotHelper.swift (#18930)
    • 26ec675 [Fastlane.Swift] Add new Swift 5.5 reserved keywords (#18928)
    • Additional commits viewable in compare view

    Dependabot compatibility score

    Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting @dependabot rebase.


    Dependabot commands and options

    You can trigger Dependabot actions by commenting on this PR:

    • @dependabot rebase will rebase this PR
    • @dependabot recreate will recreate this PR, overwriting any edits that have been made to it
    • @dependabot merge will merge this PR after your CI passes on it
    • @dependabot squash and merge will squash and merge this PR after your CI passes on it
    • @dependabot cancel merge will cancel a previously requested merge and block automerging
    • @dependabot reopen will reopen this PR if it is closed
    • @dependabot close will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually
    • @dependabot ignore this major version will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself)
    • @dependabot ignore this minor version will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself)
    • @dependabot ignore this dependency will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
    dependencies 
    opened by dependabot[bot] 2
Releases(6.1.2)
Owner
Jan Gorman
Software Engineering @alan-eu. Also compiling Swift source files.
Jan Gorman
Kingfisher is a powerful, pure-Swift library for downloading and caching images from the web

Kingfisher is a powerful, pure-Swift library for downloading and caching images from the web. It provides you a chance to use a pure-Swift way to work

Wei Wang 20.9k Dec 30, 2022
AYImageKit is a Swift Library for Async Image Downloading, Show Name's Initials and Can View image in Separate Screen.

AYImageKit AYImageKit is a Swift Library for Async Image Downloading. Features Async Image Downloading. Can Show Text Initials. Can have Custom Styles

Adnan Yousaf 11 Jan 10, 2022
An extremely high-performance, lightweight, and energy-efficient pure Swift async web image loader with memory and disk caching for iOS and ๏ฃฟ Watch.

KFSwiftImageLoader KFSwiftImageLoader is an extremely high-performance, lightweight, and energy-efficient pure Swift async web image loader with memor

Kiavash Faisali 343 Oct 29, 2022
Twitter Image Pipeline is a robust and performant image loading and caching framework for iOS clients

Twitter Image Pipeline (a.k.a. TIP) Background The Twitter Image Pipeline is a streamlined framework for fetching and storing images in an application

Twitter 1.8k Dec 17, 2022
A lightweight and fast image loader for iOS written in Swift.

ImageLoader ImageLoader is an instrument for asynchronous image loading written in Swift. It is a lightweight and fast image loader for iOS. Features

Hirohisa Kawasaki 293 Nov 24, 2022
AsyncImage before iOS 15. Lightweight, pure SwiftUI Image view, that displays an image downloaded from URL, with auxiliary views and local cache.

URLImage URLImage is a SwiftUI view that displays an image downloaded from provided URL. URLImage manages downloading remote image and caching it loca

Dmytro Anokhin 1k Jan 4, 2023
A Swift/SwiftUI utility for caching and displaying images in SwiftUI Views

A Swift/SwiftUI utility for caching and displaying images asynchronously. Built with Swift 5.5 and works with async/await.

็Ž‹้›ช้“ฎ Xuezheng Wang 1 May 5, 2022
Advanced framework for loading, caching, processing, displaying and preheating images.

Advanced framework for loading, caching, processing, displaying and preheating images. This framework is no longer maintained. Programming in Swift? C

Alexander Grebenyuk 1.2k Dec 23, 2022
Focus on avatar caching.

Navi Navi is designed for avatar caching, with style. The name of Navi from movie Avatar. Requirements Swift 3.1, iOS 8.0 Swift 2.3, use version 0.5.0

null 114 Jun 30, 2022
An image download extension of the image view written in Swift for iOS, tvOS and macOS.

Moa, an image downloader written in Swift for iOS, tvOS and macOS Moa is an image download library written in Swift. It allows to download and show an

Evgenii Neumerzhitckii 330 Sep 9, 2022
Fast and simple OCR library written in Swift

โ›”๏ธ This Project is deprecated and no longer gets maintained! Please use Apple's Vision framework instead of SwiftOCR. It is very fast, accurate and mu

Nicolas Camenisch 4.5k Dec 29, 2022
A Fast and Complete Swift Drawing Library

FastDraw A Fast and Complete Swift Drawing Library Description FastDraw is a high performance and highly extensible Drawing Library that supports Appl

Collin Zhang 18 Nov 14, 2022
Fast and simple OCR library written in Swift

โ›”๏ธ This Project is deprecated and no longer gets maintained! Please use Apple's Vision framework instead of SwiftOCR. It is very fast, accurate and mu

Nicolas Camenisch 4.5k Dec 29, 2022
๐Ÿ“ท A composable image editor using Core Image and Metal.

Brightroom - Composable image editor - building your own UI Classic Image Editor PhotosCrop Face detection Masking component ?? v2.0.0-alpha now open!

Muukii 2.8k Jan 3, 2023
๐Ÿ“ท A composable image editor using Core Image and Metal.

Brightroom - Composable image editor - building your own UI Classic Image Editor PhotosCrop Face detection Masking component ?? v2.0.0-alpha now open!

Muukii 2.8k Jan 2, 2023
A complete Mac App: drag an image file to the top section and the bottom section will show you the text of any QRCodes in the image.

QRDecode A complete Mac App: drag an image file to the top section and the bottom section will show you the text of any QRCodes in the image. QRDecode

David Phillip Oster 2 Oct 28, 2022
An instagram-like image editor that can apply preset filters passed to it and customized editings to a binded image.

CZImageEditor CZImageEditor is an instagram-like image editor with clean and intuitive UI. It is pure swift and can apply preset filters and customize

null 8 Dec 16, 2022
Convert the image to hexadecimal to send the image to e-paper

ConvertImageToHex Convert the image to hexadecimal to send the image to e-paper Conversion Order // 0. hex๋กœ ๋ณ€ํ™˜ํ•  ์ด๋ฏธ์ง€ var image = UIImage(named: "sample

Hankyeol Park 0 Feb 26, 2022
Image-cropper - Image cropper for iOS

Image-cropper Example To run the example project, clone the repo, and run pod in

Song Vuthy 0 Jan 6, 2022