├── .gitignore ├── ARTICLE.md ├── Assets ├── Browser.png ├── Home.gif ├── Introduction.gif ├── Transition.png ├── gifImage.gif ├── rawImage.jpg └── testwebp.webp ├── CHANGELOG.md ├── Example ├── Example.xcodeproj │ ├── project.pbxproj │ └── project.xcworkspace │ │ ├── contents.xcworkspacedata │ │ └── xcshareddata │ │ └── IDEWorkspaceChecks.plist ├── Example.xcworkspace │ ├── contents.xcworkspacedata │ └── xcshareddata │ │ └── IDEWorkspaceChecks.plist ├── Example │ ├── AppDelegate.swift │ ├── Assets.xcassets │ │ ├── AppIcon.appiconset │ │ │ ├── Contents.json │ │ │ ├── 图片浏览器iPadApp_76pt.png │ │ │ ├── 图片浏览器iPadApp_76pt@2x.png │ │ │ ├── 图片浏览器iPadNotifications_20pt.png │ │ │ ├── 图片浏览器iPadNotifications_20pt@2x.png │ │ │ ├── 图片浏览器iPadProApp_83.5pt@2x.png │ │ │ ├── 图片浏览器iPadSpootlight5_29pt.png │ │ │ ├── 图片浏览器iPadSpootlight5_29pt@2x.png │ │ │ ├── 图片浏览器iPadSpootlight7_40pt.png │ │ │ ├── 图片浏览器iPadSpootlight7_40pt@2x.png │ │ │ ├── 图片浏览器iPhoneApp_60pt@2x.png │ │ │ ├── 图片浏览器iPhoneApp_60pt@3x.png │ │ │ ├── 图片浏览器iPhoneNotification_20pt@2x.png │ │ │ ├── 图片浏览器iPhoneNotification_20pt@3x.png │ │ │ ├── 图片浏览器iPhoneSpootlight5_29pt@2x.png │ │ │ ├── 图片浏览器iPhoneSpootlight5_29pt@3x.png │ │ │ ├── 图片浏览器iPhoneSpootlight7_40pt@2x.png │ │ │ ├── 图片浏览器iPhoneSpootlight7_40pt@3x.png │ │ │ └── 图片浏览器store_1024pt.png │ │ ├── Contents.json │ │ ├── local_0.imageset │ │ │ ├── Contents.json │ │ │ └── local_0.jpeg │ │ ├── local_1.imageset │ │ │ ├── Contents.json │ │ │ └── local_1.png │ │ ├── local_2.imageset │ │ │ ├── Contents.json │ │ │ └── local_2.jpeg │ │ ├── local_3.imageset │ │ │ ├── Contents.json │ │ │ └── local_3.jpeg │ │ ├── local_4.imageset │ │ │ ├── Contents.json │ │ │ └── local_4.jpeg │ │ └── local_5.imageset │ │ │ ├── Contents.json │ │ │ └── local_5.jpeg │ ├── Base.lproj │ │ ├── LaunchScreen.storyboard │ │ └── Main.storyboard │ ├── BaseCollectionViewCell.swift │ ├── BaseCollectionViewController.swift │ ├── DataSourceAppendViewController.swift │ ├── DataSourceDeleteViewController.swift │ ├── DefaultPageIndicatorViewController.swift │ ├── GIFViewController.swift │ ├── HomeViewController.swift │ ├── ImageSmoothZoomViewController.swift │ ├── ImageZoomViewController.swift │ ├── Info.plist │ ├── JXNamespace.swift │ ├── JXPhotoBrowserProgressView.swift │ ├── KingfisherImageViewController.swift │ ├── LoadingProgressViewController.swift │ ├── LocalImageViewController.swift │ ├── MoreDetailViewController.swift │ ├── MultipleCellViewController.swift │ ├── MultipleSectionViewController.swift │ ├── NumberPageIndicatorViewController.swift │ ├── Photos.plist │ ├── PushNextViewController.swift │ ├── RawImageViewController.swift │ ├── ResourceModel.swift │ ├── SDWebImageViewController.swift │ ├── SceneDelegate.swift │ ├── UICollectionView+JX.swift │ ├── UITableView+JX.swift │ ├── VerticalBrowseViewController.swift │ ├── VideoCell.swift │ ├── VideoPhotoViewController.swift │ ├── video_0.MP4 │ ├── video_1.MP4 │ └── video_2.MP4 ├── Podfile ├── Podfile.lock ├── Pods │ ├── Kingfisher │ │ ├── LICENSE │ │ ├── README.md │ │ └── Sources │ │ │ ├── Cache │ │ │ ├── CacheSerializer.swift │ │ │ ├── DiskStorage.swift │ │ │ ├── FormatIndicatedCacheSerializer.swift │ │ │ ├── ImageCache.swift │ │ │ ├── MemoryStorage.swift │ │ │ └── Storage.swift │ │ │ ├── Extensions │ │ │ ├── CPListItem+Kingfisher.swift │ │ │ ├── ImageView+Kingfisher.swift │ │ │ ├── NSButton+Kingfisher.swift │ │ │ ├── NSTextAttachment+Kingfisher.swift │ │ │ ├── TVMonogramView+Kingfisher.swift │ │ │ ├── UIButton+Kingfisher.swift │ │ │ └── WKInterfaceImage+Kingfisher.swift │ │ │ ├── General │ │ │ ├── ImageSource │ │ │ │ ├── AVAssetImageDataProvider.swift │ │ │ │ ├── ImageDataProvider.swift │ │ │ │ ├── Resource.swift │ │ │ │ └── Source.swift │ │ │ ├── KF.swift │ │ │ ├── KFOptionsSetter.swift │ │ │ ├── Kingfisher.swift │ │ │ ├── KingfisherError.swift │ │ │ ├── KingfisherManager.swift │ │ │ └── KingfisherOptionsInfo.swift │ │ │ ├── Image │ │ │ ├── Filter.swift │ │ │ ├── GIFAnimatedImage.swift │ │ │ ├── GraphicsContext.swift │ │ │ ├── Image.swift │ │ │ ├── ImageDrawing.swift │ │ │ ├── ImageFormat.swift │ │ │ ├── ImageProcessor.swift │ │ │ ├── ImageProgressive.swift │ │ │ ├── ImageTransition.swift │ │ │ └── Placeholder.swift │ │ │ ├── Networking │ │ │ ├── AuthenticationChallengeResponsable.swift │ │ │ ├── ImageDataProcessor.swift │ │ │ ├── ImageDownloader.swift │ │ │ ├── ImageDownloaderDelegate.swift │ │ │ ├── ImageModifier.swift │ │ │ ├── ImagePrefetcher.swift │ │ │ ├── RedirectHandler.swift │ │ │ ├── RequestModifier.swift │ │ │ ├── RetryStrategy.swift │ │ │ ├── SessionDataTask.swift │ │ │ └── SessionDelegate.swift │ │ │ ├── PrivacyInfo.xcprivacy │ │ │ ├── SwiftUI │ │ │ ├── ImageBinder.swift │ │ │ ├── ImageContext.swift │ │ │ ├── KFAnimatedImage.swift │ │ │ ├── KFImage.swift │ │ │ ├── KFImageOptions.swift │ │ │ ├── KFImageProtocol.swift │ │ │ └── KFImageRenderer.swift │ │ │ ├── Utility │ │ │ ├── Box.swift │ │ │ ├── CallbackQueue.swift │ │ │ ├── Delegate.swift │ │ │ ├── ExtensionHelpers.swift │ │ │ ├── Result.swift │ │ │ ├── Runtime.swift │ │ │ ├── SizeExtensions.swift │ │ │ └── String+MD5.swift │ │ │ └── Views │ │ │ ├── AnimatedImageView.swift │ │ │ └── Indicator.swift │ ├── Local Podspecs │ │ └── JXPhotoBrowser.podspec.json │ ├── Manifest.lock │ ├── Pods.xcodeproj │ │ └── project.pbxproj │ ├── SDWebImage │ │ ├── LICENSE │ │ ├── README.md │ │ ├── SDWebImage │ │ │ ├── Core │ │ │ │ ├── NSButton+WebCache.h │ │ │ │ ├── NSButton+WebCache.m │ │ │ │ ├── NSData+ImageContentType.h │ │ │ │ ├── NSData+ImageContentType.m │ │ │ │ ├── NSImage+Compatibility.h │ │ │ │ ├── NSImage+Compatibility.m │ │ │ │ ├── SDAnimatedImage.h │ │ │ │ ├── SDAnimatedImage.m │ │ │ │ ├── SDAnimatedImagePlayer.h │ │ │ │ ├── SDAnimatedImagePlayer.m │ │ │ │ ├── SDAnimatedImageRep.h │ │ │ │ ├── SDAnimatedImageRep.m │ │ │ │ ├── SDAnimatedImageView+WebCache.h │ │ │ │ ├── SDAnimatedImageView+WebCache.m │ │ │ │ ├── SDAnimatedImageView.h │ │ │ │ ├── SDAnimatedImageView.m │ │ │ │ ├── SDCallbackQueue.h │ │ │ │ ├── SDCallbackQueue.m │ │ │ │ ├── SDDiskCache.h │ │ │ │ ├── SDDiskCache.m │ │ │ │ ├── SDGraphicsImageRenderer.h │ │ │ │ ├── SDGraphicsImageRenderer.m │ │ │ │ ├── SDImageAPNGCoder.h │ │ │ │ ├── SDImageAPNGCoder.m │ │ │ │ ├── SDImageAWebPCoder.h │ │ │ │ ├── SDImageAWebPCoder.m │ │ │ │ ├── SDImageCache.h │ │ │ │ ├── SDImageCache.m │ │ │ │ ├── SDImageCacheConfig.h │ │ │ │ ├── SDImageCacheConfig.m │ │ │ │ ├── SDImageCacheDefine.h │ │ │ │ ├── SDImageCacheDefine.m │ │ │ │ ├── SDImageCachesManager.h │ │ │ │ ├── SDImageCachesManager.m │ │ │ │ ├── SDImageCoder.h │ │ │ │ ├── SDImageCoder.m │ │ │ │ ├── SDImageCoderHelper.h │ │ │ │ ├── SDImageCoderHelper.m │ │ │ │ ├── SDImageCodersManager.h │ │ │ │ ├── SDImageCodersManager.m │ │ │ │ ├── SDImageFrame.h │ │ │ │ ├── SDImageFrame.m │ │ │ │ ├── SDImageGIFCoder.h │ │ │ │ ├── SDImageGIFCoder.m │ │ │ │ ├── SDImageGraphics.h │ │ │ │ ├── SDImageGraphics.m │ │ │ │ ├── SDImageHEICCoder.h │ │ │ │ ├── SDImageHEICCoder.m │ │ │ │ ├── SDImageIOAnimatedCoder.h │ │ │ │ ├── SDImageIOAnimatedCoder.m │ │ │ │ ├── SDImageIOCoder.h │ │ │ │ ├── SDImageIOCoder.m │ │ │ │ ├── SDImageLoader.h │ │ │ │ ├── SDImageLoader.m │ │ │ │ ├── SDImageLoadersManager.h │ │ │ │ ├── SDImageLoadersManager.m │ │ │ │ ├── SDImageTransformer.h │ │ │ │ ├── SDImageTransformer.m │ │ │ │ ├── SDMemoryCache.h │ │ │ │ ├── SDMemoryCache.m │ │ │ │ ├── SDWebImageCacheKeyFilter.h │ │ │ │ ├── SDWebImageCacheKeyFilter.m │ │ │ │ ├── SDWebImageCacheSerializer.h │ │ │ │ ├── SDWebImageCacheSerializer.m │ │ │ │ ├── SDWebImageCompat.h │ │ │ │ ├── SDWebImageCompat.m │ │ │ │ ├── SDWebImageDefine.h │ │ │ │ ├── SDWebImageDefine.m │ │ │ │ ├── SDWebImageDownloader.h │ │ │ │ ├── SDWebImageDownloader.m │ │ │ │ ├── SDWebImageDownloaderConfig.h │ │ │ │ ├── SDWebImageDownloaderConfig.m │ │ │ │ ├── SDWebImageDownloaderDecryptor.h │ │ │ │ ├── SDWebImageDownloaderDecryptor.m │ │ │ │ ├── SDWebImageDownloaderOperation.h │ │ │ │ ├── SDWebImageDownloaderOperation.m │ │ │ │ ├── SDWebImageDownloaderRequestModifier.h │ │ │ │ ├── SDWebImageDownloaderRequestModifier.m │ │ │ │ ├── SDWebImageDownloaderResponseModifier.h │ │ │ │ ├── SDWebImageDownloaderResponseModifier.m │ │ │ │ ├── SDWebImageError.h │ │ │ │ ├── SDWebImageError.m │ │ │ │ ├── SDWebImageIndicator.h │ │ │ │ ├── SDWebImageIndicator.m │ │ │ │ ├── SDWebImageManager.h │ │ │ │ ├── SDWebImageManager.m │ │ │ │ ├── SDWebImageOperation.h │ │ │ │ ├── SDWebImageOperation.m │ │ │ │ ├── SDWebImageOptionsProcessor.h │ │ │ │ ├── SDWebImageOptionsProcessor.m │ │ │ │ ├── SDWebImagePrefetcher.h │ │ │ │ ├── SDWebImagePrefetcher.m │ │ │ │ ├── SDWebImageTransition.h │ │ │ │ ├── SDWebImageTransition.m │ │ │ │ ├── UIButton+WebCache.h │ │ │ │ ├── UIButton+WebCache.m │ │ │ │ ├── UIImage+ExtendedCacheData.h │ │ │ │ ├── UIImage+ExtendedCacheData.m │ │ │ │ ├── UIImage+ForceDecode.h │ │ │ │ ├── UIImage+ForceDecode.m │ │ │ │ ├── UIImage+GIF.h │ │ │ │ ├── UIImage+GIF.m │ │ │ │ ├── UIImage+MemoryCacheCost.h │ │ │ │ ├── UIImage+MemoryCacheCost.m │ │ │ │ ├── UIImage+Metadata.h │ │ │ │ ├── UIImage+Metadata.m │ │ │ │ ├── UIImage+MultiFormat.h │ │ │ │ ├── UIImage+MultiFormat.m │ │ │ │ ├── UIImage+Transform.h │ │ │ │ ├── UIImage+Transform.m │ │ │ │ ├── UIImageView+HighlightedWebCache.h │ │ │ │ ├── UIImageView+HighlightedWebCache.m │ │ │ │ ├── UIImageView+WebCache.h │ │ │ │ ├── UIImageView+WebCache.m │ │ │ │ ├── UIView+WebCache.h │ │ │ │ ├── UIView+WebCache.m │ │ │ │ ├── UIView+WebCacheOperation.h │ │ │ │ ├── UIView+WebCacheOperation.m │ │ │ │ ├── UIView+WebCacheState.h │ │ │ │ └── UIView+WebCacheState.m │ │ │ └── Private │ │ │ │ ├── NSBezierPath+SDRoundedCorners.h │ │ │ │ ├── NSBezierPath+SDRoundedCorners.m │ │ │ │ ├── SDAssociatedObject.h │ │ │ │ ├── SDAssociatedObject.m │ │ │ │ ├── SDAsyncBlockOperation.h │ │ │ │ ├── SDAsyncBlockOperation.m │ │ │ │ ├── SDDeviceHelper.h │ │ │ │ ├── SDDeviceHelper.m │ │ │ │ ├── SDDisplayLink.h │ │ │ │ ├── SDDisplayLink.m │ │ │ │ ├── SDFileAttributeHelper.h │ │ │ │ ├── SDFileAttributeHelper.m │ │ │ │ ├── SDImageAssetManager.h │ │ │ │ ├── SDImageAssetManager.m │ │ │ │ ├── SDImageCachesManagerOperation.h │ │ │ │ ├── SDImageCachesManagerOperation.m │ │ │ │ ├── SDImageFramePool.h │ │ │ │ ├── SDImageFramePool.m │ │ │ │ ├── SDImageIOAnimatedCoderInternal.h │ │ │ │ ├── SDInternalMacros.h │ │ │ │ ├── SDInternalMacros.m │ │ │ │ ├── SDWeakProxy.h │ │ │ │ ├── SDWeakProxy.m │ │ │ │ ├── SDWebImageTransitionInternal.h │ │ │ │ ├── SDmetamacros.h │ │ │ │ ├── UIColor+SDHexString.h │ │ │ │ └── UIColor+SDHexString.m │ │ └── WebImage │ │ │ ├── PrivacyInfo.xcprivacy │ │ │ └── SDWebImage.h │ └── Target Support Files │ │ ├── JXPhotoBrowser │ │ ├── JXPhotoBrowser-Info.plist │ │ ├── JXPhotoBrowser-dummy.m │ │ ├── JXPhotoBrowser-prefix.pch │ │ ├── JXPhotoBrowser-umbrella.h │ │ ├── JXPhotoBrowser.debug.xcconfig │ │ ├── JXPhotoBrowser.modulemap │ │ ├── JXPhotoBrowser.release.xcconfig │ │ └── JXPhotoBrowser.xcconfig │ │ ├── Kingfisher │ │ ├── Kingfisher-Info.plist │ │ ├── Kingfisher-dummy.m │ │ ├── Kingfisher-prefix.pch │ │ ├── Kingfisher-umbrella.h │ │ ├── Kingfisher.debug.xcconfig │ │ ├── Kingfisher.modulemap │ │ ├── Kingfisher.release.xcconfig │ │ ├── Kingfisher.xcconfig │ │ └── ResourceBundle-Kingfisher-Kingfisher-Info.plist │ │ ├── Pods-Example │ │ ├── Pods-Example-Info.plist │ │ ├── Pods-Example-acknowledgements.markdown │ │ ├── Pods-Example-acknowledgements.plist │ │ ├── Pods-Example-dummy.m │ │ ├── Pods-Example-frameworks-Debug-input-files.xcfilelist │ │ ├── Pods-Example-frameworks-Debug-output-files.xcfilelist │ │ ├── Pods-Example-frameworks-Release-input-files.xcfilelist │ │ ├── Pods-Example-frameworks-Release-output-files.xcfilelist │ │ ├── Pods-Example-frameworks.sh │ │ ├── Pods-Example-umbrella.h │ │ ├── Pods-Example.debug.xcconfig │ │ ├── Pods-Example.modulemap │ │ └── Pods-Example.release.xcconfig │ │ └── SDWebImage │ │ ├── ResourceBundle-SDWebImage-SDWebImage-Info.plist │ │ ├── SDWebImage-Info.plist │ │ ├── SDWebImage-dummy.m │ │ ├── SDWebImage-prefix.pch │ │ ├── SDWebImage-umbrella.h │ │ ├── SDWebImage.debug.xcconfig │ │ ├── SDWebImage.modulemap │ │ ├── SDWebImage.release.xcconfig │ │ └── SDWebImage.xcconfig └── Sources │ ├── AppIconScreenShot.png │ └── 图片浏览器.sketch ├── JXPhotoBrowser.podspec ├── LICENSE ├── Package.swift ├── README.md ├── Sources └── JXPhotoBrowser │ ├── JXPhotoBrowser.swift │ ├── JXPhotoBrowserAnimatedTransitioning.swift │ ├── JXPhotoBrowserCell.swift │ ├── JXPhotoBrowserDefaultPageIndicator.swift │ ├── JXPhotoBrowserFadeAnimator.swift │ ├── JXPhotoBrowserImageCell.swift │ ├── JXPhotoBrowserImageView.swift │ ├── JXPhotoBrowserLog.swift │ ├── JXPhotoBrowserNoneAnimator.swift │ ├── JXPhotoBrowserNumberPageIndicator.swift │ ├── JXPhotoBrowserPageIndicator.swift │ ├── JXPhotoBrowserSmoothZoomAnimator.swift │ ├── JXPhotoBrowserView.swift │ ├── JXPhotoBrowserZoomAnimator.swift │ └── JXPhotoBrowserZoomSupportedCell.swift ├── SwiftPMExample ├── SwiftPMExample.xcodeproj │ ├── project.pbxproj │ └── project.xcworkspace │ │ ├── contents.xcworkspacedata │ │ └── xcshareddata │ │ ├── IDEWorkspaceChecks.plist │ │ └── swiftpm │ │ └── Package.resolved └── SwiftPMExample │ ├── AppDelegate.swift │ ├── Assets.xcassets │ ├── AppIcon.appiconset │ │ └── Contents.json │ └── Contents.json │ ├── Base.lproj │ ├── LaunchScreen.storyboard │ └── Main.storyboard │ ├── Info.plist │ ├── SceneDelegate.swift │ └── ViewController.swift ├── Version1.x.md └── Version2.x.md /.gitignore: -------------------------------------------------------------------------------- 1 | # OS X 2 | .DS_Store 3 | 4 | # Xcode 5 | build/ 6 | .build/ 7 | *.pbxuser 8 | !default.pbxuser 9 | *.mode1v3 10 | !default.mode1v3 11 | *.mode2v3 12 | !default.mode2v3 13 | *.perspectivev3 14 | !default.perspectivev3 15 | xcuserdata/ 16 | *.xccheckout 17 | profile 18 | *.moved-aside 19 | DerivedData 20 | *.hmap 21 | *.ipa 22 | 23 | # Bundler 24 | .bundle 25 | 26 | # Add this line if you want to avoid checking in source code from Carthage dependencies. 27 | # Carthage/Checkouts 28 | 29 | Carthage/Build 30 | 31 | # We recommend against adding the Pods directory to your .gitignore. However 32 | # you should judge for yourself, the pros and cons are mentioned at: 33 | # https://guides.cocoapods.org/using/using-cocoapods.html#should-i-ignore-the-pods-directory-in-source-control 34 | # 35 | # Note: if you ignore the Pods directory, make sure to uncomment 36 | # `pod install` in .travis.yml 37 | # 38 | # Pods/ 39 | -------------------------------------------------------------------------------- /Assets/Browser.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JiongXing/PhotoBrowser/69c5212485b54eeb0eaaa5f77dde1ebb787a51d0/Assets/Browser.png -------------------------------------------------------------------------------- /Assets/Home.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JiongXing/PhotoBrowser/69c5212485b54eeb0eaaa5f77dde1ebb787a51d0/Assets/Home.gif -------------------------------------------------------------------------------- /Assets/Introduction.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JiongXing/PhotoBrowser/69c5212485b54eeb0eaaa5f77dde1ebb787a51d0/Assets/Introduction.gif -------------------------------------------------------------------------------- /Assets/Transition.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JiongXing/PhotoBrowser/69c5212485b54eeb0eaaa5f77dde1ebb787a51d0/Assets/Transition.png -------------------------------------------------------------------------------- /Assets/gifImage.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JiongXing/PhotoBrowser/69c5212485b54eeb0eaaa5f77dde1ebb787a51d0/Assets/gifImage.gif -------------------------------------------------------------------------------- /Assets/rawImage.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JiongXing/PhotoBrowser/69c5212485b54eeb0eaaa5f77dde1ebb787a51d0/Assets/rawImage.jpg -------------------------------------------------------------------------------- /Assets/testwebp.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JiongXing/PhotoBrowser/69c5212485b54eeb0eaaa5f77dde1ebb787a51d0/Assets/testwebp.webp -------------------------------------------------------------------------------- /Example/Example.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /Example/Example.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /Example/Example.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /Example/Example.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /Example/Example/AppDelegate.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.swift 3 | // Example 4 | // 5 | // Created by JiongXing on 2019/11/26. 6 | // Copyright © 2019 JiongXing. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | @UIApplicationMain 12 | class AppDelegate: UIResponder, UIApplicationDelegate { 13 | 14 | func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { 15 | // Override point for customization after application launch. 16 | return true 17 | } 18 | 19 | // MARK: UISceneSession Lifecycle 20 | 21 | func application(_ application: UIApplication, configurationForConnecting connectingSceneSession: UISceneSession, options: UIScene.ConnectionOptions) -> UISceneConfiguration { 22 | // Called when a new scene session is being created. 23 | // Use this method to select a configuration to create the new scene with. 24 | return UISceneConfiguration(name: "Default Configuration", sessionRole: connectingSceneSession.role) 25 | } 26 | 27 | func application(_ application: UIApplication, didDiscardSceneSessions sceneSessions: Set) { 28 | // Called when the user discards a scene session. 29 | // If any sessions were discarded while the application was not running, this will be called shortly after application:didFinishLaunchingWithOptions. 30 | // Use this method to release any resources that were specific to the discarded scenes, as they will not return. 31 | } 32 | 33 | 34 | } 35 | 36 | -------------------------------------------------------------------------------- /Example/Example/Assets.xcassets/AppIcon.appiconset/图片浏览器iPadApp_76pt.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JiongXing/PhotoBrowser/69c5212485b54eeb0eaaa5f77dde1ebb787a51d0/Example/Example/Assets.xcassets/AppIcon.appiconset/图片浏览器iPadApp_76pt.png -------------------------------------------------------------------------------- /Example/Example/Assets.xcassets/AppIcon.appiconset/图片浏览器iPadApp_76pt@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JiongXing/PhotoBrowser/69c5212485b54eeb0eaaa5f77dde1ebb787a51d0/Example/Example/Assets.xcassets/AppIcon.appiconset/图片浏览器iPadApp_76pt@2x.png -------------------------------------------------------------------------------- /Example/Example/Assets.xcassets/AppIcon.appiconset/图片浏览器iPadNotifications_20pt.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JiongXing/PhotoBrowser/69c5212485b54eeb0eaaa5f77dde1ebb787a51d0/Example/Example/Assets.xcassets/AppIcon.appiconset/图片浏览器iPadNotifications_20pt.png -------------------------------------------------------------------------------- /Example/Example/Assets.xcassets/AppIcon.appiconset/图片浏览器iPadNotifications_20pt@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JiongXing/PhotoBrowser/69c5212485b54eeb0eaaa5f77dde1ebb787a51d0/Example/Example/Assets.xcassets/AppIcon.appiconset/图片浏览器iPadNotifications_20pt@2x.png -------------------------------------------------------------------------------- /Example/Example/Assets.xcassets/AppIcon.appiconset/图片浏览器iPadProApp_83.5pt@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JiongXing/PhotoBrowser/69c5212485b54eeb0eaaa5f77dde1ebb787a51d0/Example/Example/Assets.xcassets/AppIcon.appiconset/图片浏览器iPadProApp_83.5pt@2x.png -------------------------------------------------------------------------------- /Example/Example/Assets.xcassets/AppIcon.appiconset/图片浏览器iPadSpootlight5_29pt.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JiongXing/PhotoBrowser/69c5212485b54eeb0eaaa5f77dde1ebb787a51d0/Example/Example/Assets.xcassets/AppIcon.appiconset/图片浏览器iPadSpootlight5_29pt.png -------------------------------------------------------------------------------- /Example/Example/Assets.xcassets/AppIcon.appiconset/图片浏览器iPadSpootlight5_29pt@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JiongXing/PhotoBrowser/69c5212485b54eeb0eaaa5f77dde1ebb787a51d0/Example/Example/Assets.xcassets/AppIcon.appiconset/图片浏览器iPadSpootlight5_29pt@2x.png -------------------------------------------------------------------------------- /Example/Example/Assets.xcassets/AppIcon.appiconset/图片浏览器iPadSpootlight7_40pt.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JiongXing/PhotoBrowser/69c5212485b54eeb0eaaa5f77dde1ebb787a51d0/Example/Example/Assets.xcassets/AppIcon.appiconset/图片浏览器iPadSpootlight7_40pt.png -------------------------------------------------------------------------------- /Example/Example/Assets.xcassets/AppIcon.appiconset/图片浏览器iPadSpootlight7_40pt@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JiongXing/PhotoBrowser/69c5212485b54eeb0eaaa5f77dde1ebb787a51d0/Example/Example/Assets.xcassets/AppIcon.appiconset/图片浏览器iPadSpootlight7_40pt@2x.png -------------------------------------------------------------------------------- /Example/Example/Assets.xcassets/AppIcon.appiconset/图片浏览器iPhoneApp_60pt@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JiongXing/PhotoBrowser/69c5212485b54eeb0eaaa5f77dde1ebb787a51d0/Example/Example/Assets.xcassets/AppIcon.appiconset/图片浏览器iPhoneApp_60pt@2x.png -------------------------------------------------------------------------------- /Example/Example/Assets.xcassets/AppIcon.appiconset/图片浏览器iPhoneApp_60pt@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JiongXing/PhotoBrowser/69c5212485b54eeb0eaaa5f77dde1ebb787a51d0/Example/Example/Assets.xcassets/AppIcon.appiconset/图片浏览器iPhoneApp_60pt@3x.png -------------------------------------------------------------------------------- /Example/Example/Assets.xcassets/AppIcon.appiconset/图片浏览器iPhoneNotification_20pt@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JiongXing/PhotoBrowser/69c5212485b54eeb0eaaa5f77dde1ebb787a51d0/Example/Example/Assets.xcassets/AppIcon.appiconset/图片浏览器iPhoneNotification_20pt@2x.png -------------------------------------------------------------------------------- /Example/Example/Assets.xcassets/AppIcon.appiconset/图片浏览器iPhoneNotification_20pt@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JiongXing/PhotoBrowser/69c5212485b54eeb0eaaa5f77dde1ebb787a51d0/Example/Example/Assets.xcassets/AppIcon.appiconset/图片浏览器iPhoneNotification_20pt@3x.png -------------------------------------------------------------------------------- /Example/Example/Assets.xcassets/AppIcon.appiconset/图片浏览器iPhoneSpootlight5_29pt@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JiongXing/PhotoBrowser/69c5212485b54eeb0eaaa5f77dde1ebb787a51d0/Example/Example/Assets.xcassets/AppIcon.appiconset/图片浏览器iPhoneSpootlight5_29pt@2x.png -------------------------------------------------------------------------------- /Example/Example/Assets.xcassets/AppIcon.appiconset/图片浏览器iPhoneSpootlight5_29pt@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JiongXing/PhotoBrowser/69c5212485b54eeb0eaaa5f77dde1ebb787a51d0/Example/Example/Assets.xcassets/AppIcon.appiconset/图片浏览器iPhoneSpootlight5_29pt@3x.png -------------------------------------------------------------------------------- /Example/Example/Assets.xcassets/AppIcon.appiconset/图片浏览器iPhoneSpootlight7_40pt@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JiongXing/PhotoBrowser/69c5212485b54eeb0eaaa5f77dde1ebb787a51d0/Example/Example/Assets.xcassets/AppIcon.appiconset/图片浏览器iPhoneSpootlight7_40pt@2x.png -------------------------------------------------------------------------------- /Example/Example/Assets.xcassets/AppIcon.appiconset/图片浏览器iPhoneSpootlight7_40pt@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JiongXing/PhotoBrowser/69c5212485b54eeb0eaaa5f77dde1ebb787a51d0/Example/Example/Assets.xcassets/AppIcon.appiconset/图片浏览器iPhoneSpootlight7_40pt@3x.png -------------------------------------------------------------------------------- /Example/Example/Assets.xcassets/AppIcon.appiconset/图片浏览器store_1024pt.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JiongXing/PhotoBrowser/69c5212485b54eeb0eaaa5f77dde1ebb787a51d0/Example/Example/Assets.xcassets/AppIcon.appiconset/图片浏览器store_1024pt.png -------------------------------------------------------------------------------- /Example/Example/Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "version" : 1, 4 | "author" : "xcode" 5 | } 6 | } -------------------------------------------------------------------------------- /Example/Example/Assets.xcassets/local_0.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "local_0.jpeg", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /Example/Example/Assets.xcassets/local_0.imageset/local_0.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JiongXing/PhotoBrowser/69c5212485b54eeb0eaaa5f77dde1ebb787a51d0/Example/Example/Assets.xcassets/local_0.imageset/local_0.jpeg -------------------------------------------------------------------------------- /Example/Example/Assets.xcassets/local_1.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "local_1.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /Example/Example/Assets.xcassets/local_1.imageset/local_1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JiongXing/PhotoBrowser/69c5212485b54eeb0eaaa5f77dde1ebb787a51d0/Example/Example/Assets.xcassets/local_1.imageset/local_1.png -------------------------------------------------------------------------------- /Example/Example/Assets.xcassets/local_2.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "local_2.jpeg", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /Example/Example/Assets.xcassets/local_2.imageset/local_2.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JiongXing/PhotoBrowser/69c5212485b54eeb0eaaa5f77dde1ebb787a51d0/Example/Example/Assets.xcassets/local_2.imageset/local_2.jpeg -------------------------------------------------------------------------------- /Example/Example/Assets.xcassets/local_3.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "local_3.jpeg", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /Example/Example/Assets.xcassets/local_3.imageset/local_3.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JiongXing/PhotoBrowser/69c5212485b54eeb0eaaa5f77dde1ebb787a51d0/Example/Example/Assets.xcassets/local_3.imageset/local_3.jpeg -------------------------------------------------------------------------------- /Example/Example/Assets.xcassets/local_4.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "local_4.jpeg", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /Example/Example/Assets.xcassets/local_4.imageset/local_4.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JiongXing/PhotoBrowser/69c5212485b54eeb0eaaa5f77dde1ebb787a51d0/Example/Example/Assets.xcassets/local_4.imageset/local_4.jpeg -------------------------------------------------------------------------------- /Example/Example/Assets.xcassets/local_5.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "local_5.jpeg", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /Example/Example/Assets.xcassets/local_5.imageset/local_5.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JiongXing/PhotoBrowser/69c5212485b54eeb0eaaa5f77dde1ebb787a51d0/Example/Example/Assets.xcassets/local_5.imageset/local_5.jpeg -------------------------------------------------------------------------------- /Example/Example/Base.lproj/LaunchScreen.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /Example/Example/BaseCollectionViewCell.swift: -------------------------------------------------------------------------------- 1 | // 2 | // BaseCollectionViewCell.swift 3 | // JXPhotoBrwoser_Example 4 | // 5 | // Created by JiongXing on 2018/10/14. 6 | // Copyright © 2018年 CocoaPods. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | class BaseCollectionViewCell: UICollectionViewCell { 12 | lazy var imageView: UIImageView = { 13 | let iv = UIImageView() 14 | iv.clipsToBounds = true 15 | iv.contentMode = .scaleAspectFill 16 | return iv 17 | }() 18 | 19 | override init(frame: CGRect) { 20 | super.init(frame: frame) 21 | contentView.addSubview(imageView) 22 | } 23 | 24 | override func layoutSubviews() { 25 | super.layoutSubviews() 26 | imageView.frame = contentView.bounds 27 | } 28 | 29 | required init?(coder aDecoder: NSCoder) { 30 | fatalError("init(coder:) has not been implemented") 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /Example/Example/DefaultPageIndicatorViewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // DefaultPageIndicatorViewController.swift 3 | // Example 4 | // 5 | // Created by JiongXing on 2019/12/16. 6 | // Copyright © 2019 JiongXing. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | import JXPhotoBrowser 11 | import SDWebImage 12 | 13 | class DefaultPageIndicatorViewController: BaseCollectionViewController { 14 | 15 | override class func name() -> String { "UIPageControl样式的页码指示器" } 16 | override class func remark() -> String { "举例如何使用UIPageControl样式的页码指示器" } 17 | 18 | override func makeDataSource() -> [ResourceModel] { 19 | makeNetworkDataSource() 20 | } 21 | 22 | override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { 23 | let cell = collectionView.jx.dequeueReusableCell(BaseCollectionViewCell.self, for: indexPath) 24 | if let firstLevel = self.dataSource[indexPath.item].firstLevelUrl { 25 | let url = URL(string: firstLevel) 26 | cell.imageView.sd_setImage(with: url, completed: nil) 27 | } 28 | return cell 29 | } 30 | 31 | override func openPhotoBrowser(with collectionView: UICollectionView, indexPath: IndexPath) { 32 | let browser = JXPhotoBrowser() 33 | browser.numberOfItems = { 34 | self.dataSource.count 35 | } 36 | browser.reloadCellAtIndex = { context in 37 | let url = self.dataSource[context.index].secondLevelUrl.flatMap { URL(string: $0) } 38 | let browserCell = context.cell as? JXPhotoBrowserImageCell 39 | browserCell?.index = context.index 40 | let collectionPath = IndexPath(item: context.index, section: indexPath.section) 41 | let collectionCell = collectionView.cellForItem(at: collectionPath) as? BaseCollectionViewCell 42 | let placeholder = collectionCell?.imageView.image 43 | browserCell?.imageView.sd_setImage(with: url, placeholderImage: placeholder, options: [], completed: { (_, _, _, _) in 44 | browserCell?.setNeedsLayout() 45 | }) 46 | } 47 | browser.transitionAnimator = JXPhotoBrowserZoomAnimator(previousView: { index -> UIView? in 48 | let path = IndexPath(item: index, section: indexPath.section) 49 | let cell = collectionView.cellForItem(at: path) as? BaseCollectionViewCell 50 | return cell?.imageView 51 | }) 52 | // UIPageIndicator样式的页码指示器 53 | browser.pageIndicator = JXPhotoBrowserDefaultPageIndicator() 54 | browser.pageIndex = indexPath.item 55 | browser.show() 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /Example/Example/ImageSmoothZoomViewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // LocalImageSmoothZoomViewController.swift 3 | // Example 4 | // 5 | // Created by JiongXing on 2019/11/28. 6 | // Copyright © 2019 JiongXing. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | import JXPhotoBrowser 11 | 12 | class ImageSmoothZoomViewController: BaseCollectionViewController { 13 | 14 | override class func name() -> String { "更丝滑的Zoom转场动画" } 15 | override class func remark() -> String { "需要用户自己创建并提供转场视图,以及缩略图位置" } 16 | 17 | override func makeDataSource() -> [ResourceModel] { 18 | makeLocalDataSource() 19 | } 20 | 21 | override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { 22 | let cell = collectionView.jx.dequeueReusableCell(BaseCollectionViewCell.self, for: indexPath) 23 | cell.imageView.image = self.dataSource[indexPath.item].localName.flatMap { UIImage(named: $0) } 24 | // 等比拉伸,填满视图 25 | cell.imageView.contentMode = .scaleAspectFill 26 | return cell 27 | } 28 | 29 | override func openPhotoBrowser(with collectionView: UICollectionView, indexPath: IndexPath) { 30 | let browser = JXPhotoBrowser() 31 | browser.numberOfItems = { 32 | self.dataSource.count 33 | } 34 | browser.reloadCellAtIndex = { context in 35 | let browserCell = context.cell as? JXPhotoBrowserImageCell 36 | let indexPath = IndexPath(item: context.index, section: indexPath.section) 37 | browserCell?.imageView.image = self.dataSource[indexPath.item].localName.flatMap { UIImage(named: $0) } 38 | } 39 | // 更丝滑的Zoom动画 40 | browser.transitionAnimator = JXPhotoBrowserSmoothZoomAnimator(transitionViewAndFrame: { (index, destinationView) -> JXPhotoBrowserSmoothZoomAnimator.TransitionViewAndFrame? in 41 | let path = IndexPath(item: index, section: indexPath.section) 42 | guard let cell = collectionView.cellForItem(at: path) as? BaseCollectionViewCell else { 43 | return nil 44 | } 45 | let image = cell.imageView.image 46 | let transitionView = UIImageView(image: image) 47 | transitionView.contentMode = cell.imageView.contentMode 48 | transitionView.clipsToBounds = true 49 | let thumbnailFrame = cell.imageView.convert(cell.imageView.bounds, to: destinationView) 50 | return (transitionView, thumbnailFrame) 51 | }) 52 | browser.pageIndex = indexPath.item 53 | browser.show(method: .push(inNC: nil)) 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /Example/Example/ImageZoomViewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ImageZoomViewController.swift 3 | // Example 4 | // 5 | // Created by JiongXing on 2019/11/28. 6 | // Copyright © 2019 JiongXing. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | import JXPhotoBrowser 11 | 12 | class ImageZoomViewController: BaseCollectionViewController { 13 | 14 | override class func name() -> String { "Zoom转场动画" } 15 | override class func remark() -> String { "简单易用的缩放式转场动画,兼容缩略图与放大图存在差异"} 16 | 17 | override func makeDataSource() -> [ResourceModel] { 18 | makeLocalDataSource() 19 | } 20 | 21 | override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { 22 | let cell = collectionView.jx.dequeueReusableCell(BaseCollectionViewCell.self, for: indexPath) 23 | cell.imageView.image = self.dataSource[indexPath.item].localName.flatMap { UIImage(named: $0) } 24 | return cell 25 | } 26 | 27 | override func openPhotoBrowser(with collectionView: UICollectionView, indexPath: IndexPath) { 28 | let browser = JXPhotoBrowser() 29 | browser.numberOfItems = { 30 | self.dataSource.count 31 | } 32 | browser.reloadCellAtIndex = { context in 33 | let browserCell = context.cell as? JXPhotoBrowserImageCell 34 | let indexPath = IndexPath(item: context.index, section: indexPath.section) 35 | browserCell?.imageView.image = self.dataSource[indexPath.item].localName.flatMap { UIImage(named: $0) } 36 | } 37 | // 使用Zoom动画 38 | browser.transitionAnimator = JXPhotoBrowserZoomAnimator(previousView: { index -> UIView? in 39 | let path = IndexPath(item: index, section: indexPath.section) 40 | let cell = collectionView.cellForItem(at: path) as? BaseCollectionViewCell 41 | return cell?.imageView 42 | }) 43 | browser.pageIndex = indexPath.item 44 | browser.show() 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /Example/Example/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | $(DEVELOPMENT_LANGUAGE) 7 | CFBundleDisplayName 8 | PhotoBrowser 9 | CFBundleExecutable 10 | $(EXECUTABLE_NAME) 11 | CFBundleIdentifier 12 | $(PRODUCT_BUNDLE_IDENTIFIER) 13 | CFBundleInfoDictionaryVersion 14 | 6.0 15 | CFBundleName 16 | $(PRODUCT_NAME) 17 | CFBundlePackageType 18 | $(PRODUCT_BUNDLE_PACKAGE_TYPE) 19 | CFBundleShortVersionString 20 | 1.0 21 | CFBundleVersion 22 | 1 23 | LSRequiresIPhoneOS 24 | 25 | NSAppTransportSecurity 26 | 27 | NSAllowsArbitraryLoads 28 | 29 | 30 | UIApplicationSceneManifest 31 | 32 | UIApplicationSupportsMultipleScenes 33 | 34 | UISceneConfigurations 35 | 36 | UIWindowSceneSessionRoleApplication 37 | 38 | 39 | UISceneConfigurationName 40 | Default Configuration 41 | UISceneDelegateClassName 42 | $(PRODUCT_MODULE_NAME).SceneDelegate 43 | UISceneStoryboardFile 44 | Main 45 | 46 | 47 | 48 | 49 | UILaunchStoryboardName 50 | LaunchScreen 51 | UIMainStoryboardFile 52 | Main 53 | UIRequiredDeviceCapabilities 54 | 55 | armv7 56 | 57 | UISupportedInterfaceOrientations 58 | 59 | UIInterfaceOrientationPortrait 60 | UIInterfaceOrientationLandscapeLeft 61 | UIInterfaceOrientationLandscapeRight 62 | 63 | UISupportedInterfaceOrientations~ipad 64 | 65 | UIInterfaceOrientationPortrait 66 | UIInterfaceOrientationPortraitUpsideDown 67 | UIInterfaceOrientationLandscapeLeft 68 | UIInterfaceOrientationLandscapeRight 69 | 70 | 71 | 72 | -------------------------------------------------------------------------------- /Example/Example/JXNamespace.swift: -------------------------------------------------------------------------------- 1 | // 2 | // JXNamespace.swift 3 | // JXPhotoBrowser 4 | // 5 | // Created by JiongXing on 2018/10/14. 6 | // 7 | 8 | import Foundation 9 | 10 | /// 类型协议 11 | public protocol JXTypeWrapperProtocol { 12 | associatedtype JXWrappedType 13 | var jxWrappedValue: JXWrappedType { get } 14 | init(value: JXWrappedType) 15 | } 16 | 17 | public struct JXNamespaceWrapper: JXTypeWrapperProtocol { 18 | public let jxWrappedValue: T 19 | public init(value: T) { 20 | self.jxWrappedValue = value 21 | } 22 | } 23 | 24 | /// 命名空间协议 25 | public protocol JXNamespaceWrappable { 26 | associatedtype JXWrappedType 27 | var jx: JXWrappedType { get } 28 | static var jx: JXWrappedType.Type { get } 29 | } 30 | 31 | extension JXNamespaceWrappable { 32 | public var jx: JXNamespaceWrapper { 33 | return JXNamespaceWrapper(value: self) 34 | } 35 | 36 | public static var jx: JXNamespaceWrapper.Type { 37 | return JXNamespaceWrapper.self 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /Example/Example/KingfisherImageViewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // KingfisherImageViewController.swift 3 | // Example 4 | // 5 | // Created by JiongXing on 2019/11/28. 6 | // Copyright © 2019 JiongXing. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | import JXPhotoBrowser 11 | import Kingfisher 12 | 13 | class KingfisherImageViewController: BaseCollectionViewController { 14 | 15 | override class func name() -> String { "网络图片-Kingfisher" } 16 | override class func remark() -> String { "举例如何用Kingfisher加载网络图片" } 17 | 18 | override func makeDataSource() -> [ResourceModel] { 19 | makeNetworkDataSource() 20 | } 21 | 22 | override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { 23 | let cell = collectionView.jx.dequeueReusableCell(BaseCollectionViewCell.self, for: indexPath) 24 | if let firstLevel = self.dataSource[indexPath.item].firstLevelUrl { 25 | let url = URL(string: firstLevel) 26 | cell.imageView.kf.setImage(with: url) 27 | } 28 | return cell 29 | } 30 | 31 | override func openPhotoBrowser(with collectionView: UICollectionView, indexPath: IndexPath) { 32 | let browser = JXPhotoBrowser() 33 | browser.numberOfItems = { 34 | self.dataSource.count 35 | } 36 | browser.reloadCellAtIndex = { context in 37 | let url = self.dataSource[context.index].secondLevelUrl.flatMap { URL(string: $0) } 38 | let browserCell = context.cell as? JXPhotoBrowserImageCell 39 | let collectionPath = IndexPath(item: context.index, section: indexPath.section) 40 | let collectionCell = collectionView.cellForItem(at: collectionPath) as? BaseCollectionViewCell 41 | let placeholder = collectionCell?.imageView.image 42 | // 用 Kingfisher 加载 43 | browserCell?.imageView.kf.setImage(with: url, placeholder: placeholder) 44 | } 45 | browser.transitionAnimator = JXPhotoBrowserZoomAnimator(previousView: { index -> UIView? in 46 | let path = IndexPath(item: index, section: indexPath.section) 47 | let cell = collectionView.cellForItem(at: path) as? BaseCollectionViewCell 48 | return cell?.imageView 49 | }) 50 | browser.pageIndex = indexPath.item 51 | browser.show() 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /Example/Example/LocalImageViewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // LocalImageViewController.swift 3 | // JXPhotoBrwoser_Example 4 | // 5 | // Created by JiongXing on 2018/10/14. 6 | // Copyright © 2018年 CocoaPods. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | import JXPhotoBrowser 11 | 12 | class LocalImageViewController: BaseCollectionViewController { 13 | 14 | override class func name() -> String { "本地图片" } 15 | override class func remark() -> String { "最简单的场景,展示本地图片" } 16 | 17 | override func makeDataSource() -> [ResourceModel] { 18 | makeLocalDataSource() 19 | } 20 | 21 | override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { 22 | let cell = collectionView.jx.dequeueReusableCell(BaseCollectionViewCell.self, for: indexPath) 23 | cell.imageView.image = self.dataSource[indexPath.item].localName.flatMap { UIImage(named: $0) } 24 | return cell 25 | } 26 | 27 | override func openPhotoBrowser(with collectionView: UICollectionView, indexPath: IndexPath) { 28 | // 实例化 29 | let browser = JXPhotoBrowser() 30 | // 浏览过程中实时获取数据总量 31 | browser.numberOfItems = { 32 | self.dataSource.count 33 | } 34 | // 刷新Cell数据。本闭包将在Cell完成位置布局后调用。 35 | browser.reloadCellAtIndex = { context in 36 | let browserCell = context.cell as? JXPhotoBrowserImageCell 37 | let indexPath = IndexPath(item: context.index, section: indexPath.section) 38 | browserCell?.imageView.image = self.dataSource[indexPath.item].localName.flatMap { UIImage(named: $0) } 39 | } 40 | // 可指定打开时定位到哪一页 41 | browser.pageIndex = indexPath.item 42 | // 展示 43 | browser.show() 44 | 45 | // dismis回调 46 | browser.willDismiss = { _ in 47 | JXPhotoBrowserLog.low("即将dismiss!") 48 | return true 49 | } 50 | browser.didDismiss = { _ in 51 | JXPhotoBrowserLog.low("已经dismiss!") 52 | } 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /Example/Example/MoreDetailViewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // MoreDetailViewController.swift 3 | // Example 4 | // 5 | // Created by JiongXing on 2019/11/26. 6 | // Copyright © 2019 JiongXing. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | class MoreDetailViewController: UIViewController { 12 | 13 | lazy var label: UILabel = { 14 | let lab = UILabel() 15 | lab.textColor = .black 16 | lab.text = "< 更多详情 >" 17 | lab.textAlignment = .center 18 | return lab 19 | }() 20 | 21 | override func viewDidLoad() { 22 | super.viewDidLoad() 23 | view.backgroundColor = .white 24 | 25 | view.addSubview(label) 26 | } 27 | 28 | override func viewWillLayoutSubviews() { 29 | super.viewWillLayoutSubviews() 30 | label.frame = view.bounds 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /Example/Example/NumberPageIndicatorViewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // NumberPageIndicatorViewController.swift 3 | // Example 4 | // 5 | // Created by JiongXing on 2019/12/16. 6 | // Copyright © 2019 JiongXing. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | import JXPhotoBrowser 11 | import SDWebImage 12 | 13 | class NumberPageIndicatorViewController: BaseCollectionViewController { 14 | 15 | override class func name() -> String { "数字样式的页码指示器" } 16 | override class func remark() -> String { "举例如何使用数字样式的页码指示器" } 17 | 18 | override func makeDataSource() -> [ResourceModel] { 19 | makeNetworkDataSource() 20 | } 21 | 22 | override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { 23 | let cell = collectionView.jx.dequeueReusableCell(BaseCollectionViewCell.self, for: indexPath) 24 | if let firstLevel = self.dataSource[indexPath.item].firstLevelUrl { 25 | let url = URL(string: firstLevel) 26 | cell.imageView.sd_setImage(with: url, completed: nil) 27 | } 28 | return cell 29 | } 30 | 31 | override func openPhotoBrowser(with collectionView: UICollectionView, indexPath: IndexPath) { 32 | let browser = JXPhotoBrowser() 33 | browser.numberOfItems = { 34 | self.dataSource.count 35 | } 36 | browser.reloadCellAtIndex = { context in 37 | let url = self.dataSource[context.index].secondLevelUrl.flatMap { URL(string: $0) } 38 | let browserCell = context.cell as? JXPhotoBrowserImageCell 39 | browserCell?.index = context.index 40 | let collectionPath = IndexPath(item: context.index, section: indexPath.section) 41 | let collectionCell = collectionView.cellForItem(at: collectionPath) as? BaseCollectionViewCell 42 | let placeholder = collectionCell?.imageView.image 43 | browserCell?.imageView.sd_setImage(with: url, placeholderImage: placeholder, options: [], completed: { (_, _, _, _) in 44 | browserCell?.setNeedsLayout() 45 | }) 46 | } 47 | browser.transitionAnimator = JXPhotoBrowserZoomAnimator(previousView: { index -> UIView? in 48 | let path = IndexPath(item: index, section: indexPath.section) 49 | let cell = collectionView.cellForItem(at: path) as? BaseCollectionViewCell 50 | return cell?.imageView 51 | }) 52 | // 数字样式的页码指示器 53 | browser.pageIndicator = JXPhotoBrowserNumberPageIndicator() 54 | browser.pageIndex = indexPath.item 55 | browser.show() 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /Example/Example/Photos.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | http://wx3.sinaimg.cn/thumbnail/bfc243a3gy1febm7nzbz7j20ib0iek5j.jpg 7 | http://wx3.sinaimg.cn/large/bfc243a3gy1febm7nzbz7j20ib0iek5j.jpg 8 | (1)凡所有相,皆是虚妄,若见诸相非相,即见如来. 9 | 10 | 11 | http://wx1.sinaimg.cn/thumbnail/bfc243a3gy1febm7orgqfj20i80ht15x.jpg 12 | http://wx1.sinaimg.cn/large/bfc243a3gy1febm7orgqfj20i80ht15x.jpg 13 | (2)身是菩提树,心如明镜台,时时勤擦拭,莫使惹尘埃.  14 | 15 | 16 | http://wx1.sinaimg.cn/thumbnail/bfc243a3gy1febm7n9eorj20i60hsann.jpg 17 | http://wx1.sinaimg.cn/large/bfc243a3gy1febm7n9eorj20i60hsann.jpg 18 | (3)菩提本无树,名镜亦非台,本来无一物,何处惹尘埃. 19 | 20 | 21 | http://wx2.sinaimg.cn/thumbnail/bfc243a3gy1febm7pmnk7j20i70jidwo.jpg 22 | http://wx2.sinaimg.cn/large/bfc243a3gy1febm7pmnk7j20i70jidwo.jpg 23 | (4)一切有为法,如梦幻泡影。如露亦如电,应作如是观. 24 | 25 | 26 | http://wx3.sinaimg.cn/thumbnail/bfc243a3gy1febm7qjop4j20i00hw4c6.jpg 27 | http://wx3.sinaimg.cn/large/bfc243a3gy1febm7qjop4j20i00hw4c6.jpg 28 | (5)色不异空,空不异色,色即是空,空即是色. 29 | 30 | 31 | http://wx4.sinaimg.cn/thumbnail/bfc243a3gy1febm7rncxaj20ek0i74dv.jpg 32 | http://wx4.sinaimg.cn/large/bfc243a3gy1febm7rncxaj20ek0i74dv.jpg 33 | (6)一切有为法,如梦幻泡影。如露亦如电,应作如是观. 34 | 35 | 36 | http://wx2.sinaimg.cn/thumbnail/bfc243a3gy1febm7sdk4lj20ib0i714u.jpg 37 | http://wx2.sinaimg.cn/large/bfc243a3gy1febm7sdk4lj20ib0i714u.jpg 38 | (7)烦恼即菩提. 39 | 40 | 41 | http://wx4.sinaimg.cn/thumbnail/bfc243a3gy1febm7tekewj20i20i4aoy.jpg 42 | http://wx4.sinaimg.cn/large/bfc243a3gy1febm7tekewj20i20i4aoy.jpg 43 | (8)过去心不可得,现在心不可得,未来心不可得. 44 | 45 | 46 | http://wx3.sinaimg.cn/thumbnail/bfc243a3gy1febm7usmc8j20i543zngx.jpg 47 | http://wx3.sinaimg.cn/large/bfc243a3gy1febm7usmc8j20i543zngx.jpg 48 | (9)纵使经百劫,所作业不亡,因缘会遇时,果报还自受. 49 | 50 | 51 | 52 | -------------------------------------------------------------------------------- /Example/Example/ResourceModel.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ResourceModel.swift 3 | // JXPhotoBrowser 4 | // 5 | // Created by JiongXing on 2019/11/20. 6 | // Copyright © 2019 JiongXing. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | /// 视像资源模型 12 | class ResourceModel { 13 | /// 第一级资源 14 | var firstLevelUrl: String? 15 | /// 第二级资源 16 | var secondLevelUrl: String? 17 | /// 第三级资源 18 | var thirdLevelUrl: String? 19 | /// 本地资源,资源名 20 | var localName: String? 21 | /// 备注配文 22 | var remark: String? 23 | } 24 | -------------------------------------------------------------------------------- /Example/Example/SDWebImageViewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // SDWebImageViewController.swift 3 | // Example 4 | // 5 | // Created by JiongXing on 2019/11/28. 6 | // Copyright © 2019 JiongXing. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | import JXPhotoBrowser 11 | import SDWebImage 12 | 13 | class SDWebImageViewController: BaseCollectionViewController { 14 | 15 | override class func name() -> String { "网络图片-SDWebImage" } 16 | override class func remark() -> String { "举例如何用SDWebImage加载网络图片" } 17 | 18 | override func makeDataSource() -> [ResourceModel] { 19 | makeNetworkDataSource() 20 | } 21 | 22 | override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { 23 | let cell = collectionView.jx.dequeueReusableCell(BaseCollectionViewCell.self, for: indexPath) 24 | if let firstLevel = self.dataSource[indexPath.item].firstLevelUrl { 25 | let url = URL(string: firstLevel) 26 | cell.imageView.sd_setImage(with: url, completed: nil) 27 | } 28 | return cell 29 | } 30 | 31 | override func openPhotoBrowser(with collectionView: UICollectionView, indexPath: IndexPath) { 32 | let browser = JXPhotoBrowser() 33 | browser.numberOfItems = { 34 | self.dataSource.count 35 | } 36 | browser.reloadCellAtIndex = { context in 37 | let url = self.dataSource[context.index].secondLevelUrl.flatMap { URL(string: $0) } 38 | let browserCell = context.cell as? JXPhotoBrowserImageCell 39 | browserCell?.index = context.index 40 | let collectionPath = IndexPath(item: context.index, section: indexPath.section) 41 | let collectionCell = collectionView.cellForItem(at: collectionPath) as? BaseCollectionViewCell 42 | let placeholder = collectionCell?.imageView.image 43 | // 用 SDWebImage 加载 44 | browserCell?.imageView.sd_setImage(with: url, placeholderImage: placeholder) 45 | } 46 | browser.transitionAnimator = JXPhotoBrowserZoomAnimator(previousView: { index -> UIView? in 47 | let path = IndexPath(item: index, section: indexPath.section) 48 | let cell = collectionView.cellForItem(at: path) as? BaseCollectionViewCell 49 | return cell?.imageView 50 | }) 51 | browser.pageIndex = indexPath.item 52 | browser.show() 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /Example/Example/SceneDelegate.swift: -------------------------------------------------------------------------------- 1 | // 2 | // SceneDelegate.swift 3 | // Example 4 | // 5 | // Created by JiongXing on 2019/11/26. 6 | // Copyright © 2019 JiongXing. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | class SceneDelegate: UIResponder, UIWindowSceneDelegate { 12 | 13 | var window: UIWindow? 14 | 15 | 16 | func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) { 17 | // Use this method to optionally configure and attach the UIWindow `window` to the provided UIWindowScene `scene`. 18 | // If using a storyboard, the `window` property will automatically be initialized and attached to the scene. 19 | // This delegate does not imply the connecting scene or session are new (see `application:configurationForConnectingSceneSession` instead). 20 | guard let _ = (scene as? UIWindowScene) else { return } 21 | } 22 | 23 | func sceneDidDisconnect(_ scene: UIScene) { 24 | // Called as the scene is being released by the system. 25 | // This occurs shortly after the scene enters the background, or when its session is discarded. 26 | // Release any resources associated with this scene that can be re-created the next time the scene connects. 27 | // The scene may re-connect later, as its session was not neccessarily discarded (see `application:didDiscardSceneSessions` instead). 28 | } 29 | 30 | func sceneDidBecomeActive(_ scene: UIScene) { 31 | // Called when the scene has moved from an inactive state to an active state. 32 | // Use this method to restart any tasks that were paused (or not yet started) when the scene was inactive. 33 | } 34 | 35 | func sceneWillResignActive(_ scene: UIScene) { 36 | // Called when the scene will move from an active state to an inactive state. 37 | // This may occur due to temporary interruptions (ex. an incoming phone call). 38 | } 39 | 40 | func sceneWillEnterForeground(_ scene: UIScene) { 41 | // Called as the scene transitions from the background to the foreground. 42 | // Use this method to undo the changes made on entering the background. 43 | } 44 | 45 | func sceneDidEnterBackground(_ scene: UIScene) { 46 | // Called as the scene transitions from the foreground to the background. 47 | // Use this method to save data, release shared resources, and store enough scene-specific state information 48 | // to restore the scene back to its current state. 49 | } 50 | 51 | 52 | } 53 | 54 | -------------------------------------------------------------------------------- /Example/Example/UICollectionView+JX.swift: -------------------------------------------------------------------------------- 1 | // 2 | // UICollectionView+JX.swift 3 | // JXPhotoBrowser 4 | // 5 | // Created by JiongXing on 2018/10/14. 6 | // 7 | 8 | import UIKit 9 | 10 | extension UICollectionView: JXNamespaceWrappable {} 11 | 12 | extension JXTypeWrapperProtocol where JXWrappedType == UICollectionView { 13 | 14 | /// 注册Cell 15 | public func registerCell(_ type: T.Type) { 16 | let identifier = String(describing: type.self) 17 | jxWrappedValue.register(type, forCellWithReuseIdentifier: identifier) 18 | } 19 | 20 | /// 取重用Cell 21 | public func dequeueReusableCell(_ type: T.Type, for indexPath: IndexPath) -> T { 22 | let identifier = String(describing: type.self) 23 | guard let cell = jxWrappedValue.dequeueReusableCell(withReuseIdentifier: identifier, for: indexPath) as? T else { 24 | fatalError("\(type.self) was not registered") 25 | } 26 | return cell 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /Example/Example/UITableView+JX.swift: -------------------------------------------------------------------------------- 1 | // 2 | // UITableView+JX.swift 3 | // JXPhotoBrowser 4 | // 5 | // Created by JiongXing on 2019/11/20. 6 | // Copyright © 2019 JiongXing. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | extension UITableView: JXNamespaceWrappable {} 12 | 13 | extension JXTypeWrapperProtocol where JXWrappedType == UITableView { 14 | 15 | /// 注册Cell 16 | public func registerCell(_ type: T.Type) { 17 | let identifier = String(describing: type.self) 18 | jxWrappedValue.register(type, forCellReuseIdentifier: identifier) 19 | } 20 | 21 | /// 取重用Cell 22 | public func dequeueReusableCell(_ type: T.Type) -> T { 23 | let identifier = String(describing: type.self) 24 | guard let cell = jxWrappedValue.dequeueReusableCell(withIdentifier: identifier) as? T else { 25 | fatalError("\(type.self) was not registered") 26 | } 27 | return cell 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /Example/Example/VideoCell.swift: -------------------------------------------------------------------------------- 1 | // 2 | // VideoCell.swift 3 | // Example 4 | // 5 | // Created by JiongXing on 2019/12/13. 6 | // Copyright © 2019 JiongXing. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | import UIKit 11 | import AVFoundation 12 | import JXPhotoBrowser 13 | 14 | class VideoCell: UIView, JXPhotoBrowserCell { 15 | 16 | weak var photoBrowser: JXPhotoBrowser? 17 | 18 | lazy var player = AVPlayer() 19 | lazy var playerLayer = AVPlayerLayer(player: player) 20 | 21 | static func generate(with browser: JXPhotoBrowser) -> Self { 22 | let instance = Self.init(frame: .zero) 23 | instance.photoBrowser = browser 24 | return instance 25 | } 26 | 27 | required override init(frame: CGRect) { 28 | super.init(frame: .zero) 29 | backgroundColor = .black 30 | 31 | let tap = UITapGestureRecognizer(target: self, action: #selector(click)) 32 | addGestureRecognizer(tap) 33 | 34 | layer.addSublayer(playerLayer) 35 | } 36 | 37 | required init?(coder: NSCoder) { 38 | fatalError("init(coder:) has not been implemented") 39 | } 40 | 41 | override func layoutSubviews() { 42 | super.layoutSubviews() 43 | playerLayer.frame = bounds 44 | } 45 | 46 | @objc private func click() { 47 | photoBrowser?.dismiss() 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /Example/Example/video_0.MP4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JiongXing/PhotoBrowser/69c5212485b54eeb0eaaa5f77dde1ebb787a51d0/Example/Example/video_0.MP4 -------------------------------------------------------------------------------- /Example/Example/video_1.MP4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JiongXing/PhotoBrowser/69c5212485b54eeb0eaaa5f77dde1ebb787a51d0/Example/Example/video_1.MP4 -------------------------------------------------------------------------------- /Example/Example/video_2.MP4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JiongXing/PhotoBrowser/69c5212485b54eeb0eaaa5f77dde1ebb787a51d0/Example/Example/video_2.MP4 -------------------------------------------------------------------------------- /Example/Podfile: -------------------------------------------------------------------------------- 1 | 2 | platform :ios, '13.0' 3 | 4 | target 'Example' do 5 | # Comment the next line if you don't want to use dynamic frameworks 6 | use_frameworks! 7 | 8 | # Pods for Example 9 | pod 'JXPhotoBrowser', :path => '../' 10 | pod 'Kingfisher' 11 | pod 'SDWebImage' 12 | 13 | post_install do |installer| 14 | installer.pods_project.targets.each do |target| 15 | target.build_configurations.each do |config| 16 | config.build_settings['IPHONEOS_DEPLOYMENT_TARGET'] = '13.0' 17 | end 18 | end 19 | end 20 | 21 | end 22 | -------------------------------------------------------------------------------- /Example/Podfile.lock: -------------------------------------------------------------------------------- 1 | PODS: 2 | - JXPhotoBrowser (3.1.5) 3 | - Kingfisher (7.10.2) 4 | - SDWebImage (5.18.10): 5 | - SDWebImage/Core (= 5.18.10) 6 | - SDWebImage/Core (5.18.10) 7 | 8 | DEPENDENCIES: 9 | - JXPhotoBrowser (from `../`) 10 | - Kingfisher 11 | - SDWebImage 12 | 13 | SPEC REPOS: 14 | trunk: 15 | - Kingfisher 16 | - SDWebImage 17 | 18 | EXTERNAL SOURCES: 19 | JXPhotoBrowser: 20 | :path: "../" 21 | 22 | SPEC CHECKSUMS: 23 | JXPhotoBrowser: e0dad01805e85c317ac8844ce793f7935fa918ed 24 | Kingfisher: 99edc495d3b7607e6425f0d6f6847b2abd6d716d 25 | SDWebImage: fc8f2d48bbfd72ef39d70e981bd24a3f3be53fec 26 | 27 | PODFILE CHECKSUM: 92abaea6b2d28b30ee834a17b1a190e01247e20d 28 | 29 | COCOAPODS: 1.14.2 30 | -------------------------------------------------------------------------------- /Example/Pods/Kingfisher/LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2019 Wei Wang 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | -------------------------------------------------------------------------------- /Example/Pods/Kingfisher/Sources/PrivacyInfo.xcprivacy: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | NSPrivacyAccessedAPITypes 6 | 7 | 8 | NSPrivacyAccessedAPIType 9 | NSPrivacyAccessedAPICategoryFileTimestamp 10 | NSPrivacyAccessedAPITypeReasons 11 | 12 | C617.1 13 | 14 | 15 | 16 | NSPrivacyTracking 17 | 18 | NSPrivacyTrackingDomains 19 | 20 | 21 | NSPrivacyCollectedDataTypes 22 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /Example/Pods/Kingfisher/Sources/Utility/Box.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Box.swift 3 | // Kingfisher 4 | // 5 | // Created by Wei Wang on 2018/3/17. 6 | // Copyright (c) 2019 Wei Wang 7 | // 8 | // Permission is hereby granted, free of charge, to any person obtaining a copy 9 | // of this software and associated documentation files (the "Software"), to deal 10 | // in the Software without restriction, including without limitation the rights 11 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | // copies of the Software, and to permit persons to whom the Software is 13 | // furnished to do so, subject to the following conditions: 14 | // 15 | // The above copyright notice and this permission notice shall be included in 16 | // all copies or substantial portions of the Software. 17 | // 18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 24 | // THE SOFTWARE. 25 | 26 | import Foundation 27 | 28 | class Box { 29 | var value: T 30 | 31 | init(_ value: T) { 32 | self.value = value 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /Example/Pods/Kingfisher/Sources/Utility/Result.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Result.swift 3 | // Kingfisher 4 | // 5 | // Created by onevcat on 2018/09/22. 6 | // 7 | // Copyright (c) 2019 Wei Wang 8 | // 9 | // Permission is hereby granted, free of charge, to any person obtaining a copy 10 | // of this software and associated documentation files (the "Software"), to deal 11 | // in the Software without restriction, including without limitation the rights 12 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 13 | // copies of the Software, and to permit persons to whom the Software is 14 | // furnished to do so, subject to the following conditions: 15 | // 16 | // The above copyright notice and this permission notice shall be included in 17 | // all copies or substantial portions of the Software. 18 | // 19 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 20 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 21 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 22 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 23 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 24 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 25 | // THE SOFTWARE. 26 | 27 | import Foundation 28 | 29 | // These helper methods are not public since we do not want them to be exposed or cause any conflicting. 30 | // However, they are just wrapper of `ResultUtil` static methods. 31 | extension Result where Failure: Error { 32 | 33 | /// Evaluates the given transform closures to create a single output value. 34 | /// 35 | /// - Parameters: 36 | /// - onSuccess: A closure that transforms the success value. 37 | /// - onFailure: A closure that transforms the error value. 38 | /// - Returns: A single `Output` value. 39 | func match( 40 | onSuccess: (Success) -> Output, 41 | onFailure: (Failure) -> Output) -> Output 42 | { 43 | switch self { 44 | case let .success(value): 45 | return onSuccess(value) 46 | case let .failure(error): 47 | return onFailure(error) 48 | } 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /Example/Pods/Kingfisher/Sources/Utility/Runtime.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Runtime.swift 3 | // Kingfisher 4 | // 5 | // Created by Wei Wang on 2018/10/12. 6 | // 7 | // Copyright (c) 2019 Wei Wang 8 | // 9 | // Permission is hereby granted, free of charge, to any person obtaining a copy 10 | // of this software and associated documentation files (the "Software"), to deal 11 | // in the Software without restriction, including without limitation the rights 12 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 13 | // copies of the Software, and to permit persons to whom the Software is 14 | // furnished to do so, subject to the following conditions: 15 | // 16 | // The above copyright notice and this permission notice shall be included in 17 | // all copies or substantial portions of the Software. 18 | // 19 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 20 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 21 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 22 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 23 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 24 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 25 | // THE SOFTWARE. 26 | 27 | import Foundation 28 | 29 | func getAssociatedObject(_ object: Any, _ key: UnsafeRawPointer) -> T? { 30 | if #available(iOS 14, macOS 11, watchOS 7, tvOS 14, *) { // swift 5.3 fixed this issue (https://github.com/apple/swift/issues/46456) 31 | return objc_getAssociatedObject(object, key) as? T 32 | } else { 33 | return objc_getAssociatedObject(object, key) as AnyObject as? T 34 | } 35 | } 36 | 37 | func setRetainedAssociatedObject(_ object: Any, _ key: UnsafeRawPointer, _ value: T) { 38 | objc_setAssociatedObject(object, key, value, .OBJC_ASSOCIATION_RETAIN_NONATOMIC) 39 | } 40 | -------------------------------------------------------------------------------- /Example/Pods/Local Podspecs/JXPhotoBrowser.podspec.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "JXPhotoBrowser", 3 | "version": "3.1.5", 4 | "summary": "Elegant photo browser in Swift.", 5 | "description": "Elegant photo browser in Swift. Inspired by WeChat.", 6 | "homepage": "https://github.com/JiongXing/PhotoBrowser", 7 | "license": { 8 | "type": "MIT", 9 | "file": "LICENSE" 10 | }, 11 | "authors": { 12 | "JiongXing": "liangjiongxing@qq.com" 13 | }, 14 | "source": { 15 | "git": "https://github.com/JiongXing/PhotoBrowser.git", 16 | "tag": "3.1.5" 17 | }, 18 | "platforms": { 19 | "ios": "11.0" 20 | }, 21 | "source_files": "Sources/JXPhotoBrowser/*" 22 | } 23 | -------------------------------------------------------------------------------- /Example/Pods/Manifest.lock: -------------------------------------------------------------------------------- 1 | PODS: 2 | - JXPhotoBrowser (3.1.5) 3 | - Kingfisher (7.10.2) 4 | - SDWebImage (5.18.10): 5 | - SDWebImage/Core (= 5.18.10) 6 | - SDWebImage/Core (5.18.10) 7 | 8 | DEPENDENCIES: 9 | - JXPhotoBrowser (from `../`) 10 | - Kingfisher 11 | - SDWebImage 12 | 13 | SPEC REPOS: 14 | trunk: 15 | - Kingfisher 16 | - SDWebImage 17 | 18 | EXTERNAL SOURCES: 19 | JXPhotoBrowser: 20 | :path: "../" 21 | 22 | SPEC CHECKSUMS: 23 | JXPhotoBrowser: e0dad01805e85c317ac8844ce793f7935fa918ed 24 | Kingfisher: 99edc495d3b7607e6425f0d6f6847b2abd6d716d 25 | SDWebImage: fc8f2d48bbfd72ef39d70e981bd24a3f3be53fec 26 | 27 | PODFILE CHECKSUM: 92abaea6b2d28b30ee834a17b1a190e01247e20d 28 | 29 | COCOAPODS: 1.14.2 30 | -------------------------------------------------------------------------------- /Example/Pods/SDWebImage/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2009-2020 Olivier Poitrey rs@dailymotion.com 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 furnished 8 | to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in all 11 | 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 | 21 | -------------------------------------------------------------------------------- /Example/Pods/SDWebImage/SDWebImage/Core/NSData+ImageContentType.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the SDWebImage package. 3 | * (c) Olivier Poitrey 4 | * (c) Fabrice Aneche 5 | * 6 | * For the full copyright and license information, please view the LICENSE 7 | * file that was distributed with this source code. 8 | */ 9 | 10 | #import 11 | #import "SDWebImageCompat.h" 12 | 13 | /** 14 | You can use switch case like normal enum. It's also recommended to add a default case. You should not assume anything about the raw value. 15 | For custom coder plugin, it can also extern the enum for supported format. See `SDImageCoder` for more detailed information. 16 | */ 17 | typedef NSInteger SDImageFormat NS_TYPED_EXTENSIBLE_ENUM; 18 | static const SDImageFormat SDImageFormatUndefined = -1; 19 | static const SDImageFormat SDImageFormatJPEG = 0; 20 | static const SDImageFormat SDImageFormatPNG = 1; 21 | static const SDImageFormat SDImageFormatGIF = 2; 22 | static const SDImageFormat SDImageFormatTIFF = 3; 23 | static const SDImageFormat SDImageFormatWebP = 4; 24 | static const SDImageFormat SDImageFormatHEIC = 5; 25 | static const SDImageFormat SDImageFormatHEIF = 6; 26 | static const SDImageFormat SDImageFormatPDF = 7; 27 | static const SDImageFormat SDImageFormatSVG = 8; 28 | static const SDImageFormat SDImageFormatBMP = 9; 29 | static const SDImageFormat SDImageFormatRAW = 10; 30 | 31 | /** 32 | NSData category about the image content type and UTI. 33 | */ 34 | @interface NSData (ImageContentType) 35 | 36 | /** 37 | * Return image format 38 | * 39 | * @param data the input image data 40 | * 41 | * @return the image format as `SDImageFormat` (enum) 42 | */ 43 | + (SDImageFormat)sd_imageFormatForImageData:(nullable NSData *)data; 44 | 45 | /** 46 | * Convert SDImageFormat to UTType 47 | * 48 | * @param format Format as SDImageFormat 49 | * @return The UTType as CFStringRef 50 | * @note For unknown format, `kSDUTTypeImage` abstract type will return 51 | */ 52 | + (nonnull CFStringRef)sd_UTTypeFromImageFormat:(SDImageFormat)format CF_RETURNS_NOT_RETAINED NS_SWIFT_NAME(sd_UTType(from:)); 53 | 54 | /** 55 | * Convert UTType to SDImageFormat 56 | * 57 | * @param uttype The UTType as CFStringRef 58 | * @return The Format as SDImageFormat 59 | * @note For unknown type, `SDImageFormatUndefined` will return 60 | */ 61 | + (SDImageFormat)sd_imageFormatFromUTType:(nonnull CFStringRef)uttype; 62 | 63 | @end 64 | -------------------------------------------------------------------------------- /Example/Pods/SDWebImage/SDWebImage/Core/SDAnimatedImageRep.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 "SDWebImageCompat.h" 10 | 11 | #if SD_MAC 12 | 13 | #import "NSData+ImageContentType.h" 14 | 15 | /** 16 | A subclass of `NSBitmapImageRep` to fix that GIF duration issue because `NSBitmapImageRep` will reset `NSImageCurrentFrameDuration` by using `kCGImagePropertyGIFDelayTime` but not `kCGImagePropertyGIFUnclampedDelayTime`. 17 | This also fix the GIF loop count issue, which will use the Netscape standard (See http://www6.uniovi.es/gifanim/gifabout.htm) to only place once when the `kCGImagePropertyGIFLoopCount` is nil. This is what modern browser's behavior. 18 | Built in GIF coder use this instead of `NSBitmapImageRep` for better GIF rendering. If you do not want this, only enable `SDImageIOCoder`, which just call `NSImage` API and actually use `NSBitmapImageRep` for GIF image. 19 | This also support APNG format using `SDImageAPNGCoder`. Which provide full alpha-channel support and the correct duration match the `kCGImagePropertyAPNGUnclampedDelayTime`. 20 | */ 21 | @interface SDAnimatedImageRep : NSBitmapImageRep 22 | 23 | /// Current animated image format. 24 | /// @note This format is only valid when `animatedImageData` not nil 25 | @property (nonatomic, assign, readonly) SDImageFormat animatedImageFormat; 26 | 27 | /// This allows to retrive the compressed data like GIF using `sd_imageData` on parent `NSImage`, without re-encoding (waste CPU and RAM) 28 | /// @note This is typically nonnull when you create with `initWithData:`, even it's marked as weak, because ImageIO retain it 29 | @property (nonatomic, readonly, nullable, weak) NSData *animatedImageData; 30 | 31 | @end 32 | 33 | #endif 34 | -------------------------------------------------------------------------------- /Example/Pods/SDWebImage/SDWebImage/Core/SDImageAPNGCoder.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 | #import "SDImageIOAnimatedCoder.h" 11 | 12 | /** 13 | Built in coder using ImageIO that supports APNG encoding/decoding 14 | */ 15 | @interface SDImageAPNGCoder : SDImageIOAnimatedCoder 16 | 17 | @property (nonatomic, class, readonly, nonnull) SDImageAPNGCoder *sharedCoder; 18 | 19 | @end 20 | -------------------------------------------------------------------------------- /Example/Pods/SDWebImage/SDWebImage/Core/SDImageAPNGCoder.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 "SDImageAPNGCoder.h" 10 | #import "SDImageIOAnimatedCoderInternal.h" 11 | #if SD_MAC 12 | #import 13 | #else 14 | #import 15 | #endif 16 | 17 | @implementation SDImageAPNGCoder 18 | 19 | + (instancetype)sharedCoder { 20 | static SDImageAPNGCoder *coder; 21 | static dispatch_once_t onceToken; 22 | dispatch_once(&onceToken, ^{ 23 | coder = [[SDImageAPNGCoder alloc] init]; 24 | }); 25 | return coder; 26 | } 27 | 28 | #pragma mark - Subclass Override 29 | 30 | + (SDImageFormat)imageFormat { 31 | return SDImageFormatPNG; 32 | } 33 | 34 | + (NSString *)imageUTType { 35 | return (__bridge NSString *)kSDUTTypePNG; 36 | } 37 | 38 | + (NSString *)dictionaryProperty { 39 | return (__bridge NSString *)kCGImagePropertyPNGDictionary; 40 | } 41 | 42 | + (NSString *)unclampedDelayTimeProperty { 43 | return (__bridge NSString *)kCGImagePropertyAPNGUnclampedDelayTime; 44 | } 45 | 46 | + (NSString *)delayTimeProperty { 47 | return (__bridge NSString *)kCGImagePropertyAPNGDelayTime; 48 | } 49 | 50 | + (NSString *)loopCountProperty { 51 | return (__bridge NSString *)kCGImagePropertyAPNGLoopCount; 52 | } 53 | 54 | + (NSUInteger)defaultLoopCount { 55 | return 0; 56 | } 57 | 58 | @end 59 | -------------------------------------------------------------------------------- /Example/Pods/SDWebImage/SDWebImage/Core/SDImageAWebPCoder.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 | #import "SDImageIOAnimatedCoder.h" 11 | 12 | /** 13 | This coder is used for Google WebP and Animated WebP(AWebP) image format. 14 | Image/IO provide the WebP decoding support in iOS 14/macOS 11/tvOS 14/watchOS 7+. 15 | @note Currently Image/IO seems does not supports WebP encoding, if you need WebP encoding, use the custom codec below. 16 | @note If you need to support lower firmware version for WebP, you can have a try at https://github.com/SDWebImage/SDWebImageWebPCoder 17 | */ 18 | API_AVAILABLE(ios(14.0), tvos(14.0), macos(11.0), watchos(7.0)) 19 | @interface SDImageAWebPCoder : SDImageIOAnimatedCoder 20 | 21 | @property (nonatomic, class, readonly, nonnull) SDImageAWebPCoder *sharedCoder; 22 | 23 | @end 24 | -------------------------------------------------------------------------------- /Example/Pods/SDWebImage/SDWebImage/Core/SDImageCoder.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 "SDImageCoder.h" 10 | 11 | SDImageCoderOption const SDImageCoderDecodeFirstFrameOnly = @"decodeFirstFrameOnly"; 12 | SDImageCoderOption const SDImageCoderDecodeScaleFactor = @"decodeScaleFactor"; 13 | SDImageCoderOption const SDImageCoderDecodePreserveAspectRatio = @"decodePreserveAspectRatio"; 14 | SDImageCoderOption const SDImageCoderDecodeThumbnailPixelSize = @"decodeThumbnailPixelSize"; 15 | SDImageCoderOption const SDImageCoderDecodeFileExtensionHint = @"decodeFileExtensionHint"; 16 | SDImageCoderOption const SDImageCoderDecodeTypeIdentifierHint = @"decodeTypeIdentifierHint"; 17 | SDImageCoderOption const SDImageCoderDecodeUseLazyDecoding = @"decodeUseLazyDecoding"; 18 | SDImageCoderOption const SDImageCoderDecodeScaleDownLimitBytes = @"decodeScaleDownLimitBytes"; 19 | 20 | SDImageCoderOption const SDImageCoderEncodeFirstFrameOnly = @"encodeFirstFrameOnly"; 21 | SDImageCoderOption const SDImageCoderEncodeCompressionQuality = @"encodeCompressionQuality"; 22 | SDImageCoderOption const SDImageCoderEncodeBackgroundColor = @"encodeBackgroundColor"; 23 | SDImageCoderOption const SDImageCoderEncodeMaxPixelSize = @"encodeMaxPixelSize"; 24 | SDImageCoderOption const SDImageCoderEncodeMaxFileSize = @"encodeMaxFileSize"; 25 | SDImageCoderOption const SDImageCoderEncodeEmbedThumbnail = @"encodeEmbedThumbnail"; 26 | 27 | SDImageCoderOption const SDImageCoderWebImageContext = @"webImageContext"; 28 | -------------------------------------------------------------------------------- /Example/Pods/SDWebImage/SDWebImage/Core/SDImageCodersManager.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 | #import "SDImageCoder.h" 11 | 12 | /** 13 | Global object holding the array of coders, so that we avoid passing them from object to object. 14 | Uses a priority queue behind scenes, which means the latest added coders have the highest priority. 15 | This is done so when encoding/decoding something, we go through the list and ask each coder if they can handle the current data. 16 | That way, users can add their custom coders while preserving our existing prebuilt ones 17 | 18 | Note: the `coders` getter will return the coders in their reversed order 19 | Example: 20 | - by default we internally set coders = `IOCoder`, `GIFCoder`, `APNGCoder` 21 | - calling `coders` will return `@[IOCoder, GIFCoder, APNGCoder]` 22 | - call `[addCoder:[MyCrazyCoder new]]` 23 | - calling `coders` now returns `@[IOCoder, GIFCoder, APNGCoder, MyCrazyCoder]` 24 | 25 | Coders 26 | ------ 27 | A coder must conform to the `SDImageCoder` protocol or even to `SDProgressiveImageCoder` if it supports progressive decoding 28 | Conformance is important because that way, they will implement `canDecodeFromData` or `canEncodeToFormat` 29 | Those methods are called on each coder in the array (using the priority order) until one of them returns YES. 30 | That means that coder can decode that data / encode to that format 31 | */ 32 | @interface SDImageCodersManager : NSObject 33 | 34 | /** 35 | Returns the global shared coders manager instance. 36 | */ 37 | @property (nonatomic, class, readonly, nonnull) SDImageCodersManager *sharedManager; 38 | 39 | /** 40 | All coders in coders manager. The coders array is a priority queue, which means the later added coder will have the highest priority 41 | */ 42 | @property (nonatomic, copy, nullable) NSArray> *coders; 43 | 44 | /** 45 | Add a new coder to the end of coders array. Which has the highest priority. 46 | 47 | @param coder coder 48 | */ 49 | - (void)addCoder:(nonnull id)coder; 50 | 51 | /** 52 | Remove a coder in the coders array. 53 | 54 | @param coder coder 55 | */ 56 | - (void)removeCoder:(nonnull id)coder; 57 | 58 | @end 59 | -------------------------------------------------------------------------------- /Example/Pods/SDWebImage/SDWebImage/Core/SDImageFrame.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 | #import "SDWebImageCompat.h" 11 | 12 | /** 13 | This class is used for creating animated images via `animatedImageWithFrames` in `SDImageCoderHelper`. 14 | @note If you need to specify animated images loop count, use `sd_imageLoopCount` property in `UIImage+Metadata.h`. 15 | */ 16 | @interface SDImageFrame : NSObject 17 | 18 | /** 19 | The image of current frame. You should not set an animated image. 20 | */ 21 | @property (nonatomic, strong, readonly, nonnull) UIImage *image; 22 | /** 23 | The duration of current frame to be displayed. The number is seconds but not milliseconds. You should not set this to zero. 24 | */ 25 | @property (nonatomic, readonly, assign) NSTimeInterval duration; 26 | 27 | /// Create a frame instance with specify image and duration 28 | /// @param image current frame's image 29 | /// @param duration current frame's duration 30 | - (nonnull instancetype)initWithImage:(nonnull UIImage *)image duration:(NSTimeInterval)duration; 31 | 32 | /** 33 | Create a frame instance with specify image and duration 34 | 35 | @param image current frame's image 36 | @param duration current frame's duration 37 | @return frame instance 38 | */ 39 | + (nonnull instancetype)frameWithImage:(nonnull UIImage *)image duration:(NSTimeInterval)duration; 40 | 41 | - (nonnull instancetype)init NS_UNAVAILABLE; 42 | + (nonnull instancetype)new NS_UNAVAILABLE; 43 | 44 | @end 45 | -------------------------------------------------------------------------------- /Example/Pods/SDWebImage/SDWebImage/Core/SDImageFrame.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 "SDImageFrame.h" 10 | 11 | @interface SDImageFrame () 12 | 13 | @property (nonatomic, strong, readwrite, nonnull) UIImage *image; 14 | @property (nonatomic, readwrite, assign) NSTimeInterval duration; 15 | 16 | @end 17 | 18 | @implementation SDImageFrame 19 | 20 | - (instancetype)initWithImage:(UIImage *)image duration:(NSTimeInterval)duration { 21 | self = [super init]; 22 | if (self) { 23 | _image = image; 24 | _duration = duration; 25 | } 26 | return self; 27 | } 28 | 29 | + (instancetype)frameWithImage:(UIImage *)image duration:(NSTimeInterval)duration { 30 | SDImageFrame *frame = [[SDImageFrame alloc] initWithImage:image duration:duration]; 31 | return frame; 32 | } 33 | 34 | @end 35 | -------------------------------------------------------------------------------- /Example/Pods/SDWebImage/SDWebImage/Core/SDImageGIFCoder.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 | #import "SDImageIOAnimatedCoder.h" 11 | 12 | /** 13 | Built in coder using ImageIO that supports animated GIF encoding/decoding 14 | @note `SDImageIOCoder` supports GIF but only as static (will use the 1st frame). 15 | @note Use `SDImageGIFCoder` for fully animated GIFs. For `UIImageView`, it will produce animated `UIImage`(`NSImage` on macOS) for rendering. For `SDAnimatedImageView`, it will use `SDAnimatedImage` for rendering. 16 | @note The recommended approach for animated GIFs is using `SDAnimatedImage` with `SDAnimatedImageView`. It's more performant than `UIImageView` for GIF displaying(especially on memory usage) 17 | */ 18 | @interface SDImageGIFCoder : SDImageIOAnimatedCoder 19 | 20 | @property (nonatomic, class, readonly, nonnull) SDImageGIFCoder *sharedCoder; 21 | 22 | @end 23 | -------------------------------------------------------------------------------- /Example/Pods/SDWebImage/SDWebImage/Core/SDImageGIFCoder.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 "SDImageGIFCoder.h" 10 | #import "SDImageIOAnimatedCoderInternal.h" 11 | #if SD_MAC 12 | #import 13 | #else 14 | #import 15 | #endif 16 | 17 | @implementation SDImageGIFCoder 18 | 19 | + (instancetype)sharedCoder { 20 | static SDImageGIFCoder *coder; 21 | static dispatch_once_t onceToken; 22 | dispatch_once(&onceToken, ^{ 23 | coder = [[SDImageGIFCoder alloc] init]; 24 | }); 25 | return coder; 26 | } 27 | 28 | #pragma mark - Subclass Override 29 | 30 | + (SDImageFormat)imageFormat { 31 | return SDImageFormatGIF; 32 | } 33 | 34 | + (NSString *)imageUTType { 35 | return (__bridge NSString *)kSDUTTypeGIF; 36 | } 37 | 38 | + (NSString *)dictionaryProperty { 39 | return (__bridge NSString *)kCGImagePropertyGIFDictionary; 40 | } 41 | 42 | + (NSString *)unclampedDelayTimeProperty { 43 | return (__bridge NSString *)kCGImagePropertyGIFUnclampedDelayTime; 44 | } 45 | 46 | + (NSString *)delayTimeProperty { 47 | return (__bridge NSString *)kCGImagePropertyGIFDelayTime; 48 | } 49 | 50 | + (NSString *)loopCountProperty { 51 | return (__bridge NSString *)kCGImagePropertyGIFLoopCount; 52 | } 53 | 54 | + (NSUInteger)defaultLoopCount { 55 | return 1; 56 | } 57 | 58 | @end 59 | -------------------------------------------------------------------------------- /Example/Pods/SDWebImage/SDWebImage/Core/SDImageGraphics.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 "SDWebImageCompat.h" 10 | #import 11 | 12 | /** 13 | These following graphics context method are provided to easily write cross-platform(AppKit/UIKit) code. 14 | For UIKit, these methods just call the same method in `UIGraphics.h`. See the documentation for usage. 15 | For AppKit, these methods use `NSGraphicsContext` to create image context and match the behavior like UIKit. 16 | @note If you don't care bitmap format (ARGB8888) and just draw image, use `SDGraphicsImageRenderer` instead. It's more performant on RAM usage.` 17 | */ 18 | 19 | /// Returns the current graphics context. 20 | FOUNDATION_EXPORT CGContextRef __nullable SDGraphicsGetCurrentContext(void) CF_RETURNS_NOT_RETAINED; 21 | /// Creates a bitmap-based graphics context and makes it the current context. 22 | FOUNDATION_EXPORT void SDGraphicsBeginImageContext(CGSize size); 23 | /// Creates a bitmap-based graphics context with the specified options. 24 | FOUNDATION_EXPORT void SDGraphicsBeginImageContextWithOptions(CGSize size, BOOL opaque, CGFloat scale); 25 | /// Removes the current bitmap-based graphics context from the top of the stack. 26 | FOUNDATION_EXPORT void SDGraphicsEndImageContext(void); 27 | /// Returns an image based on the contents of the current bitmap-based graphics context. 28 | FOUNDATION_EXPORT UIImage * __nullable SDGraphicsGetImageFromCurrentImageContext(void); 29 | -------------------------------------------------------------------------------- /Example/Pods/SDWebImage/SDWebImage/Core/SDImageHEICCoder.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 | #import "SDImageIOAnimatedCoder.h" 11 | 12 | /** 13 | This coder is used for HEIC (HEIF with HEVC container codec) image format. 14 | Image/IO provide the static HEIC (.heic) support in iOS 11/macOS 10.13/tvOS 11/watchOS 4+. 15 | Image/IO provide the animated HEIC (.heics) support in iOS 13/macOS 10.15/tvOS 13/watchOS 6+. 16 | See https://nokiatech.github.io/heif/technical.html for the standard. 17 | @note This coder is not in the default coder list for now, since HEIC animated image is really rare, and Apple's implementation still contains performance issues. You can enable if you need this. 18 | @note If you need to support lower firmware version for HEIF, you can have a try at https://github.com/SDWebImage/SDWebImageHEIFCoder 19 | */ 20 | API_AVAILABLE(ios(13.0), tvos(13.0), macos(10.15), watchos(6.0)) 21 | @interface SDImageHEICCoder : SDImageIOAnimatedCoder 22 | 23 | @property (nonatomic, class, readonly, nonnull) SDImageHEICCoder *sharedCoder; 24 | 25 | @end 26 | -------------------------------------------------------------------------------- /Example/Pods/SDWebImage/SDWebImage/Core/SDImageIOAnimatedCoder.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 | #import "SDImageCoder.h" 11 | 12 | /** 13 | This is the abstract class for all animated coder, which use the Image/IO API. You can not use this directly as real coders. A exception will be raised if you use this class. 14 | All of the properties need the subclass to implement and works as expected. 15 | For Image/IO, See Apple's documentation: https://developer.apple.com/documentation/imageio 16 | */ 17 | @interface SDImageIOAnimatedCoder : NSObject 18 | 19 | #pragma mark - Subclass Override 20 | /** 21 | The supported animated image format. Such as `SDImageFormatGIF`. 22 | @note Subclass override. 23 | */ 24 | @property (class, readonly) SDImageFormat imageFormat; 25 | /** 26 | The supported image format UTI Type. Such as `kSDUTTypeGIF`. 27 | This can be used for cases when we can not detect `SDImageFormat. Such as progressive decoding's hint format `kCGImageSourceTypeIdentifierHint`. 28 | @note Subclass override. 29 | */ 30 | @property (class, readonly, nonnull) NSString *imageUTType; 31 | /** 32 | The image container property key used in Image/IO API. Such as `kCGImagePropertyGIFDictionary`. 33 | @note Subclass override. 34 | */ 35 | @property (class, readonly, nonnull) NSString *dictionaryProperty; 36 | /** 37 | The image unclamped delay time property key used in Image/IO API. Such as `kCGImagePropertyGIFUnclampedDelayTime` 38 | @note Subclass override. 39 | */ 40 | @property (class, readonly, nonnull) NSString *unclampedDelayTimeProperty; 41 | /** 42 | The image delay time property key used in Image/IO API. Such as `kCGImagePropertyGIFDelayTime`. 43 | @note Subclass override. 44 | */ 45 | @property (class, readonly, nonnull) NSString *delayTimeProperty; 46 | /** 47 | The image loop count property key used in Image/IO API. Such as `kCGImagePropertyGIFLoopCount`. 48 | @note Subclass override. 49 | */ 50 | @property (class, readonly, nonnull) NSString *loopCountProperty; 51 | /** 52 | The default loop count when there are no any loop count information inside image container metadata. 53 | For example, for GIF format, the standard use 1 (play once). For APNG format, the standard use 0 (infinity loop). 54 | @note Subclass override. 55 | */ 56 | @property (class, readonly) NSUInteger defaultLoopCount; 57 | 58 | @end 59 | -------------------------------------------------------------------------------- /Example/Pods/SDWebImage/SDWebImage/Core/SDImageIOCoder.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 | #import "SDImageCoder.h" 11 | 12 | /** 13 | Built in coder that supports PNG, JPEG, TIFF, includes support for progressive decoding. 14 | 15 | GIF 16 | Also supports static GIF (meaning will only handle the 1st frame). 17 | For a full GIF support, we recommend `SDAnimatedImageView` to keep both CPU and memory balanced. 18 | 19 | HEIC 20 | This coder also supports HEIC format because ImageIO supports it natively. But it depends on the system capabilities, so it won't work on all devices, see: https://devstreaming-cdn.apple.com/videos/wwdc/2017/511tj33587vdhds/511/511_working_with_heif_and_hevc.pdf 21 | Decode(Software): !Simulator && (iOS 11 || tvOS 11 || macOS 10.13) 22 | Decode(Hardware): !Simulator && ((iOS 11 && A9Chip) || (macOS 10.13 && 6thGenerationIntelCPU)) 23 | Encode(Software): macOS 10.13 24 | Encode(Hardware): !Simulator && ((iOS 11 && A10FusionChip) || (macOS 10.13 && 6thGenerationIntelCPU)) 25 | */ 26 | @interface SDImageIOCoder : NSObject 27 | 28 | @property (nonatomic, class, readonly, nonnull) SDImageIOCoder *sharedCoder; 29 | 30 | @end 31 | -------------------------------------------------------------------------------- /Example/Pods/SDWebImage/SDWebImage/Core/SDImageLoadersManager.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 "SDImageLoader.h" 10 | 11 | /** 12 | A loaders manager to manage multiple loaders 13 | */ 14 | @interface SDImageLoadersManager : NSObject 15 | 16 | /** 17 | Returns the global shared loaders manager instance. By default we will set [`SDWebImageDownloader.sharedDownloader`] into the loaders array. 18 | */ 19 | @property (nonatomic, class, readonly, nonnull) SDImageLoadersManager *sharedManager; 20 | 21 | /** 22 | All image loaders in manager. The loaders array is a priority queue, which means the later added loader will have the highest priority 23 | */ 24 | @property (nonatomic, copy, nullable) NSArray>* loaders; 25 | 26 | /** 27 | Add a new image loader to the end of loaders array. Which has the highest priority. 28 | 29 | @param loader loader 30 | */ 31 | - (void)addLoader:(nonnull id)loader; 32 | 33 | /** 34 | Remove an image loader in the loaders array. 35 | 36 | @param loader loader 37 | */ 38 | - (void)removeLoader:(nonnull id)loader; 39 | 40 | @end 41 | -------------------------------------------------------------------------------- /Example/Pods/SDWebImage/SDWebImage/Core/SDWebImageCacheKeyFilter.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 | #import "SDWebImageCompat.h" 11 | 12 | typedef NSString * _Nullable(^SDWebImageCacheKeyFilterBlock)(NSURL * _Nonnull url); 13 | 14 | /** 15 | This is the protocol for cache key filter. 16 | We can use a block to specify the cache key filter. But Using protocol can make this extensible, and allow Swift user to use it easily instead of using `@convention(block)` to store a block into context options. 17 | */ 18 | @protocol SDWebImageCacheKeyFilter 19 | 20 | - (nullable NSString *)cacheKeyForURL:(nonnull NSURL *)url; 21 | 22 | @end 23 | 24 | /** 25 | A cache key filter class with block. 26 | */ 27 | @interface SDWebImageCacheKeyFilter : NSObject 28 | 29 | - (nonnull instancetype)initWithBlock:(nonnull SDWebImageCacheKeyFilterBlock)block; 30 | + (nonnull instancetype)cacheKeyFilterWithBlock:(nonnull SDWebImageCacheKeyFilterBlock)block; 31 | 32 | @end 33 | -------------------------------------------------------------------------------- /Example/Pods/SDWebImage/SDWebImage/Core/SDWebImageCacheKeyFilter.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 "SDWebImageCacheKeyFilter.h" 10 | 11 | @interface SDWebImageCacheKeyFilter () 12 | 13 | @property (nonatomic, copy, nonnull) SDWebImageCacheKeyFilterBlock block; 14 | 15 | @end 16 | 17 | @implementation SDWebImageCacheKeyFilter 18 | 19 | - (instancetype)initWithBlock:(SDWebImageCacheKeyFilterBlock)block { 20 | self = [super init]; 21 | if (self) { 22 | self.block = block; 23 | } 24 | return self; 25 | } 26 | 27 | + (instancetype)cacheKeyFilterWithBlock:(SDWebImageCacheKeyFilterBlock)block { 28 | SDWebImageCacheKeyFilter *cacheKeyFilter = [[SDWebImageCacheKeyFilter alloc] initWithBlock:block]; 29 | return cacheKeyFilter; 30 | } 31 | 32 | - (NSString *)cacheKeyForURL:(NSURL *)url { 33 | if (!self.block) { 34 | return nil; 35 | } 36 | return self.block(url); 37 | } 38 | 39 | @end 40 | -------------------------------------------------------------------------------- /Example/Pods/SDWebImage/SDWebImage/Core/SDWebImageCacheSerializer.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 | #import "SDWebImageCompat.h" 11 | 12 | typedef NSData * _Nullable(^SDWebImageCacheSerializerBlock)(UIImage * _Nonnull image, NSData * _Nullable data, NSURL * _Nullable imageURL); 13 | 14 | /** 15 | This is the protocol for cache serializer. 16 | We can use a block to specify the cache serializer. But Using protocol can make this extensible, and allow Swift user to use it easily instead of using `@convention(block)` to store a block into context options. 17 | */ 18 | @protocol SDWebImageCacheSerializer 19 | 20 | /// Provide the image data associated to the image and store to disk cache 21 | /// @param image The loaded image 22 | /// @param data The original loaded image data. May be nil when image is transformed (UIImage.sd_isTransformed = YES) 23 | /// @param imageURL The image URL 24 | - (nullable NSData *)cacheDataWithImage:(nonnull UIImage *)image originalData:(nullable NSData *)data imageURL:(nullable NSURL *)imageURL; 25 | 26 | @end 27 | 28 | /** 29 | A cache serializer class with block. 30 | */ 31 | @interface SDWebImageCacheSerializer : NSObject 32 | 33 | - (nonnull instancetype)initWithBlock:(nonnull SDWebImageCacheSerializerBlock)block; 34 | + (nonnull instancetype)cacheSerializerWithBlock:(nonnull SDWebImageCacheSerializerBlock)block; 35 | 36 | @end 37 | -------------------------------------------------------------------------------- /Example/Pods/SDWebImage/SDWebImage/Core/SDWebImageCacheSerializer.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 "SDWebImageCacheSerializer.h" 10 | 11 | @interface SDWebImageCacheSerializer () 12 | 13 | @property (nonatomic, copy, nonnull) SDWebImageCacheSerializerBlock block; 14 | 15 | @end 16 | 17 | @implementation SDWebImageCacheSerializer 18 | 19 | - (instancetype)initWithBlock:(SDWebImageCacheSerializerBlock)block { 20 | self = [super init]; 21 | if (self) { 22 | self.block = block; 23 | } 24 | return self; 25 | } 26 | 27 | + (instancetype)cacheSerializerWithBlock:(SDWebImageCacheSerializerBlock)block { 28 | SDWebImageCacheSerializer *cacheSerializer = [[SDWebImageCacheSerializer alloc] initWithBlock:block]; 29 | return cacheSerializer; 30 | } 31 | 32 | - (NSData *)cacheDataWithImage:(UIImage *)image originalData:(NSData *)data imageURL:(nullable NSURL *)imageURL { 33 | if (!self.block) { 34 | return nil; 35 | } 36 | return self.block(image, data, imageURL); 37 | } 38 | 39 | @end 40 | -------------------------------------------------------------------------------- /Example/Pods/SDWebImage/SDWebImage/Core/SDWebImageCompat.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 "SDWebImageCompat.h" 10 | 11 | #if !__has_feature(objc_arc) 12 | #error SDWebImage is ARC only. Either turn on ARC for the project or use -fobjc-arc flag 13 | #endif 14 | 15 | #if !OS_OBJECT_USE_OBJC 16 | #error SDWebImage need ARC for dispatch object 17 | #endif 18 | -------------------------------------------------------------------------------- /Example/Pods/SDWebImage/SDWebImage/Core/SDWebImageDownloaderConfig.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 "SDWebImageDownloaderConfig.h" 10 | #import "SDWebImageDownloaderOperation.h" 11 | 12 | static SDWebImageDownloaderConfig * _defaultDownloaderConfig; 13 | 14 | @implementation SDWebImageDownloaderConfig 15 | 16 | + (SDWebImageDownloaderConfig *)defaultDownloaderConfig { 17 | static dispatch_once_t onceToken; 18 | dispatch_once(&onceToken, ^{ 19 | _defaultDownloaderConfig = [SDWebImageDownloaderConfig new]; 20 | }); 21 | return _defaultDownloaderConfig; 22 | } 23 | 24 | - (instancetype)init { 25 | self = [super init]; 26 | if (self) { 27 | _maxConcurrentDownloads = 6; 28 | _downloadTimeout = 15.0; 29 | _executionOrder = SDWebImageDownloaderFIFOExecutionOrder; 30 | _acceptableStatusCodes = [NSIndexSet indexSetWithIndexesInRange:NSMakeRange(200, 100)]; 31 | } 32 | return self; 33 | } 34 | 35 | - (id)copyWithZone:(NSZone *)zone { 36 | SDWebImageDownloaderConfig *config = [[[self class] allocWithZone:zone] init]; 37 | config.maxConcurrentDownloads = self.maxConcurrentDownloads; 38 | config.downloadTimeout = self.downloadTimeout; 39 | config.minimumProgressInterval = self.minimumProgressInterval; 40 | config.sessionConfiguration = [self.sessionConfiguration copyWithZone:zone]; 41 | config.operationClass = self.operationClass; 42 | config.executionOrder = self.executionOrder; 43 | config.urlCredential = self.urlCredential; 44 | config.username = self.username; 45 | config.password = self.password; 46 | config.acceptableStatusCodes = self.acceptableStatusCodes; 47 | config.acceptableContentTypes = self.acceptableContentTypes; 48 | 49 | return config; 50 | } 51 | 52 | - (void)setOperationClass:(Class)operationClass { 53 | if (operationClass) { 54 | NSAssert([operationClass isSubclassOfClass:[NSOperation class]] && [operationClass conformsToProtocol:@protocol(SDWebImageDownloaderOperation)], @"Custom downloader operation class must subclass NSOperation and conform to `SDWebImageDownloaderOperation` protocol"); 55 | } 56 | _operationClass = operationClass; 57 | } 58 | 59 | 60 | @end 61 | -------------------------------------------------------------------------------- /Example/Pods/SDWebImage/SDWebImage/Core/SDWebImageDownloaderDecryptor.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 | #import "SDWebImageCompat.h" 11 | 12 | typedef NSData * _Nullable (^SDWebImageDownloaderDecryptorBlock)(NSData * _Nonnull data, NSURLResponse * _Nullable response); 13 | 14 | /** 15 | This is the protocol for downloader decryptor. Which decrypt the original encrypted data before decoding. Note progressive decoding is not compatible for decryptor. 16 | We can use a block to specify the downloader decryptor. But Using protocol can make this extensible, and allow Swift user to use it easily instead of using `@convention(block)` to store a block into context options. 17 | */ 18 | @protocol SDWebImageDownloaderDecryptor 19 | 20 | /// Decrypt the original download data and return a new data. You can use this to decrypt the data using your preferred algorithm. 21 | /// @param data The original download data 22 | /// @param response The URL response for data. If you modify the original URL response via response modifier, the modified version will be here. This arg is nullable. 23 | /// @note If nil is returned, the image download will be marked as failed with error `SDWebImageErrorBadImageData` 24 | - (nullable NSData *)decryptedDataWithData:(nonnull NSData *)data response:(nullable NSURLResponse *)response; 25 | 26 | @end 27 | 28 | /** 29 | A downloader response modifier class with block. 30 | */ 31 | @interface SDWebImageDownloaderDecryptor : NSObject 32 | 33 | /// Create the data decryptor with block 34 | /// @param block A block to control decrypt logic 35 | - (nonnull instancetype)initWithBlock:(nonnull SDWebImageDownloaderDecryptorBlock)block; 36 | 37 | /// Create the data decryptor with block 38 | /// @param block A block to control decrypt logic 39 | + (nonnull instancetype)decryptorWithBlock:(nonnull SDWebImageDownloaderDecryptorBlock)block; 40 | 41 | @end 42 | 43 | /// Convenience way to create decryptor for common data encryption. 44 | @interface SDWebImageDownloaderDecryptor (Conveniences) 45 | 46 | /// Base64 Encoded image data decryptor 47 | @property (class, readonly, nonnull) SDWebImageDownloaderDecryptor *base64Decryptor; 48 | 49 | @end 50 | -------------------------------------------------------------------------------- /Example/Pods/SDWebImage/SDWebImage/Core/SDWebImageDownloaderDecryptor.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 "SDWebImageDownloaderDecryptor.h" 10 | 11 | @interface SDWebImageDownloaderDecryptor () 12 | 13 | @property (nonatomic, copy, nonnull) SDWebImageDownloaderDecryptorBlock block; 14 | 15 | @end 16 | 17 | @implementation SDWebImageDownloaderDecryptor 18 | 19 | - (instancetype)initWithBlock:(SDWebImageDownloaderDecryptorBlock)block { 20 | self = [super init]; 21 | if (self) { 22 | self.block = block; 23 | } 24 | return self; 25 | } 26 | 27 | + (instancetype)decryptorWithBlock:(SDWebImageDownloaderDecryptorBlock)block { 28 | SDWebImageDownloaderDecryptor *decryptor = [[SDWebImageDownloaderDecryptor alloc] initWithBlock:block]; 29 | return decryptor; 30 | } 31 | 32 | - (nullable NSData *)decryptedDataWithData:(nonnull NSData *)data response:(nullable NSURLResponse *)response { 33 | if (!self.block) { 34 | return nil; 35 | } 36 | return self.block(data, response); 37 | } 38 | 39 | @end 40 | 41 | @implementation SDWebImageDownloaderDecryptor (Conveniences) 42 | 43 | + (SDWebImageDownloaderDecryptor *)base64Decryptor { 44 | static SDWebImageDownloaderDecryptor *decryptor; 45 | static dispatch_once_t onceToken; 46 | dispatch_once(&onceToken, ^{ 47 | decryptor = [SDWebImageDownloaderDecryptor decryptorWithBlock:^NSData * _Nullable(NSData * _Nonnull data, NSURLResponse * _Nullable response) { 48 | NSData *modifiedData = [[NSData alloc] initWithBase64EncodedData:data options:NSDataBase64DecodingIgnoreUnknownCharacters]; 49 | return modifiedData; 50 | }]; 51 | }); 52 | return decryptor; 53 | } 54 | 55 | @end 56 | -------------------------------------------------------------------------------- /Example/Pods/SDWebImage/SDWebImage/Core/SDWebImageDownloaderRequestModifier.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 "SDWebImageDownloaderRequestModifier.h" 10 | 11 | @interface SDWebImageDownloaderRequestModifier () 12 | 13 | @property (nonatomic, copy, nonnull) SDWebImageDownloaderRequestModifierBlock block; 14 | 15 | @end 16 | 17 | @implementation SDWebImageDownloaderRequestModifier 18 | 19 | - (instancetype)initWithBlock:(SDWebImageDownloaderRequestModifierBlock)block { 20 | self = [super init]; 21 | if (self) { 22 | self.block = block; 23 | } 24 | return self; 25 | } 26 | 27 | + (instancetype)requestModifierWithBlock:(SDWebImageDownloaderRequestModifierBlock)block { 28 | SDWebImageDownloaderRequestModifier *requestModifier = [[SDWebImageDownloaderRequestModifier alloc] initWithBlock:block]; 29 | return requestModifier; 30 | } 31 | 32 | - (NSURLRequest *)modifiedRequestWithRequest:(NSURLRequest *)request { 33 | if (!self.block) { 34 | return nil; 35 | } 36 | return self.block(request); 37 | } 38 | 39 | @end 40 | 41 | @implementation SDWebImageDownloaderRequestModifier (Conveniences) 42 | 43 | - (instancetype)initWithMethod:(NSString *)method { 44 | return [self initWithMethod:method headers:nil body:nil]; 45 | } 46 | 47 | - (instancetype)initWithHeaders:(NSDictionary *)headers { 48 | return [self initWithMethod:nil headers:headers body:nil]; 49 | } 50 | 51 | - (instancetype)initWithBody:(NSData *)body { 52 | return [self initWithMethod:nil headers:nil body:body]; 53 | } 54 | 55 | - (instancetype)initWithMethod:(NSString *)method headers:(NSDictionary *)headers body:(NSData *)body { 56 | method = method ? [method copy] : @"GET"; 57 | headers = [headers copy]; 58 | body = [body copy]; 59 | return [self initWithBlock:^NSURLRequest * _Nullable(NSURLRequest * _Nonnull request) { 60 | NSMutableURLRequest *mutableRequest = [request mutableCopy]; 61 | mutableRequest.HTTPMethod = method; 62 | mutableRequest.HTTPBody = body; 63 | for (NSString *header in headers) { 64 | NSString *value = headers[header]; 65 | [mutableRequest setValue:value forHTTPHeaderField:header]; 66 | } 67 | return [mutableRequest copy]; 68 | }]; 69 | } 70 | 71 | @end 72 | -------------------------------------------------------------------------------- /Example/Pods/SDWebImage/SDWebImage/Core/SDWebImageError.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the SDWebImage package. 3 | * (c) Olivier Poitrey 4 | * (c) Jamie Pinkham 5 | * 6 | * For the full copyright and license information, please view the LICENSE 7 | * file that was distributed with this source code. 8 | */ 9 | 10 | #import "SDWebImageCompat.h" 11 | 12 | /// An error domain represent SDWebImage loading system with custom codes 13 | FOUNDATION_EXPORT NSErrorDomain const _Nonnull SDWebImageErrorDomain; 14 | 15 | /// The response instance for invalid download response (NSURLResponse *) 16 | FOUNDATION_EXPORT NSErrorUserInfoKey const _Nonnull SDWebImageErrorDownloadResponseKey; 17 | /// The HTTP status code for invalid download response (NSNumber *) 18 | FOUNDATION_EXPORT NSErrorUserInfoKey const _Nonnull SDWebImageErrorDownloadStatusCodeKey; 19 | /// The HTTP MIME content type for invalid download response (NSString *) 20 | FOUNDATION_EXPORT NSErrorUserInfoKey const _Nonnull SDWebImageErrorDownloadContentTypeKey; 21 | 22 | /// SDWebImage error domain and codes 23 | typedef NS_ERROR_ENUM(SDWebImageErrorDomain, SDWebImageError) { 24 | SDWebImageErrorInvalidURL = 1000, // The URL is invalid, such as nil URL or corrupted URL 25 | SDWebImageErrorBadImageData = 1001, // The image data can not be decoded to image, or the image data is empty 26 | SDWebImageErrorCacheNotModified = 1002, // The remote location specify that the cached image is not modified, such as the HTTP response 304 code. It's useful for `SDWebImageRefreshCached` 27 | SDWebImageErrorBlackListed = 1003, // The URL is blacklisted because of unrecoverable failure marked by downloader (such as 404), you can use `.retryFailed` option to avoid this 28 | SDWebImageErrorInvalidDownloadOperation = 2000, // The image download operation is invalid, such as nil operation or unexpected error occur when operation initialized 29 | SDWebImageErrorInvalidDownloadStatusCode = 2001, // The image download response a invalid status code. You can check the status code in error's userInfo under `SDWebImageErrorDownloadStatusCodeKey` 30 | SDWebImageErrorCancelled = 2002, // The image loading operation is cancelled before finished, during either async disk cache query, or waiting before actual network request. For actual network request error, check `NSURLErrorDomain` error domain and code. 31 | SDWebImageErrorInvalidDownloadResponse = 2003, // When using response modifier, the modified download response is nil and marked as failed. 32 | SDWebImageErrorInvalidDownloadContentType = 2004, // The image download response a invalid content type. You can check the MIME content type in error's userInfo under `SDWebImageErrorDownloadContentTypeKey` 33 | }; 34 | -------------------------------------------------------------------------------- /Example/Pods/SDWebImage/SDWebImage/Core/SDWebImageError.m: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the SDWebImage package. 3 | * (c) Olivier Poitrey 4 | * (c) Jamie Pinkham 5 | * 6 | * For the full copyright and license information, please view the LICENSE 7 | * file that was distributed with this source code. 8 | */ 9 | 10 | #import "SDWebImageError.h" 11 | 12 | NSErrorDomain const _Nonnull SDWebImageErrorDomain = @"SDWebImageErrorDomain"; 13 | 14 | NSErrorUserInfoKey const _Nonnull SDWebImageErrorDownloadResponseKey = @"SDWebImageErrorDownloadResponseKey"; 15 | NSErrorUserInfoKey const _Nonnull SDWebImageErrorDownloadStatusCodeKey = @"SDWebImageErrorDownloadStatusCodeKey"; 16 | NSErrorUserInfoKey const _Nonnull SDWebImageErrorDownloadContentTypeKey = @"SDWebImageErrorDownloadContentTypeKey"; 17 | -------------------------------------------------------------------------------- /Example/Pods/SDWebImage/SDWebImage/Core/SDWebImageOperation.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 | /// A protocol represents cancelable operation. 12 | @protocol SDWebImageOperation 13 | 14 | /// Cancel the operation 15 | - (void)cancel; 16 | 17 | @optional 18 | 19 | /// Whether the operation has been cancelled. 20 | @property (nonatomic, assign, readonly, getter=isCancelled) BOOL cancelled; 21 | 22 | @end 23 | 24 | /// NSOperation conform to `SDWebImageOperation`. 25 | @interface NSOperation (SDWebImageOperation) 26 | 27 | @end 28 | -------------------------------------------------------------------------------- /Example/Pods/SDWebImage/SDWebImage/Core/SDWebImageOperation.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 "SDWebImageOperation.h" 10 | 11 | /// NSOperation conform to `SDWebImageOperation`. 12 | @implementation NSOperation (SDWebImageOperation) 13 | 14 | @end 15 | -------------------------------------------------------------------------------- /Example/Pods/SDWebImage/SDWebImage/Core/SDWebImageOptionsProcessor.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 "SDWebImageOptionsProcessor.h" 10 | 11 | @interface SDWebImageOptionsResult () 12 | 13 | @property (nonatomic, assign) SDWebImageOptions options; 14 | @property (nonatomic, copy, nullable) SDWebImageContext *context; 15 | 16 | @end 17 | 18 | @implementation SDWebImageOptionsResult 19 | 20 | - (instancetype)initWithOptions:(SDWebImageOptions)options context:(SDWebImageContext *)context { 21 | self = [super init]; 22 | if (self) { 23 | self.options = options; 24 | self.context = context; 25 | } 26 | return self; 27 | } 28 | 29 | @end 30 | 31 | @interface SDWebImageOptionsProcessor () 32 | 33 | @property (nonatomic, copy, nonnull) SDWebImageOptionsProcessorBlock block; 34 | 35 | @end 36 | 37 | @implementation SDWebImageOptionsProcessor 38 | 39 | - (instancetype)initWithBlock:(SDWebImageOptionsProcessorBlock)block { 40 | self = [super init]; 41 | if (self) { 42 | self.block = block; 43 | } 44 | return self; 45 | } 46 | 47 | + (instancetype)optionsProcessorWithBlock:(SDWebImageOptionsProcessorBlock)block { 48 | SDWebImageOptionsProcessor *optionsProcessor = [[SDWebImageOptionsProcessor alloc] initWithBlock:block]; 49 | return optionsProcessor; 50 | } 51 | 52 | - (SDWebImageOptionsResult *)processedResultForURL:(NSURL *)url options:(SDWebImageOptions)options context:(SDWebImageContext *)context { 53 | if (!self.block) { 54 | return nil; 55 | } 56 | return self.block(url, options, context); 57 | } 58 | 59 | @end 60 | -------------------------------------------------------------------------------- /Example/Pods/SDWebImage/SDWebImage/Core/UIImage+ExtendedCacheData.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the SDWebImage package. 3 | * (c) Olivier Poitrey 4 | * (c) Fabrice Aneche 5 | * 6 | * For the full copyright and license information, please view the LICENSE 7 | * file that was distributed with this source code. 8 | */ 9 | 10 | #import 11 | #import "SDWebImageCompat.h" 12 | 13 | @interface UIImage (ExtendedCacheData) 14 | 15 | /** 16 | Read and Write the extended object and bind it to the image. Which can hold some extra metadata like Image's scale factor, URL rich link, date, etc. 17 | The extended object should conforms to NSCoding, which we use `NSKeyedArchiver` and `NSKeyedUnarchiver` to archive it to data, and write to disk cache. 18 | @note The disk cache preserve both of the data and extended data with the same cache key. For manual query, use the `SDDiskCache` protocol method `extendedDataForKey:` instead. 19 | @note You can specify arbitrary object conforms to NSCoding (NSObject protocol here is used to support object using `NS_ROOT_CLASS`, which is not NSObject subclass). If you load image from disk cache, you should check the extended object class to avoid corrupted data. 20 | @warning This object don't need to implements NSSecureCoding (but it's recommended), because we allows arbitrary class. 21 | */ 22 | @property (nonatomic, strong, nullable) id sd_extendedObject; 23 | 24 | @end 25 | -------------------------------------------------------------------------------- /Example/Pods/SDWebImage/SDWebImage/Core/UIImage+ExtendedCacheData.m: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the SDWebImage package. 3 | * (c) Olivier Poitrey 4 | * (c) Fabrice Aneche 5 | * 6 | * For the full copyright and license information, please view the LICENSE 7 | * file that was distributed with this source code. 8 | */ 9 | 10 | #import "UIImage+ExtendedCacheData.h" 11 | #import 12 | 13 | @implementation UIImage (ExtendedCacheData) 14 | 15 | - (id)sd_extendedObject { 16 | return objc_getAssociatedObject(self, @selector(sd_extendedObject)); 17 | } 18 | 19 | - (void)setSd_extendedObject:(id)sd_extendedObject { 20 | objc_setAssociatedObject(self, @selector(sd_extendedObject), sd_extendedObject, OBJC_ASSOCIATION_RETAIN_NONATOMIC); 21 | } 22 | 23 | @end 24 | -------------------------------------------------------------------------------- /Example/Pods/SDWebImage/SDWebImage/Core/UIImage+ForceDecode.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 "SDWebImageCompat.h" 10 | 11 | /** 12 | UIImage category about force decode feature (avoid Image/IO's lazy decoding during rendering behavior). 13 | */ 14 | @interface UIImage (ForceDecode) 15 | 16 | /** 17 | A bool value indicating whether the image has already been decoded. This can help to avoid extra force decode. 18 | Force decode is used for 2 cases: 19 | -- 1. for ImageIO created image (via `CGImageCreateWithImageSource` SPI), it's lazy and we trigger the decode before rendering 20 | -- 2. for non-ImageIO created image (via `CGImageCreate` API), we can ensure it's alignment is suitable to render on screen without copy by CoreAnimation 21 | @note For coder plugin developer, always use the SDImageCoderHelper's `colorSpaceGetDeviceRGB`/`preferredPixelFormat` to create CGImage. 22 | @note For more information why force decode, see: https://github.com/path/FastImageCache#byte-alignment 23 | @note From v5.17.0, the default value is always NO. Use `SDImageForceDecodePolicy` to control complicated policy. 24 | */ 25 | @property (nonatomic, assign) BOOL sd_isDecoded; 26 | 27 | /** 28 | Decode the provided image. This is useful if you want to force decode the image before rendering to improve performance. 29 | 30 | @param image The image to be decoded 31 | @return The decoded image 32 | */ 33 | + (nullable UIImage *)sd_decodedImageWithImage:(nullable UIImage *)image; 34 | 35 | /** 36 | Decode and scale down the provided image 37 | 38 | @param image The image to be decoded 39 | @return The decoded and scaled down image 40 | */ 41 | + (nullable UIImage *)sd_decodedAndScaledDownImageWithImage:(nullable UIImage *)image; 42 | 43 | /** 44 | Decode and scale down the provided image with limit bytes 45 | 46 | @param image The image to be decoded 47 | @param bytes The limit bytes size. Provide 0 to use the build-in limit. 48 | @return The decoded and scaled down image 49 | */ 50 | + (nullable UIImage *)sd_decodedAndScaledDownImageWithImage:(nullable UIImage *)image limitBytes:(NSUInteger)bytes; 51 | 52 | @end 53 | -------------------------------------------------------------------------------- /Example/Pods/SDWebImage/SDWebImage/Core/UIImage+ForceDecode.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 "UIImage+ForceDecode.h" 10 | #import "SDImageCoderHelper.h" 11 | #import "objc/runtime.h" 12 | #import "NSImage+Compatibility.h" 13 | 14 | @implementation UIImage (ForceDecode) 15 | 16 | - (BOOL)sd_isDecoded { 17 | NSNumber *value = objc_getAssociatedObject(self, @selector(sd_isDecoded)); 18 | return [value boolValue]; 19 | } 20 | 21 | - (void)setSd_isDecoded:(BOOL)sd_isDecoded { 22 | objc_setAssociatedObject(self, @selector(sd_isDecoded), @(sd_isDecoded), OBJC_ASSOCIATION_RETAIN_NONATOMIC); 23 | } 24 | 25 | + (nullable UIImage *)sd_decodedImageWithImage:(nullable UIImage *)image { 26 | if (!image) { 27 | return nil; 28 | } 29 | return [SDImageCoderHelper decodedImageWithImage:image]; 30 | } 31 | 32 | + (nullable UIImage *)sd_decodedAndScaledDownImageWithImage:(nullable UIImage *)image { 33 | return [self sd_decodedAndScaledDownImageWithImage:image limitBytes:0]; 34 | } 35 | 36 | + (nullable UIImage *)sd_decodedAndScaledDownImageWithImage:(nullable UIImage *)image limitBytes:(NSUInteger)bytes { 37 | if (!image) { 38 | return nil; 39 | } 40 | return [SDImageCoderHelper decodedAndScaledDownImageWithImage:image limitBytes:bytes]; 41 | } 42 | 43 | @end 44 | -------------------------------------------------------------------------------- /Example/Pods/SDWebImage/SDWebImage/Core/UIImage+GIF.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the SDWebImage package. 3 | * (c) Olivier Poitrey 4 | * (c) Laurin Brandner 5 | * 6 | * For the full copyright and license information, please view the LICENSE 7 | * file that was distributed with this source code. 8 | */ 9 | 10 | #import "SDWebImageCompat.h" 11 | 12 | /** 13 | This category is just use as a convenience method. For more detail control, use methods in `UIImage+MultiFormat.h` or directly use `SDImageCoder`. 14 | */ 15 | @interface UIImage (GIF) 16 | 17 | /** 18 | Creates an animated UIImage from an NSData. 19 | This will create animated image if the data is Animated GIF. And will create a static image is the data is Static GIF. 20 | 21 | @param data The GIF data 22 | @return The created image 23 | */ 24 | + (nullable UIImage *)sd_imageWithGIFData:(nullable NSData *)data; 25 | 26 | @end 27 | -------------------------------------------------------------------------------- /Example/Pods/SDWebImage/SDWebImage/Core/UIImage+GIF.m: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is part of the SDWebImage package. 3 | * (c) Olivier Poitrey 4 | * (c) Laurin Brandner 5 | * 6 | * For the full copyright and license information, please view the LICENSE 7 | * file that was distributed with this source code. 8 | */ 9 | 10 | #import "UIImage+GIF.h" 11 | #import "SDImageGIFCoder.h" 12 | 13 | @implementation UIImage (GIF) 14 | 15 | + (nullable UIImage *)sd_imageWithGIFData:(nullable NSData *)data { 16 | if (!data) { 17 | return nil; 18 | } 19 | return [[SDImageGIFCoder sharedCoder] decodedImageWithData:data options:0]; 20 | } 21 | 22 | @end 23 | -------------------------------------------------------------------------------- /Example/Pods/SDWebImage/SDWebImage/Core/UIImage+MemoryCacheCost.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 "SDWebImageCompat.h" 10 | 11 | /** 12 | UIImage category for memory cache cost. 13 | */ 14 | @interface UIImage (MemoryCacheCost) 15 | 16 | /** 17 | The memory cache cost for specify image used by image cache. The cost function is the bytes size held in memory. 18 | If you set some associated object to `UIImage`, you can set the custom value to indicate the memory cost. 19 | 20 | For `UIImage`, this method return the single frame bytes size when `image.images` is nil for static image. Return full frame bytes size when `image.images` is not nil for animated image. 21 | For `NSImage`, this method return the single frame bytes size because `NSImage` does not store all frames in memory. 22 | @note Note that because of the limitations of category this property can get out of sync if you create another instance with CGImage or other methods. 23 | @note For custom animated class conforms to `SDAnimatedImage`, you can override this getter method in your subclass to return a more proper value instead, which representing the current frame's total bytes. 24 | */ 25 | @property (assign, nonatomic) NSUInteger sd_memoryCost; 26 | 27 | @end 28 | -------------------------------------------------------------------------------- /Example/Pods/SDWebImage/SDWebImage/Core/UIImage+MemoryCacheCost.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 "UIImage+MemoryCacheCost.h" 10 | #import "objc/runtime.h" 11 | #import "NSImage+Compatibility.h" 12 | 13 | FOUNDATION_STATIC_INLINE NSUInteger SDMemoryCacheCostForImage(UIImage *image) { 14 | CGImageRef imageRef = image.CGImage; 15 | if (!imageRef) { 16 | return 0; 17 | } 18 | NSUInteger bytesPerFrame = CGImageGetBytesPerRow(imageRef) * CGImageGetHeight(imageRef); 19 | NSUInteger frameCount; 20 | #if SD_MAC 21 | frameCount = 1; 22 | #elif SD_UIKIT || SD_WATCH 23 | // Filter the same frame in `_UIAnimatedImage`. 24 | frameCount = image.images.count > 1 ? [NSSet setWithArray:image.images].count : 1; 25 | #endif 26 | NSUInteger cost = bytesPerFrame * frameCount; 27 | return cost; 28 | } 29 | 30 | @implementation UIImage (MemoryCacheCost) 31 | 32 | - (NSUInteger)sd_memoryCost { 33 | NSNumber *value = objc_getAssociatedObject(self, @selector(sd_memoryCost)); 34 | NSUInteger memoryCost; 35 | if (value != nil) { 36 | memoryCost = [value unsignedIntegerValue]; 37 | } else { 38 | memoryCost = SDMemoryCacheCostForImage(self); 39 | } 40 | return memoryCost; 41 | } 42 | 43 | - (void)setSd_memoryCost:(NSUInteger)sd_memoryCost { 44 | objc_setAssociatedObject(self, @selector(sd_memoryCost), @(sd_memoryCost), OBJC_ASSOCIATION_RETAIN_NONATOMIC); 45 | } 46 | 47 | @end 48 | -------------------------------------------------------------------------------- /Example/Pods/SDWebImage/SDWebImage/Core/UIImage+MultiFormat.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 "UIImage+MultiFormat.h" 10 | #import "SDImageCodersManager.h" 11 | #import "SDAnimatedImageRep.h" 12 | #import "UIImage+Metadata.h" 13 | 14 | @implementation UIImage (MultiFormat) 15 | 16 | + (nullable UIImage *)sd_imageWithData:(nullable NSData *)data { 17 | return [self sd_imageWithData:data scale:1]; 18 | } 19 | 20 | + (nullable UIImage *)sd_imageWithData:(nullable NSData *)data scale:(CGFloat)scale { 21 | return [self sd_imageWithData:data scale:scale firstFrameOnly:NO]; 22 | } 23 | 24 | + (nullable UIImage *)sd_imageWithData:(nullable NSData *)data scale:(CGFloat)scale firstFrameOnly:(BOOL)firstFrameOnly { 25 | if (!data) { 26 | return nil; 27 | } 28 | SDImageCoderOptions *options = @{SDImageCoderDecodeScaleFactor : @(MAX(scale, 1)), SDImageCoderDecodeFirstFrameOnly : @(firstFrameOnly)}; 29 | return [[SDImageCodersManager sharedManager] decodedImageWithData:data options:options]; 30 | } 31 | 32 | - (nullable NSData *)sd_imageData { 33 | #if SD_MAC 34 | NSRect imageRect = NSMakeRect(0, 0, self.size.width, self.size.height); 35 | NSImageRep *imageRep = [self bestRepresentationForRect:imageRect context:nil hints:nil]; 36 | // Check weak animated data firstly 37 | if ([imageRep isKindOfClass:[SDAnimatedImageRep class]]) { 38 | SDAnimatedImageRep *animatedImageRep = (SDAnimatedImageRep *)imageRep; 39 | NSData *imageData = [animatedImageRep animatedImageData]; 40 | if (imageData) { 41 | return imageData; 42 | } 43 | } 44 | #endif 45 | return [self sd_imageDataAsFormat:self.sd_imageFormat]; 46 | } 47 | 48 | - (nullable NSData *)sd_imageDataAsFormat:(SDImageFormat)imageFormat { 49 | return [self sd_imageDataAsFormat:imageFormat compressionQuality:1]; 50 | } 51 | 52 | - (nullable NSData *)sd_imageDataAsFormat:(SDImageFormat)imageFormat compressionQuality:(double)compressionQuality { 53 | return [self sd_imageDataAsFormat:imageFormat compressionQuality:compressionQuality firstFrameOnly:NO]; 54 | } 55 | 56 | - (nullable NSData *)sd_imageDataAsFormat:(SDImageFormat)imageFormat compressionQuality:(double)compressionQuality firstFrameOnly:(BOOL)firstFrameOnly { 57 | SDImageCoderOptions *options = @{SDImageCoderEncodeCompressionQuality : @(compressionQuality), SDImageCoderEncodeFirstFrameOnly : @(firstFrameOnly)}; 58 | return [[SDImageCodersManager sharedManager] encodedDataWithImage:self format:imageFormat options:options]; 59 | } 60 | 61 | @end 62 | -------------------------------------------------------------------------------- /Example/Pods/SDWebImage/SDWebImage/Core/UIView+WebCacheOperation.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 "SDWebImageCompat.h" 10 | #import "SDWebImageOperation.h" 11 | 12 | /** 13 | These methods are used to support canceling for UIView image loading, it's designed to be used internal but not external. 14 | All the stored operations are weak, so it will be dealloced after image loading finished. If you need to store operations, use your own class to keep a strong reference for them. 15 | */ 16 | @interface UIView (WebCacheOperation) 17 | 18 | /** 19 | * Get the image load operation for key 20 | * 21 | * @param key key for identifying the operations 22 | * @return the image load operation 23 | * @note If key is nil, means using the NSStringFromClass(self.class) instead, match the behavior of `operation key` 24 | */ 25 | - (nullable id)sd_imageLoadOperationForKey:(nullable NSString *)key; 26 | 27 | /** 28 | * Set the image load operation (storage in a UIView based weak map table) 29 | * 30 | * @param operation the operation, should not be nil or no-op will perform 31 | * @param key key for storing the operation 32 | * @note If key is nil, means using the NSStringFromClass(self.class) instead, match the behavior of `operation key` 33 | */ 34 | - (void)sd_setImageLoadOperation:(nullable id)operation forKey:(nullable NSString *)key; 35 | 36 | /** 37 | * Cancel the operation for the current UIView and key 38 | * 39 | * @param key key for identifying the operations 40 | * @note If key is nil, means using the NSStringFromClass(self.class) instead, match the behavior of `operation key` 41 | */ 42 | - (void)sd_cancelImageLoadOperationWithKey:(nullable NSString *)key; 43 | 44 | /** 45 | * Just remove the operation corresponding to the current UIView and key without cancelling them 46 | * 47 | * @param key key for identifying the operations. 48 | * @note If key is nil, means using the NSStringFromClass(self.class) instead, match the behavior of `operation key` 49 | */ 50 | - (void)sd_removeImageLoadOperationWithKey:(nullable NSString *)key; 51 | 52 | @end 53 | -------------------------------------------------------------------------------- /Example/Pods/SDWebImage/SDWebImage/Core/UIView+WebCacheState.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 | #import "SDWebImageCompat.h" 11 | 12 | /** 13 | A loading state to manage View Category which contains multiple states. Like UIImgeView.image && UIImageView.highlightedImage 14 | @code 15 | SDWebImageLoadState *loadState = [self sd_imageLoadStateForKey:@keypath(self, highlitedImage)]; 16 | NSProgress *highlitedImageProgress = loadState.progress; 17 | @endcode 18 | */ 19 | @interface SDWebImageLoadState : NSObject 20 | 21 | /** 22 | Image loading URL 23 | */ 24 | @property (nonatomic, strong, nullable) NSURL *url; 25 | /** 26 | Image loading progress. The unit count is the received size and excepted size of download. 27 | */ 28 | @property (nonatomic, strong, nullable) NSProgress *progress; 29 | 30 | @end 31 | 32 | /** 33 | These methods are used for WebCache view which have multiple states for image loading, for example, `UIButton` or `UIImageView.highlightedImage` 34 | It maitain the state container for per-operation, make it possible for control and check each image loading operation's state. 35 | @note For developer who want to add SDWebImage View Category support for their own stateful class, learn more on Wiki. 36 | */ 37 | @interface UIView (WebCacheState) 38 | 39 | /** 40 | Get the image loading state container for specify operation key 41 | 42 | @param key key for identifying the operations 43 | @return The image loading state container 44 | */ 45 | - (nullable SDWebImageLoadState *)sd_imageLoadStateForKey:(nullable NSString *)key; 46 | 47 | /** 48 | Set the image loading state container for specify operation key 49 | 50 | @param state The image loading state container 51 | @param key key for identifying the operations 52 | */ 53 | - (void)sd_setImageLoadState:(nullable SDWebImageLoadState *)state forKey:(nullable NSString *)key; 54 | 55 | /** 56 | Rmove the image loading state container for specify operation key 57 | 58 | @param key key for identifying the operations 59 | */ 60 | - (void)sd_removeImageLoadStateForKey:(nullable NSString *)key; 61 | 62 | @end 63 | -------------------------------------------------------------------------------- /Example/Pods/SDWebImage/SDWebImage/Core/UIView+WebCacheState.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 "UIView+WebCacheState.h" 10 | #import "objc/runtime.h" 11 | 12 | typedef NSMutableDictionary SDStatesDictionary; 13 | 14 | @implementation SDWebImageLoadState 15 | 16 | @end 17 | 18 | @implementation UIView (WebCacheState) 19 | 20 | - (SDStatesDictionary *)sd_imageLoadStateDictionary { 21 | SDStatesDictionary *states = objc_getAssociatedObject(self, @selector(sd_imageLoadStateDictionary)); 22 | if (!states) { 23 | states = [NSMutableDictionary dictionary]; 24 | objc_setAssociatedObject(self, @selector(sd_imageLoadStateDictionary), states, OBJC_ASSOCIATION_RETAIN_NONATOMIC); 25 | } 26 | return states; 27 | } 28 | 29 | - (SDWebImageLoadState *)sd_imageLoadStateForKey:(NSString *)key { 30 | if (!key) { 31 | key = NSStringFromClass(self.class); 32 | } 33 | @synchronized(self) { 34 | return [self.sd_imageLoadStateDictionary objectForKey:key]; 35 | } 36 | } 37 | 38 | - (void)sd_setImageLoadState:(SDWebImageLoadState *)state forKey:(NSString *)key { 39 | if (!key) { 40 | key = NSStringFromClass(self.class); 41 | } 42 | @synchronized(self) { 43 | self.sd_imageLoadStateDictionary[key] = state; 44 | } 45 | } 46 | 47 | - (void)sd_removeImageLoadStateForKey:(NSString *)key { 48 | if (!key) { 49 | key = NSStringFromClass(self.class); 50 | } 51 | @synchronized(self) { 52 | self.sd_imageLoadStateDictionary[key] = nil; 53 | } 54 | } 55 | 56 | @end 57 | -------------------------------------------------------------------------------- /Example/Pods/SDWebImage/SDWebImage/Private/NSBezierPath+SDRoundedCorners.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 "SDWebImageCompat.h" 10 | 11 | #if SD_MAC 12 | 13 | #import "UIImage+Transform.h" 14 | 15 | @interface NSBezierPath (SDRoundedCorners) 16 | 17 | /** 18 | Convenience way to create a bezier path with the specify rounding corners on macOS. Same as the one on `UIBezierPath`. 19 | */ 20 | + (nonnull instancetype)sd_bezierPathWithRoundedRect:(NSRect)rect byRoundingCorners:(SDRectCorner)corners cornerRadius:(CGFloat)cornerRadius; 21 | 22 | @end 23 | 24 | #endif 25 | -------------------------------------------------------------------------------- /Example/Pods/SDWebImage/SDWebImage/Private/NSBezierPath+SDRoundedCorners.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 "NSBezierPath+SDRoundedCorners.h" 10 | 11 | #if SD_MAC 12 | 13 | @implementation NSBezierPath (SDRoundedCorners) 14 | 15 | + (instancetype)sd_bezierPathWithRoundedRect:(NSRect)rect byRoundingCorners:(SDRectCorner)corners cornerRadius:(CGFloat)cornerRadius { 16 | NSBezierPath *path = [NSBezierPath bezierPath]; 17 | 18 | CGFloat maxCorner = MIN(NSWidth(rect), NSHeight(rect)) / 2; 19 | 20 | CGFloat topLeftRadius = MIN(maxCorner, (corners & SDRectCornerTopLeft) ? cornerRadius : 0); 21 | CGFloat topRightRadius = MIN(maxCorner, (corners & SDRectCornerTopRight) ? cornerRadius : 0); 22 | CGFloat bottomLeftRadius = MIN(maxCorner, (corners & SDRectCornerBottomLeft) ? cornerRadius : 0); 23 | CGFloat bottomRightRadius = MIN(maxCorner, (corners & SDRectCornerBottomRight) ? cornerRadius : 0); 24 | 25 | NSPoint topLeft = NSMakePoint(NSMinX(rect), NSMaxY(rect)); 26 | NSPoint topRight = NSMakePoint(NSMaxX(rect), NSMaxY(rect)); 27 | NSPoint bottomLeft = NSMakePoint(NSMinX(rect), NSMinY(rect)); 28 | NSPoint bottomRight = NSMakePoint(NSMaxX(rect), NSMinY(rect)); 29 | 30 | [path moveToPoint:NSMakePoint(NSMidX(rect), NSMaxY(rect))]; 31 | [path appendBezierPathWithArcFromPoint:topLeft toPoint:bottomLeft radius:topLeftRadius]; 32 | [path appendBezierPathWithArcFromPoint:bottomLeft toPoint:bottomRight radius:bottomLeftRadius]; 33 | [path appendBezierPathWithArcFromPoint:bottomRight toPoint:topRight radius:bottomRightRadius]; 34 | [path appendBezierPathWithArcFromPoint:topRight toPoint:topLeft radius:topRightRadius]; 35 | [path closePath]; 36 | 37 | return path; 38 | } 39 | 40 | @end 41 | 42 | #endif 43 | -------------------------------------------------------------------------------- /Example/Pods/SDWebImage/SDWebImage/Private/SDAssociatedObject.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 "SDWebImageCompat.h" 10 | 11 | /// Copy the associated object from source image to target image. The associated object including all the category read/write properties. 12 | /// @param source source 13 | /// @param target target 14 | FOUNDATION_EXPORT void SDImageCopyAssociatedObject(UIImage * _Nullable source, UIImage * _Nullable target); 15 | -------------------------------------------------------------------------------- /Example/Pods/SDWebImage/SDWebImage/Private/SDAssociatedObject.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 "SDAssociatedObject.h" 10 | #import "UIImage+Metadata.h" 11 | #import "UIImage+ExtendedCacheData.h" 12 | #import "UIImage+MemoryCacheCost.h" 13 | #import "UIImage+ForceDecode.h" 14 | 15 | void SDImageCopyAssociatedObject(UIImage * _Nullable source, UIImage * _Nullable target) { 16 | if (!source || !target) { 17 | return; 18 | } 19 | // Image Metadata 20 | target.sd_isIncremental = source.sd_isIncremental; 21 | target.sd_isTransformed = source.sd_isTransformed; 22 | target.sd_decodeOptions = source.sd_decodeOptions; 23 | target.sd_imageLoopCount = source.sd_imageLoopCount; 24 | target.sd_imageFormat = source.sd_imageFormat; 25 | // Force Decode 26 | target.sd_isDecoded = source.sd_isDecoded; 27 | // Extended Cache Data 28 | target.sd_extendedObject = source.sd_extendedObject; 29 | } 30 | -------------------------------------------------------------------------------- /Example/Pods/SDWebImage/SDWebImage/Private/SDAsyncBlockOperation.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 "SDWebImageCompat.h" 10 | 11 | @class SDAsyncBlockOperation; 12 | typedef void (^SDAsyncBlock)(SDAsyncBlockOperation * __nonnull asyncOperation); 13 | 14 | /// A async block operation, success after you call `completer` (not like `NSBlockOperation` which is for sync block, success on return) 15 | @interface SDAsyncBlockOperation : NSOperation 16 | 17 | - (nonnull instancetype)initWithBlock:(nonnull SDAsyncBlock)block; 18 | + (nonnull instancetype)blockOperationWithBlock:(nonnull SDAsyncBlock)block; 19 | - (void)complete; 20 | 21 | @end 22 | -------------------------------------------------------------------------------- /Example/Pods/SDWebImage/SDWebImage/Private/SDAsyncBlockOperation.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 "SDAsyncBlockOperation.h" 10 | #import "SDInternalMacros.h" 11 | 12 | @interface SDAsyncBlockOperation () 13 | 14 | @property (nonatomic, copy, nonnull) SDAsyncBlock executionBlock; 15 | 16 | @end 17 | 18 | @implementation SDAsyncBlockOperation 19 | 20 | @synthesize executing = _executing; 21 | @synthesize finished = _finished; 22 | 23 | - (nonnull instancetype)initWithBlock:(nonnull SDAsyncBlock)block { 24 | self = [super init]; 25 | if (self) { 26 | self.executionBlock = block; 27 | } 28 | return self; 29 | } 30 | 31 | + (nonnull instancetype)blockOperationWithBlock:(nonnull SDAsyncBlock)block { 32 | SDAsyncBlockOperation *operation = [[SDAsyncBlockOperation alloc] initWithBlock:block]; 33 | return operation; 34 | } 35 | 36 | - (void)start { 37 | @synchronized (self) { 38 | if (self.isCancelled) { 39 | self.finished = YES; 40 | return; 41 | } 42 | self.finished = NO; 43 | self.executing = YES; 44 | } 45 | SDAsyncBlock executionBlock = self.executionBlock; 46 | if (executionBlock) { 47 | @weakify(self); 48 | dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{ 49 | @strongify(self); 50 | if (!self) return; 51 | executionBlock(self); 52 | }); 53 | } 54 | } 55 | 56 | - (void)cancel { 57 | @synchronized (self) { 58 | [super cancel]; 59 | if (self.isExecuting) { 60 | self.executing = NO; 61 | self.finished = YES; 62 | } 63 | } 64 | } 65 | 66 | 67 | - (void)complete { 68 | @synchronized (self) { 69 | if (self.isExecuting) { 70 | self.finished = YES; 71 | self.executing = NO; 72 | } 73 | } 74 | } 75 | 76 | - (void)setFinished:(BOOL)finished { 77 | [self willChangeValueForKey:@"isFinished"]; 78 | _finished = finished; 79 | [self didChangeValueForKey:@"isFinished"]; 80 | } 81 | 82 | - (void)setExecuting:(BOOL)executing { 83 | [self willChangeValueForKey:@"isExecuting"]; 84 | _executing = executing; 85 | [self didChangeValueForKey:@"isExecuting"]; 86 | } 87 | 88 | - (BOOL)isAsynchronous { 89 | return YES; 90 | } 91 | 92 | @end 93 | -------------------------------------------------------------------------------- /Example/Pods/SDWebImage/SDWebImage/Private/SDDeviceHelper.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 | #import "SDWebImageCompat.h" 11 | 12 | /// Device information helper methods 13 | @interface SDDeviceHelper : NSObject 14 | 15 | + (NSUInteger)totalMemory; 16 | + (NSUInteger)freeMemory; 17 | 18 | @end 19 | -------------------------------------------------------------------------------- /Example/Pods/SDWebImage/SDWebImage/Private/SDDeviceHelper.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 "SDDeviceHelper.h" 10 | #import 11 | #import 12 | 13 | @implementation SDDeviceHelper 14 | 15 | + (NSUInteger)totalMemory { 16 | return (NSUInteger)[[NSProcessInfo processInfo] physicalMemory]; 17 | } 18 | 19 | + (NSUInteger)freeMemory { 20 | mach_port_t host_port = mach_host_self(); 21 | mach_msg_type_number_t host_size = sizeof(vm_statistics_data_t) / sizeof(integer_t); 22 | vm_size_t page_size; 23 | vm_statistics_data_t vm_stat; 24 | kern_return_t kern; 25 | 26 | kern = host_page_size(host_port, &page_size); 27 | if (kern != KERN_SUCCESS) return 0; 28 | kern = host_statistics(host_port, HOST_VM_INFO, (host_info_t)&vm_stat, &host_size); 29 | if (kern != KERN_SUCCESS) return 0; 30 | return vm_stat.free_count * page_size; 31 | } 32 | 33 | @end 34 | -------------------------------------------------------------------------------- /Example/Pods/SDWebImage/SDWebImage/Private/SDDisplayLink.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 | #import "SDWebImageCompat.h" 11 | 12 | /// Cross-platform display link wrapper. Do not retain the target 13 | /// Use `CADisplayLink` on iOS/tvOS, `CVDisplayLink` on macOS, `NSTimer` on watchOS 14 | @interface SDDisplayLink : NSObject 15 | 16 | @property (readonly, nonatomic, weak, nullable) id target; 17 | @property (readonly, nonatomic, assign, nonnull) SEL selector; 18 | @property (readonly, nonatomic) NSTimeInterval duration; // elapsed time in seconds of previous callback. (or it's first callback, use the time between `start` and callback). Always zero when display link not running 19 | @property (readonly, nonatomic) BOOL isRunning; 20 | 21 | + (nonnull instancetype)displayLinkWithTarget:(nonnull id)target selector:(nonnull SEL)sel; 22 | 23 | - (void)addToRunLoop:(nonnull NSRunLoop *)runloop forMode:(nonnull NSRunLoopMode)mode; 24 | - (void)removeFromRunLoop:(nonnull NSRunLoop *)runloop forMode:(nonnull NSRunLoopMode)mode; 25 | 26 | - (void)start; 27 | - (void)stop; 28 | 29 | @end 30 | -------------------------------------------------------------------------------- /Example/Pods/SDWebImage/SDWebImage/Private/SDFileAttributeHelper.h: -------------------------------------------------------------------------------- 1 | // 2 | // This file is from https://gist.github.com/zydeco/6292773 3 | // 4 | // Created by Jesús A. Álvarez on 2008-12-17. 5 | // Copyright 2008-2009 namedfork.net. All rights reserved. 6 | // 7 | 8 | #import 9 | 10 | /// File Extended Attribute (xattr) helper methods 11 | @interface SDFileAttributeHelper : NSObject 12 | 13 | + (nullable NSArray *)extendedAttributeNamesAtPath:(nonnull NSString *)path traverseLink:(BOOL)follow error:(NSError * _Nullable * _Nullable)err; 14 | + (BOOL)hasExtendedAttribute:(nonnull NSString *)name atPath:(nonnull NSString *)path traverseLink:(BOOL)follow error:(NSError * _Nullable * _Nullable)err; 15 | + (nullable NSData *)extendedAttribute:(nonnull NSString *)name atPath:(nonnull NSString *)path traverseLink:(BOOL)follow error:(NSError * _Nullable * _Nullable)err; 16 | + (BOOL)setExtendedAttribute:(nonnull NSString *)name value:(nonnull NSData *)value atPath:(nonnull NSString *)path traverseLink:(BOOL)follow overwrite:(BOOL)overwrite error:(NSError * _Nullable * _Nullable)err; 17 | + (BOOL)removeExtendedAttribute:(nonnull NSString *)name atPath:(nonnull NSString *)path traverseLink:(BOOL)follow error:(NSError * _Nullable * _Nullable)err; 18 | 19 | @end 20 | -------------------------------------------------------------------------------- /Example/Pods/SDWebImage/SDWebImage/Private/SDImageAssetManager.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 | #import "SDWebImageCompat.h" 11 | 12 | /// A Image-Asset manager to work like UIKit/AppKit's image cache behavior 13 | /// Apple parse the Asset Catalog compiled file(`Assets.car`) by CoreUI.framework, however it's a private framework and there are no other ways to directly get the data. So we just process the normal bundle files :) 14 | @interface SDImageAssetManager : NSObject 15 | 16 | @property (nonatomic, strong, nonnull) NSMapTable *imageTable; 17 | 18 | + (nonnull instancetype)sharedAssetManager; 19 | - (nullable NSString *)getPathForName:(nonnull NSString *)name bundle:(nonnull NSBundle *)bundle preferredScale:(nonnull CGFloat *)scale; 20 | - (nullable UIImage *)imageForName:(nonnull NSString *)name; 21 | - (void)storeImage:(nonnull UIImage *)image forName:(nonnull NSString *)name; 22 | 23 | @end 24 | -------------------------------------------------------------------------------- /Example/Pods/SDWebImage/SDWebImage/Private/SDImageCachesManagerOperation.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 | #import "SDWebImageCompat.h" 11 | 12 | /// This is used for operation management, but not for operation queue execute 13 | @interface SDImageCachesManagerOperation : NSOperation 14 | 15 | @property (nonatomic, assign, readonly) NSUInteger pendingCount; 16 | 17 | - (void)beginWithTotalCount:(NSUInteger)totalCount; 18 | - (void)completeOne; 19 | - (void)done; 20 | 21 | @end 22 | -------------------------------------------------------------------------------- /Example/Pods/SDWebImage/SDWebImage/Private/SDImageCachesManagerOperation.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 "SDImageCachesManagerOperation.h" 10 | #import "SDInternalMacros.h" 11 | 12 | @implementation SDImageCachesManagerOperation { 13 | SD_LOCK_DECLARE(_pendingCountLock); 14 | } 15 | 16 | @synthesize executing = _executing; 17 | @synthesize finished = _finished; 18 | @synthesize cancelled = _cancelled; 19 | @synthesize pendingCount = _pendingCount; 20 | 21 | - (instancetype)init { 22 | if (self = [super init]) { 23 | SD_LOCK_INIT(_pendingCountLock); 24 | _pendingCount = 0; 25 | } 26 | return self; 27 | } 28 | 29 | - (void)beginWithTotalCount:(NSUInteger)totalCount { 30 | self.executing = YES; 31 | self.finished = NO; 32 | _pendingCount = totalCount; 33 | } 34 | 35 | - (NSUInteger)pendingCount { 36 | SD_LOCK(_pendingCountLock); 37 | NSUInteger pendingCount = _pendingCount; 38 | SD_UNLOCK(_pendingCountLock); 39 | return pendingCount; 40 | } 41 | 42 | - (void)completeOne { 43 | SD_LOCK(_pendingCountLock); 44 | _pendingCount = _pendingCount > 0 ? _pendingCount - 1 : 0; 45 | SD_UNLOCK(_pendingCountLock); 46 | } 47 | 48 | - (void)cancel { 49 | self.cancelled = YES; 50 | [self reset]; 51 | } 52 | 53 | - (void)done { 54 | self.finished = YES; 55 | self.executing = NO; 56 | [self reset]; 57 | } 58 | 59 | - (void)reset { 60 | SD_LOCK(_pendingCountLock); 61 | _pendingCount = 0; 62 | SD_UNLOCK(_pendingCountLock); 63 | } 64 | 65 | - (void)setFinished:(BOOL)finished { 66 | [self willChangeValueForKey:@"isFinished"]; 67 | _finished = finished; 68 | [self didChangeValueForKey:@"isFinished"]; 69 | } 70 | 71 | - (void)setExecuting:(BOOL)executing { 72 | [self willChangeValueForKey:@"isExecuting"]; 73 | _executing = executing; 74 | [self didChangeValueForKey:@"isExecuting"]; 75 | } 76 | 77 | - (void)setCancelled:(BOOL)cancelled { 78 | [self willChangeValueForKey:@"isCancelled"]; 79 | _cancelled = cancelled; 80 | [self didChangeValueForKey:@"isCancelled"]; 81 | } 82 | 83 | @end 84 | -------------------------------------------------------------------------------- /Example/Pods/SDWebImage/SDWebImage/Private/SDImageFramePool.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 | #import "SDWebImageCompat.h" 11 | #import "SDImageCoder.h" 12 | 13 | NS_ASSUME_NONNULL_BEGIN 14 | 15 | /// A per-provider (provider means, AnimatedImage object) based frame pool, each player who use the same provider share the same frame buffer 16 | @interface SDImageFramePool : NSObject 17 | 18 | /// Register and return back a frame pool, also increase reference count 19 | + (instancetype)registerProvider:(id)provider; 20 | /// Unregister a frame pool, also decrease reference count, if zero dealloc the frame pool 21 | + (void)unregisterProvider:(id)provider; 22 | 23 | /// Prefetch the current frame, query using `frameAtIndex:` by caller to check whether finished. 24 | - (void)prefetchFrameAtIndex:(NSUInteger)index; 25 | 26 | /// Control the max buffer count for current frame pool, used for RAM/CPU balance, default unlimited 27 | @property (nonatomic, assign) NSUInteger maxBufferCount; 28 | /// Control the max concurrent fetch queue operation count, used for CPU balance, default 1 29 | @property (nonatomic, assign) NSUInteger maxConcurrentCount; 30 | 31 | // Frame Operations 32 | @property (nonatomic, readonly) NSUInteger currentFrameCount; 33 | - (nullable UIImage *)frameAtIndex:(NSUInteger)index; 34 | - (void)setFrame:(nullable UIImage *)frame atIndex:(NSUInteger)index; 35 | - (void)removeFrameAtIndex:(NSUInteger)index; 36 | - (void)removeAllFrames; 37 | 38 | NS_ASSUME_NONNULL_END 39 | 40 | @end 41 | -------------------------------------------------------------------------------- /Example/Pods/SDWebImage/SDWebImage/Private/SDImageIOAnimatedCoderInternal.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 | #import 11 | #import "SDImageIOAnimatedCoder.h" 12 | 13 | // AVFileTypeHEIC/AVFileTypeHEIF is defined in AVFoundation via iOS 11, we use this without import AVFoundation 14 | #define kSDUTTypeHEIC ((__bridge CFStringRef)@"public.heic") 15 | #define kSDUTTypeHEIF ((__bridge CFStringRef)@"public.heif") 16 | // HEIC Sequence (Animated Image) 17 | #define kSDUTTypeHEICS ((__bridge CFStringRef)@"public.heics") 18 | // kSDUTTypeWebP seems not defined in public UTI framework, Apple use the hardcode string, we define them :) 19 | #define kSDUTTypeWebP ((__bridge CFStringRef)@"org.webmproject.webp") 20 | 21 | #define kSDUTTypeImage ((__bridge CFStringRef)@"public.image") 22 | #define kSDUTTypeJPEG ((__bridge CFStringRef)@"public.jpeg") 23 | #define kSDUTTypePNG ((__bridge CFStringRef)@"public.png") 24 | #define kSDUTTypeTIFF ((__bridge CFStringRef)@"public.tiff") 25 | #define kSDUTTypeSVG ((__bridge CFStringRef)@"public.svg-image") 26 | #define kSDUTTypeGIF ((__bridge CFStringRef)@"com.compuserve.gif") 27 | #define kSDUTTypePDF ((__bridge CFStringRef)@"com.adobe.pdf") 28 | #define kSDUTTypeBMP ((__bridge CFStringRef)@"com.microsoft.bmp") 29 | #define kSDUTTypeRAW ((__bridge CFStringRef)@"public.camera-raw-image") 30 | 31 | @interface SDImageIOAnimatedCoder () 32 | 33 | + (NSTimeInterval)frameDurationAtIndex:(NSUInteger)index source:(nonnull CGImageSourceRef)source; 34 | + (NSUInteger)imageLoopCountWithSource:(nonnull CGImageSourceRef)source; 35 | + (nullable UIImage *)createFrameAtIndex:(NSUInteger)index source:(nonnull CGImageSourceRef)source scale:(CGFloat)scale preserveAspectRatio:(BOOL)preserveAspectRatio thumbnailSize:(CGSize)thumbnailSize lazyDecode:(BOOL)lazyDecode animatedImage:(BOOL)animatedImage; 36 | + (BOOL)canEncodeToFormat:(SDImageFormat)format; 37 | + (BOOL)canDecodeFromFormat:(SDImageFormat)format; 38 | 39 | @end 40 | -------------------------------------------------------------------------------- /Example/Pods/SDWebImage/SDWebImage/Private/SDInternalMacros.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 "SDInternalMacros.h" 10 | 11 | os_log_t sd_getDefaultLog(void) { 12 | static dispatch_once_t onceToken; 13 | static os_log_t log; 14 | dispatch_once(&onceToken, ^{ 15 | log = os_log_create("com.hackemist.SDWebImage", "Default"); 16 | }); 17 | return log; 18 | } 19 | 20 | void sd_executeCleanupBlock (__strong sd_cleanupBlock_t *block) { 21 | (*block)(); 22 | } 23 | -------------------------------------------------------------------------------- /Example/Pods/SDWebImage/SDWebImage/Private/SDWeakProxy.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 | #import "SDWebImageCompat.h" 11 | 12 | /// A weak proxy which forward all the message to the target 13 | @interface SDWeakProxy : NSProxy 14 | 15 | @property (nonatomic, weak, readonly, nullable) id target; 16 | 17 | - (nonnull instancetype)initWithTarget:(nonnull id)target; 18 | + (nonnull instancetype)proxyWithTarget:(nonnull id)target; 19 | 20 | @end 21 | -------------------------------------------------------------------------------- /Example/Pods/SDWebImage/SDWebImage/Private/SDWeakProxy.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 "SDWeakProxy.h" 10 | 11 | @implementation SDWeakProxy 12 | 13 | - (instancetype)initWithTarget:(id)target { 14 | _target = target; 15 | return self; 16 | } 17 | 18 | + (instancetype)proxyWithTarget:(id)target { 19 | return [[SDWeakProxy alloc] initWithTarget:target]; 20 | } 21 | 22 | - (id)forwardingTargetForSelector:(SEL)selector { 23 | return _target; 24 | } 25 | 26 | - (void)forwardInvocation:(NSInvocation *)invocation { 27 | void *null = NULL; 28 | [invocation setReturnValue:&null]; 29 | } 30 | 31 | - (NSMethodSignature *)methodSignatureForSelector:(SEL)selector { 32 | return [NSObject instanceMethodSignatureForSelector:@selector(init)]; 33 | } 34 | 35 | - (BOOL)respondsToSelector:(SEL)aSelector { 36 | return [_target respondsToSelector:aSelector]; 37 | } 38 | 39 | - (BOOL)isEqual:(id)object { 40 | return [_target isEqual:object]; 41 | } 42 | 43 | - (NSUInteger)hash { 44 | return [_target hash]; 45 | } 46 | 47 | - (Class)superclass { 48 | return [_target superclass]; 49 | } 50 | 51 | - (Class)class { 52 | return [_target class]; 53 | } 54 | 55 | - (BOOL)isKindOfClass:(Class)aClass { 56 | return [_target isKindOfClass:aClass]; 57 | } 58 | 59 | - (BOOL)isMemberOfClass:(Class)aClass { 60 | return [_target isMemberOfClass:aClass]; 61 | } 62 | 63 | - (BOOL)conformsToProtocol:(Protocol *)aProtocol { 64 | return [_target conformsToProtocol:aProtocol]; 65 | } 66 | 67 | - (BOOL)isProxy { 68 | return YES; 69 | } 70 | 71 | - (NSString *)description { 72 | return [_target description]; 73 | } 74 | 75 | - (NSString *)debugDescription { 76 | return [_target debugDescription]; 77 | } 78 | 79 | @end 80 | -------------------------------------------------------------------------------- /Example/Pods/SDWebImage/SDWebImage/Private/SDWebImageTransitionInternal.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 "SDWebImageCompat.h" 10 | 11 | #if SD_MAC 12 | 13 | #import 14 | 15 | /// Helper method for Core Animation transition 16 | FOUNDATION_EXPORT CAMediaTimingFunction * _Nullable SDTimingFunctionFromAnimationOptions(SDWebImageAnimationOptions options); 17 | FOUNDATION_EXPORT CATransition * _Nullable SDTransitionFromAnimationOptions(SDWebImageAnimationOptions options); 18 | 19 | #endif 20 | -------------------------------------------------------------------------------- /Example/Pods/SDWebImage/SDWebImage/Private/UIColor+SDHexString.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 "SDWebImageCompat.h" 10 | 11 | @interface UIColor (SDHexString) 12 | 13 | /** 14 | Convenience way to get hex string from color. The output should always be 32-bit RGBA hex string like `#00000000`. 15 | */ 16 | @property (nonatomic, copy, readonly, nonnull) NSString *sd_hexString; 17 | 18 | @end 19 | -------------------------------------------------------------------------------- /Example/Pods/SDWebImage/SDWebImage/Private/UIColor+SDHexString.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 "UIColor+SDHexString.h" 10 | 11 | @implementation UIColor (SDHexString) 12 | 13 | - (NSString *)sd_hexString { 14 | CGFloat red, green, blue, alpha; 15 | #if SD_UIKIT 16 | if (![self getRed:&red green:&green blue:&blue alpha:&alpha]) { 17 | [self getWhite:&red alpha:&alpha]; 18 | green = red; 19 | blue = red; 20 | } 21 | #else 22 | @try { 23 | [self getRed:&red green:&green blue:&blue alpha:&alpha]; 24 | } 25 | @catch (NSException *exception) { 26 | [self getWhite:&red alpha:&alpha]; 27 | green = red; 28 | blue = red; 29 | } 30 | #endif 31 | 32 | red = roundf(red * 255.f); 33 | green = roundf(green * 255.f); 34 | blue = roundf(blue * 255.f); 35 | alpha = roundf(alpha * 255.f); 36 | 37 | uint hex = ((uint)alpha << 24) | ((uint)red << 16) | ((uint)green << 8) | ((uint)blue); 38 | 39 | return [NSString stringWithFormat:@"#%08x", hex]; 40 | } 41 | 42 | @end 43 | -------------------------------------------------------------------------------- /Example/Pods/SDWebImage/WebImage/PrivacyInfo.xcprivacy: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | NSPrivacyTracking 6 | 7 | NSPrivacyCollectedDataTypes 8 | 9 | NSPrivacyTrackingDomains 10 | 11 | NSPrivacyAccessedAPITypes 12 | 13 | 14 | NSPrivacyAccessedAPIType 15 | NSPrivacyAccessedAPICategoryFileTimestamp 16 | NSPrivacyAccessedAPITypeReasons 17 | 18 | C617.1 19 | 20 | 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/JXPhotoBrowser/JXPhotoBrowser-Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | ${PODS_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 | 3.1.5 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | ${CURRENT_PROJECT_VERSION} 23 | NSPrincipalClass 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/JXPhotoBrowser/JXPhotoBrowser-dummy.m: -------------------------------------------------------------------------------- 1 | #import 2 | @interface PodsDummy_JXPhotoBrowser : NSObject 3 | @end 4 | @implementation PodsDummy_JXPhotoBrowser 5 | @end 6 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/JXPhotoBrowser/JXPhotoBrowser-prefix.pch: -------------------------------------------------------------------------------- 1 | #ifdef __OBJC__ 2 | #import 3 | #else 4 | #ifndef FOUNDATION_EXPORT 5 | #if defined(__cplusplus) 6 | #define FOUNDATION_EXPORT extern "C" 7 | #else 8 | #define FOUNDATION_EXPORT extern 9 | #endif 10 | #endif 11 | #endif 12 | 13 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/JXPhotoBrowser/JXPhotoBrowser-umbrella.h: -------------------------------------------------------------------------------- 1 | #ifdef __OBJC__ 2 | #import 3 | #else 4 | #ifndef FOUNDATION_EXPORT 5 | #if defined(__cplusplus) 6 | #define FOUNDATION_EXPORT extern "C" 7 | #else 8 | #define FOUNDATION_EXPORT extern 9 | #endif 10 | #endif 11 | #endif 12 | 13 | 14 | FOUNDATION_EXPORT double JXPhotoBrowserVersionNumber; 15 | FOUNDATION_EXPORT const unsigned char JXPhotoBrowserVersionString[]; 16 | 17 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/JXPhotoBrowser/JXPhotoBrowser.debug.xcconfig: -------------------------------------------------------------------------------- 1 | CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = NO 2 | CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/JXPhotoBrowser 3 | GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 4 | LIBRARY_SEARCH_PATHS = $(inherited) "${TOOLCHAIN_DIR}/usr/lib/swift/${PLATFORM_NAME}" /usr/lib/swift 5 | OTHER_SWIFT_FLAGS = $(inherited) -D COCOAPODS 6 | PODS_BUILD_DIR = ${BUILD_DIR} 7 | PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) 8 | PODS_DEVELOPMENT_LANGUAGE = ${DEVELOPMENT_LANGUAGE} 9 | PODS_ROOT = ${SRCROOT} 10 | PODS_TARGET_SRCROOT = ${PODS_ROOT}/../.. 11 | PODS_XCFRAMEWORKS_BUILD_DIR = $(PODS_CONFIGURATION_BUILD_DIR)/XCFrameworkIntermediates 12 | PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier} 13 | SKIP_INSTALL = YES 14 | USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES 15 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/JXPhotoBrowser/JXPhotoBrowser.modulemap: -------------------------------------------------------------------------------- 1 | framework module JXPhotoBrowser { 2 | umbrella header "JXPhotoBrowser-umbrella.h" 3 | 4 | export * 5 | module * { export * } 6 | } 7 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/JXPhotoBrowser/JXPhotoBrowser.release.xcconfig: -------------------------------------------------------------------------------- 1 | CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = NO 2 | CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/JXPhotoBrowser 3 | GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 4 | LIBRARY_SEARCH_PATHS = $(inherited) "${TOOLCHAIN_DIR}/usr/lib/swift/${PLATFORM_NAME}" /usr/lib/swift 5 | OTHER_SWIFT_FLAGS = $(inherited) -D COCOAPODS 6 | PODS_BUILD_DIR = ${BUILD_DIR} 7 | PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) 8 | PODS_DEVELOPMENT_LANGUAGE = ${DEVELOPMENT_LANGUAGE} 9 | PODS_ROOT = ${SRCROOT} 10 | PODS_TARGET_SRCROOT = ${PODS_ROOT}/../.. 11 | PODS_XCFRAMEWORKS_BUILD_DIR = $(PODS_CONFIGURATION_BUILD_DIR)/XCFrameworkIntermediates 12 | PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier} 13 | SKIP_INSTALL = YES 14 | USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES 15 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/JXPhotoBrowser/JXPhotoBrowser.xcconfig: -------------------------------------------------------------------------------- 1 | CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/JXPhotoBrowser 2 | GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 3 | OTHER_SWIFT_FLAGS = $(inherited) -D COCOAPODS 4 | PODS_BUILD_DIR = ${BUILD_DIR} 5 | PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) 6 | PODS_ROOT = ${SRCROOT} 7 | PODS_TARGET_SRCROOT = ${PODS_ROOT}/../.. 8 | PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier} 9 | SKIP_INSTALL = YES 10 | USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES 11 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/Kingfisher/Kingfisher-Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | ${PODS_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 | 7.10.2 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | ${CURRENT_PROJECT_VERSION} 23 | NSPrincipalClass 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/Kingfisher/Kingfisher-dummy.m: -------------------------------------------------------------------------------- 1 | #import 2 | @interface PodsDummy_Kingfisher : NSObject 3 | @end 4 | @implementation PodsDummy_Kingfisher 5 | @end 6 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/Kingfisher/Kingfisher-prefix.pch: -------------------------------------------------------------------------------- 1 | #ifdef __OBJC__ 2 | #import 3 | #else 4 | #ifndef FOUNDATION_EXPORT 5 | #if defined(__cplusplus) 6 | #define FOUNDATION_EXPORT extern "C" 7 | #else 8 | #define FOUNDATION_EXPORT extern 9 | #endif 10 | #endif 11 | #endif 12 | 13 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/Kingfisher/Kingfisher-umbrella.h: -------------------------------------------------------------------------------- 1 | #ifdef __OBJC__ 2 | #import 3 | #else 4 | #ifndef FOUNDATION_EXPORT 5 | #if defined(__cplusplus) 6 | #define FOUNDATION_EXPORT extern "C" 7 | #else 8 | #define FOUNDATION_EXPORT extern 9 | #endif 10 | #endif 11 | #endif 12 | 13 | 14 | FOUNDATION_EXPORT double KingfisherVersionNumber; 15 | FOUNDATION_EXPORT const unsigned char KingfisherVersionString[]; 16 | 17 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/Kingfisher/Kingfisher.debug.xcconfig: -------------------------------------------------------------------------------- 1 | CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = NO 2 | CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/Kingfisher 3 | GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 4 | LIBRARY_SEARCH_PATHS = $(inherited) "${TOOLCHAIN_DIR}/usr/lib/swift/${PLATFORM_NAME}" /usr/lib/swift 5 | OTHER_LDFLAGS = $(inherited) -framework "Accelerate" -framework "CFNetwork" -weak_framework "Combine" -weak_framework "SwiftUI" 6 | OTHER_SWIFT_FLAGS = $(inherited) -D COCOAPODS 7 | PODS_BUILD_DIR = ${BUILD_DIR} 8 | PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) 9 | PODS_DEVELOPMENT_LANGUAGE = ${DEVELOPMENT_LANGUAGE} 10 | PODS_ROOT = ${SRCROOT} 11 | PODS_TARGET_SRCROOT = ${PODS_ROOT}/Kingfisher 12 | PODS_XCFRAMEWORKS_BUILD_DIR = $(PODS_CONFIGURATION_BUILD_DIR)/XCFrameworkIntermediates 13 | PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier} 14 | SKIP_INSTALL = YES 15 | USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES 16 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/Kingfisher/Kingfisher.modulemap: -------------------------------------------------------------------------------- 1 | framework module Kingfisher { 2 | umbrella header "Kingfisher-umbrella.h" 3 | 4 | export * 5 | module * { export * } 6 | } 7 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/Kingfisher/Kingfisher.release.xcconfig: -------------------------------------------------------------------------------- 1 | CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = NO 2 | CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/Kingfisher 3 | GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 4 | LIBRARY_SEARCH_PATHS = $(inherited) "${TOOLCHAIN_DIR}/usr/lib/swift/${PLATFORM_NAME}" /usr/lib/swift 5 | OTHER_LDFLAGS = $(inherited) -framework "Accelerate" -framework "CFNetwork" -weak_framework "Combine" -weak_framework "SwiftUI" 6 | OTHER_SWIFT_FLAGS = $(inherited) -D COCOAPODS 7 | PODS_BUILD_DIR = ${BUILD_DIR} 8 | PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) 9 | PODS_DEVELOPMENT_LANGUAGE = ${DEVELOPMENT_LANGUAGE} 10 | PODS_ROOT = ${SRCROOT} 11 | PODS_TARGET_SRCROOT = ${PODS_ROOT}/Kingfisher 12 | PODS_XCFRAMEWORKS_BUILD_DIR = $(PODS_CONFIGURATION_BUILD_DIR)/XCFrameworkIntermediates 13 | PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier} 14 | SKIP_INSTALL = YES 15 | USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES 16 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/Kingfisher/Kingfisher.xcconfig: -------------------------------------------------------------------------------- 1 | CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/Kingfisher 2 | GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 3 | OTHER_LDFLAGS = $(inherited) -framework "Accelerate" -framework "CFNetwork" 4 | OTHER_SWIFT_FLAGS = $(inherited) -D COCOAPODS 5 | PODS_BUILD_DIR = ${BUILD_DIR} 6 | PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) 7 | PODS_ROOT = ${SRCROOT} 8 | PODS_TARGET_SRCROOT = ${PODS_ROOT}/Kingfisher 9 | PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier} 10 | SKIP_INSTALL = YES 11 | USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES 12 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/Kingfisher/ResourceBundle-Kingfisher-Kingfisher-Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | ${PODS_DEVELOPMENT_LANGUAGE} 7 | CFBundleIdentifier 8 | ${PRODUCT_BUNDLE_IDENTIFIER} 9 | CFBundleInfoDictionaryVersion 10 | 6.0 11 | CFBundleName 12 | ${PRODUCT_NAME} 13 | CFBundlePackageType 14 | BNDL 15 | CFBundleShortVersionString 16 | 7.10.2 17 | CFBundleSignature 18 | ???? 19 | CFBundleVersion 20 | 1 21 | NSPrincipalClass 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/Pods-Example/Pods-Example-Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | ${PODS_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.0.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | ${CURRENT_PROJECT_VERSION} 23 | NSPrincipalClass 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/Pods-Example/Pods-Example-dummy.m: -------------------------------------------------------------------------------- 1 | #import 2 | @interface PodsDummy_Pods_Example : NSObject 3 | @end 4 | @implementation PodsDummy_Pods_Example 5 | @end 6 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/Pods-Example/Pods-Example-frameworks-Debug-input-files.xcfilelist: -------------------------------------------------------------------------------- 1 | ${PODS_ROOT}/Target Support Files/Pods-Example/Pods-Example-frameworks.sh 2 | ${BUILT_PRODUCTS_DIR}/JXPhotoBrowser/JXPhotoBrowser.framework 3 | ${BUILT_PRODUCTS_DIR}/Kingfisher/Kingfisher.framework 4 | ${BUILT_PRODUCTS_DIR}/SDWebImage/SDWebImage.framework -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/Pods-Example/Pods-Example-frameworks-Debug-output-files.xcfilelist: -------------------------------------------------------------------------------- 1 | ${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/JXPhotoBrowser.framework 2 | ${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/Kingfisher.framework 3 | ${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/SDWebImage.framework -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/Pods-Example/Pods-Example-frameworks-Release-input-files.xcfilelist: -------------------------------------------------------------------------------- 1 | ${PODS_ROOT}/Target Support Files/Pods-Example/Pods-Example-frameworks.sh 2 | ${BUILT_PRODUCTS_DIR}/JXPhotoBrowser/JXPhotoBrowser.framework 3 | ${BUILT_PRODUCTS_DIR}/Kingfisher/Kingfisher.framework 4 | ${BUILT_PRODUCTS_DIR}/SDWebImage/SDWebImage.framework -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/Pods-Example/Pods-Example-frameworks-Release-output-files.xcfilelist: -------------------------------------------------------------------------------- 1 | ${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/JXPhotoBrowser.framework 2 | ${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/Kingfisher.framework 3 | ${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/SDWebImage.framework -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/Pods-Example/Pods-Example-umbrella.h: -------------------------------------------------------------------------------- 1 | #ifdef __OBJC__ 2 | #import 3 | #else 4 | #ifndef FOUNDATION_EXPORT 5 | #if defined(__cplusplus) 6 | #define FOUNDATION_EXPORT extern "C" 7 | #else 8 | #define FOUNDATION_EXPORT extern 9 | #endif 10 | #endif 11 | #endif 12 | 13 | 14 | FOUNDATION_EXPORT double Pods_ExampleVersionNumber; 15 | FOUNDATION_EXPORT const unsigned char Pods_ExampleVersionString[]; 16 | 17 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/Pods-Example/Pods-Example.debug.xcconfig: -------------------------------------------------------------------------------- 1 | ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES 2 | CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = NO 3 | FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/JXPhotoBrowser" "${PODS_CONFIGURATION_BUILD_DIR}/Kingfisher" "${PODS_CONFIGURATION_BUILD_DIR}/SDWebImage" 4 | GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 5 | HEADER_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/JXPhotoBrowser/JXPhotoBrowser.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/Kingfisher/Kingfisher.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/SDWebImage/SDWebImage.framework/Headers" 6 | LD_RUNPATH_SEARCH_PATHS = $(inherited) /usr/lib/swift '@executable_path/Frameworks' '@loader_path/Frameworks' 7 | LIBRARY_SEARCH_PATHS = $(inherited) "${TOOLCHAIN_DIR}/usr/lib/swift/${PLATFORM_NAME}" /usr/lib/swift 8 | OTHER_LDFLAGS = $(inherited) -framework "Accelerate" -framework "CFNetwork" -framework "ImageIO" -framework "JXPhotoBrowser" -framework "Kingfisher" -framework "SDWebImage" -weak_framework "Combine" -weak_framework "SwiftUI" 9 | OTHER_SWIFT_FLAGS = $(inherited) -D COCOAPODS 10 | PODS_BUILD_DIR = ${BUILD_DIR} 11 | PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) 12 | PODS_PODFILE_DIR_PATH = ${SRCROOT}/. 13 | PODS_ROOT = ${SRCROOT}/Pods 14 | PODS_XCFRAMEWORKS_BUILD_DIR = $(PODS_CONFIGURATION_BUILD_DIR)/XCFrameworkIntermediates 15 | USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES 16 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/Pods-Example/Pods-Example.modulemap: -------------------------------------------------------------------------------- 1 | framework module Pods_Example { 2 | umbrella header "Pods-Example-umbrella.h" 3 | 4 | export * 5 | module * { export * } 6 | } 7 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/Pods-Example/Pods-Example.release.xcconfig: -------------------------------------------------------------------------------- 1 | ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES 2 | CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = NO 3 | FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/JXPhotoBrowser" "${PODS_CONFIGURATION_BUILD_DIR}/Kingfisher" "${PODS_CONFIGURATION_BUILD_DIR}/SDWebImage" 4 | GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 5 | HEADER_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/JXPhotoBrowser/JXPhotoBrowser.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/Kingfisher/Kingfisher.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/SDWebImage/SDWebImage.framework/Headers" 6 | LD_RUNPATH_SEARCH_PATHS = $(inherited) /usr/lib/swift '@executable_path/Frameworks' '@loader_path/Frameworks' 7 | LIBRARY_SEARCH_PATHS = $(inherited) "${TOOLCHAIN_DIR}/usr/lib/swift/${PLATFORM_NAME}" /usr/lib/swift 8 | OTHER_LDFLAGS = $(inherited) -framework "Accelerate" -framework "CFNetwork" -framework "ImageIO" -framework "JXPhotoBrowser" -framework "Kingfisher" -framework "SDWebImage" -weak_framework "Combine" -weak_framework "SwiftUI" 9 | OTHER_SWIFT_FLAGS = $(inherited) -D COCOAPODS 10 | PODS_BUILD_DIR = ${BUILD_DIR} 11 | PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) 12 | PODS_PODFILE_DIR_PATH = ${SRCROOT}/. 13 | PODS_ROOT = ${SRCROOT}/Pods 14 | PODS_XCFRAMEWORKS_BUILD_DIR = $(PODS_CONFIGURATION_BUILD_DIR)/XCFrameworkIntermediates 15 | USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES 16 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/SDWebImage/ResourceBundle-SDWebImage-SDWebImage-Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | ${PODS_DEVELOPMENT_LANGUAGE} 7 | CFBundleIdentifier 8 | ${PRODUCT_BUNDLE_IDENTIFIER} 9 | CFBundleInfoDictionaryVersion 10 | 6.0 11 | CFBundleName 12 | ${PRODUCT_NAME} 13 | CFBundlePackageType 14 | BNDL 15 | CFBundleShortVersionString 16 | 5.18.10 17 | CFBundleSignature 18 | ???? 19 | CFBundleVersion 20 | 1 21 | NSPrincipalClass 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/SDWebImage/SDWebImage-Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | ${PODS_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 | 5.18.10 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | ${CURRENT_PROJECT_VERSION} 23 | NSPrincipalClass 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/SDWebImage/SDWebImage-dummy.m: -------------------------------------------------------------------------------- 1 | #import 2 | @interface PodsDummy_SDWebImage : NSObject 3 | @end 4 | @implementation PodsDummy_SDWebImage 5 | @end 6 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/SDWebImage/SDWebImage-prefix.pch: -------------------------------------------------------------------------------- 1 | #ifdef __OBJC__ 2 | #import 3 | #else 4 | #ifndef FOUNDATION_EXPORT 5 | #if defined(__cplusplus) 6 | #define FOUNDATION_EXPORT extern "C" 7 | #else 8 | #define FOUNDATION_EXPORT extern 9 | #endif 10 | #endif 11 | #endif 12 | 13 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/SDWebImage/SDWebImage-umbrella.h: -------------------------------------------------------------------------------- 1 | #ifdef __OBJC__ 2 | #import 3 | #else 4 | #ifndef FOUNDATION_EXPORT 5 | #if defined(__cplusplus) 6 | #define FOUNDATION_EXPORT extern "C" 7 | #else 8 | #define FOUNDATION_EXPORT extern 9 | #endif 10 | #endif 11 | #endif 12 | 13 | #import "NSButton+WebCache.h" 14 | #import "NSData+ImageContentType.h" 15 | #import "NSImage+Compatibility.h" 16 | #import "SDAnimatedImage.h" 17 | #import "SDAnimatedImagePlayer.h" 18 | #import "SDAnimatedImageRep.h" 19 | #import "SDAnimatedImageView+WebCache.h" 20 | #import "SDAnimatedImageView.h" 21 | #import "SDCallbackQueue.h" 22 | #import "SDDiskCache.h" 23 | #import "SDGraphicsImageRenderer.h" 24 | #import "SDImageAPNGCoder.h" 25 | #import "SDImageAWebPCoder.h" 26 | #import "SDImageCache.h" 27 | #import "SDImageCacheConfig.h" 28 | #import "SDImageCacheDefine.h" 29 | #import "SDImageCachesManager.h" 30 | #import "SDImageCoder.h" 31 | #import "SDImageCoderHelper.h" 32 | #import "SDImageCodersManager.h" 33 | #import "SDImageFrame.h" 34 | #import "SDImageGIFCoder.h" 35 | #import "SDImageGraphics.h" 36 | #import "SDImageHEICCoder.h" 37 | #import "SDImageIOAnimatedCoder.h" 38 | #import "SDImageIOCoder.h" 39 | #import "SDImageLoader.h" 40 | #import "SDImageLoadersManager.h" 41 | #import "SDImageTransformer.h" 42 | #import "SDMemoryCache.h" 43 | #import "SDWebImageCacheKeyFilter.h" 44 | #import "SDWebImageCacheSerializer.h" 45 | #import "SDWebImageCompat.h" 46 | #import "SDWebImageDefine.h" 47 | #import "SDWebImageDownloader.h" 48 | #import "SDWebImageDownloaderConfig.h" 49 | #import "SDWebImageDownloaderDecryptor.h" 50 | #import "SDWebImageDownloaderOperation.h" 51 | #import "SDWebImageDownloaderRequestModifier.h" 52 | #import "SDWebImageDownloaderResponseModifier.h" 53 | #import "SDWebImageError.h" 54 | #import "SDWebImageIndicator.h" 55 | #import "SDWebImageManager.h" 56 | #import "SDWebImageOperation.h" 57 | #import "SDWebImageOptionsProcessor.h" 58 | #import "SDWebImagePrefetcher.h" 59 | #import "SDWebImageTransition.h" 60 | #import "UIButton+WebCache.h" 61 | #import "UIImage+ExtendedCacheData.h" 62 | #import "UIImage+ForceDecode.h" 63 | #import "UIImage+GIF.h" 64 | #import "UIImage+MemoryCacheCost.h" 65 | #import "UIImage+Metadata.h" 66 | #import "UIImage+MultiFormat.h" 67 | #import "UIImage+Transform.h" 68 | #import "UIImageView+HighlightedWebCache.h" 69 | #import "UIImageView+WebCache.h" 70 | #import "UIView+WebCache.h" 71 | #import "UIView+WebCacheOperation.h" 72 | #import "UIView+WebCacheState.h" 73 | #import "SDWebImage.h" 74 | 75 | FOUNDATION_EXPORT double SDWebImageVersionNumber; 76 | FOUNDATION_EXPORT const unsigned char SDWebImageVersionString[]; 77 | 78 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/SDWebImage/SDWebImage.debug.xcconfig: -------------------------------------------------------------------------------- 1 | CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = NO 2 | CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/SDWebImage 3 | DERIVE_MACCATALYST_PRODUCT_BUNDLE_IDENTIFIER = NO 4 | GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 5 | OTHER_LDFLAGS = $(inherited) -framework "ImageIO" 6 | PODS_BUILD_DIR = ${BUILD_DIR} 7 | PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) 8 | PODS_DEVELOPMENT_LANGUAGE = ${DEVELOPMENT_LANGUAGE} 9 | PODS_ROOT = ${SRCROOT} 10 | PODS_TARGET_SRCROOT = ${PODS_ROOT}/SDWebImage 11 | PODS_XCFRAMEWORKS_BUILD_DIR = $(PODS_CONFIGURATION_BUILD_DIR)/XCFrameworkIntermediates 12 | PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier} 13 | SKIP_INSTALL = YES 14 | SUPPORTS_MACCATALYST = YES 15 | USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES 16 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/SDWebImage/SDWebImage.modulemap: -------------------------------------------------------------------------------- 1 | framework module SDWebImage { 2 | umbrella header "SDWebImage-umbrella.h" 3 | 4 | export * 5 | module * { export * } 6 | } 7 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/SDWebImage/SDWebImage.release.xcconfig: -------------------------------------------------------------------------------- 1 | CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = NO 2 | CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/SDWebImage 3 | DERIVE_MACCATALYST_PRODUCT_BUNDLE_IDENTIFIER = NO 4 | GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 5 | OTHER_LDFLAGS = $(inherited) -framework "ImageIO" 6 | PODS_BUILD_DIR = ${BUILD_DIR} 7 | PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) 8 | PODS_DEVELOPMENT_LANGUAGE = ${DEVELOPMENT_LANGUAGE} 9 | PODS_ROOT = ${SRCROOT} 10 | PODS_TARGET_SRCROOT = ${PODS_ROOT}/SDWebImage 11 | PODS_XCFRAMEWORKS_BUILD_DIR = $(PODS_CONFIGURATION_BUILD_DIR)/XCFrameworkIntermediates 12 | PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier} 13 | SKIP_INSTALL = YES 14 | SUPPORTS_MACCATALYST = YES 15 | USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES 16 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/SDWebImage/SDWebImage.xcconfig: -------------------------------------------------------------------------------- 1 | CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/SDWebImage 2 | DERIVE_MACCATALYST_PRODUCT_BUNDLE_IDENTIFIER = NO 3 | GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 4 | OTHER_LDFLAGS = $(inherited) -framework "ImageIO" 5 | PODS_BUILD_DIR = ${BUILD_DIR} 6 | PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) 7 | PODS_ROOT = ${SRCROOT} 8 | PODS_TARGET_SRCROOT = ${PODS_ROOT}/SDWebImage 9 | PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier} 10 | SKIP_INSTALL = YES 11 | SUPPORTS_MACCATALYST = YES 12 | USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES 13 | -------------------------------------------------------------------------------- /Example/Sources/AppIconScreenShot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JiongXing/PhotoBrowser/69c5212485b54eeb0eaaa5f77dde1ebb787a51d0/Example/Sources/AppIconScreenShot.png -------------------------------------------------------------------------------- /Example/Sources/图片浏览器.sketch: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JiongXing/PhotoBrowser/69c5212485b54eeb0eaaa5f77dde1ebb787a51d0/Example/Sources/图片浏览器.sketch -------------------------------------------------------------------------------- /JXPhotoBrowser.podspec: -------------------------------------------------------------------------------- 1 | 2 | Pod::Spec.new do |s| 3 | s.name = 'JXPhotoBrowser' 4 | s.version = '3.1.5' 5 | s.summary = 'Elegant photo browser in Swift.' 6 | s.description = 'Elegant photo browser in Swift. Inspired by WeChat.' 7 | 8 | s.homepage = 'https://github.com/JiongXing/PhotoBrowser' 9 | s.license = { :type => 'MIT', :file => 'LICENSE' } 10 | s.author = { 'JiongXing' => 'liangjiongxing@qq.com' } 11 | s.source = { :git => 'https://github.com/JiongXing/PhotoBrowser.git', :tag => s.version.to_s } 12 | 13 | s.ios.deployment_target = '11.0' 14 | s.swift_version = '5.0' 15 | s.source_files = 'Sources/JXPhotoBrowser/*' 16 | 17 | end 18 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2017-2019 LiangJiongXing 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 | -------------------------------------------------------------------------------- /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: "JXPhotoBrowser", 8 | products: [ 9 | // Products define the executables and libraries produced by a package, and make them visible to other packages. 10 | .library( 11 | name: "JXPhotoBrowser", 12 | targets: ["JXPhotoBrowser"]), 13 | ], 14 | dependencies: [ 15 | // Dependencies declare other packages that this package depends on. 16 | // .package(url: /* package url */, from: "1.0.0"), 17 | ], 18 | targets: [ 19 | // Targets are the basic building blocks of a package. A target can define a module or a test suite. 20 | // Targets can depend on other targets in this package, and on products in packages which this package depends on. 21 | .target( 22 | name: "JXPhotoBrowser", 23 | dependencies: []), 24 | ] 25 | ) 26 | -------------------------------------------------------------------------------- /Sources/JXPhotoBrowser/JXPhotoBrowserAnimatedTransitioning.swift: -------------------------------------------------------------------------------- 1 | // 2 | // JXPhotoBrowserAnimatedTransitioning.swift 3 | // JXPhotoBrowser 4 | // 5 | // Created by JiongXing on 2019/11/25. 6 | // Copyright © 2019 JiongXing. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | public protocol JXPhotoBrowserAnimatedTransitioning: UIViewControllerAnimatedTransitioning { 12 | var isForShow: Bool { get set } 13 | var photoBrowser: JXPhotoBrowser? { get set } 14 | var isNavigationAnimation: Bool { get set } 15 | } 16 | 17 | private var isForShowKey: Void? 18 | private var photoBrowserKey: Void? 19 | 20 | extension JXPhotoBrowserAnimatedTransitioning { 21 | 22 | public var isForShow: Bool { 23 | get { 24 | if let value = objc_getAssociatedObject(self, &isForShowKey) as? Bool { 25 | return value 26 | } 27 | return true 28 | } 29 | set { 30 | objc_setAssociatedObject(self, &isForShowKey, newValue, .OBJC_ASSOCIATION_ASSIGN) 31 | } 32 | } 33 | 34 | public weak var photoBrowser: JXPhotoBrowser? { 35 | get { 36 | if let wrapper = objc_getAssociatedObject(self, &photoBrowserKey) as? JXPhotoBrowserWeakAssociationWrapper { 37 | return wrapper.target as? JXPhotoBrowser 38 | } 39 | return nil 40 | } 41 | set { 42 | let wrapper = JXPhotoBrowserWeakAssociationWrapper(target: newValue) 43 | objc_setAssociatedObject(self, &photoBrowserKey, wrapper, .OBJC_ASSOCIATION_RETAIN_NONATOMIC) 44 | } 45 | } 46 | 47 | public var isNavigationAnimation: Bool { 48 | get { return false } 49 | set { } 50 | } 51 | 52 | public func snapshot(with view: UIView) -> UIView? { 53 | let snapshot = view.snapshotView(afterScreenUpdates: true) 54 | return snapshot 55 | } 56 | } 57 | 58 | struct JXPhotoBrowserWeakAssociationWrapper { 59 | 60 | weak var target: AnyObject? 61 | 62 | init(target: AnyObject? = nil) { 63 | self.target = target 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /Sources/JXPhotoBrowser/JXPhotoBrowserCell.swift: -------------------------------------------------------------------------------- 1 | // 2 | // JXPhotoBrowserCell.swift 3 | // JXPhotoBrowser 4 | // 5 | // Created by JiongXing on 2019/11/26. 6 | // Copyright © 2019 JiongXing. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | public protocol JXPhotoBrowserCell: UIView { 12 | 13 | static func generate(with browser: JXPhotoBrowser) -> Self 14 | } 15 | -------------------------------------------------------------------------------- /Sources/JXPhotoBrowser/JXPhotoBrowserDefaultPageIndicator.swift: -------------------------------------------------------------------------------- 1 | // 2 | // JXPhotoBrowserDefaultPageIndicator.swift 3 | // JXPhotoBrowser 4 | // 5 | // Created by JiongXing on 2019/11/25. 6 | // Copyright © 2019 JiongXing. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | open class JXPhotoBrowserDefaultPageIndicator: UIPageControl, JXPhotoBrowserPageIndicator { 12 | 13 | /// 页码与底部的距离 14 | open lazy var bottomPadding: CGFloat = { 15 | if #available(iOS 11.0, *) { 16 | let window = UIApplication.shared.windows.filter { $0.isKeyWindow }.first 17 | if let window = window, window.safeAreaInsets.bottom > 0 { 18 | return 20 19 | } 20 | } 21 | return 15 22 | }() 23 | 24 | open func setup(with browser: JXPhotoBrowser) { 25 | isEnabled = false 26 | } 27 | 28 | open func reloadData(numberOfItems: Int, pageIndex: Int) { 29 | numberOfPages = numberOfItems 30 | currentPage = min(pageIndex, numberOfPages - 1) 31 | sizeToFit() 32 | isHidden = numberOfPages <= 1 33 | if let view = superview { 34 | center.x = view.bounds.width / 2 35 | frame.origin.y = view.bounds.maxY - bottomPadding - bounds.height 36 | } 37 | } 38 | 39 | open func didChanged(pageIndex: Int) { 40 | currentPage = pageIndex 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /Sources/JXPhotoBrowser/JXPhotoBrowserFadeAnimator.swift: -------------------------------------------------------------------------------- 1 | // 2 | // JXPhotoBrowserFadeAnimator.swift 3 | // JXPhotoBrowser 4 | // 5 | // Created by JiongXing on 2019/11/25. 6 | // Copyright © 2019 JiongXing. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | open class JXPhotoBrowserFadeAnimator: NSObject, JXPhotoBrowserAnimatedTransitioning { 12 | 13 | open var showDuration: TimeInterval = 0.25 14 | 15 | open var dismissDuration: TimeInterval = 0.25 16 | 17 | public var isNavigationAnimation: Bool = false 18 | 19 | public func transitionDuration(using transitionContext: UIViewControllerContextTransitioning?) -> TimeInterval { 20 | return isForShow ? showDuration : dismissDuration 21 | } 22 | 23 | public func animateTransition(using transitionContext: UIViewControllerContextTransitioning) { 24 | guard let browser = photoBrowser else { 25 | transitionContext.completeTransition(!transitionContext.transitionWasCancelled) 26 | return 27 | } 28 | if isNavigationAnimation, isForShow, 29 | let fromView = transitionContext.view(forKey: .from), 30 | let fromViewSnapshot = snapshot(with: fromView), 31 | let toView = transitionContext.view(forKey: .to) { 32 | toView.insertSubview(fromViewSnapshot, at: 0) 33 | } 34 | if isForShow { 35 | browser.maskView.alpha = 0 36 | browser.browserView.alpha = 0 37 | if let toView = transitionContext.view(forKey: .to) { 38 | transitionContext.containerView.addSubview(toView) 39 | } 40 | } else { 41 | if isNavigationAnimation, 42 | let fromView = transitionContext.view(forKey: .from), let toView = transitionContext.view(forKey: .to) { 43 | transitionContext.containerView.insertSubview(toView, belowSubview: fromView) 44 | } 45 | } 46 | browser.browserView.isHidden = true 47 | UIView.animate(withDuration: transitionDuration(using: transitionContext), animations: { 48 | browser.browserView.isHidden = false 49 | browser.maskView.alpha = self.isForShow ? 1.0 : 0 50 | browser.browserView.alpha = self.isForShow ? 1.0 : 0 51 | }) { _ in 52 | transitionContext.completeTransition(!transitionContext.transitionWasCancelled) 53 | } 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /Sources/JXPhotoBrowser/JXPhotoBrowserImageView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // JXPhotoBrowserImageView.swift 3 | // JXPhotoBrowser 4 | // 5 | // Created by 梁大红 on 2021/2/19. 6 | // Copyright © 2021 JiongXing. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | open class JXPhotoBrowserImageView: UIImageView { 12 | 13 | public var imageDidChangedHandler: (() -> ())? 14 | 15 | public override var image: UIImage? { 16 | didSet { 17 | imageDidChangedHandler?() 18 | } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /Sources/JXPhotoBrowser/JXPhotoBrowserLog.swift: -------------------------------------------------------------------------------- 1 | // 2 | // JXPhotoBrowserLog.swift 3 | // JXPhotoBrowser 4 | // 5 | // Created by JiongXing on 2019/11/12. 6 | // Copyright © 2019 JiongXing. All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | public struct JXPhotoBrowserLog { 12 | 13 | /// 日志重要程度等级 14 | public enum Level: Int { 15 | case low = 0 16 | case middle 17 | case high 18 | case forbidden 19 | } 20 | 21 | /// 允许输出日志的最低等级。`forbidden`为禁止所有日志 22 | public static var level: Level = .forbidden 23 | 24 | public static func low(_ item: @autoclosure () -> Any) { 25 | if level.rawValue <= Level.low.rawValue { 26 | print("[JXPhotoBrowser] [low]", item()) 27 | } 28 | } 29 | 30 | public static func middle(_ item: @autoclosure () -> Any) { 31 | if level.rawValue <= Level.middle.rawValue { 32 | print("[JXPhotoBrowser] [middle]", item()) 33 | } 34 | } 35 | 36 | public static func high(_ item: @autoclosure () -> Any) { 37 | if level.rawValue <= Level.high.rawValue { 38 | print("[JXPhotoBrowser] [high]", item()) 39 | } 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /Sources/JXPhotoBrowser/JXPhotoBrowserNoneAnimator.swift: -------------------------------------------------------------------------------- 1 | // 2 | // JXPhotoBrowserNoneAnimator.swift 3 | // JXPhotoBrowser 4 | // 5 | // Created by JiongXing on 2019/11/26. 6 | // Copyright © 2019 JiongXing. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | /// 使用本类以实现不出现转场动画的需求 12 | open class JXPhotoBrowserNoneAnimator: JXPhotoBrowserFadeAnimator { 13 | 14 | public override init() { 15 | super.init() 16 | showDuration = 0 17 | dismissDuration = 0 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /Sources/JXPhotoBrowser/JXPhotoBrowserNumberPageIndicator.swift: -------------------------------------------------------------------------------- 1 | // 2 | // JXPhotoBrowserNumberPageIndicator.swift 3 | // JXPhotoBrowser 4 | // 5 | // Created by JiongXing on 2019/11/25. 6 | // Copyright © 2019 JiongXing. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | open class JXPhotoBrowserNumberPageIndicator: UILabel, JXPhotoBrowserPageIndicator { 12 | 13 | /// 页码与顶部的距离 14 | open lazy var topPadding: CGFloat = { 15 | if #available(iOS 11.0, *) { 16 | let window = UIApplication.shared.windows.filter { $0.isKeyWindow }.first 17 | if let window = window { 18 | return window.safeAreaInsets.top 19 | } 20 | } 21 | return 20 22 | }() 23 | 24 | public convenience init() { 25 | self.init(frame: .zero) 26 | } 27 | 28 | public override init(frame: CGRect) { 29 | super.init(frame: frame) 30 | config() 31 | } 32 | 33 | required public init?(coder: NSCoder) { 34 | super.init(coder: coder) 35 | config() 36 | } 37 | 38 | private func config() { 39 | font = UIFont.systemFont(ofSize: 17) 40 | textAlignment = .center 41 | textColor = UIColor.white 42 | backgroundColor = UIColor(red: 0, green: 0, blue: 0, alpha: 0.4) 43 | layer.masksToBounds = true 44 | } 45 | 46 | public func setup(with browser: JXPhotoBrowser) { 47 | 48 | } 49 | 50 | private var total: Int = 0 51 | 52 | public func reloadData(numberOfItems: Int, pageIndex: Int) { 53 | total = numberOfItems 54 | text = "\(pageIndex + 1) / \(total)" 55 | sizeToFit() 56 | frame.size.width += frame.height 57 | layer.cornerRadius = frame.height / 2 58 | if let view = superview { 59 | center.x = view.bounds.width / 2 60 | frame.origin.y = topPadding 61 | } 62 | isHidden = numberOfItems <= 1 63 | } 64 | 65 | public func didChanged(pageIndex: Int) { 66 | text = "\(pageIndex + 1) / \(total)" 67 | } 68 | 69 | } 70 | -------------------------------------------------------------------------------- /Sources/JXPhotoBrowser/JXPhotoBrowserPageIndicator.swift: -------------------------------------------------------------------------------- 1 | // 2 | // JXPhotoBrowserPageIndicator.swift 3 | // JXPhotoBrowser 4 | // 5 | // Created by JiongXing on 2019/11/25. 6 | // Copyright © 2019 JiongXing. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | public protocol JXPhotoBrowserPageIndicator: UIView { 12 | 13 | func setup(with browser: JXPhotoBrowser) 14 | 15 | func reloadData(numberOfItems: Int, pageIndex: Int) 16 | 17 | func didChanged(pageIndex: Int) 18 | } 19 | -------------------------------------------------------------------------------- /Sources/JXPhotoBrowser/JXPhotoBrowserZoomSupportedCell.swift: -------------------------------------------------------------------------------- 1 | // 2 | // JXPhotoBrowserZoomSupportedCell.swift 3 | // JXPhotoBrowser 4 | // 5 | // Created by JiongXing on 2019/11/22. 6 | // Copyright © 2019 JiongXing. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | /// 在Zoom转场时使用 12 | public protocol JXPhotoBrowserZoomSupportedCell: UIView { 13 | /// 内容视图 14 | var showContentView: UIView { get } 15 | } 16 | -------------------------------------------------------------------------------- /SwiftPMExample/SwiftPMExample.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /SwiftPMExample/SwiftPMExample.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /SwiftPMExample/SwiftPMExample.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved: -------------------------------------------------------------------------------- 1 | { 2 | "object": { 3 | "pins": [ 4 | { 5 | "package": "JXPhotoBrowser", 6 | "repositoryURL": "https://github.com/JiongXing/PhotoBrowser", 7 | "state": { 8 | "branch": null, 9 | "revision": "c7e0ef8559f304699c12bb4c0b668e3a43fe061d", 10 | "version": "3.0.5" 11 | } 12 | } 13 | ] 14 | }, 15 | "version": 1 16 | } 17 | -------------------------------------------------------------------------------- /SwiftPMExample/SwiftPMExample/AppDelegate.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.swift 3 | // SwiftPMExample 4 | // 5 | // Created by JiongXing on 2019/12/18. 6 | // Copyright © 2019 JiongXing. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | @UIApplicationMain 12 | class AppDelegate: UIResponder, UIApplicationDelegate { 13 | 14 | 15 | 16 | func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { 17 | // Override point for customization after application launch. 18 | return true 19 | } 20 | 21 | // MARK: UISceneSession Lifecycle 22 | 23 | func application(_ application: UIApplication, configurationForConnecting connectingSceneSession: UISceneSession, options: UIScene.ConnectionOptions) -> UISceneConfiguration { 24 | // Called when a new scene session is being created. 25 | // Use this method to select a configuration to create the new scene with. 26 | return UISceneConfiguration(name: "Default Configuration", sessionRole: connectingSceneSession.role) 27 | } 28 | 29 | func application(_ application: UIApplication, didDiscardSceneSessions sceneSessions: Set) { 30 | // Called when the user discards a scene session. 31 | // If any sessions were discarded while the application was not running, this will be called shortly after application:didFinishLaunchingWithOptions. 32 | // Use this method to release any resources that were specific to the discarded scenes, as they will not return. 33 | } 34 | 35 | 36 | } 37 | 38 | -------------------------------------------------------------------------------- /SwiftPMExample/SwiftPMExample/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "iphone", 5 | "size" : "20x20", 6 | "scale" : "2x" 7 | }, 8 | { 9 | "idiom" : "iphone", 10 | "size" : "20x20", 11 | "scale" : "3x" 12 | }, 13 | { 14 | "idiom" : "iphone", 15 | "size" : "29x29", 16 | "scale" : "2x" 17 | }, 18 | { 19 | "idiom" : "iphone", 20 | "size" : "29x29", 21 | "scale" : "3x" 22 | }, 23 | { 24 | "idiom" : "iphone", 25 | "size" : "40x40", 26 | "scale" : "2x" 27 | }, 28 | { 29 | "idiom" : "iphone", 30 | "size" : "40x40", 31 | "scale" : "3x" 32 | }, 33 | { 34 | "idiom" : "iphone", 35 | "size" : "60x60", 36 | "scale" : "2x" 37 | }, 38 | { 39 | "idiom" : "iphone", 40 | "size" : "60x60", 41 | "scale" : "3x" 42 | }, 43 | { 44 | "idiom" : "ipad", 45 | "size" : "20x20", 46 | "scale" : "1x" 47 | }, 48 | { 49 | "idiom" : "ipad", 50 | "size" : "20x20", 51 | "scale" : "2x" 52 | }, 53 | { 54 | "idiom" : "ipad", 55 | "size" : "29x29", 56 | "scale" : "1x" 57 | }, 58 | { 59 | "idiom" : "ipad", 60 | "size" : "29x29", 61 | "scale" : "2x" 62 | }, 63 | { 64 | "idiom" : "ipad", 65 | "size" : "40x40", 66 | "scale" : "1x" 67 | }, 68 | { 69 | "idiom" : "ipad", 70 | "size" : "40x40", 71 | "scale" : "2x" 72 | }, 73 | { 74 | "idiom" : "ipad", 75 | "size" : "76x76", 76 | "scale" : "1x" 77 | }, 78 | { 79 | "idiom" : "ipad", 80 | "size" : "76x76", 81 | "scale" : "2x" 82 | }, 83 | { 84 | "idiom" : "ipad", 85 | "size" : "83.5x83.5", 86 | "scale" : "2x" 87 | }, 88 | { 89 | "idiom" : "ios-marketing", 90 | "size" : "1024x1024", 91 | "scale" : "1x" 92 | } 93 | ], 94 | "info" : { 95 | "version" : 1, 96 | "author" : "xcode" 97 | } 98 | } -------------------------------------------------------------------------------- /SwiftPMExample/SwiftPMExample/Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "version" : 1, 4 | "author" : "xcode" 5 | } 6 | } -------------------------------------------------------------------------------- /SwiftPMExample/SwiftPMExample/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 | -------------------------------------------------------------------------------- /SwiftPMExample/SwiftPMExample/Base.lproj/Main.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /SwiftPMExample/SwiftPMExample/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 | $(PRODUCT_BUNDLE_PACKAGE_TYPE) 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleVersion 20 | 1 21 | LSRequiresIPhoneOS 22 | 23 | UIApplicationSceneManifest 24 | 25 | UIApplicationSupportsMultipleScenes 26 | 27 | UISceneConfigurations 28 | 29 | UIWindowSceneSessionRoleApplication 30 | 31 | 32 | UISceneConfigurationName 33 | Default Configuration 34 | UISceneDelegateClassName 35 | $(PRODUCT_MODULE_NAME).SceneDelegate 36 | UISceneStoryboardFile 37 | Main 38 | 39 | 40 | 41 | 42 | UILaunchStoryboardName 43 | LaunchScreen 44 | UIMainStoryboardFile 45 | Main 46 | UIRequiredDeviceCapabilities 47 | 48 | armv7 49 | 50 | UISupportedInterfaceOrientations 51 | 52 | UIInterfaceOrientationPortrait 53 | UIInterfaceOrientationLandscapeLeft 54 | UIInterfaceOrientationLandscapeRight 55 | 56 | UISupportedInterfaceOrientations~ipad 57 | 58 | UIInterfaceOrientationPortrait 59 | UIInterfaceOrientationPortraitUpsideDown 60 | UIInterfaceOrientationLandscapeLeft 61 | UIInterfaceOrientationLandscapeRight 62 | 63 | 64 | 65 | -------------------------------------------------------------------------------- /SwiftPMExample/SwiftPMExample/SceneDelegate.swift: -------------------------------------------------------------------------------- 1 | // 2 | // SceneDelegate.swift 3 | // SwiftPMExample 4 | // 5 | // Created by JiongXing on 2019/12/18. 6 | // Copyright © 2019 JiongXing. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | class SceneDelegate: UIResponder, UIWindowSceneDelegate { 12 | 13 | var window: UIWindow? 14 | 15 | 16 | func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) { 17 | // Use this method to optionally configure and attach the UIWindow `window` to the provided UIWindowScene `scene`. 18 | // If using a storyboard, the `window` property will automatically be initialized and attached to the scene. 19 | // This delegate does not imply the connecting scene or session are new (see `application:configurationForConnectingSceneSession` instead). 20 | guard let _ = (scene as? UIWindowScene) else { return } 21 | } 22 | 23 | func sceneDidDisconnect(_ scene: UIScene) { 24 | // Called as the scene is being released by the system. 25 | // This occurs shortly after the scene enters the background, or when its session is discarded. 26 | // Release any resources associated with this scene that can be re-created the next time the scene connects. 27 | // The scene may re-connect later, as its session was not neccessarily discarded (see `application:didDiscardSceneSessions` instead). 28 | } 29 | 30 | func sceneDidBecomeActive(_ scene: UIScene) { 31 | // Called when the scene has moved from an inactive state to an active state. 32 | // Use this method to restart any tasks that were paused (or not yet started) when the scene was inactive. 33 | } 34 | 35 | func sceneWillResignActive(_ scene: UIScene) { 36 | // Called when the scene will move from an active state to an inactive state. 37 | // This may occur due to temporary interruptions (ex. an incoming phone call). 38 | } 39 | 40 | func sceneWillEnterForeground(_ scene: UIScene) { 41 | // Called as the scene transitions from the background to the foreground. 42 | // Use this method to undo the changes made on entering the background. 43 | } 44 | 45 | func sceneDidEnterBackground(_ scene: UIScene) { 46 | // Called as the scene transitions from the foreground to the background. 47 | // Use this method to save data, release shared resources, and store enough scene-specific state information 48 | // to restore the scene back to its current state. 49 | } 50 | 51 | 52 | } 53 | 54 | -------------------------------------------------------------------------------- /SwiftPMExample/SwiftPMExample/ViewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.swift 3 | // SwiftPMExample 4 | // 5 | // Created by JiongXing on 2019/12/18. 6 | // Copyright © 2019 JiongXing. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | import JXPhotoBrowser 11 | 12 | class ViewController: UIViewController { 13 | 14 | override func viewDidLoad() { 15 | super.viewDidLoad() 16 | // Do any additional setup after loading the view. 17 | JXPhotoBrowserLog.minimumLevel = .high 18 | JXPhotoBrowserLog.high("Hello, world!") 19 | } 20 | 21 | 22 | } 23 | 24 | --------------------------------------------------------------------------------