Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions .swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

12 changes: 8 additions & 4 deletions Example/ImaginaryDemo/ImaginaryDemo.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
295D77431C07122700C43B07 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 295D77411C07122700C43B07 /* LaunchScreen.storyboard */; };
29FC0C2B1C07268100B66E11 /* FeedTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 29FC0C2A1C07268100B66E11 /* FeedTableViewCell.swift */; };
938EF94E073488BB7B5AE1F1 /* Pods_ImaginaryDemo.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1C16C258DB463D5FFF1DD607 /* Pods_ImaginaryDemo.framework */; };
F560478A28621EC1008ED0AC /* SwiftUIViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = F560478928621EC1008ED0AC /* SwiftUIViewController.swift */; };
/* End PBXBuildFile section */

/* Begin PBXFileReference section */
Expand All @@ -27,6 +28,7 @@
311B2CD8C66C552F516784F2 /* Pods-ImaginaryDemo.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-ImaginaryDemo.release.xcconfig"; path = "Pods/Target Support Files/Pods-ImaginaryDemo/Pods-ImaginaryDemo.release.xcconfig"; sourceTree = "<group>"; };
46273A36A5534213CB1EF279 /* Pods-ImaginaryDemo.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-ImaginaryDemo.debug.xcconfig"; path = "Pods/Target Support Files/Pods-ImaginaryDemo/Pods-ImaginaryDemo.debug.xcconfig"; sourceTree = "<group>"; };
F0A3FBC34DFEEC7A04F84F11 /* Pods.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods.framework; sourceTree = BUILT_PRODUCTS_DIR; };
F560478928621EC1008ED0AC /* SwiftUIViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SwiftUIViewController.swift; sourceTree = "<group>"; };
/* End PBXFileReference section */

/* Begin PBXFrameworksBuildPhase section */
Expand Down Expand Up @@ -68,6 +70,7 @@
295D773F1C07122700C43B07 /* Assets.xcassets */,
295D77411C07122700C43B07 /* LaunchScreen.storyboard */,
295D77441C07122700C43B07 /* Info.plist */,
F560478928621EC1008ED0AC /* SwiftUIViewController.swift */,
);
path = ImaginaryDemo;
sourceTree = "<group>";
Expand Down Expand Up @@ -203,6 +206,7 @@
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
F560478A28621EC1008ED0AC /* SwiftUIViewController.swift in Sources */,
295D773B1C07122700C43B07 /* ViewController.swift in Sources */,
29FC0C2B1C07268100B66E11 /* FeedTableViewCell.swift in Sources */,
295D77391C07122700C43B07 /* AppDelegate.swift in Sources */,
Expand Down Expand Up @@ -271,7 +275,7 @@
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 9.0;
IPHONEOS_DEPLOYMENT_TARGET = 13.0;
MTL_ENABLE_DEBUG_INFO = YES;
ONLY_ACTIVE_ARCH = YES;
SDKROOT = iphoneos;
Expand Down Expand Up @@ -323,7 +327,7 @@
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 9.0;
IPHONEOS_DEPLOYMENT_TARGET = 13.0;
MTL_ENABLE_DEBUG_INFO = NO;
SDKROOT = iphoneos;
SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule";
Expand All @@ -340,7 +344,7 @@
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = "$(inherited)";
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
INFOPLIST_FILE = ImaginaryDemo/Info.plist;
IPHONEOS_DEPLOYMENT_TARGET = 9.0;
IPHONEOS_DEPLOYMENT_TARGET = 13.0;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
PRODUCT_BUNDLE_IDENTIFIER = RamonGilabert.ImaginaryDemo;
PRODUCT_NAME = "$(TARGET_NAME)";
Expand All @@ -354,7 +358,7 @@
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = "$(inherited)";
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
INFOPLIST_FILE = ImaginaryDemo/Info.plist;
IPHONEOS_DEPLOYMENT_TARGET = 9.0;
IPHONEOS_DEPLOYMENT_TARGET = 13.0;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
PRODUCT_BUNDLE_IDENTIFIER = RamonGilabert.ImaginaryDemo;
PRODUCT_NAME = "$(TARGET_NAME)";
Expand Down
30 changes: 16 additions & 14 deletions Example/ImaginaryDemo/ImaginaryDemo/AppDelegate.swift
Original file line number Diff line number Diff line change
Expand Up @@ -2,19 +2,21 @@ import UIKit

