├── .gitignore ├── Assets ├── Banner.png ├── Home.png └── Introduction.gif ├── 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 │ │ │ ├── icon-1024.png │ │ │ ├── icon-20@2x.png │ │ │ ├── icon-20@3x.png │ │ │ ├── icon-29@2x.png │ │ │ ├── icon-29@3x.png │ │ │ ├── icon-40@2x.png │ │ │ ├── icon-40@3x.png │ │ │ ├── icon-60@2x.png │ │ │ └── icon-60@3x.png │ │ ├── Contents.json │ │ ├── lantern_Play.imageset │ │ │ ├── Contents.json │ │ │ ├── lantern_Play@2x.png │ │ │ └── lantern_Play@3x.png │ │ ├── local_0.imageset │ │ │ ├── Contents.json │ │ │ └── local_0.png │ │ ├── local_1.imageset │ │ │ ├── Contents.json │ │ │ └── local_1.png │ │ ├── local_2.imageset │ │ │ ├── Contents.json │ │ │ └── local_2.png │ │ ├── local_3.imageset │ │ │ ├── Contents.json │ │ │ └── local_3.png │ │ ├── local_4.imageset │ │ │ ├── Contents.json │ │ │ └── local_4.png │ │ └── local_5.imageset │ │ │ ├── Contents.json │ │ │ └── local_5.png │ ├── Base.lproj │ │ ├── LaunchScreen.storyboard │ │ └── Main.storyboard │ ├── BaseCollectionViewCell.swift │ ├── BaseCollectionViewController.swift │ ├── Class │ │ ├── CustomAnimatedTranstioning.swift │ │ ├── CustomViewController.swift │ │ ├── DataSourceAppendViewController.swift │ │ ├── DataSourceDeleteViewController.swift │ │ ├── DefaultPageIndicatorViewController.swift │ │ ├── GIFViewController.swift │ │ ├── KingfisherImageViewController.swift │ │ ├── LanternProgressView.swift │ │ ├── LivePhotoViewController.swift │ │ ├── LoadingProgressViewController.swift │ │ ├── LocalImageSmoothZoomViewController.swift │ │ ├── LocalImageViewController.swift │ │ ├── LocalImageZoomViewController.swift │ │ ├── LongImageViewController.swift │ │ ├── MoreDetailViewController.swift │ │ ├── MultipleCellViewController.swift │ │ ├── MultipleSectionViewController.swift │ │ ├── NumberPageIndicatorViewController.swift │ │ ├── PushNextViewController.swift │ │ ├── SDWebImageViewController.swift │ │ ├── StoreTextPageViewController.swift │ │ ├── VerticalBrowseViewController.swift │ │ ├── VideoCell.swift │ │ └── VideoPhotoViewController.swift │ ├── HomeViewController.swift │ ├── Info.plist │ ├── LongPhotos.plist │ ├── NameSpaceWrapper.swift │ ├── Photos.plist │ ├── Resource │ │ ├── pee.HEIC │ │ ├── pee.MOV │ │ ├── video_0.MP4 │ │ └── video_1.MP4 │ ├── ResourceModel.swift │ ├── UICollectionViewExtension.swift │ └── UITableViewExtension.swift ├── Podfile ├── Podfile.lock └── Pods │ ├── Kingfisher.xcodeproj │ └── project.pbxproj │ ├── Kingfisher │ ├── LICENSE │ ├── README.md │ └── Sources │ │ ├── Cache │ │ ├── CacheSerializer.swift │ │ ├── DiskStorage.swift │ │ ├── FormatIndicatedCacheSerializer.swift │ │ ├── ImageCache.swift │ │ ├── MemoryStorage.swift │ │ └── Storage.swift │ │ ├── Extensions │ │ ├── ImageView+Kingfisher.swift │ │ ├── NSButton+Kingfisher.swift │ │ ├── UIButton+Kingfisher.swift │ │ └── WKInterfaceImage+Kingfisher.swift │ │ ├── General │ │ ├── Deprecated.swift │ │ ├── ImageSource │ │ │ ├── ImageDataProvider.swift │ │ │ ├── Resource.swift │ │ │ └── Source.swift │ │ ├── Kingfisher.swift │ │ ├── KingfisherError.swift │ │ ├── KingfisherManager.swift │ │ └── KingfisherOptionsInfo.swift │ │ ├── Image │ │ ├── Filter.swift │ │ ├── GIFAnimatedImage.swift │ │ ├── Image.swift │ │ ├── ImageDrawing.swift │ │ ├── ImageFormat.swift │ │ ├── ImageProcessor.swift │ │ ├── ImageProgressive.swift │ │ ├── ImageTransition.swift │ │ └── Placeholder.swift │ │ ├── Kingfisher.h │ │ ├── Networking │ │ ├── AuthenticationChallengeResponsable.swift │ │ ├── ImageDataProcessor.swift │ │ ├── ImageDownloader.swift │ │ ├── ImageDownloaderDelegate.swift │ │ ├── ImageModifier.swift │ │ ├── ImagePrefetcher.swift │ │ ├── RedirectHandler.swift │ │ ├── RequestModifier.swift │ │ ├── SessionDataTask.swift │ │ └── SessionDelegate.swift │ │ ├── Utility │ │ ├── Box.swift │ │ ├── CallbackQueue.swift │ │ ├── Delegate.swift │ │ ├── ExtensionHelpers.swift │ │ ├── Result.swift │ │ ├── Runtime.swift │ │ ├── SizeExtensions.swift │ │ └── String+MD5.swift │ │ └── Views │ │ ├── AnimatedImageView.swift │ │ └── Indicator.swift │ ├── Lantern.xcodeproj │ └── project.pbxproj │ ├── Local Podspecs │ └── Lantern.podspec.json │ ├── Manifest.lock │ ├── Pods.xcodeproj │ └── project.pbxproj │ ├── SDWebImage.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 │ │ │ ├── SDDiskCache.h │ │ │ ├── SDDiskCache.m │ │ │ ├── SDImageAPNGCoder.h │ │ │ ├── SDImageAPNGCoder.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 │ │ │ ├── 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 │ │ └── Private │ │ │ ├── NSBezierPath+RoundedCorners.h │ │ │ ├── NSBezierPath+RoundedCorners.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 │ │ │ ├── SDImageHEICCoderInternal.h │ │ │ ├── SDImageIOAnimatedCoderInternal.h │ │ │ ├── SDInternalMacros.h │ │ │ ├── SDInternalMacros.m │ │ │ ├── SDWeakProxy.h │ │ │ ├── SDWeakProxy.m │ │ │ ├── SDmetamacros.h │ │ │ ├── UIColor+HexString.h │ │ │ └── UIColor+HexString.m │ └── WebImage │ │ └── SDWebImage.h │ └── Target Support Files │ ├── Kingfisher │ ├── Kingfisher-Info.plist │ ├── Kingfisher-dummy.m │ ├── Kingfisher-prefix.pch │ ├── Kingfisher-umbrella.h │ ├── Kingfisher.debug.xcconfig │ ├── Kingfisher.modulemap │ ├── Kingfisher.release.xcconfig │ └── Kingfisher.xcconfig │ ├── Lantern │ ├── Lantern-Info.plist │ ├── Lantern-dummy.m │ ├── Lantern-prefix.pch │ ├── Lantern-umbrella.h │ ├── Lantern.debug.xcconfig │ ├── Lantern.modulemap │ ├── Lantern.release.xcconfig │ └── Lantern.xcconfig │ ├── 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 │ ├── SDWebImage-Info.plist │ ├── SDWebImage-dummy.m │ ├── SDWebImage-prefix.pch │ ├── SDWebImage-umbrella.h │ ├── SDWebImage.debug.xcconfig │ ├── SDWebImage.modulemap │ ├── SDWebImage.release.xcconfig │ └── SDWebImage.xcconfig ├── LICENSE ├── Lantern.podspec ├── Package.swift ├── README.md ├── ReleaseNotes.md ├── Sources └── Lantern │ ├── Lantern.swift │ ├── LanternAnimatedTransitioning.swift │ ├── LanternCell.swift │ ├── LanternDefaultPageIndicator.swift │ ├── LanternFadeAnimator.swift │ ├── LanternImageCell.swift │ ├── LanternLog.swift │ ├── LanternNoneAnimator.swift │ ├── LanternNumberPageIndicator.swift │ ├── LanternPageIndicator.swift │ ├── LanternPhotoVideoCell.swift │ ├── LanternSmoothZoomAnimator.swift │ ├── LanternVideoPlayer.swift │ ├── LanternView.swift │ ├── LanternZoomAnimator.swift │ └── LanternZoomSupportedCell.swift ├── 基础用法.md ├── 环境与安装.md └── 高级用法.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/Banner.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fcbox/Lantern/b5e3c798241b5313909b2ef2508af186bc79f296/Assets/Banner.png -------------------------------------------------------------------------------- /Assets/Home.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fcbox/Lantern/b5e3c798241b5313909b2ef2508af186bc79f296/Assets/Home.png -------------------------------------------------------------------------------- /Assets/Introduction.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fcbox/Lantern/b5e3c798241b5313909b2ef2508af186bc79f296/Assets/Introduction.gif -------------------------------------------------------------------------------- /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 © 2021 Shenzhen Hive Box Technology Co.,Ltd All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | @UIApplicationMain 12 | class AppDelegate: UIResponder, UIApplicationDelegate { 13 | var window: UIWindow? 14 | func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { 15 | window = UIWindow.init(frame: UIScreen.main.bounds) 16 | window?.backgroundColor = UIColor.white 17 | window?.makeKeyAndVisible() 18 | let vc = HomeViewController() 19 | let nav = UINavigationController.init(rootViewController:vc) 20 | self.window?.rootViewController = nav 21 | configNavigationBar() 22 | return true 23 | } 24 | 25 | private func configNavigationBar() { 26 | let bar = UINavigationBar.appearance() 27 | bar.titleTextAttributes = [NSAttributedString.Key.font: UIFont.boldSystemFont(ofSize: 17), 28 | NSAttributedString.Key.foregroundColor: UIColor.black] 29 | // 适配dark 返回按钮刷新用图片有问题,暂用颜色方式代替 30 | bar.tintColor = UIColor.black 31 | bar.shadowImage = UIImage() 32 | 33 | let item = UIBarButtonItem.appearance(whenContainedInInstancesOf: [UINavigationBar.self]) 34 | let attr = [NSAttributedString.Key.font: UIFont.systemFont(ofSize: 15), 35 | NSAttributedString.Key.foregroundColor: UIColor.black] 36 | item.setTitleTextAttributes(attr, for: .normal) 37 | item.setTitleTextAttributes(attr, for: .highlighted) 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /Example/Example/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "icon-20@2x.png", 5 | "idiom" : "iphone", 6 | "scale" : "2x", 7 | "size" : "20x20" 8 | }, 9 | { 10 | "filename" : "icon-20@3x.png", 11 | "idiom" : "iphone", 12 | "scale" : "3x", 13 | "size" : "20x20" 14 | }, 15 | { 16 | "filename" : "icon-29@2x.png", 17 | "idiom" : "iphone", 18 | "scale" : "2x", 19 | "size" : "29x29" 20 | }, 21 | { 22 | "filename" : "icon-29@3x.png", 23 | "idiom" : "iphone", 24 | "scale" : "3x", 25 | "size" : "29x29" 26 | }, 27 | { 28 | "filename" : "icon-40@2x.png", 29 | "idiom" : "iphone", 30 | "scale" : "2x", 31 | "size" : "40x40" 32 | }, 33 | { 34 | "filename" : "icon-40@3x.png", 35 | "idiom" : "iphone", 36 | "scale" : "3x", 37 | "size" : "40x40" 38 | }, 39 | { 40 | "filename" : "icon-60@2x.png", 41 | "idiom" : "iphone", 42 | "scale" : "2x", 43 | "size" : "60x60" 44 | }, 45 | { 46 | "filename" : "icon-60@3x.png", 47 | "idiom" : "iphone", 48 | "scale" : "3x", 49 | "size" : "60x60" 50 | }, 51 | { 52 | "filename" : "icon-1024.png", 53 | "idiom" : "ios-marketing", 54 | "scale" : "1x", 55 | "size" : "1024x1024" 56 | } 57 | ], 58 | "info" : { 59 | "author" : "xcode", 60 | "version" : 1 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /Example/Example/Assets.xcassets/AppIcon.appiconset/icon-1024.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fcbox/Lantern/b5e3c798241b5313909b2ef2508af186bc79f296/Example/Example/Assets.xcassets/AppIcon.appiconset/icon-1024.png -------------------------------------------------------------------------------- /Example/Example/Assets.xcassets/AppIcon.appiconset/icon-20@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fcbox/Lantern/b5e3c798241b5313909b2ef2508af186bc79f296/Example/Example/Assets.xcassets/AppIcon.appiconset/icon-20@2x.png -------------------------------------------------------------------------------- /Example/Example/Assets.xcassets/AppIcon.appiconset/icon-20@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fcbox/Lantern/b5e3c798241b5313909b2ef2508af186bc79f296/Example/Example/Assets.xcassets/AppIcon.appiconset/icon-20@3x.png -------------------------------------------------------------------------------- /Example/Example/Assets.xcassets/AppIcon.appiconset/icon-29@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fcbox/Lantern/b5e3c798241b5313909b2ef2508af186bc79f296/Example/Example/Assets.xcassets/AppIcon.appiconset/icon-29@2x.png -------------------------------------------------------------------------------- /Example/Example/Assets.xcassets/AppIcon.appiconset/icon-29@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fcbox/Lantern/b5e3c798241b5313909b2ef2508af186bc79f296/Example/Example/Assets.xcassets/AppIcon.appiconset/icon-29@3x.png -------------------------------------------------------------------------------- /Example/Example/Assets.xcassets/AppIcon.appiconset/icon-40@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fcbox/Lantern/b5e3c798241b5313909b2ef2508af186bc79f296/Example/Example/Assets.xcassets/AppIcon.appiconset/icon-40@2x.png -------------------------------------------------------------------------------- /Example/Example/Assets.xcassets/AppIcon.appiconset/icon-40@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fcbox/Lantern/b5e3c798241b5313909b2ef2508af186bc79f296/Example/Example/Assets.xcassets/AppIcon.appiconset/icon-40@3x.png -------------------------------------------------------------------------------- /Example/Example/Assets.xcassets/AppIcon.appiconset/icon-60@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fcbox/Lantern/b5e3c798241b5313909b2ef2508af186bc79f296/Example/Example/Assets.xcassets/AppIcon.appiconset/icon-60@2x.png -------------------------------------------------------------------------------- /Example/Example/Assets.xcassets/AppIcon.appiconset/icon-60@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fcbox/Lantern/b5e3c798241b5313909b2ef2508af186bc79f296/Example/Example/Assets.xcassets/AppIcon.appiconset/icon-60@3x.png -------------------------------------------------------------------------------- /Example/Example/Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "author" : "xcode", 4 | "version" : 1 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /Example/Example/Assets.xcassets/lantern_Play.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "filename" : "lantern_Play@2x.png", 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "filename" : "lantern_Play@3x.png", 14 | "idiom" : "universal", 15 | "scale" : "3x" 16 | } 17 | ], 18 | "info" : { 19 | "author" : "xcode", 20 | "version" : 1 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /Example/Example/Assets.xcassets/lantern_Play.imageset/lantern_Play@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fcbox/Lantern/b5e3c798241b5313909b2ef2508af186bc79f296/Example/Example/Assets.xcassets/lantern_Play.imageset/lantern_Play@2x.png -------------------------------------------------------------------------------- /Example/Example/Assets.xcassets/lantern_Play.imageset/lantern_Play@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fcbox/Lantern/b5e3c798241b5313909b2ef2508af186bc79f296/Example/Example/Assets.xcassets/lantern_Play.imageset/lantern_Play@3x.png -------------------------------------------------------------------------------- /Example/Example/Assets.xcassets/local_0.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "local_0.png", 5 | "idiom" : "universal", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "author" : "xcode", 19 | "version" : 1 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /Example/Example/Assets.xcassets/local_0.imageset/local_0.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fcbox/Lantern/b5e3c798241b5313909b2ef2508af186bc79f296/Example/Example/Assets.xcassets/local_0.imageset/local_0.png -------------------------------------------------------------------------------- /Example/Example/Assets.xcassets/local_1.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "local_1.png", 5 | "idiom" : "universal", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "author" : "xcode", 19 | "version" : 1 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /Example/Example/Assets.xcassets/local_1.imageset/local_1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fcbox/Lantern/b5e3c798241b5313909b2ef2508af186bc79f296/Example/Example/Assets.xcassets/local_1.imageset/local_1.png -------------------------------------------------------------------------------- /Example/Example/Assets.xcassets/local_2.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "local_2.png", 5 | "idiom" : "universal", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "author" : "xcode", 19 | "version" : 1 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /Example/Example/Assets.xcassets/local_2.imageset/local_2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fcbox/Lantern/b5e3c798241b5313909b2ef2508af186bc79f296/Example/Example/Assets.xcassets/local_2.imageset/local_2.png -------------------------------------------------------------------------------- /Example/Example/Assets.xcassets/local_3.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "local_3.png", 5 | "idiom" : "universal", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "author" : "xcode", 19 | "version" : 1 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /Example/Example/Assets.xcassets/local_3.imageset/local_3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fcbox/Lantern/b5e3c798241b5313909b2ef2508af186bc79f296/Example/Example/Assets.xcassets/local_3.imageset/local_3.png -------------------------------------------------------------------------------- /Example/Example/Assets.xcassets/local_4.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "local_4.png", 5 | "idiom" : "universal", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "author" : "xcode", 19 | "version" : 1 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /Example/Example/Assets.xcassets/local_4.imageset/local_4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fcbox/Lantern/b5e3c798241b5313909b2ef2508af186bc79f296/Example/Example/Assets.xcassets/local_4.imageset/local_4.png -------------------------------------------------------------------------------- /Example/Example/Assets.xcassets/local_5.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "local_5.png", 5 | "idiom" : "universal", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "author" : "xcode", 19 | "version" : 1 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /Example/Example/Assets.xcassets/local_5.imageset/local_5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fcbox/Lantern/b5e3c798241b5313909b2ef2508af186bc79f296/Example/Example/Assets.xcassets/local_5.imageset/local_5.png -------------------------------------------------------------------------------- /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 | // Example 4 | // 5 | // Created by JiongXing on 2018/10/14. 6 | // Copyright © 2021 Shenzhen Hive Box Technology Co.,Ltd 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 | lazy var playButtonView: UIImageView = { 20 | let iv = UIImageView() 21 | iv.contentMode = .scaleAspectFit 22 | iv.image = UIImage.init(named: "lantern_Play") 23 | iv.isHidden = true 24 | return iv 25 | }() 26 | 27 | lazy var livePhotoView: UIImageView = { 28 | let iv = UIImageView() 29 | iv.isHidden = true 30 | return iv 31 | }() 32 | 33 | var livePhotoBadgeImage: UIImage! { 34 | didSet { 35 | livePhotoView.isHidden = false 36 | livePhotoView.image = livePhotoBadgeImage 37 | } 38 | } 39 | 40 | override init(frame: CGRect) { 41 | super.init(frame: frame) 42 | contentView.addSubview(imageView) 43 | contentView.addSubview(playButtonView) 44 | contentView.addSubview(livePhotoView) 45 | } 46 | 47 | override func layoutSubviews() { 48 | super.layoutSubviews() 49 | imageView.frame = contentView.bounds 50 | playButtonView.frame.origin = contentView.center 51 | playButtonView.frame = CGRect.init(x: contentView.frame.width/2-25, y: contentView.frame.height/2-25, width: 50, height: 50) 52 | livePhotoView.frame = CGRect.init(x: contentView.frame.width - 50, y: contentView.frame.height - 50, width: 40, height: 40) 53 | } 54 | 55 | required init?(coder aDecoder: NSCoder) { 56 | fatalError("init(coder:) has not been implemented") 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /Example/Example/Class/DataSourceAppendViewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // DataSourceAppendViewController.swift 3 | // Example 4 | // 5 | // Created by JiongXing on 2019/11/29. 6 | // Copyright © 2021 Shenzhen Hive Box Technology Co.,Ltd All rights reserved. 7 | // 8 | 9 | import UIKit 10 | import Lantern 11 | 12 | class DataSourceAppendViewController: BaseCollectionViewController { 13 | 14 | override var name: String { "无限新增图片" } 15 | 16 | override var remark: String { "浏览过程中不断新增图片,变更数据源,刷新UI" } 17 | 18 | override func makeDataSource() -> [ResourceModel] { 19 | makeLocalDataSource() 20 | } 21 | 22 | override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { 23 | let cell = collectionView.fc.dequeueReusableCell(BaseCollectionViewCell.self, for: indexPath) 24 | cell.imageView.image = self.dataSource[indexPath.item].localName.flatMap { UIImage(named: $0) } 25 | return cell 26 | } 27 | 28 | override func openLantern(with collectionView: UICollectionView, indexPath: IndexPath) { 29 | let lantern = Lantern() 30 | lantern.numberOfItems = {[weak self] in 31 | self?.dataSource.count ?? 0 32 | } 33 | lantern.reloadCellAtIndex = { context in 34 | let lanternCell = context.cell as? LanternImageCell 35 | let indexPath = IndexPath(item: context.index, section: indexPath.section) 36 | lanternCell?.imageView.image = self.dataSource[indexPath.item].localName.flatMap { UIImage(named: $0) } 37 | } 38 | lantern.transitionAnimator = LanternZoomAnimator(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 | // 监听页码变化 44 | lantern.didChangedPageIndex = { index in 45 | // 已到最后一张 46 | if index == self.dataSource.count - 1 { 47 | lantern.lastNumberOfItems = index 48 | self.appendMoreData(lantern: lantern) 49 | } 50 | } 51 | lantern.scrollDirection = .horizontal 52 | lantern.pageIndex = indexPath.item 53 | lantern.show() 54 | } 55 | 56 | private func appendMoreData(lantern: Lantern) { 57 | var randomIndexes = (0..<6).map { $0 } 58 | randomIndexes.shuffle() 59 | randomIndexes.forEach { index in 60 | let model = ResourceModel() 61 | model.localName = "local_\(index)" 62 | dataSource.append(model) 63 | } 64 | collectionView.reloadData() 65 | lantern.reloadData() 66 | } 67 | } 68 | 69 | -------------------------------------------------------------------------------- /Example/Example/Class/DefaultPageIndicatorViewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // DefaultPageIndicatorViewController.swift 3 | // Example 4 | // 5 | // Created by JiongXing on 2019/12/16. 6 | // Copyright © 2021 Shenzhen Hive Box Technology Co.,Ltd All rights reserved. 7 | // 8 | 9 | import UIKit 10 | import Lantern 11 | import SDWebImage 12 | 13 | class DefaultPageIndicatorViewController: BaseCollectionViewController { 14 | 15 | override var name: String { "UIPageControl样式的页码指示器" } 16 | 17 | override var remark: String { "举例如何使用UIPageControl样式的页码指示器" } 18 | 19 | override func makeDataSource() -> [ResourceModel] { 20 | makeNetworkDataSource() 21 | } 22 | 23 | override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { 24 | let cell = collectionView.fc.dequeueReusableCell(BaseCollectionViewCell.self, for: indexPath) 25 | if let firstLevel = self.dataSource[indexPath.item].firstLevelUrl { 26 | let url = URL(string: firstLevel) 27 | cell.imageView.sd_setImage(with: url, completed: nil) 28 | } 29 | return cell 30 | } 31 | 32 | override func openLantern(with collectionView: UICollectionView, indexPath: IndexPath) { 33 | let lantern = Lantern() 34 | lantern.numberOfItems = {[weak self] in 35 | self?.dataSource.count ?? 0 36 | } 37 | lantern.reloadCellAtIndex = { context in 38 | let url = self.dataSource[context.index].secondLevelUrl.flatMap { URL(string: $0) } 39 | let lanternCell = context.cell as? LanternImageCell 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 | lanternCell?.imageView.sd_setImage(with: url, placeholderImage: placeholder, options: [], completed: { (_, _, _, _) in 44 | lanternCell?.setNeedsLayout() 45 | }) 46 | } 47 | lantern.transitionAnimator = LanternZoomAnimator(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 | lantern.pageIndicator = LanternDefaultPageIndicator() 54 | lantern.pageIndex = indexPath.item 55 | lantern.show() 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /Example/Example/Class/KingfisherImageViewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // KingfisherImageViewController.swift 3 | // Example 4 | // 5 | // Created by JiongXing on 2019/11/28. 6 | // Copyright © 2021 Shenzhen Hive Box Technology Co.,Ltd All rights reserved. 7 | // 8 | 9 | import UIKit 10 | import Lantern 11 | import Kingfisher 12 | 13 | class KingfisherImageViewController: BaseCollectionViewController { 14 | 15 | override var name: String { "网络图片-Kingfisher" } 16 | 17 | override var remark: String { "举例如何用Kingfisher加载网络图片" } 18 | 19 | override func makeDataSource() -> [ResourceModel] { 20 | makeNetworkDataSource() 21 | } 22 | 23 | override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { 24 | let cell = collectionView.fc.dequeueReusableCell(BaseCollectionViewCell.self, for: indexPath) 25 | if let firstLevel = self.dataSource[indexPath.item].firstLevelUrl { 26 | let url = URL(string: firstLevel) 27 | cell.imageView.kf.setImage(with: url) 28 | } 29 | return cell 30 | } 31 | 32 | override func openLantern(with collectionView: UICollectionView, indexPath: IndexPath) { 33 | let lantern = Lantern() 34 | lantern.numberOfItems = {[weak self] in 35 | self?.dataSource.count ?? 0 36 | } 37 | lantern.reloadCellAtIndex = { context in 38 | let url = self.dataSource[context.index].secondLevelUrl.flatMap { URL(string: $0) } 39 | let lanternCell = context.cell as? LanternImageCell 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 | // 用Kingfisher加载 44 | lanternCell?.imageView.kf.setImage(with: url, placeholder: placeholder) 45 | } 46 | lantern.transitionAnimator = LanternZoomAnimator(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 | lantern.pageIndex = indexPath.item 52 | lantern.show() 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /Example/Example/Class/LanternProgressView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // LanternProgressView.swift 3 | // Lantern 4 | // 5 | // Created by JiongXing on 2018/10/14. 6 | // Copyright © 2021 Shenzhen Hive Box Technology Co.,Ltd All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | /// 加载进度环 12 | open class LanternProgressView: UIView { 13 | 14 | /// 进度 15 | open var progress: CGFloat = 0 { 16 | didSet { 17 | DispatchQueue.main.async { 18 | self.fanshapedLayer.path = self.makeProgressPath(self.progress).cgPath 19 | if self.progress >= 1.0 || self.progress < 0.01 { 20 | self.isHidden = true 21 | } else { 22 | self.isHidden = false 23 | } 24 | } 25 | } 26 | } 27 | 28 | /// 外边界 29 | private var circleLayer: CAShapeLayer! 30 | 31 | /// 扇形区 32 | private var fanshapedLayer: CAShapeLayer! 33 | 34 | public override init(frame: CGRect) { 35 | super.init(frame: frame) 36 | if self.frame.size.equalTo(.zero) { 37 | self.frame.size = CGSize(width: 50, height: 50) 38 | } 39 | setupUI() 40 | progress = 0 41 | } 42 | 43 | public required init?(coder aDecoder: NSCoder) { 44 | fatalError("init(coder:) has not been implemented") 45 | } 46 | 47 | private func setupUI() { 48 | backgroundColor = UIColor.clear 49 | let strokeColor = UIColor(white: 1, alpha: 0.8).cgColor 50 | 51 | circleLayer = CAShapeLayer() 52 | circleLayer.strokeColor = strokeColor 53 | circleLayer.fillColor = UIColor.clear.cgColor 54 | circleLayer.path = makeCirclePath().cgPath 55 | layer.addSublayer(circleLayer) 56 | 57 | fanshapedLayer = CAShapeLayer() 58 | fanshapedLayer.fillColor = strokeColor 59 | layer.addSublayer(fanshapedLayer) 60 | } 61 | 62 | private func makeCirclePath() -> UIBezierPath { 63 | let arcCenter = CGPoint(x: bounds.midX, y: bounds.midY) 64 | let path = UIBezierPath(arcCenter: arcCenter, radius: 25, startAngle: 0, endAngle: CGFloat.pi * 2, clockwise: true) 65 | path.lineWidth = 2 66 | return path 67 | } 68 | 69 | private func makeProgressPath(_ progress: CGFloat) -> UIBezierPath { 70 | let center = CGPoint(x: bounds.midX, y: bounds.midY) 71 | let radius = bounds.midY - 2.5 72 | let path = UIBezierPath() 73 | path.move(to: center) 74 | path.addLine(to: CGPoint(x: bounds.midX, y: center.y - radius)) 75 | path.addArc(withCenter: center, radius: radius, startAngle: -CGFloat.pi / 2, endAngle: -CGFloat.pi / 2 + CGFloat.pi * 2 * progress, clockwise: true) 76 | path.close() 77 | path.lineWidth = 1 78 | return path 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /Example/Example/Class/LocalImageSmoothZoomViewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // LocalImageSmoothZoomViewController.swift 3 | // Example 4 | // 5 | // Created by JiongXing on 2019/11/28. 6 | // Copyright © 2021 Shenzhen Hive Box Technology Co.,Ltd All rights reserved. 7 | // 8 | 9 | import UIKit 10 | import Lantern 11 | 12 | class LocalImageSmoothZoomViewController: BaseCollectionViewController { 13 | 14 | override var name: String { "更丝滑的Zoom转场动画" } 15 | 16 | override var remark: String { "需要用户自己创建并提供转场视图,以及缩略图位置" } 17 | 18 | override func makeDataSource() -> [ResourceModel] { 19 | makeLocalDataSource() 20 | } 21 | 22 | override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { 23 | let cell = collectionView.fc.dequeueReusableCell(BaseCollectionViewCell.self, for: indexPath) 24 | cell.imageView.image = self.dataSource[indexPath.item].localName.flatMap { UIImage(named: $0) } 25 | return cell 26 | } 27 | 28 | override func openLantern(with collectionView: UICollectionView, indexPath: IndexPath) { 29 | let lantern = Lantern() 30 | lantern.numberOfItems = {[weak self] in 31 | self?.dataSource.count ?? 0 32 | } 33 | lantern.reloadCellAtIndex = { context in 34 | let lanternCell = context.cell as? LanternImageCell 35 | let indexPath = IndexPath(item: context.index, section: indexPath.section) 36 | lanternCell?.imageView.image = self.dataSource[indexPath.item].localName.flatMap { UIImage(named: $0) } 37 | } 38 | // 更丝滑的Zoom动画 39 | lantern.transitionAnimator = LanternSmoothZoomAnimator(transitionViewAndFrame: { (index, destinationView) -> LanternSmoothZoomAnimator.TransitionViewAndFrame? in 40 | let path = IndexPath(item: index, section: indexPath.section) 41 | guard let cell = collectionView.cellForItem(at: path) as? BaseCollectionViewCell else { 42 | return nil 43 | } 44 | let image = cell.imageView.image 45 | let transitionView = UIImageView(image: image) 46 | transitionView.contentMode = cell.imageView.contentMode 47 | transitionView.clipsToBounds = true 48 | let thumbnailFrame = cell.imageView.convert(cell.imageView.bounds, to: destinationView) 49 | return (transitionView, thumbnailFrame) 50 | }) 51 | lantern.pageIndex = indexPath.item 52 | lantern.show(method: .push(inNC: nil)) 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /Example/Example/Class/LocalImageViewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // LocalImageViewController.swift 3 | // Example 4 | // 5 | // Created by JiongXing on 2018/10/14. 6 | // Copyright © 2021 Shenzhen Hive Box Technology Co.,Ltd All rights reserved. 7 | // 8 | 9 | import UIKit 10 | import Lantern 11 | 12 | class LocalImageViewController: BaseCollectionViewController { 13 | 14 | override var name: String { "本地图片" } 15 | 16 | override var remark: String { "最简单的场景,展示本地图片" } 17 | 18 | override func makeDataSource() -> [ResourceModel] { 19 | makeLocalDataSource() 20 | } 21 | 22 | override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { 23 | let cell = collectionView.fc.dequeueReusableCell(BaseCollectionViewCell.self, for: indexPath) 24 | cell.imageView.image = self.dataSource[indexPath.item].localName.flatMap { UIImage(named: $0) } 25 | return cell 26 | } 27 | 28 | override func openLantern(with collectionView: UICollectionView, indexPath: IndexPath) { 29 | // 实例化 30 | let lantern = Lantern() 31 | // 浏览过程中实时获取数据总量 32 | lantern.numberOfItems = {[weak self] in 33 | self?.dataSource.count ?? 0 34 | } 35 | // 刷新Cell数据。本闭包将在Cell完成位置布局后调用。 36 | lantern.reloadCellAtIndex = { context in 37 | let lanternCell = context.cell as? LanternImageCell 38 | let indexPath = IndexPath(item: context.index, section: indexPath.section) 39 | lanternCell?.imageView.image = self.dataSource[indexPath.item].localName.flatMap { UIImage(named: $0) } 40 | } 41 | // 可指定打开时定位到哪一页 42 | lantern.pageIndex = indexPath.item 43 | // 展示 44 | lantern.show() 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /Example/Example/Class/LocalImageZoomViewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // LocalImageZoomViewController.swift 3 | // Example 4 | // 5 | // Created by JiongXing on 2019/11/28. 6 | // Copyright © 2021 Shenzhen Hive Box Technology Co.,Ltd All rights reserved. 7 | // 8 | 9 | import UIKit 10 | import Lantern 11 | 12 | class LocalImageZoomViewController: BaseCollectionViewController { 13 | 14 | override var name: String { "Zoom转场动画" } 15 | 16 | override var remark: String { "简单易用的缩放式转场动画,兼容缩略图与放大图存在差异" } 17 | 18 | override func makeDataSource() -> [ResourceModel] { 19 | makeLocalDataSource() 20 | } 21 | 22 | override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { 23 | let cell = collectionView.fc.dequeueReusableCell(BaseCollectionViewCell.self, for: indexPath) 24 | cell.imageView.image = self.dataSource[indexPath.item].localName.flatMap { UIImage(named: $0) } 25 | return cell 26 | } 27 | 28 | override func openLantern(with collectionView: UICollectionView, indexPath: IndexPath) { 29 | let lantern = Lantern() 30 | lantern.numberOfItems = {[weak self] in 31 | self?.dataSource.count ?? 0 32 | } 33 | lantern.reloadCellAtIndex = { context in 34 | let lanternCell = context.cell as? LanternImageCell 35 | let indexPath = IndexPath(item: context.index, section: indexPath.section) 36 | lanternCell?.imageView.image = self.dataSource[indexPath.item].localName.flatMap { UIImage(named: $0) } 37 | } 38 | // 使用Zoom动画 39 | lantern.transitionAnimator = LanternZoomAnimator(previousView: { index -> UIView? in 40 | let path = IndexPath(item: index, section: indexPath.section) 41 | let cell = collectionView.cellForItem(at: path) as? BaseCollectionViewCell 42 | return cell?.imageView 43 | }) 44 | lantern.pageIndex = indexPath.item 45 | lantern.show() 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /Example/Example/Class/MoreDetailViewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // MoreDetailViewController.swift 3 | // Example 4 | // 5 | // Created by JiongXing on 2019/11/26. 6 | // Copyright © 2021 Shenzhen Hive Box Technology Co.,Ltd 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/Class/NumberPageIndicatorViewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // NumberPageIndicatorViewController.swift 3 | // Example 4 | // 5 | // Created by JiongXing on 2019/12/16. 6 | // Copyright © 2021 Shenzhen Hive Box Technology Co.,Ltd All rights reserved. 7 | // 8 | 9 | import UIKit 10 | import Lantern 11 | import SDWebImage 12 | 13 | class NumberPageIndicatorViewController: BaseCollectionViewController { 14 | 15 | override var name: String { "数字样式的页码指示器" } 16 | 17 | override var remark: String { "举例如何使用数字样式的页码指示器" } 18 | 19 | override func makeDataSource() -> [ResourceModel] { 20 | makeNetworkDataSource() 21 | } 22 | 23 | override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { 24 | let cell = collectionView.fc.dequeueReusableCell(BaseCollectionViewCell.self, for: indexPath) 25 | if let firstLevel = self.dataSource[indexPath.item].firstLevelUrl { 26 | let url = URL(string: firstLevel) 27 | cell.imageView.sd_setImage(with: url, completed: nil) 28 | } 29 | return cell 30 | } 31 | 32 | override func openLantern(with collectionView: UICollectionView, indexPath: IndexPath) { 33 | let lantern = Lantern() 34 | lantern.numberOfItems = {[weak self] in 35 | self?.dataSource.count ?? 0 36 | } 37 | lantern.reloadCellAtIndex = { context in 38 | let url = self.dataSource[context.index].secondLevelUrl.flatMap { URL(string: $0) } 39 | let lanternCell = context.cell as? LanternImageCell 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 | lanternCell?.imageView.sd_setImage(with: url, placeholderImage: placeholder, options: [], completed: { (_, _, _, _) in 44 | lanternCell?.setNeedsLayout() 45 | }) 46 | } 47 | lantern.transitionAnimator = LanternZoomAnimator(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 | lantern.pageIndicator = LanternNumberPageIndicator() 54 | lantern.pageIndex = indexPath.item 55 | lantern.show() 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /Example/Example/Class/PushNextViewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // PushNextViewController.swift 3 | // Example 4 | // 5 | // Created by JiongXing on 2019/11/29. 6 | // Copyright © 2021 Shenzhen Hive Box Technology Co.,Ltd All rights reserved. 7 | // 8 | 9 | import UIKit 10 | import Lantern 11 | 12 | class PushNextViewController: BaseCollectionViewController { 13 | 14 | override var name: String { "带导航栏Push" } 15 | 16 | override var remark: String { "让lantern嵌入导航控制器里,Push到下一页" } 17 | 18 | override func makeDataSource() -> [ResourceModel] { 19 | makeLocalDataSource() 20 | } 21 | 22 | override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { 23 | let cell = collectionView.fc.dequeueReusableCell(BaseCollectionViewCell.self, for: indexPath) 24 | cell.imageView.image = self.dataSource[indexPath.item].localName.flatMap { UIImage(named: $0) } 25 | return cell 26 | } 27 | 28 | override func openLantern(with collectionView: UICollectionView, indexPath: IndexPath) { 29 | let lantern = Lantern() 30 | lantern.numberOfItems = {[weak self] in 31 | self?.dataSource.count ?? 0 32 | } 33 | lantern.reloadCellAtIndex = { context in 34 | guard let lanternCell = context.cell as? LanternImageCell else { 35 | return 36 | } 37 | let indexPath = IndexPath(item: context.index, section: indexPath.section) 38 | lanternCell.imageView.image = self.dataSource[indexPath.item].localName.flatMap { UIImage(named: $0) } 39 | // 添加长按事件 40 | lanternCell.longPressedAction = { cell, _ in 41 | self.longPress(cell: cell) 42 | } 43 | } 44 | lantern.transitionAnimator = LanternZoomAnimator(previousView: { index -> UIView? in 45 | let path = IndexPath(item: index, section: indexPath.section) 46 | let cell = collectionView.cellForItem(at: path) as? BaseCollectionViewCell 47 | return cell?.imageView 48 | }) 49 | lantern.pageIndex = indexPath.item 50 | // 让lantern嵌入当前的导航控制器里 51 | lantern.show(method: .push(inNC: nil)) 52 | } 53 | 54 | private func longPress(cell: LanternImageCell) { 55 | let alert = UIAlertController(title: nil, message: nil, preferredStyle: .actionSheet) 56 | alert.addAction(UIAlertAction(title: "查看详情", style: .destructive, handler: { _ in 57 | let detail = MoreDetailViewController() 58 | cell.lantern?.navigationController?.pushViewController(detail, animated: true) 59 | })) 60 | alert.addAction(UIAlertAction(title: "取消", style: .cancel, handler: nil)) 61 | cell.lantern?.present(alert, animated: true, completion: nil) 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /Example/Example/Class/SDWebImageViewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // SDWebImageViewController.swift 3 | // Example 4 | // 5 | // Created by JiongXing on 2019/11/28. 6 | // Copyright © 2021 Shenzhen Hive Box Technology Co.,Ltd All rights reserved. 7 | // 8 | 9 | import UIKit 10 | import Lantern 11 | import SDWebImage 12 | 13 | class SDWebImageViewController: BaseCollectionViewController { 14 | 15 | override var name: String { "网络图片-SDWebImage" } 16 | 17 | override var remark: String { "举例如何用SDWebImage加载网络图片" } 18 | 19 | override func makeDataSource() -> [ResourceModel] { 20 | makeNetworkDataSource() 21 | } 22 | 23 | override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { 24 | let cell = collectionView.fc.dequeueReusableCell(BaseCollectionViewCell.self, for: indexPath) 25 | if let firstLevel = self.dataSource[indexPath.item].firstLevelUrl { 26 | let url = URL(string: firstLevel) 27 | cell.imageView.sd_setImage(with: url, completed: nil) 28 | } 29 | return cell 30 | } 31 | 32 | override func openLantern(with collectionView: UICollectionView, indexPath: IndexPath) { 33 | let lantern = Lantern() 34 | lantern.numberOfItems = {[weak self] in 35 | self?.dataSource.count ?? 0 36 | } 37 | lantern.reloadCellAtIndex = { context in 38 | let url = self.dataSource[context.index].secondLevelUrl.flatMap { URL(string: $0) } 39 | let lanternCell = context.cell as? LanternImageCell 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 | lanternCell?.imageView.sd_setImage(with: url, placeholderImage: placeholder) 45 | } 46 | lantern.transitionAnimator = LanternZoomAnimator(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 | lantern.pageIndex = indexPath.item 52 | lantern.show() 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /Example/Example/Class/VideoCell.swift: -------------------------------------------------------------------------------- 1 | // 2 | // VideoCell.swift 3 | // Example 4 | // 5 | // Created by JiongXing on 2019/12/13. 6 | // Copyright © 2021 Shenzhen Hive Box Technology Co.,Ltd All rights reserved. 7 | // 8 | 9 | import Foundation 10 | import UIKit 11 | import AVFoundation 12 | import Lantern 13 | 14 | class VideoCell: UIView, LanternCell { 15 | 16 | weak var lantern: Lantern? 17 | 18 | lazy var player = AVPlayer() 19 | lazy var playerLayer = AVPlayerLayer(player: player) 20 | 21 | static func generate(with lantern: Lantern) -> Self { 22 | let instance = Self.init(frame: .zero) 23 | instance.lantern = lantern 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 | lantern?.dismiss() 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /Example/Example/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | $(DEVELOPMENT_LANGUAGE) 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | $(PRODUCT_BUNDLE_PACKAGE_TYPE) 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleVersion 20 | 1 21 | LSRequiresIPhoneOS 22 | 23 | NSAppTransportSecurity 24 | 25 | NSAllowsArbitraryLoads 26 | 27 | 28 | UILaunchStoryboardName 29 | LaunchScreen 30 | UIMainStoryboardFile 31 | Main 32 | UIRequiredDeviceCapabilities 33 | 34 | armv7 35 | 36 | UISupportedInterfaceOrientations 37 | 38 | UIInterfaceOrientationPortrait 39 | UIInterfaceOrientationLandscapeLeft 40 | UIInterfaceOrientationLandscapeRight 41 | 42 | UISupportedInterfaceOrientations~ipad 43 | 44 | UIInterfaceOrientationPortrait 45 | UIInterfaceOrientationPortraitUpsideDown 46 | UIInterfaceOrientationLandscapeLeft 47 | UIInterfaceOrientationLandscapeRight 48 | 49 | 50 | 51 | -------------------------------------------------------------------------------- /Example/Example/LongPhotos.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | http://wx4.sinaimg.cn/thumbnail/bfc243a3gy1febm7tekewj20i20i4aoy.jpg 7 | http://wx4.sinaimg.cn/large/bfc243a3gy1febm7tekewj20i20i4aoy.jpg 8 | (8)过去心不可得,现在心不可得,未来心不可得. 9 | 10 | 11 | http://wx3.sinaimg.cn/thumbnail/bfc243a3gy1febm7usmc8j20i543zngx.jpg 12 | http://wx3.sinaimg.cn/large/bfc243a3gy1febm7usmc8j20i543zngx.jpg 13 | (9)纵使经百劫,所作业不亡,因缘会遇时,果报还自受. 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /Example/Example/NameSpaceWrapper.swift: -------------------------------------------------------------------------------- 1 | // 2 | // NameSpaceWrapper.swift 3 | // Example 4 | // 5 | // Created by 小豌先生 on 2021/3/26. 6 | // Copyright © 2021 Shenzhen Hive Box Technology Co.,Ltd All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | /// 类型协议 12 | public protocol TypeWrapperProtocol { 13 | associatedtype WrappedType 14 | var wrappedValue: WrappedType { get } 15 | init(value: WrappedType) 16 | } 17 | 18 | public struct NamespaceWrapper: TypeWrapperProtocol { 19 | public let wrappedValue: T 20 | public init(value: T) { 21 | self.wrappedValue = value 22 | } 23 | } 24 | 25 | /// 命名空间协议 26 | public protocol NamespaceWrappable { 27 | associatedtype WrapperType 28 | var fc: WrapperType { get } 29 | static var fc: WrapperType.Type { get } 30 | } 31 | 32 | 33 | 34 | extension NamespaceWrappable { 35 | public var fc: NamespaceWrapper { 36 | return NamespaceWrapper(value: self) 37 | } 38 | 39 | public static var fc: NamespaceWrapper.Type { 40 | return NamespaceWrapper.self 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /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 | 47 | -------------------------------------------------------------------------------- /Example/Example/Resource/pee.HEIC: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fcbox/Lantern/b5e3c798241b5313909b2ef2508af186bc79f296/Example/Example/Resource/pee.HEIC -------------------------------------------------------------------------------- /Example/Example/Resource/pee.MOV: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fcbox/Lantern/b5e3c798241b5313909b2ef2508af186bc79f296/Example/Example/Resource/pee.MOV -------------------------------------------------------------------------------- /Example/Example/Resource/video_0.MP4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fcbox/Lantern/b5e3c798241b5313909b2ef2508af186bc79f296/Example/Example/Resource/video_0.MP4 -------------------------------------------------------------------------------- /Example/Example/Resource/video_1.MP4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/fcbox/Lantern/b5e3c798241b5313909b2ef2508af186bc79f296/Example/Example/Resource/video_1.MP4 -------------------------------------------------------------------------------- /Example/Example/ResourceModel.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ResourceModel.swift 3 | // Lantern 4 | // 5 | // Created by JiongXing on 2019/11/20. 6 | // Copyright © 2021 Shenzhen Hive Box Technology Co.,Ltd All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | /// 视像资源模型 12 | class ResourceModel { 13 | /// 实况图 14 | var livePhotoUrl: String? 15 | /// 实况图mov 16 | var liveMovUrl: String? 17 | /// 视频链接 18 | var videoUrl: String? 19 | /// 第一级资源 20 | var firstLevelUrl: String? 21 | /// 第二级资源 22 | var secondLevelUrl: String? 23 | /// 第三级资源 24 | var thirdLevelUrl: String? 25 | /// 本地资源,资源名 26 | var localName: String? 27 | /// 备注配文 28 | var remark: String? 29 | } 30 | -------------------------------------------------------------------------------- /Example/Example/UICollectionViewExtension.swift: -------------------------------------------------------------------------------- 1 | // 2 | // UICollectionViewExtension.swift 3 | // Example 4 | // 5 | // Created by 小豌先生 on 2021/3/26. 6 | // Copyright © 2021 Shenzhen Hive Box Technology Co.,Ltd All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | extension UICollectionView: NamespaceWrappable {} 12 | 13 | extension TypeWrapperProtocol where WrappedType == UICollectionView { 14 | 15 | /// 注册Cell 16 | public func registerCell(_ type: T.Type) { 17 | let identifier = String(describing: type.self) 18 | wrappedValue.register(type, forCellWithReuseIdentifier: identifier) 19 | } 20 | 21 | /// 取重用Cell 22 | public func dequeueReusableCell(_ type: T.Type, for indexPath: IndexPath) -> T { 23 | let identifier = String(describing: type.self) 24 | guard let cell = wrappedValue.dequeueReusableCell(withReuseIdentifier: identifier, for: indexPath) as? T else { 25 | fatalError("\(type.self) was not registered") 26 | } 27 | return cell 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /Example/Example/UITableViewExtension.swift: -------------------------------------------------------------------------------- 1 | // 2 | // UITableViewExtension.swift 3 | // Example 4 | // 5 | // Created by 小豌先生 on 2021/3/26. 6 | // Copyright © 2021 Shenzhen Hive Box Technology Co.,Ltd All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | extension UITableView: NamespaceWrappable {} 12 | 13 | extension TypeWrapperProtocol where WrappedType == UITableView { 14 | /// 注册Cell 15 | public func registerCell(_ type: T.Type) { 16 | let identifier = String(describing: type.self) 17 | wrappedValue.register(type, forCellReuseIdentifier: identifier) 18 | } 19 | 20 | /// 取重用Cell 21 | public func dequeueReusableCell(_ type: T.Type) -> T { 22 | let identifier = String(describing: type.self) 23 | guard let cell = wrappedValue.dequeueReusableCell(withIdentifier: identifier) as? T else { 24 | fatalError("\(type.self) was not registered") 25 | } 26 | return cell 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /Example/Podfile: -------------------------------------------------------------------------------- 1 | #source 'https://github.com/CocoaPods/Specs.git' 2 | install! 'cocoapods', :generate_multiple_pod_projects => true 3 | 4 | platform :ios, '10.0' 5 | use_frameworks! 6 | 7 | target 'Example' do 8 | # Comment the next line if you don't want to use dynamic frameworks 9 | use_frameworks! 10 | 11 | # Pods for Example 12 | pod 'Lantern', :path => '../' 13 | pod 'SDWebImage' 14 | pod 'Kingfisher' 15 | end 16 | 17 | post_install do |installer| 18 | installer.generated_projects.each do |project| 19 | project.targets.each do |target| 20 | target.build_configurations.each do |config| 21 | config.build_settings['IPHONEOS_DEPLOYMENT_TARGET'] = '11.0' 22 | end 23 | end 24 | end 25 | end 26 | -------------------------------------------------------------------------------- /Example/Podfile.lock: -------------------------------------------------------------------------------- 1 | PODS: 2 | - Kingfisher (5.12.0): 3 | - Kingfisher/Core (= 5.12.0) 4 | - Kingfisher/Core (5.12.0) 5 | - Lantern (1.1.4) 6 | - SDWebImage (5.4.0): 7 | - SDWebImage/Core (= 5.4.0) 8 | - SDWebImage/Core (5.4.0) 9 | 10 | DEPENDENCIES: 11 | - Kingfisher 12 | - Lantern (from `../`) 13 | - SDWebImage 14 | 15 | SPEC REPOS: 16 | trunk: 17 | - Kingfisher 18 | - SDWebImage 19 | 20 | EXTERNAL SOURCES: 21 | Lantern: 22 | :path: "../" 23 | 24 | SPEC CHECKSUMS: 25 | Kingfisher: dc6e0f53bb5b12c3e75bedb0e01bbd7a640eea69 26 | Lantern: 26ed71b2d9ace5073ecf53521e316ed8b95acdb0 27 | SDWebImage: 5bf6aec6481ae2a062bdc59f9d6c1d1e552090e0 28 | 29 | PODFILE CHECKSUM: 6fe8253ce68714a4f2c5826cbcd0b97e3ded2637 30 | 31 | COCOAPODS: 1.12.1 32 | -------------------------------------------------------------------------------- /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/Kingfisher.h: -------------------------------------------------------------------------------- 1 | // 2 | // Kingfisher.h 3 | // Kingfisher 4 | // 5 | // Created by Wei Wang on 15/4/6. 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 28 | 29 | //! Project version number for Kingfisher. 30 | FOUNDATION_EXPORT double KingfisherVersionNumber; 31 | 32 | //! Project version string for Kingfisher. 33 | FOUNDATION_EXPORT const unsigned char KingfisherVersionString[]; 34 | 35 | // In this header, you should import all the public headers of your framework using statements like #import 36 | 37 | 38 | -------------------------------------------------------------------------------- /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/Delegate.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Delegate.swift 3 | // Kingfisher 4 | // 5 | // Created by onevcat on 2018/10/10. 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 | /// A delegate helper type to "shadow" weak `self`, to prevent creating an unexpected retain cycle. 30 | class Delegate { 31 | init() {} 32 | 33 | private var block: ((Input) -> Output?)? 34 | 35 | func delegate(on target: T, block: ((T, Input) -> Output)?) { 36 | // The `target` is weak inside block, so you do not need to worry about it in the caller side. 37 | self.block = { [weak target] input in 38 | guard let target = target else { return nil } 39 | return block?(target, input) 40 | } 41 | } 42 | 43 | func call(_ input: Input) -> Output? { 44 | return block?(input) 45 | } 46 | } 47 | 48 | extension Delegate where Input == Void { 49 | // To make syntax better for `Void` input. 50 | func call() -> Output? { 51 | return call(()) 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /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 | return objc_getAssociatedObject(object, key) as? T 31 | } 32 | 33 | func setRetainedAssociatedObject(_ object: Any, _ key: UnsafeRawPointer, _ value: T) { 34 | objc_setAssociatedObject(object, key, value, .OBJC_ASSOCIATION_RETAIN_NONATOMIC) 35 | } 36 | -------------------------------------------------------------------------------- /Example/Pods/Local Podspecs/Lantern.podspec.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Lantern", 3 | "version": "1.1.4", 4 | "summary": "Elegant photo and video browser in Swift.", 5 | "description": "Elegant photo and video browser in Swift. Inspired by WeChat.", 6 | "homepage": "https://github.com/fcbox/Lantern", 7 | "license": { 8 | "type": "Apache-2.0", 9 | "file": "LICENSE" 10 | }, 11 | "authors": { 12 | "JiongXing": "liangjiongxing@qq.com" 13 | }, 14 | "source": { 15 | "git": "https://github.com/fcbox/Lantern.git", 16 | "tag": "1.1.4" 17 | }, 18 | "platforms": { 19 | "ios": "9.0" 20 | }, 21 | "swift_versions": [ 22 | "4.2", 23 | "5.0" 24 | ], 25 | "source_files": "Sources/Lantern/*", 26 | "swift_version": "5.0" 27 | } 28 | -------------------------------------------------------------------------------- /Example/Pods/Manifest.lock: -------------------------------------------------------------------------------- 1 | PODS: 2 | - Kingfisher (5.12.0): 3 | - Kingfisher/Core (= 5.12.0) 4 | - Kingfisher/Core (5.12.0) 5 | - Lantern (1.1.4) 6 | - SDWebImage (5.4.0): 7 | - SDWebImage/Core (= 5.4.0) 8 | - SDWebImage/Core (5.4.0) 9 | 10 | DEPENDENCIES: 11 | - Kingfisher 12 | - Lantern (from `../`) 13 | - SDWebImage 14 | 15 | SPEC REPOS: 16 | trunk: 17 | - Kingfisher 18 | - SDWebImage 19 | 20 | EXTERNAL SOURCES: 21 | Lantern: 22 | :path: "../" 23 | 24 | SPEC CHECKSUMS: 25 | Kingfisher: dc6e0f53bb5b12c3e75bedb0e01bbd7a640eea69 26 | Lantern: 26ed71b2d9ace5073ecf53521e316ed8b95acdb0 27 | SDWebImage: 5bf6aec6481ae2a062bdc59f9d6c1d1e552090e0 28 | 29 | PODFILE CHECKSUM: 6fe8253ce68714a4f2c5826cbcd0b97e3ded2637 30 | 31 | COCOAPODS: 1.12.1 32 | -------------------------------------------------------------------------------- /Example/Pods/SDWebImage/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2009-2018 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 | 27 | /** 28 | NSData category about the image content type and UTI. 29 | */ 30 | @interface NSData (ImageContentType) 31 | 32 | /** 33 | * Return image format 34 | * 35 | * @param data the input image data 36 | * 37 | * @return the image format as `SDImageFormat` (enum) 38 | */ 39 | + (SDImageFormat)sd_imageFormatForImageData:(nullable NSData *)data; 40 | 41 | /** 42 | * Convert SDImageFormat to UTType 43 | * 44 | * @param format Format as SDImageFormat 45 | * @return The UTType as CFStringRef 46 | */ 47 | + (nonnull CFStringRef)sd_UTTypeFromImageFormat:(SDImageFormat)format CF_RETURNS_NOT_RETAINED NS_SWIFT_NAME(sd_UTType(from:)); 48 | 49 | /** 50 | * Convert UTTyppe to SDImageFormat 51 | * 52 | * @param uttype The UTType as CFStringRef 53 | * @return The Format as SDImageFormat 54 | */ 55 | + (SDImageFormat)sd_imageFormatFromUTType:(nonnull CFStringRef)uttype; 56 | 57 | @end 58 | -------------------------------------------------------------------------------- /Example/Pods/SDWebImage/SDWebImage/Core/NSImage+Compatibility.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 | /** 14 | This category is provided to easily write cross-platform(AppKit/UIKit) code. For common usage, see `UIImage+Metadata.h`. 15 | */ 16 | @interface NSImage (Compatibility) 17 | 18 | /** 19 | The underlying Core Graphics image object. This will actually use `CGImageForProposedRect` with the image size. 20 | */ 21 | @property (nonatomic, readonly, nullable) CGImageRef CGImage; 22 | /** 23 | The scale factor of the image. This wil actually use `bestRepresentationForRect` with image size and pixel size to calculate the scale factor. If failed, use the default value 1.0. Should be greater than or equal to 1.0. 24 | */ 25 | @property (nonatomic, readonly) CGFloat scale; 26 | 27 | // These are convenience methods to make AppKit's `NSImage` match UIKit's `UIImage` behavior. The scale factor should be greater than or equal to 1.0. 28 | 29 | /** 30 | Returns an image object with the scale factor and orientation. The representation is created from the Core Graphics image object. 31 | @note The difference between this and `initWithCGImage:size` is that `initWithCGImage:size` will actually create a `NSCGImageSnapshotRep` representation and always use `backingScaleFactor` as scale factor. So we should avoid it and use `NSBitmapImageRep` with `initWithCGImage:` instead. 32 | @note The difference between this and UIKit's `UIImage` equivalent method is the way to process orientation. If the provided image orientation is not equal to Up orientation, this method will firstly rotate the CGImage to the correct orientation to work compatible with `NSImageView`. However, UIKit will not actually rotate CGImage and just store it as `imageOrientation` property. 33 | 34 | @param cgImage A Core Graphics image object 35 | @param scale The image scale factor 36 | @param orientation The orientation of the image data 37 | @return The image object 38 | */ 39 | - (nonnull instancetype)initWithCGImage:(nonnull CGImageRef)cgImage scale:(CGFloat)scale orientation:(CGImagePropertyOrientation)orientation; 40 | 41 | /** 42 | Returns an image object with the scale factor. The representation is created from the image data. 43 | @note The difference between these this and `initWithData:` is that `initWithData:` will always use `backingScaleFactor` as scale factor. 44 | 45 | @param data The image data 46 | @param scale The image scale factor 47 | @return The image object 48 | */ 49 | - (nullable instancetype)initWithData:(nonnull NSData *)data scale:(CGFloat)scale; 50 | 51 | @end 52 | 53 | #endif 54 | -------------------------------------------------------------------------------- /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 | /** 14 | A subclass of `NSBitmapImageRep` to fix that GIF duration issue because `NSBitmapImageRep` will reset `NSImageCurrentFrameDuration` by using `kCGImagePropertyGIFDelayTime` but not `kCGImagePropertyGIFUnclampedDelayTime`. 15 | 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. 16 | 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. 17 | This also support APNG format using `SDImageAPNGCoder`. Which provide full alpha-channel support and the correct duration match the `kCGImagePropertyAPNGUnclampedDelayTime`. 18 | */ 19 | @interface SDAnimatedImageRep : NSBitmapImageRep 20 | 21 | @end 22 | 23 | #endif 24 | -------------------------------------------------------------------------------- /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 | #if SD_MAC 11 | #import 12 | #else 13 | #import 14 | #endif 15 | 16 | // iOS 8 Image/IO framework binary does not contains these APNG contants, so we define them. Thanks Apple :) 17 | // We can not use runtime @available check for this issue, because it's a global symbol and should be loaded during launch time by dyld. So hack if the min deployment target version < iOS 9.0, whatever it running on iOS 9+ or not. 18 | #if (__IPHONE_OS_VERSION_MIN_REQUIRED && __IPHONE_OS_VERSION_MIN_REQUIRED < __IPHONE_9_0) 19 | const CFStringRef kCGImagePropertyAPNGLoopCount = (__bridge CFStringRef)@"LoopCount"; 20 | const CFStringRef kCGImagePropertyAPNGDelayTime = (__bridge CFStringRef)@"DelayTime"; 21 | const CFStringRef kCGImagePropertyAPNGUnclampedDelayTime = (__bridge CFStringRef)@"UnclampedDelayTime"; 22 | #endif 23 | 24 | @implementation SDImageAPNGCoder 25 | 26 | + (instancetype)sharedCoder { 27 | static SDImageAPNGCoder *coder; 28 | static dispatch_once_t onceToken; 29 | dispatch_once(&onceToken, ^{ 30 | coder = [[SDImageAPNGCoder alloc] init]; 31 | }); 32 | return coder; 33 | } 34 | 35 | #pragma mark - Subclass Override 36 | 37 | + (SDImageFormat)imageFormat { 38 | return SDImageFormatPNG; 39 | } 40 | 41 | + (NSString *)imageUTType { 42 | return (__bridge NSString *)kUTTypePNG; 43 | } 44 | 45 | + (NSString *)dictionaryProperty { 46 | return (__bridge NSString *)kCGImagePropertyPNGDictionary; 47 | } 48 | 49 | + (NSString *)unclampedDelayTimeProperty { 50 | return (__bridge NSString *)kCGImagePropertyAPNGUnclampedDelayTime; 51 | } 52 | 53 | + (NSString *)delayTimeProperty { 54 | return (__bridge NSString *)kCGImagePropertyAPNGDelayTime; 55 | } 56 | 57 | + (NSString *)loopCountProperty { 58 | return (__bridge NSString *)kCGImagePropertyAPNGLoopCount; 59 | } 60 | 61 | + (NSUInteger)defaultLoopCount { 62 | return 0; 63 | } 64 | 65 | @end 66 | -------------------------------------------------------------------------------- /Example/Pods/SDWebImage/SDWebImage/Core/SDImageCacheConfig.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 "SDImageCacheConfig.h" 10 | #import "SDMemoryCache.h" 11 | #import "SDDiskCache.h" 12 | 13 | static SDImageCacheConfig *_defaultCacheConfig; 14 | static const NSInteger kDefaultCacheMaxDiskAge = 60 * 60 * 24 * 7; // 1 week 15 | 16 | @implementation SDImageCacheConfig 17 | 18 | + (SDImageCacheConfig *)defaultCacheConfig { 19 | static dispatch_once_t onceToken; 20 | dispatch_once(&onceToken, ^{ 21 | _defaultCacheConfig = [SDImageCacheConfig new]; 22 | }); 23 | return _defaultCacheConfig; 24 | } 25 | 26 | - (instancetype)init { 27 | if (self = [super init]) { 28 | _shouldDisableiCloud = YES; 29 | _shouldCacheImagesInMemory = YES; 30 | _shouldUseWeakMemoryCache = YES; 31 | _shouldRemoveExpiredDataWhenEnterBackground = YES; 32 | _diskCacheReadingOptions = 0; 33 | _diskCacheWritingOptions = NSDataWritingAtomic; 34 | _maxDiskAge = kDefaultCacheMaxDiskAge; 35 | _maxDiskSize = 0; 36 | _diskCacheExpireType = SDImageCacheConfigExpireTypeModificationDate; 37 | _memoryCacheClass = [SDMemoryCache class]; 38 | _diskCacheClass = [SDDiskCache class]; 39 | } 40 | return self; 41 | } 42 | 43 | - (id)copyWithZone:(NSZone *)zone { 44 | SDImageCacheConfig *config = [[[self class] allocWithZone:zone] init]; 45 | config.shouldDisableiCloud = self.shouldDisableiCloud; 46 | config.shouldCacheImagesInMemory = self.shouldCacheImagesInMemory; 47 | config.shouldUseWeakMemoryCache = self.shouldUseWeakMemoryCache; 48 | config.shouldRemoveExpiredDataWhenEnterBackground = self.shouldRemoveExpiredDataWhenEnterBackground; 49 | config.diskCacheReadingOptions = self.diskCacheReadingOptions; 50 | config.diskCacheWritingOptions = self.diskCacheWritingOptions; 51 | config.maxDiskAge = self.maxDiskAge; 52 | config.maxDiskSize = self.maxDiskSize; 53 | config.maxMemoryCost = self.maxMemoryCost; 54 | config.maxMemoryCount = self.maxMemoryCount; 55 | config.diskCacheExpireType = self.diskCacheExpireType; 56 | config.fileManager = self.fileManager; // NSFileManager does not conform to NSCopying, just pass the reference 57 | config.memoryCacheClass = self.memoryCacheClass; 58 | config.diskCacheClass = self.diskCacheClass; 59 | 60 | return config; 61 | } 62 | 63 | @end 64 | -------------------------------------------------------------------------------- /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 | 14 | SDImageCoderOption const SDImageCoderEncodeFirstFrameOnly = @"encodeFirstFrameOnly"; 15 | SDImageCoderOption const SDImageCoderEncodeCompressionQuality = @"encodeCompressionQuality"; 16 | 17 | SDImageCoderOption const SDImageCoderWebImageContext = @"webImageContext"; 18 | -------------------------------------------------------------------------------- /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 | /** 28 | Create a frame instance with specify image and duration 29 | 30 | @param image current frame's image 31 | @param duration current frame's duration 32 | @return frame instance 33 | */ 34 | + (instancetype _Nonnull)frameWithImage:(UIImage * _Nonnull)image duration:(NSTimeInterval)duration; 35 | 36 | @end 37 | -------------------------------------------------------------------------------- /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)frameWithImage:(UIImage *)image duration:(NSTimeInterval)duration { 21 | SDImageFrame *frame = [[SDImageFrame alloc] init]; 22 | frame.image = image; 23 | frame.duration = duration; 24 | 25 | return frame; 26 | } 27 | 28 | @end 29 | -------------------------------------------------------------------------------- /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 | #if SD_MAC 11 | #import 12 | #else 13 | #import 14 | #endif 15 | 16 | @implementation SDImageGIFCoder 17 | 18 | + (instancetype)sharedCoder { 19 | static SDImageGIFCoder *coder; 20 | static dispatch_once_t onceToken; 21 | dispatch_once(&onceToken, ^{ 22 | coder = [[SDImageGIFCoder alloc] init]; 23 | }); 24 | return coder; 25 | } 26 | 27 | #pragma mark - Subclass Override 28 | 29 | + (SDImageFormat)imageFormat { 30 | return SDImageFormatGIF; 31 | } 32 | 33 | + (NSString *)imageUTType { 34 | return (__bridge NSString *)kUTTypeGIF; 35 | } 36 | 37 | + (NSString *)dictionaryProperty { 38 | return (__bridge NSString *)kCGImagePropertyGIFDictionary; 39 | } 40 | 41 | + (NSString *)unclampedDelayTimeProperty { 42 | return (__bridge NSString *)kCGImagePropertyGIFUnclampedDelayTime; 43 | } 44 | 45 | + (NSString *)delayTimeProperty { 46 | return (__bridge NSString *)kCGImagePropertyGIFDelayTime; 47 | } 48 | 49 | + (NSString *)loopCountProperty { 50 | return (__bridge NSString *)kCGImagePropertyGIFLoopCount; 51 | } 52 | 53 | + (NSUInteger)defaultLoopCount { 54 | return 1; 55 | } 56 | 57 | @end 58 | -------------------------------------------------------------------------------- /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 | */ 17 | 18 | /// Returns the current graphics context. 19 | FOUNDATION_EXPORT CGContextRef __nullable SDGraphicsGetCurrentContext(void) CF_RETURNS_NOT_RETAINED; 20 | /// Creates a bitmap-based graphics context and makes it the current context. 21 | FOUNDATION_EXPORT void SDGraphicsBeginImageContext(CGSize size); 22 | /// Creates a bitmap-based graphics context with the specified options. 23 | FOUNDATION_EXPORT void SDGraphicsBeginImageContextWithOptions(CGSize size, BOOL opaque, CGFloat scale); 24 | /// Removes the current bitmap-based graphics context from the top of the stack. 25 | FOUNDATION_EXPORT void SDGraphicsEndImageContext(void); 26 | /// Returns an image based on the contents of the current bitmap-based graphics context. 27 | FOUNDATION_EXPORT UIImage * __nullable SDGraphicsGetImageFromCurrentImageContext(void); 28 | -------------------------------------------------------------------------------- /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 | @interface SDImageHEICCoder : SDImageIOAnimatedCoder 21 | 22 | @property (nonatomic, class, readonly, nonnull) SDImageHEICCoder *sharedCoder; 23 | 24 | @end 25 | -------------------------------------------------------------------------------- /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 11 | #import "SDImageCoder.h" 12 | 13 | /** 14 | 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. 15 | All of the properties need the subclass to implment and works as expceted. 16 | For Image/IO, See Apple's documentation: https://developer.apple.com/documentation/imageio 17 | */ 18 | @interface SDImageIOAnimatedCoder : NSObject 19 | 20 | #pragma mark - Subclass Override 21 | /** 22 | The supported animated image format. Such as `SDImageFormatGIF`. 23 | @note Subclass override. 24 | */ 25 | @property (class, readonly) SDImageFormat imageFormat; 26 | /** 27 | The supported image format UTI Type. Such as `kUTTypeGIF`. 28 | This can be used for cases when we can not detect `SDImageFormat. Such as progressive decoding's hint format `kCGImageSourceTypeIdentifierHint`. 29 | @note Subclass override. 30 | */ 31 | @property (class, readonly, nonnull) NSString *imageUTType; 32 | /** 33 | The image container property key used in Image/IO API. Such as `kCGImagePropertyGIFDictionary`. 34 | @note Subclass override. 35 | */ 36 | @property (class, readonly, nonnull) NSString *dictionaryProperty; 37 | /** 38 | The image unclamped deply time property key used in Image/IO API. Such as `kCGImagePropertyGIFUnclampedDelayTime` 39 | @note Subclass override. 40 | */ 41 | @property (class, readonly, nonnull) NSString *unclampedDelayTimeProperty; 42 | /** 43 | The image delay time property key used in Image/IO API. Such as `kCGImagePropertyGIFDelayTime`. 44 | @note Subclass override. 45 | */ 46 | @property (class, readonly, nonnull) NSString *delayTimeProperty; 47 | /** 48 | The image loop count property key used in Image/IO API. Such as `kCGImagePropertyGIFLoopCount`. 49 | @note Subclass override. 50 | */ 51 | @property (class, readonly, nonnull) NSString *loopCountProperty; 52 | /** 53 | The default loop count when there are no any loop count information inside image container metadata. 54 | For example, for GIF format, the standard use 1 (play once). For APNG format, the standard use 0 (infinity loop). 55 | @note Subclass override. 56 | */ 57 | @property (class, readonly) NSUInteger defaultLoopCount; 58 | 59 | @end 60 | -------------------------------------------------------------------------------- /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 a 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/SDMemoryCache.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 SDImageCacheConfig; 12 | /** 13 | A protocol to allow custom memory cache used in SDImageCache. 14 | */ 15 | @protocol SDMemoryCache 16 | 17 | @required 18 | 19 | /** 20 | Create a new memory cache instance with the specify cache config. You can check `maxMemoryCost` and `maxMemoryCount` used for memory cache. 21 | 22 | @param config The cache config to be used to create the cache. 23 | @return The new memory cache instance. 24 | */ 25 | - (nonnull instancetype)initWithConfig:(nonnull SDImageCacheConfig *)config; 26 | 27 | /** 28 | Returns the value associated with a given key. 29 | 30 | @param key An object identifying the value. If nil, just return nil. 31 | @return The value associated with key, or nil if no value is associated with key. 32 | */ 33 | - (nullable id)objectForKey:(nonnull id)key; 34 | 35 | /** 36 | Sets the value of the specified key in the cache (0 cost). 37 | 38 | @param object The object to be stored in the cache. If nil, it calls `removeObjectForKey:`. 39 | @param key The key with which to associate the value. If nil, this method has no effect. 40 | @discussion Unlike an NSMutableDictionary object, a cache does not copy the key 41 | objects that are put into it. 42 | */ 43 | - (void)setObject:(nullable id)object forKey:(nonnull id)key; 44 | 45 | /** 46 | Sets the value of the specified key in the cache, and associates the key-value 47 | pair with the specified cost. 48 | 49 | @param object The object to store in the cache. If nil, it calls `removeObjectForKey`. 50 | @param key The key with which to associate the value. If nil, this method has no effect. 51 | @param cost The cost with which to associate the key-value pair. 52 | @discussion Unlike an NSMutableDictionary object, a cache does not copy the key 53 | objects that are put into it. 54 | */ 55 | - (void)setObject:(nullable id)object forKey:(nonnull id)key cost:(NSUInteger)cost; 56 | 57 | /** 58 | Removes the value of the specified key in the cache. 59 | 60 | @param key The key identifying the value to be removed. If nil, this method has no effect. 61 | */ 62 | - (void)removeObjectForKey:(nonnull id)key; 63 | 64 | /** 65 | Empties the cache immediately. 66 | */ 67 | - (void)removeAllObjects; 68 | 69 | @end 70 | 71 | /** 72 | A memory cache which auto purge the cache on memory warning and support weak cache. 73 | */ 74 | @interface SDMemoryCache : NSCache 75 | 76 | @property (nonatomic, strong, nonnull, readonly) SDImageCacheConfig *config; 77 | 78 | @end 79 | -------------------------------------------------------------------------------- /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 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.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 11 | 12 | #ifdef __OBJC_GC__ 13 | #error SDWebImage does not support Objective-C Garbage Collection 14 | #endif 15 | 16 | // Seems like TARGET_OS_MAC is always defined (on all platforms). 17 | // To determine if we are running on macOS, use TARGET_OS_OSX in Xcode 8 18 | #if TARGET_OS_OSX 19 | #define SD_MAC 1 20 | #else 21 | #define SD_MAC 0 22 | #endif 23 | 24 | // iOS and tvOS are very similar, UIKit exists on both platforms 25 | // Note: watchOS also has UIKit, but it's very limited 26 | #if TARGET_OS_IOS || TARGET_OS_TV 27 | #define SD_UIKIT 1 28 | #else 29 | #define SD_UIKIT 0 30 | #endif 31 | 32 | #if TARGET_OS_IOS 33 | #define SD_IOS 1 34 | #else 35 | #define SD_IOS 0 36 | #endif 37 | 38 | #if TARGET_OS_TV 39 | #define SD_TV 1 40 | #else 41 | #define SD_TV 0 42 | #endif 43 | 44 | #if TARGET_OS_WATCH 45 | #define SD_WATCH 1 46 | #else 47 | #define SD_WATCH 0 48 | #endif 49 | 50 | 51 | #if SD_MAC 52 | #import 53 | #ifndef UIImage 54 | #define UIImage NSImage 55 | #endif 56 | #ifndef UIImageView 57 | #define UIImageView NSImageView 58 | #endif 59 | #ifndef UIView 60 | #define UIView NSView 61 | #endif 62 | #ifndef UIColor 63 | #define UIColor NSColor 64 | #endif 65 | #else 66 | #if SD_UIKIT 67 | #import 68 | #endif 69 | #if SD_WATCH 70 | #import 71 | #ifndef UIView 72 | #define UIView WKInterfaceObject 73 | #endif 74 | #ifndef UIImageView 75 | #define UIImageView WKInterfaceImage 76 | #endif 77 | #endif 78 | #endif 79 | 80 | #ifndef NS_ENUM 81 | #define NS_ENUM(_type, _name) enum _name : _type _name; enum _name : _type 82 | #endif 83 | 84 | #ifndef NS_OPTIONS 85 | #define NS_OPTIONS(_type, _name) enum _name : _type _name; enum _name : _type 86 | #endif 87 | 88 | #ifndef dispatch_main_async_safe 89 | #define dispatch_main_async_safe(block)\ 90 | if (dispatch_queue_get_label(DISPATCH_CURRENT_QUEUE_LABEL) == dispatch_queue_get_label(dispatch_get_main_queue())) {\ 91 | block();\ 92 | } else {\ 93 | dispatch_async(dispatch_get_main_queue(), block);\ 94 | } 95 | #endif 96 | -------------------------------------------------------------------------------- /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 | 11 | static SDWebImageDownloaderConfig * _defaultDownloaderConfig; 12 | 13 | @implementation SDWebImageDownloaderConfig 14 | 15 | + (SDWebImageDownloaderConfig *)defaultDownloaderConfig { 16 | static dispatch_once_t onceToken; 17 | dispatch_once(&onceToken, ^{ 18 | _defaultDownloaderConfig = [SDWebImageDownloaderConfig new]; 19 | }); 20 | return _defaultDownloaderConfig; 21 | } 22 | 23 | - (instancetype)init { 24 | self = [super init]; 25 | if (self) { 26 | _maxConcurrentDownloads = 6; 27 | _downloadTimeout = 15.0; 28 | _executionOrder = SDWebImageDownloaderFIFOExecutionOrder; 29 | } 30 | return self; 31 | } 32 | 33 | - (id)copyWithZone:(NSZone *)zone { 34 | SDWebImageDownloaderConfig *config = [[[self class] allocWithZone:zone] init]; 35 | config.maxConcurrentDownloads = self.maxConcurrentDownloads; 36 | config.downloadTimeout = self.downloadTimeout; 37 | config.minimumProgressInterval = self.minimumProgressInterval; 38 | config.sessionConfiguration = [self.sessionConfiguration copyWithZone:zone]; 39 | config.operationClass = self.operationClass; 40 | config.executionOrder = self.executionOrder; 41 | config.urlCredential = self.urlCredential; 42 | config.username = self.username; 43 | config.password = self.password; 44 | 45 | return config; 46 | } 47 | 48 | 49 | @end 50 | -------------------------------------------------------------------------------- /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 perfereed algorithm. 21 | /// @param data The original download data 22 | /// @param response The URL response for data. If you modifiy 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 | - (nonnull instancetype)initWithBlock:(nonnull SDWebImageDownloaderDecryptorBlock)block; 34 | + (nonnull instancetype)decryptorWithBlock:(nonnull SDWebImageDownloaderDecryptorBlock)block; 35 | 36 | @end 37 | 38 | /// Convenience way to create decryptor for common data encryption. 39 | @interface SDWebImageDownloaderDecryptor (Conveniences) 40 | 41 | /// Base64 Encoded image data decryptor 42 | @property (class, readonly, nonnull) SDWebImageDownloaderDecryptor *base64Decryptor; 43 | 44 | @end 45 | -------------------------------------------------------------------------------- /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.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 NSURLRequest * _Nullable (^SDWebImageDownloaderRequestModifierBlock)(NSURLRequest * _Nonnull request); 13 | 14 | /** 15 | This is the protocol for downloader request modifier. 16 | We can use a block to specify the downloader request modifier. 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 SDWebImageDownloaderRequestModifier 19 | 20 | /// Modify the original URL request and return a new one instead. You can modify the HTTP header, cachePolicy, etc for this URL. 21 | /// @param request The original URL request for image loading 22 | /// @note If return nil, the URL request will be cancelled. 23 | - (nullable NSURLRequest *)modifiedRequestWithRequest:(nonnull NSURLRequest *)request; 24 | 25 | @end 26 | 27 | /** 28 | A downloader request modifier class with block. 29 | */ 30 | @interface SDWebImageDownloaderRequestModifier : NSObject 31 | 32 | - (nonnull instancetype)initWithBlock:(nonnull SDWebImageDownloaderRequestModifierBlock)block; 33 | + (nonnull instancetype)requestModifierWithBlock:(nonnull SDWebImageDownloaderRequestModifierBlock)block; 34 | 35 | @end 36 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /Example/Pods/SDWebImage/SDWebImage/Core/SDWebImageDownloaderResponseModifier.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 NSURLResponse * _Nullable (^SDWebImageDownloaderResponseModifierBlock)(NSURLResponse * _Nonnull response); 13 | 14 | /** 15 | This is the protocol for downloader response modifier. 16 | We can use a block to specify the downloader response modifier. 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 SDWebImageDownloaderResponseModifier 19 | 20 | /// Modify the original URL response and return a new response. You can use this to check MIME-Type, mock server response, etc. 21 | /// @param response The original URL response, note for HTTP request it's actually a `NSHTTPURLResponse` instance 22 | /// @note If nil is returned, the image download will marked as cancelled with error `SDWebImageErrorInvalidDownloadResponse` 23 | - (nullable NSURLResponse *)modifiedResponseWithResponse:(nonnull NSURLResponse *)response; 24 | 25 | @end 26 | 27 | /** 28 | A downloader response modifier class with block. 29 | */ 30 | @interface SDWebImageDownloaderResponseModifier : NSObject 31 | 32 | - (nonnull instancetype)initWithBlock:(nonnull SDWebImageDownloaderResponseModifierBlock)block; 33 | + (nonnull instancetype)responseModifierWithBlock:(nonnull SDWebImageDownloaderResponseModifierBlock)block; 34 | 35 | @end 36 | -------------------------------------------------------------------------------- /Example/Pods/SDWebImage/SDWebImage/Core/SDWebImageDownloaderResponseModifier.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 | 10 | #import "SDWebImageDownloaderResponseModifier.h" 11 | 12 | @interface SDWebImageDownloaderResponseModifier () 13 | 14 | @property (nonatomic, copy, nonnull) SDWebImageDownloaderResponseModifierBlock block; 15 | 16 | @end 17 | 18 | @implementation SDWebImageDownloaderResponseModifier 19 | 20 | - (instancetype)initWithBlock:(SDWebImageDownloaderResponseModifierBlock)block { 21 | self = [super init]; 22 | if (self) { 23 | self.block = block; 24 | } 25 | return self; 26 | } 27 | 28 | + (instancetype)responseModifierWithBlock:(SDWebImageDownloaderResponseModifierBlock)block { 29 | SDWebImageDownloaderResponseModifier *responseModifier = [[SDWebImageDownloaderResponseModifier alloc] initWithBlock:block]; 30 | return responseModifier; 31 | } 32 | 33 | - (nullable NSURLResponse *)modifiedResponseWithResponse:(nonnull NSURLResponse *)response { 34 | if (!self.block) { 35 | return nil; 36 | } 37 | return self.block(response); 38 | } 39 | 40 | @end 41 | -------------------------------------------------------------------------------- /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 | FOUNDATION_EXPORT NSErrorDomain const _Nonnull SDWebImageErrorDomain; 13 | 14 | /// The HTTP status code for invalid download response (NSNumber *) 15 | FOUNDATION_EXPORT NSErrorUserInfoKey const _Nonnull SDWebImageErrorDownloadStatusCodeKey; 16 | 17 | /// SDWebImage error domain and codes 18 | typedef NS_ERROR_ENUM(SDWebImageErrorDomain, SDWebImageError) { 19 | SDWebImageErrorInvalidURL = 1000, // The URL is invalid, such as nil URL or corrupted URL 20 | SDWebImageErrorBadImageData = 1001, // The image data can not be decoded to image, or the image data is empty 21 | 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` 22 | SDWebImageErrorInvalidDownloadOperation = 2000, // The image download operation is invalid, such as nil operation or unexpected error occur when operation initialized 23 | SDWebImageErrorInvalidDownloadStatusCode = 2001, // The image download response a invalid status code. You can check the status code in error's userInfo under `SDWebImageErrorDownloadStatusCodeKey` 24 | 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. 25 | SDWebImageErrorInvalidDownloadResponse = 2003, // When using response modifier, the modified download response is nil and marked as cancelled. 26 | }; 27 | -------------------------------------------------------------------------------- /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 | NSErrorUserInfoKey const _Nonnull SDWebImageErrorDownloadStatusCodeKey = @"SDWebImageErrorDownloadStatusCodeKey"; 14 | -------------------------------------------------------------------------------- /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 | - (void)cancel; 15 | 16 | @end 17 | 18 | /// NSOperation conform to `SDWebImageOperation`. 19 | @interface NSOperation (SDWebImageOperation) 20 | 21 | @end 22 | -------------------------------------------------------------------------------- /Example/Pods/SDWebImage/SDWebImage/Core/SDWebImageOptionsProcessor.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 "SDWebImageDefine.h" 12 | 13 | @class SDWebImageOptionsResult; 14 | 15 | typedef SDWebImageOptionsResult * _Nullable(^SDWebImageOptionsProcessorBlock)(NSURL * _Nullable url, SDWebImageOptions options, SDWebImageContext * _Nullable context); 16 | 17 | /** 18 | The options result contains both options and context. 19 | */ 20 | @interface SDWebImageOptionsResult : NSObject 21 | 22 | /** 23 | WebCache options. 24 | */ 25 | @property (nonatomic, assign, readonly) SDWebImageOptions options; 26 | 27 | /** 28 | Context options. 29 | */ 30 | @property (nonatomic, copy, readonly, nullable) SDWebImageContext *context; 31 | 32 | /** 33 | Create a new options result. 34 | 35 | @param options options 36 | @param context context 37 | @return The options result contains both options and context. 38 | */ 39 | - (nonnull instancetype)initWithOptions:(SDWebImageOptions)options context:(nullable SDWebImageContext *)context; 40 | 41 | @end 42 | 43 | /** 44 | This is the protocol for options processor. 45 | Options processor can be used, to control the final result for individual image request's `SDWebImageOptions` and `SDWebImageContext` 46 | Implements the protocol to have a global control for each indivadual image request's option. 47 | */ 48 | @protocol SDWebImageOptionsProcessor 49 | 50 | /** 51 | Return the processed options result for specify image URL, with its options and context 52 | 53 | @param url The URL to the image 54 | @param options A mask to specify options to use for this request 55 | @param context A context contains different options to perform specify changes or processes, see `SDWebImageContextOption`. This hold the extra objects which `options` enum can not hold. 56 | @return The processed result, contains both options and context 57 | */ 58 | - (nullable SDWebImageOptionsResult *)processedResultForURL:(nullable NSURL *)url 59 | options:(SDWebImageOptions)options 60 | context:(nullable SDWebImageContext *)context; 61 | 62 | @end 63 | 64 | /** 65 | A options processor class with block. 66 | */ 67 | @interface SDWebImageOptionsProcessor : NSObject 68 | 69 | - (nonnull instancetype)initWithBlock:(nonnull SDWebImageOptionsProcessorBlock)block; 70 | + (nonnull instancetype)optionsProcessorWithBlock:(nonnull SDWebImageOptionsProcessorBlock)block; 71 | 72 | @end 73 | -------------------------------------------------------------------------------- /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 | */ 19 | @property (nonatomic, assign) BOOL sd_isDecoded; 20 | 21 | /** 22 | Decode the provided image. This is useful if you want to force decode the image before rendering to improve performance. 23 | 24 | @param image The image to be decoded 25 | @return The decoded image 26 | */ 27 | + (nullable UIImage *)sd_decodedImageWithImage:(nullable UIImage *)image; 28 | 29 | /** 30 | Decode and scale down the provided image 31 | 32 | @param image The image to be decoded 33 | @return The decoded and scaled down image 34 | */ 35 | + (nullable UIImage *)sd_decodedAndScaledDownImageWithImage:(nullable UIImage *)image; 36 | 37 | /** 38 | Decode and scale down the provided image with limit bytes 39 | 40 | @param image The image to be decoded 41 | @param bytes The limit bytes size. Provide 0 to use the build-in limit. 42 | @return The decoded and scaled down image 43 | */ 44 | + (nullable UIImage *)sd_decodedAndScaledDownImageWithImage:(nullable UIImage *)image limitBytes:(NSUInteger)bytes; 45 | 46 | @end 47 | -------------------------------------------------------------------------------- /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 | 13 | @implementation UIImage (ForceDecode) 14 | 15 | - (BOOL)sd_isDecoded { 16 | NSNumber *value = objc_getAssociatedObject(self, @selector(sd_isDecoded)); 17 | return value.boolValue; 18 | } 19 | 20 | - (void)setSd_isDecoded:(BOOL)sd_isDecoded { 21 | objc_setAssociatedObject(self, @selector(sd_isDecoded), @(sd_isDecoded), OBJC_ASSOCIATION_RETAIN_NONATOMIC); 22 | } 23 | 24 | + (nullable UIImage *)sd_decodedImageWithImage:(nullable UIImage *)image { 25 | if (!image) { 26 | return nil; 27 | } 28 | return [SDImageCoderHelper decodedImageWithImage:image]; 29 | } 30 | 31 | + (nullable UIImage *)sd_decodedAndScaledDownImageWithImage:(nullable UIImage *)image { 32 | return [self sd_decodedAndScaledDownImageWithImage:image limitBytes:0]; 33 | } 34 | 35 | + (nullable UIImage *)sd_decodedAndScaledDownImageWithImage:(nullable UIImage *)image limitBytes:(NSUInteger)bytes { 36 | if (!image) { 37 | return nil; 38 | } 39 | return [SDImageCoderHelper decodedAndScaledDownImageWithImage:image limitBytes:bytes]; 40 | } 41 | 42 | @end 43 | -------------------------------------------------------------------------------- /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 directlly 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. Retuen 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 | frameCount = image.images.count > 0 ? image.images.count : 1; 24 | #endif 25 | NSUInteger cost = bytesPerFrame * frameCount; 26 | return cost; 27 | } 28 | 29 | @implementation UIImage (MemoryCacheCost) 30 | 31 | - (NSUInteger)sd_memoryCost { 32 | NSNumber *value = objc_getAssociatedObject(self, @selector(sd_memoryCost)); 33 | NSUInteger memoryCost; 34 | if (value != nil) { 35 | memoryCost = [value unsignedIntegerValue]; 36 | } else { 37 | memoryCost = SDMemoryCacheCostForImage(self); 38 | } 39 | return memoryCost; 40 | } 41 | 42 | - (void)setSd_memoryCost:(NSUInteger)sd_memoryCost { 43 | objc_setAssociatedObject(self, @selector(sd_memoryCost), @(sd_memoryCost), OBJC_ASSOCIATION_RETAIN_NONATOMIC); 44 | } 45 | 46 | @end 47 | -------------------------------------------------------------------------------- /Example/Pods/SDWebImage/SDWebImage/Core/UIImage+Metadata.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 "NSData+ImageContentType.h" 11 | 12 | /** 13 | UIImage category for image metadata, including animation, loop count, format, incremental, etc. 14 | */ 15 | @interface UIImage (Metadata) 16 | 17 | /** 18 | * UIKit: 19 | * For static image format, this value is always 0. 20 | * For animated image format, 0 means infinite looping. 21 | * Note that because of the limitations of categories this property can get out of sync if you create another instance with CGImage or other methods. 22 | * AppKit: 23 | * NSImage currently only support animated via GIF imageRep unlike UIImage. 24 | * The getter of this property will get the loop count from GIF imageRep 25 | * The setter of this property will set the loop count from GIF imageRep 26 | */ 27 | @property (nonatomic, assign) NSUInteger sd_imageLoopCount; 28 | 29 | /** 30 | * UIKit: 31 | * Check the `images` array property 32 | * AppKit: 33 | * NSImage currently only support animated via GIF imageRep unlike UIImage. It will check the imageRep's frame count. 34 | */ 35 | @property (nonatomic, assign, readonly) BOOL sd_isAnimated; 36 | 37 | /** 38 | * The image format represent the original compressed image data format. 39 | * If you don't manually specify a format, this information is retrieve from CGImage using `CGImageGetUTType`, which may return nil for non-CG based image. At this time it will return `SDImageFormatUndefined` as default value. 40 | * @note Note that because of the limitations of categories this property can get out of sync if you create another instance with CGImage or other methods. 41 | */ 42 | @property (nonatomic, assign) SDImageFormat sd_imageFormat; 43 | 44 | /** 45 | A bool value indicating whether the image is during incremental decoding and may not contains full pixels. 46 | */ 47 | @property (nonatomic, assign) BOOL sd_isIncremental; 48 | 49 | @end 50 | -------------------------------------------------------------------------------- /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 | 12 | @implementation UIImage (MultiFormat) 13 | 14 | + (nullable UIImage *)sd_imageWithData:(nullable NSData *)data { 15 | return [self sd_imageWithData:data scale:1]; 16 | } 17 | 18 | + (nullable UIImage *)sd_imageWithData:(nullable NSData *)data scale:(CGFloat)scale { 19 | return [self sd_imageWithData:data scale:scale firstFrameOnly:NO]; 20 | } 21 | 22 | + (nullable UIImage *)sd_imageWithData:(nullable NSData *)data scale:(CGFloat)scale firstFrameOnly:(BOOL)firstFrameOnly { 23 | if (!data) { 24 | return nil; 25 | } 26 | SDImageCoderOptions *options = @{SDImageCoderDecodeScaleFactor : @(MAX(scale, 1)), SDImageCoderDecodeFirstFrameOnly : @(firstFrameOnly)}; 27 | return [[SDImageCodersManager sharedManager] decodedImageWithData:data options:options]; 28 | } 29 | 30 | - (nullable NSData *)sd_imageData { 31 | return [self sd_imageDataAsFormat:SDImageFormatUndefined]; 32 | } 33 | 34 | - (nullable NSData *)sd_imageDataAsFormat:(SDImageFormat)imageFormat { 35 | return [self sd_imageDataAsFormat:imageFormat compressionQuality:1]; 36 | } 37 | 38 | - (nullable NSData *)sd_imageDataAsFormat:(SDImageFormat)imageFormat compressionQuality:(double)compressionQuality { 39 | return [self sd_imageDataAsFormat:imageFormat compressionQuality:compressionQuality firstFrameOnly:NO]; 40 | } 41 | 42 | - (nullable NSData *)sd_imageDataAsFormat:(SDImageFormat)imageFormat compressionQuality:(double)compressionQuality firstFrameOnly:(BOOL)firstFrameOnly { 43 | SDImageCoderOptions *options = @{SDImageCoderEncodeCompressionQuality : @(compressionQuality), SDImageCoderEncodeFirstFrameOnly : @(firstFrameOnly)}; 44 | return [[SDImageCodersManager sharedManager] encodedDataWithImage:self format:imageFormat options:options]; 45 | } 46 | 47 | @end 48 | -------------------------------------------------------------------------------- /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 dalloced 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 | */ 24 | - (nullable id)sd_imageLoadOperationForKey:(nullable NSString *)key; 25 | 26 | /** 27 | * Set the image load operation (storage in a UIView based weak map table) 28 | * 29 | * @param operation the operation 30 | * @param key key for storing the operation 31 | */ 32 | - (void)sd_setImageLoadOperation:(nullable id)operation forKey:(nullable NSString *)key; 33 | 34 | /** 35 | * Cancel all operations for the current UIView and key 36 | * 37 | * @param key key for identifying the operations 38 | */ 39 | - (void)sd_cancelImageLoadOperationWithKey:(nullable NSString *)key; 40 | 41 | /** 42 | * Just remove the operations corresponding to the current UIView and key without cancelling them 43 | * 44 | * @param key key for identifying the operations 45 | */ 46 | - (void)sd_removeImageLoadOperationWithKey:(nullable NSString *)key; 47 | 48 | @end 49 | -------------------------------------------------------------------------------- /Example/Pods/SDWebImage/SDWebImage/Private/NSBezierPath+RoundedCorners.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 (RoundedCorners) 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+RoundedCorners.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+RoundedCorners.h" 10 | 11 | #if SD_MAC 12 | 13 | @implementation NSBezierPath (RoundedCorners) 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_imageLoopCount = source.sd_imageLoopCount; 22 | target.sd_imageFormat = source.sd_imageFormat; 23 | // Force Decode 24 | target.sd_isDecoded = source.sd_isDecoded; 25 | // Extended Cache Data 26 | target.sd_extendedObject = source.sd_extendedObject; 27 | } 28 | -------------------------------------------------------------------------------- /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 | @interface SDAsyncBlockOperation : NSOperation 15 | 16 | - (nonnull instancetype)initWithBlock:(nonnull SDAsyncBlock)block; 17 | + (nonnull instancetype)blockOperationWithBlock:(nonnull SDAsyncBlock)block; 18 | - (void)complete; 19 | 20 | @end 21 | -------------------------------------------------------------------------------- /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 | 11 | @interface SDAsyncBlockOperation () 12 | 13 | @property (assign, nonatomic, getter = isExecuting) BOOL executing; 14 | @property (assign, nonatomic, getter = isFinished) BOOL finished; 15 | @property (nonatomic, copy, nonnull) SDAsyncBlock executionBlock; 16 | 17 | @end 18 | 19 | @implementation SDAsyncBlockOperation 20 | 21 | @synthesize executing = _executing; 22 | @synthesize finished = _finished; 23 | 24 | - (nonnull instancetype)initWithBlock:(nonnull SDAsyncBlock)block { 25 | self = [super init]; 26 | if (self) { 27 | self.executionBlock = block; 28 | } 29 | return self; 30 | } 31 | 32 | + (nonnull instancetype)blockOperationWithBlock:(nonnull SDAsyncBlock)block { 33 | SDAsyncBlockOperation *operation = [[SDAsyncBlockOperation alloc] initWithBlock:block]; 34 | return operation; 35 | } 36 | 37 | - (void)start { 38 | if (self.isCancelled) { 39 | return; 40 | } 41 | 42 | [self willChangeValueForKey:@"isExecuting"]; 43 | self.executing = YES; 44 | [self didChangeValueForKey:@"isExecuting"]; 45 | 46 | if (self.executionBlock) { 47 | self.executionBlock(self); 48 | } else { 49 | [self complete]; 50 | } 51 | } 52 | 53 | - (void)cancel { 54 | [super cancel]; 55 | [self complete]; 56 | } 57 | 58 | - (void)complete { 59 | [self willChangeValueForKey:@"isExecuting"]; 60 | [self willChangeValueForKey:@"isFinished"]; 61 | self.executing = NO; 62 | self.finished = YES; 63 | [self didChangeValueForKey:@"isExecuting"]; 64 | [self didChangeValueForKey:@"isFinished"]; 65 | } 66 | 67 | @end 68 | -------------------------------------------------------------------------------- /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 | @interface SDDeviceHelper : NSObject 13 | 14 | + (NSUInteger)totalMemory; 15 | + (NSUInteger)freeMemory; 16 | 17 | @end 18 | -------------------------------------------------------------------------------- /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 | 12 | @implementation SDDeviceHelper 13 | 14 | + (NSUInteger)totalMemory { 15 | return (NSUInteger)[[NSProcessInfo processInfo] physicalMemory]; 16 | } 17 | 18 | + (NSUInteger)freeMemory { 19 | mach_port_t host_port = mach_host_self(); 20 | mach_msg_type_number_t host_size = sizeof(vm_statistics_data_t) / sizeof(integer_t); 21 | vm_size_t page_size; 22 | vm_statistics_data_t vm_stat; 23 | kern_return_t kern; 24 | 25 | kern = host_page_size(host_port, &page_size); 26 | if (kern != KERN_SUCCESS) return 0; 27 | kern = host_statistics(host_port, HOST_VM_INFO, (host_info_t)&vm_stat, &host_size); 28 | if (kern != KERN_SUCCESS) return 0; 29 | return vm_stat.free_count * page_size; 30 | } 31 | 32 | @end 33 | -------------------------------------------------------------------------------- /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 | 15 | @interface SDDisplayLink : NSObject 16 | 17 | @property (readonly, nonatomic, weak, nullable) id target; 18 | @property (readonly, nonatomic, assign, nonnull) SEL selector; 19 | @property (readonly, nonatomic) CFTimeInterval duration; 20 | @property (readonly, nonatomic) BOOL isRunning; 21 | 22 | + (nonnull instancetype)displayLinkWithTarget:(nonnull id)target selector:(nonnull SEL)sel; 23 | 24 | - (void)addToRunLoop:(nonnull NSRunLoop *)runloop forMode:(nonnull NSRunLoopMode)mode; 25 | - (void)removeFromRunLoop:(nonnull NSRunLoop *)runloop forMode:(nonnull NSRunLoopMode)mode; 26 | 27 | - (void)start; 28 | - (void)stop; 29 | 30 | @end 31 | -------------------------------------------------------------------------------- /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 | @interface SDFileAttributeHelper : NSObject 11 | 12 | + (NSArray*)extendedAttributeNamesAtPath:(NSString*)path traverseLink:(BOOL)follow error:(NSError**)err; 13 | + (BOOL)hasExtendedAttribute:(NSString*)name atPath:(NSString*)path traverseLink:(BOOL)follow error:(NSError**)err; 14 | + (NSData*)extendedAttribute:(NSString*)name atPath:(NSString*)path traverseLink:(BOOL)follow error:(NSError**)err; 15 | + (BOOL)setExtendedAttribute:(NSString*)name value:(NSData*)value atPath:(NSString*)path traverseLink:(BOOL)follow overwrite:(BOOL)overwrite error:(NSError**)err; 16 | + (BOOL)removeExtendedAttribute:(NSString*)name atPath:(NSString*)path traverseLink:(BOOL)follow error:(NSError**)err; 17 | 18 | @end 19 | -------------------------------------------------------------------------------- /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 | // 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 :) 13 | 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 | { 14 | dispatch_semaphore_t _pendingCountLock; 15 | } 16 | 17 | @synthesize executing = _executing; 18 | @synthesize finished = _finished; 19 | @synthesize cancelled = _cancelled; 20 | @synthesize pendingCount = _pendingCount; 21 | 22 | - (instancetype)init { 23 | if (self = [super init]) { 24 | _pendingCountLock = dispatch_semaphore_create(1); 25 | _pendingCount = 0; 26 | } 27 | return self; 28 | } 29 | 30 | - (void)beginWithTotalCount:(NSUInteger)totalCount { 31 | self.executing = YES; 32 | self.finished = NO; 33 | _pendingCount = totalCount; 34 | } 35 | 36 | - (NSUInteger)pendingCount { 37 | SD_LOCK(_pendingCountLock); 38 | NSUInteger pendingCount = _pendingCount; 39 | SD_UNLOCK(_pendingCountLock); 40 | return pendingCount; 41 | } 42 | 43 | - (void)completeOne { 44 | SD_LOCK(_pendingCountLock); 45 | _pendingCount = _pendingCount > 0 ? _pendingCount - 1 : 0; 46 | SD_UNLOCK(_pendingCountLock); 47 | } 48 | 49 | - (void)cancel { 50 | self.cancelled = YES; 51 | [self reset]; 52 | } 53 | 54 | - (void)done { 55 | self.finished = YES; 56 | self.executing = NO; 57 | [self reset]; 58 | } 59 | 60 | - (void)reset { 61 | SD_LOCK(_pendingCountLock); 62 | _pendingCount = 0; 63 | SD_UNLOCK(_pendingCountLock); 64 | } 65 | 66 | - (void)setFinished:(BOOL)finished { 67 | [self willChangeValueForKey:@"isFinished"]; 68 | _finished = finished; 69 | [self didChangeValueForKey:@"isFinished"]; 70 | } 71 | 72 | - (void)setExecuting:(BOOL)executing { 73 | [self willChangeValueForKey:@"isExecuting"]; 74 | _executing = executing; 75 | [self didChangeValueForKey:@"isExecuting"]; 76 | } 77 | 78 | - (void)setCancelled:(BOOL)cancelled { 79 | [self willChangeValueForKey:@"isCancelled"]; 80 | _cancelled = cancelled; 81 | [self didChangeValueForKey:@"isCancelled"]; 82 | } 83 | 84 | @end 85 | -------------------------------------------------------------------------------- /Example/Pods/SDWebImage/SDWebImage/Private/SDImageHEICCoderInternal.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 "SDImageHEICCoder.h" 11 | 12 | // AVFileTypeHEIC/AVFileTypeHEIF is defined in AVFoundation via iOS 11, we use this without import AVFoundation 13 | #define kSDUTTypeHEIC ((__bridge CFStringRef)@"public.heic") 14 | #define kSDUTTypeHEIF ((__bridge CFStringRef)@"public.heif") 15 | // HEIC Sequence (Animated Image) 16 | #define kSDUTTypeHEICS ((__bridge CFStringRef)@"public.heics") 17 | 18 | @interface SDImageHEICCoder () 19 | 20 | + (BOOL)canDecodeFromHEICFormat; 21 | + (BOOL)canDecodeFromHEIFFormat; 22 | + (BOOL)canEncodeToHEICFormat; 23 | + (BOOL)canEncodeToHEIFFormat; 24 | 25 | @end 26 | -------------------------------------------------------------------------------- /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 "SDImageIOAnimatedCoder.h" 11 | 12 | @interface SDImageIOAnimatedCoder () 13 | 14 | + (NSTimeInterval)frameDurationAtIndex:(NSUInteger)index source:(nonnull CGImageSourceRef)source; 15 | + (NSUInteger)imageLoopCountWithSource:(nonnull CGImageSourceRef)source; 16 | 17 | @end 18 | -------------------------------------------------------------------------------- /Example/Pods/SDWebImage/SDWebImage/Private/SDInternalMacros.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 "SDmetamacros.h" 11 | 12 | #ifndef SD_LOCK 13 | #define SD_LOCK(lock) dispatch_semaphore_wait(lock, DISPATCH_TIME_FOREVER); 14 | #endif 15 | 16 | #ifndef SD_UNLOCK 17 | #define SD_UNLOCK(lock) dispatch_semaphore_signal(lock); 18 | #endif 19 | 20 | #ifndef SD_OPTIONS_CONTAINS 21 | #define SD_OPTIONS_CONTAINS(options, value) (((options) & (value)) == (value)) 22 | #endif 23 | 24 | #ifndef weakify 25 | #define weakify(...) \ 26 | sd_keywordify \ 27 | metamacro_foreach_cxt(sd_weakify_,, __weak, __VA_ARGS__) 28 | #endif 29 | 30 | #ifndef strongify 31 | #define strongify(...) \ 32 | sd_keywordify \ 33 | _Pragma("clang diagnostic push") \ 34 | _Pragma("clang diagnostic ignored \"-Wshadow\"") \ 35 | metamacro_foreach(sd_strongify_,, __VA_ARGS__) \ 36 | _Pragma("clang diagnostic pop") 37 | #endif 38 | 39 | #define sd_weakify_(INDEX, CONTEXT, VAR) \ 40 | CONTEXT __typeof__(VAR) metamacro_concat(VAR, _weak_) = (VAR); 41 | 42 | #define sd_strongify_(INDEX, VAR) \ 43 | __strong __typeof__(VAR) VAR = metamacro_concat(VAR, _weak_); 44 | 45 | #if DEBUG 46 | #define sd_keywordify autoreleasepool {} 47 | #else 48 | #define sd_keywordify try {} @catch (...) {} 49 | #endif 50 | 51 | #ifndef onExit 52 | #define onExit \ 53 | sd_keywordify \ 54 | __strong sd_cleanupBlock_t metamacro_concat(sd_exitBlock_, __LINE__) __attribute__((cleanup(sd_executeCleanupBlock), unused)) = ^ 55 | #endif 56 | 57 | typedef void (^sd_cleanupBlock_t)(void); 58 | 59 | #if defined(__cplusplus) 60 | extern "C" { 61 | #endif 62 | void sd_executeCleanupBlock (__strong sd_cleanupBlock_t *block); 63 | #if defined(__cplusplus) 64 | } 65 | #endif 66 | -------------------------------------------------------------------------------- /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 | void sd_executeCleanupBlock (__strong sd_cleanupBlock_t *block) { 12 | (*block)(); 13 | } 14 | -------------------------------------------------------------------------------- /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 | @interface SDWeakProxy : NSProxy 13 | 14 | @property (nonatomic, weak, readonly, nullable) id target; 15 | 16 | - (nonnull instancetype)initWithTarget:(nonnull id)target; 17 | + (nonnull instancetype)proxyWithTarget:(nonnull id)target; 18 | 19 | @end 20 | -------------------------------------------------------------------------------- /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/UIColor+HexString.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 (HexString) 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+HexString.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+HexString.h" 10 | 11 | @implementation UIColor (HexString) 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/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 | 5.12.0 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 | #import "Kingfisher.h" 14 | 15 | FOUNDATION_EXPORT double KingfisherVersionNumber; 16 | FOUNDATION_EXPORT const unsigned char KingfisherVersionString[]; 17 | 18 | -------------------------------------------------------------------------------- /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) "${DT_TOOLCHAIN_DIR}/usr/lib/swift/${PLATFORM_NAME}" /usr/lib/swift 5 | OTHER_LDFLAGS = $(inherited) -framework "Accelerate" -framework "CFNetwork" 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) "${DT_TOOLCHAIN_DIR}/usr/lib/swift/${PLATFORM_NAME}" /usr/lib/swift 5 | OTHER_LDFLAGS = $(inherited) -framework "Accelerate" -framework "CFNetwork" 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/Lantern/Lantern-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.1.4 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | ${CURRENT_PROJECT_VERSION} 23 | NSPrincipalClass 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/Lantern/Lantern-dummy.m: -------------------------------------------------------------------------------- 1 | #import 2 | @interface PodsDummy_Lantern : NSObject 3 | @end 4 | @implementation PodsDummy_Lantern 5 | @end 6 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/Lantern/Lantern-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/Lantern/Lantern-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 LanternVersionNumber; 15 | FOUNDATION_EXPORT const unsigned char LanternVersionString[]; 16 | 17 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/Lantern/Lantern.debug.xcconfig: -------------------------------------------------------------------------------- 1 | CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = NO 2 | CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/Lantern 3 | GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 4 | LIBRARY_SEARCH_PATHS = $(inherited) "${DT_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/Lantern/Lantern.modulemap: -------------------------------------------------------------------------------- 1 | framework module Lantern { 2 | umbrella header "Lantern-umbrella.h" 3 | 4 | export * 5 | module * { export * } 6 | } 7 | -------------------------------------------------------------------------------- /Example/Pods/Target Support Files/Lantern/Lantern.release.xcconfig: -------------------------------------------------------------------------------- 1 | CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = NO 2 | CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/Lantern 3 | GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 4 | LIBRARY_SEARCH_PATHS = $(inherited) "${DT_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/Lantern/Lantern.xcconfig: -------------------------------------------------------------------------------- 1 | CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/Lantern 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/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}/Kingfisher/Kingfisher.framework 3 | ${BUILT_PRODUCTS_DIR}/Lantern/Lantern.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}/Kingfisher.framework 2 | ${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/Lantern.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}/Kingfisher/Kingfisher.framework 3 | ${BUILT_PRODUCTS_DIR}/Lantern/Lantern.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}/Kingfisher.framework 2 | ${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/Lantern.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}/Kingfisher" "${PODS_CONFIGURATION_BUILD_DIR}/Lantern" "${PODS_CONFIGURATION_BUILD_DIR}/SDWebImage" 4 | GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 5 | HEADER_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/Kingfisher/Kingfisher.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/Lantern/Lantern.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) "${DT_TOOLCHAIN_DIR}/usr/lib/swift/${PLATFORM_NAME}" /usr/lib/swift 8 | OTHER_LDFLAGS = $(inherited) -framework "Accelerate" -framework "CFNetwork" -framework "ImageIO" -framework "Kingfisher" -framework "Lantern" -framework "SDWebImage" 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}/Kingfisher" "${PODS_CONFIGURATION_BUILD_DIR}/Lantern" "${PODS_CONFIGURATION_BUILD_DIR}/SDWebImage" 4 | GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 5 | HEADER_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/Kingfisher/Kingfisher.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/Lantern/Lantern.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) "${DT_TOOLCHAIN_DIR}/usr/lib/swift/${PLATFORM_NAME}" /usr/lib/swift 8 | OTHER_LDFLAGS = $(inherited) -framework "Accelerate" -framework "CFNetwork" -framework "ImageIO" -framework "Kingfisher" -framework "Lantern" -framework "SDWebImage" 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/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.4.0 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 "SDDiskCache.h" 22 | #import "SDImageAPNGCoder.h" 23 | #import "SDImageCache.h" 24 | #import "SDImageCacheConfig.h" 25 | #import "SDImageCacheDefine.h" 26 | #import "SDImageCachesManager.h" 27 | #import "SDImageCoder.h" 28 | #import "SDImageCoderHelper.h" 29 | #import "SDImageCodersManager.h" 30 | #import "SDImageFrame.h" 31 | #import "SDImageGIFCoder.h" 32 | #import "SDImageGraphics.h" 33 | #import "SDImageHEICCoder.h" 34 | #import "SDImageIOAnimatedCoder.h" 35 | #import "SDImageIOCoder.h" 36 | #import "SDImageLoader.h" 37 | #import "SDImageLoadersManager.h" 38 | #import "SDImageTransformer.h" 39 | #import "SDMemoryCache.h" 40 | #import "SDWebImageCacheKeyFilter.h" 41 | #import "SDWebImageCacheSerializer.h" 42 | #import "SDWebImageCompat.h" 43 | #import "SDWebImageDefine.h" 44 | #import "SDWebImageDownloader.h" 45 | #import "SDWebImageDownloaderConfig.h" 46 | #import "SDWebImageDownloaderDecryptor.h" 47 | #import "SDWebImageDownloaderOperation.h" 48 | #import "SDWebImageDownloaderRequestModifier.h" 49 | #import "SDWebImageDownloaderResponseModifier.h" 50 | #import "SDWebImageError.h" 51 | #import "SDWebImageIndicator.h" 52 | #import "SDWebImageManager.h" 53 | #import "SDWebImageOperation.h" 54 | #import "SDWebImageOptionsProcessor.h" 55 | #import "SDWebImagePrefetcher.h" 56 | #import "SDWebImageTransition.h" 57 | #import "UIButton+WebCache.h" 58 | #import "UIImage+ExtendedCacheData.h" 59 | #import "UIImage+ForceDecode.h" 60 | #import "UIImage+GIF.h" 61 | #import "UIImage+MemoryCacheCost.h" 62 | #import "UIImage+Metadata.h" 63 | #import "UIImage+MultiFormat.h" 64 | #import "UIImage+Transform.h" 65 | #import "UIImageView+HighlightedWebCache.h" 66 | #import "UIImageView+WebCache.h" 67 | #import "UIView+WebCache.h" 68 | #import "UIView+WebCacheOperation.h" 69 | #import "SDWebImage.h" 70 | 71 | FOUNDATION_EXPORT double SDWebImageVersionNumber; 72 | FOUNDATION_EXPORT const unsigned char SDWebImageVersionString[]; 73 | 74 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /Lantern.podspec: -------------------------------------------------------------------------------- 1 | 2 | Pod::Spec.new do |s| 3 | s.name = 'Lantern' 4 | s.version = '1.1.5' 5 | s.summary = 'Elegant photo and video browser in Swift.' 6 | s.description = 'Elegant photo and video browser in Swift. Inspired by WeChat.' 7 | 8 | s.homepage = 'https://github.com/fcbox/Lantern' 9 | s.license = { :type => 'Apache-2.0', :file => 'LICENSE' } 10 | s.author = { 'JiongXing' => 'liangjiongxing@qq.com' } 11 | s.source = { :git => 'https://github.com/fcbox/Lantern.git', :tag => s.version.to_s } 12 | 13 | s.ios.deployment_target = '9.0' 14 | s.swift_version = '4.2', '5.0' 15 | s.source_files = 'Sources/Lantern/*' 16 | 17 | end 18 | -------------------------------------------------------------------------------- /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: "Lantern", 8 | products: [ 9 | // Products define the executables and libraries produced by a package, and make them visible to other packages. 10 | .library( 11 | name: "Lantern", 12 | targets: ["Lantern"]), 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: "Lantern", 23 | dependencies: []), 24 | ] 25 | ) 26 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Lantern(花灯) 2 | 3 | ![](https://github.com/fcbox/Lantern/raw/master/Assets/Banner.png) 4 | 5 | 6 | Lantern(花灯)是一个基于Swift的高可用视图框架。它基于iOS原生的图片/视频浏览功能进行封装,并提供了更加酷炫的交互方式。此外,它还提供丰富的接口,扩展灵活,能让App快速集成浏览功能。 7 | 8 | 经过我们一年多的试用和改进,现将Lantern面向社区开源,希望和大家一起改进App图片/视频浏览交互,提供更好的用户体验。 9 | 10 | 本项目由丰巢研发团队开发维护,并基于[Apache-2.0协议](http://www.apache.org/licenses/LICENSE-2.0)开源的项目,源地址为:[https://github.com/JiongXing/PhotoBrowser](https://github.com/JiongXing/PhotoBrowser)。后续将逐步全面迁移到此处,敬请留意。 11 | 12 | 13 | ## 效果预览 14 | 15 |
16 | 17 | 18 |
19 | 20 | ## 特性 21 | 22 | - [x] 基于纯Swift开发 23 | - [x] 支持图片、视频、图片与视频混合浏览 24 | - [x] 支持横向和竖向滚动 25 | - [x] 支持嵌入导航栏 26 | - [x] 支持`push`和`present`打开 27 | - [x] 支持数据源实时变更,框架不持有数据源 28 | - [x] 支持自定义转场动画,框架提供了`Fade`、`Zoom`、`SoomthZoom`三个转场动画的实现 29 | - [x] 支持自定义Cell,框架提供了常用的图片展示Cell的实现 30 | - [x] 支持网络图片加载、查看原图加载,由用户自由选择其他框架进行图片加载与缓存 31 | - [x] 支持各种附加控件的添加,框架提供了两种页面指示器的实现,以及在例子工程提供了加载进度环的实现 32 | 33 | ## 版本更新记录 34 | 35 | ### Version 1.1.5 36 | 37 | > 2023/08/03 38 | 39 | - 新增实况动图预览场景 40 | 41 | - 新增视频图片混合场景 42 | 43 | - 新增ImageCell拖拽视图回调 44 | 45 | - 修复若干问题,优化图片浏览框架 46 | 47 | ### Version 1.1.4 48 | 49 | > 2022/06/23 50 | 51 | - 修复图片删除闪退问题 52 | 53 | - 内存泄露优化 54 | 55 | - 监控网络图片imageView刷新问题 56 | 57 | - 长图显示抖动动画效果优化 58 | 59 | 60 | 61 | ### Version 1.1.2 62 | 63 | > 2021/03/30 64 | 65 | - 加载更多新增图片时,图片偏移问题的优化 66 | 67 | - 网络图片加载完成后,视图刷新回调优化处理 68 | 69 | - 自定义Cell查看原图优化 70 | 71 | - Example的Demo文件命名规范 72 | 73 | 74 | 75 | ### Version 1.1.1 76 | 77 | > 2021/01/20 78 | 79 | - 优化屏幕旋转时闪屏修复 80 | 81 | 82 | 83 | ### Version 1.1.0 84 | 85 | > 2020/09/16 86 | 87 | - 优化LanternCell,支持子类自定义转场动画 88 | - 优化LanternImageCell,暴露方法支持子类自定义创建视图 89 | - 更好支持嵌入导航栏场景下的转场动画 90 | - 视频与图片混合浏览视频的拖拽动画优化 91 | - Example的Demo样式更新,更直观的UI样式 92 | 93 | ## 接入文档 94 | 95 | - [环境与安装](环境与安装.md) 96 | - [基础用法](基础用法.md) 97 | - [高级用法](高级用法.md) 98 | 99 | ## 更新日志 100 | 101 | - [Release Notes](ReleaseNotes.md) 102 | 103 | > 深圳市丰巢科技有限公司成立于2015年6月6日,是一家致力以智能快递柜为切入点,提供最后一公里交付解决方案的科技公司。 104 | 105 | -------------------------------------------------------------------------------- /ReleaseNotes.md: -------------------------------------------------------------------------------- 1 | ## ReleaseNotes 2 | 3 | ### Version 1.1.3 4 | 5 | > 2022/06/23 6 | 7 | - 修复图片删除闪退问题 8 | 9 | - 内存泄露优化 10 | 11 | - 监控网络图片imageView刷新问题 12 | 13 | - 长图显示抖动动画效果优化 14 | 15 | 16 | 17 | ### Version 1.1.2 18 | 19 | > 2021/03/30 20 | 21 | - 加载更多新增图片时,图片偏移问题的优化 22 | - 网络图片加载完成后,视图刷新回调优化处理 23 | - 自定义Cell查看原图优化 24 | - Example的Demo文件命名规范 25 | 26 | 27 | 28 | ### Version 1.1.1 29 | 30 | > 2021/01/20 31 | 32 | - 优化屏幕旋转时闪屏修复 33 | 34 | 35 | 36 | ### Version 1.1.0 37 | 38 | > 2020/09/16 39 | 40 | - 优化LanternCell,支持子类自定义转场动画 41 | - 优化LanternImageCell,暴露方法支持子类自定义创建视图 42 | - 更好支持嵌入导航栏场景下的转场动画 43 | - 视频与图片混合浏览视频的拖拽动画优化 44 | - Example的Demo样式更新,更直观的UI样式 45 | 46 | 47 | 48 | ### Version 1.0.0 49 | 50 | > 2020/03/06 51 | 52 | 1. 完成主流常见的图片与视频全屏浏览 53 | 54 | -------------------------------------------------------------------------------- /Sources/Lantern/LanternAnimatedTransitioning.swift: -------------------------------------------------------------------------------- 1 | // 2 | // LanternAnimatedTransitioning.swift 3 | // Lantern 4 | // 5 | // Created by JiongXing on 2019/11/25. 6 | // Copyright © 2021 Shenzhen Hive Box Technology Co.,Ltd All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | public protocol LanternAnimatedTransitioning: UIViewControllerAnimatedTransitioning { 12 | var isForShow: Bool { get set } 13 | var lantern: Lantern? { get set } 14 | var isNavigationAnimation: Bool { get set } 15 | } 16 | 17 | private var isForShowKey = "isForShowKey" 18 | private var lanternKey = "lanternKey" 19 | 20 | extension LanternAnimatedTransitioning { 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 lantern: Lantern? { 35 | get { 36 | objc_getAssociatedObject(self, &lanternKey) as? Lantern 37 | } 38 | set { 39 | objc_setAssociatedObject(self, &lanternKey, newValue, .OBJC_ASSOCIATION_ASSIGN) 40 | } 41 | } 42 | 43 | public var isNavigationAnimation: Bool { 44 | get { false } 45 | set { } 46 | } 47 | 48 | public func fastSnapshot(with view: UIView) -> UIView? { 49 | UIGraphicsBeginImageContextWithOptions(view.bounds.size, false, UIScreen.main.scale) 50 | view.drawHierarchy(in: view.bounds, afterScreenUpdates: false) 51 | let image = UIGraphicsGetImageFromCurrentImageContext() 52 | UIGraphicsEndImageContext() 53 | return UIImageView(image: image) 54 | } 55 | 56 | public func snapshot(with view: UIView) -> UIView? { 57 | UIGraphicsBeginImageContextWithOptions(view.bounds.size, false, UIScreen.main.scale) 58 | guard let context = UIGraphicsGetCurrentContext() else { return nil } 59 | view.layer.render(in: context) 60 | let image = UIGraphicsGetImageFromCurrentImageContext() 61 | UIGraphicsEndImageContext() 62 | return UIImageView(image: image) 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /Sources/Lantern/LanternCell.swift: -------------------------------------------------------------------------------- 1 | // 2 | // LanternCell.swift 3 | // Lantern 4 | // 5 | // Created by JiongXing on 2019/11/26. 6 | // Copyright © 2021 Shenzhen Hive Box Technology Co.,Ltd All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | public protocol LanternCell: UIView { 12 | 13 | static func generate(with lantern: Lantern) -> Self 14 | } 15 | -------------------------------------------------------------------------------- /Sources/Lantern/LanternDefaultPageIndicator.swift: -------------------------------------------------------------------------------- 1 | // 2 | // LanternDefaultPageIndicator.swift 3 | // Lantern 4 | // 5 | // Created by JiongXing on 2019/11/25. 6 | // Copyright © 2021 Shenzhen Hive Box Technology Co.,Ltd All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | open class LanternDefaultPageIndicator: UIPageControl, LanternPageIndicator { 12 | 13 | /// 页码与底部的距离 14 | open lazy var bottomPadding: CGFloat = { 15 | if #available(iOS 11.0, *), 16 | let window = UIApplication.shared.keyWindow, 17 | window.safeAreaInsets.bottom > 0 { 18 | return 20 19 | } 20 | return 15 21 | }() 22 | 23 | open func setup(with lantern: Lantern) { 24 | isEnabled = false 25 | } 26 | 27 | open func reloadData(numberOfItems: Int, pageIndex: Int) { 28 | numberOfPages = numberOfItems 29 | currentPage = min(pageIndex, numberOfPages - 1) 30 | sizeToFit() 31 | isHidden = numberOfPages <= 1 32 | if let view = superview { 33 | center.x = view.bounds.width / 2 34 | frame.origin.y = view.bounds.maxY - bottomPadding - bounds.height 35 | } 36 | } 37 | 38 | open func didChanged(pageIndex: Int) { 39 | currentPage = pageIndex 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /Sources/Lantern/LanternFadeAnimator.swift: -------------------------------------------------------------------------------- 1 | // 2 | // LanternFadeAnimator.swift 3 | // Lantern 4 | // 5 | // Created by JiongXing on 2019/11/25. 6 | // Copyright © 2021 Shenzhen Hive Box Technology Co.,Ltd All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | open class LanternFadeAnimator: NSObject, LanternAnimatedTransitioning { 12 | 13 | open var showDuration: TimeInterval = 0.25 14 | 15 | open var dismissDuration: TimeInterval = 0.25 16 | 17 | open 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 = lantern 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), 43 | let toView = transitionContext.view(forKey: .to) { 44 | transitionContext.containerView.insertSubview(toView, belowSubview: fromView) 45 | } 46 | } 47 | browser.browserView.isHidden = true 48 | UIView.animate(withDuration: transitionDuration(using: transitionContext), animations: { 49 | browser.browserView.isHidden = false 50 | browser.maskView.alpha = self.isForShow ? 1.0 : 0 51 | browser.browserView.alpha = self.isForShow ? 1.0 : 0 52 | }) { _ in 53 | transitionContext.completeTransition(!transitionContext.transitionWasCancelled) 54 | } 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /Sources/Lantern/LanternLog.swift: -------------------------------------------------------------------------------- 1 | // 2 | // LanternLog.swift 3 | // Lantern 4 | // 5 | // Created by JiongXing on 2019/11/12. 6 | // Copyright © 2021 Shenzhen Hive Box Technology Co.,Ltd All rights reserved. 7 | // 8 | 9 | import Foundation 10 | 11 | public struct LanternLog { 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 minimumLevel: Level = .forbidden 23 | 24 | public static func low(_ item: @autoclosure () -> Any) { 25 | if minimumLevel.rawValue <= Level.low.rawValue { 26 | print("[Lantern] [low]", item()) 27 | } 28 | } 29 | 30 | public static func middle(_ item: @autoclosure () -> Any) { 31 | if minimumLevel.rawValue <= Level.middle.rawValue { 32 | print("[Lantern] [middle]", item()) 33 | } 34 | } 35 | 36 | public static func high(_ item: @autoclosure () -> Any) { 37 | if minimumLevel.rawValue <= Level.high.rawValue { 38 | print("[Lantern] [high]", item()) 39 | } 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /Sources/Lantern/LanternNoneAnimator.swift: -------------------------------------------------------------------------------- 1 | // 2 | // LanternNoneAnimator.swift 3 | // Lantern 4 | // 5 | // Created by JiongXing on 2019/11/26. 6 | // Copyright © 2021 Shenzhen Hive Box Technology Co.,Ltd All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | /// 使用本类以实现不出现转场动画的需求 12 | open class LanternNoneAnimator: LanternFadeAnimator { 13 | 14 | public override init() { 15 | super.init() 16 | showDuration = 0 17 | dismissDuration = 0 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /Sources/Lantern/LanternNumberPageIndicator.swift: -------------------------------------------------------------------------------- 1 | // 2 | // LanternNumberPageIndicator.swift 3 | // Lantern 4 | // 5 | // Created by JiongXing on 2019/11/25. 6 | // Copyright © 2021 Shenzhen Hive Box Technology Co.,Ltd All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | open class LanternNumberPageIndicator: UILabel, LanternPageIndicator { 12 | 13 | /// 页码与顶部的距离 14 | open lazy var topPadding: CGFloat = { 15 | if #available(iOS 11.0, *), 16 | let window = UIApplication.shared.keyWindow { 17 | return window.safeAreaInsets.top 18 | } 19 | return 20 20 | }() 21 | 22 | public convenience init() { 23 | self.init(frame: .zero) 24 | } 25 | 26 | public override init(frame: CGRect) { 27 | super.init(frame: frame) 28 | config() 29 | } 30 | 31 | required public init?(coder: NSCoder) { 32 | super.init(coder: coder) 33 | config() 34 | } 35 | 36 | private func config() { 37 | font = UIFont.systemFont(ofSize: 17) 38 | textAlignment = .center 39 | textColor = UIColor.white 40 | backgroundColor = UIColor(red: 0, green: 0, blue: 0, alpha: 0.4) 41 | layer.masksToBounds = true 42 | } 43 | 44 | public func setup(with lantern: Lantern) { 45 | 46 | } 47 | 48 | private var total: Int = 0 49 | 50 | public func reloadData(numberOfItems: Int, pageIndex: Int) { 51 | total = numberOfItems 52 | text = "\(pageIndex + 1) / \(total)" 53 | sizeToFit() 54 | frame.size.width += frame.height 55 | layer.cornerRadius = frame.height / 2 56 | if let view = superview { 57 | center.x = view.bounds.width / 2 58 | frame.origin.y = topPadding 59 | } 60 | isHidden = numberOfItems <= 1 61 | } 62 | 63 | public func didChanged(pageIndex: Int) { 64 | text = "\(pageIndex + 1) / \(total)" 65 | } 66 | 67 | } 68 | -------------------------------------------------------------------------------- /Sources/Lantern/LanternPageIndicator.swift: -------------------------------------------------------------------------------- 1 | // 2 | // LanternPageIndicator.swift 3 | // Lantern 4 | // 5 | // Created by JiongXing on 2019/11/25. 6 | // Copyright © 2021 Shenzhen Hive Box Technology Co.,Ltd All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | public protocol LanternPageIndicator: UIView { 12 | 13 | func setup(with lantern: Lantern) 14 | 15 | func reloadData(numberOfItems: Int, pageIndex: Int) 16 | 17 | func didChanged(pageIndex: Int) 18 | } 19 | -------------------------------------------------------------------------------- /Sources/Lantern/LanternPhotoVideoCell.swift: -------------------------------------------------------------------------------- 1 | // 2 | // LanternPhotoVideoCell.swift 3 | // Lantern 4 | // 5 | // Created by 小豌先生 on 2023/7/20. 6 | // 7 | 8 | import UIKit 9 | 10 | open class LanternPhotoVideoCell: LanternImageCell { 11 | public var player: LanternVideoPlayer = { 12 | let view = LanternVideoPlayer() 13 | return view 14 | }() 15 | 16 | open override func setup() { 17 | imageView.isUserInteractionEnabled = true 18 | contentView = player 19 | super.setup() 20 | } 21 | 22 | open func refreshPlayer() { 23 | self.panGestureEndAction = {[weak self] (_, isEnd) in 24 | if isEnd { 25 | self?.player.stop() 26 | } else { 27 | self?.player.play() 28 | } 29 | } 30 | self.panGestureChangeAction = { [weak self] (_, _) in 31 | self?.player.pause() 32 | } 33 | } 34 | 35 | open func showPlayer(url: URL) { 36 | DispatchQueue.main.asyncAfter(deadline: .now() + 0.01) { 37 | self.player.url = url 38 | self.isVideo = true 39 | self.player.play() 40 | } 41 | } 42 | } 43 | 44 | 45 | -------------------------------------------------------------------------------- /Sources/Lantern/LanternVideoPlayer.swift: -------------------------------------------------------------------------------- 1 | // 2 | // LanternVideoPlayer.swift 3 | // Lantern 4 | // 5 | // Created by 小豌先生 on 2023/7/20. 6 | // 7 | 8 | import UIKit 9 | import AVFoundation 10 | 11 | open class LanternVideoPlayer: UIView { 12 | 13 | private var player: AVPlayer? 14 | 15 | private var playerLayer: AVPlayerLayer? 16 | 17 | private var playerItem: AVPlayerItem? 18 | 19 | override init(frame: CGRect) { 20 | super.init(frame: frame) 21 | backgroundColor = .black 22 | } 23 | 24 | required public init?(coder aDecoder: NSCoder) { 25 | fatalError("init(coder:) has not been implemented") 26 | } 27 | 28 | public var url: URL? { 29 | didSet { 30 | guard let url = url else { return } 31 | 32 | self.stop() 33 | 34 | let session = AVAudioSession.sharedInstance() 35 | do { 36 | try session.setCategory(.playback) 37 | try session.setActive(true) 38 | } catch { 39 | print("set session error:\(error)") 40 | } 41 | 42 | playerItem = AVPlayerItem(asset: AVAsset(url: url)) 43 | player = AVPlayer(playerItem: playerItem) 44 | playerLayer = layer as? AVPlayerLayer 45 | playerLayer?.videoGravity = .resizeAspect 46 | playerLayer?.player = player 47 | } 48 | } 49 | } 50 | 51 | public extension LanternVideoPlayer { 52 | override class var layerClass: AnyClass { 53 | return AVPlayerLayer.classForCoder() 54 | } 55 | } 56 | 57 | public extension LanternVideoPlayer { 58 | func play() { 59 | player?.play() 60 | } 61 | 62 | func pause() { 63 | player?.pause() 64 | } 65 | 66 | func stop() { 67 | player?.pause() 68 | playerItem = nil 69 | player = nil 70 | playerLayer = nil 71 | } 72 | } 73 | 74 | -------------------------------------------------------------------------------- /Sources/Lantern/LanternZoomSupportedCell.swift: -------------------------------------------------------------------------------- 1 | // 2 | // LanternZoomSupportedCell.swift 3 | // Lantern 4 | // 5 | // Created by JiongXing on 2019/11/22. 6 | // Copyright © 2021 Shenzhen Hive Box Technology Co.,Ltd All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | /// 在Zoom转场时使用 12 | public protocol LanternZoomSupportedCell: UIView { 13 | /// 内容视图 14 | var showContentView: UIView { get } 15 | } 16 | -------------------------------------------------------------------------------- /基础用法.md: -------------------------------------------------------------------------------- 1 | 2 | ### 基本用法 3 | 4 | 以下代码取自项目Example例子工程,更详细完整的代码请打开例子工程查看,下文是其关键代码的讲解。 5 | 6 | #### 1.先实例化一个图片浏览器对象。 7 | 8 | 注意每次打开图片浏览,都应该重新实例化(重新实例化的开销很小,不必担心)。 9 | 10 | ```swift 11 | let lantern = Lantern() 12 | ``` 13 | 14 | #### 2.实时提供图片总量。 15 | 16 | 因考虑到数据源有可能是在浏览过程中变化的,所以Lantern框架(以下简称'框架')将会在适当时机调用闭包动态获取当前用户的数据源数量,类似`UITableView`的机制。 17 | 18 | ```swift 19 | lantern.numberOfItems = { 20 | self.dataSource.count 21 | } 22 | ``` 23 | 24 | #### 3.刷新项视图。 25 | 26 | 框架的项视图(展示单张图片的View)是复用的,由最多3个视图重复使用来实现无限数量的图片浏览。 27 | 28 | 在每个项视图需要被刷新时,`reloadCellAtIndex`闭包将会被调用,用户应当在此时更新对应数据源的视图展示。 29 | 30 | 框架默认实现并使用了`LanternImageCell`作为项视图,用户也可以自由定制项视图,更多细节在下文介绍。 31 | 32 | `LanternImageCell`有一个`imageView`视图,用户只需要对其加载图片即可正常使用。 33 | 34 | ```swift 35 | lantern.reloadCellAtIndex = { context in 36 | let lanternCell = context.cell as? LanternImageCell 37 | let indexPath = IndexPath(item: context.index, section: indexPath.section) 38 | lanternCell?.imageView.image = self.dataSource[indexPath.item].localName.flatMap { UIImage(named: $0) } 39 | } 40 | ``` 41 | 42 | #### 4.指定打开图片浏览器时定位到哪一页。 43 | 44 | 所赋的值应当在用户数据源的范围内,如数据源共有10项,则`pageIndex`允许范围是`0~9`。 45 | 46 | ```swift 47 | lantern.pageIndex = indexPath.item 48 | ``` 49 | 50 | #### 5.显示图片浏览器 51 | 52 | 浏览器主类`Lantern`是一个`UIViewController`,支持导航栏`push`,也支持模态`present`。 53 | 框架提供的`show()`方法封装实现了常见的打开方式。 54 | 55 | 无参调用`show()`方法的时候,默认使用了`present`模态打开一个不带导航栏的图片浏览器。 56 | 57 | ```swift 58 | lantern.show() 59 | ``` 60 | 61 | -------------------------------------------------------------------------------- /环境与安装.md: -------------------------------------------------------------------------------- 1 | ## 环境要求 2 | 3 | - iOS 9.0 以上 4 | - Swift 4.2 以上 5 | 6 | ## 安装方法 7 | 8 | ### Cocoapods 9 | 10 | 在`podfile`中添加: 11 | 12 | 在`podfile`配置 13 | 14 | ``` 15 | pod 'Lantern', '1.1.3' 16 | ``` 17 | 18 | 然后`pod install`集成。 19 | 20 | ### Swift Package Manager (Xcode 11+) 21 | 22 | 使用Xcode的包管理器添加本仓库URL。 23 | 24 | `File -> Swift Packages -> Add Package Dependency` 25 | 26 | 添加URL:`https://github.com/fcbox/Lantern` 27 | 28 | ### Manual 29 | 30 | 把本仓库下载到你本地,然后把`Sources`文件夹下的`Lantern`文件夹整个拖入Xcode,勾选拷贝文件选项即可,没有其它第三方依赖。 31 | --------------------------------------------------------------------------------