├── SDWebImagePhotosPlugin ├── Assets │ └── .gitkeep ├── Module │ ├── SDWebImagePhotosPlugin.modulemap │ ├── Info.plist │ └── SDWebImagePhotosPlugin.h └── Classes │ ├── SDWebImagePhotosError.m │ ├── PHAsset+SDWebImagePhotosPlugin.m │ ├── PHAsset+SDWebImagePhotosPlugin.h │ ├── PHImageRequestOptions+SDWebImagePhotosPlugin.h │ ├── SDWebImagePhotosError.h │ ├── SDWebImagePhotosDefine.m │ ├── NSURL+SDWebImagePhotosPlugin.h │ ├── PHImageRequestOptions+SDWebImagePhotosPlugin.m │ ├── NSURL+SDWebImagePhotosPlugin.m │ ├── SDImagePhotosLoader.h │ ├── SDWebImagePhotosDefine.h │ └── SDImagePhotosLoader.m ├── Cartfile ├── Cartfile.resolved ├── Example ├── Tests │ ├── en.lproj │ │ └── InfoPlist.strings │ ├── Images │ │ ├── TestImage.gif │ │ ├── TestImage.jpg │ │ ├── TestImage.png │ │ ├── TestImageStatic.webp │ │ ├── TestImageAnimated.apng │ │ └── TestImageAnimated.webp │ ├── Tests-Prefix.pch │ ├── SystemAlert.h │ ├── Tests-Info.plist │ ├── SDTestCase.h │ ├── SystemAlert.m │ ├── SDTestCase.m │ └── SDPhotosPluginTests.m ├── SDWebImagePhotosPlugin │ ├── en.lproj │ │ └── InfoPlist.strings │ ├── MasterViewController.h │ ├── SDWebImagePhotosPlugin-Prefix.pch │ ├── main.m │ ├── DetailViewController.h │ ├── SDAppDelegate.h │ ├── MasterViewController.xib │ ├── SDWebImagePhotosPlugin-Info.plist │ ├── Base.lproj │ │ └── LaunchScreen.storyboard │ ├── Images.xcassets │ │ └── AppIcon.appiconset │ │ │ └── Contents.json │ ├── DetailViewController.m │ ├── DetailViewController.xib │ ├── SDAppDelegate.m │ └── MasterViewController.m ├── SDWebImagePhotosPlugin_Example macOS │ ├── Assets.xcassets │ │ ├── Contents.json │ │ └── AppIcon.appiconset │ │ │ └── Contents.json │ ├── ViewController.h │ ├── main.m │ ├── AppDelegate.h │ ├── TestCollectionViewItem.h │ ├── TestCollectionViewItem.m │ ├── SDWebImagePhotosPlugin_Example_macOS.entitlements │ ├── AppDelegate.m │ ├── Info.plist │ ├── TestCollectionViewItem.xib │ └── ViewController.m ├── SDWebImagePhotosPlugin.xcodeproj │ ├── project.xcworkspace │ │ └── contents.xcworkspacedata │ └── xcshareddata │ │ └── xcschemes │ │ ├── SDWebImagePhotosPlugin_Tests.xcscheme │ │ ├── SDWebImagePhotosPlugin_Example macOS.xcscheme │ │ └── SDWebImagePhotosPlugin-Example.xcscheme ├── SDWebImagePhotosPlugin.xcworkspace │ ├── xcshareddata │ │ └── WorkspaceSettings.xcsettings │ └── contents.xcworkspacedata ├── Podfile └── SDWebImagePhotosPlugin_Example.entitlements ├── SDWebImagePhotosPlugin.xcodeproj ├── project.xcworkspace │ └── contents.xcworkspacedata ├── xcshareddata │ └── xcschemes │ │ ├── SDWebImagePhotosPlugin.xcscheme │ │ ├── SDWebImagePhotosPlugin-tvOS.xcscheme │ │ └── SDWebImagePhotosPlugin-macOS.xcscheme └── project.pbxproj ├── Package.resolved ├── .github ├── ISSUE_TEMPLATE │ ├── feature_request.md │ └── bug_report.md ├── config.yml └── stale.yml ├── .gitignore ├── LICENSE ├── Package.swift ├── .travis.yml ├── SDWebImagePhotosPlugin.podspec └── README.md /SDWebImagePhotosPlugin/Assets/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /Cartfile: -------------------------------------------------------------------------------- 1 | github "SDWebImage/SDWebImage" ~> 5.10 -------------------------------------------------------------------------------- /Cartfile.resolved: -------------------------------------------------------------------------------- 1 | github "SDWebImage/SDWebImage" "5.8.3" 2 | -------------------------------------------------------------------------------- /Example/Tests/en.lproj/InfoPlist.strings: -------------------------------------------------------------------------------- 1 | /* Localized versions of Info.plist keys */ 2 | 3 | -------------------------------------------------------------------------------- /Example/SDWebImagePhotosPlugin/en.lproj/InfoPlist.strings: -------------------------------------------------------------------------------- 1 | /* Localized versions of Info.plist keys */ 2 | 3 | -------------------------------------------------------------------------------- /Example/Tests/Images/TestImage.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SDWebImage/SDWebImagePhotosPlugin/HEAD/Example/Tests/Images/TestImage.gif -------------------------------------------------------------------------------- /Example/Tests/Images/TestImage.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SDWebImage/SDWebImagePhotosPlugin/HEAD/Example/Tests/Images/TestImage.jpg -------------------------------------------------------------------------------- /Example/Tests/Images/TestImage.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SDWebImage/SDWebImagePhotosPlugin/HEAD/Example/Tests/Images/TestImage.png -------------------------------------------------------------------------------- /Example/Tests/Images/TestImageStatic.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SDWebImage/SDWebImagePhotosPlugin/HEAD/Example/Tests/Images/TestImageStatic.webp -------------------------------------------------------------------------------- /Example/SDWebImagePhotosPlugin_Example macOS/Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "version" : 1, 4 | "author" : "xcode" 5 | } 6 | } -------------------------------------------------------------------------------- /Example/Tests/Images/TestImageAnimated.apng: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SDWebImage/SDWebImagePhotosPlugin/HEAD/Example/Tests/Images/TestImageAnimated.apng -------------------------------------------------------------------------------- /Example/Tests/Images/TestImageAnimated.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SDWebImage/SDWebImagePhotosPlugin/HEAD/Example/Tests/Images/TestImageAnimated.webp -------------------------------------------------------------------------------- /Example/Tests/Tests-Prefix.pch: -------------------------------------------------------------------------------- 1 | // The contents of this file are implicitly included at the beginning of every test case source file. 2 | 3 | #ifdef __OBJC__ 4 | 5 | 6 | 7 | #endif 8 | -------------------------------------------------------------------------------- /SDWebImagePhotosPlugin/Module/SDWebImagePhotosPlugin.modulemap: -------------------------------------------------------------------------------- 1 | framework module SDWebImagePhotosPlugin { 2 | umbrella header "SDWebImagePhotosPlugin.h" 3 | 4 | export * 5 | module * { export * } 6 | } 7 | -------------------------------------------------------------------------------- /SDWebImagePhotosPlugin.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /Example/SDWebImagePhotosPlugin.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /Example/SDWebImagePhotosPlugin.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | PreviewsEnabled 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /Example/SDWebImagePhotosPlugin.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /Example/SDWebImagePhotosPlugin_Example macOS/ViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.h 3 | // SDWebImagePhotosPlugin_Example macOS 4 | // 5 | // Created by lizhuoli on 2018/7/19. 6 | // Copyright © 2018年 DreamPiggy. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface ViewController : NSViewController 12 | 13 | 14 | @end 15 | 16 | -------------------------------------------------------------------------------- /Example/SDWebImagePhotosPlugin_Example macOS/main.m: -------------------------------------------------------------------------------- 1 | // 2 | // main.m 3 | // SDWebImagePhotosPlugin_Example macOS 4 | // 5 | // Created by lizhuoli on 2018/7/19. 6 | // Copyright © 2018年 DreamPiggy. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | int main(int argc, const char * argv[]) { 12 | return NSApplicationMain(argc, argv); 13 | } 14 | -------------------------------------------------------------------------------- /Example/SDWebImagePhotosPlugin_Example macOS/AppDelegate.h: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.h 3 | // SDWebImagePhotosPlugin_Example macOS 4 | // 5 | // Created by lizhuoli on 2018/7/19. 6 | // Copyright © 2018年 DreamPiggy. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface AppDelegate : NSObject 12 | 13 | 14 | @end 15 | 16 | -------------------------------------------------------------------------------- /Package.resolved: -------------------------------------------------------------------------------- 1 | { 2 | "object": { 3 | "pins": [ 4 | { 5 | "package": "SDWebImage", 6 | "repositoryURL": "https://github.com/SDWebImage/SDWebImage.git", 7 | "state": { 8 | "branch": null, 9 | "revision": "0a3cd255a655b73fb3b3437acf2ab506b5c0c9c6", 10 | "version": "5.1.0" 11 | } 12 | } 13 | ] 14 | }, 15 | "version": 1 16 | } 17 | -------------------------------------------------------------------------------- /Example/SDWebImagePhotosPlugin/MasterViewController.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the SDWebImage package. 3 | * (c) Olivier Poitrey 4 | * 5 | * For the full copyright and license information, please view the LICENSE 6 | * file that was distributed with this source code. 7 | */ 8 | 9 | #import 10 | 11 | @interface MasterViewController : UITableViewController 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /Example/SDWebImagePhotosPlugin_Example macOS/TestCollectionViewItem.h: -------------------------------------------------------------------------------- 1 | // 2 | // TestCollectionViewItem.h 3 | // SDWebImagePhotosPlugin_Example macOS 4 | // 5 | // Created by lizhuoli on 2019/4/3. 6 | // Copyright © 2019 DreamPiggy. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface TestCollectionViewItem : NSCollectionViewItem 12 | 13 | @property (weak) IBOutlet NSImageView *imageViewDisplay; 14 | 15 | @end 16 | -------------------------------------------------------------------------------- /Example/SDWebImagePhotosPlugin/SDWebImagePhotosPlugin-Prefix.pch: -------------------------------------------------------------------------------- 1 | // 2 | // Prefix header 3 | // 4 | // The contents of this file are implicitly included at the beginning of every source file. 5 | // 6 | 7 | #import 8 | 9 | #ifndef __IPHONE_5_0 10 | #warning "This project uses features only available in iOS SDK 5.0 and later." 11 | #endif 12 | 13 | #ifdef __OBJC__ 14 | @import UIKit; 15 | @import Foundation; 16 | #endif 17 | -------------------------------------------------------------------------------- /SDWebImagePhotosPlugin/Classes/SDWebImagePhotosError.m: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the SDWebImage package. 3 | * (c) Olivier Poitrey 4 | * 5 | * For the full copyright and license information, please view the LICENSE 6 | * file that was distributed with this source code. 7 | */ 8 | 9 | #import "SDWebImagePhotosError.h" 10 | 11 | NSErrorDomain const _Nonnull SDWebImagePhotosErrorDomain = @"SDWebImagePhotosErrorDomain"; 12 | -------------------------------------------------------------------------------- /Example/SDWebImagePhotosPlugin/main.m: -------------------------------------------------------------------------------- 1 | // 2 | // main.m 3 | // SDWebImagePhotosPlugin 4 | // 5 | // Created by DreamPiggy on 05/07/2018. 6 | // Copyright (c) 2018 DreamPiggy. All rights reserved. 7 | // 8 | 9 | @import UIKit; 10 | #import "SDAppDelegate.h" 11 | 12 | int main(int argc, char * argv[]) 13 | { 14 | @autoreleasepool { 15 | return UIApplicationMain(argc, argv, nil, NSStringFromClass([SDAppDelegate class])); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /Example/Tests/SystemAlert.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the SDWebImagePhotosPlugin package. 3 | * 4 | * For the full copyright and license information, please view the LICENSE 5 | * file that was distributed with this source code. 6 | */ 7 | 8 | #import 9 | 10 | // Automation API to force tap current system alert 11 | @interface SystemAlert : NSObject 12 | + (void)tapLeftButton; 13 | + (void)tapRightButton; 14 | @end 15 | -------------------------------------------------------------------------------- /Example/Podfile: -------------------------------------------------------------------------------- 1 | use_frameworks! 2 | inhibit_all_warnings! 3 | 4 | target 'SDWebImagePhotosPlugin_Example' do 5 | platform :ios, '9.0' 6 | pod 'SDWebImagePhotosPlugin', :path => '../' 7 | 8 | target 'SDWebImagePhotosPlugin_Tests' do 9 | inherit! :search_paths 10 | pod 'Expecta' 11 | 12 | end 13 | end 14 | 15 | target 'SDWebImagePhotosPlugin_Example macOS' do 16 | platform :osx, '10.13' 17 | pod 'SDWebImagePhotosPlugin', :path => '../' 18 | end -------------------------------------------------------------------------------- /Example/SDWebImagePhotosPlugin_Example.entitlements: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | com.apple.security.app-sandbox 6 | 7 | com.apple.security.network.client 8 | 9 | com.apple.security.personal-information.photos-library 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /Example/SDWebImagePhotosPlugin/DetailViewController.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the SDWebImage package. 3 | * (c) Olivier Poitrey 4 | * 5 | * For the full copyright and license information, please view the LICENSE 6 | * file that was distributed with this source code. 7 | */ 8 | 9 | #import 10 | 11 | @interface DetailViewController : UIViewController 12 | 13 | @property (strong, nonatomic) NSURL *imageURL; 14 | 15 | @end 16 | -------------------------------------------------------------------------------- /Example/SDWebImagePhotosPlugin_Example macOS/TestCollectionViewItem.m: -------------------------------------------------------------------------------- 1 | // 2 | // TestCollectionViewItem.m 3 | // SDWebImagePhotosPlugin_Example macOS 4 | // 5 | // Created by lizhuoli on 2019/4/3. 6 | // Copyright © 2019 DreamPiggy. All rights reserved. 7 | // 8 | 9 | #import "TestCollectionViewItem.h" 10 | 11 | @interface TestCollectionViewItem () 12 | 13 | @end 14 | 15 | @implementation TestCollectionViewItem 16 | 17 | - (void)viewDidLoad { 18 | [super viewDidLoad]; 19 | } 20 | 21 | @end 22 | -------------------------------------------------------------------------------- /Example/SDWebImagePhotosPlugin_Example macOS/SDWebImagePhotosPlugin_Example_macOS.entitlements: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | com.apple.security.app-sandbox 6 | 7 | com.apple.security.files.user-selected.read-only 8 | 9 | com.apple.security.assets.pictures.read-write 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /Example/SDWebImagePhotosPlugin/SDAppDelegate.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the SDWebImage package. 3 | * (c) Olivier Poitrey 4 | * 5 | * For the full copyright and license information, please view the LICENSE 6 | * file that was distributed with this source code. 7 | */ 8 | 9 | @import UIKit; 10 | 11 | @interface SDAppDelegate : UIResponder 12 | 13 | @property (strong, nonatomic) UIWindow *window; 14 | 15 | @property (strong, nonatomic) UINavigationController *navigationController; 16 | 17 | @end 18 | -------------------------------------------------------------------------------- /SDWebImagePhotosPlugin/Classes/PHAsset+SDWebImagePhotosPlugin.m: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the SDWebImage package. 3 | * (c) Olivier Poitrey 4 | * 5 | * For the full copyright and license information, please view the LICENSE 6 | * file that was distributed with this source code. 7 | */ 8 | 9 | #import "PHAsset+SDWebImagePhotosPlugin.h" 10 | #import "NSURL+SDWebImagePhotosPlugin.h" 11 | 12 | @implementation PHAsset (SDWebImagePhotosPlugin) 13 | 14 | - (NSURL *)sd_URLRepresentation { 15 | return [NSURL sd_URLWithAsset:self]; 16 | } 17 | 18 | @end 19 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature request 3 | about: Suggest an idea for this project 4 | 5 | --- 6 | 7 | ### New Feature Request Checklist 8 | 9 | * [ ] I have checked the current documentations or APIs and does not find a solution 10 | * [ ] I have searched for a similar issue in the [project](https://github.com/SDWebImage/SDWebImagePhotosPlugin/issues) and found none 11 | 12 | 13 | ### Feature Request Description 14 | 15 | Please fill in the detailed description about feature request, including the feature use case (what you need) and the solution you want (like usage, demo code, ...) 16 | -------------------------------------------------------------------------------- /SDWebImagePhotosPlugin/Classes/PHAsset+SDWebImagePhotosPlugin.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the SDWebImage package. 3 | * (c) Olivier Poitrey 4 | * 5 | * For the full copyright and license information, please view the LICENSE 6 | * file that was distributed with this source code. 7 | */ 8 | 9 | #import 10 | 11 | @interface PHAsset (SDWebImagePhotosPlugin) 12 | 13 | /// The convenience way to retrive the URL representation of PHAsset. The same as `+[NSURL sd_URLWithAsset:]`. 14 | /// @note This API always create and return new object in Objective-C/struct in Swift of URL. (which does not store the URL inside PHAssets, to avoid retain cycle) 15 | @property (nonatomic, strong, readonly, nonnull) NSURL *sd_URLRepresentation; 16 | 17 | @end 18 | -------------------------------------------------------------------------------- /Example/Tests/Tests-Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | ${EXECUTABLE_NAME} 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundlePackageType 14 | BNDL 15 | CFBundleShortVersionString 16 | 1.0 17 | CFBundleSignature 18 | ???? 19 | CFBundleVersion 20 | 1 21 | 22 | 23 | -------------------------------------------------------------------------------- /SDWebImagePhotosPlugin/Module/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 | FMWK 17 | CFBundleShortVersionString 18 | 1.2.1 19 | CFBundleVersion 20 | 1.2.1 21 | NSPrincipalClass 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /SDWebImagePhotosPlugin/Module/SDWebImagePhotosPlugin.h: -------------------------------------------------------------------------------- 1 | #ifdef __OBJC__ 2 | #if __has_include() 3 | #import 4 | #endif 5 | #else 6 | #ifndef FOUNDATION_EXPORT 7 | #if defined(__cplusplus) 8 | #define FOUNDATION_EXPORT extern "C" 9 | #else 10 | #define FOUNDATION_EXPORT extern 11 | #endif 12 | #endif 13 | #endif 14 | 15 | #import 16 | #import 17 | #import 18 | #import 19 | #import 20 | #import 21 | 22 | FOUNDATION_EXPORT double SDWebImagePhotosPluginVersionNumber; 23 | FOUNDATION_EXPORT const unsigned char SDWebImagePhotosPluginVersionString[]; 24 | 25 | -------------------------------------------------------------------------------- /SDWebImagePhotosPlugin/Classes/PHImageRequestOptions+SDWebImagePhotosPlugin.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the SDWebImage package. 3 | * (c) Olivier Poitrey 4 | * 5 | * For the full copyright and license information, please view the LICENSE 6 | * file that was distributed with this source code. 7 | */ 8 | 9 | #import 10 | 11 | /// PHImageRequestOptions category to provide targetSize and contentMode when fetch Photos image asset 12 | @interface PHImageRequestOptions (SDWebImagePhotosPlugin) 13 | 14 | /** 15 | The `targetSize` value for image asset request. Defaults to `PHImageManagerMaximumSize`. 16 | */ 17 | @property (nonatomic, assign) CGSize sd_targetSize; 18 | 19 | /** 20 | The `contentMode` value for image asset request. Defaults to `PHImageContentModeDefault`. 21 | */ 22 | @property (nonatomic, assign) PHImageContentMode sd_contentMode; 23 | 24 | @end 25 | -------------------------------------------------------------------------------- /SDWebImagePhotosPlugin/Classes/SDWebImagePhotosError.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the SDWebImage package. 3 | * (c) Olivier Poitrey 4 | * 5 | * For the full copyright and license information, please view the LICENSE 6 | * file that was distributed with this source code. 7 | */ 8 | 9 | #import 10 | 11 | FOUNDATION_EXPORT NSErrorDomain const SDWebImagePhotosErrorDomain; 12 | 13 | /// The error domain for SDWebImagePhotosPlugin's NSError 14 | typedef NS_ERROR_ENUM(SDWebImagePhotosErrorDomain, SDWebImagePhotosError) { 15 | /// Photos framework access is not authorized by user 16 | SDWebImagePhotosErrorNotAuthorized = 10001, 17 | /// Photos URL is not image asset type (like Video or Audio) 18 | SDWebImagePhotosErrorNotImageAsset = 10002, 19 | /// Photos local identifier failed to query PHAsset, is this valid ? 20 | SDWebImagePhotosErrorInvalidLocalIdentifier = 10003 21 | }; 22 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # OS X 2 | .DS_Store 3 | 4 | # Xcode 5 | build/ 6 | *.pbxuser 7 | !default.pbxuser 8 | *.mode1v3 9 | !default.mode1v3 10 | *.mode2v3 11 | !default.mode2v3 12 | *.perspectivev3 13 | !default.perspectivev3 14 | xcuserdata/ 15 | *.xccheckout 16 | profile 17 | *.moved-aside 18 | DerivedData 19 | *.hmap 20 | *.ipa 21 | 22 | # Bundler 23 | .bundle 24 | 25 | # Add this line if you want to avoid checking in source code from Carthage dependencies. 26 | Carthage/Checkouts 27 | Carthage/Build 28 | 29 | # We recommend against adding the Pods directory to your .gitignore. However 30 | # you should judge for yourself, the pros and cons are mentioned at: 31 | # https://guides.cocoapods.org/using/using-cocoapods.html#should-i-ignore-the-pods-directory-in-source-control 32 | # 33 | # Note: if you ignore the Pods directory, make sure to uncomment 34 | # `pod install` in .travis.yml 35 | # 36 | Example/Pods 37 | Example/Podfile.lock 38 | 39 | # SwiftPM 40 | .swiftpm 41 | .build 42 | -------------------------------------------------------------------------------- /SDWebImagePhotosPlugin/Classes/SDWebImagePhotosDefine.m: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the SDWebImage package. 3 | * (c) Olivier Poitrey 4 | * 5 | * For the full copyright and license information, please view the LICENSE 6 | * file that was distributed with this source code. 7 | */ 8 | 9 | #import "SDWebImagePhotosDefine.h" 10 | 11 | NSString * _Nonnull const SDWebImagePhotosScheme = @"ph"; 12 | // PHImageManagerMaximumSize value is (-1.0, -1.0) 13 | const CGSize SDWebImagePhotosPixelSize = {.width = -2.0, .height = -2.0}; 14 | const CGSize SDWebImagePhotosPointSize = {.width = -3.0, .height = -3.0}; 15 | const int64_t SDWebImagePhotosProgressExpectedSize = 100LL; 16 | 17 | SDWebImageContextOption _Nonnull const SDWebImageContextPhotosFetchOptions = @"photosFetchOptions"; 18 | SDWebImageContextOption _Nonnull const SDWebImageContextPhotosImageRequestOptions = @"photosImageRequestOptions"; 19 | SDWebImageContextOption _Nonnull const SDWebImageContextPhotosRequestImageData = @"photosRequestImageData"; 20 | -------------------------------------------------------------------------------- /Example/SDWebImagePhotosPlugin_Example macOS/AppDelegate.m: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.m 3 | // SDWebImagePhotosPlugin_Example macOS 4 | // 5 | // Created by lizhuoli on 2018/7/19. 6 | // Copyright © 2018年 DreamPiggy. All rights reserved. 7 | // 8 | 9 | #import "AppDelegate.h" 10 | #import 11 | 12 | @interface AppDelegate () 13 | 14 | @end 15 | 16 | @implementation AppDelegate 17 | 18 | - (void)applicationDidFinishLaunching:(NSNotification *)aNotification { 19 | // Insert code here to initialize your application 20 | if (@available(macOS 11.0, *)) { 21 | [SDImageCodersManager.sharedManager addCoder:SDImageAWebPCoder.sharedCoder]; 22 | } 23 | [SDImageCodersManager.sharedManager addCoder:SDImageHEICCoder.sharedCoder]; 24 | } 25 | 26 | 27 | - (void)applicationWillTerminate:(NSNotification *)aNotification { 28 | // Insert code here to tear down your application 29 | } 30 | 31 | - (IBAction)reloadButtonDidTap:(NSMenuItem *)sender { 32 | // Menu item target-action 33 | } 34 | 35 | @end 36 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2018 DreamPiggy 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy 4 | of this software and associated documentation files (the "Software"), to deal 5 | in the Software without restriction, including without limitation the rights 6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | copies of the Software, and to permit persons to whom the Software is 8 | furnished to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in 11 | all copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | THE SOFTWARE. 20 | -------------------------------------------------------------------------------- /Example/Tests/SDTestCase.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the SDWebImagePhotosPlugin package. 3 | * 4 | * For the full copyright and license information, please view the LICENSE 5 | * file that was distributed with this source code. 6 | */ 7 | 8 | #define EXP_SHORTHAND // required by Expecta 9 | 10 | 11 | #import 12 | #import 13 | #import 14 | #import 15 | 16 | FOUNDATION_EXPORT const int64_t kAsyncTestTimeout; 17 | FOUNDATION_EXPORT const int64_t kMinDelayNanosecond; 18 | FOUNDATION_EXPORT NSString * _Nonnull const kTestJPEGURL; 19 | FOUNDATION_EXPORT NSString * _Nonnull const kTestProgressiveJPEGURL; 20 | FOUNDATION_EXPORT NSString * _Nonnull const kTestPNGURL; 21 | FOUNDATION_EXPORT NSString * _Nonnull const kTestGIFURL; 22 | FOUNDATION_EXPORT NSString * _Nonnull const kTestWebPURL; 23 | FOUNDATION_EXPORT NSString * _Nonnull const kTestAPNGPURL; 24 | 25 | @interface SDTestCase : XCTestCase 26 | 27 | - (void)waitForExpectationsWithCommonTimeout; 28 | - (void)waitForExpectationsWithCommonTimeoutUsingHandler:(nullable XCWaitCompletionHandler)handler; 29 | 30 | @end 31 | -------------------------------------------------------------------------------- /Example/SDWebImagePhotosPlugin_Example macOS/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "mac", 5 | "size" : "16x16", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "mac", 10 | "size" : "16x16", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "mac", 15 | "size" : "32x32", 16 | "scale" : "1x" 17 | }, 18 | { 19 | "idiom" : "mac", 20 | "size" : "32x32", 21 | "scale" : "2x" 22 | }, 23 | { 24 | "idiom" : "mac", 25 | "size" : "128x128", 26 | "scale" : "1x" 27 | }, 28 | { 29 | "idiom" : "mac", 30 | "size" : "128x128", 31 | "scale" : "2x" 32 | }, 33 | { 34 | "idiom" : "mac", 35 | "size" : "256x256", 36 | "scale" : "1x" 37 | }, 38 | { 39 | "idiom" : "mac", 40 | "size" : "256x256", 41 | "scale" : "2x" 42 | }, 43 | { 44 | "idiom" : "mac", 45 | "size" : "512x512", 46 | "scale" : "1x" 47 | }, 48 | { 49 | "idiom" : "mac", 50 | "size" : "512x512", 51 | "scale" : "2x" 52 | } 53 | ], 54 | "info" : { 55 | "version" : 1, 56 | "author" : "xcode" 57 | } 58 | } -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: Create a report to help us improve 4 | 5 | --- 6 | 7 | ### New Issue Checklist 8 | 9 | * [ ] I have read the tutorial [usage](https://github.com/SDWebImage/SDWebImagePhotosPlugin#usage) 10 | * [ ] I have searched for a similar issue in the [project](https://github.com/SDWebImage/SDWebImagePhotosPlugin/issues) and found none 11 | 12 | ### Issue Info 13 | 14 | Info | Value | 15 | -------------------------|-------------------------------------| 16 | Platform Name | e.g. ios / macos / tvos 17 | Platform Version | e.g. 11.0 / 10.13.0 / 11.0 18 | Framework Version | e.g. 0.1.1 19 | Integration Method | e.g. carthage / cocoapods 20 | Xcode Version | e.g. Xcode 9 21 | Repro rate | e.g. all the time (100%) / sometimes x% / only once 22 | Repro with our demo prj | e.g. does it happen with our demo project? 23 | Demo project link | e.g. link to a demo project that highlights the issue 24 | 25 | ### Issue Description and Steps 26 | 27 | Please fill in the detailed description of the issue (full output of any stack trace, compiler error, ...) and the steps to reproduce the issue. 28 | -------------------------------------------------------------------------------- /Example/Tests/SystemAlert.m: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the SDWebImagePhotosPlugin package. 3 | * 4 | * For the full copyright and license information, please view the LICENSE 5 | * file that was distributed with this source code. 6 | */ 7 | 8 | #import "SystemAlert.h" 9 | #import "dlfcn.h" 10 | 11 | @interface SystemAlert (ForMethodCompletionOnly) 12 | + (id)localTarget; 13 | - (id)frontMostApp; 14 | - (id)alert; 15 | - (id)buttons; 16 | - (void)tap; 17 | @end 18 | 19 | @implementation SystemAlert 20 | 21 | + (void)load { 22 | dlopen([@"/Developer/Library/PrivateFrameworks/UIAutomation.framework/UIAutomation" fileSystemRepresentation], RTLD_LOCAL); 23 | } 24 | 25 | + (NSArray *)currentButtons { 26 | id localTarget = [NSClassFromString(@"UIATarget") localTarget]; 27 | id app = [localTarget frontMostApp]; 28 | id alert = [app alert]; 29 | id buttons = [alert buttons]; 30 | if (![buttons isKindOfClass:[NSArray class]]) { 31 | return nil; 32 | } 33 | return buttons; 34 | } 35 | 36 | + (void)tapLeftButton { 37 | id button = [self currentButtons].firstObject; 38 | [button tap]; 39 | } 40 | 41 | + (void)tapRightButton { 42 | id button = [self currentButtons].lastObject; 43 | [button tap]; 44 | } 45 | 46 | @end 47 | -------------------------------------------------------------------------------- /Example/SDWebImagePhotosPlugin_Example macOS/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | $(DEVELOPMENT_LANGUAGE) 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIconFile 10 | 11 | CFBundleIdentifier 12 | $(PRODUCT_BUNDLE_IDENTIFIER) 13 | CFBundleInfoDictionaryVersion 14 | 6.0 15 | CFBundleName 16 | $(PRODUCT_NAME) 17 | CFBundlePackageType 18 | APPL 19 | CFBundleShortVersionString 20 | 1.0 21 | CFBundleVersion 22 | 1 23 | LSMinimumSystemVersion 24 | $(MACOSX_DEPLOYMENT_TARGET) 25 | NSHumanReadableCopyright 26 | Copyright © 2018年 DreamPiggy. All rights reserved. 27 | NSMainStoryboardFile 28 | Main 29 | NSPhotoLibraryUsageDescription 30 | Allow SDWebImage Demo to show Photos Library images 31 | NSPrincipalClass 32 | NSApplication 33 | 34 | 35 | -------------------------------------------------------------------------------- /Example/Tests/SDTestCase.m: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the SDWebImagePhotosPlugin package. 3 | * 4 | * For the full copyright and license information, please view the LICENSE 5 | * file that was distributed with this source code. 6 | */ 7 | 8 | #import "SDTestCase.h" 9 | 10 | const int64_t kAsyncTestTimeout = 5; 11 | const int64_t kMinDelayNanosecond = NSEC_PER_MSEC * 100; // 0.1s 12 | NSString *const kTestJPEGURL = @"http://via.placeholder.com/50x50.jpg"; 13 | NSString *const kTestProgressiveJPEGURL = @"https://raw.githubusercontent.com/ibireme/YYImage/master/Demo/YYImageDemo/mew_progressive.jpg"; 14 | NSString *const kTestPNGURL = @"http://via.placeholder.com/50x50.png"; 15 | NSString *const kTestGIFURL = @"https://media.giphy.com/media/UEsrLdv7ugRTq/giphy.gif"; 16 | NSString *const kTestWebPURL = @"http://littlesvr.ca/apng/images/SteamEngine.webp"; 17 | NSString *const kTestAPNGPURL = @"https://upload.wikimedia.org/wikipedia/commons/1/14/Animated_PNG_example_bouncing_beach_ball.png"; 18 | 19 | @implementation SDTestCase 20 | 21 | - (void)waitForExpectationsWithCommonTimeout { 22 | [self waitForExpectationsWithCommonTimeoutUsingHandler:nil]; 23 | } 24 | 25 | - (void)waitForExpectationsWithCommonTimeoutUsingHandler:(XCWaitCompletionHandler)handler { 26 | [self waitForExpectationsWithTimeout:kAsyncTestTimeout handler:handler]; 27 | } 28 | 29 | @end 30 | -------------------------------------------------------------------------------- /Package.swift: -------------------------------------------------------------------------------- 1 | // swift-tools-version:5.0 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: "SDWebImagePhotosPlugin", 8 | platforms: [ 9 | .macOS(.v10_13), .iOS(.v9), .tvOS(.v10) 10 | ], 11 | products: [ 12 | // Products define the executables and libraries produced by a package, and make them visible to other packages. 13 | .library( 14 | name: "SDWebImagePhotosPlugin", 15 | targets: ["SDWebImagePhotosPlugin"]), 16 | ], 17 | dependencies: [ 18 | // Dependencies declare other packages that this package depends on. 19 | // .package(url: /* package url */, from: "1.0.0"), 20 | .package(url: "https://github.com/SDWebImage/SDWebImage.git", from: "5.10.0") 21 | ], 22 | targets: [ 23 | // Targets are the basic building blocks of a package. A target can define a module or a test suite. 24 | // Targets can depend on other targets in this package, and on products in packages which this package depends on. 25 | .target( 26 | name: "SDWebImagePhotosPlugin", 27 | dependencies: ["SDWebImage"], 28 | path: ".", 29 | sources: ["SDWebImagePhotosPlugin/Classes"], 30 | publicHeadersPath: "SDWebImagePhotosPlugin/Classes" 31 | ) 32 | ] 33 | ) 34 | -------------------------------------------------------------------------------- /SDWebImagePhotosPlugin/Classes/NSURL+SDWebImagePhotosPlugin.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the SDWebImage package. 3 | * (c) Olivier Poitrey 4 | * 5 | * For the full copyright and license information, please view the LICENSE 6 | * file that was distributed with this source code. 7 | */ 8 | 9 | #import 10 | 11 | @class PHAsset; 12 | /// NSURL category for Photos URL support 13 | @interface NSURL (SDWebImagePhotosPlugin) 14 | 15 | /** 16 | The localIdentifier value for Photos URL, or nil for other URL. 17 | */ 18 | @property (nonatomic, copy, readonly, nullable) NSString *sd_assetLocalIdentifier; 19 | 20 | /** 21 | The `PHAsset` value for Photos URL, or nil for other URL, or the `PHAsset` is not availble. 22 | */ 23 | @property (nonatomic, strong, readonly, nullable) PHAsset *sd_asset; 24 | 25 | /** 26 | Check whether the current URL represents Photos URL. 27 | */ 28 | @property (nonatomic, assign, readonly) BOOL sd_isPhotosURL; 29 | 30 | /** 31 | Create a Photos URL with `PHAsset` 's local identifier 32 | 33 | @param identifier `PHAsset` 's local identifier 34 | @return A Photos URL 35 | */ 36 | + (nonnull instancetype)sd_URLWithAssetLocalIdentifier:(nonnull NSString *)identifier; 37 | 38 | /** 39 | Create a Photos URL with `PHAsset` 40 | 41 | @param asset `PHAsset` object 42 | @return A Photos URL 43 | */ 44 | + (nonnull instancetype)sd_URLWithAsset:(nonnull PHAsset *)asset; 45 | 46 | @end 47 | -------------------------------------------------------------------------------- /.github/config.yml: -------------------------------------------------------------------------------- 1 | # Configuration for request-info - https://github.com/behaviorbot/request-info 2 | 3 | # *OPTIONAL* Comment to reply with 4 | # Can be either a string : 5 | requestInfoReplyComment: > 6 | Hi there! We found that the issue does not follow the issue template. Please fill it to provide the basic information for us to investigate the issue, thanks! 7 | 8 | # Or an array: 9 | # requestInfoReplyComment: 10 | # - Ah no! young blade! That was a trifle short! 11 | # - Tell me more ! 12 | # - I am sure you can be more effusive 13 | 14 | 15 | # *OPTIONAL* default titles to check against for lack of descriptiveness 16 | # MUST BE ALL LOWERCASE 17 | # requestInfoDefaultTitles: 18 | # - update readme.md 19 | # - updates 20 | 21 | # *OPTIONAL* Label to be added to Issues and Pull Requests with insufficient information given 22 | requestInfoLabelToAdd: needs more info 23 | 24 | # *OPTIONAL* Require Pull Requests to contain more information than what is provided in the PR template 25 | # Will fail if the pull request's body is equal to the provided template 26 | checkPullRequestTemplate: true 27 | 28 | # *OPTIONAL* Only warn about insufficient information on these events type 29 | # Keys must be lowercase. Valid values are 'issue' and 'pullRequest' 30 | requestInfoOn: 31 | pullRequest: false 32 | issue: true 33 | 34 | # *OPTIONAL* Add a list of people whose Issues/PRs will not be commented on 35 | # keys must be GitHub usernames 36 | # requestInfoUserstoExclude: 37 | # - hiimbex 38 | # - bexo -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: objective-c 2 | osx_image: xcode11.2 3 | 4 | env: 5 | global: 6 | - LC_CTYPE=en_US.UTF-8 7 | - LANG=en_US.UTF-8 8 | 9 | addons: 10 | ssh_known_hosts: github.com 11 | 12 | notifications: 13 | email: false 14 | 15 | before_install: 16 | - env 17 | - locale 18 | - gem install cocoapods --no-document --quiet 19 | - gem install xcpretty --no-document --quiet 20 | - pod --version 21 | - pod repo update --silent 22 | - xcpretty --version 23 | - xcodebuild -version 24 | - xcodebuild -showsdks 25 | 26 | script: 27 | - set -o pipefail 28 | 29 | - echo Check if the library described by the podspec can be built 30 | - pod lib lint --allow-warnings 31 | 32 | - echo Build example 33 | - pod install --project-directory=Example 34 | - xcodebuild build -workspace Example/SDWebImagePhotosPlugin.xcworkspace -scheme SDWebImagePhotosPlugin-Example -destination 'platform=iOS Simulator,name=iPhone 11 Pro' -configuration Debug | xcpretty -c 35 | 36 | - echo Clean DerivedData 37 | - rm -rf ~/Library/Developer/Xcode/DerivedData/ 38 | - mkdir DerivedData 39 | 40 | - echo Run the tests 41 | - xcodebuild test -workspace Example/SDWebImagePhotosPlugin.xcworkspace -scheme 'SDWebImagePhotosPlugin_Tests' -destination 'platform=iOS Simulator,name=iPhone 11 Pro' -configuration Debug | xcpretty -c 42 | - mv ~/Library/Developer/Xcode/DerivedData/ ./DerivedData/iOS 43 | 44 | after_success: 45 | - bash <(curl -s https://codecov.io/bash) -D './DerivedData/iOS' -J '^SDWebImagePhotosPlugin$' -F 'iOS' -------------------------------------------------------------------------------- /SDWebImagePhotosPlugin/Classes/PHImageRequestOptions+SDWebImagePhotosPlugin.m: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the SDWebImage package. 3 | * (c) Olivier Poitrey 4 | * 5 | * For the full copyright and license information, please view the LICENSE 6 | * file that was distributed with this source code. 7 | */ 8 | 9 | #import "PHImageRequestOptions+SDWebImagePhotosPlugin.h" 10 | #import "SDWebImagePhotosDefine.h" 11 | #import 12 | 13 | @implementation PHImageRequestOptions (SDWebImagePhotosPlugin) 14 | 15 | - (CGSize)sd_targetSize { 16 | NSValue *value = objc_getAssociatedObject(self, @selector(sd_targetSize)); 17 | if (!value) { 18 | return PHImageManagerMaximumSize; 19 | } 20 | #if SD_MAC 21 | CGSize targetSize = value.sizeValue; 22 | #else 23 | CGSize targetSize = value.CGSizeValue; 24 | #endif 25 | return targetSize; 26 | } 27 | 28 | - (void)setSd_targetSize:(CGSize)sd_targetSize { 29 | objc_setAssociatedObject(self, @selector(sd_targetSize), @(sd_targetSize), OBJC_ASSOCIATION_RETAIN_NONATOMIC); 30 | } 31 | 32 | - (PHImageContentMode)sd_contentMode { 33 | NSNumber *value = objc_getAssociatedObject(self, @selector(sd_contentMode)); 34 | if (value != nil) { 35 | return PHImageContentModeDefault; 36 | } 37 | return value.integerValue; 38 | } 39 | 40 | - (void)setSd_contentMode:(PHImageContentMode)sd_contentMode { 41 | objc_setAssociatedObject(self, @selector(sd_contentMode), @(sd_contentMode), OBJC_ASSOCIATION_RETAIN_NONATOMIC); 42 | } 43 | 44 | @end 45 | -------------------------------------------------------------------------------- /Example/SDWebImagePhotosPlugin/MasterViewController.xib: -------------------------------------------------------------------------------- 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 | -------------------------------------------------------------------------------- /SDWebImagePhotosPlugin.podspec: -------------------------------------------------------------------------------- 1 | # 2 | # Be sure to run `pod lib lint SDWebImagePhotosPlugin.podspec' to ensure this is a 3 | # valid spec before submitting. 4 | # 5 | # Any lines starting with a # are optional, but their use is encouraged 6 | # To learn more about a Podspec see https://guides.cocoapods.org/syntax/podspec.html 7 | # 8 | 9 | Pod::Spec.new do |s| 10 | s.name = 'SDWebImagePhotosPlugin' 11 | s.version = '1.2.1' 12 | s.summary = 'A SDWebImage plugin to support Photos framework image loading.' 13 | 14 | s.description = <<-DESC 15 | This is a SDWebImage loader plugin to support Apple's Photos framework image asset. 16 | DESC 17 | 18 | s.homepage = 'https://github.com/SDWebImage/SDWebImagePhotosPlugin' 19 | # s.screenshots = 'www.example.com/screenshots_1', 'www.example.com/screenshots_2' 20 | s.license = { :type => 'MIT', :file => 'LICENSE' } 21 | s.author = { 'DreamPiggy' => 'lizhuoli1126@126.com' } 22 | s.source = { :git => 'https://github.com/SDWebImage/SDWebImagePhotosPlugin.git', :tag => s.version.to_s } 23 | # s.social_media_url = 'https://twitter.com/' 24 | 25 | s.osx.deployment_target = '10.13' 26 | s.ios.deployment_target = '9.0' 27 | s.tvos.deployment_target = '10.0' 28 | 29 | s.source_files = 'SDWebImagePhotosPlugin/Classes/**/*', 'SDWebImagePhotosPlugin/Module/SDWebImagePhotosPlugin.h' 30 | s.module_map = 'SDWebImagePhotosPlugin/Module/SDWebImagePhotosPlugin.modulemap' 31 | 32 | s.pod_target_xcconfig = { 33 | 'SUPPORTS_MACCATALYST' => 'YES', 34 | 'DERIVE_MACCATALYST_PRODUCT_BUNDLE_IDENTIFIER' => 'NO' 35 | } 36 | 37 | s.frameworks = 'Photos' 38 | s.dependency 'SDWebImage/Core', '~> 5.10' 39 | end 40 | -------------------------------------------------------------------------------- /Example/SDWebImagePhotosPlugin/SDWebImagePhotosPlugin-Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleDisplayName 8 | ${PRODUCT_NAME} 9 | CFBundleExecutable 10 | ${EXECUTABLE_NAME} 11 | CFBundleIdentifier 12 | $(PRODUCT_BUNDLE_IDENTIFIER) 13 | CFBundleInfoDictionaryVersion 14 | 6.0 15 | CFBundleName 16 | ${PRODUCT_NAME} 17 | CFBundlePackageType 18 | APPL 19 | CFBundleShortVersionString 20 | 1.0 21 | CFBundleSignature 22 | ???? 23 | CFBundleVersion 24 | 1.0 25 | LSRequiresIPhoneOS 26 | 27 | UILaunchStoryboardName 28 | LaunchScreen 29 | UIRequiredDeviceCapabilities 30 | 31 | armv7 32 | 33 | UISupportedInterfaceOrientations 34 | 35 | UIInterfaceOrientationPortrait 36 | UIInterfaceOrientationLandscapeLeft 37 | UIInterfaceOrientationLandscapeRight 38 | 39 | UISupportedInterfaceOrientations~ipad 40 | 41 | UIInterfaceOrientationPortrait 42 | UIInterfaceOrientationPortraitUpsideDown 43 | UIInterfaceOrientationLandscapeLeft 44 | UIInterfaceOrientationLandscapeRight 45 | 46 | NSPhotoLibraryUsageDescription 47 | Allow SDWebImage Demo to show Photos Library images 48 | 49 | 50 | -------------------------------------------------------------------------------- /.github/stale.yml: -------------------------------------------------------------------------------- 1 | # Configuration for probot-stale - https://github.com/probot/stale 2 | 3 | # Number of days of inactivity before an Issue or Pull Request becomes stale 4 | daysUntilStale: 60 5 | 6 | # Number of days of inactivity before an Issue or Pull Request with the stale label is closed. 7 | # Set to false to disable. If disabled, issues still need to be closed manually, but will remain marked as stale. 8 | daysUntilClose: 7 9 | 10 | # Issues or Pull Requests with these labels will never be considered stale. Set to `[]` to disable 11 | exemptLabels: 12 | - crash 13 | 14 | # Set to true to ignore issues in a project (defaults to false) 15 | exemptProjects: false 16 | 17 | # Set to true to ignore issues in a milestone (defaults to false) 18 | exemptMilestones: false 19 | 20 | # Label to use when marking as stale 21 | staleLabel: wontfix 22 | 23 | # Comment to post when marking as stale. Set to `false` to disable 24 | markComment: > 25 | This issue has been automatically marked as stale because it has not had 26 | recent activity. It will be closed if no further activity occurs. Thank you 27 | for your contributions. 28 | 29 | # Comment to post when removing the stale label. 30 | # unmarkComment: > 31 | # Your comment here. 32 | 33 | # Comment to post when closing a stale Issue or Pull Request. 34 | # closeComment: > 35 | # Your comment here. 36 | 37 | # Limit the number of actions per hour, from 1-30. Default is 30 38 | limitPerRun: 30 39 | 40 | # Limit to only `issues` or `pulls` 41 | only: issues 42 | 43 | # Optionally, specify configuration settings that are specific to just 'issues' or 'pulls': 44 | # pulls: 45 | # daysUntilStale: 30 46 | # markComment: > 47 | # This pull request has been automatically marked as stale because it has not had 48 | # recent activity. It will be closed if no further activity occurs. Thank you 49 | # for your contributions. 50 | 51 | # issues: 52 | # exemptLabels: 53 | # - confirmed -------------------------------------------------------------------------------- /Example/SDWebImagePhotosPlugin/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 | 27 | 28 | 29 | 30 | 31 | 32 | -------------------------------------------------------------------------------- /Example/SDWebImagePhotosPlugin/Images.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 | } 99 | -------------------------------------------------------------------------------- /SDWebImagePhotosPlugin/Classes/NSURL+SDWebImagePhotosPlugin.m: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the SDWebImage package. 3 | * (c) Olivier Poitrey 4 | * 5 | * For the full copyright and license information, please view the LICENSE 6 | * file that was distributed with this source code. 7 | */ 8 | 9 | #import "NSURL+SDWebImagePhotosPlugin.h" 10 | #import "SDWebImagePhotosDefine.h" 11 | #import 12 | #import 13 | 14 | @implementation NSURL (SDWebImagePhotosPlugin) 15 | 16 | - (BOOL)sd_isPhotosURL { 17 | return [self.scheme isEqualToString:SDWebImagePhotosScheme]; 18 | } 19 | 20 | - (NSString *)sd_assetLocalIdentifier { 21 | if (!self.sd_isPhotosURL) { 22 | return nil; 23 | } 24 | PHAsset *asset = self.sd_asset; 25 | if (asset) { 26 | return asset.localIdentifier; 27 | } 28 | NSString *urlString = self.absoluteString; 29 | NSString *prefix = [NSString stringWithFormat:@"%@://", SDWebImagePhotosScheme]; 30 | if (urlString.length <= prefix.length) { 31 | return nil; 32 | } 33 | return [urlString stringByReplacingOccurrencesOfString:prefix withString:@""]; 34 | } 35 | 36 | - (PHAsset *)sd_asset { 37 | return objc_getAssociatedObject(self, @selector(sd_asset)); 38 | } 39 | 40 | - (void)setSd_asset:(PHAsset * _Nullable)sd_asset { 41 | objc_setAssociatedObject(self, @selector(sd_asset), sd_asset, OBJC_ASSOCIATION_RETAIN_NONATOMIC); 42 | } 43 | 44 | + (instancetype)sd_URLWithAssetLocalIdentifier:(NSString *)identifier { 45 | NSParameterAssert(identifier); 46 | // ph://F2A9F582-BA45-4308-924E-6D146B784A09/L0/001 47 | NSString *prefix = [NSString stringWithFormat:@"%@://", SDWebImagePhotosScheme]; 48 | return [NSURL URLWithString:[NSString stringWithFormat:@"%@%@", prefix, identifier]]; 49 | } 50 | 51 | + (instancetype)sd_URLWithAsset:(PHAsset *)asset { 52 | NSParameterAssert(asset); 53 | NSString *localIdentifier = asset.localIdentifier; 54 | NSURL *url = [self sd_URLWithAssetLocalIdentifier:localIdentifier]; 55 | url.sd_asset = asset; 56 | 57 | return url; 58 | } 59 | 60 | @end 61 | -------------------------------------------------------------------------------- /Example/SDWebImagePhotosPlugin.xcodeproj/xcshareddata/xcschemes/SDWebImagePhotosPlugin_Tests.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 16 | 18 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 40 | 41 | 42 | 43 | 49 | 50 | 52 | 53 | 56 | 57 | 58 | -------------------------------------------------------------------------------- /Example/SDWebImagePhotosPlugin/DetailViewController.m: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the SDWebImage package. 3 | * (c) Olivier Poitrey 4 | * 5 | * For the full copyright and license information, please view the LICENSE 6 | * file that was distributed with this source code. 7 | */ 8 | 9 | #import "DetailViewController.h" 10 | #import 11 | #import 12 | 13 | @interface DetailViewController () 14 | 15 | @property (weak, nonatomic) IBOutlet UIImageView *imageView; 16 | @property (weak, nonatomic) IBOutlet UIScrollView *scrollView; 17 | 18 | @end 19 | 20 | @implementation DetailViewController 21 | 22 | - (UIView *)viewForZoomingInScrollView:(UIScrollView *)scrollView { 23 | return self.imageView; 24 | } 25 | 26 | - (void)scrollViewDidDoubleTapped:(UIGestureRecognizer *)gestureRecognizer { 27 | if (self.scrollView.zoomScale > self.scrollView.minimumZoomScale) { 28 | [self.scrollView setZoomScale:self.scrollView.minimumZoomScale animated:YES]; 29 | } else { 30 | [self.scrollView setZoomScale:self.scrollView.maximumZoomScale animated:YES]; 31 | } 32 | } 33 | 34 | - (void)configureView 35 | { 36 | self.scrollView.delegate = self; 37 | UITapGestureRecognizer *doubleTapGestureRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(scrollViewDidDoubleTapped:)]; 38 | doubleTapGestureRecognizer.numberOfTapsRequired = 2; 39 | [self.scrollView addGestureRecognizer:doubleTapGestureRecognizer]; 40 | if (!self.imageView.sd_imageIndicator) { 41 | self.imageView.sd_imageIndicator = SDWebImageProgressIndicator.defaultIndicator; 42 | } 43 | [self.imageView sd_setImageWithURL:self.imageURL 44 | placeholderImage:nil 45 | options:SDWebImageFromLoaderOnly 46 | context:@{SDWebImageContextStoreCacheType : @(SDImageCacheTypeNone)}]; 47 | } 48 | 49 | - (void)viewDidLoad 50 | { 51 | [super viewDidLoad]; 52 | if (@available(iOS 11.0, *)) { 53 | self.scrollView.contentInsetAdjustmentBehavior = UIScrollViewContentInsetAdjustmentNever; 54 | } else { 55 | self.automaticallyAdjustsScrollViewInsets = NO; 56 | } 57 | [self configureView]; 58 | } 59 | 60 | @end 61 | -------------------------------------------------------------------------------- /Example/SDWebImagePhotosPlugin_Example macOS/TestCollectionViewItem.xib: -------------------------------------------------------------------------------- 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 | -------------------------------------------------------------------------------- /Example/SDWebImagePhotosPlugin/DetailViewController.xib: -------------------------------------------------------------------------------- 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 | -------------------------------------------------------------------------------- /SDWebImagePhotosPlugin/Classes/SDImagePhotosLoader.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the SDWebImage package. 3 | * (c) Olivier Poitrey 4 | * 5 | * For the full copyright and license information, please view the LICENSE 6 | * file that was distributed with this source code. 7 | */ 8 | 9 | #if __has_include() 10 | #import 11 | #else 12 | @import SDWebImage; 13 | #endif 14 | #import 15 | 16 | /** 17 | The imgae loader to load image asset from Photos library. You need to register the loader into manager firstly. Use `@import SDWebImagePhotosPlugin` to import full framework instead of each header. 18 | @note To control single image request options, use the context option in `SDWebImagePhotosDefine.h`. 19 | @note Use `NSURL+SDWebImagePhotosPlugin.h` category to create Photos URL instead of string. Use `PHImageRequestOptions+SDWebImagePhotosPlugin.h` category to provide extra info for request options. 20 | @note And it's also strongly recommeded to totally disable memory cache if you want to query batch of Photos images frequently. You can do this by using `SDWebImageFromLoaderOnly` options during image request. And you can use `SDWebImageContextStoreCacheType` with `SDImageCacheTypeNone` to disable cache storing. This is because Photos framework manage the image cache by their own process outside your application process and can reduce memory usage. 21 | */ 22 | @interface SDImagePhotosLoader : NSObject 23 | 24 | /** 25 | The global shared instance for Photos loader. 26 | */ 27 | @property (nonatomic, class, readonly, nonnull) SDImagePhotosLoader *sharedLoader; 28 | 29 | /** 30 | The default `fetchOptions` used for PHAsset fetch with the localIdentifier. 31 | Defaults to nil. 32 | */ 33 | @property (nonatomic, strong, nullable) PHFetchOptions *fetchOptions; 34 | 35 | /** 36 | The default `imageRequestOptions` used for image asset request. 37 | Defatuls value are these: 38 | networkAccessAllowed = YES; 39 | resizeMode = PHImageRequestOptionsResizeModeFast; 40 | deliveryMode = PHImageRequestOptionsDeliveryModeOpportunistic; 41 | version = PHImageRequestOptionsVersionCurrent; 42 | */ 43 | @property (nonatomic, strong, nullable) PHImageRequestOptions *imageRequestOptions; 44 | 45 | /** 46 | Whether we request only `PHAssetMediaTypeImage` asset and ignore other types (video/audio/unknown). 47 | When we found other type, an error `SDWebImagePhotosErrorNotImageAsset` will be reported. 48 | Defaults to YES. If you prefer to load other type like video asset's poster image, set this value to NO. 49 | */ 50 | @property (nonatomic, assign) BOOL requestImageAssetOnly; 51 | 52 | @end 53 | -------------------------------------------------------------------------------- /SDWebImagePhotosPlugin/Classes/SDWebImagePhotosDefine.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the SDWebImage package. 3 | * (c) Olivier Poitrey 4 | * 5 | * For the full copyright and license information, please view the LICENSE 6 | * file that was distributed with this source code. 7 | */ 8 | 9 | #if __has_include() 10 | #import 11 | #else 12 | @import SDWebImage; 13 | #endif 14 | 15 | /** 16 | * The scheme when identifing the URL is Photos URL 17 | */ 18 | FOUNDATION_EXPORT NSString * _Nonnull const SDWebImagePhotosScheme; 19 | 20 | /** 21 | * Specify to use the exact size of image instead of original pixel size. 22 | * Use this size if you want full image that PHImageManagerMaximumSize can not provide. This is the designed behavior for PhotoKit. 23 | * @note SDWebImagePhotosPixelSize > PHImageManagerMaximumSize(default) > SDWebImagePhotosPointSize 24 | */ 25 | FOUNDATION_EXPORT const CGSize SDWebImagePhotosPixelSize; 26 | 27 | /** 28 | * Specify to use the exact size of image instead of original point size. 29 | * The scale is from the custom scale factor, or using the device scale factor if not provide. 30 | */ 31 | FOUNDATION_EXPORT const CGSize SDWebImagePhotosPointSize; 32 | 33 | /** 34 | * Because Photos Framework progressBlock does not contains the file size, only the progress. See `PHAssetImageProgressHandler`. 35 | * This value is used to represent the `exceptedSize`, and the `receivedSize` is calculated by multiplying with the progress value. 36 | */ 37 | FOUNDATION_EXPORT const int64_t SDWebImagePhotosProgressExpectedSize; /* 100LL */ 38 | 39 | /** 40 | A PHFetchOptions instance used in the Photos Library fetch process. If you do not provide, we will use the default options to fetch the asset. (PHFetchOptions) 41 | */ 42 | FOUNDATION_EXPORT SDWebImageContextOption _Nonnull const SDWebImageContextPhotosFetchOptions; 43 | 44 | /** 45 | A PHImageRequestOptions instance used in the Photos Library image request process. If you do not provide, we will use the default options to fetch the image (PHImageRequestOptions) 46 | */ 47 | FOUNDATION_EXPORT SDWebImageContextOption _Nonnull const SDWebImageContextPhotosImageRequestOptions; 48 | 49 | /** 50 | A Bool value specify whether or not, to use `requestImageDataForAsset:options:resultHandler:` instead of `requestImageForAsset:targetSize:contentMode:options:resultHandler:` API to request Asset's Image. 51 | By default, we automatically use `requestImageDataForAsset` for Animated Asset (GIF images), use `requestImageForAsset` for other Asset. If you provide a custom value, always using that value instead. 52 | If you care about the raw image data, you can enable this context option to get the raw image data in completion block. 53 | @note When query the raw image data, the `targetSize` and `contentMode` are ignored. You can use image transformer or other ways from your propose. See Apple's documentation for more details information. (NSNumber *) 54 | */ 55 | FOUNDATION_EXPORT SDWebImageContextOption _Nonnull const SDWebImageContextPhotosRequestImageData; 56 | -------------------------------------------------------------------------------- /Example/SDWebImagePhotosPlugin/SDAppDelegate.m: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the SDWebImage package. 3 | * (c) Olivier Poitrey 4 | * 5 | * For the full copyright and license information, please view the LICENSE 6 | * file that was distributed with this source code. 7 | */ 8 | 9 | #import "SDAppDelegate.h" 10 | #import "MasterViewController.h" 11 | #import 12 | 13 | @implementation SDAppDelegate 14 | 15 | @synthesize window = _window; 16 | @synthesize navigationController = _navigationController; 17 | 18 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions 19 | { 20 | // Override point for customization after application launch. 21 | if (@available(iOS 14.0, *)) { 22 | [SDImageCodersManager.sharedManager addCoder:SDImageAWebPCoder.sharedCoder]; 23 | } 24 | if (@available(iOS 13.0, *)) { 25 | [SDImageCodersManager.sharedManager addCoder:SDImageHEICCoder.sharedCoder]; 26 | } 27 | 28 | self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds]; 29 | 30 | MasterViewController *masterViewController = [[MasterViewController alloc] initWithNibName:@"MasterViewController" bundle:nil]; 31 | self.navigationController = [[UINavigationController alloc] initWithRootViewController:masterViewController]; 32 | self.window.rootViewController = self.navigationController; 33 | [self.window makeKeyAndVisible]; 34 | return YES; 35 | } 36 | 37 | - (void)applicationWillResignActive:(UIApplication *)application 38 | { 39 | // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. 40 | // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game. 41 | } 42 | 43 | - (void)applicationDidEnterBackground:(UIApplication *)application 44 | { 45 | // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. 46 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. 47 | } 48 | 49 | - (void)applicationWillEnterForeground:(UIApplication *)application 50 | { 51 | // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background. 52 | } 53 | 54 | - (void)applicationDidBecomeActive:(UIApplication *)application 55 | { 56 | // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. 57 | } 58 | 59 | - (void)applicationWillTerminate:(UIApplication *)application 60 | { 61 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. 62 | } 63 | 64 | @end 65 | -------------------------------------------------------------------------------- /SDWebImagePhotosPlugin.xcodeproj/xcshareddata/xcschemes/SDWebImagePhotosPlugin.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 32 | 33 | 34 | 35 | 45 | 46 | 52 | 53 | 54 | 55 | 56 | 57 | 63 | 64 | 70 | 71 | 72 | 73 | 75 | 76 | 79 | 80 | 81 | -------------------------------------------------------------------------------- /SDWebImagePhotosPlugin.xcodeproj/xcshareddata/xcschemes/SDWebImagePhotosPlugin-tvOS.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 32 | 33 | 34 | 35 | 45 | 46 | 52 | 53 | 54 | 55 | 56 | 57 | 63 | 64 | 70 | 71 | 72 | 73 | 75 | 76 | 79 | 80 | 81 | -------------------------------------------------------------------------------- /SDWebImagePhotosPlugin.xcodeproj/xcshareddata/xcschemes/SDWebImagePhotosPlugin-macOS.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 32 | 33 | 34 | 35 | 45 | 46 | 52 | 53 | 54 | 55 | 56 | 57 | 63 | 64 | 70 | 71 | 72 | 73 | 75 | 76 | 79 | 80 | 81 | -------------------------------------------------------------------------------- /Example/SDWebImagePhotosPlugin.xcodeproj/xcshareddata/xcschemes/SDWebImagePhotosPlugin_Example macOS.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 32 | 33 | 39 | 40 | 41 | 42 | 43 | 44 | 54 | 56 | 62 | 63 | 64 | 65 | 66 | 67 | 73 | 75 | 81 | 82 | 83 | 84 | 86 | 87 | 90 | 91 | 92 | -------------------------------------------------------------------------------- /Example/SDWebImagePhotosPlugin.xcodeproj/xcshareddata/xcschemes/SDWebImagePhotosPlugin-Example.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 33 | 39 | 40 | 41 | 42 | 43 | 49 | 50 | 51 | 52 | 53 | 54 | 64 | 66 | 72 | 73 | 74 | 75 | 76 | 77 | 83 | 85 | 91 | 92 | 93 | 94 | 96 | 97 | 100 | 101 | 102 | -------------------------------------------------------------------------------- /Example/SDWebImagePhotosPlugin_Example macOS/ViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.m 3 | // SDWebImagePhotosPlugin_Example macOS 4 | // 5 | // Created by lizhuoli on 2018/7/19. 6 | // Copyright © 2018年 DreamPiggy. All rights reserved. 7 | // 8 | 9 | #import "ViewController.h" 10 | #import 11 | #import 12 | #import "TestCollectionViewItem.h" 13 | 14 | @interface ViewController () 15 | 16 | @property (nonatomic, strong) NSMutableArray *objects; 17 | @property (weak) IBOutlet NSScrollView *scrollView; 18 | @property (weak) IBOutlet NSCollectionView *collectionView; 19 | 20 | 21 | @end 22 | 23 | @implementation ViewController 24 | 25 | - (instancetype)initWithCoder:(NSCoder *)coder { 26 | self = [super initWithCoder:coder]; 27 | if (self) { 28 | self.objects = [NSMutableArray array]; 29 | // Setup Photos Loader 30 | SDWebImageManager.defaultImageLoader = [SDImagePhotosLoader sharedLoader]; 31 | // The original image size may be 4K, we only query the max view size :) 32 | SDImagePhotosLoader.sharedLoader.imageRequestOptions.sd_targetSize = CGSizeMake(500, 500); 33 | 34 | // Reload 35 | [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(menuItemDidTap:) name:NSMenuDidSendActionNotification object:nil]; 36 | } 37 | return self; 38 | } 39 | 40 | - (void)viewDidLoad { 41 | [super viewDidLoad]; 42 | 43 | // Photos Library Demo 44 | [self reloadData]; 45 | } 46 | 47 | #pragma clang diagnostic push 48 | #pragma clang diagnostic ignored "-Wunguarded-availability" 49 | - (void)fetchAssets { 50 | [self.objects removeAllObjects]; 51 | PHFetchResult *result = [PHAssetCollection fetchAssetCollectionsWithType:PHAssetCollectionTypeSmartAlbum 52 | subtype:PHAssetCollectionSubtypeSmartAlbumUserLibrary 53 | options:nil]; 54 | PHAssetCollection *collection = result.firstObject; 55 | PHFetchOptions *fetchOptions = [PHFetchOptions new]; 56 | fetchOptions.predicate = [NSPredicate predicateWithFormat:@"mediaType = %d", PHAssetMediaTypeImage]; 57 | fetchOptions.sortDescriptors = @[[NSSortDescriptor sortDescriptorWithKey:@"creationDate" ascending:NO]]; 58 | PHFetchResult *assets = [PHAsset fetchAssetsInAssetCollection:collection options:fetchOptions]; 59 | for (PHAsset *asset in assets) { 60 | // You can use local identifier of `PHAsset` to create URL 61 | // NSURL *url = [NSURL sd_URLWithAssetLocalIdentifier:asset.localIdentifier]; 62 | // Or even `PHAsset` itself 63 | NSURL *url = [NSURL sd_URLWithAsset:asset]; 64 | [self.objects addObject:url]; 65 | } 66 | } 67 | #pragma clang diagnostic pop 68 | 69 | - (void)menuItemDidTap:(NSNotification *)notification { 70 | NSMenuItem *menuItem = notification.userInfo[@"MenuItem"]; 71 | if ([menuItem.title isEqualToString:@"Reload"]) { 72 | [self reloadData]; 73 | } 74 | } 75 | 76 | - (void)reloadData { 77 | [self fetchAssets]; 78 | [self.collectionView reloadData]; 79 | } 80 | 81 | - (NSCollectionViewItem *)collectionView:(NSCollectionView *)collectionView itemForRepresentedObjectAtIndexPath:(NSIndexPath *)indexPath { 82 | TestCollectionViewItem *cell = [collectionView makeItemWithIdentifier:@"TestCollectionViewItem" forIndexPath:indexPath]; 83 | NSURL *photosURL = self.objects[indexPath.item]; 84 | BOOL supportsHDR = NSScreen.mainScreen.maximumPotentialExtendedDynamicRangeColorComponentValue > 1.0; 85 | SDWebImageMutableContext *context = [@{SDWebImageContextStoreCacheType: @(SDImageCacheTypeNone)} mutableCopy]; 86 | if (supportsHDR) { 87 | if (@available (macOS 14.0, *)) { 88 | cell.imageViewDisplay.preferredImageDynamicRange = NSImageDynamicRangeHigh; // Enable Image View Level control for HDR 89 | } 90 | context[SDWebImageContextPhotosRequestImageData] = @(YES); // Photos Library only load HDR info when requestImageData 91 | context[SDWebImageContextImageDecodeToHDR] = @(YES); // When decoding HDR data, we need explicit enable HDR decoding 92 | } 93 | cell.imageViewDisplay.animates = YES; 94 | cell.imageViewDisplay.sd_imageTransition = SDWebImageTransition.fadeTransition; 95 | [cell.imageViewDisplay sd_setImageWithURL:photosURL placeholderImage:nil options:SDWebImageFromLoaderOnly context:context]; 96 | return cell; 97 | } 98 | 99 | - (NSInteger)collectionView:(NSCollectionView *)collectionView numberOfItemsInSection:(NSInteger)section { 100 | return self.objects.count; 101 | } 102 | 103 | - (NSInteger)numberOfSectionsInCollectionView:(NSCollectionView *)collectionView { 104 | return 1; 105 | } 106 | 107 | @end 108 | -------------------------------------------------------------------------------- /Example/SDWebImagePhotosPlugin/MasterViewController.m: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the SDWebImage package. 3 | * (c) Olivier Poitrey 4 | * 5 | * For the full copyright and license information, please view the LICENSE 6 | * file that was distributed with this source code. 7 | */ 8 | 9 | #import "MasterViewController.h" 10 | #import "DetailViewController.h" 11 | #import 12 | #import 13 | 14 | @interface MyCustomTableViewCell : UITableViewCell 15 | 16 | @property (nonatomic, strong) UILabel *customTextLabel; 17 | @property (nonatomic, strong) SDAnimatedImageView *customImageView; 18 | 19 | @end 20 | 21 | @implementation MyCustomTableViewCell 22 | 23 | - (instancetype)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier { 24 | if (self = [super initWithStyle:style reuseIdentifier:reuseIdentifier]) { 25 | _customImageView = [[SDAnimatedImageView alloc] initWithFrame:CGRectMake(20.0, 2.0, 60.0, 40.0)]; 26 | [self.contentView addSubview:_customImageView]; 27 | _customTextLabel = [[UILabel alloc] initWithFrame:CGRectMake(100.0, 12.0, 200, 20.0)]; 28 | [self.contentView addSubview:_customTextLabel]; 29 | 30 | _customImageView.clipsToBounds = YES; 31 | _customImageView.contentMode = UIViewContentModeScaleAspectFill; 32 | } 33 | return self; 34 | } 35 | 36 | @end 37 | 38 | @interface MasterViewController () 39 | 40 | @property (nonatomic, strong) NSMutableArray *objects; 41 | 42 | @end 43 | 44 | @implementation MasterViewController 45 | 46 | - (instancetype)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil 47 | { 48 | self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil]; 49 | if (self) 50 | { 51 | self.title = @"SDWebImage"; 52 | self.navigationItem.rightBarButtonItem = [UIBarButtonItem.alloc initWithTitle:@"Reload" 53 | style:UIBarButtonItemStylePlain 54 | target:self 55 | action:@selector(reloadData)]; 56 | self.objects = [NSMutableArray array]; 57 | // Setup Photos Loader 58 | SDWebImageManager.defaultImageLoader = [SDImagePhotosLoader sharedLoader]; 59 | // The original image size may be 4K, we only query the max view size :) 60 | SDImagePhotosLoader.sharedLoader.imageRequestOptions.sd_targetSize = CGSizeMake(500, 500); 61 | // Request Video Asset Poster as well 62 | SDImagePhotosLoader.sharedLoader.requestImageAssetOnly = NO; 63 | } 64 | return self; 65 | } 66 | 67 | - (void)viewDidLoad { 68 | [super viewDidLoad]; 69 | 70 | // Photos Library Demo 71 | [self reloadData]; 72 | } 73 | 74 | - (void)fetchAssets { 75 | [self.objects removeAllObjects]; 76 | PHFetchResult *result = [PHAssetCollection fetchAssetCollectionsWithType:PHAssetCollectionTypeSmartAlbum 77 | subtype:PHAssetCollectionSubtypeSmartAlbumUserLibrary 78 | options:nil]; 79 | PHAssetCollection *collection = result.firstObject; 80 | PHFetchOptions *fetchOptions = [PHFetchOptions new]; 81 | fetchOptions.sortDescriptors = @[[NSSortDescriptor sortDescriptorWithKey:@"creationDate" ascending:NO]]; 82 | PHFetchResult *assets = [PHAsset fetchAssetsInAssetCollection:collection options:fetchOptions]; 83 | for (PHAsset *asset in assets) { 84 | // You can use local identifier of `PHAsset` to create URL 85 | // NSURL *url = [NSURL sd_URLWithAssetLocalIdentifier:asset.localIdentifier]; 86 | // Or even `PHAsset` itself 87 | NSURL *url = [NSURL sd_URLWithAsset:asset]; 88 | [self.objects addObject:url]; 89 | } 90 | } 91 | 92 | - (void)reloadData 93 | { 94 | [self fetchAssets]; 95 | [self.tableView reloadData]; 96 | } 97 | 98 | #pragma mark - Table View 99 | 100 | - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView 101 | { 102 | return 1; 103 | } 104 | 105 | - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section 106 | { 107 | return self.objects.count; 108 | } 109 | 110 | - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath 111 | { 112 | static NSString *CellIdentifier = @"Cell"; 113 | 114 | static UIImage *placeholderImage = nil; 115 | if (!placeholderImage) { 116 | placeholderImage = [UIImage imageNamed:@"placeholder"]; 117 | } 118 | 119 | MyCustomTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier]; 120 | if (cell == nil) { 121 | cell = [[MyCustomTableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier]; 122 | cell.customImageView.sd_imageTransition = SDWebImageTransition.fadeTransition; 123 | cell.customImageView.sd_imageIndicator = SDWebImageActivityIndicator.grayIndicator; 124 | } 125 | 126 | cell.customTextLabel.text = [NSString stringWithFormat:@"Image #%ld", (long)indexPath.row]; 127 | SDWebImageMutableContext *context = [@{SDWebImageContextStoreCacheType : @(SDImageCacheTypeNone)} mutableCopy]; 128 | BOOL supportsHDR = NO; 129 | if (@available(iOS 16.0, *)) { 130 | supportsHDR = UIScreen.mainScreen.potentialEDRHeadroom > 1.0; 131 | } 132 | if (supportsHDR) { 133 | if (@available(iOS 17.0, *)) { 134 | cell.customImageView.preferredImageDynamicRange = UIImageDynamicRangeHigh; // Enable Image View Level control for HDR 135 | } 136 | context[SDWebImageContextPhotosRequestImageData] = @(YES); // Photos Library only load HDR info when requestImageData 137 | context[SDWebImageContextImageDecodeToHDR] = @(YES); // When decoding HDR data, we need explicit enable HDR decoding 138 | } 139 | [cell.customImageView sd_setImageWithURL:self.objects[indexPath.row] 140 | placeholderImage:placeholderImage 141 | options:SDWebImageFromLoaderOnly 142 | context:context]; // Disable memory cache query/store 143 | return cell; 144 | } 145 | 146 | - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath 147 | { 148 | NSURL *largeImageURL = self.objects[indexPath.row]; 149 | DetailViewController *detailViewController = [[DetailViewController alloc] initWithNibName:@"DetailViewController" bundle:nil]; 150 | detailViewController.imageURL = largeImageURL; 151 | [self.navigationController pushViewController:detailViewController animated:YES]; 152 | } 153 | 154 | @end 155 | -------------------------------------------------------------------------------- /Example/Tests/SDPhotosPluginTests.m: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the SDWebImagePhotosPlugin package. 3 | * 4 | * For the full copyright and license information, please view the LICENSE 5 | * file that was distributed with this source code. 6 | */ 7 | 8 | #import "SDTestCase.h" 9 | #import "SystemAlert.h" 10 | 11 | @interface SDPhotosPluginTests : SDTestCase 12 | 13 | @end 14 | 15 | @implementation SDPhotosPluginTests 16 | 17 | + (void)setUp { 18 | XCTestExpectation *expectation = [[XCTestExpectation alloc] initWithDescription:@"Photos Library Permission"]; 19 | // Request Photos Library access in advance 20 | [PHPhotoLibrary requestAuthorization:^(PHAuthorizationStatus status) { 21 | [expectation fulfill]; 22 | }]; 23 | // Auto grant access (OK button) 24 | [SystemAlert tapRightButton]; 25 | 26 | __unused XCTWaiterResult result = [XCTWaiter waitForExpectations:@[expectation] timeout:kAsyncTestTimeout]; 27 | } 28 | 29 | - (void)testUIImageViewSetImageWithAsset { 30 | XCTestExpectation *expectation = [self expectationWithDescription:@"UIImageView setImageWithAsset"]; 31 | SDWebImageManager *manager = [[SDWebImageManager alloc] initWithCache:SDImageCache.sharedImageCache loader:SDImagePhotosLoader.sharedLoader]; 32 | PHAsset *asset = [self smartAlbumAssets].firstObject; 33 | expect(asset).notTo.beNil(); 34 | NSURL *originalImageURL = [NSURL sd_URLWithAsset:asset]; 35 | 36 | UIImageView *imageView = [[UIImageView alloc] init]; 37 | [imageView sd_setImageWithURL:originalImageURL 38 | placeholderImage:nil 39 | options:SDWebImageFromLoaderOnly 40 | context:@{SDWebImageContextCustomManager : manager} 41 | progress:nil 42 | completed:^(UIImage * _Nullable image, NSError * _Nullable error, SDImageCacheType cacheType, NSURL * _Nullable imageURL) { 43 | expect(image).toNot.beNil(); 44 | expect(error).to.beNil(); 45 | expect(originalImageURL).to.equal(imageURL); 46 | expect(imageView.image).to.equal(image); 47 | [expectation fulfill]; 48 | }]; 49 | [self waitForExpectationsWithTimeout:kAsyncTestTimeout handler:nil]; 50 | } 51 | 52 | - (void)testUIImageViewSetImageWithAssetLocalIdentifier { 53 | XCTestExpectation *expectation = [self expectationWithDescription:@"UIImageView setImageWithAssetLocalIdentifier"]; 54 | SDWebImageManager *manager = [[SDWebImageManager alloc] initWithCache:SDImageCache.sharedImageCache loader:SDImagePhotosLoader.sharedLoader]; 55 | NSString *localIdentifier = [self smartAlbumAssets].firstObject.localIdentifier; 56 | expect(localIdentifier).notTo.beNil(); 57 | NSURL *originalImageURL = [NSURL sd_URLWithAssetLocalIdentifier:localIdentifier]; 58 | 59 | UIImageView *imageView = [[UIImageView alloc] init]; 60 | [imageView sd_setImageWithURL:originalImageURL 61 | placeholderImage:nil 62 | options:SDWebImageFromLoaderOnly 63 | context:@{SDWebImageContextCustomManager : manager} 64 | progress:nil 65 | completed:^(UIImage * _Nullable image, NSError * _Nullable error, SDImageCacheType cacheType, NSURL * _Nullable imageURL) { 66 | expect(image).toNot.beNil(); 67 | expect(error).to.beNil(); 68 | expect(originalImageURL).to.equal(imageURL); 69 | expect(imageView.image).to.equal(image); 70 | [expectation fulfill]; 71 | }]; 72 | [self waitForExpectationsWithTimeout:kAsyncTestTimeout handler:nil]; 73 | } 74 | 75 | - (void)testUIImageViewSetImageWithAssetAndThumbnailPixelSize { 76 | XCTestExpectation *expectation = [self expectationWithDescription:@"UIImageView setImageWithAssetAndThumbnailPixelSize"]; 77 | SDWebImageManager *manager = [[SDWebImageManager alloc] initWithCache:SDImageCache.sharedImageCache loader:SDImagePhotosLoader.sharedLoader]; 78 | PHAsset *asset = [self smartAlbumAssets].firstObject; 79 | expect(asset).notTo.beNil(); 80 | NSURL *originalImageURL = [NSURL sd_URLWithAsset:asset]; 81 | CGSize thumbnailPixelSize = CGSizeMake(1000, 1000); 82 | 83 | UIImageView *imageView = [[UIImageView alloc] init]; 84 | [imageView sd_setImageWithURL:originalImageURL 85 | placeholderImage:nil 86 | options:0 87 | context:@{SDWebImageContextCustomManager : manager, SDWebImageContextImageThumbnailPixelSize : @(thumbnailPixelSize)} 88 | progress:nil 89 | completed:^(UIImage * _Nullable image, NSError * _Nullable error, SDImageCacheType cacheType, NSURL * _Nullable imageURL) { 90 | expect(image).toNot.beNil(); 91 | expect(error).to.beNil(); 92 | expect(MAX(image.size.width, image.size.height), MAX(thumbnailPixelSize.width, thumbnailPixelSize.height)); // Aspect Fit 93 | expect(originalImageURL).to.equal(imageURL); 94 | expect(imageView.image).to.equal(image); 95 | [expectation fulfill]; 96 | }]; 97 | [self waitForExpectationsWithTimeout:kAsyncTestTimeout handler:nil]; 98 | } 99 | 100 | - (void)testUIImageViewSetImageWithGIFAsset { 101 | XCTestExpectation *expectation = [self expectationWithDescription:@"UIImageView setImageWithGIFAsset"]; 102 | 103 | NSData *GIFData = [self testGIFData]; 104 | __block NSString *localIdentifier = nil; 105 | // Write GIF image into Photos Library firstly 106 | [[PHPhotoLibrary sharedPhotoLibrary] performChanges:^{ 107 | PHAssetCreationRequest *request = [PHAssetCreationRequest creationRequestForAsset]; 108 | localIdentifier = request.placeholderForCreatedAsset.localIdentifier; 109 | [request addResourceWithType:PHAssetResourceTypePhoto data:GIFData options:nil]; 110 | } completionHandler:^(BOOL success, NSError * _Nullable error) { 111 | expect(success).to.beTruthy(); 112 | 113 | dispatch_async(dispatch_get_main_queue(), ^{ 114 | // Query the GIF image with localIdentifier 115 | SDWebImageManager *manager = [[SDWebImageManager alloc] initWithCache:SDImageCache.sharedImageCache loader:SDImagePhotosLoader.sharedLoader]; 116 | NSURL *originalImageURL = [NSURL sd_URLWithAssetLocalIdentifier:localIdentifier]; 117 | 118 | UIImageView *imageView = [[UIImageView alloc] init]; 119 | [imageView sd_setImageWithURL:originalImageURL 120 | placeholderImage:nil 121 | options:SDWebImageFromLoaderOnly 122 | context:@{SDWebImageContextCustomManager : manager} 123 | progress:nil 124 | completed:^(UIImage * _Nullable image, NSError * _Nullable error, SDImageCacheType cacheType, NSURL * _Nullable imageURL) { 125 | // Strong retain imageView to avoid immediatelly dealloc 126 | expect(imageView.image).equal(image); 127 | // Expect animated image 128 | expect(image.sd_isAnimated).to.beTruthy(); 129 | [expectation fulfill]; 130 | // The removal of temp GIF will cause a GUI dialog which is not suitable for running on CI machine :( 131 | // // Clean the temp GIF asset 132 | // [[PHPhotoLibrary sharedPhotoLibrary] performChanges:^{ 133 | // PHFetchResult *assets = [PHAsset fetchAssetsWithLocalIdentifiers:@[localIdentifier] options:nil]; 134 | // [PHAssetChangeRequest deleteAssets:assets]; 135 | // } completionHandler:^(BOOL success, NSError * _Nullable error) { 136 | // [expectation fulfill]; 137 | // }]; 138 | }]; 139 | }); 140 | }]; 141 | 142 | [self waitForExpectationsWithTimeout:kAsyncTestTimeout * 2 handler:nil]; 143 | } 144 | 145 | #pragma mark - Util 146 | 147 | - (PHFetchResult *)smartAlbumAssets { 148 | PHFetchResult *result = [PHAssetCollection fetchAssetCollectionsWithType:PHAssetCollectionTypeSmartAlbum 149 | subtype:PHAssetCollectionSubtypeSmartAlbumUserLibrary 150 | options:nil]; 151 | PHAssetCollection *collection = result.firstObject; 152 | PHFetchOptions *fetchOptions = [PHFetchOptions new]; 153 | fetchOptions.predicate = [NSPredicate predicateWithFormat:@"mediaType = %d", PHAssetMediaTypeImage]; 154 | fetchOptions.sortDescriptors = @[[NSSortDescriptor sortDescriptorWithKey:@"creationDate" ascending:NO]]; 155 | PHFetchResult *assets = [PHAsset fetchAssetsInAssetCollection:collection options:fetchOptions]; 156 | 157 | return assets; 158 | } 159 | 160 | - (NSString *)testGIFPath { 161 | NSBundle *testBundle = [NSBundle bundleForClass:[self class]]; 162 | return [testBundle pathForResource:@"TestImage" ofType:@"gif"]; 163 | } 164 | 165 | - (NSData *)testGIFData { 166 | NSData *testData = [NSData dataWithContentsOfFile:[self testGIFPath]]; 167 | return testData; 168 | } 169 | 170 | @end 171 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # SDWebImagePhotosPlugin 2 | 3 | [![CI Status](https://img.shields.io/travis/SDWebImage/SDWebImagePhotosPlugin.svg?style=flat)](https://travis-ci.org/SDWebImage/SDWebImagePhotosPlugin) 4 | [![Version](https://img.shields.io/cocoapods/v/SDWebImagePhotosPlugin.svg?style=flat)](https://cocoapods.org/pods/SDWebImagePhotosPlugin) 5 | [![License](https://img.shields.io/cocoapods/l/SDWebImagePhotosPlugin.svg?style=flat)](https://cocoapods.org/pods/SDWebImagePhotosPlugin) 6 | [![Platform](https://img.shields.io/cocoapods/p/SDWebImagePhotosPlugin.svg?style=flat)](https://cocoapods.org/pods/SDWebImagePhotosPlugin) 7 | [![Carthage compatible](https://img.shields.io/badge/Carthage-compatible-brightgreen.svg?style=flat)](https://github.com/SDWebImage/SDWebImagePhotosPlugin) 8 | [![SwiftPM compatible](https://img.shields.io/badge/SwiftPM-compatible-brightgreen.svg?style=flat)](https://swift.org/package-manager/) 9 | [![codecov](https://codecov.io/gh/SDWebImage/SDWebImagePhotosPlugin/branch/master/graph/badge.svg)](https://codecov.io/gh/SDWebImage/SDWebImagePhotosPlugin) 10 | 11 | ## What it's for 12 | SDWebImagePhotosPlugin is a plugin for the [SDWebImage](https://github.com/rs/SDWebImage/) framework, which provides image loading support for the [Photos Library](https://developer.apple.com/documentation/photokit). 13 | 14 | This plugin allows you to use your familiar View Category method from SDWebImage, for loading Photos images with `PHAsset` or `localIdentifier`. 15 | 16 | 17 | ## Requirements 18 | 19 | + iOS 9+ 20 | + macOS 10.13+ 21 | + tvOS 10+ 22 | + Xcode 10+ 23 | 24 | ## Installation 25 | 26 | #### CocoaPods 27 | 28 | SDWebImagePhotosPlugin is available through [CocoaPods](https://cocoapods.org). To install 29 | it, simply add the following line to your Podfile: 30 | 31 | ```ruby 32 | pod 'SDWebImagePhotosPlugin' 33 | ``` 34 | 35 | #### Carthage 36 | 37 | SDWebImagePhotosPlugin is available through [Carthage](https://github.com/Carthage/Carthage). 38 | 39 | ``` 40 | github "SDWebImage/SDWebImagePhotosPlugin" 41 | ``` 42 | 43 | #### Swift Package Manager (Xcode 11+) 44 | 45 | SDWebImagePhotosPlugin is available through [Swift Package Manager](https://swift.org/package-manager). 46 | 47 | ```swift 48 | let package = Package( 49 | dependencies: [ 50 | .package(url: "https://github.com/SDWebImage/SDWebImagePhotosPlugin.git", from: "1.0") 51 | ] 52 | ) 53 | ``` 54 | 55 | ## Usage 56 | **Important!** To use this Photos Library plugin, you first need to register the photos loader to image manager. 57 | 58 | There are two ways to register the photos loader. One is for temporarily usage (when providing URL is definitely Photos URL but not HTTP URL), and another for global support (don't need any check, supports both HTTP URL as well as Photos URL). 59 | 60 | #### Use custom manager (temporarily) 61 | You can create a custom manager for temporary usage. When you use custom manager, be sure to specify `SDWebImageContextCustomManager` context option with your custom manager for View Category methods. 62 | 63 | + Objective-C 64 | 65 | ```objectivec 66 | // Assign loader to custom manager 67 | SDWebImageManager *manager = [[SDWebImageManager alloc] initWithCache:SDImageCache.sharedImageCache loader:SDImagePhotosLoader.sharedLoader]; 68 | ``` 69 | 70 | + Swift 71 | 72 | ```swift 73 | // Assign loader to custom manager 74 | let manager = SDWebImageManager(cache: SDImageCache.shared, loader: SDImagePhotosLoader.shared) 75 | ``` 76 | 77 | #### Use loaders manager (globally) 78 | You can replace the default manager's loader implementation using [loaders manager](https://github.com/rs/SDWebImage/wiki/Advanced-Usage#loaders-manager) to support both HTTP && Photos URL globally. Put these code just at the application launch time (or some time just before `SDWebImageManager.sharedManager` is initialized). 79 | 80 | + Objective-C 81 | 82 | ```objectivec 83 | // Supports HTTP URL as well as Photos URL globally 84 | SDImageLoadersManager.sharedManager.loaders = @[SDWebImageDownloader.sharedDownloader, SDImagePhotosLoader.sharedLoader]; 85 | // Replace default manager's loader implementation 86 | SDWebImageManager.defaultImageLoader = SDImageLoadersManager.sharedManager; 87 | ``` 88 | 89 | + Swift 90 | 91 | ```swift 92 | // Supports HTTP URL as well as Photos URL globally 93 | SDImageLoadersManager.shared.loaders = [SDWebImageDownloader.shared, SDImagePhotosLoader.shared] 94 | // Replace default manager's loader implementation 95 | SDWebImageManager.defaultImageLoader = SDImageLoadersManager.shared 96 | ``` 97 | 98 | #### Load Images 99 | To start loading the Photos Library image, use the `NSURL+SDWebImagePhotosPlugin` to create a Photos URL and call View Category method. 100 | 101 | + Objective-C 102 | 103 | ```objectivec 104 | // Create with `PHAsset` 105 | PHAsset *asset; 106 | NSURL *photosURL = asset.sd_URLRepresentation; 107 | // The same as `[NSURL sd_URLWithAsset:asset];` 108 | // Create with `localIdentifier` 109 | NSString *identifier; 110 | NSURL *potosURL = [NSURL sd_URLWithAssetLocalIdentifier:identifier]; 111 | 112 | // Load image (assume using custom manager) 113 | [imageView sd_setImageWithURL:photosURL placeholderImage:nil context:@{SDWebImageContextCustomManager: manager}]; 114 | ``` 115 | 116 | + Swift 117 | 118 | ```swift 119 | // Create with `PHAsset` 120 | let asset: PHAsset 121 | let photosURL = asset.sd_URLRepresentation 122 | // The same as `NSURL.sd_URL(with: asset) as URL` 123 | // Create with `localIdentifier` 124 | let identifier: String 125 | let potosURL = NSURL.sd_URL(withAssetLocalIdentifier: identifier) as URL 126 | 127 | // Load image (assume using custom manager) 128 | imageView.sd_setImage(with: photosURL, placeholderImage: nil, context: [.customManager: manager]) 129 | ``` 130 | 131 | #### Animated Images 132 | SDWebImagePhotosPlugin supports GIF images stored in Photos Library as well. Just use the same API as normal images to query the asset. We will query the image data and decode the animated images (compatible with `UIImageView` as well as [SDAnimatedImageView](https://github.com/rs/SDWebImage/wiki/Advanced-Usage#animated-image-50)) 133 | 134 | 135 | #### Video Assets 136 | SDWebImagePhotosPlugin supports loading Video Asset poster as well. By default, we don't allow non-image type assets, to avoid accidentally picking a wrong Asset. But you can disable this limit as well. 137 | 138 | + Objective-C 139 | 140 | ```objectivec 141 | SDImagePhotosLoader.sharedLoader.requestImageAssetOnly = NO; 142 | ``` 143 | 144 | + Swift 145 | 146 | ```swift 147 | SDImagePhotosLoader.shared.requestImageAssetOnly = false 148 | ``` 149 | 150 | Then just request the PHAssets or using the fetch options, which the media type is `.video`. 151 | 152 | #### HDR Photo Rendering 153 | To enable HDR decoding and rendering, upgrade SDWebImage to 5.21.0+, then, request the image data from Photos Library and turn on HDR decoding. 154 | 155 | + Objective-C 156 | 157 | ```objective-c 158 | #if TARGET_OS_OSX 159 | BOOL supportsHDR = NSScreen.mainScreen.maximumPotentialExtendedDynamicRangeColorComponentValue > 1.0; 160 | #else 161 | #define NSImageDynamicRangeHigh UIImageDynamicRangeHigh 162 | BOOL supportsHDR = UIScreen.mainScreen.potentialEDRHeadroom > 1.0; 163 | #endif 164 | SDWebImageMutableContext *context = [@{SDWebImageContextStoreCacheType: @(SDImageCacheTypeNone)} mutableCopy]; 165 | if (supportsHDR) { 166 | if (@available (macOS 14.0, iOS 17, *)) { 167 | cell.imageViewDisplay.preferredImageDynamicRange = NSImageDynamicRangeHigh; // Enable Image View Level control for HDR 168 | } 169 | context[SDWebImageContextPhotosRequestImageData] = @(YES); // Photos Library only load HDR info when requestImageData 170 | context[SDWebImageContextImageDecodeToHDR] = @(YES); // When decoding HDR data, we need explicit enable HDR decoding 171 | } 172 | // Then loading HDR assets with context option 173 | [imageView sd_setImageWithURL:photosURL placeholderImage:nil context:context]; 174 | ``` 175 | 176 | + Swift 177 | 178 | ```swift 179 | #if os(macOS) 180 | let supportsHDR = NSScreen.main.maximumPotentialExtendedDynamicRangeColorComponentValue > 1.0 181 | #else 182 | let supportsHDR = UIScreen.main.potentialEDRHeadroom > 1.0 183 | #endif 184 | var context = [ 185 | SDWebImageContextStoreCacheType: SDImageCacheType.none.rawValue 186 | ] 187 | if supportsHDR { 188 | if #available(macOS 14.0, iOS 17, *) { 189 | cell.imageViewDisplay.preferredImageDynamicRange = .high // Enable Image View Level control for HDR 190 | } 191 | context[.photosRequestImageData] = true // Photos Library only load HDR info when requestImageData 192 | context[.imageDecodeToHDR] = true // When decoding HDR data, we need explicit enable HDR decoding 193 | } 194 | // Then loading HDR assets with context option 195 | imageView.sd_setImage(with: photosURL, placeholderImage: nil, context:context) 196 | ``` 197 | 198 | #### Fetch/Request Options 199 | To specify options like `PHFetchOptions` or `PHImageRequestOptions` for Photos Library. Either to change the correspond properties in loader, or provide a context options for each image request. 200 | 201 | + Objective-C 202 | 203 | ```objectivec 204 | // loader-level options 205 | // ignore iCloud Shared Album (`localIdentifier` Photos URL only) 206 | PHFetchOptions *fetchOptions = SDImagePhotosLoader.sharedLoader.fetchOptions; 207 | fetchOptions.predicate = [NSPredicate predicateWithFormat:@"sourceType != %d", PHAssetSourceTypeCloudShared]; 208 | 209 | // request-level options 210 | // disable iCloud Photos Library (networkAccessAllowed defaults to YES) 211 | PHImageRequestOptions *requestOptions = [PHImageRequestOptions new]; 212 | requestOptions.networkAccessAllowed = NO; 213 | [imageView sd_setImageWithURL:photosURL placeholderImage:nil context:@{SDWebImageContextPhotosImageRequestOptions: requestOptions, SDWebImageContextCustomManager: manager}]; 214 | ``` 215 | 216 | + Swift 217 | 218 | ```swift 219 | // loader-level options 220 | // ignore iCloud Shared Album (`localIdentifier` Photos URL only) 221 | let fetchOptions = SDImagePhotosLoader.shared.fetchOptions 222 | fetchOptions.predicate = NSPredicate(format: "sourceType != %d", PHAssetSourceType.typeCloudShared.rawValue) 223 | 224 | // request-level options 225 | // disable iCloud Photos Library (networkAccessAllowed defaults to YES) 226 | let requestOptions = PHImageRequestOptions() 227 | requestOptions.networkAccessAllowed = false 228 | imageView.sd_setImage(with: photosURL, placeholderImage: nil, context:[.photosImageRequestOptions: requestOptions, .customManager: manager]) 229 | ``` 230 | 231 | #### Control Query Image Size 232 | Photos taken by the iPhone camera may have a really large pixel size (4K+). So, if you want to load large Photos Library assets for rendering, you should specify target size with a limited size (for example, the size of the imageView that you are loading into). 233 | 234 | By default, we query the target size that matches the original image's largest size (see: [PHImageManagerMaximumSize](https://developer.apple.com/documentation/photokit/phimagemanagermaximumsize?language=objc)), which may consume too much memory on iOS devices. There are also two built-in dynamic values `SDWebImagePhotosPixelSize/SDWebImagePhotosPointSize` which are suitable for some cases. 235 | 236 | You can change the fetch image size by either using the `PHImageRequestOptions.sd_targetSize`, or [Thumbnail Decoding](https://github.com/SDWebImage/SDWebImage/wiki/Advanced-Usage#thumbnail-decoding-550) via `.imageThumbnailPixelSize` context option. 237 | 238 | Control query image size limit in global: 239 | 240 | + Objective-C 241 | 242 | ```objective-c 243 | SDImagePhotosLoader.sharedLoader.imageRequestOptions.sd_targetSize = CGSizeMake(1000, 1000); // Limit 1000x1000 pixels 244 | ``` 245 | 246 | + Swift 247 | 248 | ```swift 249 | SDImagePhotosLoader.shared.imageRequestOptions.sd_targetSize = CGSize(width: 1000, height: 1000) // Limit 1000x1000 pixels 250 | ``` 251 | 252 | Control query image size for individual assets: 253 | 254 | + Objective-C 255 | 256 | ```objective-c 257 | UIImageView *imageView; 258 | PHAsset *asset; 259 | NSURL *url = asset.sd_URLRepresentation; 260 | [imageView.sd_setImageWithURL:url options:0 context:@{SDWebImageContextImageThumbnailPixelSize: @(imageView.bounds.size)}]; // Fetch image based on image view size 261 | ``` 262 | 263 | + Swift 264 | 265 | ```swift 266 | let imageView: UIImageView 267 | let asset: PHAsset 268 | let url = asset.sd_URLRepresentation 269 | imageView.sd_setImage(with: url, context: [.imageThumbnailPixelSize : imageView.bounds.size]) // Fetch image based on image view size 270 | ``` 271 | 272 | Note: You can also use `SDWebImageContextPhotosImageRequestOptions` as shown above. But the thumbnail pixel size can be used for normal Network URL as well, which can help you to unify the logic for HTTP URL and PHAsset URL. 273 | 274 | 275 | ## Tips 276 | 277 | 1. Images from the Photos Library are already stored on the device disk, and query speed is fast enough for small resolution images, so cache storage might be unnecessary. You can use `SDWebImageContextStoreCacheType` with `SDImageCacheTypeNone` to disable cache storage, and use `SDWebImageFromLoaderOnly` to disable cache queries. 278 | 2. If you use `PHImageRequestOptionsDeliveryModeOpportunistic` (default) to load the image, PhotosKit will return a degraded thumbnail image first and again with the full pixel image. When the image is degraded, the loader completion block will set `finished = NO`. However, this will not trigger the View Category completion block, and only trigger a image refresh (like progressive loading behavior for network image using `SDWebImageProgressiveLoad`) 279 | 3. By default, we will prefer using Photos [requestImageForAsset:targetSize:contentMode:options:resultHandler:](https://developer.apple.com/documentation/photokit/phimagemanager/1616964-requestimageforasset?language=objc) API for normal images, using [requestImageDataForAsset:options:resultHandler:](https://developer.apple.com/documentation/photokit/phimagemanager/1616957-requestimagedataforasset?language=objc) for animated images like GIF asset. If you need the raw image data for further image processing, you can always pass the `SDWebImageContextPhotosRequestImageData` context option to force using the request data API instead. Note that when requesting data, the `targetSize` and `contentMode` options are ignored. If you need smaller image sizes, consider using [Image Transformer](https://github.com/SDWebImage/SDWebImage/wiki/Advanced-Usage#image-transformer-50) feature from SDWebImage 5.0. 280 | 281 | ## Demo 282 | 283 | If you have some issue about usage, SDWebImagePhotosPlugin provide a demo for iOS & macOS platform. To run the demo, clone the repo and run the following command. 284 | 285 | ```bash 286 | cd Example/ 287 | pod install 288 | open SDWebImagePhotosPlugin.xcworkspace 289 | ``` 290 | 291 | After the Xcode project is opened, click Run to build and run the demo. 292 | 293 | ## Author 294 | 295 | DreamPiggy, lizhuoli1126@126.com 296 | 297 | ## License 298 | 299 | SDWebImagePhotosPlugin is available under the MIT license. See the LICENSE file for more info. 300 | 301 | 302 | -------------------------------------------------------------------------------- /SDWebImagePhotosPlugin/Classes/SDImagePhotosLoader.m: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the SDWebImage package. 3 | * (c) Olivier Poitrey 4 | * 5 | * For the full copyright and license information, please view the LICENSE 6 | * file that was distributed with this source code. 7 | */ 8 | 9 | #import "SDImagePhotosLoader.h" 10 | #import "SDWebImagePhotosDefine.h" 11 | #import "NSURL+SDWebImagePhotosPlugin.h" 12 | #import "PHImageRequestOptions+SDWebImagePhotosPlugin.h" 13 | #import "SDWebImagePhotosError.h" 14 | #import 15 | 16 | // Compatible 17 | #if SD_UIKIT 18 | #import 19 | typedef UIImageOrientation SDImageOrientation; 20 | #else 21 | typedef CGImagePropertyOrientation SDImageOrientation; 22 | #endif 23 | // This protocol is used to fix the Xcode 11's API declaration for macOS. Which should be available on macOS 10.13 24 | @protocol PHImageManager 25 | - (PHImageRequestID)requestImageDataForAsset:(PHAsset *)asset options:(nullable PHImageRequestOptions *)options resultHandler:(void(^)(NSData *__nullable imageData, NSString *__nullable dataUTI, SDImageOrientation orientation, NSDictionary *__nullable info))resultHandler; 26 | @end 27 | @interface PHImageManager () 28 | @end 29 | 30 | @interface SDImagePhotosLoaderOperation : NSObject 31 | 32 | @property (nonatomic, assign) PHImageRequestID requestID; 33 | @property (nonatomic, getter=isCancelled) BOOL cancelled; 34 | 35 | @end 36 | 37 | @implementation SDImagePhotosLoaderOperation 38 | 39 | - (void)cancel { 40 | [[PHImageManager defaultManager] cancelImageRequest:self.requestID]; 41 | self.cancelled = YES; 42 | } 43 | 44 | @end 45 | 46 | @interface SDImagePhotosLoader () 47 | 48 | @property (nonatomic, strong, nonnull) NSHashTable *operationsTable; 49 | @property (nonatomic, strong, nonnull) dispatch_queue_t fetchQueue; 50 | 51 | @end 52 | 53 | @implementation SDImagePhotosLoader 54 | 55 | - (void)dealloc { 56 | #if SD_UIKIT 57 | [[NSNotificationCenter defaultCenter] removeObserver:self]; 58 | #endif 59 | } 60 | 61 | + (SDImagePhotosLoader *)sharedLoader { 62 | static dispatch_once_t onceToken; 63 | static SDImagePhotosLoader *loader; 64 | dispatch_once(&onceToken, ^{ 65 | loader = [[SDImagePhotosLoader alloc] init]; 66 | }); 67 | return loader; 68 | } 69 | 70 | - (instancetype)init { 71 | self = [super init]; 72 | if (self) { 73 | PHImageRequestOptions *requestOptions = [PHImageRequestOptions new]; 74 | requestOptions.networkAccessAllowed = YES; 75 | requestOptions.resizeMode = PHImageRequestOptionsResizeModeFast; 76 | requestOptions.deliveryMode = PHImageRequestOptionsDeliveryModeOpportunistic; 77 | requestOptions.version = PHImageRequestOptionsVersionCurrent; 78 | self.imageRequestOptions = requestOptions; 79 | self.operationsTable = [NSHashTable weakObjectsHashTable]; 80 | self.requestImageAssetOnly = YES; 81 | self.fetchQueue = dispatch_queue_create("SDImagePhotosLoader", DISPATCH_QUEUE_SERIAL); 82 | #if SD_UIKIT 83 | [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(didReceiveMemoryWarning:) name:UIApplicationDidReceiveMemoryWarningNotification object:nil]; 84 | #endif 85 | } 86 | return self; 87 | } 88 | 89 | #if SD_UIKIT 90 | - (void)didReceiveMemoryWarning:(NSNotification *)notification { 91 | for (SDImagePhotosLoaderOperation *operation in self.operationsTable) { 92 | [operation cancel]; 93 | } 94 | [self.operationsTable removeAllObjects]; 95 | } 96 | #endif 97 | 98 | #pragma mark - Helper 99 | + (BOOL)isAnimatedImageWithUTType:(NSString *)UTType { 100 | if (!UTType) { 101 | return NO; 102 | } 103 | if ([UTType isEqualToString:(__bridge_transfer NSString *)kUTTypeGIF]) { 104 | return YES; 105 | } 106 | 107 | return NO; 108 | } 109 | 110 | + (BOOL)isPhotosStatusAuthorized { 111 | return [PHPhotoLibrary authorizationStatus] == PHAuthorizationStatusAuthorized; 112 | } 113 | 114 | #pragma mark - SDImageLoader 115 | 116 | - (BOOL)canRequestImageForURL:(NSURL *)url { 117 | return url.sd_isPhotosURL; 118 | } 119 | 120 | - (id)requestImageWithURL:(NSURL *)url options:(SDWebImageOptions)options context:(SDWebImageContext *)context progress:(SDImageLoaderProgressBlock)progressBlock completed:(SDImageLoaderCompletedBlock)completedBlock { 121 | BOOL isPhotosURL = url.sd_isPhotosURL; 122 | if (!isPhotosURL) { 123 | if (completedBlock) { 124 | NSError *error = [NSError errorWithDomain:SDWebImageErrorDomain code:SDWebImageErrorInvalidURL userInfo:@{NSLocalizedDescriptionKey : @"Photos URL is nil"}]; 125 | completedBlock(nil, nil, error, YES); 126 | } 127 | return nil; 128 | } 129 | 130 | if (![[self class] isPhotosStatusAuthorized]) { 131 | if (completedBlock) { 132 | NSError *error = [NSError errorWithDomain:SDWebImagePhotosErrorDomain code:SDWebImagePhotosErrorNotAuthorized userInfo:@{NSLocalizedDescriptionKey : @"Photos library access not authorized"}]; 133 | completedBlock(nil, nil, error, YES); 134 | } 135 | return nil; 136 | } 137 | 138 | PHFetchOptions *fetchOptions; 139 | if ([context valueForKey:SDWebImageContextPhotosFetchOptions]) { 140 | fetchOptions = [context valueForKey:SDWebImageContextPhotosFetchOptions]; 141 | } else { 142 | fetchOptions = self.fetchOptions; 143 | } 144 | 145 | // Begin fetch asset in fetcher queue because this block main queue 146 | SDImagePhotosLoaderOperation *operation = [[SDImagePhotosLoaderOperation alloc] init]; 147 | dispatch_async(self.fetchQueue, ^{ 148 | if (operation.isCancelled) { 149 | // Cancelled 150 | NSError *error = [NSError errorWithDomain:NSURLErrorDomain code:NSURLErrorCancelled userInfo:nil]; 151 | if (completedBlock) { 152 | completedBlock(nil, nil, error, YES); 153 | } 154 | return; 155 | } 156 | PHAsset *asset = url.sd_asset; 157 | if (!asset) { 158 | NSString *localIdentifier = url.sd_assetLocalIdentifier; 159 | PHFetchResult *fetchResult = [PHAsset fetchAssetsWithLocalIdentifiers:@[localIdentifier] options:fetchOptions]; 160 | asset = fetchResult.firstObject; 161 | if (!asset) { 162 | NSString *desc = [NSString stringWithFormat:@"Invalid PHAsset localIdentifier: %@", localIdentifier]; 163 | NSError *error = [NSError errorWithDomain:SDWebImagePhotosErrorDomain code:SDWebImagePhotosErrorInvalidLocalIdentifier userInfo:@{NSLocalizedDescriptionKey: desc}]; 164 | if (completedBlock) { 165 | completedBlock(nil, nil, error, YES); 166 | } 167 | return; 168 | } 169 | } 170 | // Check whether we should request only image asset 171 | if (self.requestImageAssetOnly && asset.mediaType != PHAssetMediaTypeImage) { 172 | // Call error 173 | NSString *desc = [NSString stringWithFormat:@"Unsupported PHAsset localIdentifier: %d, PHAssetMediaType: %d", asset.localIdentifier, asset.mediaType]; 174 | NSError *error = [NSError errorWithDomain:SDWebImagePhotosErrorDomain code:SDWebImagePhotosErrorNotImageAsset userInfo:@{NSLocalizedDescriptionKey: desc}]; 175 | if (completedBlock) { 176 | completedBlock(nil, nil, error, YES); 177 | } 178 | return; 179 | } 180 | 181 | // Request image data instead of image 182 | BOOL requestImageData; 183 | if (context[SDWebImageContextPhotosRequestImageData]) { 184 | requestImageData = [context[SDWebImageContextPhotosRequestImageData] boolValue]; 185 | } else { 186 | // Check UTType 187 | NSString *uniformTypeIdentifier; 188 | if ([asset respondsToSelector:@selector(uniformTypeIdentifier)]) { 189 | uniformTypeIdentifier = [asset valueForKey:NSStringFromSelector(@selector(uniformTypeIdentifier))]; 190 | } 191 | // Check Animated Image, which need the original image data 192 | requestImageData = [[self class] isAnimatedImageWithUTType:uniformTypeIdentifier]; 193 | } 194 | 195 | if (requestImageData) { 196 | [self fetchImageDataWithAsset:asset operation:operation url:url options:options context:context progress:progressBlock completed:completedBlock]; 197 | } else { 198 | [self fetchImageWithAsset:asset operation:operation url:url options:options context:context progress:progressBlock completed:completedBlock]; 199 | } 200 | }); 201 | [self.operationsTable addObject:operation]; 202 | 203 | return operation; 204 | } 205 | 206 | - (BOOL)shouldBlockFailedURLWithURL:(NSURL *)url error:(NSError *)error { 207 | BOOL shouldBlockFailedURL = NO; 208 | if ([error.domain isEqualToString:SDWebImageErrorDomain]) { 209 | shouldBlockFailedURL = error.code == SDWebImageErrorInvalidURL 210 | || error.code == SDWebImageErrorBadImageData; 211 | } else if ([error.domain isEqualToString:SDWebImagePhotosErrorDomain]) { 212 | shouldBlockFailedURL = error.code == SDWebImagePhotosErrorNotImageAsset; 213 | } 214 | return shouldBlockFailedURL; 215 | } 216 | 217 | // This is used for normal image loading (With `requestImage:` API) 218 | - (void)fetchImageWithAsset:(PHAsset *)asset operation:(SDImagePhotosLoaderOperation *)operation url:(NSURL *)url options:(SDWebImageOptions)options context:(SDWebImageContext *)context progress:(SDImageLoaderProgressBlock)progressBlock completed:(SDImageLoaderCompletedBlock)completedBlock { 219 | PHImageRequestOptions *requestOptions; 220 | if ([context valueForKey:SDWebImageContextPhotosImageRequestOptions]) { 221 | requestOptions = [context valueForKey:SDWebImageContextPhotosImageRequestOptions]; 222 | } else { 223 | requestOptions = self.imageRequestOptions; 224 | } 225 | CGSize targetSize; 226 | PHImageContentMode contentMode; 227 | // Check Thumbnail 228 | if ([context valueForKey:SDWebImageContextImageThumbnailPixelSize]) { 229 | NSValue *thumbnailSizeValue = [context valueForKey:SDWebImageContextImageThumbnailPixelSize]; 230 | #if SD_MAC 231 | targetSize = thumbnailSizeValue.sizeValue; 232 | #else 233 | targetSize = thumbnailSizeValue.CGSizeValue; 234 | #endif 235 | BOOL preserveAspectRatio = YES; 236 | if ([context valueForKey:SDWebImageContextImagePreserveAspectRatio]) { 237 | preserveAspectRatio = [[context valueForKey:SDWebImageContextImagePreserveAspectRatio] boolValue]; 238 | } 239 | contentMode = preserveAspectRatio ? PHImageContentModeAspectFit : PHImageContentModeAspectFill; 240 | } else { 241 | // Use request options 242 | targetSize = requestOptions.sd_targetSize; 243 | if (CGSizeEqualToSize(targetSize, SDWebImagePhotosPixelSize)) { 244 | targetSize = CGSizeMake(asset.pixelWidth, asset.pixelHeight); 245 | } else if (CGSizeEqualToSize(targetSize, SDWebImagePhotosPointSize)) { 246 | CGFloat scale = 1; 247 | NSNumber *scaleValue = [context valueForKey:SDWebImageContextImageScaleFactor]; 248 | if (scaleValue) { 249 | scale = scaleValue.doubleValue; 250 | if (scale < 1) { 251 | scale = 1; 252 | } 253 | } else { 254 | #if SD_MAC 255 | scale = [NSScreen mainScreen].backingScaleFactor; 256 | #else 257 | scale = [UIScreen mainScreen].scale; 258 | #endif 259 | } 260 | targetSize = CGSizeMake(asset.pixelHeight * scale, asset.pixelHeight * scale); 261 | } 262 | contentMode = requestOptions.sd_contentMode; 263 | } 264 | 265 | // Progerss Handler 266 | if (progressBlock) { 267 | requestOptions.progressHandler = ^(double progress, NSError * _Nullable error, BOOL * _Nonnull stop, NSDictionary * _Nullable info) { 268 | // Global queue, the same as us 269 | if (progressBlock) { 270 | progressBlock(progress * SDWebImagePhotosProgressExpectedSize, SDWebImagePhotosProgressExpectedSize, url); 271 | } 272 | }; 273 | } 274 | 275 | __weak typeof(operation) weakOperation = operation; 276 | PHImageRequestID requestID = [[PHImageManager defaultManager] requestImageForAsset:asset targetSize:targetSize contentMode:contentMode options:requestOptions resultHandler:^(UIImage * _Nullable result, NSDictionary * _Nullable info) { 277 | if (weakOperation.isCancelled || [info[PHImageCancelledKey] boolValue]) { 278 | // Cancelled 279 | NSError *error = [NSError errorWithDomain:NSURLErrorDomain code:NSURLErrorCancelled userInfo:nil]; 280 | if (completedBlock) { 281 | completedBlock(nil, nil, error, YES); 282 | } 283 | return; 284 | } 285 | if (result) { 286 | BOOL isDegraded = [info[PHImageResultIsDegradedKey] boolValue]; 287 | BOOL finished; 288 | if (requestOptions.deliveryMode == PHImageRequestOptionsDeliveryModeOpportunistic) { 289 | // The completion block may call multiple times. Only pass YES when `isDegraded` set to NO 290 | finished = !isDegraded; 291 | } else { 292 | finished = YES; 293 | } 294 | dispatch_main_async_safe(^{ 295 | if (completedBlock) { 296 | completedBlock(result, nil, nil, finished); 297 | } 298 | }); 299 | } else { 300 | NSError *error = info[PHImageErrorKey]; 301 | dispatch_main_async_safe(^{ 302 | if (completedBlock) { 303 | completedBlock(nil, nil, error, YES); 304 | } 305 | }); 306 | } 307 | }]; 308 | 309 | operation.requestID = requestID; 310 | } 311 | 312 | // This is used for animated image loading (With `requestImageData:` API) 313 | - (void)fetchImageDataWithAsset:(PHAsset *)asset operation:(SDImagePhotosLoaderOperation *)operation url:(NSURL *)url options:(SDWebImageOptions)options context:(SDWebImageContext *)context progress:(SDImageLoaderProgressBlock)progressBlock completed:(SDImageLoaderCompletedBlock)completedBlock { 314 | PHImageRequestOptions *requestOptions; 315 | if ([context valueForKey:SDWebImageContextPhotosImageRequestOptions]) { 316 | requestOptions = [context valueForKey:SDWebImageContextPhotosImageRequestOptions]; 317 | } else { 318 | requestOptions = self.imageRequestOptions; 319 | } 320 | 321 | // Progerss Handler 322 | if (progressBlock) { 323 | requestOptions.progressHandler = ^(double progress, NSError * _Nullable error, BOOL * _Nonnull stop, NSDictionary * _Nullable info) { 324 | // Global queue, the same as us 325 | if (progressBlock) { 326 | progressBlock(progress * SDWebImagePhotosProgressExpectedSize, SDWebImagePhotosProgressExpectedSize, url); 327 | } 328 | }; 329 | } 330 | 331 | __weak typeof(operation) weakOperation = operation; 332 | PHImageRequestID requestID = [(id)[PHImageManager defaultManager] requestImageDataForAsset:asset options:requestOptions resultHandler:^(NSData * _Nullable imageData, NSString * _Nullable dataUTI, SDImageOrientation orientation, NSDictionary * _Nullable info) { 333 | if (weakOperation.isCancelled || [info[PHImageCancelledKey] boolValue]) { 334 | // Cancelled 335 | NSError *error = [NSError errorWithDomain:NSURLErrorDomain code:NSURLErrorCancelled userInfo:nil]; 336 | if (completedBlock) { 337 | completedBlock(nil, nil, error, YES); 338 | } 339 | return; 340 | } 341 | if (imageData) { 342 | // Decode the image with data 343 | dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{ 344 | if (weakOperation.isCancelled) { 345 | // Cancelled 346 | NSError *error = [NSError errorWithDomain:NSURLErrorDomain code:NSURLErrorCancelled userInfo:nil]; 347 | if (completedBlock) { 348 | completedBlock(nil, nil, error, YES); 349 | } 350 | return; 351 | } 352 | UIImage *image = SDImageLoaderDecodeImageData(imageData, url, options, context); 353 | NSError *error; 354 | if (!image) { 355 | error = [NSError errorWithDomain:SDWebImageErrorDomain code:SDWebImageErrorBadImageData userInfo:nil]; 356 | } 357 | dispatch_async(dispatch_get_main_queue(), ^{ 358 | if (completedBlock) { 359 | completedBlock(image, imageData, error, YES); 360 | } 361 | }); 362 | }); 363 | } else { 364 | NSError *error = info[PHImageErrorKey]; 365 | dispatch_main_async_safe(^{ 366 | if (completedBlock) { 367 | completedBlock(nil, nil, error, YES); 368 | } 369 | }) 370 | } 371 | }]; 372 | 373 | operation.requestID = requestID; 374 | } 375 | 376 | @end 377 | -------------------------------------------------------------------------------- /SDWebImagePhotosPlugin.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 50; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 3235B28021FAD1E6008668C5 /* Photos.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3235B27F21FAD1E6008668C5 /* Photos.framework */; }; 11 | 3235B28221FAD1ED008668C5 /* Photos.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3235B28121FAD1ED008668C5 /* Photos.framework */; }; 12 | 3235B28421FAD1F5008668C5 /* Photos.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3235B28321FAD1F5008668C5 /* Photos.framework */; }; 13 | 32380B5425B95E87002A50E1 /* PHAsset+SDWebImagePhotosPlugin.h in Headers */ = {isa = PBXBuildFile; fileRef = 32380B5225B95E87002A50E1 /* PHAsset+SDWebImagePhotosPlugin.h */; settings = {ATTRIBUTES = (Public, ); }; }; 14 | 32380B5525B95E87002A50E1 /* PHAsset+SDWebImagePhotosPlugin.h in Headers */ = {isa = PBXBuildFile; fileRef = 32380B5225B95E87002A50E1 /* PHAsset+SDWebImagePhotosPlugin.h */; settings = {ATTRIBUTES = (Public, ); }; }; 15 | 32380B5625B95E87002A50E1 /* PHAsset+SDWebImagePhotosPlugin.h in Headers */ = {isa = PBXBuildFile; fileRef = 32380B5225B95E87002A50E1 /* PHAsset+SDWebImagePhotosPlugin.h */; settings = {ATTRIBUTES = (Public, ); }; }; 16 | 32380B5725B95E87002A50E1 /* PHAsset+SDWebImagePhotosPlugin.m in Sources */ = {isa = PBXBuildFile; fileRef = 32380B5325B95E87002A50E1 /* PHAsset+SDWebImagePhotosPlugin.m */; }; 17 | 32380B5825B95E87002A50E1 /* PHAsset+SDWebImagePhotosPlugin.m in Sources */ = {isa = PBXBuildFile; fileRef = 32380B5325B95E87002A50E1 /* PHAsset+SDWebImagePhotosPlugin.m */; }; 18 | 32380B5925B95E87002A50E1 /* PHAsset+SDWebImagePhotosPlugin.m in Sources */ = {isa = PBXBuildFile; fileRef = 32380B5325B95E87002A50E1 /* PHAsset+SDWebImagePhotosPlugin.m */; }; 19 | 32CCEA13213E38CD00214381 /* SDWebImagePhotosPlugin.h in Headers */ = {isa = PBXBuildFile; fileRef = 32CCEA12213E38CD00214381 /* SDWebImagePhotosPlugin.h */; settings = {ATTRIBUTES = (Public, ); }; }; 20 | 32CCEA14213E38CD00214381 /* SDWebImagePhotosPlugin.h in Headers */ = {isa = PBXBuildFile; fileRef = 32CCEA12213E38CD00214381 /* SDWebImagePhotosPlugin.h */; settings = {ATTRIBUTES = (Public, ); }; }; 21 | 32CCEA15213E38CD00214381 /* SDWebImagePhotosPlugin.h in Headers */ = {isa = PBXBuildFile; fileRef = 32CCEA12213E38CD00214381 /* SDWebImagePhotosPlugin.h */; settings = {ATTRIBUTES = (Public, ); }; }; 22 | 32CCEA25213E38F600214381 /* SDImagePhotosLoader.m in Sources */ = {isa = PBXBuildFile; fileRef = 32CCEA1B213E38F600214381 /* SDImagePhotosLoader.m */; }; 23 | 32CCEA26213E38F600214381 /* SDImagePhotosLoader.m in Sources */ = {isa = PBXBuildFile; fileRef = 32CCEA1B213E38F600214381 /* SDImagePhotosLoader.m */; }; 24 | 32CCEA27213E38F600214381 /* SDImagePhotosLoader.m in Sources */ = {isa = PBXBuildFile; fileRef = 32CCEA1B213E38F600214381 /* SDImagePhotosLoader.m */; }; 25 | 32CCEA28213E38F600214381 /* SDWebImagePhotosDefine.h in Headers */ = {isa = PBXBuildFile; fileRef = 32CCEA1C213E38F600214381 /* SDWebImagePhotosDefine.h */; settings = {ATTRIBUTES = (Public, ); }; }; 26 | 32CCEA29213E38F600214381 /* SDWebImagePhotosDefine.h in Headers */ = {isa = PBXBuildFile; fileRef = 32CCEA1C213E38F600214381 /* SDWebImagePhotosDefine.h */; settings = {ATTRIBUTES = (Public, ); }; }; 27 | 32CCEA2A213E38F600214381 /* SDWebImagePhotosDefine.h in Headers */ = {isa = PBXBuildFile; fileRef = 32CCEA1C213E38F600214381 /* SDWebImagePhotosDefine.h */; settings = {ATTRIBUTES = (Public, ); }; }; 28 | 32CCEA2B213E38F600214381 /* SDWebImagePhotosError.m in Sources */ = {isa = PBXBuildFile; fileRef = 32CCEA1D213E38F600214381 /* SDWebImagePhotosError.m */; }; 29 | 32CCEA2C213E38F600214381 /* SDWebImagePhotosError.m in Sources */ = {isa = PBXBuildFile; fileRef = 32CCEA1D213E38F600214381 /* SDWebImagePhotosError.m */; }; 30 | 32CCEA2D213E38F600214381 /* SDWebImagePhotosError.m in Sources */ = {isa = PBXBuildFile; fileRef = 32CCEA1D213E38F600214381 /* SDWebImagePhotosError.m */; }; 31 | 32CCEA2E213E38F600214381 /* NSURL+SDWebImagePhotosPlugin.m in Sources */ = {isa = PBXBuildFile; fileRef = 32CCEA1E213E38F600214381 /* NSURL+SDWebImagePhotosPlugin.m */; }; 32 | 32CCEA2F213E38F600214381 /* NSURL+SDWebImagePhotosPlugin.m in Sources */ = {isa = PBXBuildFile; fileRef = 32CCEA1E213E38F600214381 /* NSURL+SDWebImagePhotosPlugin.m */; }; 33 | 32CCEA30213E38F600214381 /* NSURL+SDWebImagePhotosPlugin.m in Sources */ = {isa = PBXBuildFile; fileRef = 32CCEA1E213E38F600214381 /* NSURL+SDWebImagePhotosPlugin.m */; }; 34 | 32CCEA31213E38F600214381 /* PHImageRequestOptions+SDWebImagePhotosPlugin.h in Headers */ = {isa = PBXBuildFile; fileRef = 32CCEA1F213E38F600214381 /* PHImageRequestOptions+SDWebImagePhotosPlugin.h */; settings = {ATTRIBUTES = (Public, ); }; }; 35 | 32CCEA32213E38F600214381 /* PHImageRequestOptions+SDWebImagePhotosPlugin.h in Headers */ = {isa = PBXBuildFile; fileRef = 32CCEA1F213E38F600214381 /* PHImageRequestOptions+SDWebImagePhotosPlugin.h */; settings = {ATTRIBUTES = (Public, ); }; }; 36 | 32CCEA33213E38F600214381 /* PHImageRequestOptions+SDWebImagePhotosPlugin.h in Headers */ = {isa = PBXBuildFile; fileRef = 32CCEA1F213E38F600214381 /* PHImageRequestOptions+SDWebImagePhotosPlugin.h */; settings = {ATTRIBUTES = (Public, ); }; }; 37 | 32CCEA34213E38F600214381 /* SDImagePhotosLoader.h in Headers */ = {isa = PBXBuildFile; fileRef = 32CCEA20213E38F600214381 /* SDImagePhotosLoader.h */; settings = {ATTRIBUTES = (Public, ); }; }; 38 | 32CCEA35213E38F600214381 /* SDImagePhotosLoader.h in Headers */ = {isa = PBXBuildFile; fileRef = 32CCEA20213E38F600214381 /* SDImagePhotosLoader.h */; settings = {ATTRIBUTES = (Public, ); }; }; 39 | 32CCEA36213E38F600214381 /* SDImagePhotosLoader.h in Headers */ = {isa = PBXBuildFile; fileRef = 32CCEA20213E38F600214381 /* SDImagePhotosLoader.h */; settings = {ATTRIBUTES = (Public, ); }; }; 40 | 32CCEA37213E38F600214381 /* SDWebImagePhotosDefine.m in Sources */ = {isa = PBXBuildFile; fileRef = 32CCEA21213E38F600214381 /* SDWebImagePhotosDefine.m */; }; 41 | 32CCEA38213E38F600214381 /* SDWebImagePhotosDefine.m in Sources */ = {isa = PBXBuildFile; fileRef = 32CCEA21213E38F600214381 /* SDWebImagePhotosDefine.m */; }; 42 | 32CCEA39213E38F600214381 /* SDWebImagePhotosDefine.m in Sources */ = {isa = PBXBuildFile; fileRef = 32CCEA21213E38F600214381 /* SDWebImagePhotosDefine.m */; }; 43 | 32CCEA3A213E38F600214381 /* PHImageRequestOptions+SDWebImagePhotosPlugin.m in Sources */ = {isa = PBXBuildFile; fileRef = 32CCEA22213E38F600214381 /* PHImageRequestOptions+SDWebImagePhotosPlugin.m */; }; 44 | 32CCEA3B213E38F600214381 /* PHImageRequestOptions+SDWebImagePhotosPlugin.m in Sources */ = {isa = PBXBuildFile; fileRef = 32CCEA22213E38F600214381 /* PHImageRequestOptions+SDWebImagePhotosPlugin.m */; }; 45 | 32CCEA3C213E38F600214381 /* PHImageRequestOptions+SDWebImagePhotosPlugin.m in Sources */ = {isa = PBXBuildFile; fileRef = 32CCEA22213E38F600214381 /* PHImageRequestOptions+SDWebImagePhotosPlugin.m */; }; 46 | 32CCEA3D213E38F600214381 /* NSURL+SDWebImagePhotosPlugin.h in Headers */ = {isa = PBXBuildFile; fileRef = 32CCEA23213E38F600214381 /* NSURL+SDWebImagePhotosPlugin.h */; settings = {ATTRIBUTES = (Public, ); }; }; 47 | 32CCEA3E213E38F600214381 /* NSURL+SDWebImagePhotosPlugin.h in Headers */ = {isa = PBXBuildFile; fileRef = 32CCEA23213E38F600214381 /* NSURL+SDWebImagePhotosPlugin.h */; settings = {ATTRIBUTES = (Public, ); }; }; 48 | 32CCEA3F213E38F600214381 /* NSURL+SDWebImagePhotosPlugin.h in Headers */ = {isa = PBXBuildFile; fileRef = 32CCEA23213E38F600214381 /* NSURL+SDWebImagePhotosPlugin.h */; settings = {ATTRIBUTES = (Public, ); }; }; 49 | 32CCEA40213E38F600214381 /* SDWebImagePhotosError.h in Headers */ = {isa = PBXBuildFile; fileRef = 32CCEA24213E38F600214381 /* SDWebImagePhotosError.h */; settings = {ATTRIBUTES = (Public, ); }; }; 50 | 32CCEA41213E38F600214381 /* SDWebImagePhotosError.h in Headers */ = {isa = PBXBuildFile; fileRef = 32CCEA24213E38F600214381 /* SDWebImagePhotosError.h */; settings = {ATTRIBUTES = (Public, ); }; }; 51 | 32CCEA42213E38F600214381 /* SDWebImagePhotosError.h in Headers */ = {isa = PBXBuildFile; fileRef = 32CCEA24213E38F600214381 /* SDWebImagePhotosError.h */; settings = {ATTRIBUTES = (Public, ); }; }; 52 | 32CCEA45213E431000214381 /* SDWebImage.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 32CCEA44213E431000214381 /* SDWebImage.framework */; }; 53 | 32CCEA47213E431E00214381 /* SDWebImage.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 32CCEA46213E431E00214381 /* SDWebImage.framework */; }; 54 | 32CCEA49213E432A00214381 /* SDWebImage.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 32CCEA48213E432900214381 /* SDWebImage.framework */; }; 55 | /* End PBXBuildFile section */ 56 | 57 | /* Begin PBXFileReference section */ 58 | 3235B27F21FAD1E6008668C5 /* Photos.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Photos.framework; path = Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.14.sdk/System/Library/Frameworks/Photos.framework; sourceTree = DEVELOPER_DIR; }; 59 | 3235B28121FAD1ED008668C5 /* Photos.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Photos.framework; path = Platforms/AppleTVOS.platform/Developer/SDKs/AppleTVOS12.1.sdk/System/Library/Frameworks/Photos.framework; sourceTree = DEVELOPER_DIR; }; 60 | 3235B28321FAD1F5008668C5 /* Photos.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Photos.framework; path = System/Library/Frameworks/Photos.framework; sourceTree = SDKROOT; }; 61 | 32380B5225B95E87002A50E1 /* PHAsset+SDWebImagePhotosPlugin.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "PHAsset+SDWebImagePhotosPlugin.h"; sourceTree = ""; }; 62 | 32380B5325B95E87002A50E1 /* PHAsset+SDWebImagePhotosPlugin.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = "PHAsset+SDWebImagePhotosPlugin.m"; sourceTree = ""; }; 63 | 32CCE9E8213E383E00214381 /* SDWebImagePhotosPlugin.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = SDWebImagePhotosPlugin.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 64 | 32CCE9F8213E384500214381 /* SDWebImagePhotosPlugin_tvOS.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = SDWebImagePhotosPlugin_tvOS.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 65 | 32CCEA05213E385A00214381 /* SDWebImagePhotosPlugin_macOS.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = SDWebImagePhotosPlugin_macOS.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 66 | 32CCEA12213E38CD00214381 /* SDWebImagePhotosPlugin.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SDWebImagePhotosPlugin.h; path = Module/SDWebImagePhotosPlugin.h; sourceTree = ""; }; 67 | 32CCEA16213E38D000214381 /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = Info.plist; path = Module/Info.plist; sourceTree = ""; }; 68 | 32CCEA1B213E38F600214381 /* SDImagePhotosLoader.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SDImagePhotosLoader.m; sourceTree = ""; }; 69 | 32CCEA1C213E38F600214381 /* SDWebImagePhotosDefine.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDWebImagePhotosDefine.h; sourceTree = ""; }; 70 | 32CCEA1D213E38F600214381 /* SDWebImagePhotosError.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SDWebImagePhotosError.m; sourceTree = ""; }; 71 | 32CCEA1E213E38F600214381 /* NSURL+SDWebImagePhotosPlugin.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSURL+SDWebImagePhotosPlugin.m"; sourceTree = ""; }; 72 | 32CCEA1F213E38F600214381 /* PHImageRequestOptions+SDWebImagePhotosPlugin.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "PHImageRequestOptions+SDWebImagePhotosPlugin.h"; sourceTree = ""; }; 73 | 32CCEA20213E38F600214381 /* SDImagePhotosLoader.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDImagePhotosLoader.h; sourceTree = ""; }; 74 | 32CCEA21213E38F600214381 /* SDWebImagePhotosDefine.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SDWebImagePhotosDefine.m; sourceTree = ""; }; 75 | 32CCEA22213E38F600214381 /* PHImageRequestOptions+SDWebImagePhotosPlugin.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "PHImageRequestOptions+SDWebImagePhotosPlugin.m"; sourceTree = ""; }; 76 | 32CCEA23213E38F600214381 /* NSURL+SDWebImagePhotosPlugin.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSURL+SDWebImagePhotosPlugin.h"; sourceTree = ""; }; 77 | 32CCEA24213E38F600214381 /* SDWebImagePhotosError.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDWebImagePhotosError.h; sourceTree = ""; }; 78 | 32CCEA44213E431000214381 /* SDWebImage.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SDWebImage.framework; path = Carthage/Build/Mac/SDWebImage.framework; sourceTree = ""; }; 79 | 32CCEA46213E431E00214381 /* SDWebImage.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SDWebImage.framework; path = Carthage/Build/tvOS/SDWebImage.framework; sourceTree = ""; }; 80 | 32CCEA48213E432900214381 /* SDWebImage.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SDWebImage.framework; path = Carthage/Build/iOS/SDWebImage.framework; sourceTree = ""; }; 81 | /* End PBXFileReference section */ 82 | 83 | /* Begin PBXFrameworksBuildPhase section */ 84 | 32CCE9E4213E383E00214381 /* Frameworks */ = { 85 | isa = PBXFrameworksBuildPhase; 86 | buildActionMask = 2147483647; 87 | files = ( 88 | 3235B28421FAD1F5008668C5 /* Photos.framework in Frameworks */, 89 | 32CCEA49213E432A00214381 /* SDWebImage.framework in Frameworks */, 90 | ); 91 | runOnlyForDeploymentPostprocessing = 0; 92 | }; 93 | 32CCE9F4213E384500214381 /* Frameworks */ = { 94 | isa = PBXFrameworksBuildPhase; 95 | buildActionMask = 2147483647; 96 | files = ( 97 | 3235B28221FAD1ED008668C5 /* Photos.framework in Frameworks */, 98 | 32CCEA47213E431E00214381 /* SDWebImage.framework in Frameworks */, 99 | ); 100 | runOnlyForDeploymentPostprocessing = 0; 101 | }; 102 | 32CCEA01213E385A00214381 /* Frameworks */ = { 103 | isa = PBXFrameworksBuildPhase; 104 | buildActionMask = 2147483647; 105 | files = ( 106 | 3235B28021FAD1E6008668C5 /* Photos.framework in Frameworks */, 107 | 32CCEA45213E431000214381 /* SDWebImage.framework in Frameworks */, 108 | ); 109 | runOnlyForDeploymentPostprocessing = 0; 110 | }; 111 | /* End PBXFrameworksBuildPhase section */ 112 | 113 | /* Begin PBXGroup section */ 114 | 32CCE9DE213E383E00214381 = { 115 | isa = PBXGroup; 116 | children = ( 117 | 32CCE9EA213E383E00214381 /* SDWebImagePhotosPlugin */, 118 | 32CCE9E9213E383E00214381 /* Products */, 119 | 32CCEA43213E430F00214381 /* Frameworks */, 120 | ); 121 | sourceTree = ""; 122 | }; 123 | 32CCE9E9213E383E00214381 /* Products */ = { 124 | isa = PBXGroup; 125 | children = ( 126 | 32CCE9E8213E383E00214381 /* SDWebImagePhotosPlugin.framework */, 127 | 32CCE9F8213E384500214381 /* SDWebImagePhotosPlugin_tvOS.framework */, 128 | 32CCEA05213E385A00214381 /* SDWebImagePhotosPlugin_macOS.framework */, 129 | ); 130 | name = Products; 131 | sourceTree = ""; 132 | }; 133 | 32CCE9EA213E383E00214381 /* SDWebImagePhotosPlugin */ = { 134 | isa = PBXGroup; 135 | children = ( 136 | 32CCEA1A213E38F600214381 /* Classes */, 137 | 32CCEA12213E38CD00214381 /* SDWebImagePhotosPlugin.h */, 138 | 32CCEA16213E38D000214381 /* Info.plist */, 139 | ); 140 | path = SDWebImagePhotosPlugin; 141 | sourceTree = ""; 142 | }; 143 | 32CCEA1A213E38F600214381 /* Classes */ = { 144 | isa = PBXGroup; 145 | children = ( 146 | 32CCEA23213E38F600214381 /* NSURL+SDWebImagePhotosPlugin.h */, 147 | 32CCEA1E213E38F600214381 /* NSURL+SDWebImagePhotosPlugin.m */, 148 | 32CCEA1F213E38F600214381 /* PHImageRequestOptions+SDWebImagePhotosPlugin.h */, 149 | 32CCEA22213E38F600214381 /* PHImageRequestOptions+SDWebImagePhotosPlugin.m */, 150 | 32CCEA1C213E38F600214381 /* SDWebImagePhotosDefine.h */, 151 | 32CCEA21213E38F600214381 /* SDWebImagePhotosDefine.m */, 152 | 32CCEA24213E38F600214381 /* SDWebImagePhotosError.h */, 153 | 32CCEA1D213E38F600214381 /* SDWebImagePhotosError.m */, 154 | 32CCEA20213E38F600214381 /* SDImagePhotosLoader.h */, 155 | 32CCEA1B213E38F600214381 /* SDImagePhotosLoader.m */, 156 | 32380B5225B95E87002A50E1 /* PHAsset+SDWebImagePhotosPlugin.h */, 157 | 32380B5325B95E87002A50E1 /* PHAsset+SDWebImagePhotosPlugin.m */, 158 | ); 159 | path = Classes; 160 | sourceTree = ""; 161 | }; 162 | 32CCEA43213E430F00214381 /* Frameworks */ = { 163 | isa = PBXGroup; 164 | children = ( 165 | 3235B27F21FAD1E6008668C5 /* Photos.framework */, 166 | 3235B28121FAD1ED008668C5 /* Photos.framework */, 167 | 3235B28321FAD1F5008668C5 /* Photos.framework */, 168 | 32CCEA48213E432900214381 /* SDWebImage.framework */, 169 | 32CCEA46213E431E00214381 /* SDWebImage.framework */, 170 | 32CCEA44213E431000214381 /* SDWebImage.framework */, 171 | ); 172 | name = Frameworks; 173 | sourceTree = ""; 174 | }; 175 | /* End PBXGroup section */ 176 | 177 | /* Begin PBXHeadersBuildPhase section */ 178 | 32CCE9E5213E383E00214381 /* Headers */ = { 179 | isa = PBXHeadersBuildPhase; 180 | buildActionMask = 2147483647; 181 | files = ( 182 | 32CCEA28213E38F600214381 /* SDWebImagePhotosDefine.h in Headers */, 183 | 32380B5425B95E87002A50E1 /* PHAsset+SDWebImagePhotosPlugin.h in Headers */, 184 | 32CCEA31213E38F600214381 /* PHImageRequestOptions+SDWebImagePhotosPlugin.h in Headers */, 185 | 32CCEA40213E38F600214381 /* SDWebImagePhotosError.h in Headers */, 186 | 32CCEA34213E38F600214381 /* SDImagePhotosLoader.h in Headers */, 187 | 32CCEA13213E38CD00214381 /* SDWebImagePhotosPlugin.h in Headers */, 188 | 32CCEA3D213E38F600214381 /* NSURL+SDWebImagePhotosPlugin.h in Headers */, 189 | ); 190 | runOnlyForDeploymentPostprocessing = 0; 191 | }; 192 | 32CCE9F5213E384500214381 /* Headers */ = { 193 | isa = PBXHeadersBuildPhase; 194 | buildActionMask = 2147483647; 195 | files = ( 196 | 32CCEA29213E38F600214381 /* SDWebImagePhotosDefine.h in Headers */, 197 | 32380B5525B95E87002A50E1 /* PHAsset+SDWebImagePhotosPlugin.h in Headers */, 198 | 32CCEA32213E38F600214381 /* PHImageRequestOptions+SDWebImagePhotosPlugin.h in Headers */, 199 | 32CCEA41213E38F600214381 /* SDWebImagePhotosError.h in Headers */, 200 | 32CCEA35213E38F600214381 /* SDImagePhotosLoader.h in Headers */, 201 | 32CCEA14213E38CD00214381 /* SDWebImagePhotosPlugin.h in Headers */, 202 | 32CCEA3E213E38F600214381 /* NSURL+SDWebImagePhotosPlugin.h in Headers */, 203 | ); 204 | runOnlyForDeploymentPostprocessing = 0; 205 | }; 206 | 32CCEA02213E385A00214381 /* Headers */ = { 207 | isa = PBXHeadersBuildPhase; 208 | buildActionMask = 2147483647; 209 | files = ( 210 | 32CCEA2A213E38F600214381 /* SDWebImagePhotosDefine.h in Headers */, 211 | 32380B5625B95E87002A50E1 /* PHAsset+SDWebImagePhotosPlugin.h in Headers */, 212 | 32CCEA33213E38F600214381 /* PHImageRequestOptions+SDWebImagePhotosPlugin.h in Headers */, 213 | 32CCEA42213E38F600214381 /* SDWebImagePhotosError.h in Headers */, 214 | 32CCEA36213E38F600214381 /* SDImagePhotosLoader.h in Headers */, 215 | 32CCEA15213E38CD00214381 /* SDWebImagePhotosPlugin.h in Headers */, 216 | 32CCEA3F213E38F600214381 /* NSURL+SDWebImagePhotosPlugin.h in Headers */, 217 | ); 218 | runOnlyForDeploymentPostprocessing = 0; 219 | }; 220 | /* End PBXHeadersBuildPhase section */ 221 | 222 | /* Begin PBXNativeTarget section */ 223 | 32CCE9E7213E383E00214381 /* SDWebImagePhotosPlugin */ = { 224 | isa = PBXNativeTarget; 225 | buildConfigurationList = 32CCE9F0213E383E00214381 /* Build configuration list for PBXNativeTarget "SDWebImagePhotosPlugin" */; 226 | buildPhases = ( 227 | 32CCE9E3213E383E00214381 /* Sources */, 228 | 32CCE9E4213E383E00214381 /* Frameworks */, 229 | 32CCE9E5213E383E00214381 /* Headers */, 230 | 32CCE9E6213E383E00214381 /* Resources */, 231 | ); 232 | buildRules = ( 233 | ); 234 | dependencies = ( 235 | ); 236 | name = SDWebImagePhotosPlugin; 237 | productName = SDWebImagePhotosPlugin; 238 | productReference = 32CCE9E8213E383E00214381 /* SDWebImagePhotosPlugin.framework */; 239 | productType = "com.apple.product-type.framework"; 240 | }; 241 | 32CCE9F7213E384500214381 /* SDWebImagePhotosPlugin-tvOS */ = { 242 | isa = PBXNativeTarget; 243 | buildConfigurationList = 32CCE9FD213E384600214381 /* Build configuration list for PBXNativeTarget "SDWebImagePhotosPlugin-tvOS" */; 244 | buildPhases = ( 245 | 32CCE9F3213E384500214381 /* Sources */, 246 | 32CCE9F4213E384500214381 /* Frameworks */, 247 | 32CCE9F5213E384500214381 /* Headers */, 248 | 32CCE9F6213E384500214381 /* Resources */, 249 | ); 250 | buildRules = ( 251 | ); 252 | dependencies = ( 253 | ); 254 | name = "SDWebImagePhotosPlugin-tvOS"; 255 | productName = "SDWebImagePhotosPlugin-tvOS"; 256 | productReference = 32CCE9F8213E384500214381 /* SDWebImagePhotosPlugin_tvOS.framework */; 257 | productType = "com.apple.product-type.framework"; 258 | }; 259 | 32CCEA04213E385A00214381 /* SDWebImagePhotosPlugin-macOS */ = { 260 | isa = PBXNativeTarget; 261 | buildConfigurationList = 32CCEA0A213E385A00214381 /* Build configuration list for PBXNativeTarget "SDWebImagePhotosPlugin-macOS" */; 262 | buildPhases = ( 263 | 32CCEA00213E385A00214381 /* Sources */, 264 | 32CCEA01213E385A00214381 /* Frameworks */, 265 | 32CCEA02213E385A00214381 /* Headers */, 266 | 32CCEA03213E385A00214381 /* Resources */, 267 | ); 268 | buildRules = ( 269 | ); 270 | dependencies = ( 271 | ); 272 | name = "SDWebImagePhotosPlugin-macOS"; 273 | productName = "SDWebImagePhotosPlugin-macOS"; 274 | productReference = 32CCEA05213E385A00214381 /* SDWebImagePhotosPlugin_macOS.framework */; 275 | productType = "com.apple.product-type.framework"; 276 | }; 277 | /* End PBXNativeTarget section */ 278 | 279 | /* Begin PBXProject section */ 280 | 32CCE9DF213E383E00214381 /* Project object */ = { 281 | isa = PBXProject; 282 | attributes = { 283 | LastUpgradeCheck = 0940; 284 | ORGANIZATIONNAME = SDWebImagePhotosPlugin; 285 | TargetAttributes = { 286 | 32CCE9E7213E383E00214381 = { 287 | CreatedOnToolsVersion = 9.4; 288 | }; 289 | 32CCE9F7213E384500214381 = { 290 | CreatedOnToolsVersion = 9.4; 291 | }; 292 | 32CCEA04213E385A00214381 = { 293 | CreatedOnToolsVersion = 9.4; 294 | }; 295 | }; 296 | }; 297 | buildConfigurationList = 32CCE9E2213E383E00214381 /* Build configuration list for PBXProject "SDWebImagePhotosPlugin" */; 298 | compatibilityVersion = "Xcode 9.3"; 299 | developmentRegion = en; 300 | hasScannedForEncodings = 0; 301 | knownRegions = ( 302 | en, 303 | ); 304 | mainGroup = 32CCE9DE213E383E00214381; 305 | productRefGroup = 32CCE9E9213E383E00214381 /* Products */; 306 | projectDirPath = ""; 307 | projectRoot = ""; 308 | targets = ( 309 | 32CCE9E7213E383E00214381 /* SDWebImagePhotosPlugin */, 310 | 32CCE9F7213E384500214381 /* SDWebImagePhotosPlugin-tvOS */, 311 | 32CCEA04213E385A00214381 /* SDWebImagePhotosPlugin-macOS */, 312 | ); 313 | }; 314 | /* End PBXProject section */ 315 | 316 | /* Begin PBXResourcesBuildPhase section */ 317 | 32CCE9E6213E383E00214381 /* Resources */ = { 318 | isa = PBXResourcesBuildPhase; 319 | buildActionMask = 2147483647; 320 | files = ( 321 | ); 322 | runOnlyForDeploymentPostprocessing = 0; 323 | }; 324 | 32CCE9F6213E384500214381 /* Resources */ = { 325 | isa = PBXResourcesBuildPhase; 326 | buildActionMask = 2147483647; 327 | files = ( 328 | ); 329 | runOnlyForDeploymentPostprocessing = 0; 330 | }; 331 | 32CCEA03213E385A00214381 /* Resources */ = { 332 | isa = PBXResourcesBuildPhase; 333 | buildActionMask = 2147483647; 334 | files = ( 335 | ); 336 | runOnlyForDeploymentPostprocessing = 0; 337 | }; 338 | /* End PBXResourcesBuildPhase section */ 339 | 340 | /* Begin PBXSourcesBuildPhase section */ 341 | 32CCE9E3213E383E00214381 /* Sources */ = { 342 | isa = PBXSourcesBuildPhase; 343 | buildActionMask = 2147483647; 344 | files = ( 345 | 32CCEA25213E38F600214381 /* SDImagePhotosLoader.m in Sources */, 346 | 32CCEA3A213E38F600214381 /* PHImageRequestOptions+SDWebImagePhotosPlugin.m in Sources */, 347 | 32CCEA2B213E38F600214381 /* SDWebImagePhotosError.m in Sources */, 348 | 32CCEA2E213E38F600214381 /* NSURL+SDWebImagePhotosPlugin.m in Sources */, 349 | 32380B5725B95E87002A50E1 /* PHAsset+SDWebImagePhotosPlugin.m in Sources */, 350 | 32CCEA37213E38F600214381 /* SDWebImagePhotosDefine.m in Sources */, 351 | ); 352 | runOnlyForDeploymentPostprocessing = 0; 353 | }; 354 | 32CCE9F3213E384500214381 /* Sources */ = { 355 | isa = PBXSourcesBuildPhase; 356 | buildActionMask = 2147483647; 357 | files = ( 358 | 32CCEA26213E38F600214381 /* SDImagePhotosLoader.m in Sources */, 359 | 32CCEA3B213E38F600214381 /* PHImageRequestOptions+SDWebImagePhotosPlugin.m in Sources */, 360 | 32CCEA2C213E38F600214381 /* SDWebImagePhotosError.m in Sources */, 361 | 32CCEA2F213E38F600214381 /* NSURL+SDWebImagePhotosPlugin.m in Sources */, 362 | 32380B5825B95E87002A50E1 /* PHAsset+SDWebImagePhotosPlugin.m in Sources */, 363 | 32CCEA38213E38F600214381 /* SDWebImagePhotosDefine.m in Sources */, 364 | ); 365 | runOnlyForDeploymentPostprocessing = 0; 366 | }; 367 | 32CCEA00213E385A00214381 /* Sources */ = { 368 | isa = PBXSourcesBuildPhase; 369 | buildActionMask = 2147483647; 370 | files = ( 371 | 32CCEA27213E38F600214381 /* SDImagePhotosLoader.m in Sources */, 372 | 32CCEA3C213E38F600214381 /* PHImageRequestOptions+SDWebImagePhotosPlugin.m in Sources */, 373 | 32CCEA2D213E38F600214381 /* SDWebImagePhotosError.m in Sources */, 374 | 32CCEA30213E38F600214381 /* NSURL+SDWebImagePhotosPlugin.m in Sources */, 375 | 32380B5925B95E87002A50E1 /* PHAsset+SDWebImagePhotosPlugin.m in Sources */, 376 | 32CCEA39213E38F600214381 /* SDWebImagePhotosDefine.m in Sources */, 377 | ); 378 | runOnlyForDeploymentPostprocessing = 0; 379 | }; 380 | /* End PBXSourcesBuildPhase section */ 381 | 382 | /* Begin XCBuildConfiguration section */ 383 | 32CCE9EE213E383E00214381 /* Debug */ = { 384 | isa = XCBuildConfiguration; 385 | buildSettings = { 386 | ALWAYS_SEARCH_USER_PATHS = NO; 387 | CLANG_ANALYZER_NONNULL = YES; 388 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 389 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; 390 | CLANG_CXX_LIBRARY = "libc++"; 391 | CLANG_ENABLE_MODULES = YES; 392 | CLANG_ENABLE_OBJC_ARC = YES; 393 | CLANG_ENABLE_OBJC_WEAK = YES; 394 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 395 | CLANG_WARN_BOOL_CONVERSION = YES; 396 | CLANG_WARN_COMMA = YES; 397 | CLANG_WARN_CONSTANT_CONVERSION = YES; 398 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 399 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 400 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 401 | CLANG_WARN_EMPTY_BODY = YES; 402 | CLANG_WARN_ENUM_CONVERSION = YES; 403 | CLANG_WARN_INFINITE_RECURSION = YES; 404 | CLANG_WARN_INT_CONVERSION = YES; 405 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 406 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 407 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 408 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 409 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 410 | CLANG_WARN_STRICT_PROTOTYPES = YES; 411 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 412 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 413 | CLANG_WARN_UNREACHABLE_CODE = YES; 414 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 415 | CODE_SIGN_IDENTITY = "iPhone Developer"; 416 | COPY_PHASE_STRIP = NO; 417 | CURRENT_PROJECT_VERSION = 1; 418 | DEBUG_INFORMATION_FORMAT = dwarf; 419 | ENABLE_STRICT_OBJC_MSGSEND = YES; 420 | ENABLE_TESTABILITY = YES; 421 | GCC_C_LANGUAGE_STANDARD = gnu11; 422 | GCC_DYNAMIC_NO_PIC = NO; 423 | GCC_NO_COMMON_BLOCKS = YES; 424 | GCC_OPTIMIZATION_LEVEL = 0; 425 | GCC_PREPROCESSOR_DEFINITIONS = ( 426 | "DEBUG=1", 427 | "$(inherited)", 428 | ); 429 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 430 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 431 | GCC_WARN_UNDECLARED_SELECTOR = YES; 432 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 433 | GCC_WARN_UNUSED_FUNCTION = YES; 434 | GCC_WARN_UNUSED_VARIABLE = YES; 435 | IPHONEOS_DEPLOYMENT_TARGET = 9.0; 436 | MACOSX_DEPLOYMENT_TARGET = 10.13; 437 | MTL_ENABLE_DEBUG_INFO = YES; 438 | ONLY_ACTIVE_ARCH = YES; 439 | SDKROOT = iphoneos; 440 | VERSIONING_SYSTEM = "apple-generic"; 441 | VERSION_INFO_PREFIX = ""; 442 | }; 443 | name = Debug; 444 | }; 445 | 32CCE9EF213E383E00214381 /* Release */ = { 446 | isa = XCBuildConfiguration; 447 | buildSettings = { 448 | ALWAYS_SEARCH_USER_PATHS = NO; 449 | CLANG_ANALYZER_NONNULL = YES; 450 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 451 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; 452 | CLANG_CXX_LIBRARY = "libc++"; 453 | CLANG_ENABLE_MODULES = YES; 454 | CLANG_ENABLE_OBJC_ARC = YES; 455 | CLANG_ENABLE_OBJC_WEAK = YES; 456 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 457 | CLANG_WARN_BOOL_CONVERSION = YES; 458 | CLANG_WARN_COMMA = YES; 459 | CLANG_WARN_CONSTANT_CONVERSION = YES; 460 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 461 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 462 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 463 | CLANG_WARN_EMPTY_BODY = YES; 464 | CLANG_WARN_ENUM_CONVERSION = YES; 465 | CLANG_WARN_INFINITE_RECURSION = YES; 466 | CLANG_WARN_INT_CONVERSION = YES; 467 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 468 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 469 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 470 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 471 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 472 | CLANG_WARN_STRICT_PROTOTYPES = YES; 473 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 474 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 475 | CLANG_WARN_UNREACHABLE_CODE = YES; 476 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 477 | CODE_SIGN_IDENTITY = "iPhone Developer"; 478 | COPY_PHASE_STRIP = NO; 479 | CURRENT_PROJECT_VERSION = 1; 480 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 481 | ENABLE_NS_ASSERTIONS = NO; 482 | ENABLE_STRICT_OBJC_MSGSEND = YES; 483 | GCC_C_LANGUAGE_STANDARD = gnu11; 484 | GCC_NO_COMMON_BLOCKS = YES; 485 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 486 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 487 | GCC_WARN_UNDECLARED_SELECTOR = YES; 488 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 489 | GCC_WARN_UNUSED_FUNCTION = YES; 490 | GCC_WARN_UNUSED_VARIABLE = YES; 491 | IPHONEOS_DEPLOYMENT_TARGET = 9.0; 492 | MACOSX_DEPLOYMENT_TARGET = 10.13; 493 | MTL_ENABLE_DEBUG_INFO = NO; 494 | SDKROOT = iphoneos; 495 | VALIDATE_PRODUCT = YES; 496 | VERSIONING_SYSTEM = "apple-generic"; 497 | VERSION_INFO_PREFIX = ""; 498 | }; 499 | name = Release; 500 | }; 501 | 32CCE9F1213E383E00214381 /* Debug */ = { 502 | isa = XCBuildConfiguration; 503 | buildSettings = { 504 | CODE_SIGN_IDENTITY = ""; 505 | CODE_SIGN_STYLE = Automatic; 506 | DEFINES_MODULE = YES; 507 | DYLIB_COMPATIBILITY_VERSION = 1; 508 | DYLIB_CURRENT_VERSION = 1; 509 | DYLIB_INSTALL_NAME_BASE = "@rpath"; 510 | FRAMEWORK_SEARCH_PATHS = ( 511 | "$(inherited)", 512 | "$(PROJECT_DIR)/Carthage/Build/iOS", 513 | ); 514 | INFOPLIST_FILE = "$(SRCROOT)/SDWebImagePhotosPlugin/Module/Info.plist"; 515 | INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; 516 | LD_RUNPATH_SEARCH_PATHS = ( 517 | "$(inherited)", 518 | "@executable_path/Frameworks", 519 | "@loader_path/Frameworks", 520 | ); 521 | PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.SDWebImagePhotosPlugin; 522 | PRODUCT_MODULE_NAME = SDWebImagePhotosPlugin; 523 | PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; 524 | SKIP_INSTALL = YES; 525 | TARGETED_DEVICE_FAMILY = "1,2"; 526 | }; 527 | name = Debug; 528 | }; 529 | 32CCE9F2213E383E00214381 /* Release */ = { 530 | isa = XCBuildConfiguration; 531 | buildSettings = { 532 | CODE_SIGN_IDENTITY = ""; 533 | CODE_SIGN_STYLE = Automatic; 534 | DEFINES_MODULE = YES; 535 | DYLIB_COMPATIBILITY_VERSION = 1; 536 | DYLIB_CURRENT_VERSION = 1; 537 | DYLIB_INSTALL_NAME_BASE = "@rpath"; 538 | FRAMEWORK_SEARCH_PATHS = ( 539 | "$(inherited)", 540 | "$(PROJECT_DIR)/Carthage/Build/iOS", 541 | ); 542 | INFOPLIST_FILE = "$(SRCROOT)/SDWebImagePhotosPlugin/Module/Info.plist"; 543 | INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; 544 | LD_RUNPATH_SEARCH_PATHS = ( 545 | "$(inherited)", 546 | "@executable_path/Frameworks", 547 | "@loader_path/Frameworks", 548 | ); 549 | PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.SDWebImagePhotosPlugin; 550 | PRODUCT_MODULE_NAME = SDWebImagePhotosPlugin; 551 | PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; 552 | SKIP_INSTALL = YES; 553 | TARGETED_DEVICE_FAMILY = "1,2"; 554 | }; 555 | name = Release; 556 | }; 557 | 32CCE9FE213E384600214381 /* Debug */ = { 558 | isa = XCBuildConfiguration; 559 | buildSettings = { 560 | CODE_SIGN_IDENTITY = ""; 561 | CODE_SIGN_STYLE = Automatic; 562 | DEFINES_MODULE = YES; 563 | DYLIB_COMPATIBILITY_VERSION = 1; 564 | DYLIB_CURRENT_VERSION = 1; 565 | DYLIB_INSTALL_NAME_BASE = "@rpath"; 566 | FRAMEWORK_SEARCH_PATHS = ( 567 | "$(inherited)", 568 | "$(PROJECT_DIR)/Carthage/Build/tvOS", 569 | ); 570 | INFOPLIST_FILE = "$(SRCROOT)/SDWebImagePhotosPlugin/Module/Info.plist"; 571 | INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; 572 | LD_RUNPATH_SEARCH_PATHS = ( 573 | "$(inherited)", 574 | "@executable_path/Frameworks", 575 | "@loader_path/Frameworks", 576 | ); 577 | PRODUCT_BUNDLE_IDENTIFIER = "org.cocoapods.SDWebImagePhotosPlugin-tvOS"; 578 | PRODUCT_MODULE_NAME = SDWebImagePhotosPlugin; 579 | PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; 580 | SDKROOT = appletvos; 581 | SKIP_INSTALL = YES; 582 | TARGETED_DEVICE_FAMILY = 3; 583 | TVOS_DEPLOYMENT_TARGET = 10.0; 584 | }; 585 | name = Debug; 586 | }; 587 | 32CCE9FF213E384600214381 /* Release */ = { 588 | isa = XCBuildConfiguration; 589 | buildSettings = { 590 | CODE_SIGN_IDENTITY = ""; 591 | CODE_SIGN_STYLE = Automatic; 592 | DEFINES_MODULE = YES; 593 | DYLIB_COMPATIBILITY_VERSION = 1; 594 | DYLIB_CURRENT_VERSION = 1; 595 | DYLIB_INSTALL_NAME_BASE = "@rpath"; 596 | FRAMEWORK_SEARCH_PATHS = ( 597 | "$(inherited)", 598 | "$(PROJECT_DIR)/Carthage/Build/tvOS", 599 | ); 600 | INFOPLIST_FILE = "$(SRCROOT)/SDWebImagePhotosPlugin/Module/Info.plist"; 601 | INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; 602 | LD_RUNPATH_SEARCH_PATHS = ( 603 | "$(inherited)", 604 | "@executable_path/Frameworks", 605 | "@loader_path/Frameworks", 606 | ); 607 | PRODUCT_BUNDLE_IDENTIFIER = "org.cocoapods.SDWebImagePhotosPlugin-tvOS"; 608 | PRODUCT_MODULE_NAME = SDWebImagePhotosPlugin; 609 | PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; 610 | SDKROOT = appletvos; 611 | SKIP_INSTALL = YES; 612 | TARGETED_DEVICE_FAMILY = 3; 613 | TVOS_DEPLOYMENT_TARGET = 10.0; 614 | }; 615 | name = Release; 616 | }; 617 | 32CCEA0B213E385A00214381 /* Debug */ = { 618 | isa = XCBuildConfiguration; 619 | buildSettings = { 620 | CODE_SIGN_IDENTITY = "-"; 621 | CODE_SIGN_STYLE = Automatic; 622 | COMBINE_HIDPI_IMAGES = YES; 623 | DEFINES_MODULE = YES; 624 | DYLIB_COMPATIBILITY_VERSION = 1; 625 | DYLIB_CURRENT_VERSION = 1; 626 | DYLIB_INSTALL_NAME_BASE = "@rpath"; 627 | FRAMEWORK_SEARCH_PATHS = ( 628 | "$(inherited)", 629 | "$(PROJECT_DIR)/Carthage/Build/Mac", 630 | ); 631 | FRAMEWORK_VERSION = A; 632 | INFOPLIST_FILE = "$(SRCROOT)/SDWebImagePhotosPlugin/Module/Info.plist"; 633 | INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; 634 | LD_RUNPATH_SEARCH_PATHS = ( 635 | "$(inherited)", 636 | "@executable_path/../Frameworks", 637 | "@loader_path/Frameworks", 638 | ); 639 | MACOSX_DEPLOYMENT_TARGET = 10.13; 640 | PRODUCT_BUNDLE_IDENTIFIER = "org.cocoapods.SDWebImagePhotosPlugin-macOS"; 641 | PRODUCT_MODULE_NAME = SDWebImagePhotosPlugin; 642 | PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; 643 | SDKROOT = macosx; 644 | SKIP_INSTALL = YES; 645 | }; 646 | name = Debug; 647 | }; 648 | 32CCEA0C213E385A00214381 /* Release */ = { 649 | isa = XCBuildConfiguration; 650 | buildSettings = { 651 | CODE_SIGN_IDENTITY = "-"; 652 | CODE_SIGN_STYLE = Automatic; 653 | COMBINE_HIDPI_IMAGES = YES; 654 | DEFINES_MODULE = YES; 655 | DYLIB_COMPATIBILITY_VERSION = 1; 656 | DYLIB_CURRENT_VERSION = 1; 657 | DYLIB_INSTALL_NAME_BASE = "@rpath"; 658 | FRAMEWORK_SEARCH_PATHS = ( 659 | "$(inherited)", 660 | "$(PROJECT_DIR)/Carthage/Build/Mac", 661 | ); 662 | FRAMEWORK_VERSION = A; 663 | INFOPLIST_FILE = "$(SRCROOT)/SDWebImagePhotosPlugin/Module/Info.plist"; 664 | INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; 665 | LD_RUNPATH_SEARCH_PATHS = ( 666 | "$(inherited)", 667 | "@executable_path/../Frameworks", 668 | "@loader_path/Frameworks", 669 | ); 670 | MACOSX_DEPLOYMENT_TARGET = 10.13; 671 | PRODUCT_BUNDLE_IDENTIFIER = "org.cocoapods.SDWebImagePhotosPlugin-macOS"; 672 | PRODUCT_MODULE_NAME = SDWebImagePhotosPlugin; 673 | PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; 674 | SDKROOT = macosx; 675 | SKIP_INSTALL = YES; 676 | }; 677 | name = Release; 678 | }; 679 | /* End XCBuildConfiguration section */ 680 | 681 | /* Begin XCConfigurationList section */ 682 | 32CCE9E2213E383E00214381 /* Build configuration list for PBXProject "SDWebImagePhotosPlugin" */ = { 683 | isa = XCConfigurationList; 684 | buildConfigurations = ( 685 | 32CCE9EE213E383E00214381 /* Debug */, 686 | 32CCE9EF213E383E00214381 /* Release */, 687 | ); 688 | defaultConfigurationIsVisible = 0; 689 | defaultConfigurationName = Release; 690 | }; 691 | 32CCE9F0213E383E00214381 /* Build configuration list for PBXNativeTarget "SDWebImagePhotosPlugin" */ = { 692 | isa = XCConfigurationList; 693 | buildConfigurations = ( 694 | 32CCE9F1213E383E00214381 /* Debug */, 695 | 32CCE9F2213E383E00214381 /* Release */, 696 | ); 697 | defaultConfigurationIsVisible = 0; 698 | defaultConfigurationName = Release; 699 | }; 700 | 32CCE9FD213E384600214381 /* Build configuration list for PBXNativeTarget "SDWebImagePhotosPlugin-tvOS" */ = { 701 | isa = XCConfigurationList; 702 | buildConfigurations = ( 703 | 32CCE9FE213E384600214381 /* Debug */, 704 | 32CCE9FF213E384600214381 /* Release */, 705 | ); 706 | defaultConfigurationIsVisible = 0; 707 | defaultConfigurationName = Release; 708 | }; 709 | 32CCEA0A213E385A00214381 /* Build configuration list for PBXNativeTarget "SDWebImagePhotosPlugin-macOS" */ = { 710 | isa = XCConfigurationList; 711 | buildConfigurations = ( 712 | 32CCEA0B213E385A00214381 /* Debug */, 713 | 32CCEA0C213E385A00214381 /* Release */, 714 | ); 715 | defaultConfigurationIsVisible = 0; 716 | defaultConfigurationName = Release; 717 | }; 718 | /* End XCConfigurationList section */ 719 | }; 720 | rootObject = 32CCE9DF213E383E00214381 /* Project object */; 721 | } 722 | --------------------------------------------------------------------------------