";
229 | };
230 | /* End PBXVariantGroup section */
231 |
232 | /* Begin XCBuildConfiguration section */
233 | 78B88846209E0BCC0023F90B /* Debug */ = {
234 | isa = XCBuildConfiguration;
235 | buildSettings = {
236 | ALWAYS_SEARCH_USER_PATHS = NO;
237 | CLANG_ANALYZER_NONNULL = YES;
238 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
239 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
240 | CLANG_CXX_LIBRARY = "libc++";
241 | CLANG_ENABLE_MODULES = YES;
242 | CLANG_ENABLE_OBJC_ARC = YES;
243 | CLANG_ENABLE_OBJC_WEAK = YES;
244 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
245 | CLANG_WARN_BOOL_CONVERSION = YES;
246 | CLANG_WARN_COMMA = YES;
247 | CLANG_WARN_CONSTANT_CONVERSION = YES;
248 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
249 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
250 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
251 | CLANG_WARN_EMPTY_BODY = YES;
252 | CLANG_WARN_ENUM_CONVERSION = YES;
253 | CLANG_WARN_INFINITE_RECURSION = YES;
254 | CLANG_WARN_INT_CONVERSION = YES;
255 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
256 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
257 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
258 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
259 | CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
260 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
261 | CLANG_WARN_STRICT_PROTOTYPES = YES;
262 | CLANG_WARN_SUSPICIOUS_MOVE = YES;
263 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
264 | CLANG_WARN_UNREACHABLE_CODE = YES;
265 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
266 | CODE_SIGN_IDENTITY = "iPhone Developer";
267 | COPY_PHASE_STRIP = NO;
268 | DEBUG_INFORMATION_FORMAT = dwarf;
269 | ENABLE_STRICT_OBJC_MSGSEND = YES;
270 | ENABLE_TESTABILITY = YES;
271 | GCC_C_LANGUAGE_STANDARD = gnu11;
272 | GCC_DYNAMIC_NO_PIC = NO;
273 | GCC_NO_COMMON_BLOCKS = YES;
274 | GCC_OPTIMIZATION_LEVEL = 0;
275 | GCC_PREPROCESSOR_DEFINITIONS = (
276 | "DEBUG=1",
277 | "$(inherited)",
278 | );
279 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
280 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
281 | GCC_WARN_UNDECLARED_SELECTOR = YES;
282 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
283 | GCC_WARN_UNUSED_FUNCTION = YES;
284 | GCC_WARN_UNUSED_VARIABLE = YES;
285 | IPHONEOS_DEPLOYMENT_TARGET = 12.0;
286 | MTL_ENABLE_DEBUG_INFO = YES;
287 | ONLY_ACTIVE_ARCH = YES;
288 | SDKROOT = iphoneos;
289 | SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
290 | SWIFT_OPTIMIZATION_LEVEL = "-Onone";
291 | SWIFT_VERSION = 4.2;
292 | };
293 | name = Debug;
294 | };
295 | 78B88847209E0BCC0023F90B /* Release */ = {
296 | isa = XCBuildConfiguration;
297 | buildSettings = {
298 | ALWAYS_SEARCH_USER_PATHS = NO;
299 | CLANG_ANALYZER_NONNULL = YES;
300 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
301 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
302 | CLANG_CXX_LIBRARY = "libc++";
303 | CLANG_ENABLE_MODULES = YES;
304 | CLANG_ENABLE_OBJC_ARC = YES;
305 | CLANG_ENABLE_OBJC_WEAK = YES;
306 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
307 | CLANG_WARN_BOOL_CONVERSION = YES;
308 | CLANG_WARN_COMMA = YES;
309 | CLANG_WARN_CONSTANT_CONVERSION = YES;
310 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
311 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
312 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
313 | CLANG_WARN_EMPTY_BODY = YES;
314 | CLANG_WARN_ENUM_CONVERSION = YES;
315 | CLANG_WARN_INFINITE_RECURSION = YES;
316 | CLANG_WARN_INT_CONVERSION = YES;
317 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
318 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
319 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
320 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
321 | CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
322 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
323 | CLANG_WARN_STRICT_PROTOTYPES = YES;
324 | CLANG_WARN_SUSPICIOUS_MOVE = YES;
325 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
326 | CLANG_WARN_UNREACHABLE_CODE = YES;
327 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
328 | CODE_SIGN_IDENTITY = "iPhone Developer";
329 | COPY_PHASE_STRIP = NO;
330 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
331 | ENABLE_NS_ASSERTIONS = NO;
332 | ENABLE_STRICT_OBJC_MSGSEND = YES;
333 | GCC_C_LANGUAGE_STANDARD = gnu11;
334 | GCC_NO_COMMON_BLOCKS = YES;
335 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
336 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
337 | GCC_WARN_UNDECLARED_SELECTOR = YES;
338 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
339 | GCC_WARN_UNUSED_FUNCTION = YES;
340 | GCC_WARN_UNUSED_VARIABLE = YES;
341 | IPHONEOS_DEPLOYMENT_TARGET = 12.0;
342 | MTL_ENABLE_DEBUG_INFO = NO;
343 | SDKROOT = iphoneos;
344 | SWIFT_COMPILATION_MODE = wholemodule;
345 | SWIFT_OPTIMIZATION_LEVEL = "-O";
346 | SWIFT_VERSION = 4.2;
347 | VALIDATE_PRODUCT = YES;
348 | };
349 | name = Release;
350 | };
351 | 78B88849209E0BCC0023F90B /* Debug */ = {
352 | isa = XCBuildConfiguration;
353 | baseConfigurationReference = D4C80BC259AF761125CD8346 /* Pods-Example.debug.xcconfig */;
354 | buildSettings = {
355 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
356 | CODE_SIGN_STYLE = Automatic;
357 | INFOPLIST_FILE = Example/Info.plist;
358 | IPHONEOS_DEPLOYMENT_TARGET = 12.1;
359 | LD_RUNPATH_SEARCH_PATHS = (
360 | "$(inherited)",
361 | "@executable_path/Frameworks",
362 | );
363 | PRODUCT_BUNDLE_IDENTIFIER = com.freak4pc.Example;
364 | PRODUCT_NAME = "$(TARGET_NAME)";
365 | SWIFT_VERSION = 5.0;
366 | TARGETED_DEVICE_FAMILY = "1,2";
367 | };
368 | name = Debug;
369 | };
370 | 78B8884A209E0BCC0023F90B /* Release */ = {
371 | isa = XCBuildConfiguration;
372 | baseConfigurationReference = CB2DAF75842D531199F69CEB /* Pods-Example.release.xcconfig */;
373 | buildSettings = {
374 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
375 | CODE_SIGN_STYLE = Automatic;
376 | INFOPLIST_FILE = Example/Info.plist;
377 | IPHONEOS_DEPLOYMENT_TARGET = 12.1;
378 | LD_RUNPATH_SEARCH_PATHS = (
379 | "$(inherited)",
380 | "@executable_path/Frameworks",
381 | );
382 | PRODUCT_BUNDLE_IDENTIFIER = com.freak4pc.Example;
383 | PRODUCT_NAME = "$(TARGET_NAME)";
384 | SWIFT_VERSION = 5.0;
385 | TARGETED_DEVICE_FAMILY = "1,2";
386 | };
387 | name = Release;
388 | };
389 | /* End XCBuildConfiguration section */
390 |
391 | /* Begin XCConfigurationList section */
392 | 78B88831209E0BCB0023F90B /* Build configuration list for PBXProject "Example" */ = {
393 | isa = XCConfigurationList;
394 | buildConfigurations = (
395 | 78B88846209E0BCC0023F90B /* Debug */,
396 | 78B88847209E0BCC0023F90B /* Release */,
397 | );
398 | defaultConfigurationIsVisible = 0;
399 | defaultConfigurationName = Release;
400 | };
401 | 78B88848209E0BCC0023F90B /* Build configuration list for PBXNativeTarget "Example" */ = {
402 | isa = XCConfigurationList;
403 | buildConfigurations = (
404 | 78B88849209E0BCC0023F90B /* Debug */,
405 | 78B8884A209E0BCC0023F90B /* Release */,
406 | );
407 | defaultConfigurationIsVisible = 0;
408 | defaultConfigurationName = Release;
409 | };
410 | /* End XCConfigurationList section */
411 | };
412 | rootObject = 78B8882E209E0BCB0023F90B /* Project object */;
413 | }
414 |
--------------------------------------------------------------------------------
/Example/Example.xcodeproj/project.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/Example/Example.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | IDEDidComputeMac32BitWarning
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/Example/Example.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/Example/Example.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | IDEDidComputeMac32BitWarning
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/Example/Example/AppDelegate.swift:
--------------------------------------------------------------------------------
1 | //
2 | // AppDelegate.swift
3 | // Example
4 | //
5 | // Created by Shai Mishali on 5/5/18.
6 | // Copyright © 2018 Shai Mishali. All rights reserved.
7 | //
8 |
9 | import UIKit
10 |
11 | @UIApplicationMain
12 | class AppDelegate: UIResponder, UIApplicationDelegate {
13 | var window: UIWindow?
14 | }
15 |
--------------------------------------------------------------------------------
/Example/Example/Assets.xcassets/AppIcon.appiconset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "iphone",
5 | "size" : "20x20",
6 | "scale" : "2x"
7 | },
8 | {
9 | "idiom" : "iphone",
10 | "size" : "20x20",
11 | "scale" : "3x"
12 | },
13 | {
14 | "idiom" : "iphone",
15 | "size" : "29x29",
16 | "scale" : "2x"
17 | },
18 | {
19 | "idiom" : "iphone",
20 | "size" : "29x29",
21 | "scale" : "3x"
22 | },
23 | {
24 | "idiom" : "iphone",
25 | "size" : "40x40",
26 | "scale" : "2x"
27 | },
28 | {
29 | "idiom" : "iphone",
30 | "size" : "40x40",
31 | "scale" : "3x"
32 | },
33 | {
34 | "idiom" : "iphone",
35 | "size" : "60x60",
36 | "scale" : "2x"
37 | },
38 | {
39 | "idiom" : "iphone",
40 | "size" : "60x60",
41 | "scale" : "3x"
42 | },
43 | {
44 | "idiom" : "ipad",
45 | "size" : "20x20",
46 | "scale" : "1x"
47 | },
48 | {
49 | "idiom" : "ipad",
50 | "size" : "20x20",
51 | "scale" : "2x"
52 | },
53 | {
54 | "idiom" : "ipad",
55 | "size" : "29x29",
56 | "scale" : "1x"
57 | },
58 | {
59 | "idiom" : "ipad",
60 | "size" : "29x29",
61 | "scale" : "2x"
62 | },
63 | {
64 | "idiom" : "ipad",
65 | "size" : "40x40",
66 | "scale" : "1x"
67 | },
68 | {
69 | "idiom" : "ipad",
70 | "size" : "40x40",
71 | "scale" : "2x"
72 | },
73 | {
74 | "idiom" : "ipad",
75 | "size" : "76x76",
76 | "scale" : "1x"
77 | },
78 | {
79 | "idiom" : "ipad",
80 | "size" : "76x76",
81 | "scale" : "2x"
82 | },
83 | {
84 | "idiom" : "ipad",
85 | "size" : "83.5x83.5",
86 | "scale" : "2x"
87 | },
88 | {
89 | "idiom" : "ios-marketing",
90 | "size" : "1024x1024",
91 | "scale" : "1x"
92 | }
93 | ],
94 | "info" : {
95 | "version" : 1,
96 | "author" : "xcode"
97 | }
98 | }
--------------------------------------------------------------------------------
/Example/Example/Assets.xcassets/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "info" : {
3 | "version" : 1,
4 | "author" : "xcode"
5 | }
6 | }
--------------------------------------------------------------------------------
/Example/Example/Base.lproj/LaunchScreen.storyboard:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
--------------------------------------------------------------------------------
/Example/Example/Base.lproj/Main.storyboard:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
--------------------------------------------------------------------------------
/Example/Example/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | $(DEVELOPMENT_LANGUAGE)
7 | CFBundleExecutable
8 | $(EXECUTABLE_NAME)
9 | CFBundleIdentifier
10 | $(PRODUCT_BUNDLE_IDENTIFIER)
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | $(PRODUCT_NAME)
15 | CFBundlePackageType
16 | APPL
17 | CFBundleShortVersionString
18 | 1.0
19 | CFBundleVersion
20 | 1
21 | LSRequiresIPhoneOS
22 |
23 | NSPhotoLibraryAddUsageDescription
24 | Save image to library
25 | NSPhotoLibraryUsageDescription
26 | Save image to library
27 | UILaunchStoryboardName
28 | LaunchScreen
29 | UIMainStoryboardFile
30 | Main
31 | UIRequiredDeviceCapabilities
32 |
33 | armv7
34 |
35 | UISupportedInterfaceOrientations
36 |
37 | UIInterfaceOrientationPortrait
38 | UIInterfaceOrientationLandscapeLeft
39 | UIInterfaceOrientationLandscapeRight
40 |
41 | UISupportedInterfaceOrientations~ipad
42 |
43 | UIInterfaceOrientationPortrait
44 | UIInterfaceOrientationPortraitUpsideDown
45 | UIInterfaceOrientationLandscapeLeft
46 | UIInterfaceOrientationLandscapeRight
47 |
48 |
49 |
50 |
--------------------------------------------------------------------------------
/Example/Example/ViewController.swift:
--------------------------------------------------------------------------------
1 | //
2 | // ViewController.swift
3 | // Example
4 | //
5 | // Created by Shai Mishali on 5/5/18.
6 | // Copyright © 2018 Shai Mishali. All rights reserved.
7 | //
8 |
9 | import UIKit
10 | import RxKingfisher
11 | import Kingfisher
12 | import RxCocoa
13 | import RxSwift
14 | import Fakery
15 |
16 | class ViewController: UIViewController {
17 | @IBOutlet private weak var image: UIImageView!
18 | @IBOutlet private weak var picker: UIPickerView!
19 | @IBOutlet private weak var btnSave: UIButton!
20 | @IBOutlet private weak var loader: UIActivityIndicatorView!
21 |
22 | private let disposeBag = DisposeBag()
23 |
24 | private var options: [String] {
25 | let faker = Faker()
26 | let names = (0...45)
27 | .map { _ in faker.name.firstName().capitalized }
28 |
29 | return ["-- Select an Option --",
30 | "Hello!",
31 | "RxSwift Rules!",
32 | "How are you",
33 | ";-)"] + names
34 | }
35 |
36 | override func viewDidLoad() {
37 | super.viewDidLoad()
38 |
39 | setupUI()
40 | setupRx()
41 | }
42 |
43 | private func setupUI() {
44 | image.layer.borderColor = UIColor.black.cgColor
45 | image.layer.borderWidth = 4
46 | }
47 |
48 | private func setupRx() {
49 | let imageSize = image.bounds.size
50 | let imageURL: (String) -> URL = { text in
51 | return URL(string: "https://fakeimg.pl/\(Int(imageSize.width))x\(Int(imageSize.height))/?text=\(text.addingPercentEncoding(withAllowedCharacters: .urlHostAllowed)!)&font=museo")!
52 | }
53 |
54 | Observable.just(options)
55 | .bind(to: picker.rx.itemTitles) { $1 }
56 | .disposed(by: disposeBag)
57 |
58 | let selectedOption = picker.rx.modelSelected(String.self)
59 | .map { $0.first! }
60 | .share()
61 |
62 | selectedOption
63 | .map { $0 != "-- Select an Option --" }
64 | .startWith(false)
65 | .bind(to: btnSave.rx.isEnabled)
66 | .disposed(by: disposeBag)
67 |
68 | // Example of binding a URL to the Kingfisher Rx extension
69 | selectedOption
70 | .startWith("Select Option")
71 | .map { $0 == "-- Select an Option" ? "Select Option" : $0 }
72 | .map(imageURL)
73 | .bind(to: image.kf.rx.image(options: [.transition(.fade(0.2)),
74 | .keepCurrentImageWhileLoading,
75 | .forceTransition]))
76 | .disposed(by: disposeBag)
77 |
78 | // Example of retrieving an Image from a KingfisherManager
79 | // without being tied to a specific Image View.
80 | btnSave.rx.tap
81 | .do(onNext: { [weak self] in
82 | self?.btnSave.isHidden = true
83 | self?.loader.isHidden = false
84 | })
85 | .withLatestFrom(selectedOption)
86 | .map(imageURL)
87 | .flatMapLatest { KingfisherManager.shared.rx.retrieveImage(with: $0) }
88 | .observe(on: MainScheduler.instance)
89 | .subscribe(with: self) { vc, image in
90 | vc.btnSave.isHidden = false
91 | vc.loader.isHidden = true
92 |
93 | // Save image to Photo Library and redirect
94 | UIImageWriteToSavedPhotosAlbum(image, nil, nil, nil)
95 | UIApplication.shared.open(URL(string:"photos-redirect://")!)
96 | }
97 | .disposed(by: disposeBag)
98 | }
99 | }
100 |
--------------------------------------------------------------------------------
/Example/Podfile:
--------------------------------------------------------------------------------
1 | target 'Example' do
2 | use_frameworks!
3 | platform :ios, '12.0'
4 | inhibit_all_warnings!
5 |
6 | pod 'RxKingfisher', :path => '../'
7 | pod 'Fakery'
8 | pod 'RxCocoa'
9 | end
10 |
--------------------------------------------------------------------------------
/Example/Podfile.lock:
--------------------------------------------------------------------------------
1 | PODS:
2 | - Fakery (5.1.0)
3 | - Kingfisher (7.2.1)
4 | - RxCocoa (6.2.0):
5 | - RxRelay (= 6.2.0)
6 | - RxSwift (= 6.2.0)
7 | - RxKingfisher (2.1.0):
8 | - Kingfisher (~> 7)
9 | - RxCocoa (~> 6)
10 | - RxSwift (~> 6)
11 | - RxRelay (6.2.0):
12 | - RxSwift (= 6.2.0)
13 | - RxSwift (6.2.0)
14 |
15 | DEPENDENCIES:
16 | - Fakery
17 | - RxCocoa
18 | - RxKingfisher (from `../`)
19 |
20 | SPEC REPOS:
21 | trunk:
22 | - Fakery
23 | - Kingfisher
24 | - RxCocoa
25 | - RxRelay
26 | - RxSwift
27 |
28 | EXTERNAL SOURCES:
29 | RxKingfisher:
30 | :path: "../"
31 |
32 | SPEC CHECKSUMS:
33 | Fakery: a90caff00ca5cacde6c161c3eafc72314a03d34d
34 | Kingfisher: 7c084bebf7d548c623ad41bcf765fb200efed369
35 | RxCocoa: 4baf94bb35f2c0ab31bc0cb9f1900155f646ba42
36 | RxKingfisher: 3718612911238bb1a52e50b9f3797394aa705f6c
37 | RxRelay: e72dbfd157807478401ef1982e1c61c945c94b2f
38 | RxSwift: d356ab7bee873611322f134c5f9ef379fa183d8f
39 |
40 | PODFILE CHECKSUM: c2c6711fe7cf93b2a28df5eb886c2eb1ee88e971
41 |
42 | COCOAPODS: 1.10.1
43 |
--------------------------------------------------------------------------------
/Images/example.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/RxSwiftCommunity/RxKingfisher/3afba5ccbaf30b493529c4f686a8d6d11304e367/Images/example.gif
--------------------------------------------------------------------------------
/Images/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/RxSwiftCommunity/RxKingfisher/3afba5ccbaf30b493529c4f686a8d6d11304e367/Images/logo.png
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2018 Shai Mishali
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
23 |
--------------------------------------------------------------------------------
/Package.resolved:
--------------------------------------------------------------------------------
1 | {
2 | "object": {
3 | "pins": [
4 | {
5 | "package": "Kingfisher",
6 | "repositoryURL": "https://github.com/onevcat/Kingfisher.git",
7 | "state": {
8 | "branch": null,
9 | "revision": "8c65ddf756c633d01d9ae01092bf72f0c66dfc60",
10 | "version": "7.0.0"
11 | }
12 | },
13 | {
14 | "package": "RxSwift",
15 | "repositoryURL": "https://github.com/ReactiveX/RxSwift.git",
16 | "state": {
17 | "branch": null,
18 | "revision": "c8742ed97fc2f0c015a5ea5eddefb064cd7532d2",
19 | "version": "6.0.0"
20 | }
21 | }
22 | ]
23 | },
24 | "version": 1
25 | }
26 |
--------------------------------------------------------------------------------
/Package.swift:
--------------------------------------------------------------------------------
1 | // swift-tools-version:5.2
2 | // The swift-tools-version declares the minimum version of Swift required to build this package.
3 |
4 | import PackageDescription
5 |
6 | let package = Package(
7 | name: "RxKingfisher",
8 | platforms: [
9 | .macOS(.v10_14), .iOS(.v12), .tvOS(.v12), .watchOS(.v5)
10 | ],
11 | products: [
12 | .library(
13 | name: "RxKingfisher",
14 | targets: ["RxKingfisher"]),
15 | ],
16 | dependencies: [
17 | .package(url: "https://github.com/ReactiveX/RxSwift.git", .upToNextMajor(from: "6.0.0" )),
18 | .package(url: "https://github.com/onevcat/Kingfisher.git", .upToNextMajor(from: "7.0.0" )),
19 | ],
20 | targets: [
21 | .target(
22 | name: "RxKingfisher",
23 | dependencies: ["RxSwift", .product(name: "RxCocoa", package: "RxSwift"), "Kingfisher"]),
24 | .testTarget(
25 | name: "RxKingfisherTests",
26 | dependencies: ["RxKingfisher"]),
27 | ]
28 | )
29 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 | **RxKingfisher** is a Reactive Extension for Kingfisher - a lightweight, pure-Swift library for downloading and caching images from the web.
14 |
15 |
16 |
17 | It provides Reactive Extensions on top of Kingfisher's `.kf` namespace, via `.kf.rx` and introduces two main usages:
18 |
19 | #### Bind URL to Image View by `Resource` or `Source`
20 |
21 | Every Image view supports two different options for binding a URL to an Image view.
22 |
23 | ```swift
24 | optionSelected // Observable or Observable
25 | .bind(to: image.kf.rx.image(options: [.transition(.fade(0.2))])
26 | .disposed(by: disposeBag)
27 | ```
28 |
29 | OR
30 |
31 | ```swift
32 | optionSelected // Observable or Observable
33 | .flatMap { url in imageView.kf.rx.setImage(with: url, options: [.transition(.fade(0.2))]) }
34 | .subscribe(onNext: { image in
35 | print("Image successfully loaded and set on Image view: \(image)")
36 | })
37 | .disposed(by: disposeBag)
38 | ```
39 | > ### Refer
40 | > `URL` is implementing `Resource` (See [Kingfisher.Resource.swift](https://github.com/onevcat/Kingfisher/blob/c598ab7a7b3f3a4778ab18076b3449a30fc8c0d3/Sources/General/ImageSource/Resource.swift#L71-L74))
41 |
42 |
43 | ### Retrieve an Image without an Image View
44 |
45 | Every `KingfisherManager` supports fetching an image from a URL, returning a `Single`:
46 |
47 | ```swift
48 | tappedButton
49 | .flatMapLatest { KingfisherManager.shared.rx.retrieveImage(with: urlToImage) }
50 | .subscribe(onNext: { image in
51 | print("Image successfully loaded: \(image)")
52 | })
53 | .disposed(by: disposeBag)
54 | ```
55 |
56 | ### License
57 |
58 | RxKingfisher is released under the MIT license. See LICENSE for details.
59 |
--------------------------------------------------------------------------------
/RxKingfisher.podspec:
--------------------------------------------------------------------------------
1 | Pod::Spec.new do |s|
2 | s.name = "RxKingfisher"
3 | s.version = "2.1.0"
4 | s.summary = "Reactive extension for the Kingfisher image downloading and caching library"
5 | s.description = <<-DESC
6 | Reactive extension for the Kingfisher image downloading and caching library
7 | DESC
8 | s.homepage = "https://github.com/RxSwiftCommunity/RxKingfisher"
9 | s.license = { :type => "MIT", :file => "LICENSE" }
10 | s.author = { "Shai Mishali" => "freak4pc@gmail.com" }
11 | s.social_media_url = "https://raw.githubusercontent.com/RxSwiftCommunity/RxKingfisher/main/Images/logo.png"
12 | s.source = { :git => "https://github.com/RxSwiftCommunity/RxKingfisher.git", :tag => s.version.to_s }
13 | s.source_files = "Sources/**/*"
14 | s.frameworks = "Foundation"
15 |
16 | s.swift_version = "5.3"
17 |
18 | s.ios.deployment_target = "12.0"
19 | s.tvos.deployment_target = "12.0"
20 | s.osx.deployment_target = "10.14"
21 |
22 | s.dependency 'Kingfisher', '~> 7'
23 | s.dependency 'RxSwift', '~> 6'
24 | s.dependency 'RxCocoa', '~> 6'
25 | end
26 |
--------------------------------------------------------------------------------
/RxKingfisher.xcodeproj/Kingfisher_Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | CFBundleDevelopmentRegion
5 | en
6 | CFBundleExecutable
7 | $(EXECUTABLE_NAME)
8 | CFBundleIdentifier
9 | $(PRODUCT_BUNDLE_IDENTIFIER)
10 | CFBundleInfoDictionaryVersion
11 | 6.0
12 | CFBundleName
13 | $(PRODUCT_NAME)
14 | CFBundlePackageType
15 | FMWK
16 | CFBundleShortVersionString
17 | 1.0
18 | CFBundleSignature
19 | ????
20 | CFBundleVersion
21 | $(CURRENT_PROJECT_VERSION)
22 | NSPrincipalClass
23 |
24 |
25 |
26 |
--------------------------------------------------------------------------------
/RxKingfisher.xcodeproj/RxCocoaRuntime_Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | CFBundleDevelopmentRegion
5 | en
6 | CFBundleExecutable
7 | $(EXECUTABLE_NAME)
8 | CFBundleIdentifier
9 | $(PRODUCT_BUNDLE_IDENTIFIER)
10 | CFBundleInfoDictionaryVersion
11 | 6.0
12 | CFBundleName
13 | $(PRODUCT_NAME)
14 | CFBundlePackageType
15 | FMWK
16 | CFBundleShortVersionString
17 | 1.0
18 | CFBundleSignature
19 | ????
20 | CFBundleVersion
21 | $(CURRENT_PROJECT_VERSION)
22 | NSPrincipalClass
23 |
24 |
25 |
26 |
--------------------------------------------------------------------------------
/RxKingfisher.xcodeproj/RxCocoa_Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | CFBundleDevelopmentRegion
5 | en
6 | CFBundleExecutable
7 | $(EXECUTABLE_NAME)
8 | CFBundleIdentifier
9 | $(PRODUCT_BUNDLE_IDENTIFIER)
10 | CFBundleInfoDictionaryVersion
11 | 6.0
12 | CFBundleName
13 | $(PRODUCT_NAME)
14 | CFBundlePackageType
15 | FMWK
16 | CFBundleShortVersionString
17 | 1.0
18 | CFBundleSignature
19 | ????
20 | CFBundleVersion
21 | $(CURRENT_PROJECT_VERSION)
22 | NSPrincipalClass
23 |
24 |
25 |
26 |
--------------------------------------------------------------------------------
/RxKingfisher.xcodeproj/RxKingfisherTests_Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | CFBundleDevelopmentRegion
5 | en
6 | CFBundleExecutable
7 | $(EXECUTABLE_NAME)
8 | CFBundleIdentifier
9 | $(PRODUCT_BUNDLE_IDENTIFIER)
10 | CFBundleInfoDictionaryVersion
11 | 6.0
12 | CFBundleName
13 | $(PRODUCT_NAME)
14 | CFBundlePackageType
15 | BNDL
16 | CFBundleShortVersionString
17 | 1.0
18 | CFBundleSignature
19 | ????
20 | CFBundleVersion
21 | $(CURRENT_PROJECT_VERSION)
22 | NSPrincipalClass
23 |
24 |
25 |
26 |
--------------------------------------------------------------------------------
/RxKingfisher.xcodeproj/RxKingfisher_Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | CFBundleDevelopmentRegion
5 | en
6 | CFBundleExecutable
7 | $(EXECUTABLE_NAME)
8 | CFBundleIdentifier
9 | $(PRODUCT_BUNDLE_IDENTIFIER)
10 | CFBundleInfoDictionaryVersion
11 | 6.0
12 | CFBundleName
13 | $(PRODUCT_NAME)
14 | CFBundlePackageType
15 | FMWK
16 | CFBundleShortVersionString
17 | 1.0
18 | CFBundleSignature
19 | ????
20 | CFBundleVersion
21 | $(CURRENT_PROJECT_VERSION)
22 | NSPrincipalClass
23 |
24 |
25 |
26 |
--------------------------------------------------------------------------------
/RxKingfisher.xcodeproj/RxRelay_Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | CFBundleDevelopmentRegion
5 | en
6 | CFBundleExecutable
7 | $(EXECUTABLE_NAME)
8 | CFBundleIdentifier
9 | $(PRODUCT_BUNDLE_IDENTIFIER)
10 | CFBundleInfoDictionaryVersion
11 | 6.0
12 | CFBundleName
13 | $(PRODUCT_NAME)
14 | CFBundlePackageType
15 | FMWK
16 | CFBundleShortVersionString
17 | 1.0
18 | CFBundleSignature
19 | ????
20 | CFBundleVersion
21 | $(CURRENT_PROJECT_VERSION)
22 | NSPrincipalClass
23 |
24 |
25 |
26 |
--------------------------------------------------------------------------------
/RxKingfisher.xcodeproj/RxSwift_Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | CFBundleDevelopmentRegion
5 | en
6 | CFBundleExecutable
7 | $(EXECUTABLE_NAME)
8 | CFBundleIdentifier
9 | $(PRODUCT_BUNDLE_IDENTIFIER)
10 | CFBundleInfoDictionaryVersion
11 | 6.0
12 | CFBundleName
13 | $(PRODUCT_NAME)
14 | CFBundlePackageType
15 | FMWK
16 | CFBundleShortVersionString
17 | 1.0
18 | CFBundleSignature
19 | ????
20 | CFBundleVersion
21 | $(CURRENT_PROJECT_VERSION)
22 | NSPrincipalClass
23 |
24 |
25 |
26 |
--------------------------------------------------------------------------------
/RxKingfisher.xcodeproj/project.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
--------------------------------------------------------------------------------
/RxKingfisher.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | IDEDidComputeMac32BitWarning
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/RxKingfisher.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | IDEWorkspaceSharedSettings_AutocreateContextsIfNeeded
6 |
7 |
8 |
--------------------------------------------------------------------------------
/RxKingfisher.xcodeproj/xcshareddata/xcschemes/RxKingfisher-Package.xcscheme:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
11 |
12 |
13 |
14 |
15 |
21 |
22 |
24 |
29 |
30 |
31 |
32 |
33 |
34 |
--------------------------------------------------------------------------------
/Sources/RxKingfisher/Kingfisher+Rx.swift:
--------------------------------------------------------------------------------
1 | //
2 | // RxKingfisher.swift
3 | // RxKingfisher
4 | //
5 | // Created by Shai Mishali on 5/5/18.
6 | // Copyright © 2018 RxSwift Community. All rights reserved.
7 | //
8 |
9 | import RxCocoa
10 | import RxSwift
11 | import Kingfisher
12 |
13 | extension KingfisherWrapper {
14 | public struct Rx {
15 | private let wrapper: KingfisherWrapper
16 |
17 | init(_ base: KingfisherWrapper) {
18 | self.wrapper = base
19 | }
20 |
21 | public func image(placeholder: Placeholder? = nil,
22 | options: KingfisherOptionsInfo? = nil) -> Binder {
23 | // `base.base` is the `Kingfisher` class' associated `ImageView`.
24 | return Binder(wrapper.base) { imageView, image in
25 | imageView.kf.setImage(with: image,
26 | placeholder: placeholder,
27 | options: options)
28 | }
29 | }
30 |
31 | public func setImage(with source: Source?,
32 | placeholder: Placeholder? = nil,
33 | options: KingfisherOptionsInfo? = nil) -> Single {
34 | Single.create { [wrapper] single in
35 | let task = wrapper.setImage(
36 | with: source,
37 | placeholder: placeholder,
38 | options: options,
39 | completionHandler: { result in
40 | switch result {
41 | case .success(let value):
42 | single(.success(value.image))
43 | case .failure(let error):
44 | single(.failure(error))
45 | }
46 | }
47 | )
48 |
49 | return Disposables.create { task?.cancel() }
50 | }
51 | }
52 |
53 | public func setImage(with resource: Resource?,
54 | placeholder: Placeholder? = nil,
55 | options: KingfisherOptionsInfo? = nil) -> Single {
56 | let source: Source?
57 | if let resource = resource {
58 | source = Source.network(resource)
59 | } else {
60 | source = nil
61 | }
62 | return setImage(with: source, placeholder: placeholder, options: options)
63 | }
64 | }
65 | }
66 |
67 | public extension KingfisherWrapper where Base == KFCrossPlatformImageView {
68 | var rx: KingfisherWrapper.Rx {
69 | .init(self)
70 | }
71 | }
72 |
--------------------------------------------------------------------------------
/Sources/RxKingfisher/KingfisherManager+Rx.swift:
--------------------------------------------------------------------------------
1 | //
2 | // KingfisherManager+Rx.swift
3 | // RxKingfisher
4 | //
5 | // Created by Shai Mishali on 5/5/18.
6 | // Copyright © 2018 RxSwift Community. All rights reserved.
7 | //
8 |
9 | import RxSwift
10 | import Kingfisher
11 |
12 | extension Reactive where Base == KingfisherManager {
13 | public func retrieveImage(with source: Source,
14 | options: KingfisherOptionsInfo? = nil) -> Single {
15 | return Single.create { [base] single in
16 | let task = base.retrieveImage(with: source,
17 | options: options) { result in
18 | switch result {
19 | case .success(let value):
20 | single(.success(value.image))
21 | case .failure(let error):
22 | single(.failure(error))
23 | }
24 | }
25 |
26 | return Disposables.create { task?.cancel() }
27 | }
28 | }
29 |
30 | public func retrieveImage(with resource: Resource,
31 | options: KingfisherOptionsInfo? = nil) -> Single {
32 | let source = Source.network(resource)
33 | return retrieveImage(with: source, options: options)
34 | }
35 |
36 | }
37 |
38 | extension KingfisherManager: ReactiveCompatible {
39 | public var rx: Reactive {
40 | get { return Reactive(self) }
41 | set { }
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/Tests/LinuxMain.swift:
--------------------------------------------------------------------------------
1 | import XCTest
2 | @testable import RxKingfisherTests
3 |
4 | XCTMain([
5 | testCase(RxKingfisherTests.allTests),
6 | ])
7 |
--------------------------------------------------------------------------------
/Tests/RxKingfisherTests/RxKingfisherTests.swift:
--------------------------------------------------------------------------------
1 | //
2 | // RxKingfisherTests.swift
3 | // RxSwift Community
4 | //
5 | // Created by Shai Mishali on 5/6/18.
6 | // Copyright © 2018 RxSwift Community. All rights reserved.
7 | //
8 |
9 | import Foundation
10 | import XCTest
11 |
12 | class RxKingfisherTests: XCTestCase {
13 | func testImageViewSuccess() {
14 | // TODO:
15 | }
16 |
17 | func testImageViewFailure() {
18 | // TODO:
19 | }
20 |
21 | func testImageManagerSuccess() {
22 | // TODO:
23 | }
24 |
25 | func testImageManagerFailure() {
26 | // TODO:
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/scripts/bootstrap-if-needed.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 |
3 | RED='\033[1;31m'
4 | GREEN='\033[1;32m'
5 | NC='\033[0m' # No Color
6 |
7 | if ! cmp -s Cartfile.resolved Carthage/Cartfile.resolved; then
8 | printf "${RED}Dependencies out of date with cache.${NC} Bootstrapping...\n"
9 | scripts/bootstrap.sh
10 | else
11 | printf "${GREEN}Cache up-to-date.${NC} Skipping bootstrap...\n"
12 | fi
13 |
--------------------------------------------------------------------------------
/scripts/bootstrap.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 |
3 | carthage bootstrap
4 | cp Cartfile.resolved Carthage
5 |
--------------------------------------------------------------------------------