@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {

lazy var viewController: ViewController = ViewController()

var window: UIWindow?

lazy var viewController: ViewController = ViewController()
lazy var swiftUIViewController: SwiftUIViewController = SwiftUIViewController()
var window: UIWindow?
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
let navigationController = UINavigationController(rootViewController: viewController)
viewController.title = "Imaginary".uppercased()

window = UIWindow()
window?.rootViewController = navigationController
window?.makeKeyAndVisible()

return true
}
let tabVC = UITabBarController()
viewController.tabBarItem.title = "UIKit"
swiftUIViewController.tabBarItem.title = "SwiftUI"
tabVC.setViewControllers([viewController, swiftUIViewController], animated: true)

window = UIWindow()
window?.rootViewController = tabVC
window?.makeKeyAndVisible()

return true
}
}
52 changes: 52 additions & 0 deletions Example/ImaginaryDemo/ImaginaryDemo/SwiftUIViewController.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
//
// SwiftUIViewController.swift
// ImaginaryDemo
//
// Created by Arslan Rafique on 2022-06-21.
// Copyright © 2022 Ramon Gilabert Llop. All rights reserved.
//

import SwiftUI
import Imaginary

struct ContentView: SwiftUI.View {

struct Constants {
static let imageWidth = 500
static let imageHeight = 500
static let imageNumber = 400
}

var imaginaryArray: [URL] = {
var array = [URL]()

for i in 0..<Constants.imageNumber {
if let imageURL = URL(
string: "https://placeimg.com/640/480/any/\(i)") {
array.append(imageURL)
}
}

return array
}()

var body: some SwiftUI.View {
ScrollView {
VStack {
ForEach(imaginaryArray, id: \.self) { url in
ImageViewAdapter(url: url)
.id(url.absoluteString)
}
}
}
}
}

class SwiftUIViewController: UITableViewController {
override func viewDidLoad() {
let hosting = UIHostingController(rootView: ContentView())
self.addChild(hosting)
self.view.addSubview(hosting.view)
hosting.view.frame = UIScreen.main.bounds
}
}
2 changes: 1 addition & 1 deletion Example/ImaginaryDemo/Podfile
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
platform :ios, '9.0'
platform :ios, '13.0'

target 'ImaginaryDemo' do
use_frameworks!
Expand Down
14 changes: 7 additions & 7 deletions Example/ImaginaryDemo/Podfile.lock
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
PODS:
- Cache (5.3.0)
- Imaginary (4.3.0):
- Cache (~> 5.3.0)
- Cache (6.0.0)
- Imaginary (5.0.0):
- Cache (~> 6.0.0)

DEPENDENCIES:
- Imaginary (from `../../`)
Expand All @@ -15,9 +15,9 @@ EXTERNAL SOURCES:
:path: "../../"

SPEC CHECKSUMS:
Cache: 48762993ec44e1d93483c4d4a13edd18452326f4
Imaginary: c3153bbdfadcf1736d736e307d80717b7a8c6040
Cache: 4ca7e00363fca5455f26534e5607634c820ffc2d
Imaginary: cf5e3a7dd6ab1dcbd47ba8ce5edf2307c4e99eb3

PODFILE CHECKSUM: 317cccf04e61f3f6f7e8a7e2dbc1ad0f7fa2beee
PODFILE CHECKSUM: f44736d98f74418007761e4973f2c94b08d5db15

COCOAPODS: 1.9.3
COCOAPODS: 1.11.3
2 changes: 1 addition & 1 deletion Imaginary.podspec
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
Pod::Spec.new do |s|
s.name = "Imaginary"
s.summary = "Remote images, as easy as one, two, three."
s.version = "5.0.0"
s.version = "5.0.1"
s.homepage = "https://github.com/hyperoslo/Imaginary"
s.license = 'MIT'
s.author = { "Hyper Interaktiv AS" => "[email protected]" }
Expand Down
2 changes: 2 additions & 0 deletions Imaginary.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,7 @@
D5DF75911C403D8200BF1AB6 /* Imaginary.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Imaginary.framework; sourceTree = BUILT_PRODUCTS_DIR; };
D5DF759E1C403E1000BF1AB6 /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
D5DF75B11C403FBF00BF1AB6 /* Cache.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Cache.framework; path = Carthage/Build/iOS/Cache.framework; sourceTree = "<group>"; };
F560478B2862217B008ED0AC /* SwiftUI */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = folder; path = SwiftUI; sourceTree = "<group>"; };
/* End PBXFileReference section */

/* Begin PBXFrameworksBuildPhase section */
Expand Down Expand Up @@ -244,6 +245,7 @@
D2E8C8051F7252C300D2B8EF /* Shared */ = {
isa = PBXGroup;
children = (
F560478B2862217B008ED0AC /* SwiftUI */,
D2E8C8071F7252C300D2B8EF /* Extensions */,
D2E8C8091F7252C300D2B8EF /* Fetcher */,
D2E8C80D1F7252C300D2B8EF /* Library */,
Expand Down
16 changes: 16 additions & 0 deletions Package.resolved

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

18 changes: 13 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,16 @@ imageView.setImage(url: imageUrl) { result in

`result` is an enum `Result` that let you know if the operation succeeded or failed. The possible error is of `ImaginaryError`.

## SwiftUI

#### Set image with URL

Simply pass `URL` to `ImageViewAdapter`.

```swift
ImageViewAdapter(url: "https://avatars2.githubusercontent.com/u/1340892?v=3&s=200")
```

## Advanced

### Passing option
Expand All @@ -99,7 +109,6 @@ public protocol ImageProcessor {

This is how you apply tint color before setting images.


```swift
let option = Option(imagePreprocessor: TintImageProcessor(tintColor: .orange))
imageView.setImage(url: imageUrl, option: option)
Expand Down Expand Up @@ -142,15 +151,15 @@ These are the buit in displayers. You need to supply the correct displayer for y

### Downloading

`Imaginary` uses `ImageFetcher` under the hood, which has downloader and storage. You can specify your own `ImageDownloader` together with a `modifyRequest` closure, there you can change request body or add more HTTP headers.
`Imaginary` uses `ImageFetcher` under the hood, which has downloader and storage. You can specify your own `ImageDownloader` together with a `modifyRequest` closure, there you can change request body or add more HTTP headers.

```swift
var option = Option()
option.downloaderMaker = {
return ImageDownloader(modifyRequest: {
return ImageDownloader(modifyRequest: {
var request = $0
request.addValue("Bearer 123", forHTTPHeaderField: "Authorization")
return request
return request
})
}

Expand Down Expand Up @@ -220,7 +229,6 @@ multipleFetcher.fetch(urls: imageUrls, each: { result in

This is ideal for the new [prefetching mode in UICollectionView](https://developer.apple.com/documentation/uikit/uicollectionview/1771771-prefetchingenabled)


## Installation

**Imaginary** is available through [CocoaPods](http://cocoapods.org). To install
Expand Down
18 changes: 9 additions & 9 deletions Sources/Shared/Fetcher/ImageFetcher.swift
Original file line number Diff line number Diff line change
Expand Up @@ -43,16 +43,16 @@ public class ImageFetcher {
guard let `self` = self else {
return
}

switch result {
case .success(let image):
completion(.value(image))
case .failure:
if url.isFileURL {
self.fetchFromDisk(url: url, completion: completion)
} else {
self.fetchFromNetwork(url: url, completion: completion)
}
case .value(let image):
completion(.value(image))
case .error(let error):
if url.isFileURL {
self.fetchFromDisk(url: url, completion: completion)
} else {
self.fetchFromNetwork(url: url, completion: completion)
}
}
})
}
Expand Down
27 changes: 27 additions & 0 deletions Sources/Shared/SwiftUI/ImageViewAdapter.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
//
// ImageViewAdapter.swift
//
//
// Created by Arslan Rafique on 2022-06-21.
//

import SwiftUI

@available(iOS 13.0, macOS 10.15, *)
public struct ImageViewAdapter: UIViewRepresentable {

let url: URL

public init(url: URL) {
self.url = url
}

public func makeUIView(context: Context) -> UIView {
let imageView: UIImageView = UIImageView()
imageView.contentMode = .scaleToFill
imageView.setImage(url: self.url)
return imageView
}

public func updateUIView(_ uiView: UIView, context: Context) {}
}