diff --git a/.gitignore b/.gitignore index c964cd8..0187506 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,15 @@ +# OS X +.DS_Store + # Xcode # +# gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore + +## Build generated build/ +DerivedData/ + +## Various settings *.pbxuser !default.pbxuser *.mode1v3 @@ -9,18 +18,50 @@ build/ !default.mode2v3 *.perspectivev3 !default.perspectivev3 -xcuserdata -*.xccheckout +xcuserdata/ + +## Other *.moved-aside -DerivedData +*.xccheckout +*.xcuserstate +*.xcscmblueprint + +## Obj-C/Swift specific *.hmap *.ipa -*.xcuserstate +*.dSYM.zip +*.dSYM # CocoaPods # # We recommend against adding the Pods directory to your .gitignore. However # you should judge for yourself, the pros and cons are mentioned at: -# http://guides.cocoapods.org/using/using-cocoapods.html#should-i-ignore-the-pods-directory-in-source-control +# https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control # -#Pods/ +# Pods/ + +# Carthage +# +# Add this line if you want to avoid checking in source code from Carthage dependencies. +# Carthage/Checkouts + +Carthage/Build + +# fastlane +# +# It is recommended to not store the screenshots in the git repo. Instead, use fastlane to re-generate the +# screenshots whenever they are needed. +# For more information about the recommended setup visit: +# https://docs.fastlane.tools/best-practices/source-control/#source-control + +fastlane/report.xml +fastlane/Preview.html +fastlane/screenshots +fastlane/test_output + +# Code Injection +# +# After new code Injection tools there's a generated folder /iOSInjectionProject +# https://github.com/johnno1962/injectionforxcode + +iOSInjectionProject/ diff --git a/.travis.yml b/.travis.yml index 24245f3..0e8d70b 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,7 +1,14 @@ language: objective-c -osx_image: xcode7 +osx_image: xcode8 xcode_project: Framework/YYWebImage.xcodeproj xcode_scheme: YYWebImage +before_install: +- env +- xcodebuild -version +- xcodebuild -showsdks +- xcpretty --version + script: -- xctool -project Framework/YYWebImage.xcodeproj -scheme YYWebImage build test CODE_SIGN_IDENTITY="" CODE_SIGNING_REQUIRED=NO \ No newline at end of file +- set -o pipefail +- xcodebuild clean build -project "$TRAVIS_XCODE_PROJECT" -scheme "$TRAVIS_XCODE_SCHEME" | xcpretty diff --git a/Demo/YYWebImageDemo.xcodeproj/project.pbxproj b/Demo/YYWebImageDemo.xcodeproj/project.pbxproj index 19959b7..5af23b5 100644 --- a/Demo/YYWebImageDemo.xcodeproj/project.pbxproj +++ b/Demo/YYWebImageDemo.xcodeproj/project.pbxproj @@ -3,364 +3,375 @@ archiveVersion = 1; classes = { }; - objectVersion = 46; + objectVersion = 48; objects = { /* Begin PBXBuildFile section */ - ABC4238E1BE3244A00703518 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = ABC4238D1BE3244A00703518 /* main.m */; }; - ABC423911BE3244A00703518 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = ABC423901BE3244A00703518 /* AppDelegate.m */; }; - ABC423941BE3244A00703518 /* ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = ABC423931BE3244A00703518 /* ViewController.m */; }; - ABC423971BE3244A00703518 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = ABC423951BE3244A00703518 /* Main.storyboard */; }; - ABC423991BE3244A00703518 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = ABC423981BE3244A00703518 /* Assets.xcassets */; }; - ABC4239C1BE3244A00703518 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = ABC4239A1BE3244A00703518 /* LaunchScreen.storyboard */; }; - ABC423A61BE324E800703518 /* WebP.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = ABC423A51BE324E800703518 /* WebP.framework */; }; - ABC423D01BE324F000703518 /* YYCache.m in Sources */ = {isa = PBXBuildFile; fileRef = ABC423AA1BE324F000703518 /* YYCache.m */; }; - ABC423D11BE324F000703518 /* YYDiskCache.m in Sources */ = {isa = PBXBuildFile; fileRef = ABC423AC1BE324F000703518 /* YYDiskCache.m */; }; - ABC423D21BE324F000703518 /* YYKVStorage.m in Sources */ = {isa = PBXBuildFile; fileRef = ABC423AE1BE324F000703518 /* YYKVStorage.m */; }; - ABC423D31BE324F000703518 /* YYMemoryCache.m in Sources */ = {isa = PBXBuildFile; fileRef = ABC423B01BE324F000703518 /* YYMemoryCache.m */; }; - ABC423D41BE324F000703518 /* _YYWebImageSetter.m in Sources */ = {isa = PBXBuildFile; fileRef = ABC423B31BE324F000703518 /* _YYWebImageSetter.m */; }; - ABC423D51BE324F000703518 /* CALayer+YYWebImage.m in Sources */ = {isa = PBXBuildFile; fileRef = ABC423B51BE324F000703518 /* CALayer+YYWebImage.m */; }; - ABC423D61BE324F000703518 /* MKAnnotationView+YYWebImage.m in Sources */ = {isa = PBXBuildFile; fileRef = ABC423B71BE324F000703518 /* MKAnnotationView+YYWebImage.m */; }; - ABC423D71BE324F000703518 /* UIButton+YYWebImage.m in Sources */ = {isa = PBXBuildFile; fileRef = ABC423B91BE324F000703518 /* UIButton+YYWebImage.m */; }; - ABC423D81BE324F000703518 /* UIImage+YYWebImage.m in Sources */ = {isa = PBXBuildFile; fileRef = ABC423BB1BE324F000703518 /* UIImage+YYWebImage.m */; }; - ABC423D91BE324F000703518 /* UIImageView+YYWebImage.m in Sources */ = {isa = PBXBuildFile; fileRef = ABC423BD1BE324F000703518 /* UIImageView+YYWebImage.m */; }; - ABC423DA1BE324F000703518 /* YYAnimatedImageView.m in Sources */ = {isa = PBXBuildFile; fileRef = ABC423C01BE324F000703518 /* YYAnimatedImageView.m */; }; - ABC423DB1BE324F000703518 /* YYFrameImage.m in Sources */ = {isa = PBXBuildFile; fileRef = ABC423C21BE324F000703518 /* YYFrameImage.m */; }; - ABC423DC1BE324F000703518 /* YYImage.m in Sources */ = {isa = PBXBuildFile; fileRef = ABC423C41BE324F000703518 /* YYImage.m */; }; - ABC423DD1BE324F000703518 /* YYImageCoder.m in Sources */ = {isa = PBXBuildFile; fileRef = ABC423C61BE324F000703518 /* YYImageCoder.m */; }; - ABC423DE1BE324F000703518 /* YYSpriteSheetImage.m in Sources */ = {isa = PBXBuildFile; fileRef = ABC423C81BE324F000703518 /* YYSpriteSheetImage.m */; }; - ABC423DF1BE324F000703518 /* YYImageCache.m in Sources */ = {isa = PBXBuildFile; fileRef = ABC423CA1BE324F000703518 /* YYImageCache.m */; }; - ABC423E01BE324F000703518 /* YYWebImageManager.m in Sources */ = {isa = PBXBuildFile; fileRef = ABC423CD1BE324F000703518 /* YYWebImageManager.m */; }; - ABC423E11BE324F000703518 /* YYWebImageOperation.m in Sources */ = {isa = PBXBuildFile; fileRef = ABC423CF1BE324F000703518 /* YYWebImageOperation.m */; }; - ABC423E51BE3252800703518 /* libsqlite3.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = ABC423E41BE3252800703518 /* libsqlite3.tbd */; }; - ABC423E71BE3252D00703518 /* libz.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = ABC423E61BE3252D00703518 /* libz.tbd */; }; - ABC423E91BE3253300703518 /* MobileCoreServices.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = ABC423E81BE3253300703518 /* MobileCoreServices.framework */; }; - ABC423EB1BE3253800703518 /* AssetsLibrary.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = ABC423EA1BE3253800703518 /* AssetsLibrary.framework */; }; - ABC423ED1BE3253D00703518 /* QuartzCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = ABC423EC1BE3253D00703518 /* QuartzCore.framework */; }; - ABC423EF1BE3254400703518 /* ImageIO.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = ABC423EE1BE3254400703518 /* ImageIO.framework */; }; - ABC423F11BE3254C00703518 /* CoreFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = ABC423F01BE3254C00703518 /* CoreFoundation.framework */; }; - ABC423F21BE3255200703518 /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = ABC423E21BE3251C00703518 /* UIKit.framework */; }; - ABC424011BE325EF00703518 /* YYImageExample.m in Sources */ = {isa = PBXBuildFile; fileRef = ABC423F41BE325EF00703518 /* YYImageExample.m */; }; - ABC424021BE325EF00703518 /* YYImageDisplayExample.m in Sources */ = {isa = PBXBuildFile; fileRef = ABC423F61BE325EF00703518 /* YYImageDisplayExample.m */; }; - ABC424031BE325EF00703518 /* YYImageProgressiveExample.m in Sources */ = {isa = PBXBuildFile; fileRef = ABC423F81BE325EF00703518 /* YYImageProgressiveExample.m */; }; - ABC424041BE325EF00703518 /* YYWebImageExample.m in Sources */ = {isa = PBXBuildFile; fileRef = ABC423FA1BE325EF00703518 /* YYWebImageExample.m */; }; - ABC424061BE325EF00703518 /* YYImageExampleHelper.m in Sources */ = {isa = PBXBuildFile; fileRef = ABC423FE1BE325EF00703518 /* YYImageExampleHelper.m */; }; - ABC424181BE3265500703518 /* ResourceTwitter.bundle in Resources */ = {isa = PBXBuildFile; fileRef = ABC4240A1BE3265500703518 /* ResourceTwitter.bundle */; }; - ABC424191BE3265500703518 /* EmoticonWeibo.bundle in Resources */ = {isa = PBXBuildFile; fileRef = ABC4240B1BE3265500703518 /* EmoticonWeibo.bundle */; }; - ABC4241A1BE3265500703518 /* niconiconi@2x.gif in Resources */ = {isa = PBXBuildFile; fileRef = ABC4240C1BE3265500703518 /* niconiconi@2x.gif */; }; - ABC4241B1BE3265500703518 /* google@2x.webp in Resources */ = {isa = PBXBuildFile; fileRef = ABC4240D1BE3265500703518 /* google@2x.webp */; }; - ABC4241C1BE3265500703518 /* nyancat@2x.webp in Resources */ = {isa = PBXBuildFile; fileRef = ABC4240E1BE3265500703518 /* nyancat@2x.webp */; }; - ABC4241D1BE3265500703518 /* pia@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = ABC4240F1BE3265500703518 /* pia@2x.png */; }; - ABC4241E1BE3265500703518 /* cube@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = ABC424101BE3265500703518 /* cube@2x.png */; }; - ABC4241F1BE3265500703518 /* wall-e@2x.webp in Resources */ = {isa = PBXBuildFile; fileRef = ABC424111BE3265500703518 /* wall-e@2x.webp */; }; - ABC424201BE3265500703518 /* mew_baseline.jpg in Resources */ = {isa = PBXBuildFile; fileRef = ABC424121BE3265500703518 /* mew_baseline.jpg */; }; - ABC424211BE3265500703518 /* mew_progressive.jpg in Resources */ = {isa = PBXBuildFile; fileRef = ABC424131BE3265500703518 /* mew_progressive.jpg */; }; - ABC424221BE3265500703518 /* mew_baseline.png in Resources */ = {isa = PBXBuildFile; fileRef = ABC424141BE3265500703518 /* mew_baseline.png */; }; - ABC424231BE3265500703518 /* mew_interlaced.png in Resources */ = {isa = PBXBuildFile; fileRef = ABC424151BE3265500703518 /* mew_interlaced.png */; }; - ABC424241BE3265500703518 /* mew_baseline.gif in Resources */ = {isa = PBXBuildFile; fileRef = ABC424161BE3265500703518 /* mew_baseline.gif */; }; - ABC424251BE3265500703518 /* mew_interlaced.gif in Resources */ = {isa = PBXBuildFile; fileRef = ABC424171BE3265500703518 /* mew_interlaced.gif */; }; - ABC4242C1BE3268800703518 /* UIView+YYAdd.m in Sources */ = {isa = PBXBuildFile; fileRef = ABC424271BE3268800703518 /* UIView+YYAdd.m */; }; - ABC4242D1BE3268800703518 /* UIControl+YYAdd.m in Sources */ = {isa = PBXBuildFile; fileRef = ABC424291BE3268800703518 /* UIControl+YYAdd.m */; }; - ABC4242E1BE3268800703518 /* UIGestureRecognizer+YYAdd.m in Sources */ = {isa = PBXBuildFile; fileRef = ABC4242B1BE3268800703518 /* UIGestureRecognizer+YYAdd.m */; }; - ABC424311BE3284000703518 /* CALayer+YYAdd.m in Sources */ = {isa = PBXBuildFile; fileRef = ABC424301BE3284000703518 /* CALayer+YYAdd.m */; }; + D97E77FA1F36DE8900450835 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = D97E77F91F36DE8900450835 /* AppDelegate.m */; }; + D97E77FD1F36DE8900450835 /* ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = D97E77FC1F36DE8900450835 /* ViewController.m */; }; + D97E78001F36DE8900450835 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = D97E77FE1F36DE8900450835 /* Main.storyboard */; }; + D97E78021F36DE8900450835 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = D97E78011F36DE8900450835 /* Assets.xcassets */; }; + D97E78051F36DE8900450835 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = D97E78031F36DE8900450835 /* LaunchScreen.storyboard */; }; + D97E78081F36DE8900450835 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = D97E78071F36DE8900450835 /* main.m */; }; + D9EF63871F36DEEB00AB19C3 /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D9EF63861F36DEEB00AB19C3 /* UIKit.framework */; }; + D9EF63891F36DEEF00AB19C3 /* CoreFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D9EF63881F36DEEF00AB19C3 /* CoreFoundation.framework */; }; + D9EF638B1F36DEF300AB19C3 /* ImageIO.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D9EF638A1F36DEF300AB19C3 /* ImageIO.framework */; }; + D9EF638D1F36DEF800AB19C3 /* QuartzCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D9EF638C1F36DEF800AB19C3 /* QuartzCore.framework */; }; + D9EF638F1F36DEFD00AB19C3 /* AssetsLibrary.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D9EF638E1F36DEFD00AB19C3 /* AssetsLibrary.framework */; }; + D9EF63911F36DF0500AB19C3 /* MobileCoreServices.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D9EF63901F36DF0500AB19C3 /* MobileCoreServices.framework */; }; + D9EF63931F36DF0900AB19C3 /* libz.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = D9EF63921F36DF0900AB19C3 /* libz.tbd */; }; + D9EF63951F36DF0C00AB19C3 /* libsqlite3.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = D9EF63941F36DF0C00AB19C3 /* libsqlite3.tbd */; }; + D9EF63971F36DF2400AB19C3 /* WebP.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D9EF63961F36DF2400AB19C3 /* WebP.framework */; }; + D9EF63C11F36DF7C00AB19C3 /* YYCache.m in Sources */ = {isa = PBXBuildFile; fileRef = D9EF639B1F36DF7B00AB19C3 /* YYCache.m */; }; + D9EF63C21F36DF7C00AB19C3 /* YYDiskCache.m in Sources */ = {isa = PBXBuildFile; fileRef = D9EF639D1F36DF7B00AB19C3 /* YYDiskCache.m */; }; + D9EF63C31F36DF7C00AB19C3 /* YYKVStorage.m in Sources */ = {isa = PBXBuildFile; fileRef = D9EF639F1F36DF7B00AB19C3 /* YYKVStorage.m */; }; + D9EF63C41F36DF7C00AB19C3 /* YYMemoryCache.m in Sources */ = {isa = PBXBuildFile; fileRef = D9EF63A11F36DF7B00AB19C3 /* YYMemoryCache.m */; }; + D9EF63C51F36DF7C00AB19C3 /* _YYWebImageSetter.m in Sources */ = {isa = PBXBuildFile; fileRef = D9EF63A41F36DF7B00AB19C3 /* _YYWebImageSetter.m */; }; + D9EF63C61F36DF7C00AB19C3 /* CALayer+YYWebImage.m in Sources */ = {isa = PBXBuildFile; fileRef = D9EF63A61F36DF7B00AB19C3 /* CALayer+YYWebImage.m */; }; + D9EF63C71F36DF7C00AB19C3 /* MKAnnotationView+YYWebImage.m in Sources */ = {isa = PBXBuildFile; fileRef = D9EF63A81F36DF7B00AB19C3 /* MKAnnotationView+YYWebImage.m */; }; + D9EF63C81F36DF7C00AB19C3 /* UIButton+YYWebImage.m in Sources */ = {isa = PBXBuildFile; fileRef = D9EF63AA1F36DF7B00AB19C3 /* UIButton+YYWebImage.m */; }; + D9EF63C91F36DF7C00AB19C3 /* UIImage+YYWebImage.m in Sources */ = {isa = PBXBuildFile; fileRef = D9EF63AC1F36DF7B00AB19C3 /* UIImage+YYWebImage.m */; }; + D9EF63CA1F36DF7C00AB19C3 /* UIImageView+YYWebImage.m in Sources */ = {isa = PBXBuildFile; fileRef = D9EF63AE1F36DF7B00AB19C3 /* UIImageView+YYWebImage.m */; }; + D9EF63CB1F36DF7C00AB19C3 /* YYAnimatedImageView.m in Sources */ = {isa = PBXBuildFile; fileRef = D9EF63B11F36DF7B00AB19C3 /* YYAnimatedImageView.m */; }; + D9EF63CC1F36DF7C00AB19C3 /* YYFrameImage.m in Sources */ = {isa = PBXBuildFile; fileRef = D9EF63B31F36DF7B00AB19C3 /* YYFrameImage.m */; }; + D9EF63CD1F36DF7C00AB19C3 /* YYImage.m in Sources */ = {isa = PBXBuildFile; fileRef = D9EF63B51F36DF7B00AB19C3 /* YYImage.m */; }; + D9EF63CE1F36DF7C00AB19C3 /* YYImageCoder.m in Sources */ = {isa = PBXBuildFile; fileRef = D9EF63B71F36DF7B00AB19C3 /* YYImageCoder.m */; }; + D9EF63CF1F36DF7C00AB19C3 /* YYSpriteSheetImage.m in Sources */ = {isa = PBXBuildFile; fileRef = D9EF63B91F36DF7B00AB19C3 /* YYSpriteSheetImage.m */; }; + D9EF63D01F36DF7C00AB19C3 /* YYImageCache.m in Sources */ = {isa = PBXBuildFile; fileRef = D9EF63BB1F36DF7B00AB19C3 /* YYImageCache.m */; }; + D9EF63D11F36DF7C00AB19C3 /* YYWebImageManager.m in Sources */ = {isa = PBXBuildFile; fileRef = D9EF63BE1F36DF7B00AB19C3 /* YYWebImageManager.m */; }; + D9EF63D21F36DF7C00AB19C3 /* YYWebImageOperation.m in Sources */ = {isa = PBXBuildFile; fileRef = D9EF63C01F36DF7B00AB19C3 /* YYWebImageOperation.m */; }; + D9EF63DC1F36DFEE00AB19C3 /* UIView+YYAdd.m in Sources */ = {isa = PBXBuildFile; fileRef = D9EF63D51F36DFEE00AB19C3 /* UIView+YYAdd.m */; }; + D9EF63DD1F36DFEE00AB19C3 /* CALayer+YYAdd.m in Sources */ = {isa = PBXBuildFile; fileRef = D9EF63D71F36DFEE00AB19C3 /* CALayer+YYAdd.m */; }; + D9EF63DE1F36DFEE00AB19C3 /* UIControl+YYAdd.m in Sources */ = {isa = PBXBuildFile; fileRef = D9EF63D91F36DFEE00AB19C3 /* UIControl+YYAdd.m */; }; + D9EF63DF1F36DFEE00AB19C3 /* UIGestureRecognizer+YYAdd.m in Sources */ = {isa = PBXBuildFile; fileRef = D9EF63DB1F36DFEE00AB19C3 /* UIGestureRecognizer+YYAdd.m */; }; + D9EF63F41F36E22400AB19C3 /* ResourceTwitter.bundle in Resources */ = {isa = PBXBuildFile; fileRef = D9EF63E61F36E22400AB19C3 /* ResourceTwitter.bundle */; }; + D9EF63F51F36E22400AB19C3 /* EmoticonWeibo.bundle in Resources */ = {isa = PBXBuildFile; fileRef = D9EF63E71F36E22400AB19C3 /* EmoticonWeibo.bundle */; }; + D9EF63F61F36E22400AB19C3 /* niconiconi@2x.gif in Resources */ = {isa = PBXBuildFile; fileRef = D9EF63E81F36E22400AB19C3 /* niconiconi@2x.gif */; }; + D9EF63F71F36E22400AB19C3 /* google@2x.webp in Resources */ = {isa = PBXBuildFile; fileRef = D9EF63E91F36E22400AB19C3 /* google@2x.webp */; }; + D9EF63F81F36E22400AB19C3 /* nyancat@2x.webp in Resources */ = {isa = PBXBuildFile; fileRef = D9EF63EA1F36E22400AB19C3 /* nyancat@2x.webp */; }; + D9EF63F91F36E22400AB19C3 /* pia@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = D9EF63EB1F36E22400AB19C3 /* pia@2x.png */; }; + D9EF63FA1F36E22400AB19C3 /* cube@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = D9EF63EC1F36E22400AB19C3 /* cube@2x.png */; }; + D9EF63FB1F36E22400AB19C3 /* wall-e@2x.webp in Resources */ = {isa = PBXBuildFile; fileRef = D9EF63ED1F36E22400AB19C3 /* wall-e@2x.webp */; }; + D9EF63FC1F36E22400AB19C3 /* mew_baseline.jpg in Resources */ = {isa = PBXBuildFile; fileRef = D9EF63EE1F36E22400AB19C3 /* mew_baseline.jpg */; }; + D9EF63FD1F36E22400AB19C3 /* mew_progressive.jpg in Resources */ = {isa = PBXBuildFile; fileRef = D9EF63EF1F36E22400AB19C3 /* mew_progressive.jpg */; }; + D9EF63FE1F36E22400AB19C3 /* mew_baseline.png in Resources */ = {isa = PBXBuildFile; fileRef = D9EF63F01F36E22400AB19C3 /* mew_baseline.png */; }; + D9EF63FF1F36E22400AB19C3 /* mew_interlaced.png in Resources */ = {isa = PBXBuildFile; fileRef = D9EF63F11F36E22400AB19C3 /* mew_interlaced.png */; }; + D9EF64001F36E22400AB19C3 /* mew_baseline.gif in Resources */ = {isa = PBXBuildFile; fileRef = D9EF63F21F36E22400AB19C3 /* mew_baseline.gif */; }; + D9EF64011F36E22400AB19C3 /* mew_interlaced.gif in Resources */ = {isa = PBXBuildFile; fileRef = D9EF63F31F36E22400AB19C3 /* mew_interlaced.gif */; }; + D9EF640C1F36E24D00AB19C3 /* YYImageExample.m in Sources */ = {isa = PBXBuildFile; fileRef = D9EF64031F36E24D00AB19C3 /* YYImageExample.m */; }; + D9EF640D1F36E24D00AB19C3 /* YYImageDisplayExample.m in Sources */ = {isa = PBXBuildFile; fileRef = D9EF64051F36E24D00AB19C3 /* YYImageDisplayExample.m */; }; + D9EF640E1F36E24D00AB19C3 /* YYImageProgressiveExample.m in Sources */ = {isa = PBXBuildFile; fileRef = D9EF64071F36E24D00AB19C3 /* YYImageProgressiveExample.m */; }; + D9EF640F1F36E24D00AB19C3 /* YYWebImageExample.m in Sources */ = {isa = PBXBuildFile; fileRef = D9EF64091F36E24D00AB19C3 /* YYWebImageExample.m */; }; + D9EF64101F36E24D00AB19C3 /* YYImageExampleHelper.m in Sources */ = {isa = PBXBuildFile; fileRef = D9EF640B1F36E24D00AB19C3 /* YYImageExampleHelper.m */; }; /* End PBXBuildFile section */ /* Begin PBXFileReference section */ - ABC423891BE3244A00703518 /* YYWebImageDemo.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = YYWebImageDemo.app; sourceTree = BUILT_PRODUCTS_DIR; }; - ABC4238D1BE3244A00703518 /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; - ABC4238F1BE3244A00703518 /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; - ABC423901BE3244A00703518 /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; - ABC423921BE3244A00703518 /* ViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ViewController.h; sourceTree = ""; }; - ABC423931BE3244A00703518 /* ViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ViewController.m; sourceTree = ""; }; - ABC423961BE3244A00703518 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; - ABC423981BE3244A00703518 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; - ABC4239B1BE3244A00703518 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; - ABC4239D1BE3244A00703518 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; - ABC423A51BE324E800703518 /* WebP.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = WebP.framework; path = ../Vendor/WebP.framework; sourceTree = ""; }; - ABC423A91BE324F000703518 /* YYCache.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = YYCache.h; sourceTree = ""; }; - ABC423AA1BE324F000703518 /* YYCache.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = YYCache.m; sourceTree = ""; }; - ABC423AB1BE324F000703518 /* YYDiskCache.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = YYDiskCache.h; sourceTree = ""; }; - ABC423AC1BE324F000703518 /* YYDiskCache.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = YYDiskCache.m; sourceTree = ""; }; - ABC423AD1BE324F000703518 /* YYKVStorage.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = YYKVStorage.h; sourceTree = ""; }; - ABC423AE1BE324F000703518 /* YYKVStorage.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = YYKVStorage.m; sourceTree = ""; }; - ABC423AF1BE324F000703518 /* YYMemoryCache.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = YYMemoryCache.h; sourceTree = ""; }; - ABC423B01BE324F000703518 /* YYMemoryCache.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = YYMemoryCache.m; sourceTree = ""; }; - ABC423B21BE324F000703518 /* _YYWebImageSetter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = _YYWebImageSetter.h; sourceTree = ""; }; - ABC423B31BE324F000703518 /* _YYWebImageSetter.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = _YYWebImageSetter.m; sourceTree = ""; }; - ABC423B41BE324F000703518 /* CALayer+YYWebImage.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "CALayer+YYWebImage.h"; sourceTree = ""; }; - ABC423B51BE324F000703518 /* CALayer+YYWebImage.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "CALayer+YYWebImage.m"; sourceTree = ""; }; - ABC423B61BE324F000703518 /* MKAnnotationView+YYWebImage.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "MKAnnotationView+YYWebImage.h"; sourceTree = ""; }; - ABC423B71BE324F000703518 /* MKAnnotationView+YYWebImage.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "MKAnnotationView+YYWebImage.m"; sourceTree = ""; }; - ABC423B81BE324F000703518 /* UIButton+YYWebImage.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "UIButton+YYWebImage.h"; sourceTree = ""; }; - ABC423B91BE324F000703518 /* UIButton+YYWebImage.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "UIButton+YYWebImage.m"; sourceTree = ""; }; - ABC423BA1BE324F000703518 /* UIImage+YYWebImage.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "UIImage+YYWebImage.h"; sourceTree = ""; }; - ABC423BB1BE324F000703518 /* UIImage+YYWebImage.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "UIImage+YYWebImage.m"; sourceTree = ""; }; - ABC423BC1BE324F000703518 /* UIImageView+YYWebImage.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "UIImageView+YYWebImage.h"; sourceTree = ""; }; - ABC423BD1BE324F000703518 /* UIImageView+YYWebImage.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "UIImageView+YYWebImage.m"; sourceTree = ""; }; - ABC423BF1BE324F000703518 /* YYAnimatedImageView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = YYAnimatedImageView.h; sourceTree = ""; }; - ABC423C01BE324F000703518 /* YYAnimatedImageView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = YYAnimatedImageView.m; sourceTree = ""; }; - ABC423C11BE324F000703518 /* YYFrameImage.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = YYFrameImage.h; sourceTree = ""; }; - ABC423C21BE324F000703518 /* YYFrameImage.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = YYFrameImage.m; sourceTree = ""; }; - ABC423C31BE324F000703518 /* YYImage.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = YYImage.h; sourceTree = ""; }; - ABC423C41BE324F000703518 /* YYImage.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = YYImage.m; sourceTree = ""; }; - ABC423C51BE324F000703518 /* YYImageCoder.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = YYImageCoder.h; sourceTree = ""; }; - ABC423C61BE324F000703518 /* YYImageCoder.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = YYImageCoder.m; sourceTree = ""; }; - ABC423C71BE324F000703518 /* YYSpriteSheetImage.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = YYSpriteSheetImage.h; sourceTree = ""; }; - ABC423C81BE324F000703518 /* YYSpriteSheetImage.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = YYSpriteSheetImage.m; sourceTree = ""; }; - ABC423C91BE324F000703518 /* YYImageCache.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = YYImageCache.h; sourceTree = ""; }; - ABC423CA1BE324F000703518 /* YYImageCache.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = YYImageCache.m; sourceTree = ""; }; - ABC423CB1BE324F000703518 /* YYWebImage.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = YYWebImage.h; sourceTree = ""; }; - ABC423CC1BE324F000703518 /* YYWebImageManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = YYWebImageManager.h; sourceTree = ""; }; - ABC423CD1BE324F000703518 /* YYWebImageManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = YYWebImageManager.m; sourceTree = ""; }; - ABC423CE1BE324F000703518 /* YYWebImageOperation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = YYWebImageOperation.h; sourceTree = ""; }; - ABC423CF1BE324F000703518 /* YYWebImageOperation.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = YYWebImageOperation.m; sourceTree = ""; }; - ABC423E21BE3251C00703518 /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = System/Library/Frameworks/UIKit.framework; sourceTree = SDKROOT; }; - ABC423E41BE3252800703518 /* libsqlite3.tbd */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = libsqlite3.tbd; path = usr/lib/libsqlite3.tbd; sourceTree = SDKROOT; }; - ABC423E61BE3252D00703518 /* libz.tbd */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = libz.tbd; path = usr/lib/libz.tbd; sourceTree = SDKROOT; }; - ABC423E81BE3253300703518 /* MobileCoreServices.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = MobileCoreServices.framework; path = System/Library/Frameworks/MobileCoreServices.framework; sourceTree = SDKROOT; }; - ABC423EA1BE3253800703518 /* AssetsLibrary.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AssetsLibrary.framework; path = System/Library/Frameworks/AssetsLibrary.framework; sourceTree = SDKROOT; }; - ABC423EC1BE3253D00703518 /* QuartzCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = QuartzCore.framework; path = System/Library/Frameworks/QuartzCore.framework; sourceTree = SDKROOT; }; - ABC423EE1BE3254400703518 /* ImageIO.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = ImageIO.framework; path = System/Library/Frameworks/ImageIO.framework; sourceTree = SDKROOT; }; - ABC423F01BE3254C00703518 /* CoreFoundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreFoundation.framework; path = System/Library/Frameworks/CoreFoundation.framework; sourceTree = SDKROOT; }; - ABC423F31BE325EF00703518 /* YYImageExample.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = YYImageExample.h; sourceTree = ""; }; - ABC423F41BE325EF00703518 /* YYImageExample.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = YYImageExample.m; sourceTree = ""; }; - ABC423F51BE325EF00703518 /* YYImageDisplayExample.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = YYImageDisplayExample.h; sourceTree = ""; }; - ABC423F61BE325EF00703518 /* YYImageDisplayExample.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = YYImageDisplayExample.m; sourceTree = ""; }; - ABC423F71BE325EF00703518 /* YYImageProgressiveExample.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = YYImageProgressiveExample.h; sourceTree = ""; }; - ABC423F81BE325EF00703518 /* YYImageProgressiveExample.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = YYImageProgressiveExample.m; sourceTree = ""; }; - ABC423F91BE325EF00703518 /* YYWebImageExample.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = YYWebImageExample.h; sourceTree = ""; }; - ABC423FA1BE325EF00703518 /* YYWebImageExample.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = YYWebImageExample.m; sourceTree = ""; }; - ABC423FB1BE325EF00703518 /* YYImageBenchmark.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = YYImageBenchmark.h; sourceTree = ""; }; - ABC423FC1BE325EF00703518 /* YYImageBenchmark.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = YYImageBenchmark.m; sourceTree = ""; }; - ABC423FD1BE325EF00703518 /* YYImageExampleHelper.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = YYImageExampleHelper.h; sourceTree = ""; }; - ABC423FE1BE325EF00703518 /* YYImageExampleHelper.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = YYImageExampleHelper.m; sourceTree = ""; }; - ABC423FF1BE325EF00703518 /* YYBPGCoder.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = YYBPGCoder.h; sourceTree = ""; }; - ABC424001BE325EF00703518 /* YYBPGCoder.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = YYBPGCoder.m; sourceTree = ""; }; - ABC4240A1BE3265500703518 /* ResourceTwitter.bundle */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.plug-in"; path = ResourceTwitter.bundle; sourceTree = ""; }; - ABC4240B1BE3265500703518 /* EmoticonWeibo.bundle */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.plug-in"; path = EmoticonWeibo.bundle; sourceTree = ""; }; - ABC4240C1BE3265500703518 /* niconiconi@2x.gif */ = {isa = PBXFileReference; lastKnownFileType = image.gif; path = "niconiconi@2x.gif"; sourceTree = ""; }; - ABC4240D1BE3265500703518 /* google@2x.webp */ = {isa = PBXFileReference; lastKnownFileType = file; path = "google@2x.webp"; sourceTree = ""; }; - ABC4240E1BE3265500703518 /* nyancat@2x.webp */ = {isa = PBXFileReference; lastKnownFileType = file; path = "nyancat@2x.webp"; sourceTree = ""; }; - ABC4240F1BE3265500703518 /* pia@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "pia@2x.png"; sourceTree = ""; }; - ABC424101BE3265500703518 /* cube@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "cube@2x.png"; sourceTree = ""; }; - ABC424111BE3265500703518 /* wall-e@2x.webp */ = {isa = PBXFileReference; lastKnownFileType = file; path = "wall-e@2x.webp"; sourceTree = ""; }; - ABC424121BE3265500703518 /* mew_baseline.jpg */ = {isa = PBXFileReference; lastKnownFileType = image.jpeg; path = mew_baseline.jpg; sourceTree = ""; }; - ABC424131BE3265500703518 /* mew_progressive.jpg */ = {isa = PBXFileReference; lastKnownFileType = image.jpeg; path = mew_progressive.jpg; sourceTree = ""; }; - ABC424141BE3265500703518 /* mew_baseline.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = mew_baseline.png; sourceTree = ""; }; - ABC424151BE3265500703518 /* mew_interlaced.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = mew_interlaced.png; sourceTree = ""; }; - ABC424161BE3265500703518 /* mew_baseline.gif */ = {isa = PBXFileReference; lastKnownFileType = image.gif; path = mew_baseline.gif; sourceTree = ""; }; - ABC424171BE3265500703518 /* mew_interlaced.gif */ = {isa = PBXFileReference; lastKnownFileType = image.gif; path = mew_interlaced.gif; sourceTree = ""; }; - ABC424261BE3268800703518 /* UIView+YYAdd.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "UIView+YYAdd.h"; sourceTree = ""; }; - ABC424271BE3268800703518 /* UIView+YYAdd.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "UIView+YYAdd.m"; sourceTree = ""; }; - ABC424281BE3268800703518 /* UIControl+YYAdd.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "UIControl+YYAdd.h"; sourceTree = ""; }; - ABC424291BE3268800703518 /* UIControl+YYAdd.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "UIControl+YYAdd.m"; sourceTree = ""; }; - ABC4242A1BE3268800703518 /* UIGestureRecognizer+YYAdd.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "UIGestureRecognizer+YYAdd.h"; sourceTree = ""; }; - ABC4242B1BE3268800703518 /* UIGestureRecognizer+YYAdd.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "UIGestureRecognizer+YYAdd.m"; sourceTree = ""; }; - ABC4242F1BE3284000703518 /* CALayer+YYAdd.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "CALayer+YYAdd.h"; sourceTree = ""; }; - ABC424301BE3284000703518 /* CALayer+YYAdd.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "CALayer+YYAdd.m"; sourceTree = ""; }; + D97E77F51F36DE8900450835 /* YYWebImageDemo.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = YYWebImageDemo.app; sourceTree = BUILT_PRODUCTS_DIR; }; + D97E77F81F36DE8900450835 /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; + D97E77F91F36DE8900450835 /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; + D97E77FB1F36DE8900450835 /* ViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ViewController.h; sourceTree = ""; }; + D97E77FC1F36DE8900450835 /* ViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ViewController.m; sourceTree = ""; }; + D97E77FF1F36DE8900450835 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; + D97E78011F36DE8900450835 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; + D97E78041F36DE8900450835 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; + D97E78061F36DE8900450835 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + D97E78071F36DE8900450835 /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; + D9EF63861F36DEEB00AB19C3 /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = System/Library/Frameworks/UIKit.framework; sourceTree = SDKROOT; }; + D9EF63881F36DEEF00AB19C3 /* CoreFoundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreFoundation.framework; path = System/Library/Frameworks/CoreFoundation.framework; sourceTree = SDKROOT; }; + D9EF638A1F36DEF300AB19C3 /* ImageIO.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = ImageIO.framework; path = System/Library/Frameworks/ImageIO.framework; sourceTree = SDKROOT; }; + D9EF638C1F36DEF800AB19C3 /* QuartzCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = QuartzCore.framework; path = System/Library/Frameworks/QuartzCore.framework; sourceTree = SDKROOT; }; + D9EF638E1F36DEFD00AB19C3 /* AssetsLibrary.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AssetsLibrary.framework; path = System/Library/Frameworks/AssetsLibrary.framework; sourceTree = SDKROOT; }; + D9EF63901F36DF0500AB19C3 /* MobileCoreServices.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = MobileCoreServices.framework; path = System/Library/Frameworks/MobileCoreServices.framework; sourceTree = SDKROOT; }; + D9EF63921F36DF0900AB19C3 /* libz.tbd */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = libz.tbd; path = usr/lib/libz.tbd; sourceTree = SDKROOT; }; + D9EF63941F36DF0C00AB19C3 /* libsqlite3.tbd */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = libsqlite3.tbd; path = usr/lib/libsqlite3.tbd; sourceTree = SDKROOT; }; + D9EF63961F36DF2400AB19C3 /* WebP.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = WebP.framework; path = ../Vendor/WebP.framework; sourceTree = ""; }; + D9EF639A1F36DF7B00AB19C3 /* YYCache.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = YYCache.h; sourceTree = ""; }; + D9EF639B1F36DF7B00AB19C3 /* YYCache.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = YYCache.m; sourceTree = ""; }; + D9EF639C1F36DF7B00AB19C3 /* YYDiskCache.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = YYDiskCache.h; sourceTree = ""; }; + D9EF639D1F36DF7B00AB19C3 /* YYDiskCache.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = YYDiskCache.m; sourceTree = ""; }; + D9EF639E1F36DF7B00AB19C3 /* YYKVStorage.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = YYKVStorage.h; sourceTree = ""; }; + D9EF639F1F36DF7B00AB19C3 /* YYKVStorage.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = YYKVStorage.m; sourceTree = ""; }; + D9EF63A01F36DF7B00AB19C3 /* YYMemoryCache.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = YYMemoryCache.h; sourceTree = ""; }; + D9EF63A11F36DF7B00AB19C3 /* YYMemoryCache.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = YYMemoryCache.m; sourceTree = ""; }; + D9EF63A31F36DF7B00AB19C3 /* _YYWebImageSetter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = _YYWebImageSetter.h; sourceTree = ""; }; + D9EF63A41F36DF7B00AB19C3 /* _YYWebImageSetter.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = _YYWebImageSetter.m; sourceTree = ""; }; + D9EF63A51F36DF7B00AB19C3 /* CALayer+YYWebImage.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "CALayer+YYWebImage.h"; sourceTree = ""; }; + D9EF63A61F36DF7B00AB19C3 /* CALayer+YYWebImage.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "CALayer+YYWebImage.m"; sourceTree = ""; }; + D9EF63A71F36DF7B00AB19C3 /* MKAnnotationView+YYWebImage.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "MKAnnotationView+YYWebImage.h"; sourceTree = ""; }; + D9EF63A81F36DF7B00AB19C3 /* MKAnnotationView+YYWebImage.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "MKAnnotationView+YYWebImage.m"; sourceTree = ""; }; + D9EF63A91F36DF7B00AB19C3 /* UIButton+YYWebImage.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "UIButton+YYWebImage.h"; sourceTree = ""; }; + D9EF63AA1F36DF7B00AB19C3 /* UIButton+YYWebImage.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "UIButton+YYWebImage.m"; sourceTree = ""; }; + D9EF63AB1F36DF7B00AB19C3 /* UIImage+YYWebImage.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "UIImage+YYWebImage.h"; sourceTree = ""; }; + D9EF63AC1F36DF7B00AB19C3 /* UIImage+YYWebImage.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "UIImage+YYWebImage.m"; sourceTree = ""; }; + D9EF63AD1F36DF7B00AB19C3 /* UIImageView+YYWebImage.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "UIImageView+YYWebImage.h"; sourceTree = ""; }; + D9EF63AE1F36DF7B00AB19C3 /* UIImageView+YYWebImage.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "UIImageView+YYWebImage.m"; sourceTree = ""; }; + D9EF63B01F36DF7B00AB19C3 /* YYAnimatedImageView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = YYAnimatedImageView.h; sourceTree = ""; }; + D9EF63B11F36DF7B00AB19C3 /* YYAnimatedImageView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = YYAnimatedImageView.m; sourceTree = ""; }; + D9EF63B21F36DF7B00AB19C3 /* YYFrameImage.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = YYFrameImage.h; sourceTree = ""; }; + D9EF63B31F36DF7B00AB19C3 /* YYFrameImage.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = YYFrameImage.m; sourceTree = ""; }; + D9EF63B41F36DF7B00AB19C3 /* YYImage.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = YYImage.h; sourceTree = ""; }; + D9EF63B51F36DF7B00AB19C3 /* YYImage.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = YYImage.m; sourceTree = ""; }; + D9EF63B61F36DF7B00AB19C3 /* YYImageCoder.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = YYImageCoder.h; sourceTree = ""; }; + D9EF63B71F36DF7B00AB19C3 /* YYImageCoder.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = YYImageCoder.m; sourceTree = ""; }; + D9EF63B81F36DF7B00AB19C3 /* YYSpriteSheetImage.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = YYSpriteSheetImage.h; sourceTree = ""; }; + D9EF63B91F36DF7B00AB19C3 /* YYSpriteSheetImage.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = YYSpriteSheetImage.m; sourceTree = ""; }; + D9EF63BA1F36DF7B00AB19C3 /* YYImageCache.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = YYImageCache.h; sourceTree = ""; }; + D9EF63BB1F36DF7B00AB19C3 /* YYImageCache.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = YYImageCache.m; sourceTree = ""; }; + D9EF63BC1F36DF7B00AB19C3 /* YYWebImage.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = YYWebImage.h; sourceTree = ""; }; + D9EF63BD1F36DF7B00AB19C3 /* YYWebImageManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = YYWebImageManager.h; sourceTree = ""; }; + D9EF63BE1F36DF7B00AB19C3 /* YYWebImageManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = YYWebImageManager.m; sourceTree = ""; }; + D9EF63BF1F36DF7B00AB19C3 /* YYWebImageOperation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = YYWebImageOperation.h; sourceTree = ""; }; + D9EF63C01F36DF7B00AB19C3 /* YYWebImageOperation.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = YYWebImageOperation.m; sourceTree = ""; }; + D9EF63D41F36DFEE00AB19C3 /* UIView+YYAdd.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "UIView+YYAdd.h"; sourceTree = ""; }; + D9EF63D51F36DFEE00AB19C3 /* UIView+YYAdd.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "UIView+YYAdd.m"; sourceTree = ""; }; + D9EF63D61F36DFEE00AB19C3 /* CALayer+YYAdd.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "CALayer+YYAdd.h"; sourceTree = ""; }; + D9EF63D71F36DFEE00AB19C3 /* CALayer+YYAdd.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "CALayer+YYAdd.m"; sourceTree = ""; }; + D9EF63D81F36DFEE00AB19C3 /* UIControl+YYAdd.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "UIControl+YYAdd.h"; sourceTree = ""; }; + D9EF63D91F36DFEE00AB19C3 /* UIControl+YYAdd.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "UIControl+YYAdd.m"; sourceTree = ""; }; + D9EF63DA1F36DFEE00AB19C3 /* UIGestureRecognizer+YYAdd.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "UIGestureRecognizer+YYAdd.h"; sourceTree = ""; }; + D9EF63DB1F36DFEE00AB19C3 /* UIGestureRecognizer+YYAdd.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "UIGestureRecognizer+YYAdd.m"; sourceTree = ""; }; + D9EF63E11F36E1FC00AB19C3 /* YYImageBenchmark.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = YYImageBenchmark.h; sourceTree = ""; }; + D9EF63E21F36E1FC00AB19C3 /* YYImageBenchmark.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = YYImageBenchmark.m; sourceTree = ""; }; + D9EF63E31F36E1FC00AB19C3 /* YYBPGCoder.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = YYBPGCoder.h; sourceTree = ""; }; + D9EF63E41F36E1FC00AB19C3 /* YYBPGCoder.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = YYBPGCoder.m; sourceTree = ""; }; + D9EF63E61F36E22400AB19C3 /* ResourceTwitter.bundle */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.plug-in"; path = ResourceTwitter.bundle; sourceTree = ""; }; + D9EF63E71F36E22400AB19C3 /* EmoticonWeibo.bundle */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.plug-in"; path = EmoticonWeibo.bundle; sourceTree = ""; }; + D9EF63E81F36E22400AB19C3 /* niconiconi@2x.gif */ = {isa = PBXFileReference; lastKnownFileType = image.gif; path = "niconiconi@2x.gif"; sourceTree = ""; }; + D9EF63E91F36E22400AB19C3 /* google@2x.webp */ = {isa = PBXFileReference; lastKnownFileType = file; path = "google@2x.webp"; sourceTree = ""; }; + D9EF63EA1F36E22400AB19C3 /* nyancat@2x.webp */ = {isa = PBXFileReference; lastKnownFileType = file; path = "nyancat@2x.webp"; sourceTree = ""; }; + D9EF63EB1F36E22400AB19C3 /* pia@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "pia@2x.png"; sourceTree = ""; }; + D9EF63EC1F36E22400AB19C3 /* cube@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "cube@2x.png"; sourceTree = ""; }; + D9EF63ED1F36E22400AB19C3 /* wall-e@2x.webp */ = {isa = PBXFileReference; lastKnownFileType = file; path = "wall-e@2x.webp"; sourceTree = ""; }; + D9EF63EE1F36E22400AB19C3 /* mew_baseline.jpg */ = {isa = PBXFileReference; lastKnownFileType = image.jpeg; path = mew_baseline.jpg; sourceTree = ""; }; + D9EF63EF1F36E22400AB19C3 /* mew_progressive.jpg */ = {isa = PBXFileReference; lastKnownFileType = image.jpeg; path = mew_progressive.jpg; sourceTree = ""; }; + D9EF63F01F36E22400AB19C3 /* mew_baseline.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = mew_baseline.png; sourceTree = ""; }; + D9EF63F11F36E22400AB19C3 /* mew_interlaced.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = mew_interlaced.png; sourceTree = ""; }; + D9EF63F21F36E22400AB19C3 /* mew_baseline.gif */ = {isa = PBXFileReference; lastKnownFileType = image.gif; path = mew_baseline.gif; sourceTree = ""; }; + D9EF63F31F36E22400AB19C3 /* mew_interlaced.gif */ = {isa = PBXFileReference; lastKnownFileType = image.gif; path = mew_interlaced.gif; sourceTree = ""; }; + D9EF64021F36E24D00AB19C3 /* YYImageExample.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = YYImageExample.h; sourceTree = ""; }; + D9EF64031F36E24D00AB19C3 /* YYImageExample.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = YYImageExample.m; sourceTree = ""; }; + D9EF64041F36E24D00AB19C3 /* YYImageDisplayExample.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = YYImageDisplayExample.h; sourceTree = ""; }; + D9EF64051F36E24D00AB19C3 /* YYImageDisplayExample.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = YYImageDisplayExample.m; sourceTree = ""; }; + D9EF64061F36E24D00AB19C3 /* YYImageProgressiveExample.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = YYImageProgressiveExample.h; sourceTree = ""; }; + D9EF64071F36E24D00AB19C3 /* YYImageProgressiveExample.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = YYImageProgressiveExample.m; sourceTree = ""; }; + D9EF64081F36E24D00AB19C3 /* YYWebImageExample.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = YYWebImageExample.h; sourceTree = ""; }; + D9EF64091F36E24D00AB19C3 /* YYWebImageExample.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = YYWebImageExample.m; sourceTree = ""; }; + D9EF640A1F36E24D00AB19C3 /* YYImageExampleHelper.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = YYImageExampleHelper.h; sourceTree = ""; }; + D9EF640B1F36E24D00AB19C3 /* YYImageExampleHelper.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = YYImageExampleHelper.m; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ - ABC423861BE3244A00703518 /* Frameworks */ = { + D97E77F21F36DE8900450835 /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( - ABC423A61BE324E800703518 /* WebP.framework in Frameworks */, - ABC423F21BE3255200703518 /* UIKit.framework in Frameworks */, - ABC423F11BE3254C00703518 /* CoreFoundation.framework in Frameworks */, - ABC423EF1BE3254400703518 /* ImageIO.framework in Frameworks */, - ABC423ED1BE3253D00703518 /* QuartzCore.framework in Frameworks */, - ABC423EB1BE3253800703518 /* AssetsLibrary.framework in Frameworks */, - ABC423E91BE3253300703518 /* MobileCoreServices.framework in Frameworks */, - ABC423E71BE3252D00703518 /* libz.tbd in Frameworks */, - ABC423E51BE3252800703518 /* libsqlite3.tbd in Frameworks */, + D9EF63951F36DF0C00AB19C3 /* libsqlite3.tbd in Frameworks */, + D9EF63931F36DF0900AB19C3 /* libz.tbd in Frameworks */, + D9EF63911F36DF0500AB19C3 /* MobileCoreServices.framework in Frameworks */, + D9EF638F1F36DEFD00AB19C3 /* AssetsLibrary.framework in Frameworks */, + D9EF638D1F36DEF800AB19C3 /* QuartzCore.framework in Frameworks */, + D9EF638B1F36DEF300AB19C3 /* ImageIO.framework in Frameworks */, + D9EF63971F36DF2400AB19C3 /* WebP.framework in Frameworks */, + D9EF63891F36DEEF00AB19C3 /* CoreFoundation.framework in Frameworks */, + D9EF63871F36DEEB00AB19C3 /* UIKit.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ - ABC423801BE3244A00703518 = { + D97E77EC1F36DE8900450835 = { isa = PBXGroup; children = ( - ABC423A51BE324E800703518 /* WebP.framework */, - ABC423A71BE324F000703518 /* YYWebImage */, - ABC4238B1BE3244A00703518 /* YYWebImageDemo */, - ABC4238A1BE3244A00703518 /* Products */, + D9EF63981F36DF7B00AB19C3 /* YYWebImage */, + D97E77F71F36DE8900450835 /* YYWebImageDemo */, + D9EF63E51F36E21600AB19C3 /* Resources */, + D9EF63E01F36E1F000AB19C3 /* Not available */, + D9EF63D31F36DFD100AB19C3 /* Supporting Files */, + D9EF63851F36DEEB00AB19C3 /* Frameworks */, + D97E77F61F36DE8900450835 /* Products */, ); sourceTree = ""; }; - ABC4238A1BE3244A00703518 /* Products */ = { + D97E77F61F36DE8900450835 /* Products */ = { isa = PBXGroup; children = ( - ABC423891BE3244A00703518 /* YYWebImageDemo.app */, + D97E77F51F36DE8900450835 /* YYWebImageDemo.app */, ); name = Products; sourceTree = ""; }; - ABC4238B1BE3244A00703518 /* YYWebImageDemo */ = { + D97E77F71F36DE8900450835 /* YYWebImageDemo */ = { isa = PBXGroup; children = ( - ABC423F31BE325EF00703518 /* YYImageExample.h */, - ABC423F41BE325EF00703518 /* YYImageExample.m */, - ABC423F51BE325EF00703518 /* YYImageDisplayExample.h */, - ABC423F61BE325EF00703518 /* YYImageDisplayExample.m */, - ABC423F71BE325EF00703518 /* YYImageProgressiveExample.h */, - ABC423F81BE325EF00703518 /* YYImageProgressiveExample.m */, - ABC423F91BE325EF00703518 /* YYWebImageExample.h */, - ABC423FA1BE325EF00703518 /* YYWebImageExample.m */, - ABC423FD1BE325EF00703518 /* YYImageExampleHelper.h */, - ABC423FE1BE325EF00703518 /* YYImageExampleHelper.m */, - ABC424091BE3264600703518 /* Resources */, - ABC424081BE3262E00703518 /* Not available */, - ABC4238C1BE3244A00703518 /* Supporting Files */, + D9EF64021F36E24D00AB19C3 /* YYImageExample.h */, + D9EF64031F36E24D00AB19C3 /* YYImageExample.m */, + D9EF64041F36E24D00AB19C3 /* YYImageDisplayExample.h */, + D9EF64051F36E24D00AB19C3 /* YYImageDisplayExample.m */, + D9EF64061F36E24D00AB19C3 /* YYImageProgressiveExample.h */, + D9EF64071F36E24D00AB19C3 /* YYImageProgressiveExample.m */, + D9EF64081F36E24D00AB19C3 /* YYWebImageExample.h */, + D9EF64091F36E24D00AB19C3 /* YYWebImageExample.m */, + D9EF640A1F36E24D00AB19C3 /* YYImageExampleHelper.h */, + D9EF640B1F36E24D00AB19C3 /* YYImageExampleHelper.m */, ); path = YYWebImageDemo; sourceTree = ""; }; - ABC4238C1BE3244A00703518 /* Supporting Files */ = { + D9EF63851F36DEEB00AB19C3 /* Frameworks */ = { isa = PBXGroup; children = ( - ABC4238F1BE3244A00703518 /* AppDelegate.h */, - ABC423901BE3244A00703518 /* AppDelegate.m */, - ABC423921BE3244A00703518 /* ViewController.h */, - ABC423931BE3244A00703518 /* ViewController.m */, - ABC424261BE3268800703518 /* UIView+YYAdd.h */, - ABC424271BE3268800703518 /* UIView+YYAdd.m */, - ABC4242F1BE3284000703518 /* CALayer+YYAdd.h */, - ABC424301BE3284000703518 /* CALayer+YYAdd.m */, - ABC424281BE3268800703518 /* UIControl+YYAdd.h */, - ABC424291BE3268800703518 /* UIControl+YYAdd.m */, - ABC4242A1BE3268800703518 /* UIGestureRecognizer+YYAdd.h */, - ABC4242B1BE3268800703518 /* UIGestureRecognizer+YYAdd.m */, - ABC423F01BE3254C00703518 /* CoreFoundation.framework */, - ABC423EE1BE3254400703518 /* ImageIO.framework */, - ABC423EC1BE3253D00703518 /* QuartzCore.framework */, - ABC423EA1BE3253800703518 /* AssetsLibrary.framework */, - ABC423E81BE3253300703518 /* MobileCoreServices.framework */, - ABC423E61BE3252D00703518 /* libz.tbd */, - ABC423E41BE3252800703518 /* libsqlite3.tbd */, - ABC423E21BE3251C00703518 /* UIKit.framework */, - ABC423951BE3244A00703518 /* Main.storyboard */, - ABC423981BE3244A00703518 /* Assets.xcassets */, - ABC4239A1BE3244A00703518 /* LaunchScreen.storyboard */, - ABC4239D1BE3244A00703518 /* Info.plist */, - ABC4238D1BE3244A00703518 /* main.m */, + D9EF63961F36DF2400AB19C3 /* WebP.framework */, + D9EF63941F36DF0C00AB19C3 /* libsqlite3.tbd */, + D9EF63921F36DF0900AB19C3 /* libz.tbd */, + D9EF63901F36DF0500AB19C3 /* MobileCoreServices.framework */, + D9EF638E1F36DEFD00AB19C3 /* AssetsLibrary.framework */, + D9EF638C1F36DEF800AB19C3 /* QuartzCore.framework */, + D9EF638A1F36DEF300AB19C3 /* ImageIO.framework */, + D9EF63881F36DEEF00AB19C3 /* CoreFoundation.framework */, + D9EF63861F36DEEB00AB19C3 /* UIKit.framework */, ); - name = "Supporting Files"; + name = Frameworks; sourceTree = ""; }; - ABC423A71BE324F000703518 /* YYWebImage */ = { + D9EF63981F36DF7B00AB19C3 /* YYWebImage */ = { isa = PBXGroup; children = ( - ABC423A81BE324F000703518 /* Cache */, - ABC423BE1BE324F000703518 /* Image */, - ABC423B11BE324F000703518 /* Categories */, - ABC423C91BE324F000703518 /* YYImageCache.h */, - ABC423CA1BE324F000703518 /* YYImageCache.m */, - ABC423CB1BE324F000703518 /* YYWebImage.h */, - ABC423CC1BE324F000703518 /* YYWebImageManager.h */, - ABC423CD1BE324F000703518 /* YYWebImageManager.m */, - ABC423CE1BE324F000703518 /* YYWebImageOperation.h */, - ABC423CF1BE324F000703518 /* YYWebImageOperation.m */, + D9EF63991F36DF7B00AB19C3 /* Cache */, + D9EF63AF1F36DF7B00AB19C3 /* Image */, + D9EF63A21F36DF7B00AB19C3 /* Categories */, + D9EF63BC1F36DF7B00AB19C3 /* YYWebImage.h */, + D9EF63BA1F36DF7B00AB19C3 /* YYImageCache.h */, + D9EF63BB1F36DF7B00AB19C3 /* YYImageCache.m */, + D9EF63BD1F36DF7B00AB19C3 /* YYWebImageManager.h */, + D9EF63BE1F36DF7B00AB19C3 /* YYWebImageManager.m */, + D9EF63BF1F36DF7B00AB19C3 /* YYWebImageOperation.h */, + D9EF63C01F36DF7B00AB19C3 /* YYWebImageOperation.m */, ); name = YYWebImage; path = ../YYWebImage; sourceTree = ""; }; - ABC423A81BE324F000703518 /* Cache */ = { + D9EF63991F36DF7B00AB19C3 /* Cache */ = { isa = PBXGroup; children = ( - ABC423A91BE324F000703518 /* YYCache.h */, - ABC423AA1BE324F000703518 /* YYCache.m */, - ABC423AB1BE324F000703518 /* YYDiskCache.h */, - ABC423AC1BE324F000703518 /* YYDiskCache.m */, - ABC423AD1BE324F000703518 /* YYKVStorage.h */, - ABC423AE1BE324F000703518 /* YYKVStorage.m */, - ABC423AF1BE324F000703518 /* YYMemoryCache.h */, - ABC423B01BE324F000703518 /* YYMemoryCache.m */, + D9EF639A1F36DF7B00AB19C3 /* YYCache.h */, + D9EF639B1F36DF7B00AB19C3 /* YYCache.m */, + D9EF639C1F36DF7B00AB19C3 /* YYDiskCache.h */, + D9EF639D1F36DF7B00AB19C3 /* YYDiskCache.m */, + D9EF639E1F36DF7B00AB19C3 /* YYKVStorage.h */, + D9EF639F1F36DF7B00AB19C3 /* YYKVStorage.m */, + D9EF63A01F36DF7B00AB19C3 /* YYMemoryCache.h */, + D9EF63A11F36DF7B00AB19C3 /* YYMemoryCache.m */, ); path = Cache; sourceTree = ""; }; - ABC423B11BE324F000703518 /* Categories */ = { + D9EF63A21F36DF7B00AB19C3 /* Categories */ = { isa = PBXGroup; children = ( - ABC423B21BE324F000703518 /* _YYWebImageSetter.h */, - ABC423B31BE324F000703518 /* _YYWebImageSetter.m */, - ABC423B41BE324F000703518 /* CALayer+YYWebImage.h */, - ABC423B51BE324F000703518 /* CALayer+YYWebImage.m */, - ABC423B61BE324F000703518 /* MKAnnotationView+YYWebImage.h */, - ABC423B71BE324F000703518 /* MKAnnotationView+YYWebImage.m */, - ABC423B81BE324F000703518 /* UIButton+YYWebImage.h */, - ABC423B91BE324F000703518 /* UIButton+YYWebImage.m */, - ABC423BA1BE324F000703518 /* UIImage+YYWebImage.h */, - ABC423BB1BE324F000703518 /* UIImage+YYWebImage.m */, - ABC423BC1BE324F000703518 /* UIImageView+YYWebImage.h */, - ABC423BD1BE324F000703518 /* UIImageView+YYWebImage.m */, + D9EF63A31F36DF7B00AB19C3 /* _YYWebImageSetter.h */, + D9EF63A41F36DF7B00AB19C3 /* _YYWebImageSetter.m */, + D9EF63A51F36DF7B00AB19C3 /* CALayer+YYWebImage.h */, + D9EF63A61F36DF7B00AB19C3 /* CALayer+YYWebImage.m */, + D9EF63A71F36DF7B00AB19C3 /* MKAnnotationView+YYWebImage.h */, + D9EF63A81F36DF7B00AB19C3 /* MKAnnotationView+YYWebImage.m */, + D9EF63A91F36DF7B00AB19C3 /* UIButton+YYWebImage.h */, + D9EF63AA1F36DF7B00AB19C3 /* UIButton+YYWebImage.m */, + D9EF63AB1F36DF7B00AB19C3 /* UIImage+YYWebImage.h */, + D9EF63AC1F36DF7B00AB19C3 /* UIImage+YYWebImage.m */, + D9EF63AD1F36DF7B00AB19C3 /* UIImageView+YYWebImage.h */, + D9EF63AE1F36DF7B00AB19C3 /* UIImageView+YYWebImage.m */, ); path = Categories; sourceTree = ""; }; - ABC423BE1BE324F000703518 /* Image */ = { + D9EF63AF1F36DF7B00AB19C3 /* Image */ = { isa = PBXGroup; children = ( - ABC423BF1BE324F000703518 /* YYAnimatedImageView.h */, - ABC423C01BE324F000703518 /* YYAnimatedImageView.m */, - ABC423C11BE324F000703518 /* YYFrameImage.h */, - ABC423C21BE324F000703518 /* YYFrameImage.m */, - ABC423C31BE324F000703518 /* YYImage.h */, - ABC423C41BE324F000703518 /* YYImage.m */, - ABC423C51BE324F000703518 /* YYImageCoder.h */, - ABC423C61BE324F000703518 /* YYImageCoder.m */, - ABC423C71BE324F000703518 /* YYSpriteSheetImage.h */, - ABC423C81BE324F000703518 /* YYSpriteSheetImage.m */, + D9EF63B01F36DF7B00AB19C3 /* YYAnimatedImageView.h */, + D9EF63B11F36DF7B00AB19C3 /* YYAnimatedImageView.m */, + D9EF63B21F36DF7B00AB19C3 /* YYFrameImage.h */, + D9EF63B31F36DF7B00AB19C3 /* YYFrameImage.m */, + D9EF63B41F36DF7B00AB19C3 /* YYImage.h */, + D9EF63B51F36DF7B00AB19C3 /* YYImage.m */, + D9EF63B61F36DF7B00AB19C3 /* YYImageCoder.h */, + D9EF63B71F36DF7B00AB19C3 /* YYImageCoder.m */, + D9EF63B81F36DF7B00AB19C3 /* YYSpriteSheetImage.h */, + D9EF63B91F36DF7B00AB19C3 /* YYSpriteSheetImage.m */, ); path = Image; sourceTree = ""; }; - ABC424081BE3262E00703518 /* Not available */ = { + D9EF63D31F36DFD100AB19C3 /* Supporting Files */ = { + isa = PBXGroup; + children = ( + D97E77F81F36DE8900450835 /* AppDelegate.h */, + D97E77F91F36DE8900450835 /* AppDelegate.m */, + D97E77FB1F36DE8900450835 /* ViewController.h */, + D97E77FC1F36DE8900450835 /* ViewController.m */, + D9EF63D41F36DFEE00AB19C3 /* UIView+YYAdd.h */, + D9EF63D51F36DFEE00AB19C3 /* UIView+YYAdd.m */, + D9EF63D61F36DFEE00AB19C3 /* CALayer+YYAdd.h */, + D9EF63D71F36DFEE00AB19C3 /* CALayer+YYAdd.m */, + D9EF63D81F36DFEE00AB19C3 /* UIControl+YYAdd.h */, + D9EF63D91F36DFEE00AB19C3 /* UIControl+YYAdd.m */, + D9EF63DA1F36DFEE00AB19C3 /* UIGestureRecognizer+YYAdd.h */, + D9EF63DB1F36DFEE00AB19C3 /* UIGestureRecognizer+YYAdd.m */, + D97E77FE1F36DE8900450835 /* Main.storyboard */, + D97E78011F36DE8900450835 /* Assets.xcassets */, + D97E78031F36DE8900450835 /* LaunchScreen.storyboard */, + D97E78061F36DE8900450835 /* Info.plist */, + D97E78071F36DE8900450835 /* main.m */, + ); + name = "Supporting Files"; + path = YYWebImageDemo; + sourceTree = ""; + }; + D9EF63E01F36E1F000AB19C3 /* Not available */ = { isa = PBXGroup; children = ( - ABC423FB1BE325EF00703518 /* YYImageBenchmark.h */, - ABC423FC1BE325EF00703518 /* YYImageBenchmark.m */, - ABC423FF1BE325EF00703518 /* YYBPGCoder.h */, - ABC424001BE325EF00703518 /* YYBPGCoder.m */, + D9EF63E11F36E1FC00AB19C3 /* YYImageBenchmark.h */, + D9EF63E21F36E1FC00AB19C3 /* YYImageBenchmark.m */, + D9EF63E31F36E1FC00AB19C3 /* YYBPGCoder.h */, + D9EF63E41F36E1FC00AB19C3 /* YYBPGCoder.m */, ); name = "Not available"; + path = YYWebImageDemo; sourceTree = ""; }; - ABC424091BE3264600703518 /* Resources */ = { + D9EF63E51F36E21600AB19C3 /* Resources */ = { isa = PBXGroup; children = ( - ABC4240A1BE3265500703518 /* ResourceTwitter.bundle */, - ABC4240B1BE3265500703518 /* EmoticonWeibo.bundle */, - ABC4240C1BE3265500703518 /* niconiconi@2x.gif */, - ABC4240D1BE3265500703518 /* google@2x.webp */, - ABC4240E1BE3265500703518 /* nyancat@2x.webp */, - ABC4240F1BE3265500703518 /* pia@2x.png */, - ABC424101BE3265500703518 /* cube@2x.png */, - ABC424111BE3265500703518 /* wall-e@2x.webp */, - ABC424121BE3265500703518 /* mew_baseline.jpg */, - ABC424131BE3265500703518 /* mew_progressive.jpg */, - ABC424141BE3265500703518 /* mew_baseline.png */, - ABC424151BE3265500703518 /* mew_interlaced.png */, - ABC424161BE3265500703518 /* mew_baseline.gif */, - ABC424171BE3265500703518 /* mew_interlaced.gif */, + D9EF63E61F36E22400AB19C3 /* ResourceTwitter.bundle */, + D9EF63E71F36E22400AB19C3 /* EmoticonWeibo.bundle */, + D9EF63E81F36E22400AB19C3 /* niconiconi@2x.gif */, + D9EF63E91F36E22400AB19C3 /* google@2x.webp */, + D9EF63EA1F36E22400AB19C3 /* nyancat@2x.webp */, + D9EF63EB1F36E22400AB19C3 /* pia@2x.png */, + D9EF63EC1F36E22400AB19C3 /* cube@2x.png */, + D9EF63ED1F36E22400AB19C3 /* wall-e@2x.webp */, + D9EF63EE1F36E22400AB19C3 /* mew_baseline.jpg */, + D9EF63EF1F36E22400AB19C3 /* mew_progressive.jpg */, + D9EF63F01F36E22400AB19C3 /* mew_baseline.png */, + D9EF63F11F36E22400AB19C3 /* mew_interlaced.png */, + D9EF63F21F36E22400AB19C3 /* mew_baseline.gif */, + D9EF63F31F36E22400AB19C3 /* mew_interlaced.gif */, ); name = Resources; + path = YYWebImageDemo; sourceTree = ""; }; /* End PBXGroup section */ /* Begin PBXNativeTarget section */ - ABC423881BE3244A00703518 /* YYWebImageDemo */ = { + D97E77F41F36DE8900450835 /* YYWebImageDemo */ = { isa = PBXNativeTarget; - buildConfigurationList = ABC423A01BE3244A00703518 /* Build configuration list for PBXNativeTarget "YYWebImageDemo" */; + buildConfigurationList = D97E780B1F36DE8900450835 /* Build configuration list for PBXNativeTarget "YYWebImageDemo" */; buildPhases = ( - ABC423851BE3244A00703518 /* Sources */, - ABC423861BE3244A00703518 /* Frameworks */, - ABC423871BE3244A00703518 /* Resources */, + D97E77F11F36DE8900450835 /* Sources */, + D97E77F21F36DE8900450835 /* Frameworks */, + D97E77F31F36DE8900450835 /* Resources */, ); buildRules = ( ); @@ -368,121 +379,121 @@ ); name = YYWebImageDemo; productName = YYWebImageDemo; - productReference = ABC423891BE3244A00703518 /* YYWebImageDemo.app */; + productReference = D97E77F51F36DE8900450835 /* YYWebImageDemo.app */; productType = "com.apple.product-type.application"; }; /* End PBXNativeTarget section */ /* Begin PBXProject section */ - ABC423811BE3244A00703518 /* Project object */ = { + D97E77ED1F36DE8900450835 /* Project object */ = { isa = PBXProject; attributes = { - LastUpgradeCheck = 0710; + LastUpgradeCheck = 0900; ORGANIZATIONNAME = ibireme; TargetAttributes = { - ABC423881BE3244A00703518 = { - CreatedOnToolsVersion = 7.1; + D97E77F41F36DE8900450835 = { + CreatedOnToolsVersion = 9.0; }; }; }; - buildConfigurationList = ABC423841BE3244A00703518 /* Build configuration list for PBXProject "YYWebImageDemo" */; - compatibilityVersion = "Xcode 3.2"; - developmentRegion = English; + buildConfigurationList = D97E77F01F36DE8900450835 /* Build configuration list for PBXProject "YYWebImageDemo" */; + compatibilityVersion = "Xcode 8.0"; + developmentRegion = en; hasScannedForEncodings = 0; knownRegions = ( en, Base, ); - mainGroup = ABC423801BE3244A00703518; - productRefGroup = ABC4238A1BE3244A00703518 /* Products */; + mainGroup = D97E77EC1F36DE8900450835; + productRefGroup = D97E77F61F36DE8900450835 /* Products */; projectDirPath = ""; projectRoot = ""; targets = ( - ABC423881BE3244A00703518 /* YYWebImageDemo */, + D97E77F41F36DE8900450835 /* YYWebImageDemo */, ); }; /* End PBXProject section */ /* Begin PBXResourcesBuildPhase section */ - ABC423871BE3244A00703518 /* Resources */ = { + D97E77F31F36DE8900450835 /* Resources */ = { isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( - ABC4241D1BE3265500703518 /* pia@2x.png in Resources */, - ABC4239C1BE3244A00703518 /* LaunchScreen.storyboard in Resources */, - ABC424181BE3265500703518 /* ResourceTwitter.bundle in Resources */, - ABC4241B1BE3265500703518 /* google@2x.webp in Resources */, - ABC4241C1BE3265500703518 /* nyancat@2x.webp in Resources */, - ABC4241F1BE3265500703518 /* wall-e@2x.webp in Resources */, - ABC424251BE3265500703518 /* mew_interlaced.gif in Resources */, - ABC424211BE3265500703518 /* mew_progressive.jpg in Resources */, - ABC424231BE3265500703518 /* mew_interlaced.png in Resources */, - ABC4241A1BE3265500703518 /* niconiconi@2x.gif in Resources */, - ABC424221BE3265500703518 /* mew_baseline.png in Resources */, - ABC423991BE3244A00703518 /* Assets.xcassets in Resources */, - ABC423971BE3244A00703518 /* Main.storyboard in Resources */, - ABC424191BE3265500703518 /* EmoticonWeibo.bundle in Resources */, - ABC424201BE3265500703518 /* mew_baseline.jpg in Resources */, - ABC4241E1BE3265500703518 /* cube@2x.png in Resources */, - ABC424241BE3265500703518 /* mew_baseline.gif in Resources */, + D9EF63F91F36E22400AB19C3 /* pia@2x.png in Resources */, + D97E78051F36DE8900450835 /* LaunchScreen.storyboard in Resources */, + D9EF63F41F36E22400AB19C3 /* ResourceTwitter.bundle in Resources */, + D9EF63F71F36E22400AB19C3 /* google@2x.webp in Resources */, + D9EF63F81F36E22400AB19C3 /* nyancat@2x.webp in Resources */, + D9EF63FB1F36E22400AB19C3 /* wall-e@2x.webp in Resources */, + D9EF64011F36E22400AB19C3 /* mew_interlaced.gif in Resources */, + D9EF63FD1F36E22400AB19C3 /* mew_progressive.jpg in Resources */, + D9EF63FF1F36E22400AB19C3 /* mew_interlaced.png in Resources */, + D9EF63F61F36E22400AB19C3 /* niconiconi@2x.gif in Resources */, + D9EF63FE1F36E22400AB19C3 /* mew_baseline.png in Resources */, + D97E78021F36DE8900450835 /* Assets.xcassets in Resources */, + D97E78001F36DE8900450835 /* Main.storyboard in Resources */, + D9EF63F51F36E22400AB19C3 /* EmoticonWeibo.bundle in Resources */, + D9EF63FC1F36E22400AB19C3 /* mew_baseline.jpg in Resources */, + D9EF63FA1F36E22400AB19C3 /* cube@2x.png in Resources */, + D9EF64001F36E22400AB19C3 /* mew_baseline.gif in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXResourcesBuildPhase section */ /* Begin PBXSourcesBuildPhase section */ - ABC423851BE3244A00703518 /* Sources */ = { + D97E77F11F36DE8900450835 /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - ABC424031BE325EF00703518 /* YYImageProgressiveExample.m in Sources */, - ABC424021BE325EF00703518 /* YYImageDisplayExample.m in Sources */, - ABC4242E1BE3268800703518 /* UIGestureRecognizer+YYAdd.m in Sources */, - ABC423D91BE324F000703518 /* UIImageView+YYWebImage.m in Sources */, - ABC423D21BE324F000703518 /* YYKVStorage.m in Sources */, - ABC424061BE325EF00703518 /* YYImageExampleHelper.m in Sources */, - ABC423941BE3244A00703518 /* ViewController.m in Sources */, - ABC423911BE3244A00703518 /* AppDelegate.m in Sources */, - ABC424011BE325EF00703518 /* YYImageExample.m in Sources */, - ABC423D11BE324F000703518 /* YYDiskCache.m in Sources */, - ABC423DD1BE324F000703518 /* YYImageCoder.m in Sources */, - ABC423DF1BE324F000703518 /* YYImageCache.m in Sources */, - ABC423D01BE324F000703518 /* YYCache.m in Sources */, - ABC423E01BE324F000703518 /* YYWebImageManager.m in Sources */, - ABC423DB1BE324F000703518 /* YYFrameImage.m in Sources */, - ABC4242D1BE3268800703518 /* UIControl+YYAdd.m in Sources */, - ABC423D31BE324F000703518 /* YYMemoryCache.m in Sources */, - ABC4238E1BE3244A00703518 /* main.m in Sources */, - ABC423DC1BE324F000703518 /* YYImage.m in Sources */, - ABC423E11BE324F000703518 /* YYWebImageOperation.m in Sources */, - ABC424041BE325EF00703518 /* YYWebImageExample.m in Sources */, - ABC423D41BE324F000703518 /* _YYWebImageSetter.m in Sources */, - ABC423DE1BE324F000703518 /* YYSpriteSheetImage.m in Sources */, - ABC424311BE3284000703518 /* CALayer+YYAdd.m in Sources */, - ABC423DA1BE324F000703518 /* YYAnimatedImageView.m in Sources */, - ABC423D61BE324F000703518 /* MKAnnotationView+YYWebImage.m in Sources */, - ABC4242C1BE3268800703518 /* UIView+YYAdd.m in Sources */, - ABC423D51BE324F000703518 /* CALayer+YYWebImage.m in Sources */, - ABC423D81BE324F000703518 /* UIImage+YYWebImage.m in Sources */, - ABC423D71BE324F000703518 /* UIButton+YYWebImage.m in Sources */, + D9EF640E1F36E24D00AB19C3 /* YYImageProgressiveExample.m in Sources */, + D9EF63CA1F36DF7C00AB19C3 /* UIImageView+YYWebImage.m in Sources */, + D9EF63C31F36DF7C00AB19C3 /* YYKVStorage.m in Sources */, + D9EF63DC1F36DFEE00AB19C3 /* UIView+YYAdd.m in Sources */, + D97E77FD1F36DE8900450835 /* ViewController.m in Sources */, + D97E78081F36DE8900450835 /* main.m in Sources */, + D9EF63C21F36DF7C00AB19C3 /* YYDiskCache.m in Sources */, + D9EF640C1F36E24D00AB19C3 /* YYImageExample.m in Sources */, + D9EF63CE1F36DF7C00AB19C3 /* YYImageCoder.m in Sources */, + D9EF63D01F36DF7C00AB19C3 /* YYImageCache.m in Sources */, + D9EF63C11F36DF7C00AB19C3 /* YYCache.m in Sources */, + D9EF63DE1F36DFEE00AB19C3 /* UIControl+YYAdd.m in Sources */, + D9EF63D11F36DF7C00AB19C3 /* YYWebImageManager.m in Sources */, + D9EF63CC1F36DF7C00AB19C3 /* YYFrameImage.m in Sources */, + D9EF63C41F36DF7C00AB19C3 /* YYMemoryCache.m in Sources */, + D9EF63DF1F36DFEE00AB19C3 /* UIGestureRecognizer+YYAdd.m in Sources */, + D97E77FA1F36DE8900450835 /* AppDelegate.m in Sources */, + D9EF63CD1F36DF7C00AB19C3 /* YYImage.m in Sources */, + D9EF63D21F36DF7C00AB19C3 /* YYWebImageOperation.m in Sources */, + D9EF63DD1F36DFEE00AB19C3 /* CALayer+YYAdd.m in Sources */, + D9EF63C51F36DF7C00AB19C3 /* _YYWebImageSetter.m in Sources */, + D9EF63CF1F36DF7C00AB19C3 /* YYSpriteSheetImage.m in Sources */, + D9EF63CB1F36DF7C00AB19C3 /* YYAnimatedImageView.m in Sources */, + D9EF63C71F36DF7C00AB19C3 /* MKAnnotationView+YYWebImage.m in Sources */, + D9EF63C61F36DF7C00AB19C3 /* CALayer+YYWebImage.m in Sources */, + D9EF640D1F36E24D00AB19C3 /* YYImageDisplayExample.m in Sources */, + D9EF640F1F36E24D00AB19C3 /* YYWebImageExample.m in Sources */, + D9EF63C91F36DF7C00AB19C3 /* UIImage+YYWebImage.m in Sources */, + D9EF64101F36E24D00AB19C3 /* YYImageExampleHelper.m in Sources */, + D9EF63C81F36DF7C00AB19C3 /* UIButton+YYWebImage.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXSourcesBuildPhase section */ /* Begin PBXVariantGroup section */ - ABC423951BE3244A00703518 /* Main.storyboard */ = { + D97E77FE1F36DE8900450835 /* Main.storyboard */ = { isa = PBXVariantGroup; children = ( - ABC423961BE3244A00703518 /* Base */, + D97E77FF1F36DE8900450835 /* Base */, ); name = Main.storyboard; sourceTree = ""; }; - ABC4239A1BE3244A00703518 /* LaunchScreen.storyboard */ = { + D97E78031F36DE8900450835 /* LaunchScreen.storyboard */ = { isa = PBXVariantGroup; children = ( - ABC4239B1BE3244A00703518 /* Base */, + D97E78041F36DE8900450835 /* Base */, ); name = LaunchScreen.storyboard; sourceTree = ""; @@ -490,29 +501,39 @@ /* End PBXVariantGroup section */ /* Begin XCBuildConfiguration section */ - ABC4239E1BE3244A00703518 /* Debug */ = { + D97E78091F36DE8900450835 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; CLANG_WARN_INT_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + CODE_SIGN_IDENTITY = "iPhone Developer"; COPY_PHASE_STRIP = NO; DEBUG_INFORMATION_FORMAT = dwarf; ENABLE_STRICT_OBJC_MSGSEND = YES; ENABLE_TESTABILITY = YES; - GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_C_LANGUAGE_STANDARD = gnu11; GCC_DYNAMIC_NO_PIC = NO; GCC_NO_COMMON_BLOCKS = YES; GCC_OPTIMIZATION_LEVEL = 0; @@ -526,36 +547,46 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 9.1; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; MTL_ENABLE_DEBUG_INFO = YES; ONLY_ACTIVE_ARCH = YES; SDKROOT = iphoneos; }; name = Debug; }; - ABC4239F1BE3244A00703518 /* Release */ = { + D97E780A1F36DE8900450835 /* Release */ = { isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; CLANG_WARN_INT_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + CODE_SIGN_IDENTITY = "iPhone Developer"; COPY_PHASE_STRIP = NO; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; ENABLE_NS_ASSERTIONS = NO; ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_C_LANGUAGE_STANDARD = gnu11; GCC_NO_COMMON_BLOCKS = YES; GCC_WARN_64_TO_32_BIT_CONVERSION = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; @@ -563,61 +594,65 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 9.1; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = iphoneos; VALIDATE_PRODUCT = YES; }; name = Release; }; - ABC423A11BE3244A00703518 /* Debug */ = { + D97E780C1F36DE8900450835 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + COMPRESS_PNG_FILES = NO; FRAMEWORK_SEARCH_PATHS = "\"$(SRCROOT)/../Vendor\""; INFOPLIST_FILE = YYWebImageDemo/Info.plist; - IPHONEOS_DEPLOYMENT_TARGET = 8.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = com.ibireme.YYWebImageDemo; PRODUCT_NAME = "$(TARGET_NAME)"; + STRIP_PNG_TEXT = NO; + TARGETED_DEVICE_FAMILY = "1,2"; }; name = Debug; }; - ABC423A21BE3244A00703518 /* Release */ = { + D97E780D1F36DE8900450835 /* Release */ = { isa = XCBuildConfiguration; buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + COMPRESS_PNG_FILES = NO; FRAMEWORK_SEARCH_PATHS = "\"$(SRCROOT)/../Vendor\""; INFOPLIST_FILE = YYWebImageDemo/Info.plist; - IPHONEOS_DEPLOYMENT_TARGET = 8.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = com.ibireme.YYWebImageDemo; PRODUCT_NAME = "$(TARGET_NAME)"; + STRIP_PNG_TEXT = NO; + TARGETED_DEVICE_FAMILY = "1,2"; }; name = Release; }; /* End XCBuildConfiguration section */ /* Begin XCConfigurationList section */ - ABC423841BE3244A00703518 /* Build configuration list for PBXProject "YYWebImageDemo" */ = { + D97E77F01F36DE8900450835 /* Build configuration list for PBXProject "YYWebImageDemo" */ = { isa = XCConfigurationList; buildConfigurations = ( - ABC4239E1BE3244A00703518 /* Debug */, - ABC4239F1BE3244A00703518 /* Release */, + D97E78091F36DE8900450835 /* Debug */, + D97E780A1F36DE8900450835 /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; - ABC423A01BE3244A00703518 /* Build configuration list for PBXNativeTarget "YYWebImageDemo" */ = { + D97E780B1F36DE8900450835 /* Build configuration list for PBXNativeTarget "YYWebImageDemo" */ = { isa = XCConfigurationList; buildConfigurations = ( - ABC423A11BE3244A00703518 /* Debug */, - ABC423A21BE3244A00703518 /* Release */, + D97E780C1F36DE8900450835 /* Debug */, + D97E780D1F36DE8900450835 /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; /* End XCConfigurationList section */ }; - rootObject = ABC423811BE3244A00703518 /* Project object */; + rootObject = D97E77ED1F36DE8900450835 /* Project object */; } diff --git a/Demo/YYWebImageDemo.xcodeproj/project.xcworkspace/xcshareddata/YYWebImageDemo.xcscmblueprint b/Demo/YYWebImageDemo.xcodeproj/project.xcworkspace/xcshareddata/YYWebImageDemo.xcscmblueprint deleted file mode 100644 index ab6f561..0000000 --- a/Demo/YYWebImageDemo.xcodeproj/project.xcworkspace/xcshareddata/YYWebImageDemo.xcscmblueprint +++ /dev/null @@ -1,30 +0,0 @@ -{ - "DVTSourceControlWorkspaceBlueprintPrimaryRemoteRepositoryKey" : "2B63CCF71525A271478FBA0FCECF929E60AF80A6", - "DVTSourceControlWorkspaceBlueprintWorkingCopyRepositoryLocationsKey" : { - - }, - "DVTSourceControlWorkspaceBlueprintWorkingCopyStatesKey" : { - "2B63CCF71525A271478FBA0FCECF929E60AF80A6" : 0, - "7D036270E758B4C9CAAD42288C450F2518AF5495" : 0 - }, - "DVTSourceControlWorkspaceBlueprintIdentifierKey" : "C206B33E-2BB5-4703-A85A-81C8A02DF852", - "DVTSourceControlWorkspaceBlueprintWorkingCopyPathsKey" : { - "2B63CCF71525A271478FBA0FCECF929E60AF80A6" : "YYWebImage\/", - "7D036270E758B4C9CAAD42288C450F2518AF5495" : "YYImage\/" - }, - "DVTSourceControlWorkspaceBlueprintNameKey" : "YYWebImageDemo", - "DVTSourceControlWorkspaceBlueprintVersion" : 204, - "DVTSourceControlWorkspaceBlueprintRelativePathToProjectKey" : "Demo\/YYWebImageDemo.xcodeproj", - "DVTSourceControlWorkspaceBlueprintRemoteRepositoriesKey" : [ - { - "DVTSourceControlWorkspaceBlueprintRemoteRepositoryURLKey" : "https:\/\/github.com\/ibireme\/YYWebImage.git", - "DVTSourceControlWorkspaceBlueprintRemoteRepositorySystemKey" : "com.apple.dt.Xcode.sourcecontrol.Git", - "DVTSourceControlWorkspaceBlueprintRemoteRepositoryIdentifierKey" : "2B63CCF71525A271478FBA0FCECF929E60AF80A6" - }, - { - "DVTSourceControlWorkspaceBlueprintRemoteRepositoryURLKey" : "https:\/\/github.com\/ibireme\/YYImage.git", - "DVTSourceControlWorkspaceBlueprintRemoteRepositorySystemKey" : "com.apple.dt.Xcode.sourcecontrol.Git", - "DVTSourceControlWorkspaceBlueprintRemoteRepositoryIdentifierKey" : "7D036270E758B4C9CAAD42288C450F2518AF5495" - } - ] -} \ No newline at end of file diff --git a/Demo/YYWebImageDemo/Assets.xcassets/AppIcon.appiconset/Contents.json b/Demo/YYWebImageDemo/Assets.xcassets/AppIcon.appiconset/Contents.json index 118c98f..1d060ed 100644 --- a/Demo/YYWebImageDemo/Assets.xcassets/AppIcon.appiconset/Contents.json +++ b/Demo/YYWebImageDemo/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -1,5 +1,15 @@ { "images" : [ + { + "idiom" : "iphone", + "size" : "20x20", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "size" : "20x20", + "scale" : "3x" + }, { "idiom" : "iphone", "size" : "29x29", @@ -29,6 +39,51 @@ "idiom" : "iphone", "size" : "60x60", "scale" : "3x" + }, + { + "idiom" : "ipad", + "size" : "20x20", + "scale" : "1x" + }, + { + "idiom" : "ipad", + "size" : "20x20", + "scale" : "2x" + }, + { + "idiom" : "ipad", + "size" : "29x29", + "scale" : "1x" + }, + { + "idiom" : "ipad", + "size" : "29x29", + "scale" : "2x" + }, + { + "idiom" : "ipad", + "size" : "40x40", + "scale" : "1x" + }, + { + "idiom" : "ipad", + "size" : "40x40", + "scale" : "2x" + }, + { + "idiom" : "ipad", + "size" : "76x76", + "scale" : "1x" + }, + { + "idiom" : "ipad", + "size" : "76x76", + "scale" : "2x" + }, + { + "idiom" : "ipad", + "size" : "83.5x83.5", + "scale" : "2x" } ], "info" : { diff --git a/Demo/YYWebImageDemo/Base.lproj/LaunchScreen.storyboard b/Demo/YYWebImageDemo/Base.lproj/LaunchScreen.storyboard index 1447b3c..fdf3f97 100644 --- a/Demo/YYWebImageDemo/Base.lproj/LaunchScreen.storyboard +++ b/Demo/YYWebImageDemo/Base.lproj/LaunchScreen.storyboard @@ -1,8 +1,8 @@ - + - - + + @@ -14,10 +14,9 @@ - + - - + diff --git a/Demo/YYWebImageDemo/Base.lproj/Main.storyboard b/Demo/YYWebImageDemo/Base.lproj/Main.storyboard index 01e6fa5..4529698 100644 --- a/Demo/YYWebImageDemo/Base.lproj/Main.storyboard +++ b/Demo/YYWebImageDemo/Base.lproj/Main.storyboard @@ -1,23 +1,22 @@ - + - - + + - + - + - - + diff --git a/Demo/YYWebImageDemo/Info.plist b/Demo/YYWebImageDemo/Info.plist index 5ef7bbd..f87da23 100644 --- a/Demo/YYWebImageDemo/Info.plist +++ b/Demo/YYWebImageDemo/Info.plist @@ -3,7 +3,7 @@ CFBundleDevelopmentRegion - en + $(DEVELOPMENT_LANGUAGE) CFBundleExecutable $(EXECUTABLE_NAME) CFBundleIdentifier @@ -16,8 +16,6 @@ APPL CFBundleShortVersionString 1.0 - CFBundleSignature - ???? CFBundleVersion 1 LSRequiresIPhoneOS @@ -35,11 +33,18 @@ armv7 - UIRequiresFullScreen - UISupportedInterfaceOrientations UIInterfaceOrientationPortrait + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + UISupportedInterfaceOrientations~ipad + + UIInterfaceOrientationPortrait + UIInterfaceOrientationPortraitUpsideDown + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight diff --git a/Demo/YYWebImageDemo/YYImageExample.m b/Demo/YYWebImageDemo/YYImageExample.m index 60e73d3..345b7e3 100644 --- a/Demo/YYWebImageDemo/YYImageExample.m +++ b/Demo/YYWebImageDemo/YYImageExample.m @@ -20,7 +20,7 @@ @interface YYImageExample() @implementation YYImageExample - (void)viewDidLoad { - self.title = @"YYWebImage Demo"; + self.title = @"Demo"; [super viewDidLoad]; self.titles = @[].mutableCopy; self.classNames = @[].mutableCopy; diff --git a/Demo/YYWebImageDemo/YYWebImageExample.m b/Demo/YYWebImageDemo/YYWebImageExample.m index eef9953..8122b39 100644 --- a/Demo/YYWebImageDemo/YYWebImageExample.m +++ b/Demo/YYWebImageDemo/YYWebImageExample.m @@ -134,7 +134,7 @@ - (void)viewDidLoad { */ // progressive jpeg - @"https://s-media-cache-ak0.pinimg.com/1200x/2e/0c/c5/2e0cc5d86e7b7cd42af225c29f21c37f.jpg", + @"https://raw.githubusercontent.com/ibireme/YYWebImage/master/Demo/YYWebImageDemo/mew_progressive.jpg", // animated gif: http://cinemagraphs.com/ @"http://i.imgur.com/uoBwCLj.gif", @@ -192,7 +192,7 @@ - (void)viewWillDisappear:(BOOL)animated { - (void)reload { [[YYImageCache sharedCache].memoryCache removeAllObjects]; - [[YYImageCache sharedCache].diskCache removeAllObjectsWithBlock:nil]; + [[YYImageCache sharedCache].diskCache removeAllObjectsWithBlock:^{}]; [self.tableView performSelector:@selector(reloadData) withObject:nil afterDelay:0.1]; } diff --git a/Framework/Info.plist b/Framework/Info.plist index 76d3d18..d04a6b4 100644 --- a/Framework/Info.plist +++ b/Framework/Info.plist @@ -3,7 +3,7 @@ CFBundleDevelopmentRegion - en + $(DEVELOPMENT_LANGUAGE) CFBundleExecutable $(EXECUTABLE_NAME) CFBundleIdentifier @@ -15,9 +15,7 @@ CFBundlePackageType FMWK CFBundleShortVersionString - 0.9.0 - CFBundleSignature - ???? + 1.0.5 CFBundleVersion $(CURRENT_PROJECT_VERSION) NSPrincipalClass diff --git a/Framework/YYWebImage-Static.xcodeproj/project.pbxproj b/Framework/YYWebImage-Static.xcodeproj/project.pbxproj deleted file mode 100644 index 65fd3cb..0000000 --- a/Framework/YYWebImage-Static.xcodeproj/project.pbxproj +++ /dev/null @@ -1,519 +0,0 @@ -// !$*UTF8*$! -{ - archiveVersion = 1; - classes = { - }; - objectVersion = 46; - objects = { - -/* Begin PBXBuildFile section */ - D9753A1B1BD3BBE600C6F4B8 /* YYCache.h in Headers */ = {isa = PBXBuildFile; fileRef = D97539F41BD3BBE600C6F4B8 /* YYCache.h */; settings = {ATTRIBUTES = (Public, ); }; }; - D9753A1C1BD3BBE600C6F4B8 /* YYCache.m in Sources */ = {isa = PBXBuildFile; fileRef = D97539F51BD3BBE600C6F4B8 /* YYCache.m */; }; - D9753A1D1BD3BBE600C6F4B8 /* YYDiskCache.h in Headers */ = {isa = PBXBuildFile; fileRef = D97539F61BD3BBE600C6F4B8 /* YYDiskCache.h */; settings = {ATTRIBUTES = (Public, ); }; }; - D9753A1E1BD3BBE600C6F4B8 /* YYDiskCache.m in Sources */ = {isa = PBXBuildFile; fileRef = D97539F71BD3BBE600C6F4B8 /* YYDiskCache.m */; }; - D9753A1F1BD3BBE600C6F4B8 /* YYKVStorage.h in Headers */ = {isa = PBXBuildFile; fileRef = D97539F81BD3BBE600C6F4B8 /* YYKVStorage.h */; settings = {ATTRIBUTES = (Public, ); }; }; - D9753A201BD3BBE600C6F4B8 /* YYKVStorage.m in Sources */ = {isa = PBXBuildFile; fileRef = D97539F91BD3BBE600C6F4B8 /* YYKVStorage.m */; }; - D9753A211BD3BBE600C6F4B8 /* YYMemoryCache.h in Headers */ = {isa = PBXBuildFile; fileRef = D97539FA1BD3BBE600C6F4B8 /* YYMemoryCache.h */; settings = {ATTRIBUTES = (Public, ); }; }; - D9753A221BD3BBE600C6F4B8 /* YYMemoryCache.m in Sources */ = {isa = PBXBuildFile; fileRef = D97539FB1BD3BBE600C6F4B8 /* YYMemoryCache.m */; }; - D9753A231BD3BBE600C6F4B8 /* _YYWebImageSetter.h in Headers */ = {isa = PBXBuildFile; fileRef = D97539FD1BD3BBE600C6F4B8 /* _YYWebImageSetter.h */; settings = {ATTRIBUTES = (Private, ); }; }; - D9753A241BD3BBE600C6F4B8 /* _YYWebImageSetter.m in Sources */ = {isa = PBXBuildFile; fileRef = D97539FE1BD3BBE600C6F4B8 /* _YYWebImageSetter.m */; }; - D9753A251BD3BBE600C6F4B8 /* CALayer+YYWebImage.h in Headers */ = {isa = PBXBuildFile; fileRef = D97539FF1BD3BBE600C6F4B8 /* CALayer+YYWebImage.h */; settings = {ATTRIBUTES = (Public, ); }; }; - D9753A261BD3BBE600C6F4B8 /* CALayer+YYWebImage.m in Sources */ = {isa = PBXBuildFile; fileRef = D9753A001BD3BBE600C6F4B8 /* CALayer+YYWebImage.m */; }; - D9753A271BD3BBE600C6F4B8 /* MKAnnotationView+YYWebImage.h in Headers */ = {isa = PBXBuildFile; fileRef = D9753A011BD3BBE600C6F4B8 /* MKAnnotationView+YYWebImage.h */; settings = {ATTRIBUTES = (Public, ); }; }; - D9753A281BD3BBE600C6F4B8 /* MKAnnotationView+YYWebImage.m in Sources */ = {isa = PBXBuildFile; fileRef = D9753A021BD3BBE600C6F4B8 /* MKAnnotationView+YYWebImage.m */; }; - D9753A291BD3BBE600C6F4B8 /* UIButton+YYWebImage.h in Headers */ = {isa = PBXBuildFile; fileRef = D9753A031BD3BBE600C6F4B8 /* UIButton+YYWebImage.h */; settings = {ATTRIBUTES = (Public, ); }; }; - D9753A2A1BD3BBE600C6F4B8 /* UIButton+YYWebImage.m in Sources */ = {isa = PBXBuildFile; fileRef = D9753A041BD3BBE600C6F4B8 /* UIButton+YYWebImage.m */; }; - D9753A2B1BD3BBE600C6F4B8 /* UIImage+YYWebImage.h in Headers */ = {isa = PBXBuildFile; fileRef = D9753A051BD3BBE600C6F4B8 /* UIImage+YYWebImage.h */; settings = {ATTRIBUTES = (Public, ); }; }; - D9753A2C1BD3BBE600C6F4B8 /* UIImage+YYWebImage.m in Sources */ = {isa = PBXBuildFile; fileRef = D9753A061BD3BBE600C6F4B8 /* UIImage+YYWebImage.m */; }; - D9753A2D1BD3BBE600C6F4B8 /* UIImageView+YYWebImage.h in Headers */ = {isa = PBXBuildFile; fileRef = D9753A071BD3BBE600C6F4B8 /* UIImageView+YYWebImage.h */; settings = {ATTRIBUTES = (Public, ); }; }; - D9753A2E1BD3BBE600C6F4B8 /* UIImageView+YYWebImage.m in Sources */ = {isa = PBXBuildFile; fileRef = D9753A081BD3BBE600C6F4B8 /* UIImageView+YYWebImage.m */; }; - D9753A2F1BD3BBE600C6F4B8 /* YYAnimatedImageView.h in Headers */ = {isa = PBXBuildFile; fileRef = D9753A0A1BD3BBE600C6F4B8 /* YYAnimatedImageView.h */; settings = {ATTRIBUTES = (Public, ); }; }; - D9753A301BD3BBE600C6F4B8 /* YYAnimatedImageView.m in Sources */ = {isa = PBXBuildFile; fileRef = D9753A0B1BD3BBE600C6F4B8 /* YYAnimatedImageView.m */; }; - D9753A311BD3BBE600C6F4B8 /* YYFrameImage.h in Headers */ = {isa = PBXBuildFile; fileRef = D9753A0C1BD3BBE600C6F4B8 /* YYFrameImage.h */; settings = {ATTRIBUTES = (Public, ); }; }; - D9753A321BD3BBE600C6F4B8 /* YYFrameImage.m in Sources */ = {isa = PBXBuildFile; fileRef = D9753A0D1BD3BBE600C6F4B8 /* YYFrameImage.m */; }; - D9753A331BD3BBE600C6F4B8 /* YYImage.h in Headers */ = {isa = PBXBuildFile; fileRef = D9753A0E1BD3BBE600C6F4B8 /* YYImage.h */; settings = {ATTRIBUTES = (Public, ); }; }; - D9753A341BD3BBE600C6F4B8 /* YYImage.m in Sources */ = {isa = PBXBuildFile; fileRef = D9753A0F1BD3BBE600C6F4B8 /* YYImage.m */; }; - D9753A351BD3BBE600C6F4B8 /* YYImageCoder.h in Headers */ = {isa = PBXBuildFile; fileRef = D9753A101BD3BBE600C6F4B8 /* YYImageCoder.h */; settings = {ATTRIBUTES = (Public, ); }; }; - D9753A361BD3BBE600C6F4B8 /* YYImageCoder.m in Sources */ = {isa = PBXBuildFile; fileRef = D9753A111BD3BBE600C6F4B8 /* YYImageCoder.m */; }; - D9753A371BD3BBE600C6F4B8 /* YYSpriteSheetImage.h in Headers */ = {isa = PBXBuildFile; fileRef = D9753A121BD3BBE600C6F4B8 /* YYSpriteSheetImage.h */; settings = {ATTRIBUTES = (Public, ); }; }; - D9753A381BD3BBE600C6F4B8 /* YYSpriteSheetImage.m in Sources */ = {isa = PBXBuildFile; fileRef = D9753A131BD3BBE600C6F4B8 /* YYSpriteSheetImage.m */; }; - D9753A391BD3BBE600C6F4B8 /* YYImageCache.h in Headers */ = {isa = PBXBuildFile; fileRef = D9753A141BD3BBE600C6F4B8 /* YYImageCache.h */; settings = {ATTRIBUTES = (Public, ); }; }; - D9753A3A1BD3BBE600C6F4B8 /* YYImageCache.m in Sources */ = {isa = PBXBuildFile; fileRef = D9753A151BD3BBE600C6F4B8 /* YYImageCache.m */; }; - D9753A3B1BD3BBE600C6F4B8 /* YYWebImage.h in Headers */ = {isa = PBXBuildFile; fileRef = D9753A161BD3BBE600C6F4B8 /* YYWebImage.h */; settings = {ATTRIBUTES = (Public, ); }; }; - D9753A3C1BD3BBE600C6F4B8 /* YYWebImageManager.h in Headers */ = {isa = PBXBuildFile; fileRef = D9753A171BD3BBE600C6F4B8 /* YYWebImageManager.h */; settings = {ATTRIBUTES = (Public, ); }; }; - D9753A3D1BD3BBE600C6F4B8 /* YYWebImageManager.m in Sources */ = {isa = PBXBuildFile; fileRef = D9753A181BD3BBE600C6F4B8 /* YYWebImageManager.m */; }; - D9753A3E1BD3BBE600C6F4B8 /* YYWebImageOperation.h in Headers */ = {isa = PBXBuildFile; fileRef = D9753A191BD3BBE600C6F4B8 /* YYWebImageOperation.h */; settings = {ATTRIBUTES = (Public, ); }; }; - D9753A3F1BD3BBE600C6F4B8 /* YYWebImageOperation.m in Sources */ = {isa = PBXBuildFile; fileRef = D9753A1A1BD3BBE600C6F4B8 /* YYWebImageOperation.m */; }; - D9753A411BD3BE6400C6F4B8 /* libsqlite3.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = D9753A401BD3BE6400C6F4B8 /* libsqlite3.tbd */; }; - D9753A431BD3BE6800C6F4B8 /* libz.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = D9753A421BD3BE6800C6F4B8 /* libz.tbd */; }; - D9753A451BD3BE6C00C6F4B8 /* MobileCoreServices.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D9753A441BD3BE6C00C6F4B8 /* MobileCoreServices.framework */; }; - D9753A471BD3BE7000C6F4B8 /* AssetsLibrary.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D9753A461BD3BE7000C6F4B8 /* AssetsLibrary.framework */; }; - D9753A491BD3BE7600C6F4B8 /* Accelerate.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D9753A481BD3BE7600C6F4B8 /* Accelerate.framework */; }; - D9753A4B1BD3BE7B00C6F4B8 /* QuartzCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D9753A4A1BD3BE7B00C6F4B8 /* QuartzCore.framework */; }; - D9753A4D1BD3BE8000C6F4B8 /* ImageIO.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D9753A4C1BD3BE8000C6F4B8 /* ImageIO.framework */; }; - D9753A4F1BD3BE8600C6F4B8 /* CoreFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D9753A4E1BD3BE8600C6F4B8 /* CoreFoundation.framework */; }; - D9753A511BD3BE8A00C6F4B8 /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D9753A501BD3BE8A00C6F4B8 /* UIKit.framework */; }; - D9753A531BD3BE9D00C6F4B8 /* WebP.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D9753A521BD3BE9D00C6F4B8 /* WebP.framework */; }; -/* End PBXBuildFile section */ - -/* Begin PBXFileReference section */ - D97539DE1BD3BB6F00C6F4B8 /* YYWebImage.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = YYWebImage.framework; sourceTree = BUILT_PRODUCTS_DIR; }; - D97539EF1BD3BB9D00C6F4B8 /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; - D97539F41BD3BBE600C6F4B8 /* YYCache.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = YYCache.h; sourceTree = ""; }; - D97539F51BD3BBE600C6F4B8 /* YYCache.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = YYCache.m; sourceTree = ""; }; - D97539F61BD3BBE600C6F4B8 /* YYDiskCache.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = YYDiskCache.h; sourceTree = ""; }; - D97539F71BD3BBE600C6F4B8 /* YYDiskCache.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = YYDiskCache.m; sourceTree = ""; }; - D97539F81BD3BBE600C6F4B8 /* YYKVStorage.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = YYKVStorage.h; sourceTree = ""; }; - D97539F91BD3BBE600C6F4B8 /* YYKVStorage.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = YYKVStorage.m; sourceTree = ""; }; - D97539FA1BD3BBE600C6F4B8 /* YYMemoryCache.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = YYMemoryCache.h; sourceTree = ""; }; - D97539FB1BD3BBE600C6F4B8 /* YYMemoryCache.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = YYMemoryCache.m; sourceTree = ""; }; - D97539FD1BD3BBE600C6F4B8 /* _YYWebImageSetter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = _YYWebImageSetter.h; sourceTree = ""; }; - D97539FE1BD3BBE600C6F4B8 /* _YYWebImageSetter.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = _YYWebImageSetter.m; sourceTree = ""; }; - D97539FF1BD3BBE600C6F4B8 /* CALayer+YYWebImage.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "CALayer+YYWebImage.h"; sourceTree = ""; }; - D9753A001BD3BBE600C6F4B8 /* CALayer+YYWebImage.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "CALayer+YYWebImage.m"; sourceTree = ""; }; - D9753A011BD3BBE600C6F4B8 /* MKAnnotationView+YYWebImage.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "MKAnnotationView+YYWebImage.h"; sourceTree = ""; }; - D9753A021BD3BBE600C6F4B8 /* MKAnnotationView+YYWebImage.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "MKAnnotationView+YYWebImage.m"; sourceTree = ""; }; - D9753A031BD3BBE600C6F4B8 /* UIButton+YYWebImage.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "UIButton+YYWebImage.h"; sourceTree = ""; }; - D9753A041BD3BBE600C6F4B8 /* UIButton+YYWebImage.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "UIButton+YYWebImage.m"; sourceTree = ""; }; - D9753A051BD3BBE600C6F4B8 /* UIImage+YYWebImage.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "UIImage+YYWebImage.h"; sourceTree = ""; }; - D9753A061BD3BBE600C6F4B8 /* UIImage+YYWebImage.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "UIImage+YYWebImage.m"; sourceTree = ""; }; - D9753A071BD3BBE600C6F4B8 /* UIImageView+YYWebImage.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "UIImageView+YYWebImage.h"; sourceTree = ""; }; - D9753A081BD3BBE600C6F4B8 /* UIImageView+YYWebImage.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "UIImageView+YYWebImage.m"; sourceTree = ""; }; - D9753A0A1BD3BBE600C6F4B8 /* YYAnimatedImageView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = YYAnimatedImageView.h; sourceTree = ""; }; - D9753A0B1BD3BBE600C6F4B8 /* YYAnimatedImageView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = YYAnimatedImageView.m; sourceTree = ""; }; - D9753A0C1BD3BBE600C6F4B8 /* YYFrameImage.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = YYFrameImage.h; sourceTree = ""; }; - D9753A0D1BD3BBE600C6F4B8 /* YYFrameImage.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = YYFrameImage.m; sourceTree = ""; }; - D9753A0E1BD3BBE600C6F4B8 /* YYImage.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = YYImage.h; sourceTree = ""; }; - D9753A0F1BD3BBE600C6F4B8 /* YYImage.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = YYImage.m; sourceTree = ""; }; - D9753A101BD3BBE600C6F4B8 /* YYImageCoder.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = YYImageCoder.h; sourceTree = ""; }; - D9753A111BD3BBE600C6F4B8 /* YYImageCoder.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = YYImageCoder.m; sourceTree = ""; }; - D9753A121BD3BBE600C6F4B8 /* YYSpriteSheetImage.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = YYSpriteSheetImage.h; sourceTree = ""; }; - D9753A131BD3BBE600C6F4B8 /* YYSpriteSheetImage.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = YYSpriteSheetImage.m; sourceTree = ""; }; - D9753A141BD3BBE600C6F4B8 /* YYImageCache.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = YYImageCache.h; sourceTree = ""; }; - D9753A151BD3BBE600C6F4B8 /* YYImageCache.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = YYImageCache.m; sourceTree = ""; }; - D9753A161BD3BBE600C6F4B8 /* YYWebImage.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = YYWebImage.h; sourceTree = ""; }; - D9753A171BD3BBE600C6F4B8 /* YYWebImageManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = YYWebImageManager.h; sourceTree = ""; }; - D9753A181BD3BBE600C6F4B8 /* YYWebImageManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = YYWebImageManager.m; sourceTree = ""; }; - D9753A191BD3BBE600C6F4B8 /* YYWebImageOperation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = YYWebImageOperation.h; sourceTree = ""; }; - D9753A1A1BD3BBE600C6F4B8 /* YYWebImageOperation.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = YYWebImageOperation.m; sourceTree = ""; }; - D9753A401BD3BE6400C6F4B8 /* libsqlite3.tbd */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = libsqlite3.tbd; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS9.0.sdk/usr/lib/libsqlite3.tbd; sourceTree = DEVELOPER_DIR; }; - D9753A421BD3BE6800C6F4B8 /* libz.tbd */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = libz.tbd; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS9.0.sdk/usr/lib/libz.tbd; sourceTree = DEVELOPER_DIR; }; - D9753A441BD3BE6C00C6F4B8 /* MobileCoreServices.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = MobileCoreServices.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS9.0.sdk/System/Library/Frameworks/MobileCoreServices.framework; sourceTree = DEVELOPER_DIR; }; - D9753A461BD3BE7000C6F4B8 /* AssetsLibrary.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AssetsLibrary.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS9.0.sdk/System/Library/Frameworks/AssetsLibrary.framework; sourceTree = DEVELOPER_DIR; }; - D9753A481BD3BE7600C6F4B8 /* Accelerate.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Accelerate.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS9.0.sdk/System/Library/Frameworks/Accelerate.framework; sourceTree = DEVELOPER_DIR; }; - D9753A4A1BD3BE7B00C6F4B8 /* QuartzCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = QuartzCore.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS9.0.sdk/System/Library/Frameworks/QuartzCore.framework; sourceTree = DEVELOPER_DIR; }; - D9753A4C1BD3BE8000C6F4B8 /* ImageIO.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = ImageIO.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS9.0.sdk/System/Library/Frameworks/ImageIO.framework; sourceTree = DEVELOPER_DIR; }; - D9753A4E1BD3BE8600C6F4B8 /* CoreFoundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreFoundation.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS9.0.sdk/System/Library/Frameworks/CoreFoundation.framework; sourceTree = DEVELOPER_DIR; }; - D9753A501BD3BE8A00C6F4B8 /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS9.0.sdk/System/Library/Frameworks/UIKit.framework; sourceTree = DEVELOPER_DIR; }; - D9753A521BD3BE9D00C6F4B8 /* WebP.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = WebP.framework; path = ../Vendor/WebP.framework; sourceTree = ""; }; -/* End PBXFileReference section */ - -/* Begin PBXFrameworksBuildPhase section */ - D97539D91BD3BB6F00C6F4B8 /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - D9753A531BD3BE9D00C6F4B8 /* WebP.framework in Frameworks */, - D9753A511BD3BE8A00C6F4B8 /* UIKit.framework in Frameworks */, - D9753A4F1BD3BE8600C6F4B8 /* CoreFoundation.framework in Frameworks */, - D9753A4D1BD3BE8000C6F4B8 /* ImageIO.framework in Frameworks */, - D9753A4B1BD3BE7B00C6F4B8 /* QuartzCore.framework in Frameworks */, - D9753A491BD3BE7600C6F4B8 /* Accelerate.framework in Frameworks */, - D9753A471BD3BE7000C6F4B8 /* AssetsLibrary.framework in Frameworks */, - D9753A451BD3BE6C00C6F4B8 /* MobileCoreServices.framework in Frameworks */, - D9753A431BD3BE6800C6F4B8 /* libz.tbd in Frameworks */, - D9753A411BD3BE6400C6F4B8 /* libsqlite3.tbd in Frameworks */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXFrameworksBuildPhase section */ - -/* Begin PBXGroup section */ - D97539D31BD3BB6F00C6F4B8 = { - isa = PBXGroup; - children = ( - D97539F21BD3BBE600C6F4B8 /* YYWebImage */, - D97539F11BD3BBE000C6F4B8 /* Supporting Files */, - D97539DF1BD3BB6F00C6F4B8 /* Products */, - ); - sourceTree = ""; - }; - D97539DF1BD3BB6F00C6F4B8 /* Products */ = { - isa = PBXGroup; - children = ( - D97539DE1BD3BB6F00C6F4B8 /* YYWebImage.framework */, - ); - name = Products; - sourceTree = ""; - }; - D97539F11BD3BBE000C6F4B8 /* Supporting Files */ = { - isa = PBXGroup; - children = ( - D9753A521BD3BE9D00C6F4B8 /* WebP.framework */, - D9753A501BD3BE8A00C6F4B8 /* UIKit.framework */, - D9753A4E1BD3BE8600C6F4B8 /* CoreFoundation.framework */, - D9753A4C1BD3BE8000C6F4B8 /* ImageIO.framework */, - D9753A4A1BD3BE7B00C6F4B8 /* QuartzCore.framework */, - D9753A481BD3BE7600C6F4B8 /* Accelerate.framework */, - D9753A461BD3BE7000C6F4B8 /* AssetsLibrary.framework */, - D9753A441BD3BE6C00C6F4B8 /* MobileCoreServices.framework */, - D9753A421BD3BE6800C6F4B8 /* libz.tbd */, - D9753A401BD3BE6400C6F4B8 /* libsqlite3.tbd */, - D97539EF1BD3BB9D00C6F4B8 /* Info.plist */, - ); - name = "Supporting Files"; - sourceTree = ""; - }; - D97539F21BD3BBE600C6F4B8 /* YYWebImage */ = { - isa = PBXGroup; - children = ( - D9753A161BD3BBE600C6F4B8 /* YYWebImage.h */, - D9753A141BD3BBE600C6F4B8 /* YYImageCache.h */, - D9753A151BD3BBE600C6F4B8 /* YYImageCache.m */, - D9753A191BD3BBE600C6F4B8 /* YYWebImageOperation.h */, - D9753A1A1BD3BBE600C6F4B8 /* YYWebImageOperation.m */, - D9753A171BD3BBE600C6F4B8 /* YYWebImageManager.h */, - D9753A181BD3BBE600C6F4B8 /* YYWebImageManager.m */, - D9753A091BD3BBE600C6F4B8 /* Image */, - D97539F31BD3BBE600C6F4B8 /* Cache */, - D97539FC1BD3BBE600C6F4B8 /* Categories */, - ); - name = YYWebImage; - path = ../YYWebImage; - sourceTree = ""; - }; - D97539F31BD3BBE600C6F4B8 /* Cache */ = { - isa = PBXGroup; - children = ( - D97539F41BD3BBE600C6F4B8 /* YYCache.h */, - D97539F51BD3BBE600C6F4B8 /* YYCache.m */, - D97539FA1BD3BBE600C6F4B8 /* YYMemoryCache.h */, - D97539FB1BD3BBE600C6F4B8 /* YYMemoryCache.m */, - D97539F61BD3BBE600C6F4B8 /* YYDiskCache.h */, - D97539F71BD3BBE600C6F4B8 /* YYDiskCache.m */, - D97539F81BD3BBE600C6F4B8 /* YYKVStorage.h */, - D97539F91BD3BBE600C6F4B8 /* YYKVStorage.m */, - ); - path = Cache; - sourceTree = ""; - }; - D97539FC1BD3BBE600C6F4B8 /* Categories */ = { - isa = PBXGroup; - children = ( - D9753A051BD3BBE600C6F4B8 /* UIImage+YYWebImage.h */, - D9753A061BD3BBE600C6F4B8 /* UIImage+YYWebImage.m */, - D9753A071BD3BBE600C6F4B8 /* UIImageView+YYWebImage.h */, - D9753A081BD3BBE600C6F4B8 /* UIImageView+YYWebImage.m */, - D9753A031BD3BBE600C6F4B8 /* UIButton+YYWebImage.h */, - D9753A041BD3BBE600C6F4B8 /* UIButton+YYWebImage.m */, - D97539FF1BD3BBE600C6F4B8 /* CALayer+YYWebImage.h */, - D9753A001BD3BBE600C6F4B8 /* CALayer+YYWebImage.m */, - D9753A011BD3BBE600C6F4B8 /* MKAnnotationView+YYWebImage.h */, - D9753A021BD3BBE600C6F4B8 /* MKAnnotationView+YYWebImage.m */, - D97539FD1BD3BBE600C6F4B8 /* _YYWebImageSetter.h */, - D97539FE1BD3BBE600C6F4B8 /* _YYWebImageSetter.m */, - ); - path = Categories; - sourceTree = ""; - }; - D9753A091BD3BBE600C6F4B8 /* Image */ = { - isa = PBXGroup; - children = ( - D9753A0E1BD3BBE600C6F4B8 /* YYImage.h */, - D9753A0F1BD3BBE600C6F4B8 /* YYImage.m */, - D9753A0C1BD3BBE600C6F4B8 /* YYFrameImage.h */, - D9753A0D1BD3BBE600C6F4B8 /* YYFrameImage.m */, - D9753A121BD3BBE600C6F4B8 /* YYSpriteSheetImage.h */, - D9753A131BD3BBE600C6F4B8 /* YYSpriteSheetImage.m */, - D9753A101BD3BBE600C6F4B8 /* YYImageCoder.h */, - D9753A111BD3BBE600C6F4B8 /* YYImageCoder.m */, - D9753A0A1BD3BBE600C6F4B8 /* YYAnimatedImageView.h */, - D9753A0B1BD3BBE600C6F4B8 /* YYAnimatedImageView.m */, - ); - path = Image; - sourceTree = ""; - }; -/* End PBXGroup section */ - -/* Begin PBXHeadersBuildPhase section */ - D97539DA1BD3BB6F00C6F4B8 /* Headers */ = { - isa = PBXHeadersBuildPhase; - buildActionMask = 2147483647; - files = ( - D9753A2F1BD3BBE600C6F4B8 /* YYAnimatedImageView.h in Headers */, - D9753A211BD3BBE600C6F4B8 /* YYMemoryCache.h in Headers */, - D9753A251BD3BBE600C6F4B8 /* CALayer+YYWebImage.h in Headers */, - D9753A1F1BD3BBE600C6F4B8 /* YYKVStorage.h in Headers */, - D9753A291BD3BBE600C6F4B8 /* UIButton+YYWebImage.h in Headers */, - D9753A2D1BD3BBE600C6F4B8 /* UIImageView+YYWebImage.h in Headers */, - D9753A271BD3BBE600C6F4B8 /* MKAnnotationView+YYWebImage.h in Headers */, - D9753A1D1BD3BBE600C6F4B8 /* YYDiskCache.h in Headers */, - D9753A351BD3BBE600C6F4B8 /* YYImageCoder.h in Headers */, - D9753A311BD3BBE600C6F4B8 /* YYFrameImage.h in Headers */, - D9753A2B1BD3BBE600C6F4B8 /* UIImage+YYWebImage.h in Headers */, - D9753A1B1BD3BBE600C6F4B8 /* YYCache.h in Headers */, - D9753A3E1BD3BBE600C6F4B8 /* YYWebImageOperation.h in Headers */, - D9753A391BD3BBE600C6F4B8 /* YYImageCache.h in Headers */, - D9753A3B1BD3BBE600C6F4B8 /* YYWebImage.h in Headers */, - D9753A3C1BD3BBE600C6F4B8 /* YYWebImageManager.h in Headers */, - D9753A331BD3BBE600C6F4B8 /* YYImage.h in Headers */, - D9753A371BD3BBE600C6F4B8 /* YYSpriteSheetImage.h in Headers */, - D9753A231BD3BBE600C6F4B8 /* _YYWebImageSetter.h in Headers */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXHeadersBuildPhase section */ - -/* Begin PBXNativeTarget section */ - D97539DD1BD3BB6F00C6F4B8 /* YYWebImage */ = { - isa = PBXNativeTarget; - buildConfigurationList = D97539EC1BD3BB6F00C6F4B8 /* Build configuration list for PBXNativeTarget "YYWebImage" */; - buildPhases = ( - D97539D81BD3BB6F00C6F4B8 /* Sources */, - D97539D91BD3BB6F00C6F4B8 /* Frameworks */, - D97539DA1BD3BB6F00C6F4B8 /* Headers */, - D97539DB1BD3BB6F00C6F4B8 /* Resources */, - D97539DC1BD3BB6F00C6F4B8 /* ShellScript */, - ); - buildRules = ( - ); - dependencies = ( - ); - name = YYWebImage; - productName = YYWebImage; - productReference = D97539DE1BD3BB6F00C6F4B8 /* YYWebImage.framework */; - productType = "com.apple.product-type.bundle"; - }; -/* End PBXNativeTarget section */ - -/* Begin PBXProject section */ - D97539D41BD3BB6F00C6F4B8 /* Project object */ = { - isa = PBXProject; - attributes = { - LastUpgradeCheck = 0710; - ORGANIZATIONNAME = ibireme; - TargetAttributes = { - D97539DD1BD3BB6F00C6F4B8 = { - CreatedOnToolsVersion = 7.0.1; - }; - }; - }; - buildConfigurationList = D97539D71BD3BB6F00C6F4B8 /* Build configuration list for PBXProject "YYWebImage-Static" */; - compatibilityVersion = "Xcode 3.2"; - developmentRegion = English; - hasScannedForEncodings = 0; - knownRegions = ( - en, - ); - mainGroup = D97539D31BD3BB6F00C6F4B8; - productRefGroup = D97539DF1BD3BB6F00C6F4B8 /* Products */; - projectDirPath = ""; - projectRoot = ""; - targets = ( - D97539DD1BD3BB6F00C6F4B8 /* YYWebImage */, - ); - }; -/* End PBXProject section */ - -/* Begin PBXResourcesBuildPhase section */ - D97539DB1BD3BB6F00C6F4B8 /* Resources */ = { - isa = PBXResourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXResourcesBuildPhase section */ - -/* Begin PBXShellScriptBuildPhase section */ - D97539DC1BD3BB6F00C6F4B8 /* ShellScript */ = { - isa = PBXShellScriptBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - inputPaths = ( - ); - outputPaths = ( - ); - runOnlyForDeploymentPostprocessing = 0; - shellPath = /usr/bin/python; - shellScript = "# TAG: BUILD SCRIPT (do not remove this comment)\n# Build script generated using https://github.com/kstenerud/iOS-Universal-Framework Mk 8 (beta 2012-06-16)\nimport logging\n\n\n##############################################################################\n#\n# Configuration\n#\n##############################################################################\n\n# Select which kind of framework to build.\n#\n# Note: Due to issues with Xcode's build process, if you select\n# 'embeddedframework', it will still show the regular framework\n# (as a symlink) along side of the embedded framework. Be sure to\n# instruct your users to copy/move the embedded framework in this case!\n#\n# If your framework contains resources such as images, nibs, momds, plists,\n# zipfiles and such, choose 'embeddedframework'.\n#\n# If your framework contains no resources, choose 'framework'.\n#\nconfig_framework_type = 'framework'\n#config_framework_type = 'embeddedframework'\n\n# Open the build directory in Finder when the universal framework is\n# successfully built.\n#\n# This value can be overridden by setting the UFW_OPEN_BUILD_DIR env variable\n# to True or False.\n#\n# Recommended setting: True\n#\nconfig_open_build_dir = True\n\n# If true, ensures that all public headers are stored in the framework under\n# the same directory hierarchy as they were in the source tree.\n#\n# Xcode by default places all headers at the same top level, but every other\n# build tool in the known universe preserves directory structure. For simple\n# libraries it doesn't really matter much, but for ports of existing software\n# packages or for bigger libraries, it makes sense to have more structure.\n#\n# The default is set to \"False\" since that's what most Xcode users are used to.\n#\n# Recommended setting: True for deep hierarchy projects, False otherwise.\n#\nconfig_deep_header_hierarchy = False\n\n# Specify where the top of the public header hierarchy is. This path is\n# relative to the project's dir (PROJECT_DIR). You can reference environment\n# variables using templating syntax (e.g. \"${TARGET_NAME}/Some/Subdir\")\n#\n# NOTE: Only used if config_deep_header_hierarchy is True.\n#\n# If this is set to None, the script will attempt to figure out for itself\n# where the top of the header hierarchy is by looking for common path prefixes\n# in the public header files. This process can fail if:\n# - You only have one public header file.\n# - Your source header files don't all have a common root.\n#\n# A common approach is to use \"${TARGET_NAME}\", working under the assumption\n# that all of your header files share the common root of a directory under\n# your project with the same name as your target (which is the Xcode default).\n#\n# Recommended setting: \"${TARGET_NAME}\"\n#\nconfig_deep_header_top = \"${TARGET_NAME}\"\n\n# Warn when \"DerivedData\" is detected in any of the header, library, or\n# framework search paths. In almost all cases, references to directories under\n# DerivedData are added as a result of an Xcode bug and must be manually\n# removed.\n#\n# Recommended setting: True\n#\nconfig_warn_derived_data = True\n\n# Warn if no headers were marked public in this framework.\n#\n# Recommended setting: True\n#\nconfig_warn_no_public_headers = True\n\n# Cause the build to fail if any warnings are issued.\n#\n# Recommended setting: True\n#\nconfig_fail_on_warnings = True\n\n# Minimum log level\n#\n# Recommended setting: logging.INFO\n#\nconfig_log_level = logging.INFO\n\n\n##############################################################################\n#\n# Don't touch anything below here unless you know what you're doing.\n#\n##############################################################################\n\nimport collections\nimport json\nimport os\nimport re\nimport shlex\nimport shutil\nimport string\nimport subprocess\nimport sys\nimport time\nimport traceback\n\n\n##############################################################################\n#\n# Globals\n#\n##############################################################################\n\nlog = logging.getLogger('UFW')\n\nissued_warnings = False\n\n\n##############################################################################\n#\n# Classes\n#\n##############################################################################\n\n# Allows the slave build to communicate with the master build.\n#\nclass BuildState:\n\n def __init__(self):\n self.reload()\n\n def reset(self):\n self.slave_platform = None\n self.slave_architectures = []\n self.slave_linked_archive_paths = []\n self.slave_built_fw_path = None\n self.slave_built_embedded_fw_path = None\n\n def set_slave_properties(self, architectures,\n linked_archive_paths,\n built_fw_path,\n built_embedded_fw_path):\n self.slave_platform = os.environ['PLATFORM_NAME']\n self.slave_architectures = architectures\n self.slave_linked_archive_paths = linked_archive_paths\n self.slave_built_fw_path = built_fw_path\n self.slave_built_embedded_fw_path = built_embedded_fw_path\n\n def get_save_path(self):\n return os.path.join(os.environ['PROJECT_TEMP_DIR'], \"ufw_build_state.json\")\n\n def persist(self):\n filename = self.get_save_path()\n parent = os.path.dirname(filename)\n if not os.path.isdir(parent):\n os.makedirs(parent)\n with open(filename, \"w\") as f:\n f.write(json.dumps(self.__dict__))\n\n def reload(self):\n self.reset()\n filename = self.get_save_path()\n if os.path.exists(filename):\n with open(filename, \"r\") as f:\n new_dict = json.loads(f.read())\n if new_dict is not None:\n self.__dict__ = dict(self.__dict__.items() + new_dict.items())\n\n\n# Holds information about the current project and build environment.\n#\nclass Project:\n\n def __init__(self, filename):\n sourcecode_types = ['sourcecode.c.c',\n 'sourcecode.c.objc',\n 'sourcecode.cpp.cpp',\n 'sourcecode.cpp.objcpp',\n 'sourcecode.asm.asm',\n 'sourcecode.asm.llvm',\n 'sourcecode.nasm']\n\n self.build_state = BuildState()\n self.project_data = self.load_from_file(filename)\n self.target = filter(lambda x: x['name'] == os.environ['TARGET_NAME'], self.project_data['targets'])[0]\n self.public_headers = self.get_build_phase_files('PBXHeadersBuildPhase', lambda x: x.get('settings', False) and x['settings'].get('ATTRIBUTES', False) and 'Public' in x['settings']['ATTRIBUTES'])\n self.static_libraries = self.get_build_phase_files('PBXFrameworksBuildPhase', lambda x: x['fileRef']['fileType'] == 'archive.ar' and x['fileRef']['sourceTree'] not in ['DEVELOPER_DIR', 'SDKROOT'])\n self.static_frameworks = self.get_build_phase_files('PBXFrameworksBuildPhase', lambda x: x['fileRef']['fileType'] == 'wrapper.framework' and x['fileRef']['sourceTree'] not in ['DEVELOPER_DIR', 'SDKROOT'])\n self.compilable_sources = self.get_build_phase_files('PBXSourcesBuildPhase', lambda x: x['fileRef']['fileType'] in sourcecode_types)\n self.header_paths = [os.path.join(*x['pathComponents']) for x in self.public_headers]\n\n self.headers_dir = os.path.join(os.environ['TARGET_BUILD_DIR'], os.environ['CONTENTS_FOLDER_PATH'], 'Headers')\n self.libtool_path = os.path.join(os.environ['DT_TOOLCHAIN_DIR'], 'usr', 'bin', 'libtool')\n self.project_filename = os.path.join(os.environ['PROJECT_FILE_PATH'], \"project.pbxproj\")\n self.local_exe_path = os.path.join(os.environ['TARGET_BUILD_DIR'], os.environ['EXECUTABLE_PATH'])\n self.local_architectures = os.environ['ARCHS'].split(' ')\n self.local_built_fw_path = os.path.join(os.environ['TARGET_BUILD_DIR'], os.environ['WRAPPER_NAME'])\n self.local_built_embedded_fw_path = os.path.splitext(self.local_built_fw_path)[0] + \".embeddedframework\"\n self.local_linked_archive_paths = [self.get_linked_ufw_archive_path(arch) for arch in self.local_architectures]\n self.local_platform = os.environ['PLATFORM_NAME']\n other_platforms = os.environ['SUPPORTED_PLATFORMS'].split(' ')\n other_platforms.remove(self.local_platform)\n self.other_platform = other_platforms[0]\n\n sdk_name = os.environ['SDK_NAME']\n if not sdk_name.startswith(self.local_platform):\n raise Exception(\"%s didn't start with %s\" % (sdk_name, self.local_platform))\n self.sdk_version = sdk_name[len(self.local_platform):]\n\n # Load an Xcode project file.\n #\n def load_from_file(self, filename):\n project_file = json.loads(subprocess.check_output([\"plutil\", \"-convert\", \"json\", \"-o\", \"-\", filename]))\n all_objects = project_file['objects']\n del project_file['objects']\n for obj in all_objects.values():\n self.fix_keys(obj)\n self.unpack_objects(self.build_dereference_list(all_objects, None, None, project_file))\n self.unpack_objects(self.build_dereference_list(all_objects, None, None, all_objects.values()))\n project_data = project_file['rootObject']\n self.build_full_paths(project_data, splitpath(os.environ['SOURCE_ROOT']))\n return project_data\n\n def is_key(self, obj): \n return isinstance(obj, basestring) and len(obj) == 24 and re.search('^[0-9a-fA-F]+$', obj) is not None\n \n def build_dereference_list(self, all_objects, parent, key, obj):\n deref_list = []\n if self.is_key(obj):\n dereferenced = all_objects.get(obj, obj)\n if dereferenced is not obj:\n deref_list.append((parent, key, obj, dereferenced))\n elif isinstance(obj, collections.Mapping):\n for k, v in obj.iteritems():\n deref_list += self.build_dereference_list(all_objects, obj, k, v)\n elif isinstance(obj, collections.Iterable) and not isinstance(obj, basestring):\n for item in obj:\n deref_list += self.build_dereference_list(all_objects, obj, None, item)\n return deref_list\n \n def unpack_objects(self, deref_list):\n for parent, key, orig, obj in deref_list:\n if key is None:\n parent.remove(orig)\n parent.append(obj)\n else:\n parent[key] = obj\n\n # Store the full path, separated into components, to a node inside the node\n # as \"pathComponents\". Also recurse into that node if it's a group.\n #\n def build_full_paths(self, node, base_path):\n # Some nodes are relative to a different source tree, specified as an\n # env variable.\n if node.get('sourceTree', '') != '':\n new_base_path = os.environ.get(node['sourceTree'], None)\n if new_base_path:\n base_path = splitpath(new_base_path)\n # Add the current node's path, if any.\n if node.get('path', False):\n base_path = base_path + splitpath(node['path'])\n node['pathComponents'] = base_path\n # Recurse if this is a group.\n if node['isa'] == 'PBXGroup':\n for child in node['children']:\n self.build_full_paths(child, base_path)\n elif node['isa'] == 'PBXProject':\n self.build_full_paths(node['mainGroup'], base_path)\n self.build_full_paths(node['productRefGroup'], base_path)\n for child in node['targets']:\n self.build_full_paths(child, base_path)\n projectRefs = node.get('projectReferences', None)\n if projectRefs is not None:\n for child in projectRefs[0].values():\n self.build_full_paths(child, base_path)\n\n # Fix up any inconvenient keys.\n #\n def fix_keys(self, obj):\n key_remappings = {'lastKnownFileType': 'fileType', 'explicitFileType': 'fileType'}\n for key in list(set(key_remappings.keys()) & set(obj.keys())):\n obj[key_remappings[key]] = obj[key]\n del obj[key]\n\n # Get the files from a build phase.\n #\n def get_build_phase_files(self, build_phase_name, filter_func):\n build_phase = filter(lambda x: x['isa'] == build_phase_name, self.target['buildPhases'])[0]\n build_files = filter(filter_func, build_phase['files'])\n return [x['fileRef'] for x in build_files]\n\n # Get the truncated paths of all headers that start with the specified\n # relative path. Paths are read and returned as fully separated lists.\n # e.g. ['Some', 'Path', 'To', 'A', 'Header'] with relative_path of\n # ['Some', 'Path'] gets truncated to ['To', 'A', 'Header']\n #\n def movable_headers_relative_to(self, relative_path):\n rel_path_length = len(relative_path)\n result = filter(lambda path: len(path) >= rel_path_length and\n path[:rel_path_length] == relative_path, self.header_paths)\n return [path[rel_path_length:] for path in result]\n\n # Get the full path to where a linkable archive (library or framework)\n # is supposed to be.\n #\n def get_linked_archive_path(self, architecture):\n return os.path.join(os.environ['OBJECT_FILE_DIR_%s' % os.environ['CURRENT_VARIANT']],\n architecture,\n os.environ['EXECUTABLE_NAME'])\n\n # Get the full path to our custom linked archive of the project.\n #\n def get_linked_ufw_archive_path(self, architecture):\n return self.get_linked_archive_path(architecture) + \".ufwbuild\"\n\n # Get the full path to the executable of an archive.\n #\n def get_exe_path(self, node):\n path = os.path.join(*node['pathComponents'])\n if node['fileType'] == 'wrapper.framework':\n # Frameworks are directories, so go one deeper\n path = os.path.join(path, os.path.splitext(node['pathComponents'][-1])[0])\n return path\n\n # Get the path to the directory containing the archive.\n #\n def get_containing_path(self, node):\n return os.path.join(*node['pathComponents'])\n \n def get_archive_search_paths(self):\n log.info(\"Search paths = %s\" % set([self.get_containing_path(fw) for fw in self.static_frameworks] + [self.get_containing_path(fw) for fw in self.static_libraries]))\n return set([self.get_containing_path(fw) for fw in self.static_frameworks] + [self.get_containing_path(fw) for fw in self.static_libraries])\n\n # Command to link all objects of a single architecture.\n #\n def get_single_arch_link_command(self, architecture):\n cmd = [self.libtool_path,\n \"-static\",\n \"-arch_only\", architecture,\n \"-syslibroot\", os.environ['SDKROOT'],\n \"-L%s\" % os.environ['TARGET_BUILD_DIR'],\n \"-filelist\", os.environ['LINK_FILE_LIST_%s_%s' % (os.environ['CURRENT_VARIANT'], architecture)]]\n if os.environ.get('OTHER_LDFLAGS', False):\n cmd += [os.environ['OTHER_LDFLAGS']]\n if os.environ.get('WARNING_LDFLAGS', False):\n cmd += [os.environ['WARNING_LDFLAGS']]\n# cmd += [\"-L%s\" % libpath for libpath in self.get_archive_search_paths()]\n cmd += [self.get_exe_path(fw) for fw in self.static_frameworks]\n cmd += [self.get_exe_path(lib) for lib in self.static_libraries]\n cmd += [\"-o\", self.get_linked_ufw_archive_path(architecture)]\n return cmd\n\n # Command to link all local architectures for the current configuration\n # into an archive. This reads all libraries + the UFW-built archives and\n # overwrites the final product.\n #\n def get_local_archs_link_command(self):\n cmd = [self.libtool_path,\n \"-static\"]\n cmd += self.local_linked_archive_paths\n cmd += [self.get_exe_path(fw) for fw in self.static_frameworks]\n cmd += [self.get_exe_path(lib) for lib in self.static_libraries]\n cmd += [\"-o\", os.path.join(os.environ['TARGET_BUILD_DIR'], os.environ['EXECUTABLE_PATH'])]\n return cmd\n\n # Command to link all architectures into a universal archive.\n # This reads all UFW-built archives and overwrites the final product.\n #\n def get_all_archs_link_command(self):\n cmd = [self.libtool_path,\n \"-static\"]\n cmd += self.local_linked_archive_paths + self.build_state.slave_linked_archive_paths\n cmd += [\"-o\", os.path.join(os.environ['TARGET_BUILD_DIR'], os.environ['EXECUTABLE_PATH'])]\n return cmd\n\n # Build up an environment for the slave process. This uses BUILD_ROOT\n # and TEMP_ROOT to convert all environment variables to values suitable\n # for the slave build environment so that xcodebuild doesn't try to build\n # in the project directory under \"build\".\n #\n def get_slave_environment(self):\n ignored = ['LD_MAP_FILE_PATH',\n 'HEADER_SEARCH_PATHS',\n 'LIBRARY_SEARCH_PATHS',\n 'FRAMEWORK_SEARCH_PATHS']\n build_root = os.environ['BUILD_ROOT']\n temp_root = os.environ['TEMP_ROOT']\n newenv = {}\n for key, value in os.environ.items():\n if key not in ignored and not key.startswith('LINK_FILE_LIST_') and not key.startswith('LD_DEPENDENCY_'):\n if build_root in value or temp_root in value:\n newenv[key] = value.replace(self.local_platform, self.other_platform)\n return newenv\n\n # Command to invoke xcodebuild on the slave platform.\n #\n def get_slave_project_build_command(self):\n cmd = [\"xcodebuild\",\n \"-project\",\n os.environ['PROJECT_FILE_PATH'],\n \"-target\",\n os.environ['TARGET_NAME'],\n \"-configuration\",\n os.environ['CONFIGURATION'],\n \"-sdk\",\n self.other_platform + self.sdk_version]\n cmd += [\"%s=%s\" % (key, value) for key, value in self.get_slave_environment().items()]\n cmd += [\"UFW_MASTER_PLATFORM=\" + os.environ['PLATFORM_NAME']]\n cmd += [os.environ['ACTION']]\n return cmd\n\n\n\n##############################################################################\n#\n# Utility Functions\n#\n##############################################################################\n\n# Split a path into a list of path components.\n#\ndef splitpath(path, maxdepth=20):\n (head, tail) = os.path.split(path)\n return splitpath(head, maxdepth - 1) + [tail] if maxdepth and head and head != path else [ head or tail ]\n\n# Remove all subdirectories under a path.\n#\ndef remove_subdirs(path, ignore_files):\n if os.path.exists(path):\n for filename in filter(lambda x: x not in ignore_files, os.listdir(path)):\n fullpath = os.path.join(path, filename)\n if os.path.isdir(fullpath):\n log.info(\"Remove %s\" % fullpath)\n shutil.rmtree(fullpath)\n\n# Make whatever parent paths are necessary for a path to exist.\n#\ndef ensure_path_exists(path):\n if not os.path.isdir(path):\n os.makedirs(path)\n\n# Make whatever parent paths are necessary for a path's parent to exist.\n#\ndef ensure_parent_exists(path):\n parent = os.path.dirname(path)\n if not os.path.isdir(parent):\n os.makedirs(parent)\n\n# Remove a file or dir if it exists.\n#\ndef remove_path(path):\n if os.path.exists(path):\n if os.path.isdir(path) and not os.path.islink(path):\n shutil.rmtree(path)\n else:\n os.remove(path)\n\n# Move a file or dir, replacing the destination if it exists.\n#\ndef move_file(src, dst):\n if src == dst or not os.path.isfile(src):\n return\n log.info(\"Move %s to %s\" % (src, dst))\n ensure_parent_exists(dst)\n remove_path(dst)\n shutil.move(src, dst)\n\n# Copy a file or dir, replacing the destination if it exists already.\n#\ndef copy_overwrite(src, dst):\n if src != dst:\n remove_path(dst)\n ensure_parent_exists(dst)\n shutil.copytree(src, dst, symlinks=True)\n\n# Attempt to symlink link_path -> link_to.\n# link_to must be a path relative to link_path's parent and must exist.\n# If link_path already exists, do nothing.\n#\ndef attempt_symlink(link_path, link_to):\n # Only allow linking to an existing file\n os.stat(os.path.abspath(os.path.join(link_path, \"..\", link_to)))\n\n # Only make the link if it hasn't already been made\n if not os.path.exists(link_path):\n log.info(\"Symlink %s -> %s\" % (link_path, link_to))\n os.symlink(link_to, link_path)\n\n# Takes the last entry in an array-based path and returns a normal path\n# relative to base_path.\n#\ndef top_level_file_path(base_path, path_list):\n return os.path.join(base_path, os.path.split(path_list[-1])[-1])\n\n# Takes all entries in an array-based path and returns a normal path\n# relative to base_path.\n#\ndef full_file_path(base_path, path_list):\n return os.path.join(*([base_path] + path_list))\n\n# Print a command before executing it.\n# Also print out all output from the command to STDOUT.\n#\ndef print_and_call(cmd):\n log.info(\"Cmd \" + \" \".join(cmd))\n p = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)\n result = p.communicate()[0]\n if len(result) > 0:\n log.info(result)\n if p.returncode != 0:\n raise subprocess.CalledProcessError(p.returncode, cmd)\n\n# Special print-and-call command for the slave build that strips out\n# xcodebuild's spammy list of environment variables.\n#\ndef print_and_call_slave_build(cmd, other_platform):\n separator = '=== BUILD NATIVE TARGET '\n p = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)\n result = p.communicate()[0].split(separator)\n if len(result) == 1:\n result = result[0]\n else:\n result = separator + result[1]\n log.info(\"Cmd \" + \" \".join(cmd) + \"\\n\" + result)\n if p.returncode != 0:\n raise subprocess.CalledProcessError(p.returncode, cmd)\n\n# Issue a warning and record that a warning has been issued.\n#\ndef issue_warning(msg, *args, **kwargs):\n global issued_warnings\n issued_warnings = True\n log.warn(msg, *args, **kwargs)\n\n\n\n##############################################################################\n#\n# Main Application\n#\n##############################################################################\n\n# Check if we are running as master.\n#\ndef is_master():\n return os.environ.get('UFW_MASTER_PLATFORM', os.environ['PLATFORM_NAME']) == os.environ['PLATFORM_NAME']\n\n# DerivedData should almost never appear in any framework, library, or header\n# search paths. However, Xcode will sometimes add them in, so we check to make\n# sure.\n#\ndef check_for_derived_data_in_search_paths(project):\n search_path_keys = [\"FRAMEWORK_SEARCH_PATHS\", \"LIBRARY_SEARCH_PATHS\", \"HEADER_SEARCH_PATHS\"]\n build_configs = project.target['buildConfigurationList']['buildConfigurations']\n build_settings = filter(lambda x: x['name'] == os.environ['CONFIGURATION'], build_configs)[0]['buildSettings']\n \n found_something = False\n for path_key in filter(lambda x: x in build_settings, search_path_keys):\n path = build_settings[path_key]\n if \"DerivedData\" in path:\n found_something = True\n log.warn(\"Derived data in %s\" % path)\n issue_warning(\"'%s' contains reference to 'DerivedData'.\" % path_key)\n if found_something:\n log.warn(\"Check your build settings and remove any entries that contain paths inside the DerivedData folder.\")\n log.warn(\"Otherwise you can disable this warning by changing 'config_warn_derived_data' in this script.\")\n\n# Link local architectures into their respective archives.\n#\ndef link_local_archs(project):\n for arch in project.local_architectures:\n print_and_call(project.get_single_arch_link_command(arch))\n\n# Link only the local architectures into the final product, not the slave\n# architectures. For iphoneos, this will be armv6, armv7. For simulator, this\n# will be i386.\n#\ndef link_combine_local_archs(project):\n print_and_call(project.get_local_archs_link_command())\n\n# Link all architectures into the final product.\n#\ndef link_combine_all_archs(project):\n print_and_call(project.get_all_archs_link_command())\n\n# Check if we should open the build directory after a successful build.\n#\ndef should_open_build_dir():\n env_setting = os.environ.get('UFW_OPEN_BUILD_DIR', None)\n if env_setting is not None:\n return env_setting\n\n return config_open_build_dir\n\n# Open the build dir in Finder.\n#\ndef open_build_dir():\n print_and_call(['open', os.environ['TARGET_BUILD_DIR']])\n\n# Check if the build was started by selecting \"Archive\" under \"Product\" in\n# Xcode.\n#\ndef is_archive_build():\n # ACTION is always 'build', but perhaps Apple will fix this someday?\n archive_build = os.environ['ACTION'] == 'archive'\n\n if not archive_build:\n # This can be passed in as an env variable when building from command line.\n archive_build = os.environ.get('UFW_ACTION', None) == 'archive'\n\n build_dir = splitpath(os.environ['BUILD_DIR'])\n if not archive_build:\n # This partial path is used when you select \"archive\" from within Xcode.\n archive_build = 'ArchiveIntermediates' in build_dir\n\n # It only counts as a full archive build if this target is being built into\n # its own build dir (not being built as a dependency of another target)\n if archive_build:\n archive_build = os.environ['TARGET_NAME'] in build_dir\n \n return archive_build\n\n# Xcode by default throws all public headers into the top level directory.\n# This function moves them to their expected deep hierarchy.\n#\ndef build_deep_header_hierarchy(project):\n header_path_top = config_deep_header_top\n if not header_path_top:\n header_path_top = os.path.commonprefix(project.header_paths)\n else:\n header_path_top = splitpath(header_path_top)\n\n built_headers_path = os.path.join(os.environ['TARGET_BUILD_DIR'], os.environ['PUBLIC_HEADERS_FOLDER_PATH'])\n movable_headers = project.movable_headers_relative_to(header_path_top)\n\n # Remove subdirs if they only contain files that have been rebuilt\n ignore_headers = filter(lambda x: not os.path.isfile(top_level_file_path(built_headers_path, x)), movable_headers)\n remove_subdirs(built_headers_path, [file[0] for file in ignore_headers])\n\n # Move rebuilt headers into their proper subdirs\n for header in movable_headers:\n move_file(top_level_file_path(built_headers_path, header), full_file_path(built_headers_path, header))\n\n# Add all symlinks needed to make a full framework structure:\n#\n# MyFramework.framework\n# |-- MyFramework -> Versions/Current/MyFramework\n# |-- Headers -> Versions/Current/Headers\n# |-- Resources -> Versions/Current/Resources\n# `-- Versions\n# |-- A\n# | |-- MyFramework\n# | |-- Headers\n# | | `-- MyFramework.h\n# | `-- Resources\n# | |-- Info.plist\n# | |-- MyViewController.nib\n# | `-- en.lproj\n# | `-- InfoPlist.strings\n# `-- Current -> A\n#\ndef add_symlinks_to_framework(project):\n base_dir = project.local_built_fw_path\n attempt_symlink(os.path.join(base_dir, \"Versions\", \"Current\"), os.environ['FRAMEWORK_VERSION'])\n if os.path.isdir(os.path.join(base_dir, \"Versions\", \"Current\", \"Headers\")):\n attempt_symlink(os.path.join(base_dir, \"Headers\"), os.path.join(\"Versions\", \"Current\", \"Headers\"))\n if os.path.isdir(os.path.join(base_dir, \"Versions\", \"Current\", \"Resources\")):\n attempt_symlink(os.path.join(base_dir, \"Resources\"), os.path.join(\"Versions\", \"Current\", \"Resources\"))\n attempt_symlink(os.path.join(base_dir, os.environ['EXECUTABLE_NAME']), os.path.join(\"Versions\", \"Current\", os.environ['EXECUTABLE_NAME']))\n\n# Build an embedded framework structure.\n# An embedded framework contains the actual framework, plus a \"Resources\"\n# directory containing symlinks to all resources found in the actual framework,\n# with the exception of \"Info.plist\" and anything ending in \".lproj\":\n#\n# MyFramework.embeddedframework\n# |-- MyFramework.framework\n# | |-- MyFramework -> Versions/Current/MyFramework\n# | |-- Headers -> Versions/Current/Headers\n# | |-- Resources -> Versions/Current/Resources\n# | `-- Versions\n# | |-- A\n# | | |-- MyFramework\n# | | |-- Headers\n# | | | `-- MyFramework.h\n# | | `-- Resources\n# | | |-- Info.plist\n# | | |-- MyViewController.nib\n# | | `-- en.lproj\n# | | `-- InfoPlist.strings\n# | `-- Current -> A\n# `-- Resources\n# `-- MyViewController.nib -> ../MyFramework.framework/Resources/MyViewController.nib\n#\ndef build_embedded_framework(project):\n fw_path = project.local_built_fw_path\n embedded_path = project.local_built_embedded_fw_path\n fw_name = os.environ['WRAPPER_NAME']\n\n if (os.path.islink(fw_path)):\n # If the framework path is a link, the build result already in embeddedframework.\n # Just recreate embeddedframework's Resources\n remove_path(os.path.join(embedded_path, \"Resources\"))\n else:\n remove_path(embedded_path)\n ensure_path_exists(embedded_path)\n copy_overwrite(fw_path, os.path.join(embedded_path, fw_name))\n\n # Create embeddedframework's Resources \n ensure_path_exists(os.path.join(embedded_path, \"Resources\"))\n symlink_source = os.path.join(\"..\", fw_name, \"Resources\")\n symlink_path = os.path.join(embedded_path, \"Resources\")\n if os.path.isdir(os.path.join(fw_path, \"Resources\")):\n for file in filter(lambda x: x != \"Info.plist\" and not x.endswith(\".lproj\"), os.listdir(os.path.join(fw_path, \"Resources\"))):\n attempt_symlink(os.path.join(symlink_path, file), os.path.join(symlink_source, file))\n\n # Remove the normal framework and replace it with a symlink to the copy\n # in the embedded framework. This is needed because Xcode runs its strip\n # phase AFTER the script runs.\n embed_fw_wrapper = os.path.splitext(os.environ['WRAPPER_NAME'])[0] + \".embeddedframework\"\n remove_path(fw_path)\n attempt_symlink(fw_path, os.path.join(embed_fw_wrapper, os.environ['WRAPPER_NAME']))\n\n\n# Run the build process in slave mode to build the other configuration\n# (device/simulator).\n#\ndef run_slave_build(project):\n print_and_call_slave_build(project.get_slave_project_build_command(), project.other_platform)\n\n# Run the build process.\n#\ndef run_build():\n project = Project(os.path.join(os.environ['PROJECT_FILE_PATH'], \"project.pbxproj\"))\n\n # Issue warnings only if we're master.\n if is_master():\n if len(project.compilable_sources) == 0:\n raise Exception(\"No compilable sources found. Please add at least one source file to build target %s.\" % os.environ['TARGET_NAME'])\n\n if config_warn_derived_data:\n check_for_derived_data_in_search_paths(project)\n if config_warn_no_public_headers and len(project.public_headers) == 0:\n issue_warning('No headers in build target %s were marked public. Please move at least one header to \"Public\" in the \"Copy Headers\" build phase.' % os.environ['TARGET_NAME'])\n\n # Only build slave if this is an archive build.\n if is_archive_build():\n if is_master():\n log.debug(\"Building as MASTER\")\n # The slave-side linker tries to include this (nonexistent) path as\n # a library path.\n ensure_path_exists(project.get_slave_environment()['BUILT_PRODUCTS_DIR'])\n project.build_state.persist()\n run_slave_build(project)\n project.build_state.reload()\n else:\n log.debug(\"Building as SLAVE\")\n project.build_state.reload()\n project.build_state.set_slave_properties(project.local_architectures,\n project.local_linked_archive_paths,\n project.local_built_fw_path,\n project.local_built_embedded_fw_path)\n project.build_state.persist()\n\n link_local_archs(project)\n \n # Only do a universal binary when building an archive.\n if is_archive_build() and is_master():\n link_combine_all_archs(project)\n else:\n link_combine_local_archs(project)\n\n if config_deep_header_hierarchy:\n build_deep_header_hierarchy(project)\n\n add_symlinks_to_framework(project)\n \n if is_master():\n if config_framework_type == 'embeddedframework':\n build_embedded_framework(project)\n elif config_framework_type != 'framework':\n raise Exception(\"%s: Unknown framework type for config_framework_type\" % config_framework_type)\n\n\nif __name__ == \"__main__\":\n log_handler = logging.StreamHandler()\n log_handler.setFormatter(logging.Formatter(\"%(name)s (\" + os.environ['PLATFORM_NAME'] + \"): %(levelname)s: %(message)s\"))\n log.addHandler(log_handler)\n log.setLevel(config_log_level)\n\n error_code = 0\n prefix = \"M\" if is_master() else \"S\"\n log_handler.setFormatter(logging.Formatter(\"%(name)s (\" + prefix + \" \" + os.environ['PLATFORM_NAME'] + \"): %(levelname)s: %(message)s\"))\n\n log.debug(\"Begin build process\")\n\n if config_deep_header_top:\n config_deep_header_top = string.Template(config_deep_header_top).substitute(os.environ)\n\n try:\n run_build()\n if issued_warnings:\n if config_fail_on_warnings:\n error_code = 1\n log.warn(\"Build completed with warnings\")\n else:\n log.info(\"Build completed\")\n if not is_archive_build():\n log.info(\"Note: This is *NOT* a universal framework build. To build as a universal framework, do an archive build.\")\n log.info(\"To do an archive build from command line, use \\\"xcodebuild -configuration Release UFW_ACTION=archive clean build\\\"\")\n except Exception:\n traceback.print_exc(file=sys.stdout)\n error_code = 1\n log.error(\"Build failed\")\n finally:\n if error_code == 0 and is_archive_build() and is_master():\n log.info(\"Built framework is in \" + os.environ['TARGET_BUILD_DIR'])\n if should_open_build_dir():\n open_build_dir()\n sys.exit(error_code)\n"; - showEnvVarsInLog = 0; - }; -/* End PBXShellScriptBuildPhase section */ - -/* Begin PBXSourcesBuildPhase section */ - D97539D81BD3BB6F00C6F4B8 /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - D9753A2A1BD3BBE600C6F4B8 /* UIButton+YYWebImage.m in Sources */, - D9753A281BD3BBE600C6F4B8 /* MKAnnotationView+YYWebImage.m in Sources */, - D9753A3A1BD3BBE600C6F4B8 /* YYImageCache.m in Sources */, - D9753A201BD3BBE600C6F4B8 /* YYKVStorage.m in Sources */, - D9753A341BD3BBE600C6F4B8 /* YYImage.m in Sources */, - D9753A221BD3BBE600C6F4B8 /* YYMemoryCache.m in Sources */, - D9753A361BD3BBE600C6F4B8 /* YYImageCoder.m in Sources */, - D9753A301BD3BBE600C6F4B8 /* YYAnimatedImageView.m in Sources */, - D9753A2C1BD3BBE600C6F4B8 /* UIImage+YYWebImage.m in Sources */, - D9753A261BD3BBE600C6F4B8 /* CALayer+YYWebImage.m in Sources */, - D9753A381BD3BBE600C6F4B8 /* YYSpriteSheetImage.m in Sources */, - D9753A1C1BD3BBE600C6F4B8 /* YYCache.m in Sources */, - D9753A1E1BD3BBE600C6F4B8 /* YYDiskCache.m in Sources */, - D9753A3D1BD3BBE600C6F4B8 /* YYWebImageManager.m in Sources */, - D9753A321BD3BBE600C6F4B8 /* YYFrameImage.m in Sources */, - D9753A241BD3BBE600C6F4B8 /* _YYWebImageSetter.m in Sources */, - D9753A3F1BD3BBE600C6F4B8 /* YYWebImageOperation.m in Sources */, - D9753A2E1BD3BBE600C6F4B8 /* UIImageView+YYWebImage.m in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXSourcesBuildPhase section */ - -/* Begin XCBuildConfiguration section */ - D97539EA1BD3BB6F00C6F4B8 /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_UNREACHABLE_CODE = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - COPY_PHASE_STRIP = NO; - DEBUG_INFORMATION_FORMAT = dwarf; - ENABLE_STRICT_OBJC_MSGSEND = YES; - ENABLE_TESTABILITY = YES; - GCC_C_LANGUAGE_STANDARD = gnu99; - GCC_DYNAMIC_NO_PIC = NO; - GCC_NO_COMMON_BLOCKS = YES; - GCC_OPTIMIZATION_LEVEL = 0; - GCC_PREPROCESSOR_DEFINITIONS = ( - "DEBUG=1", - "$(inherited)", - ); - GCC_WARN_64_TO_32_BIT_CONVERSION = YES; - GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; - GCC_WARN_UNDECLARED_SELECTOR = YES; - GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; - GCC_WARN_UNUSED_FUNCTION = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - MTL_ENABLE_DEBUG_INFO = YES; - ONLY_ACTIVE_ARCH = YES; - }; - name = Debug; - }; - D97539EB1BD3BB6F00C6F4B8 /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_UNREACHABLE_CODE = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - COPY_PHASE_STRIP = NO; - DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; - ENABLE_NS_ASSERTIONS = NO; - ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_C_LANGUAGE_STANDARD = gnu99; - GCC_NO_COMMON_BLOCKS = YES; - GCC_WARN_64_TO_32_BIT_CONVERSION = YES; - GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; - GCC_WARN_UNDECLARED_SELECTOR = YES; - GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; - GCC_WARN_UNUSED_FUNCTION = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - MTL_ENABLE_DEBUG_INFO = NO; - }; - name = Release; - }; - D97539ED1BD3BB6F00C6F4B8 /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - CONTENTS_FOLDER_PATH = "$(WRAPPER_NAME)/Versions/$(FRAMEWORK_VERSION)"; - DEAD_CODE_STRIPPING = NO; - DYLIB_COMPATIBILITY_VERSION = 1; - DYLIB_CURRENT_VERSION = 1; - FRAMEWORK_SEARCH_PATHS = "\"$(SRCROOT)/../Vendor\""; - FRAMEWORK_VERSION = A; - INFOPLIST_FILE = Info.plist; - INFOPLIST_PATH = "$(UNLOCALIZED_RESOURCES_FOLDER_PATH)/Info.plist"; - INSTALL_PATH = "$(BUILT_PRODUCTS_DIR)"; - IPHONEOS_DEPLOYMENT_TARGET = 6.0; - LINK_WITH_STANDARD_LIBRARIES = NO; - MACH_O_TYPE = mh_object; - PRODUCT_BUNDLE_IDENTIFIER = com.ibireme.YYWebImage; - PRODUCT_NAME = "$(TARGET_NAME)"; - SDKROOT = iphoneos; - SKIP_INSTALL = YES; - UNLOCALIZED_RESOURCES_FOLDER_PATH = "$(CONTENTS_FOLDER_PATH)/Resources"; - WRAPPER_EXTENSION = framework; - }; - name = Debug; - }; - D97539EE1BD3BB6F00C6F4B8 /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - CONTENTS_FOLDER_PATH = "$(WRAPPER_NAME)/Versions/$(FRAMEWORK_VERSION)"; - DEAD_CODE_STRIPPING = NO; - DYLIB_COMPATIBILITY_VERSION = 1; - DYLIB_CURRENT_VERSION = 1; - FRAMEWORK_SEARCH_PATHS = "\"$(SRCROOT)/../Vendor\""; - FRAMEWORK_VERSION = A; - INFOPLIST_FILE = Info.plist; - INFOPLIST_PATH = "$(UNLOCALIZED_RESOURCES_FOLDER_PATH)/Info.plist"; - INSTALL_PATH = "$(BUILT_PRODUCTS_DIR)"; - IPHONEOS_DEPLOYMENT_TARGET = 6.0; - LINK_WITH_STANDARD_LIBRARIES = NO; - MACH_O_TYPE = mh_object; - PRODUCT_BUNDLE_IDENTIFIER = com.ibireme.YYWebImage; - PRODUCT_NAME = "$(TARGET_NAME)"; - SDKROOT = iphoneos; - SKIP_INSTALL = YES; - UNLOCALIZED_RESOURCES_FOLDER_PATH = "$(CONTENTS_FOLDER_PATH)/Resources"; - WRAPPER_EXTENSION = framework; - }; - name = Release; - }; -/* End XCBuildConfiguration section */ - -/* Begin XCConfigurationList section */ - D97539D71BD3BB6F00C6F4B8 /* Build configuration list for PBXProject "YYWebImage-Static" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - D97539EA1BD3BB6F00C6F4B8 /* Debug */, - D97539EB1BD3BB6F00C6F4B8 /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - D97539EC1BD3BB6F00C6F4B8 /* Build configuration list for PBXNativeTarget "YYWebImage" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - D97539ED1BD3BB6F00C6F4B8 /* Debug */, - D97539EE1BD3BB6F00C6F4B8 /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; -/* End XCConfigurationList section */ - }; - rootObject = D97539D41BD3BB6F00C6F4B8 /* Project object */; -} diff --git a/Framework/YYWebImage-Static.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/Framework/YYWebImage-Static.xcodeproj/project.xcworkspace/contents.xcworkspacedata deleted file mode 100644 index 17b1522..0000000 --- a/Framework/YYWebImage-Static.xcodeproj/project.xcworkspace/contents.xcworkspacedata +++ /dev/null @@ -1,7 +0,0 @@ - - - - - diff --git a/Framework/YYWebImage.xcodeproj/project.pbxproj b/Framework/YYWebImage.xcodeproj/project.pbxproj index 977e023..9f647a7 100644 --- a/Framework/YYWebImage.xcodeproj/project.pbxproj +++ b/Framework/YYWebImage.xcodeproj/project.pbxproj @@ -3,272 +3,272 @@ archiveVersion = 1; classes = { }; - objectVersion = 46; + objectVersion = 48; objects = { /* Begin PBXBuildFile section */ - D97539951BD2997800C6F4B8 /* YYCache.h in Headers */ = {isa = PBXBuildFile; fileRef = D97539701BD2997800C6F4B8 /* YYCache.h */; settings = {ATTRIBUTES = (Public, ); }; }; - D97539961BD2997800C6F4B8 /* YYCache.m in Sources */ = {isa = PBXBuildFile; fileRef = D97539711BD2997800C6F4B8 /* YYCache.m */; settings = {ASSET_TAGS = (); }; }; - D97539971BD2997800C6F4B8 /* YYDiskCache.h in Headers */ = {isa = PBXBuildFile; fileRef = D97539721BD2997800C6F4B8 /* YYDiskCache.h */; settings = {ATTRIBUTES = (Public, ); }; }; - D97539981BD2997800C6F4B8 /* YYDiskCache.m in Sources */ = {isa = PBXBuildFile; fileRef = D97539731BD2997800C6F4B8 /* YYDiskCache.m */; settings = {ASSET_TAGS = (); }; }; - D97539991BD2997800C6F4B8 /* YYKVStorage.h in Headers */ = {isa = PBXBuildFile; fileRef = D97539741BD2997800C6F4B8 /* YYKVStorage.h */; settings = {ATTRIBUTES = (Public, ); }; }; - D975399A1BD2997800C6F4B8 /* YYKVStorage.m in Sources */ = {isa = PBXBuildFile; fileRef = D97539751BD2997800C6F4B8 /* YYKVStorage.m */; settings = {ASSET_TAGS = (); }; }; - D975399B1BD2997800C6F4B8 /* YYMemoryCache.h in Headers */ = {isa = PBXBuildFile; fileRef = D97539761BD2997800C6F4B8 /* YYMemoryCache.h */; settings = {ATTRIBUTES = (Public, ); }; }; - D975399C1BD2997800C6F4B8 /* YYMemoryCache.m in Sources */ = {isa = PBXBuildFile; fileRef = D97539771BD2997800C6F4B8 /* YYMemoryCache.m */; settings = {ASSET_TAGS = (); }; }; - D975399D1BD2997800C6F4B8 /* _YYWebImageSetter.h in Headers */ = {isa = PBXBuildFile; fileRef = D97539791BD2997800C6F4B8 /* _YYWebImageSetter.h */; settings = {ATTRIBUTES = (Private, ); }; }; - D975399E1BD2997800C6F4B8 /* _YYWebImageSetter.m in Sources */ = {isa = PBXBuildFile; fileRef = D975397A1BD2997800C6F4B8 /* _YYWebImageSetter.m */; settings = {ASSET_TAGS = (); }; }; - D975399F1BD2997800C6F4B8 /* CALayer+YYWebImage.h in Headers */ = {isa = PBXBuildFile; fileRef = D975397B1BD2997800C6F4B8 /* CALayer+YYWebImage.h */; settings = {ATTRIBUTES = (Public, ); }; }; - D97539A01BD2997800C6F4B8 /* CALayer+YYWebImage.m in Sources */ = {isa = PBXBuildFile; fileRef = D975397C1BD2997800C6F4B8 /* CALayer+YYWebImage.m */; settings = {ASSET_TAGS = (); }; }; - D97539A11BD2997800C6F4B8 /* MKAnnotationView+YYWebImage.h in Headers */ = {isa = PBXBuildFile; fileRef = D975397D1BD2997800C6F4B8 /* MKAnnotationView+YYWebImage.h */; settings = {ATTRIBUTES = (Public, ); }; }; - D97539A21BD2997800C6F4B8 /* MKAnnotationView+YYWebImage.m in Sources */ = {isa = PBXBuildFile; fileRef = D975397E1BD2997800C6F4B8 /* MKAnnotationView+YYWebImage.m */; settings = {ASSET_TAGS = (); }; }; - D97539A31BD2997800C6F4B8 /* UIButton+YYWebImage.h in Headers */ = {isa = PBXBuildFile; fileRef = D975397F1BD2997800C6F4B8 /* UIButton+YYWebImage.h */; settings = {ATTRIBUTES = (Public, ); }; }; - D97539A41BD2997800C6F4B8 /* UIButton+YYWebImage.m in Sources */ = {isa = PBXBuildFile; fileRef = D97539801BD2997800C6F4B8 /* UIButton+YYWebImage.m */; settings = {ASSET_TAGS = (); }; }; - D97539A51BD2997800C6F4B8 /* UIImageView+YYWebImage.h in Headers */ = {isa = PBXBuildFile; fileRef = D97539811BD2997800C6F4B8 /* UIImageView+YYWebImage.h */; settings = {ATTRIBUTES = (Public, ); }; }; - D97539A61BD2997800C6F4B8 /* UIImageView+YYWebImage.m in Sources */ = {isa = PBXBuildFile; fileRef = D97539821BD2997800C6F4B8 /* UIImageView+YYWebImage.m */; settings = {ASSET_TAGS = (); }; }; - D97539A71BD2997800C6F4B8 /* YYAnimatedImageView.h in Headers */ = {isa = PBXBuildFile; fileRef = D97539841BD2997800C6F4B8 /* YYAnimatedImageView.h */; settings = {ATTRIBUTES = (Public, ); }; }; - D97539A81BD2997800C6F4B8 /* YYAnimatedImageView.m in Sources */ = {isa = PBXBuildFile; fileRef = D97539851BD2997800C6F4B8 /* YYAnimatedImageView.m */; settings = {ASSET_TAGS = (); }; }; - D97539A91BD2997800C6F4B8 /* YYFrameImage.h in Headers */ = {isa = PBXBuildFile; fileRef = D97539861BD2997800C6F4B8 /* YYFrameImage.h */; settings = {ATTRIBUTES = (Public, ); }; }; - D97539AA1BD2997800C6F4B8 /* YYFrameImage.m in Sources */ = {isa = PBXBuildFile; fileRef = D97539871BD2997800C6F4B8 /* YYFrameImage.m */; settings = {ASSET_TAGS = (); }; }; - D97539AB1BD2997800C6F4B8 /* YYImage.h in Headers */ = {isa = PBXBuildFile; fileRef = D97539881BD2997800C6F4B8 /* YYImage.h */; settings = {ATTRIBUTES = (Public, ); }; }; - D97539AC1BD2997800C6F4B8 /* YYImage.m in Sources */ = {isa = PBXBuildFile; fileRef = D97539891BD2997800C6F4B8 /* YYImage.m */; settings = {ASSET_TAGS = (); }; }; - D97539AD1BD2997800C6F4B8 /* YYImageCoder.h in Headers */ = {isa = PBXBuildFile; fileRef = D975398A1BD2997800C6F4B8 /* YYImageCoder.h */; settings = {ATTRIBUTES = (Public, ); }; }; - D97539AE1BD2997800C6F4B8 /* YYImageCoder.m in Sources */ = {isa = PBXBuildFile; fileRef = D975398B1BD2997800C6F4B8 /* YYImageCoder.m */; settings = {ASSET_TAGS = (); }; }; - D97539AF1BD2997800C6F4B8 /* YYSpriteSheetImage.h in Headers */ = {isa = PBXBuildFile; fileRef = D975398C1BD2997800C6F4B8 /* YYSpriteSheetImage.h */; settings = {ATTRIBUTES = (Public, ); }; }; - D97539B01BD2997800C6F4B8 /* YYSpriteSheetImage.m in Sources */ = {isa = PBXBuildFile; fileRef = D975398D1BD2997800C6F4B8 /* YYSpriteSheetImage.m */; settings = {ASSET_TAGS = (); }; }; - D97539B11BD2997800C6F4B8 /* YYImageCache.h in Headers */ = {isa = PBXBuildFile; fileRef = D975398E1BD2997800C6F4B8 /* YYImageCache.h */; settings = {ATTRIBUTES = (Public, ); }; }; - D97539B21BD2997800C6F4B8 /* YYImageCache.m in Sources */ = {isa = PBXBuildFile; fileRef = D975398F1BD2997800C6F4B8 /* YYImageCache.m */; settings = {ASSET_TAGS = (); }; }; - D97539B31BD2997800C6F4B8 /* YYWebImage.h in Headers */ = {isa = PBXBuildFile; fileRef = D97539901BD2997800C6F4B8 /* YYWebImage.h */; settings = {ATTRIBUTES = (Public, ); }; }; - D97539B41BD2997800C6F4B8 /* YYWebImageManager.h in Headers */ = {isa = PBXBuildFile; fileRef = D97539911BD2997800C6F4B8 /* YYWebImageManager.h */; settings = {ATTRIBUTES = (Public, ); }; }; - D97539B51BD2997800C6F4B8 /* YYWebImageManager.m in Sources */ = {isa = PBXBuildFile; fileRef = D97539921BD2997800C6F4B8 /* YYWebImageManager.m */; settings = {ASSET_TAGS = (); }; }; - D97539B61BD2997800C6F4B8 /* YYWebImageOperation.h in Headers */ = {isa = PBXBuildFile; fileRef = D97539931BD2997800C6F4B8 /* YYWebImageOperation.h */; settings = {ATTRIBUTES = (Public, ); }; }; - D97539B71BD2997800C6F4B8 /* YYWebImageOperation.m in Sources */ = {isa = PBXBuildFile; fileRef = D97539941BD2997800C6F4B8 /* YYWebImageOperation.m */; settings = {ASSET_TAGS = (); }; }; - D97539BA1BD2A92300C6F4B8 /* libsqlite3.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = D97539B91BD2A92300C6F4B8 /* libsqlite3.tbd */; }; - D97539BD1BD2AC3E00C6F4B8 /* UIImage+YYWebImage.h in Headers */ = {isa = PBXBuildFile; fileRef = D97539BB1BD2AC3E00C6F4B8 /* UIImage+YYWebImage.h */; settings = {ATTRIBUTES = (Public, ); }; }; - D97539BE1BD2AC3E00C6F4B8 /* UIImage+YYWebImage.m in Sources */ = {isa = PBXBuildFile; fileRef = D97539BC1BD2AC3E00C6F4B8 /* UIImage+YYWebImage.m */; settings = {ASSET_TAGS = (); }; }; - D97539C41BD2D17F00C6F4B8 /* libz.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = D97539C31BD2D17F00C6F4B8 /* libz.tbd */; }; - D97539C61BD35C3A00C6F4B8 /* MobileCoreServices.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D97539C51BD35C3A00C6F4B8 /* MobileCoreServices.framework */; }; - D97539C81BD35C3F00C6F4B8 /* AssetsLibrary.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D97539C71BD35C3F00C6F4B8 /* AssetsLibrary.framework */; }; - D97539CA1BD35C4400C6F4B8 /* Accelerate.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D97539C91BD35C4400C6F4B8 /* Accelerate.framework */; }; - D97539CC1BD35C4900C6F4B8 /* QuartzCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D97539CB1BD35C4900C6F4B8 /* QuartzCore.framework */; }; - D97539CE1BD35C4D00C6F4B8 /* ImageIO.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D97539CD1BD35C4D00C6F4B8 /* ImageIO.framework */; }; - D97539D01BD35C5200C6F4B8 /* CoreFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D97539CF1BD35C5200C6F4B8 /* CoreFoundation.framework */; }; - D97539D21BD35C5600C6F4B8 /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D97539D11BD35C5600C6F4B8 /* UIKit.framework */; }; + D98DD8CE1F36DD0800582F3B /* YYCache.h in Headers */ = {isa = PBXBuildFile; fileRef = D98DD8A71F36DD0800582F3B /* YYCache.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D98DD8CF1F36DD0800582F3B /* YYCache.m in Sources */ = {isa = PBXBuildFile; fileRef = D98DD8A81F36DD0800582F3B /* YYCache.m */; }; + D98DD8D01F36DD0800582F3B /* YYDiskCache.h in Headers */ = {isa = PBXBuildFile; fileRef = D98DD8A91F36DD0800582F3B /* YYDiskCache.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D98DD8D11F36DD0800582F3B /* YYDiskCache.m in Sources */ = {isa = PBXBuildFile; fileRef = D98DD8AA1F36DD0800582F3B /* YYDiskCache.m */; }; + D98DD8D21F36DD0800582F3B /* YYKVStorage.h in Headers */ = {isa = PBXBuildFile; fileRef = D98DD8AB1F36DD0800582F3B /* YYKVStorage.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D98DD8D31F36DD0800582F3B /* YYKVStorage.m in Sources */ = {isa = PBXBuildFile; fileRef = D98DD8AC1F36DD0800582F3B /* YYKVStorage.m */; }; + D98DD8D41F36DD0800582F3B /* YYMemoryCache.h in Headers */ = {isa = PBXBuildFile; fileRef = D98DD8AD1F36DD0800582F3B /* YYMemoryCache.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D98DD8D51F36DD0800582F3B /* YYMemoryCache.m in Sources */ = {isa = PBXBuildFile; fileRef = D98DD8AE1F36DD0800582F3B /* YYMemoryCache.m */; }; + D98DD8D61F36DD0800582F3B /* _YYWebImageSetter.h in Headers */ = {isa = PBXBuildFile; fileRef = D98DD8B01F36DD0800582F3B /* _YYWebImageSetter.h */; }; + D98DD8D71F36DD0800582F3B /* _YYWebImageSetter.m in Sources */ = {isa = PBXBuildFile; fileRef = D98DD8B11F36DD0800582F3B /* _YYWebImageSetter.m */; }; + D98DD8D81F36DD0800582F3B /* CALayer+YYWebImage.h in Headers */ = {isa = PBXBuildFile; fileRef = D98DD8B21F36DD0800582F3B /* CALayer+YYWebImage.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D98DD8D91F36DD0800582F3B /* CALayer+YYWebImage.m in Sources */ = {isa = PBXBuildFile; fileRef = D98DD8B31F36DD0800582F3B /* CALayer+YYWebImage.m */; }; + D98DD8DA1F36DD0800582F3B /* MKAnnotationView+YYWebImage.h in Headers */ = {isa = PBXBuildFile; fileRef = D98DD8B41F36DD0800582F3B /* MKAnnotationView+YYWebImage.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D98DD8DB1F36DD0800582F3B /* MKAnnotationView+YYWebImage.m in Sources */ = {isa = PBXBuildFile; fileRef = D98DD8B51F36DD0800582F3B /* MKAnnotationView+YYWebImage.m */; }; + D98DD8DC1F36DD0800582F3B /* UIButton+YYWebImage.h in Headers */ = {isa = PBXBuildFile; fileRef = D98DD8B61F36DD0800582F3B /* UIButton+YYWebImage.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D98DD8DD1F36DD0800582F3B /* UIButton+YYWebImage.m in Sources */ = {isa = PBXBuildFile; fileRef = D98DD8B71F36DD0800582F3B /* UIButton+YYWebImage.m */; }; + D98DD8DE1F36DD0800582F3B /* UIImage+YYWebImage.h in Headers */ = {isa = PBXBuildFile; fileRef = D98DD8B81F36DD0800582F3B /* UIImage+YYWebImage.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D98DD8DF1F36DD0800582F3B /* UIImage+YYWebImage.m in Sources */ = {isa = PBXBuildFile; fileRef = D98DD8B91F36DD0800582F3B /* UIImage+YYWebImage.m */; }; + D98DD8E01F36DD0800582F3B /* UIImageView+YYWebImage.h in Headers */ = {isa = PBXBuildFile; fileRef = D98DD8BA1F36DD0800582F3B /* UIImageView+YYWebImage.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D98DD8E11F36DD0800582F3B /* UIImageView+YYWebImage.m in Sources */ = {isa = PBXBuildFile; fileRef = D98DD8BB1F36DD0800582F3B /* UIImageView+YYWebImage.m */; }; + D98DD8E21F36DD0800582F3B /* YYAnimatedImageView.h in Headers */ = {isa = PBXBuildFile; fileRef = D98DD8BD1F36DD0800582F3B /* YYAnimatedImageView.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D98DD8E31F36DD0800582F3B /* YYAnimatedImageView.m in Sources */ = {isa = PBXBuildFile; fileRef = D98DD8BE1F36DD0800582F3B /* YYAnimatedImageView.m */; }; + D98DD8E41F36DD0800582F3B /* YYFrameImage.h in Headers */ = {isa = PBXBuildFile; fileRef = D98DD8BF1F36DD0800582F3B /* YYFrameImage.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D98DD8E51F36DD0800582F3B /* YYFrameImage.m in Sources */ = {isa = PBXBuildFile; fileRef = D98DD8C01F36DD0800582F3B /* YYFrameImage.m */; }; + D98DD8E61F36DD0800582F3B /* YYImage.h in Headers */ = {isa = PBXBuildFile; fileRef = D98DD8C11F36DD0800582F3B /* YYImage.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D98DD8E71F36DD0800582F3B /* YYImage.m in Sources */ = {isa = PBXBuildFile; fileRef = D98DD8C21F36DD0800582F3B /* YYImage.m */; }; + D98DD8E81F36DD0800582F3B /* YYImageCoder.h in Headers */ = {isa = PBXBuildFile; fileRef = D98DD8C31F36DD0800582F3B /* YYImageCoder.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D98DD8E91F36DD0800582F3B /* YYImageCoder.m in Sources */ = {isa = PBXBuildFile; fileRef = D98DD8C41F36DD0800582F3B /* YYImageCoder.m */; }; + D98DD8EA1F36DD0800582F3B /* YYSpriteSheetImage.h in Headers */ = {isa = PBXBuildFile; fileRef = D98DD8C51F36DD0800582F3B /* YYSpriteSheetImage.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D98DD8EB1F36DD0800582F3B /* YYSpriteSheetImage.m in Sources */ = {isa = PBXBuildFile; fileRef = D98DD8C61F36DD0800582F3B /* YYSpriteSheetImage.m */; }; + D98DD8EC1F36DD0800582F3B /* YYImageCache.h in Headers */ = {isa = PBXBuildFile; fileRef = D98DD8C71F36DD0800582F3B /* YYImageCache.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D98DD8ED1F36DD0800582F3B /* YYImageCache.m in Sources */ = {isa = PBXBuildFile; fileRef = D98DD8C81F36DD0800582F3B /* YYImageCache.m */; }; + D98DD8EE1F36DD0800582F3B /* YYWebImage.h in Headers */ = {isa = PBXBuildFile; fileRef = D98DD8C91F36DD0800582F3B /* YYWebImage.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D98DD8EF1F36DD0800582F3B /* YYWebImageManager.h in Headers */ = {isa = PBXBuildFile; fileRef = D98DD8CA1F36DD0800582F3B /* YYWebImageManager.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D98DD8F01F36DD0800582F3B /* YYWebImageManager.m in Sources */ = {isa = PBXBuildFile; fileRef = D98DD8CB1F36DD0800582F3B /* YYWebImageManager.m */; }; + D98DD8F11F36DD0800582F3B /* YYWebImageOperation.h in Headers */ = {isa = PBXBuildFile; fileRef = D98DD8CC1F36DD0800582F3B /* YYWebImageOperation.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D98DD8F21F36DD0800582F3B /* YYWebImageOperation.m in Sources */ = {isa = PBXBuildFile; fileRef = D98DD8CD1F36DD0800582F3B /* YYWebImageOperation.m */; }; + D98DD8F51F36DD5E00582F3B /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D98DD8F41F36DD5E00582F3B /* UIKit.framework */; }; + D98DD8F71F36DD6600582F3B /* CoreFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D98DD8F61F36DD6600582F3B /* CoreFoundation.framework */; }; + D98DD8F91F36DD6B00582F3B /* ImageIO.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D98DD8F81F36DD6B00582F3B /* ImageIO.framework */; }; + D98DD8FB1F36DD6F00582F3B /* QuartzCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D98DD8FA1F36DD6F00582F3B /* QuartzCore.framework */; }; + D98DD8FD1F36DD7300582F3B /* Accelerate.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D98DD8FC1F36DD7300582F3B /* Accelerate.framework */; }; + D98DD8FF1F36DD7700582F3B /* AssetsLibrary.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D98DD8FE1F36DD7700582F3B /* AssetsLibrary.framework */; }; + D98DD9011F36DD7D00582F3B /* MobileCoreServices.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D98DD9001F36DD7D00582F3B /* MobileCoreServices.framework */; }; + D98DD9031F36DD8100582F3B /* libz.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = D98DD9021F36DD8100582F3B /* libz.tbd */; }; + D98DD9051F36DD8500582F3B /* libsqlite3.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = D98DD9041F36DD8500582F3B /* libsqlite3.tbd */; }; /* End PBXBuildFile section */ /* Begin PBXFileReference section */ - D97539601BD2970400C6F4B8 /* YYWebImage.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = YYWebImage.framework; sourceTree = BUILT_PRODUCTS_DIR; }; - D975396B1BD2971D00C6F4B8 /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; - D97539701BD2997800C6F4B8 /* YYCache.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = YYCache.h; sourceTree = ""; }; - D97539711BD2997800C6F4B8 /* YYCache.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = YYCache.m; sourceTree = ""; }; - D97539721BD2997800C6F4B8 /* YYDiskCache.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = YYDiskCache.h; sourceTree = ""; }; - D97539731BD2997800C6F4B8 /* YYDiskCache.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = YYDiskCache.m; sourceTree = ""; }; - D97539741BD2997800C6F4B8 /* YYKVStorage.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = YYKVStorage.h; sourceTree = ""; }; - D97539751BD2997800C6F4B8 /* YYKVStorage.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = YYKVStorage.m; sourceTree = ""; }; - D97539761BD2997800C6F4B8 /* YYMemoryCache.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = YYMemoryCache.h; sourceTree = ""; }; - D97539771BD2997800C6F4B8 /* YYMemoryCache.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = YYMemoryCache.m; sourceTree = ""; }; - D97539791BD2997800C6F4B8 /* _YYWebImageSetter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = _YYWebImageSetter.h; sourceTree = ""; }; - D975397A1BD2997800C6F4B8 /* _YYWebImageSetter.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = _YYWebImageSetter.m; sourceTree = ""; }; - D975397B1BD2997800C6F4B8 /* CALayer+YYWebImage.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "CALayer+YYWebImage.h"; sourceTree = ""; }; - D975397C1BD2997800C6F4B8 /* CALayer+YYWebImage.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "CALayer+YYWebImage.m"; sourceTree = ""; }; - D975397D1BD2997800C6F4B8 /* MKAnnotationView+YYWebImage.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "MKAnnotationView+YYWebImage.h"; sourceTree = ""; }; - D975397E1BD2997800C6F4B8 /* MKAnnotationView+YYWebImage.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "MKAnnotationView+YYWebImage.m"; sourceTree = ""; }; - D975397F1BD2997800C6F4B8 /* UIButton+YYWebImage.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "UIButton+YYWebImage.h"; sourceTree = ""; }; - D97539801BD2997800C6F4B8 /* UIButton+YYWebImage.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "UIButton+YYWebImage.m"; sourceTree = ""; }; - D97539811BD2997800C6F4B8 /* UIImageView+YYWebImage.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "UIImageView+YYWebImage.h"; sourceTree = ""; }; - D97539821BD2997800C6F4B8 /* UIImageView+YYWebImage.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "UIImageView+YYWebImage.m"; sourceTree = ""; }; - D97539841BD2997800C6F4B8 /* YYAnimatedImageView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = YYAnimatedImageView.h; sourceTree = ""; }; - D97539851BD2997800C6F4B8 /* YYAnimatedImageView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = YYAnimatedImageView.m; sourceTree = ""; }; - D97539861BD2997800C6F4B8 /* YYFrameImage.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = YYFrameImage.h; sourceTree = ""; }; - D97539871BD2997800C6F4B8 /* YYFrameImage.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = YYFrameImage.m; sourceTree = ""; }; - D97539881BD2997800C6F4B8 /* YYImage.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = YYImage.h; sourceTree = ""; }; - D97539891BD2997800C6F4B8 /* YYImage.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = YYImage.m; sourceTree = ""; }; - D975398A1BD2997800C6F4B8 /* YYImageCoder.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = YYImageCoder.h; sourceTree = ""; }; - D975398B1BD2997800C6F4B8 /* YYImageCoder.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = YYImageCoder.m; sourceTree = ""; }; - D975398C1BD2997800C6F4B8 /* YYSpriteSheetImage.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = YYSpriteSheetImage.h; sourceTree = ""; }; - D975398D1BD2997800C6F4B8 /* YYSpriteSheetImage.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = YYSpriteSheetImage.m; sourceTree = ""; }; - D975398E1BD2997800C6F4B8 /* YYImageCache.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = YYImageCache.h; sourceTree = ""; }; - D975398F1BD2997800C6F4B8 /* YYImageCache.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = YYImageCache.m; sourceTree = ""; }; - D97539901BD2997800C6F4B8 /* YYWebImage.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = YYWebImage.h; sourceTree = ""; }; - D97539911BD2997800C6F4B8 /* YYWebImageManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = YYWebImageManager.h; sourceTree = ""; }; - D97539921BD2997800C6F4B8 /* YYWebImageManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = YYWebImageManager.m; sourceTree = ""; }; - D97539931BD2997800C6F4B8 /* YYWebImageOperation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = YYWebImageOperation.h; sourceTree = ""; }; - D97539941BD2997800C6F4B8 /* YYWebImageOperation.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = YYWebImageOperation.m; sourceTree = ""; }; - D97539B91BD2A92300C6F4B8 /* libsqlite3.tbd */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = libsqlite3.tbd; path = usr/lib/libsqlite3.tbd; sourceTree = SDKROOT; }; - D97539BB1BD2AC3E00C6F4B8 /* UIImage+YYWebImage.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "UIImage+YYWebImage.h"; sourceTree = ""; }; - D97539BC1BD2AC3E00C6F4B8 /* UIImage+YYWebImage.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "UIImage+YYWebImage.m"; sourceTree = ""; }; - D97539C31BD2D17F00C6F4B8 /* libz.tbd */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = libz.tbd; path = usr/lib/libz.tbd; sourceTree = SDKROOT; }; - D97539C51BD35C3A00C6F4B8 /* MobileCoreServices.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = MobileCoreServices.framework; path = System/Library/Frameworks/MobileCoreServices.framework; sourceTree = SDKROOT; }; - D97539C71BD35C3F00C6F4B8 /* AssetsLibrary.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AssetsLibrary.framework; path = System/Library/Frameworks/AssetsLibrary.framework; sourceTree = SDKROOT; }; - D97539C91BD35C4400C6F4B8 /* Accelerate.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Accelerate.framework; path = System/Library/Frameworks/Accelerate.framework; sourceTree = SDKROOT; }; - D97539CB1BD35C4900C6F4B8 /* QuartzCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = QuartzCore.framework; path = System/Library/Frameworks/QuartzCore.framework; sourceTree = SDKROOT; }; - D97539CD1BD35C4D00C6F4B8 /* ImageIO.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = ImageIO.framework; path = System/Library/Frameworks/ImageIO.framework; sourceTree = SDKROOT; }; - D97539CF1BD35C5200C6F4B8 /* CoreFoundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreFoundation.framework; path = System/Library/Frameworks/CoreFoundation.framework; sourceTree = SDKROOT; }; - D97539D11BD35C5600C6F4B8 /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = System/Library/Frameworks/UIKit.framework; sourceTree = SDKROOT; }; + D9312D061F36DC820055FE6D /* YYWebImage.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = YYWebImage.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + D9312D0A1F36DC820055FE6D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + D98DD8A71F36DD0800582F3B /* YYCache.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = YYCache.h; sourceTree = ""; }; + D98DD8A81F36DD0800582F3B /* YYCache.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = YYCache.m; sourceTree = ""; }; + D98DD8A91F36DD0800582F3B /* YYDiskCache.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = YYDiskCache.h; sourceTree = ""; }; + D98DD8AA1F36DD0800582F3B /* YYDiskCache.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = YYDiskCache.m; sourceTree = ""; }; + D98DD8AB1F36DD0800582F3B /* YYKVStorage.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = YYKVStorage.h; sourceTree = ""; }; + D98DD8AC1F36DD0800582F3B /* YYKVStorage.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = YYKVStorage.m; sourceTree = ""; }; + D98DD8AD1F36DD0800582F3B /* YYMemoryCache.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = YYMemoryCache.h; sourceTree = ""; }; + D98DD8AE1F36DD0800582F3B /* YYMemoryCache.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = YYMemoryCache.m; sourceTree = ""; }; + D98DD8B01F36DD0800582F3B /* _YYWebImageSetter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = _YYWebImageSetter.h; sourceTree = ""; }; + D98DD8B11F36DD0800582F3B /* _YYWebImageSetter.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = _YYWebImageSetter.m; sourceTree = ""; }; + D98DD8B21F36DD0800582F3B /* CALayer+YYWebImage.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "CALayer+YYWebImage.h"; sourceTree = ""; }; + D98DD8B31F36DD0800582F3B /* CALayer+YYWebImage.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "CALayer+YYWebImage.m"; sourceTree = ""; }; + D98DD8B41F36DD0800582F3B /* MKAnnotationView+YYWebImage.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "MKAnnotationView+YYWebImage.h"; sourceTree = ""; }; + D98DD8B51F36DD0800582F3B /* MKAnnotationView+YYWebImage.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "MKAnnotationView+YYWebImage.m"; sourceTree = ""; }; + D98DD8B61F36DD0800582F3B /* UIButton+YYWebImage.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "UIButton+YYWebImage.h"; sourceTree = ""; }; + D98DD8B71F36DD0800582F3B /* UIButton+YYWebImage.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "UIButton+YYWebImage.m"; sourceTree = ""; }; + D98DD8B81F36DD0800582F3B /* UIImage+YYWebImage.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "UIImage+YYWebImage.h"; sourceTree = ""; }; + D98DD8B91F36DD0800582F3B /* UIImage+YYWebImage.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "UIImage+YYWebImage.m"; sourceTree = ""; }; + D98DD8BA1F36DD0800582F3B /* UIImageView+YYWebImage.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "UIImageView+YYWebImage.h"; sourceTree = ""; }; + D98DD8BB1F36DD0800582F3B /* UIImageView+YYWebImage.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "UIImageView+YYWebImage.m"; sourceTree = ""; }; + D98DD8BD1F36DD0800582F3B /* YYAnimatedImageView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = YYAnimatedImageView.h; sourceTree = ""; }; + D98DD8BE1F36DD0800582F3B /* YYAnimatedImageView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = YYAnimatedImageView.m; sourceTree = ""; }; + D98DD8BF1F36DD0800582F3B /* YYFrameImage.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = YYFrameImage.h; sourceTree = ""; }; + D98DD8C01F36DD0800582F3B /* YYFrameImage.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = YYFrameImage.m; sourceTree = ""; }; + D98DD8C11F36DD0800582F3B /* YYImage.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = YYImage.h; sourceTree = ""; }; + D98DD8C21F36DD0800582F3B /* YYImage.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = YYImage.m; sourceTree = ""; }; + D98DD8C31F36DD0800582F3B /* YYImageCoder.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = YYImageCoder.h; sourceTree = ""; }; + D98DD8C41F36DD0800582F3B /* YYImageCoder.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = YYImageCoder.m; sourceTree = ""; }; + D98DD8C51F36DD0800582F3B /* YYSpriteSheetImage.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = YYSpriteSheetImage.h; sourceTree = ""; }; + D98DD8C61F36DD0800582F3B /* YYSpriteSheetImage.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = YYSpriteSheetImage.m; sourceTree = ""; }; + D98DD8C71F36DD0800582F3B /* YYImageCache.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = YYImageCache.h; sourceTree = ""; }; + D98DD8C81F36DD0800582F3B /* YYImageCache.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = YYImageCache.m; sourceTree = ""; }; + D98DD8C91F36DD0800582F3B /* YYWebImage.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = YYWebImage.h; sourceTree = ""; }; + D98DD8CA1F36DD0800582F3B /* YYWebImageManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = YYWebImageManager.h; sourceTree = ""; }; + D98DD8CB1F36DD0800582F3B /* YYWebImageManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = YYWebImageManager.m; sourceTree = ""; }; + D98DD8CC1F36DD0800582F3B /* YYWebImageOperation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = YYWebImageOperation.h; sourceTree = ""; }; + D98DD8CD1F36DD0800582F3B /* YYWebImageOperation.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = YYWebImageOperation.m; sourceTree = ""; }; + D98DD8F41F36DD5E00582F3B /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = System/Library/Frameworks/UIKit.framework; sourceTree = SDKROOT; }; + D98DD8F61F36DD6600582F3B /* CoreFoundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreFoundation.framework; path = System/Library/Frameworks/CoreFoundation.framework; sourceTree = SDKROOT; }; + D98DD8F81F36DD6B00582F3B /* ImageIO.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = ImageIO.framework; path = System/Library/Frameworks/ImageIO.framework; sourceTree = SDKROOT; }; + D98DD8FA1F36DD6F00582F3B /* QuartzCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = QuartzCore.framework; path = System/Library/Frameworks/QuartzCore.framework; sourceTree = SDKROOT; }; + D98DD8FC1F36DD7300582F3B /* Accelerate.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Accelerate.framework; path = System/Library/Frameworks/Accelerate.framework; sourceTree = SDKROOT; }; + D98DD8FE1F36DD7700582F3B /* AssetsLibrary.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AssetsLibrary.framework; path = System/Library/Frameworks/AssetsLibrary.framework; sourceTree = SDKROOT; }; + D98DD9001F36DD7D00582F3B /* MobileCoreServices.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = MobileCoreServices.framework; path = System/Library/Frameworks/MobileCoreServices.framework; sourceTree = SDKROOT; }; + D98DD9021F36DD8100582F3B /* libz.tbd */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = libz.tbd; path = usr/lib/libz.tbd; sourceTree = SDKROOT; }; + D98DD9041F36DD8500582F3B /* libsqlite3.tbd */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = libsqlite3.tbd; path = usr/lib/libsqlite3.tbd; sourceTree = SDKROOT; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ - D975395C1BD2970400C6F4B8 /* Frameworks */ = { + D9312D021F36DC810055FE6D /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( - D97539D21BD35C5600C6F4B8 /* UIKit.framework in Frameworks */, - D97539D01BD35C5200C6F4B8 /* CoreFoundation.framework in Frameworks */, - D97539CE1BD35C4D00C6F4B8 /* ImageIO.framework in Frameworks */, - D97539CC1BD35C4900C6F4B8 /* QuartzCore.framework in Frameworks */, - D97539CA1BD35C4400C6F4B8 /* Accelerate.framework in Frameworks */, - D97539C81BD35C3F00C6F4B8 /* AssetsLibrary.framework in Frameworks */, - D97539C61BD35C3A00C6F4B8 /* MobileCoreServices.framework in Frameworks */, - D97539C41BD2D17F00C6F4B8 /* libz.tbd in Frameworks */, - D97539BA1BD2A92300C6F4B8 /* libsqlite3.tbd in Frameworks */, + D98DD9051F36DD8500582F3B /* libsqlite3.tbd in Frameworks */, + D98DD9031F36DD8100582F3B /* libz.tbd in Frameworks */, + D98DD9011F36DD7D00582F3B /* MobileCoreServices.framework in Frameworks */, + D98DD8FF1F36DD7700582F3B /* AssetsLibrary.framework in Frameworks */, + D98DD8FD1F36DD7300582F3B /* Accelerate.framework in Frameworks */, + D98DD8FB1F36DD6F00582F3B /* QuartzCore.framework in Frameworks */, + D98DD8F91F36DD6B00582F3B /* ImageIO.framework in Frameworks */, + D98DD8F71F36DD6600582F3B /* CoreFoundation.framework in Frameworks */, + D98DD8F51F36DD5E00582F3B /* UIKit.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ - D97539561BD2970400C6F4B8 = { + D9312CFC1F36DC810055FE6D = { isa = PBXGroup; children = ( - D975396E1BD2997800C6F4B8 /* YYWebImage */, - D975396D1BD2996900C6F4B8 /* Supporting Files */, - D97539611BD2970400C6F4B8 /* Products */, + D98DD8A51F36DD0800582F3B /* YYWebImage */, + D98DD8F31F36DD5E00582F3B /* Frameworks */, + D9312D071F36DC820055FE6D /* Products */, ); sourceTree = ""; }; - D97539611BD2970400C6F4B8 /* Products */ = { + D9312D071F36DC820055FE6D /* Products */ = { isa = PBXGroup; children = ( - D97539601BD2970400C6F4B8 /* YYWebImage.framework */, + D9312D061F36DC820055FE6D /* YYWebImage.framework */, ); name = Products; sourceTree = ""; }; - D975396D1BD2996900C6F4B8 /* Supporting Files */ = { + D98DD8A51F36DD0800582F3B /* YYWebImage */ = { isa = PBXGroup; children = ( - D97539D11BD35C5600C6F4B8 /* UIKit.framework */, - D97539CF1BD35C5200C6F4B8 /* CoreFoundation.framework */, - D97539CD1BD35C4D00C6F4B8 /* ImageIO.framework */, - D97539CB1BD35C4900C6F4B8 /* QuartzCore.framework */, - D97539C91BD35C4400C6F4B8 /* Accelerate.framework */, - D97539C71BD35C3F00C6F4B8 /* AssetsLibrary.framework */, - D97539C51BD35C3A00C6F4B8 /* MobileCoreServices.framework */, - D97539C31BD2D17F00C6F4B8 /* libz.tbd */, - D97539B91BD2A92300C6F4B8 /* libsqlite3.tbd */, - D975396B1BD2971D00C6F4B8 /* Info.plist */, - ); - name = "Supporting Files"; - sourceTree = ""; - }; - D975396E1BD2997800C6F4B8 /* YYWebImage */ = { - isa = PBXGroup; - children = ( - D97539901BD2997800C6F4B8 /* YYWebImage.h */, - D975398E1BD2997800C6F4B8 /* YYImageCache.h */, - D975398F1BD2997800C6F4B8 /* YYImageCache.m */, - D97539931BD2997800C6F4B8 /* YYWebImageOperation.h */, - D97539941BD2997800C6F4B8 /* YYWebImageOperation.m */, - D97539911BD2997800C6F4B8 /* YYWebImageManager.h */, - D97539921BD2997800C6F4B8 /* YYWebImageManager.m */, - D97539831BD2997800C6F4B8 /* Image */, - D975396F1BD2997800C6F4B8 /* Cache */, - D97539781BD2997800C6F4B8 /* Categories */, + D98DD8C91F36DD0800582F3B /* YYWebImage.h */, + D98DD8C71F36DD0800582F3B /* YYImageCache.h */, + D98DD8C81F36DD0800582F3B /* YYImageCache.m */, + D98DD8CA1F36DD0800582F3B /* YYWebImageManager.h */, + D98DD8CB1F36DD0800582F3B /* YYWebImageManager.m */, + D98DD8CC1F36DD0800582F3B /* YYWebImageOperation.h */, + D98DD8CD1F36DD0800582F3B /* YYWebImageOperation.m */, + D98DD8A61F36DD0800582F3B /* Cache */, + D98DD8BC1F36DD0800582F3B /* Image */, + D98DD8AF1F36DD0800582F3B /* Categories */, ); name = YYWebImage; path = ../YYWebImage; sourceTree = ""; }; - D975396F1BD2997800C6F4B8 /* Cache */ = { + D98DD8A61F36DD0800582F3B /* Cache */ = { isa = PBXGroup; children = ( - D97539701BD2997800C6F4B8 /* YYCache.h */, - D97539711BD2997800C6F4B8 /* YYCache.m */, - D97539761BD2997800C6F4B8 /* YYMemoryCache.h */, - D97539771BD2997800C6F4B8 /* YYMemoryCache.m */, - D97539721BD2997800C6F4B8 /* YYDiskCache.h */, - D97539731BD2997800C6F4B8 /* YYDiskCache.m */, - D97539741BD2997800C6F4B8 /* YYKVStorage.h */, - D97539751BD2997800C6F4B8 /* YYKVStorage.m */, + D98DD8A71F36DD0800582F3B /* YYCache.h */, + D98DD8A81F36DD0800582F3B /* YYCache.m */, + D98DD8A91F36DD0800582F3B /* YYDiskCache.h */, + D98DD8AA1F36DD0800582F3B /* YYDiskCache.m */, + D98DD8AD1F36DD0800582F3B /* YYMemoryCache.h */, + D98DD8AE1F36DD0800582F3B /* YYMemoryCache.m */, + D98DD8AB1F36DD0800582F3B /* YYKVStorage.h */, + D98DD8AC1F36DD0800582F3B /* YYKVStorage.m */, ); path = Cache; sourceTree = ""; }; - D97539781BD2997800C6F4B8 /* Categories */ = { + D98DD8AF1F36DD0800582F3B /* Categories */ = { isa = PBXGroup; children = ( - D97539BB1BD2AC3E00C6F4B8 /* UIImage+YYWebImage.h */, - D97539BC1BD2AC3E00C6F4B8 /* UIImage+YYWebImage.m */, - D97539811BD2997800C6F4B8 /* UIImageView+YYWebImage.h */, - D97539821BD2997800C6F4B8 /* UIImageView+YYWebImage.m */, - D975397F1BD2997800C6F4B8 /* UIButton+YYWebImage.h */, - D97539801BD2997800C6F4B8 /* UIButton+YYWebImage.m */, - D975397B1BD2997800C6F4B8 /* CALayer+YYWebImage.h */, - D975397C1BD2997800C6F4B8 /* CALayer+YYWebImage.m */, - D975397D1BD2997800C6F4B8 /* MKAnnotationView+YYWebImage.h */, - D975397E1BD2997800C6F4B8 /* MKAnnotationView+YYWebImage.m */, - D97539791BD2997800C6F4B8 /* _YYWebImageSetter.h */, - D975397A1BD2997800C6F4B8 /* _YYWebImageSetter.m */, + D98DD8B01F36DD0800582F3B /* _YYWebImageSetter.h */, + D98DD8B11F36DD0800582F3B /* _YYWebImageSetter.m */, + D98DD8B21F36DD0800582F3B /* CALayer+YYWebImage.h */, + D98DD8B31F36DD0800582F3B /* CALayer+YYWebImage.m */, + D98DD8B41F36DD0800582F3B /* MKAnnotationView+YYWebImage.h */, + D98DD8B51F36DD0800582F3B /* MKAnnotationView+YYWebImage.m */, + D98DD8B61F36DD0800582F3B /* UIButton+YYWebImage.h */, + D98DD8B71F36DD0800582F3B /* UIButton+YYWebImage.m */, + D98DD8B81F36DD0800582F3B /* UIImage+YYWebImage.h */, + D98DD8B91F36DD0800582F3B /* UIImage+YYWebImage.m */, + D98DD8BA1F36DD0800582F3B /* UIImageView+YYWebImage.h */, + D98DD8BB1F36DD0800582F3B /* UIImageView+YYWebImage.m */, ); path = Categories; sourceTree = ""; }; - D97539831BD2997800C6F4B8 /* Image */ = { + D98DD8BC1F36DD0800582F3B /* Image */ = { isa = PBXGroup; children = ( - D97539881BD2997800C6F4B8 /* YYImage.h */, - D97539891BD2997800C6F4B8 /* YYImage.m */, - D97539861BD2997800C6F4B8 /* YYFrameImage.h */, - D97539871BD2997800C6F4B8 /* YYFrameImage.m */, - D975398C1BD2997800C6F4B8 /* YYSpriteSheetImage.h */, - D975398D1BD2997800C6F4B8 /* YYSpriteSheetImage.m */, - D975398A1BD2997800C6F4B8 /* YYImageCoder.h */, - D975398B1BD2997800C6F4B8 /* YYImageCoder.m */, - D97539841BD2997800C6F4B8 /* YYAnimatedImageView.h */, - D97539851BD2997800C6F4B8 /* YYAnimatedImageView.m */, + D98DD8C11F36DD0800582F3B /* YYImage.h */, + D98DD8C21F36DD0800582F3B /* YYImage.m */, + D98DD8BD1F36DD0800582F3B /* YYAnimatedImageView.h */, + D98DD8BE1F36DD0800582F3B /* YYAnimatedImageView.m */, + D98DD8BF1F36DD0800582F3B /* YYFrameImage.h */, + D98DD8C01F36DD0800582F3B /* YYFrameImage.m */, + D98DD8C31F36DD0800582F3B /* YYImageCoder.h */, + D98DD8C41F36DD0800582F3B /* YYImageCoder.m */, + D98DD8C51F36DD0800582F3B /* YYSpriteSheetImage.h */, + D98DD8C61F36DD0800582F3B /* YYSpriteSheetImage.m */, ); path = Image; sourceTree = ""; }; + D98DD8F31F36DD5E00582F3B /* Frameworks */ = { + isa = PBXGroup; + children = ( + D9312D0A1F36DC820055FE6D /* Info.plist */, + D98DD9041F36DD8500582F3B /* libsqlite3.tbd */, + D98DD9021F36DD8100582F3B /* libz.tbd */, + D98DD9001F36DD7D00582F3B /* MobileCoreServices.framework */, + D98DD8FE1F36DD7700582F3B /* AssetsLibrary.framework */, + D98DD8FC1F36DD7300582F3B /* Accelerate.framework */, + D98DD8FA1F36DD6F00582F3B /* QuartzCore.framework */, + D98DD8F81F36DD6B00582F3B /* ImageIO.framework */, + D98DD8F61F36DD6600582F3B /* CoreFoundation.framework */, + D98DD8F41F36DD5E00582F3B /* UIKit.framework */, + ); + name = Frameworks; + sourceTree = ""; + }; /* End PBXGroup section */ /* Begin PBXHeadersBuildPhase section */ - D975395D1BD2970400C6F4B8 /* Headers */ = { + D9312D031F36DC810055FE6D /* Headers */ = { isa = PBXHeadersBuildPhase; buildActionMask = 2147483647; files = ( - D97539BD1BD2AC3E00C6F4B8 /* UIImage+YYWebImage.h in Headers */, - D97539A91BD2997800C6F4B8 /* YYFrameImage.h in Headers */, - D975399B1BD2997800C6F4B8 /* YYMemoryCache.h in Headers */, - D97539B41BD2997800C6F4B8 /* YYWebImageManager.h in Headers */, - D975399F1BD2997800C6F4B8 /* CALayer+YYWebImage.h in Headers */, - D97539991BD2997800C6F4B8 /* YYKVStorage.h in Headers */, - D97539A51BD2997800C6F4B8 /* UIImageView+YYWebImage.h in Headers */, - D97539B31BD2997800C6F4B8 /* YYWebImage.h in Headers */, - D97539B61BD2997800C6F4B8 /* YYWebImageOperation.h in Headers */, - D97539A71BD2997800C6F4B8 /* YYAnimatedImageView.h in Headers */, - D97539AD1BD2997800C6F4B8 /* YYImageCoder.h in Headers */, - D97539A31BD2997800C6F4B8 /* UIButton+YYWebImage.h in Headers */, - D97539A11BD2997800C6F4B8 /* MKAnnotationView+YYWebImage.h in Headers */, - D97539AB1BD2997800C6F4B8 /* YYImage.h in Headers */, - D97539971BD2997800C6F4B8 /* YYDiskCache.h in Headers */, - D97539AF1BD2997800C6F4B8 /* YYSpriteSheetImage.h in Headers */, - D97539951BD2997800C6F4B8 /* YYCache.h in Headers */, - D97539B11BD2997800C6F4B8 /* YYImageCache.h in Headers */, - D975399D1BD2997800C6F4B8 /* _YYWebImageSetter.h in Headers */, + D98DD8E21F36DD0800582F3B /* YYAnimatedImageView.h in Headers */, + D98DD8D41F36DD0800582F3B /* YYMemoryCache.h in Headers */, + D98DD8D81F36DD0800582F3B /* CALayer+YYWebImage.h in Headers */, + D98DD8D21F36DD0800582F3B /* YYKVStorage.h in Headers */, + D98DD8DC1F36DD0800582F3B /* UIButton+YYWebImage.h in Headers */, + D98DD8E01F36DD0800582F3B /* UIImageView+YYWebImage.h in Headers */, + D98DD8DA1F36DD0800582F3B /* MKAnnotationView+YYWebImage.h in Headers */, + D98DD8D01F36DD0800582F3B /* YYDiskCache.h in Headers */, + D98DD8E81F36DD0800582F3B /* YYImageCoder.h in Headers */, + D98DD8E41F36DD0800582F3B /* YYFrameImage.h in Headers */, + D98DD8DE1F36DD0800582F3B /* UIImage+YYWebImage.h in Headers */, + D98DD8CE1F36DD0800582F3B /* YYCache.h in Headers */, + D98DD8F11F36DD0800582F3B /* YYWebImageOperation.h in Headers */, + D98DD8EC1F36DD0800582F3B /* YYImageCache.h in Headers */, + D98DD8EE1F36DD0800582F3B /* YYWebImage.h in Headers */, + D98DD8EF1F36DD0800582F3B /* YYWebImageManager.h in Headers */, + D98DD8E61F36DD0800582F3B /* YYImage.h in Headers */, + D98DD8EA1F36DD0800582F3B /* YYSpriteSheetImage.h in Headers */, + D98DD8D61F36DD0800582F3B /* _YYWebImageSetter.h in Headers */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXHeadersBuildPhase section */ /* Begin PBXNativeTarget section */ - D975395F1BD2970400C6F4B8 /* YYWebImage */ = { + D9312D051F36DC810055FE6D /* YYWebImage */ = { isa = PBXNativeTarget; - buildConfigurationList = D97539681BD2970400C6F4B8 /* Build configuration list for PBXNativeTarget "YYWebImage" */; + buildConfigurationList = D9312D0E1F36DC820055FE6D /* Build configuration list for PBXNativeTarget "YYWebImage" */; buildPhases = ( - D975395B1BD2970400C6F4B8 /* Sources */, - D975395C1BD2970400C6F4B8 /* Frameworks */, - D975395D1BD2970400C6F4B8 /* Headers */, - D975395E1BD2970400C6F4B8 /* Resources */, + D9312D011F36DC810055FE6D /* Sources */, + D9312D021F36DC810055FE6D /* Frameworks */, + D9312D031F36DC810055FE6D /* Headers */, + D9312D041F36DC810055FE6D /* Resources */, ); buildRules = ( ); @@ -276,42 +276,42 @@ ); name = YYWebImage; productName = YYWebImage; - productReference = D97539601BD2970400C6F4B8 /* YYWebImage.framework */; + productReference = D9312D061F36DC820055FE6D /* YYWebImage.framework */; productType = "com.apple.product-type.framework"; }; /* End PBXNativeTarget section */ /* Begin PBXProject section */ - D97539571BD2970400C6F4B8 /* Project object */ = { + D9312CFD1F36DC810055FE6D /* Project object */ = { isa = PBXProject; attributes = { - LastUpgradeCheck = 0700; + LastUpgradeCheck = 0900; ORGANIZATIONNAME = ibireme; TargetAttributes = { - D975395F1BD2970400C6F4B8 = { - CreatedOnToolsVersion = 7.0.1; + D9312D051F36DC810055FE6D = { + CreatedOnToolsVersion = 9.0; }; }; }; - buildConfigurationList = D975395A1BD2970400C6F4B8 /* Build configuration list for PBXProject "YYWebImage" */; - compatibilityVersion = "Xcode 3.2"; - developmentRegion = English; + buildConfigurationList = D9312D001F36DC810055FE6D /* Build configuration list for PBXProject "YYWebImage" */; + compatibilityVersion = "Xcode 8.0"; + developmentRegion = en; hasScannedForEncodings = 0; knownRegions = ( en, ); - mainGroup = D97539561BD2970400C6F4B8; - productRefGroup = D97539611BD2970400C6F4B8 /* Products */; + mainGroup = D9312CFC1F36DC810055FE6D; + productRefGroup = D9312D071F36DC820055FE6D /* Products */; projectDirPath = ""; projectRoot = ""; targets = ( - D975395F1BD2970400C6F4B8 /* YYWebImage */, + D9312D051F36DC810055FE6D /* YYWebImage */, ); }; /* End PBXProject section */ /* Begin PBXResourcesBuildPhase section */ - D975395E1BD2970400C6F4B8 /* Resources */ = { + D9312D041F36DC810055FE6D /* Resources */ = { isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( @@ -321,58 +321,68 @@ /* End PBXResourcesBuildPhase section */ /* Begin PBXSourcesBuildPhase section */ - D975395B1BD2970400C6F4B8 /* Sources */ = { + D9312D011F36DC810055FE6D /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - D97539A41BD2997800C6F4B8 /* UIButton+YYWebImage.m in Sources */, - D97539BE1BD2AC3E00C6F4B8 /* UIImage+YYWebImage.m in Sources */, - D97539A21BD2997800C6F4B8 /* MKAnnotationView+YYWebImage.m in Sources */, - D975399A1BD2997800C6F4B8 /* YYKVStorage.m in Sources */, - D975399C1BD2997800C6F4B8 /* YYMemoryCache.m in Sources */, - D97539A61BD2997800C6F4B8 /* UIImageView+YYWebImage.m in Sources */, - D97539AE1BD2997800C6F4B8 /* YYImageCoder.m in Sources */, - D97539AC1BD2997800C6F4B8 /* YYImage.m in Sources */, - D97539A01BD2997800C6F4B8 /* CALayer+YYWebImage.m in Sources */, - D97539B01BD2997800C6F4B8 /* YYSpriteSheetImage.m in Sources */, - D97539B21BD2997800C6F4B8 /* YYImageCache.m in Sources */, - D97539B71BD2997800C6F4B8 /* YYWebImageOperation.m in Sources */, - D97539961BD2997800C6F4B8 /* YYCache.m in Sources */, - D97539981BD2997800C6F4B8 /* YYDiskCache.m in Sources */, - D97539B51BD2997800C6F4B8 /* YYWebImageManager.m in Sources */, - D97539AA1BD2997800C6F4B8 /* YYFrameImage.m in Sources */, - D975399E1BD2997800C6F4B8 /* _YYWebImageSetter.m in Sources */, - D97539A81BD2997800C6F4B8 /* YYAnimatedImageView.m in Sources */, + D98DD8DD1F36DD0800582F3B /* UIButton+YYWebImage.m in Sources */, + D98DD8DB1F36DD0800582F3B /* MKAnnotationView+YYWebImage.m in Sources */, + D98DD8ED1F36DD0800582F3B /* YYImageCache.m in Sources */, + D98DD8D31F36DD0800582F3B /* YYKVStorage.m in Sources */, + D98DD8E71F36DD0800582F3B /* YYImage.m in Sources */, + D98DD8D51F36DD0800582F3B /* YYMemoryCache.m in Sources */, + D98DD8E91F36DD0800582F3B /* YYImageCoder.m in Sources */, + D98DD8E31F36DD0800582F3B /* YYAnimatedImageView.m in Sources */, + D98DD8DF1F36DD0800582F3B /* UIImage+YYWebImage.m in Sources */, + D98DD8D91F36DD0800582F3B /* CALayer+YYWebImage.m in Sources */, + D98DD8EB1F36DD0800582F3B /* YYSpriteSheetImage.m in Sources */, + D98DD8CF1F36DD0800582F3B /* YYCache.m in Sources */, + D98DD8D11F36DD0800582F3B /* YYDiskCache.m in Sources */, + D98DD8F01F36DD0800582F3B /* YYWebImageManager.m in Sources */, + D98DD8E51F36DD0800582F3B /* YYFrameImage.m in Sources */, + D98DD8D71F36DD0800582F3B /* _YYWebImageSetter.m in Sources */, + D98DD8F21F36DD0800582F3B /* YYWebImageOperation.m in Sources */, + D98DD8E11F36DD0800582F3B /* UIImageView+YYWebImage.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXSourcesBuildPhase section */ /* Begin XCBuildConfiguration section */ - D97539661BD2970400C6F4B8 /* Debug */ = { + D9312D0C1F36DC820055FE6D /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; CLANG_WARN_INT_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + CODE_SIGN_IDENTITY = "iPhone Developer"; COPY_PHASE_STRIP = NO; CURRENT_PROJECT_VERSION = 1; DEBUG_INFORMATION_FORMAT = dwarf; ENABLE_STRICT_OBJC_MSGSEND = YES; ENABLE_TESTABILITY = YES; - GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_C_LANGUAGE_STANDARD = gnu11; GCC_DYNAMIC_NO_PIC = NO; GCC_NO_COMMON_BLOCKS = YES; GCC_OPTIMIZATION_LEVEL = 0; @@ -386,40 +396,49 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 9.0; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; MTL_ENABLE_DEBUG_INFO = YES; ONLY_ACTIVE_ARCH = YES; SDKROOT = iphoneos; - TARGETED_DEVICE_FAMILY = "1,2"; VERSIONING_SYSTEM = "apple-generic"; VERSION_INFO_PREFIX = ""; }; name = Debug; }; - D97539671BD2970400C6F4B8 /* Release */ = { + D9312D0D1F36DC820055FE6D /* Release */ = { isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; CLANG_WARN_INT_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + CODE_SIGN_IDENTITY = "iPhone Developer"; COPY_PHASE_STRIP = NO; CURRENT_PROJECT_VERSION = 1; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; ENABLE_NS_ASSERTIONS = NO; ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_C_LANGUAGE_STANDARD = gnu11; GCC_NO_COMMON_BLOCKS = YES; GCC_WARN_64_TO_32_BIT_CONVERSION = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; @@ -427,72 +446,75 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 9.0; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = iphoneos; - TARGETED_DEVICE_FAMILY = "1,2"; VALIDATE_PRODUCT = YES; VERSIONING_SYSTEM = "apple-generic"; VERSION_INFO_PREFIX = ""; }; name = Release; }; - D97539691BD2970400C6F4B8 /* Debug */ = { + D9312D0F1F36DC820055FE6D /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { + APPLICATION_EXTENSION_API_ONLY = YES; + CODE_SIGN_IDENTITY = ""; DEFINES_MODULE = YES; DYLIB_COMPATIBILITY_VERSION = 1; DYLIB_CURRENT_VERSION = 1; DYLIB_INSTALL_NAME_BASE = "@rpath"; - INFOPLIST_FILE = Info.plist; + INFOPLIST_FILE = "$(SRCROOT)/Info.plist"; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; - IPHONEOS_DEPLOYMENT_TARGET = 8.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = com.ibireme.YYWebImage; - PRODUCT_NAME = "$(TARGET_NAME)"; + PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; SKIP_INSTALL = YES; + TARGETED_DEVICE_FAMILY = "1,2"; }; name = Debug; }; - D975396A1BD2970400C6F4B8 /* Release */ = { + D9312D101F36DC820055FE6D /* Release */ = { isa = XCBuildConfiguration; buildSettings = { + APPLICATION_EXTENSION_API_ONLY = YES; + CODE_SIGN_IDENTITY = ""; DEFINES_MODULE = YES; DYLIB_COMPATIBILITY_VERSION = 1; DYLIB_CURRENT_VERSION = 1; DYLIB_INSTALL_NAME_BASE = "@rpath"; - INFOPLIST_FILE = Info.plist; + INFOPLIST_FILE = "$(SRCROOT)/Info.plist"; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; - IPHONEOS_DEPLOYMENT_TARGET = 8.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = com.ibireme.YYWebImage; - PRODUCT_NAME = "$(TARGET_NAME)"; + PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)"; SKIP_INSTALL = YES; + TARGETED_DEVICE_FAMILY = "1,2"; }; name = Release; }; /* End XCBuildConfiguration section */ /* Begin XCConfigurationList section */ - D975395A1BD2970400C6F4B8 /* Build configuration list for PBXProject "YYWebImage" */ = { + D9312D001F36DC810055FE6D /* Build configuration list for PBXProject "YYWebImage" */ = { isa = XCConfigurationList; buildConfigurations = ( - D97539661BD2970400C6F4B8 /* Debug */, - D97539671BD2970400C6F4B8 /* Release */, + D9312D0C1F36DC820055FE6D /* Debug */, + D9312D0D1F36DC820055FE6D /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; - D97539681BD2970400C6F4B8 /* Build configuration list for PBXNativeTarget "YYWebImage" */ = { + D9312D0E1F36DC820055FE6D /* Build configuration list for PBXNativeTarget "YYWebImage" */ = { isa = XCConfigurationList; buildConfigurations = ( - D97539691BD2970400C6F4B8 /* Debug */, - D975396A1BD2970400C6F4B8 /* Release */, + D9312D0F1F36DC820055FE6D /* Debug */, + D9312D101F36DC820055FE6D /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; /* End XCConfigurationList section */ }; - rootObject = D97539571BD2970400C6F4B8 /* Project object */; + rootObject = D9312CFD1F36DC810055FE6D /* Project object */; } diff --git a/Framework/YYWebImage.xcodeproj/xcshareddata/xcschemes/YYWebImage.xcscheme b/Framework/YYWebImage.xcodeproj/xcshareddata/xcschemes/YYWebImage.xcscheme index bdfe7aa..21094c6 100644 --- a/Framework/YYWebImage.xcodeproj/xcshareddata/xcschemes/YYWebImage.xcscheme +++ b/Framework/YYWebImage.xcodeproj/xcshareddata/xcschemes/YYWebImage.xcscheme @@ -1,6 +1,6 @@ @@ -45,7 +45,7 @@ @@ -63,7 +63,7 @@ diff --git a/README.md b/README.md index 993fd49..62a6b3f 100755 --- a/README.md +++ b/README.md @@ -1,9 +1,9 @@ -YYWebImage 中文介绍 +YYWebImage ============== [![License MIT](https://img.shields.io/badge/license-MIT-green.svg?style=flat)](https://raw.githubusercontent.com/ibireme/YYWebImage/master/LICENSE)  [![Carthage compatible](https://img.shields.io/badge/Carthage-compatible-4BC51D.svg?style=flat)](https://github.com/Carthage/Carthage)  -[![Cocoapods](http://img.shields.io/cocoapods/v/YYWebImage.svg?style=flat)](http://cocoapods.org/?q= YYWebImage)  -[![Cocoapods](http://img.shields.io/cocoapods/p/YYWebImage.svg?style=flat)](http://cocoapods.org/?q= YYWebImage)  +[![CocoaPods](http://img.shields.io/cocoapods/v/YYWebImage.svg?style=flat)](http://cocoapods.org/pods/YYWebImage)  +[![CocoaPods](http://img.shields.io/cocoapods/p/YYWebImage.svg?style=flat)](http://cocoadocs.org/docsets/YYWebImage)  [![Support](https://img.shields.io/badge/support-iOS%206%2B%20-blue.svg?style=flat)](https://www.apple.com/nl/ios/)  [![Build Status](https://travis-ci.org/ibireme/YYWebImage.svg?branch=master)](https://travis-ci.org/ibireme/YYWebImage) @@ -21,7 +21,7 @@ See these project for more information. Features ============== - Asynchronous image load from remote or local URL. -- Animated WebP, APNG, GIF support. +- Animated WebP, APNG, GIF support (dynamic buffer, lower memory usage). - Baseline/progressive/interlaced image decode support. - Image loading category for UIImageView, UIButton, MKAnnotationView and CALayer. - Image effect: blur, round corner, resize, color tint, crop, rotate and more. @@ -32,98 +32,127 @@ Features Usage ============== -###Load image from URL - - // load from remote url - imageView.yy_imageURL = [NSURL URLWithString:@"http://github.com/logo.png"]; - - // load from local url - imageView.yy_imageURL = [NSURL fileURLWithPath:@"/tmp/logo.png"]; - - -###Load animated image +### Load image from URL +```objc +// load from remote url +imageView.yy_imageURL = [NSURL URLWithString:@"http://github.com/logo.png"]; - // just replace `UIImageView` with `YYAnimatedImageView` - UIImageView *imageView = [YYAnimatedImageView new]; - imageView.yy_imageURL = [NSURL URLWithString:@"http://github.com/ani.webp"]; - - -###Load image progressively +// load from local url +imageView.yy_imageURL = [NSURL fileURLWithPath:@"/tmp/logo.png"]; +``` + +### Load animated image +```objc +// just replace `UIImageView` with `YYAnimatedImageView` +UIImageView *imageView = [YYAnimatedImageView new]; +imageView.yy_imageURL = [NSURL URLWithString:@"http://github.com/ani.webp"]; +``` + +### Load image progressively +```objc +// progressive +[imageView yy_setImageWithURL:url options:YYWebImageOptionProgressive]; - // progressive - [imageView yy_setImageWithURL:url options:YYWebImageOptionProgressive]; +// progressive with blur and fade animation (see the demo at the top of this page) +[imageView yy_setImageWithURL:url options:YYWebImageOptionProgressiveBlur | YYWebImageOptionSetImageWithFadeAnimation]; +``` + +### Load and process image +```objc +// 1. download image from remote +// 2. get download progress +// 3. resize image and add round corner +// 4. set image with a fade animation - // progressive with blur and fade animation (see the demo at the top of this page) - [imageView yy_setImageWithURL:url options:YYWebImageOptionProgressiveBlur | YYWebImageOptionSetImageWithFadeAnimation]; +[imageView yy_setImageWithURL:url + placeholder:nil + options:YYWebImageOptionSetImageWithFadeAnimation + progress:^(NSInteger receivedSize, NSInteger expectedSize) { + progress = (float)receivedSize / expectedSize; + } + transform:^UIImage *(UIImage *image, NSURL *url) { + image = [image yy_imageByResizeToSize:CGSizeMake(100, 100) contentMode:UIViewContentModeCenter]; + return [image yy_imageByRoundCornerRadius:10]; + } + completion:^(UIImage *image, NSURL *url, YYWebImageFromType from, YYWebImageStage stage, NSError *error) { + if (from == YYWebImageFromDiskCache) { + NSLog(@"load from disk cache"); + } + }]; +``` + +### Image Cache +```objc +YYImageCache *cache = [YYWebImageManager sharedManager].cache; + +// get cache capacity +cache.memoryCache.totalCost; +cache.memoryCache.totalCount; +cache.diskCache.totalCost; +cache.diskCache.totalCount; + +// clear cache +[cache.memoryCache removeAllObjects]; +[cache.diskCache removeAllObjects]; + +// clear disk cache with progress +[cache.diskCache removeAllObjectsWithProgressBlock:^(int removedCount, int totalCount) { + // progress +} endBlock:^(BOOL error) { + // end +}]; +``` - -###Load and process image - - // 1. download image from remote - // 2. get download progress - // 3. resize image and add round corner - // 4. set image with a fade animation - - [imageView yy_setImageWithURL:url - placeholder:nil - options:YYWebImageOptionSetImageWithFadeAnimation - progress:^(NSInteger receivedSize, NSInteger expectedSize) { - progress = (float)receivedSize / expectedSize; - } - transform:^UIImage *(UIImage *image, NSURL *url) { - image = [image yy_imageByResizeToSize:CGSizeMake(100, 100) contentMode:UIViewContentModeCenter]; - return [image yy_imageByRoundCornerRadius:10]; - } - completion:^(UIImage *image, NSURL *url, YYWebImageFromType from, YYWebImageStage stage, NSError *error) { - if (from == YYWebImageFromDiskCache) { - NSLog(@"load from disk cache"); - } - }]; - Installation ============== -### Cocoapods +### CocoaPods 1. Update cocoapods to the latest version. -1. Add `pod "YYWebImage"` to your Podfile. -2. Run `pod install` or `pod update`. -3. Import \ - +2. Add `pod 'YYWebImage'` to your Podfile. +3. Run `pod install` or `pod update`. +4. Import \. +5. Notice: it doesn't include WebP subspec by default, if you want to support WebP format, you may add `pod 'YYImage/WebP'` to your Podfile. You may call `YYImageWebPAvailable()` to check whether the WebP subspec is installed correctly. ### Carthage 1. Add `github "ibireme/YYWebImage"` to your Cartfile. 2. Run `carthage update --platform ios` and add the framework to your project. -3. Import \ -4. Notice: carthage framework doesn't include webp component, if you want to support webp, use cocoapods or install manually. +3. Import \. +4. Notice: carthage framework doesn't include webp component, if you want to support WebP format, use CocoaPods or install manually. You may call `YYImageWebPAvailable()` to check whether the WebP library is installed correctly. ### Manually 1. Download all the files in the YYWebImage subdirectory. 2. Add the source files to your Xcode project. 3. Link with required frameworks: - * UIKit.framework - * CoreFoundation.framework - * QuartzCore.framework - * AssetsLibrary.framework - * ImageIO.framework - * Accelerate.framework - * MobileCoreServices.framework - * libsqlite3 + * UIKit + * CoreFoundation + * QuartzCore + * AssetsLibrary + * ImageIO + * Accelerate + * MobileCoreServices + * sqlite3 * libz -4. Add `Vendor/WebP.framework`(static library) to your Xcode project if you want to support webp. -5. Import `YYWebImage.h`. +4. Import `YYWebImage.h`. +5. Notice: if you want to support WebP format, you may add `Vendor/WebP.framework`(static library) to your Xcode project. + + +Documentation +============== +Full API documentation is available on [CocoaDocs](http://cocoadocs.org/docsets/YYWebImage/).
+You can also install documentation locally using [appledoc](https://github.com/tomaz/appledoc). -About +Requirements ============== -This library supports iOS 6.0 and later. +This library requires `iOS 6.0+` and `Xcode 8.0+`. License ============== -YYImage is provided under the MIT license. See LICENSE file for details. +YYWebImage is provided under the MIT license. See LICENSE file for details.

@@ -144,7 +173,7 @@ YYWebImage 是一个异步图片加载框架 ([YYKit](https://github.com/ibireme 特性 ============== - 异步的图片加载,支持 HTTP 和本地文件。 -- 支持 WebP、APNG、GIF 动画。 +- 支持 GIF、APNG、WebP 动画(动态缓存,低内存占用)。 - 支持逐行扫描、隔行扫描、渐进式图像加载。 - UIImageView、UIButton、MKAnnotationView、CALayer 的 Category 方法支持。 - 常见图片处理:模糊、圆角、大小调整、裁切、旋转、色调等。 @@ -155,93 +184,121 @@ YYWebImage 是一个异步图片加载框架 ([YYKit](https://github.com/ibireme 用法 ============== -###从 URL 加载图片 - - // 加载网络图片 - imageView.yy_imageURL = [NSURL URLWithString:@"http://github.com/logo.png"]; +### 从 URL 加载图片 +```objc +// 加载网络图片 +imageView.yy_imageURL = [NSURL URLWithString:@"http://github.com/logo.png"]; - // 加载本地图片 - imageView.yy_imageURL = [NSURL fileURLWithPath:@"/tmp/logo.png"]; +// 加载本地图片 +imageView.yy_imageURL = [NSURL fileURLWithPath:@"/tmp/logo.png"]; +``` + +### 加载动图 +```objc +// 只需要把 `UIImageView` 替换为 `YYAnimatedImageView` 即可。 +UIImageView *imageView = [YYAnimatedImageView new]; +imageView.yy_imageURL = [NSURL URLWithString:@"http://github.com/ani.webp"]; +``` + +### 渐进式图片加载 +```objc +// 渐进式:边下载边显示 +[imageView yy_setImageWithURL:url options:YYWebImageOptionProgressive]; - -###加载动图 +// 渐进式加载,增加模糊效果和渐变动画 (见本页最上方的GIF演示) +[imageView yy_setImageWithURL:url options:YYWebImageOptionProgressiveBlur | YYWebImageOptionSetImageWithFadeAnimation]; +``` + +### 加载、处理图片 +```objc +// 1. 下载图片 +// 2. 获得图片下载进度 +// 3. 调整图片大小、加圆角 +// 4. 显示图片时增加一个淡入动画,以获得更好的用户体验 - // 只需要把 `UIImageView` 替换为 `YYAnimatedImageView` 即可。 - UIImageView *imageView = [YYAnimatedImageView new]; - imageView.yy_imageURL = [NSURL URLWithString:@"http://github.com/ani.webp"]; +[imageView yy_setImageWithURL:url + placeholder:nil + options:YYWebImageOptionSetImageWithFadeAnimation + progress:^(NSInteger receivedSize, NSInteger expectedSize) { + progress = (float)receivedSize / expectedSize; + } + transform:^UIImage *(UIImage *image, NSURL *url) { + image = [image yy_imageByResizeToSize:CGSizeMake(100, 100) contentMode:UIViewContentModeCenter]; + return [image yy_imageByRoundCornerRadius:10]; + } + completion:^(UIImage *image, NSURL *url, YYWebImageFromType from, YYWebImageStage stage, NSError *error) { + if (from == YYWebImageFromDiskCache) { + NSLog(@"load from disk cache"); + } + }]; +``` + +### 图片缓存 +```objc +YYImageCache *cache = [YYWebImageManager sharedManager].cache; + +// 获取缓存大小 +cache.memoryCache.totalCost; +cache.memoryCache.totalCount; +cache.diskCache.totalCost; +cache.diskCache.totalCount; + +// 清空缓存 +[cache.memoryCache removeAllObjects]; +[cache.diskCache removeAllObjects]; + +// 清空磁盘缓存,带进度回调 +[cache.diskCache removeAllObjectsWithProgressBlock:^(int removedCount, int totalCount) { + // progress +} endBlock:^(BOOL error) { + // end +}]; +``` - -###渐进式图片加载 - - // 渐进式:边下载边显示 - [imageView yy_setImageWithURL:url options:YYWebImageOptionProgressive]; - - // 渐进式加载,增加模糊效果和渐变动画 (见本页最上方的GIF演示) - [imageView yy_setImageWithURL:url options:YYWebImageOptionProgressiveBlur | YYWebImageOptionSetImageWithFadeAnimation]; - - -###加载、处理图片 - - // 1. 下载图片 - // 2. 获得图片下载进度 - // 3. 调整图片大小、加圆角 - // 4. 显示图片时增加一个淡入动画,以获得更好的用户体验 - - [imageView yy_setImageWithURL:url - placeholder:nil - options:YYWebImageOptionSetImageWithFadeAnimation - progress:^(NSInteger receivedSize, NSInteger expectedSize) { - progress = (float)receivedSize / expectedSize; - } - transform:^UIImage *(UIImage *image, NSURL *url) { - image = [image yy_imageByResizeToSize:CGSizeMake(100, 100) contentMode:UIViewContentModeCenter]; - return [image yy_imageByRoundCornerRadius:10]; - } - completion:^(UIImage *image, NSURL *url, YYWebImageFromType from, YYWebImageStage stage, NSError *error) { - if (from == YYWebImageFromDiskCache) { - NSLog(@"load from disk cache"); - } - }]; - 安装 ============== -### Cocoapods +### CocoaPods 1. 将 cocoapods 更新至最新版本. -1. 在 Podfile 中添加 `pod "YYWebImage"`。 -2. 执行 `pod install` 或 `pod update`。 -3. 导入 \。 - +2. 在 Podfile 中添加 `pod 'YYWebImage'`。 +3. 执行 `pod install` 或 `pod update`。 +4. 导入 \。 +5. 注意:pod 配置并没有包含 WebP 组件, 如果你需要支持 WebP,可以在 Podfile 中添加 `pod 'YYImage/WebP'`。你可以调用 `YYImageWebPAvailable()` 来检查一下 WebP 组件是否被正确安装。 ### Carthage 1. 在 Cartfile 中添加 `github "ibireme/YYWebImage"`。 2. 执行 `carthage update --platform ios` 并将生成的 framework 添加到你的工程。 3. 导入 \。 -4. 注意: carthage framework 并没有包含 webp 组件。如果你需要支持 webp,可以用 Cocoapods 安装,或者手动安装。 +4. 注意: carthage framework 并没有包含 webp 组件。如果你需要支持 WebP,可以用 CocoaPods 安装,或者手动安装。 ### 手动安装 1. 下载 YYWebImage 文件夹内的所有内容。 -2. 将 YYWebModel 内的源文件添加(拖放)到你的工程。 +2. 将 YYWebImage 内的源文件添加(拖放)到你的工程。 3. 链接以下 frameworks: - * UIKit.framework - * CoreFoundation.framework - * QuartzCore.framework - * AssetsLibrary.framework - * ImageIO.framework - * Accelerate.framework - * MobileCoreServices.framework - * libsqlite3 + * UIKit + * CoreFoundation + * QuartzCore + * AssetsLibrary + * ImageIO + * Accelerate + * MobileCoreServices + * sqlite3 * libz -4. 如果你需要支持 webp,可以将 `Vendor/WebP.framework`(静态库) 加入你的工程。 -5. 导入 `YYWebImage.h`。 +4. 导入 `YYWebImage.h`。 +5. 注意:如果你需要支持 WebP,可以将 `Vendor/WebP.framework`(静态库) 加入你的工程。你可以调用 `YYImageWebPAvailable()` 来检查一下 WebP 组件是否被正确安装。 -关于 +文档 ============== -该项目最低支持 iOS 6.0。 +你可以在 [CocoaDocs](http://cocoadocs.org/docsets/YYWebImage/) 查看在线 API 文档,也可以用 [appledoc](https://github.com/tomaz/appledoc) 本地生成文档。 + + +系统要求 +============== +该项目最低支持 `iOS 6.0` 和 `Xcode 8.0`。 许可证 @@ -250,5 +307,7 @@ YYWebImage 使用 MIT 许可证,详情见 LICENSE 文件。 相关链接 ============== -[移动端图片格式调研](http://blog.ibireme.com/2015/11/02/mobile_image_benchmark/) -[iOS 处理图片的一些小 Tip](http://blog.ibireme.com/2015/11/02/ios_image_tips/) \ No newline at end of file +[移动端图片格式调研](https://blog.ibireme.com/2015/11/02/mobile_image_benchmark/)
+ +[iOS 处理图片的一些小 Tip](https://blog.ibireme.com/2015/11/02/ios_image_tips/) + diff --git a/Vendor/WebP.framework/Headers/config.h b/Vendor/WebP.framework/Headers/config.h index 5c9035c..70b1fbd 100644 --- a/Vendor/WebP.framework/Headers/config.h +++ b/Vendor/WebP.framework/Headers/config.h @@ -78,7 +78,7 @@ #define PACKAGE_NAME "libwebp" /* Define to the full name and version of this package. */ -#define PACKAGE_STRING "libwebp 0.4.4" +#define PACKAGE_STRING "libwebp 0.5.0" /* Define to the one symbol short name of this package. */ #define PACKAGE_TARNAME "libwebp" @@ -87,7 +87,7 @@ #define PACKAGE_URL "http://developers.google.com/speed/webp" /* Define to the version of this package. */ -#define PACKAGE_VERSION "0.4.4" +#define PACKAGE_VERSION "0.5.0" /* Define to necessary symbol if this constant uses a non-standard name on your system. */ @@ -97,7 +97,7 @@ #define STDC_HEADERS 1 /* Version number of package */ -#define VERSION "0.4.4" +#define VERSION "0.5.0" /* Enable experimental code */ /* #undef WEBP_EXPERIMENTAL_FEATURES */ @@ -123,6 +123,9 @@ /* Set to 1 if SSE2 is supported */ /* #undef WEBP_HAVE_SSE2 */ +/* Set to 1 if SSE4.1 is supported */ +/* #undef WEBP_HAVE_SSE41 */ + /* Set to 1 if TIFF library is installed */ /* #undef WEBP_HAVE_TIFF */ diff --git a/Vendor/WebP.framework/Headers/decode.h b/Vendor/WebP.framework/Headers/decode.h index 8d3f7be..143e4fb 100644 --- a/Vendor/WebP.framework/Headers/decode.h +++ b/Vendor/WebP.framework/Headers/decode.h @@ -20,7 +20,7 @@ extern "C" { #endif -#define WEBP_DECODER_ABI_VERSION 0x0203 // MAJOR(8b) + MINOR(8b) +#define WEBP_DECODER_ABI_VERSION 0x0208 // MAJOR(8b) + MINOR(8b) // Note: forward declaring enumerations is not allowed in (strict) C and C++, // the types are left here for reference. @@ -48,7 +48,7 @@ WEBP_EXTERN(int) WebPGetInfo(const uint8_t* data, size_t data_size, // Decodes WebP images pointed to by 'data' and returns RGBA samples, along // with the dimensions in *width and *height. The ordering of samples in // memory is R, G, B, A, R, G, B, A... in scan order (endian-independent). -// The returned pointer should be deleted calling free(). +// The returned pointer should be deleted calling WebPFree(). // Returns NULL in case of error. WEBP_EXTERN(uint8_t*) WebPDecodeRGBA(const uint8_t* data, size_t data_size, int* width, int* height); @@ -73,9 +73,9 @@ WEBP_EXTERN(uint8_t*) WebPDecodeBGR(const uint8_t* data, size_t data_size, // Decode WebP images pointed to by 'data' to Y'UV format(*). The pointer // returned is the Y samples buffer. Upon return, *u and *v will point to -// the U and V chroma data. These U and V buffers need NOT be free()'d, -// unlike the returned Y luma one. The dimension of the U and V planes -// are both (*width + 1) / 2 and (*height + 1)/ 2. +// the U and V chroma data. These U and V buffers need NOT be passed to +// WebPFree(), unlike the returned Y luma one. The dimension of the U and V +// planes are both (*width + 1) / 2 and (*height + 1)/ 2. // Upon return, the Y buffer has a stride returned as '*stride', while U and V // have a common stride returned as '*uv_stride'. // Return NULL in case of error. @@ -85,6 +85,9 @@ WEBP_EXTERN(uint8_t*) WebPDecodeYUV(const uint8_t* data, size_t data_size, uint8_t** u, uint8_t** v, int* stride, int* uv_stride); +// Releases memory returned by the WebPDecode*() functions above. +WEBP_EXTERN(void) WebPFree(void* ptr); + // These five functions are variants of the above ones, that decode the image // directly into a pre-allocated buffer 'output_buffer'. The maximum storage // available in this buffer is indicated by 'output_buffer_size'. If this @@ -406,12 +409,7 @@ struct WebPBitstreamFeatures { int has_animation; // True if the bitstream is an animation. int format; // 0 = undefined (/mixed), 1 = lossy, 2 = lossless - // Unused for now: - int no_incremental_decoding; // if true, using incremental decoding is not - // recommended. - int rotate; // TODO(later) - int uv_sampling; // should be 0 for now. TODO(later) - uint32_t pad[2]; // padding for later use + uint32_t pad[5]; // padding for later use }; // Internal, version-checked, entry point @@ -442,23 +440,10 @@ struct WebPDecoderOptions { int scaled_width, scaled_height; // final resolution int use_threads; // if true, use multi-threaded decoding int dithering_strength; // dithering strength (0=Off, 100=full) -#if WEBP_DECODER_ABI_VERSION > 0x0203 int flip; // flip output vertically -#endif -#if WEBP_DECODER_ABI_VERSION > 0x0204 int alpha_dithering_strength; // alpha dithering strength in [0..100] -#endif - // Unused for now: - int force_rotation; // forced rotation (to be applied _last_) - int no_enhancement; // if true, discard enhancement layer -#if WEBP_DECODER_ABI_VERSION < 0x0203 uint32_t pad[5]; // padding for later use -#elif WEBP_DECODER_ABI_VERSION < 0x0204 - uint32_t pad[4]; // padding for later use -#else - uint32_t pad[3]; // padding for later use -#endif }; // Main object storing the configuration for advanced decoding. diff --git a/Vendor/WebP.framework/Headers/demux.h b/Vendor/WebP.framework/Headers/demux.h index 2da3239..454f691 100644 --- a/Vendor/WebP.framework/Headers/demux.h +++ b/Vendor/WebP.framework/Headers/demux.h @@ -48,13 +48,14 @@ #ifndef WEBP_WEBP_DEMUX_H_ #define WEBP_WEBP_DEMUX_H_ +#include "./decode.h" // for WEBP_CSP_MODE #include "./mux_types.h" #ifdef __cplusplus extern "C" { #endif -#define WEBP_DEMUX_ABI_VERSION 0x0101 // MAJOR(8b) + MINOR(8b) +#define WEBP_DEMUX_ABI_VERSION 0x0107 // MAJOR(8b) + MINOR(8b) // Note: forward declaring enumerations is not allowed in (strict) C and C++, // the types are left here for reference. @@ -63,6 +64,8 @@ extern "C" { typedef struct WebPDemuxer WebPDemuxer; typedef struct WebPIterator WebPIterator; typedef struct WebPChunkIterator WebPChunkIterator; +typedef struct WebPAnimInfo WebPAnimInfo; +typedef struct WebPAnimDecoderOptions WebPAnimDecoderOptions; //------------------------------------------------------------------------------ @@ -85,7 +88,8 @@ typedef enum WebPDemuxState { WEBP_EXTERN(WebPDemuxer*) WebPDemuxInternal( const WebPData*, int, WebPDemuxState*, int); -// Parses the full WebP file given by 'data'. +// Parses the full WebP file given by 'data'. For single images the WebP file +// header alone or the file header and the chunk header may be absent. // Returns a WebPDemuxer object on successful parse, NULL otherwise. static WEBP_INLINE WebPDemuxer* WebPDemux(const WebPData* data) { return WebPDemuxInternal(data, 0, NULL, WEBP_DEMUX_ABI_VERSION); @@ -134,17 +138,15 @@ WEBP_EXTERN(uint32_t) WebPDemuxGetI( struct WebPIterator { int frame_num; int num_frames; // equivalent to WEBP_FF_FRAME_COUNT. - int fragment_num; - int num_fragments; int x_offset, y_offset; // offset relative to the canvas. - int width, height; // dimensions of this frame or fragment. + int width, height; // dimensions of this frame. int duration; // display duration in milliseconds. WebPMuxAnimDispose dispose_method; // dispose method for the frame. int complete; // true if 'fragment' contains a full frame. partial images // may still be decoded with the WebP incremental decoder. - WebPData fragment; // The frame or fragment given by 'frame_num' and - // 'fragment_num'. - int has_alpha; // True if the frame or fragment contains transparency. + WebPData fragment; // The frame given by 'frame_num'. Note for historical + // reasons this is called a fragment. + int has_alpha; // True if the frame contains transparency. WebPMuxAnimBlend blend_method; // Blend operation for the frame. uint32_t pad[2]; // padding for later use. @@ -152,8 +154,7 @@ struct WebPIterator { }; // Retrieves frame 'frame_number' from 'dmux'. -// 'iter->fragment' points to the first fragment on return from this function. -// Individual fragments may be extracted using WebPDemuxSelectFragment(). +// 'iter->fragment' points to the frame on return from this function. // Setting 'frame_number' equal to 0 will return the last frame of the image. // Returns false if 'dmux' is NULL or frame 'frame_number' is not present. // Call WebPDemuxReleaseIterator() when use of the iterator is complete. @@ -167,10 +168,6 @@ WEBP_EXTERN(int) WebPDemuxGetFrame( WEBP_EXTERN(int) WebPDemuxNextFrame(WebPIterator* iter); WEBP_EXTERN(int) WebPDemuxPrevFrame(WebPIterator* iter); -// Sets 'iter->fragment' to reflect fragment number 'fragment_num'. -// Returns true if fragment 'fragment_num' is present, false otherwise. -WEBP_EXTERN(int) WebPDemuxSelectFragment(WebPIterator* iter, int fragment_num); - // Releases any memory associated with 'iter'. // Must be called before any subsequent calls to WebPDemuxGetChunk() on the same // iter. Also, must be called before destroying the associated WebPDemuxer with @@ -216,6 +213,143 @@ WEBP_EXTERN(int) WebPDemuxPrevChunk(WebPChunkIterator* iter); WEBP_EXTERN(void) WebPDemuxReleaseChunkIterator(WebPChunkIterator* iter); //------------------------------------------------------------------------------ +// WebPAnimDecoder API +// +// This API allows decoding (possibly) animated WebP images. +// +// Code Example: +/* + WebPAnimDecoderOptions dec_options; + WebPAnimDecoderOptionsInit(&dec_options); + // Tune 'dec_options' as needed. + WebPAnimDecoder* dec = WebPAnimDecoderNew(webp_data, &dec_options); + WebPAnimInfo anim_info; + WebPAnimDecoderGetInfo(dec, &anim_info); + for (uint32_t i = 0; i < anim_info.loop_count; ++i) { + while (WebPAnimDecoderHasMoreFrames(dec)) { + uint8_t* buf; + int timestamp; + WebPAnimDecoderGetNext(dec, &buf, ×tamp); + // ... (Render 'buf' based on 'timestamp'). + // ... (Do NOT free 'buf', as it is owned by 'dec'). + } + WebPAnimDecoderReset(dec); + } + const WebPDemuxer* demuxer = WebPAnimDecoderGetDemuxer(dec); + // ... (Do something using 'demuxer'; e.g. get EXIF/XMP/ICC data). + WebPAnimDecoderDelete(dec); +*/ + +typedef struct WebPAnimDecoder WebPAnimDecoder; // Main opaque object. + +// Global options. +struct WebPAnimDecoderOptions { + // Output colorspace. Only the following modes are supported: + // MODE_RGBA, MODE_BGRA, MODE_rgbA and MODE_bgrA. + WEBP_CSP_MODE color_mode; + int use_threads; // If true, use multi-threaded decoding. + uint32_t padding[7]; // Padding for later use. +}; + +// Internal, version-checked, entry point. +WEBP_EXTERN(int) WebPAnimDecoderOptionsInitInternal( + WebPAnimDecoderOptions*, int); + +// Should always be called, to initialize a fresh WebPAnimDecoderOptions +// structure before modification. Returns false in case of version mismatch. +// WebPAnimDecoderOptionsInit() must have succeeded before using the +// 'dec_options' object. +static WEBP_INLINE int WebPAnimDecoderOptionsInit( + WebPAnimDecoderOptions* dec_options) { + return WebPAnimDecoderOptionsInitInternal(dec_options, + WEBP_DEMUX_ABI_VERSION); +} + +// Internal, version-checked, entry point. +WEBP_EXTERN(WebPAnimDecoder*) WebPAnimDecoderNewInternal( + const WebPData*, const WebPAnimDecoderOptions*, int); + +// Creates and initializes a WebPAnimDecoder object. +// Parameters: +// webp_data - (in) WebP bitstream. This should remain unchanged during the +// lifetime of the output WebPAnimDecoder object. +// dec_options - (in) decoding options. Can be passed NULL to choose +// reasonable defaults (in particular, color mode MODE_RGBA +// will be picked). +// Returns: +// A pointer to the newly created WebPAnimDecoder object, or NULL in case of +// parsing error, invalid option or memory error. +static WEBP_INLINE WebPAnimDecoder* WebPAnimDecoderNew( + const WebPData* webp_data, const WebPAnimDecoderOptions* dec_options) { + return WebPAnimDecoderNewInternal(webp_data, dec_options, + WEBP_DEMUX_ABI_VERSION); +} + +// Global information about the animation.. +struct WebPAnimInfo { + uint32_t canvas_width; + uint32_t canvas_height; + uint32_t loop_count; + uint32_t bgcolor; + uint32_t frame_count; + uint32_t pad[4]; // padding for later use +}; + +// Get global information about the animation. +// Parameters: +// dec - (in) decoder instance to get information from. +// info - (out) global information fetched from the animation. +// Returns: +// True on success. +WEBP_EXTERN(int) WebPAnimDecoderGetInfo(const WebPAnimDecoder* dec, + WebPAnimInfo* info); + +// Fetch the next frame from 'dec' based on options supplied to +// WebPAnimDecoderNew(). This will be a fully reconstructed canvas of size +// 'canvas_width * 4 * canvas_height', and not just the frame sub-rectangle. The +// returned buffer 'buf' is valid only until the next call to +// WebPAnimDecoderGetNext(), WebPAnimDecoderReset() or WebPAnimDecoderDelete(). +// Parameters: +// dec - (in/out) decoder instance from which the next frame is to be fetched. +// buf - (out) decoded frame. +// timestamp - (out) timestamp of the frame in milliseconds. +// Returns: +// False if any of the arguments are NULL, or if there is a parsing or +// decoding error, or if there are no more frames. Otherwise, returns true. +WEBP_EXTERN(int) WebPAnimDecoderGetNext(WebPAnimDecoder* dec, + uint8_t** buf, int* timestamp); + +// Check if there are more frames left to decode. +// Parameters: +// dec - (in) decoder instance to be checked. +// Returns: +// True if 'dec' is not NULL and some frames are yet to be decoded. +// Otherwise, returns false. +WEBP_EXTERN(int) WebPAnimDecoderHasMoreFrames(const WebPAnimDecoder* dec); + +// Resets the WebPAnimDecoder object, so that next call to +// WebPAnimDecoderGetNext() will restart decoding from 1st frame. This would be +// helpful when all frames need to be decoded multiple times (e.g. +// info.loop_count times) without destroying and recreating the 'dec' object. +// Parameters: +// dec - (in/out) decoder instance to be reset +WEBP_EXTERN(void) WebPAnimDecoderReset(WebPAnimDecoder* dec); + +// Grab the internal demuxer object. +// Getting the demuxer object can be useful if one wants to use operations only +// available through demuxer; e.g. to get XMP/EXIF/ICC metadata. The returned +// demuxer object is owned by 'dec' and is valid only until the next call to +// WebPAnimDecoderDelete(). +// +// Parameters: +// dec - (in) decoder instance from which the demuxer object is to be fetched. +WEBP_EXTERN(const WebPDemuxer*) WebPAnimDecoderGetDemuxer( + const WebPAnimDecoder* dec); + +// Deletes the WebPAnimDecoder object. +// Parameters: +// dec - (in/out) decoder instance to be deleted +WEBP_EXTERN(void) WebPAnimDecoderDelete(WebPAnimDecoder* dec); #ifdef __cplusplus } // extern "C" diff --git a/Vendor/WebP.framework/Headers/encode.h b/Vendor/WebP.framework/Headers/encode.h index b3f05b1..c382ea7 100644 --- a/Vendor/WebP.framework/Headers/encode.h +++ b/Vendor/WebP.framework/Headers/encode.h @@ -20,7 +20,7 @@ extern "C" { #endif -#define WEBP_ENCODER_ABI_VERSION 0x0202 // MAJOR(8b) + MINOR(8b) +#define WEBP_ENCODER_ABI_VERSION 0x0209 // MAJOR(8b) + MINOR(8b) // Note: forward declaring enumerations is not allowed in (strict) C and C++, // the types are left here for reference. @@ -42,7 +42,7 @@ WEBP_EXTERN(int) WebPGetEncoderVersion(void); // Returns the size of the compressed data (pointed to by *output), or 0 if // an error occurred. The compressed data must be released by the caller -// using the call 'free(*output)'. +// using the call 'WebPFree(*output)'. // These functions compress using the lossy format, and the quality_factor // can go from 0 (smaller output, lower quality) to 100 (best quality, // larger output). @@ -75,6 +75,9 @@ WEBP_EXTERN(size_t) WebPEncodeLosslessBGRA(const uint8_t* bgra, int width, int height, int stride, uint8_t** output); +// Releases memory returned by the WebPEncode*() functions above. +WEBP_EXTERN(void) WebPFree(void* ptr); + //------------------------------------------------------------------------------ // Coding parameters @@ -131,7 +134,19 @@ struct WebPConfig { int thread_level; // If non-zero, try and use multi-threaded encoding. int low_memory; // If set, reduce memory usage (but increase CPU use). - uint32_t pad[5]; // padding for later use + int near_lossless; // Near lossless encoding [0 = off(default) .. 100]. + // This feature is experimental. + int exact; // if non-zero, preserve the exact RGB values under + // transparent area. Otherwise, discard this invisible + // RGB information for better compression. The default + // value is 0. + +#ifdef WEBP_EXPERIMENTAL_FEATURES + int delta_palettization; + uint32_t pad[2]; // padding for later use +#else + uint32_t pad[3]; // padding for later use +#endif // WEBP_EXPERIMENTAL_FEATURES }; // Enumerate some predefined settings for WebPConfig, depending on the type @@ -167,7 +182,6 @@ static WEBP_INLINE int WebPConfigPreset(WebPConfig* config, WEBP_ENCODER_ABI_VERSION); } -#if WEBP_ENCODER_ABI_VERSION > 0x0202 // Activate the lossless compression mode with the desired efficiency level // between 0 (fastest, lowest compression) and 9 (slower, best compression). // A good default level is '6', providing a fair tradeoff between compression @@ -175,7 +189,6 @@ static WEBP_INLINE int WebPConfigPreset(WebPConfig* config, // This function will overwrite several fields from config: 'method', 'quality' // and 'lossless'. Returns false in case of parameter error. WEBP_EXTERN(int) WebPConfigLosslessPreset(WebPConfig* config, int level); -#endif // Returns true if 'config' is non-NULL and all configuration parameters are // within their valid ranges. @@ -209,8 +222,10 @@ struct WebPAuxStats { int cache_bits; // number of bits for color cache lookup int palette_size; // number of color in palette, if used int lossless_size; // final lossless size + int lossless_hdr_size; // lossless header (transform, huffman etc) size + int lossless_data_size; // lossless image data size - uint32_t pad[4]; // padding for later use + uint32_t pad[2]; // padding for later use }; // Signature for output function. Should return true if writing was successful. @@ -231,18 +246,12 @@ struct WebPMemoryWriter { // The following must be called first before any use. WEBP_EXTERN(void) WebPMemoryWriterInit(WebPMemoryWriter* writer); -#if WEBP_ENCODER_ABI_VERSION > 0x0203 // The following must be called to deallocate writer->mem memory. The 'writer' // object itself is not deallocated. WEBP_EXTERN(void) WebPMemoryWriterClear(WebPMemoryWriter* writer); -#endif // The custom writer to be used with WebPMemoryWriter as custom_ptr. Upon // completion, writer.mem and writer.size will hold the coded data. -#if WEBP_ENCODER_ABI_VERSION > 0x0203 // writer.mem must be freed by calling WebPMemoryWriterClear. -#else -// writer.mem must be freed by calling 'free(writer.mem)'. -#endif WEBP_EXTERN(int) WebPMemoryWrite(const uint8_t* data, size_t data_size, const WebPPicture* picture); @@ -379,8 +388,8 @@ WEBP_EXTERN(void) WebPPictureFree(WebPPicture* picture); // Returns false in case of memory allocation error. WEBP_EXTERN(int) WebPPictureCopy(const WebPPicture* src, WebPPicture* dst); -// Compute PSNR, SSIM or LSIM distortion metric between two pictures. -// Result is in dB, stores in result[] in the Y/U/V/Alpha/All order. +// Compute PSNR, SSIM or LSIM distortion metric between two pictures. Results +// are in dB, stored in result[] in the Y/U/V/Alpha/All or B/G/R/A/All order. // Returns false in case of error (src and ref don't have same dimension, ...) // Warning: this function is rather CPU-intensive. WEBP_EXTERN(int) WebPPictureDistortion( @@ -464,14 +473,12 @@ WEBP_EXTERN(int) WebPPictureARGBToYUVA(WebPPicture* picture, WEBP_EXTERN(int) WebPPictureARGBToYUVADithered( WebPPicture* picture, WebPEncCSP colorspace, float dithering); -#if WEBP_ENCODER_ABI_VERSION > 0x0204 // Performs 'smart' RGBA->YUVA420 downsampling and colorspace conversion. // Downsampling is handled with extra care in case of color clipping. This // method is roughly 2x slower than WebPPictureARGBToYUVA() but produces better // YUV representation. // Returns false in case of error. WEBP_EXTERN(int) WebPPictureSmartARGBToYUVA(WebPPicture* picture); -#endif // Converts picture->yuv to picture->argb and sets picture->use_argb to true. // The input format must be YUV_420 or YUV_420A. diff --git a/Vendor/WebP.framework/Headers/extras.h b/Vendor/WebP.framework/Headers/extras.h new file mode 100644 index 0000000..1c24be2 --- /dev/null +++ b/Vendor/WebP.framework/Headers/extras.h @@ -0,0 +1,51 @@ +// Copyright 2015 Google Inc. All Rights Reserved. +// +// Use of this source code is governed by a BSD-style license +// that can be found in the COPYING file in the root of the source +// tree. An additional intellectual property rights grant can be found +// in the file PATENTS. All contributing project authors may +// be found in the AUTHORS file in the root of the source tree. +// ----------------------------------------------------------------------------- +// + +#ifndef WEBP_WEBP_EXTRAS_H_ +#define WEBP_WEBP_EXTRAS_H_ + +#include "./types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#include "./encode.h" + +#define WEBP_EXTRAS_ABI_VERSION 0x0000 // MAJOR(8b) + MINOR(8b) + +//------------------------------------------------------------------------------ + +// Returns the version number of the extras library, packed in hexadecimal using +// 8bits for each of major/minor/revision. E.g: v2.5.7 is 0x020507. +WEBP_EXTERN(int) WebPGetExtrasVersion(void); + +//------------------------------------------------------------------------------ +// Ad-hoc colorspace importers. + +// Import luma sample (gray scale image) into 'picture'. The 'picture' +// width and height must be set prior to calling this function. +WEBP_EXTERN(int) WebPImportGray(const uint8_t* gray, WebPPicture* picture); + +// Import rgb sample in RGB565 packed format into 'picture'. The 'picture' +// width and height must be set prior to calling this function. +WEBP_EXTERN(int) WebPImportRGB565(const uint8_t* rgb565, WebPPicture* pic); + +// Import rgb sample in RGB4444 packed format into 'picture'. The 'picture' +// width and height must be set prior to calling this function. +WEBP_EXTERN(int) WebPImportRGB4444(const uint8_t* rgb4444, WebPPicture* pic); + +//------------------------------------------------------------------------------ + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif /* WEBP_WEBP_EXTRAS_H_ */ diff --git a/Vendor/WebP.framework/Headers/format_constants.h b/Vendor/WebP.framework/Headers/format_constants.h index 4c04b50..b6e78a6 100644 --- a/Vendor/WebP.framework/Headers/format_constants.h +++ b/Vendor/WebP.framework/Headers/format_constants.h @@ -15,7 +15,7 @@ #define WEBP_WEBP_FORMAT_CONSTANTS_H_ // Create fourcc of the chunk from the chunk tag characters. -#define MKFOURCC(a, b, c, d) ((uint32_t)(a) | (b) << 8 | (c) << 16 | (d) << 24) +#define MKFOURCC(a, b, c, d) ((a) | (b) << 8 | (c) << 16 | (uint32_t)(d) << 24) // VP8 related constants. #define VP8_SIGNATURE 0x9d012a // Signature in VP8 data. diff --git a/Vendor/WebP.framework/Headers/mux.h b/Vendor/WebP.framework/Headers/mux.h index 1ae03b3..b72658c 100644 --- a/Vendor/WebP.framework/Headers/mux.h +++ b/Vendor/WebP.framework/Headers/mux.h @@ -7,11 +7,25 @@ // be found in the AUTHORS file in the root of the source tree. // ----------------------------------------------------------------------------- // -// RIFF container manipulation for WebP images. +// RIFF container manipulation and encoding for WebP images. // // Authors: Urvang (urvang@google.com) // Vikas (vikasa@google.com) +#ifndef WEBP_WEBP_MUX_H_ +#define WEBP_WEBP_MUX_H_ + +#include "./mux_types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define WEBP_MUX_ABI_VERSION 0x0106 // MAJOR(8b) + MINOR(8b) + +//------------------------------------------------------------------------------ +// Mux API +// // This API allows manipulation of WebP container images containing features // like color profile, metadata, animation and fragmented images. // @@ -46,17 +60,6 @@ free(data); */ -#ifndef WEBP_WEBP_MUX_H_ -#define WEBP_WEBP_MUX_H_ - -#include "./mux_types.h" - -#ifdef __cplusplus -extern "C" { -#endif - -#define WEBP_MUX_ABI_VERSION 0x0101 // MAJOR(8b) + MINOR(8b) - // Note: forward declaring enumerations is not allowed in (strict) C and C++, // the types are left here for reference. // typedef enum WebPMuxError WebPMuxError; @@ -64,6 +67,7 @@ extern "C" { typedef struct WebPMux WebPMux; // main opaque object. typedef struct WebPMuxFrameInfo WebPMuxFrameInfo; typedef struct WebPMuxAnimParams WebPMuxAnimParams; +typedef struct WebPAnimEncoderOptions WebPAnimEncoderOptions; // Error codes typedef enum WebPMuxError { @@ -310,7 +314,6 @@ WEBP_EXTERN(WebPMuxError) WebPMuxGetAnimationParams( //------------------------------------------------------------------------------ // Misc Utilities. -#if WEBP_MUX_ABI_VERSION > 0x0101 // Sets the canvas size for the mux object. The width and height can be // specified explicitly or left as zero (0, 0). // * When width and height are specified explicitly, then this frame bound is @@ -328,7 +331,6 @@ WEBP_EXTERN(WebPMuxError) WebPMuxGetAnimationParams( // WEBP_MUX_OK - on success. WEBP_EXTERN(WebPMuxError) WebPMuxSetCanvasSize(WebPMux* mux, int width, int height); -#endif // Gets the canvas size from the mux object. // Note: This method assumes that the VP8X chunk, if present, is up-to-date. @@ -390,6 +392,135 @@ WEBP_EXTERN(WebPMuxError) WebPMuxNumChunks(const WebPMux* mux, WEBP_EXTERN(WebPMuxError) WebPMuxAssemble(WebPMux* mux, WebPData* assembled_data); +//------------------------------------------------------------------------------ +// WebPAnimEncoder API +// +// This API allows encoding (possibly) animated WebP images. +// +// Code Example: +/* + WebPAnimEncoderOptions enc_options; + WebPAnimEncoderOptionsInit(&enc_options); + // Tune 'enc_options' as needed. + WebPAnimEncoder* enc = WebPAnimEncoderNew(width, height, &enc_options); + while() { + WebPConfig config; + WebPConfigInit(&config); + // Tune 'config' as needed. + WebPAnimEncoderAdd(enc, frame, timestamp_ms, &config); + } + WebPAnimEncoderAdd(enc, NULL, timestamp_ms, NULL); + WebPAnimEncoderAssemble(enc, webp_data); + WebPAnimEncoderDelete(enc); + // Write the 'webp_data' to a file, or re-mux it further. +*/ + +typedef struct WebPAnimEncoder WebPAnimEncoder; // Main opaque object. + +// Forward declarations. Defined in encode.h. +struct WebPPicture; +struct WebPConfig; + +// Global options. +struct WebPAnimEncoderOptions { + WebPMuxAnimParams anim_params; // Animation parameters. + int minimize_size; // If true, minimize the output size (slow). Implicitly + // disables key-frame insertion. + int kmin; + int kmax; // Minimum and maximum distance between consecutive key + // frames in the output. The library may insert some key + // frames as needed to satisfy this criteria. + // Note that these conditions should hold: kmax > kmin + // and kmin >= kmax / 2 + 1. Also, if kmin == 0, then + // key-frame insertion is disabled; and if kmax == 0, + // then all frames will be key-frames. + int allow_mixed; // If true, use mixed compression mode; may choose + // either lossy and lossless for each frame. + int verbose; // If true, print info and warning messages to stderr. + + uint32_t padding[4]; // Padding for later use. +}; + +// Internal, version-checked, entry point. +WEBP_EXTERN(int) WebPAnimEncoderOptionsInitInternal( + WebPAnimEncoderOptions*, int); + +// Should always be called, to initialize a fresh WebPAnimEncoderOptions +// structure before modification. Returns false in case of version mismatch. +// WebPAnimEncoderOptionsInit() must have succeeded before using the +// 'enc_options' object. +static WEBP_INLINE int WebPAnimEncoderOptionsInit( + WebPAnimEncoderOptions* enc_options) { + return WebPAnimEncoderOptionsInitInternal(enc_options, WEBP_MUX_ABI_VERSION); +} + +// Internal, version-checked, entry point. +WEBP_EXTERN(WebPAnimEncoder*) WebPAnimEncoderNewInternal( + int, int, const WebPAnimEncoderOptions*, int); + +// Creates and initializes a WebPAnimEncoder object. +// Parameters: +// width/height - (in) canvas width and height of the animation. +// enc_options - (in) encoding options; can be passed NULL to pick +// reasonable defaults. +// Returns: +// A pointer to the newly created WebPAnimEncoder object. +// Or NULL in case of memory error. +static WEBP_INLINE WebPAnimEncoder* WebPAnimEncoderNew( + int width, int height, const WebPAnimEncoderOptions* enc_options) { + return WebPAnimEncoderNewInternal(width, height, enc_options, + WEBP_MUX_ABI_VERSION); +} + +// Optimize the given frame for WebP, encode it and add it to the +// WebPAnimEncoder object. +// The last call to 'WebPAnimEncoderAdd' should be with frame = NULL, which +// indicates that no more frames are to be added. This call is also used to +// determine the duration of the last frame. +// Parameters: +// enc - (in/out) object to which the frame is to be added. +// frame - (in/out) frame data in ARGB or YUV(A) format. If it is in YUV(A) +// format, it will be converted to ARGB, which incurs a small loss. +// timestamp_ms - (in) timestamp of this frame in milliseconds. +// Duration of a frame would be calculated as +// "timestamp of next frame - timestamp of this frame". +// Hence, timestamps should be in non-decreasing order. +// config - (in) encoding options; can be passed NULL to pick +// reasonable defaults. +// Returns: +// On error, returns false and frame->error_code is set appropriately. +// Otherwise, returns true. +WEBP_EXTERN(int) WebPAnimEncoderAdd( + WebPAnimEncoder* enc, struct WebPPicture* frame, int timestamp_ms, + const struct WebPConfig* config); + +// Assemble all frames added so far into a WebP bitstream. +// This call should be preceded by a call to 'WebPAnimEncoderAdd' with +// frame = NULL; if not, the duration of the last frame will be internally +// estimated. +// Parameters: +// enc - (in/out) object from which the frames are to be assembled. +// webp_data - (out) generated WebP bitstream. +// Returns: +// True on success. +WEBP_EXTERN(int) WebPAnimEncoderAssemble(WebPAnimEncoder* enc, + WebPData* webp_data); + +// Get error string corresponding to the most recent call using 'enc'. The +// returned string is owned by 'enc' and is valid only until the next call to +// WebPAnimEncoderAdd() or WebPAnimEncoderAssemble() or WebPAnimEncoderDelete(). +// Parameters: +// enc - (in/out) object from which the error string is to be fetched. +// Returns: +// NULL if 'enc' is NULL. Otherwise, returns the error string if the last call +// to 'enc' had an error, or an empty string if the last call was a success. +WEBP_EXTERN(const char*) WebPAnimEncoderGetError(WebPAnimEncoder* enc); + +// Deletes the WebPAnimEncoder object. +// Parameters: +// enc - (in/out) object to be deleted +WEBP_EXTERN(void) WebPAnimEncoderDelete(WebPAnimEncoder* enc); + //------------------------------------------------------------------------------ #ifdef __cplusplus diff --git a/Vendor/WebP.framework/Headers/types.h b/Vendor/WebP.framework/Headers/types.h index 9b036e0..98fff35 100644 --- a/Vendor/WebP.framework/Headers/types.h +++ b/Vendor/WebP.framework/Headers/types.h @@ -39,7 +39,11 @@ typedef long long int int64_t; #ifndef WEBP_EXTERN // This explicitly marks library functions and allows for changing the // signature for e.g., Windows DLL builds. -#define WEBP_EXTERN(type) extern type +# if defined(__GNUC__) && __GNUC__ >= 4 +# define WEBP_EXTERN(type) extern __attribute__ ((visibility ("default"))) type +# else +# define WEBP_EXTERN(type) extern type +# endif /* __GNUC__ >= 4 */ #endif /* WEBP_EXTERN */ // Macro to check ABI compatibility (same major revision number) diff --git a/Vendor/WebP.framework/WebP b/Vendor/WebP.framework/WebP index 12b8e2a..5d88df8 100644 Binary files a/Vendor/WebP.framework/WebP and b/Vendor/WebP.framework/WebP differ diff --git a/Vendor/WebP.sh b/Vendor/WebP.sh index 1ce52aa..3db9637 100755 --- a/Vendor/WebP.sh +++ b/Vendor/WebP.sh @@ -104,7 +104,6 @@ for PLATFORM in ${PLATFORMS}; do --disable-shared --enable-static \ --enable-libwebpmux \ --enable-libwebpdemux \ - --enable-libwebpdecoder \ --enable-swap-16bit-csp \ CFLAGS="${CFLAGS}" set +x @@ -119,7 +118,6 @@ for PLATFORM in ${PLATFORMS}; do ar x libwebp.a ar x libwebpmux.a ar x libwebpdemux.a - ar x libwebpdecoder.a ar q webp.a *.o LIBLIST+=" ${ROOTDIR}/lib/webp.a" diff --git a/YYWebImage.podspec b/YYWebImage.podspec index df283d1..a218d65 100644 --- a/YYWebImage.podspec +++ b/YYWebImage.podspec @@ -1,7 +1,7 @@ Pod::Spec.new do |s| s.name = 'YYWebImage' s.summary = 'Asynchronous image loading framework.' - s.version = '0.9.0' + s.version = '1.0.5' s.license = { :type => 'MIT', :file => 'LICENSE' } s.authors = { 'ibireme' => 'ibireme@gmail.com' } s.social_media_url = 'http://blog.ibireme.com/' @@ -11,11 +11,12 @@ Pod::Spec.new do |s| s.source = { :git => 'https://github.com/ibireme/YYWebImage.git', :tag => s.version.to_s } s.requires_arc = true - s.source_files = 'YYWebImage/**/*.{h,m}' - s.public_header_files = 'YYWebImage/**/*.{h}' - - s.libraries = 'z', 'sqlite3' + s.source_files = 'YYWebImage/*.{h,m}', 'YYWebImage/Categories/*.{h,m}' + s.public_header_files = 'YYWebImage/*.{h}', 'YYWebImage/Categories/*.{h}' + s.private_header_files = 'YYWebImage/Categories/_*.{h}' s.frameworks = 'UIKit', 'CoreFoundation', 'QuartzCore', 'AssetsLibrary', 'ImageIO', 'Accelerate', 'MobileCoreServices' - s.ios.vendored_frameworks = 'Vendor/WebP.framework' - + + s.dependency 'YYImage' + s.dependency 'YYCache' + end diff --git a/YYWebImage/Cache/YYCache.h b/YYWebImage/Cache/YYCache.h index 474583f..f042ed7 100644 --- a/YYWebImage/Cache/YYCache.h +++ b/YYWebImage/Cache/YYCache.h @@ -27,6 +27,7 @@ FOUNDATION_EXPORT const unsigned char YYCacheVersionString[]; #import "YYKVStorage.h" #endif +NS_ASSUME_NONNULL_BEGIN /** @@ -55,20 +56,41 @@ FOUNDATION_EXPORT const unsigned char YYCacheVersionString[]; the app's caches dictionary for disk cache. Once initialized you should not read and write to this directory. @result A new cache object, or nil if an error occurs. - @warning Multiple instances with the same name will make the storage unstable. */ -- (instancetype)initWithName:(NSString *)name; +- (nullable instancetype)initWithName:(NSString *)name; /** + Create a new instance with the specified path. + Multiple instances with the same name will make the cache unstable. + + @param path Full path of a directory in which the cache will write data. + Once initialized you should not read and write to this directory. + @result A new cache object, or nil if an error occurs. + */ +- (nullable instancetype)initWithPath:(NSString *)path NS_DESIGNATED_INITIALIZER; + +/** + Convenience Initializers Create a new instance with the specified name. Multiple instances with the same name will make the cache unstable. + @param name The name of the cache. It will create a dictionary with the name in + the app's caches dictionary for disk cache. Once initialized you should not + read and write to this directory. + @result A new cache object, or nil if an error occurs. + */ ++ (nullable instancetype)cacheWithName:(NSString *)name; + +/** + Convenience Initializers + Create a new instance with the specified path. + Multiple instances with the same name will make the cache unstable. + @param path Full path of a directory in which the cache will write data. Once initialized you should not read and write to this directory. @result A new cache object, or nil if an error occurs. - @warning Multiple instances with the same path will make the storage unstable. */ -- (instancetype)initWithPath:(NSString *)path; ++ (nullable instancetype)cacheWithPath:(NSString *)path; - (instancetype)init UNAVAILABLE_ATTRIBUTE; + (instancetype)new UNAVAILABLE_ATTRIBUTE; @@ -89,13 +111,13 @@ FOUNDATION_EXPORT const unsigned char YYCacheVersionString[]; /** Returns a boolean value with the block that indicates whether a given key is in cache. - This method returns immediately and revoke the passed block in background queue + This method returns immediately and invoke the passed block in background queue when the operation finished. @param key A string identifying the value. If nil, just return NO. - @param block A block which will be revoked in background queue when finished. + @param block A block which will be invoked in background queue when finished. */ -- (void)containsObjectForKey:(NSString *)key withBlock:(void(^)(NSString *key, BOOL contains))block; +- (void)containsObjectForKey:(NSString *)key withBlock:(nullable void(^)(NSString *key, BOOL contains))block; /** Returns the value associated with a given key. @@ -104,17 +126,17 @@ FOUNDATION_EXPORT const unsigned char YYCacheVersionString[]; @param key A string identifying the value. If nil, just return nil. @return The value associated with key, or nil if no value is associated with key. */ -- (id)objectForKey:(NSString *)key; +- (nullable id)objectForKey:(NSString *)key; /** Returns the value associated with a given key. - This method returns immediately and revoke the passed block in background queue + This method returns immediately and invoke the passed block in background queue when the operation finished. @param key A string identifying the value. If nil, just return nil. - @param block A block which will be revoked in background queue when finished. + @param block A block which will be invoked in background queue when finished. */ -- (void)objectForKey:(NSString *)key withBlock:(void(^)(NSString *key, id object))block; +- (void)objectForKey:(NSString *)key withBlock:(nullable void(^)(NSString *key, id object))block; /** Sets the value of the specified key in the cache. @@ -123,17 +145,17 @@ FOUNDATION_EXPORT const unsigned char YYCacheVersionString[]; @param object The object to be stored in the cache. If nil, it calls `removeObjectForKey:`. @param key The key with which to associate the value. If nil, this method has no effect. */ -- (void)setObject:(id)object forKey:(NSString *)key; +- (void)setObject:(nullable id)object forKey:(NSString *)key; /** Sets the value of the specified key in the cache. - This method returns immediately and revoke the passed block in background queue + This method returns immediately and invoke the passed block in background queue when the operation finished. @param object The object to be stored in the cache. If nil, it calls `removeObjectForKey:`. - @param block A block which will be revoked in background queue when finished. + @param block A block which will be invoked in background queue when finished. */ -- (void)setObject:(id)object forKey:(NSString *)key withBlock:(void(^)(void))block; +- (void)setObject:(nullable id)object forKey:(NSString *)key withBlock:(nullable void(^)(void))block; /** Removes the value of the specified key in the cache. @@ -145,13 +167,13 @@ FOUNDATION_EXPORT const unsigned char YYCacheVersionString[]; /** Removes the value of the specified key in the cache. - This method returns immediately and revoke the passed block in background queue + This method returns immediately and invoke the passed block in background queue when the operation finished. @param key The key identifying the value to be removed. If nil, this method has no effect. - @param block A block which will be revoked in background queue when finished. + @param block A block which will be invoked in background queue when finished. */ -- (void)removeObjectForKey:(NSString *)key withBlock:(void(^)(NSString *key))block; +- (void)removeObjectForKey:(NSString *)key withBlock:(nullable void(^)(NSString *key))block; /** Empties the cache. @@ -161,10 +183,10 @@ FOUNDATION_EXPORT const unsigned char YYCacheVersionString[]; /** Empties the cache. - This method returns immediately and revoke the passed block in background queue + This method returns immediately and invoke the passed block in background queue when the operation finished. - @param block A block which will be revoked in background queue when finished. + @param block A block which will be invoked in background queue when finished. */ - (void)removeAllObjectsWithBlock:(void(^)(void))block; @@ -173,10 +195,12 @@ FOUNDATION_EXPORT const unsigned char YYCacheVersionString[]; This method returns immediately and executes the clear operation with block in background. @warning You should not send message to this instance in these blocks. - @param progress This block will be revoked during removing, pass nil to ignore. - @param end This block will be revoked at the end, pass nil to ignore. + @param progress This block will be invoked during removing, pass nil to ignore. + @param end This block will be invoked at the end, pass nil to ignore. */ -- (void)removeAllObjectsWithProgressBlock:(void(^)(int removedCount, int totalCount))progress - endBlock:(void(^)(BOOL error))end; +- (void)removeAllObjectsWithProgressBlock:(nullable void(^)(int removedCount, int totalCount))progress + endBlock:(nullable void(^)(BOOL error))end; @end + +NS_ASSUME_NONNULL_END diff --git a/YYWebImage/Cache/YYCache.m b/YYWebImage/Cache/YYCache.m index 61f73bf..e6cdcba 100644 --- a/YYWebImage/Cache/YYCache.m +++ b/YYWebImage/Cache/YYCache.m @@ -16,14 +16,12 @@ @implementation YYCache - (instancetype) init { - self = [super init]; NSLog(@"Use \"initWithName\" or \"initWithPath\" to create YYCache instance."); - return self; + return [self initWithPath:@""]; } - (instancetype)initWithName:(NSString *)name { if (name.length == 0) return nil; - self = [super init]; NSString *cacheFolder = [NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) firstObject]; NSString *path = [cacheFolder stringByAppendingPathComponent:name]; return [self initWithPath:path]; @@ -44,6 +42,14 @@ - (instancetype)initWithPath:(NSString *)path { return self; } ++ (instancetype)cacheWithName:(NSString *)name { + return [[self alloc] initWithName:name]; +} + ++ (instancetype)cacheWithPath:(NSString *)path { + return [[self alloc] initWithPath:path]; +} + - (BOOL)containsObjectForKey:(NSString *)key { return [_memoryCache containsObjectForKey:key] || [_diskCache containsObjectForKey:key]; } @@ -79,7 +85,12 @@ - (void)objectForKey:(NSString *)key withBlock:(void (^)(NSString *key, id object) { + if (object && ![_memoryCache objectForKey:key]) { + [_memoryCache setObject:object forKey:key]; + } + block(key, object); + }]; } } diff --git a/YYWebImage/Cache/YYDiskCache.h b/YYWebImage/Cache/YYDiskCache.h index 0c2bf18..dd193e4 100644 --- a/YYWebImage/Cache/YYDiskCache.h +++ b/YYWebImage/Cache/YYDiskCache.h @@ -11,6 +11,8 @@ #import +NS_ASSUME_NONNULL_BEGIN + /** YYDiskCache is a thread-safe cache that stores key-value pairs backed by SQLite and file system (similar to NSURLCache's disk cache). @@ -23,7 +25,7 @@ * It can automatically decide the storage type (sqlite/file) for each object to get better performance. - You may compile the lastest version of sqlite and ignore the libsqlite3.dylib in + You may compile the latest version of sqlite and ignore the libsqlite3.dylib in iOS system to get 2x~4x speed up. */ @interface YYDiskCache : NSObject @@ -34,7 +36,7 @@ ///============================================================================= /** The name of the cache. Default is nil. */ -@property (copy) NSString *name; +@property (nullable, copy) NSString *name; /** The path of the cache (read-only). */ @property (readonly) NSString *path; @@ -51,31 +53,31 @@ @property (readonly) NSUInteger inlineThreshold; /** - If this block in not nil, then the block will be used to archive object instead + If this block is not nil, then the block will be used to archive object instead of NSKeyedArchiver. You can use this block to support the objects which do not conform to the `NSCoding` protocol. The default value is nil. */ -@property (copy) NSData *(^customArchiveBlock)(id object); +@property (nullable, copy) NSData *(^customArchiveBlock)(id object); /** - If this block in not nil, then the block will be used to unarchive object instead + If this block is not nil, then the block will be used to unarchive object instead of NSKeyedUnarchiver. You can use this block to support the objects which do not conform to the `NSCoding` protocol. The default value is nil. */ -@property (copy) id (^customUnarchiveBlock)(NSData *data); +@property (nullable, copy) id (^customUnarchiveBlock)(NSData *data); /** - When an object needs to be saved as a file, this block will be revoked to generate + When an object needs to be saved as a file, this block will be invoked to generate a file name for a specified key. If the block is nil, the cache use md5(key) as default file name. The default value is nil. */ -@property (copy) NSString *(^customFilenameBlock)(NSString *key); +@property (nullable, copy) NSString *(^customFileNameBlock)(NSString *key); @@ -91,7 +93,7 @@ This is not a strict limit — if the cache goes over the limit, some objects in the cache could be evicted later in background queue. */ -@property (assign) NSUInteger countLimit; +@property NSUInteger countLimit; /** The maximum total cost that the cache can hold before it starts evicting objects. @@ -100,7 +102,7 @@ This is not a strict limit — if the cache goes over the limit, some objects in the cache could be evicted later in background queue. */ -@property (assign) NSUInteger costLimit; +@property NSUInteger costLimit; /** The maximum expiry time of objects in cache. @@ -109,7 +111,7 @@ This is not a strict limit — if an object goes over the limit, the objects could be evicted later in background queue. */ -@property (assign) NSTimeInterval ageLimit; +@property NSTimeInterval ageLimit; /** The minimum free disk space (in bytes) which the cache should kept. @@ -119,7 +121,7 @@ to free some disk space. This is not a strict limit—if the free disk space goes over the limit, the objects could be evicted later in background queue. */ -@property (assign) NSUInteger freeDiskSpaceLimit; +@property NSUInteger freeDiskSpaceLimit; /** The auto trim check time interval in seconds. Default is 60 (1 minute). @@ -127,8 +129,12 @@ @discussion The cache holds an internal timer to check whether the cache reaches its limits, and if the limit is reached, it begins to evict objects. */ -@property (assign) NSTimeInterval autoTrimInterval; +@property NSTimeInterval autoTrimInterval; +/** + Set `YES` to enable error logs for debug. + */ +@property BOOL errorLogsEnabled; #pragma mark - Initializer ///============================================================================= @@ -145,9 +151,10 @@ @return A new cache object, or nil if an error occurs. - @warning Multiple instances with the same path will make the storage unstable. + @warning If the cache instance for the specified path already exists in memory, + this method will return it directly, instead of creating a new instance. */ -- (instancetype)initWithPath:(NSString *)path; +- (nullable instancetype)initWithPath:(NSString *)path; /** The designated initializer. @@ -164,10 +171,11 @@ @return A new cache object, or nil if an error occurs. - @warning Multiple instances with the same path will make the storage unstable. + @warning If the cache instance for the specified path already exists in memory, + this method will return it directly, instead of creating a new instance. */ -- (instancetype)initWithPath:(NSString *)path - inlineThreshold:(NSUInteger)threshold NS_DESIGNATED_INITIALIZER; +- (nullable instancetype)initWithPath:(NSString *)path + inlineThreshold:(NSUInteger)threshold NS_DESIGNATED_INITIALIZER; #pragma mark - Access Methods @@ -186,11 +194,11 @@ /** Returns a boolean value with the block that indicates whether a given key is in cache. - This method returns immediately and revoke the passed block in background queue + This method returns immediately and invoke the passed block in background queue when the operation finished. @param key A string identifying the value. If nil, just return NO. - @param block A block which will be revoked in background queue when finished. + @param block A block which will be invoked in background queue when finished. */ - (void)containsObjectForKey:(NSString *)key withBlock:(void(^)(NSString *key, BOOL contains))block; @@ -201,17 +209,17 @@ @param key A string identifying the value. If nil, just return nil. @return The value associated with key, or nil if no value is associated with key. */ -- (id)objectForKey:(NSString *)key; +- (nullable id)objectForKey:(NSString *)key; /** Returns the value associated with a given key. - This method returns immediately and revoke the passed block in background queue + This method returns immediately and invoke the passed block in background queue when the operation finished. @param key A string identifying the value. If nil, just return nil. - @param block A block which will be revoked in background queue when finished. + @param block A block which will be invoked in background queue when finished. */ -- (void)objectForKey:(NSString *)key withBlock:(void(^)(NSString *key, id object))block; +- (void)objectForKey:(NSString *)key withBlock:(void(^)(NSString *key, id _Nullable object))block; /** Sets the value of the specified key in the cache. @@ -220,17 +228,17 @@ @param object The object to be stored in the cache. If nil, it calls `removeObjectForKey:`. @param key The key with which to associate the value. If nil, this method has no effect. */ -- (void)setObject:(id)object forKey:(NSString *)key; +- (void)setObject:(nullable id)object forKey:(NSString *)key; /** Sets the value of the specified key in the cache. - This method returns immediately and revoke the passed block in background queue + This method returns immediately and invoke the passed block in background queue when the operation finished. @param object The object to be stored in the cache. If nil, it calls `removeObjectForKey:`. - @param block A block which will be revoked in background queue when finished. + @param block A block which will be invoked in background queue when finished. */ -- (void)setObject:(id)object forKey:(NSString *)key withBlock:(void(^)(void))block; +- (void)setObject:(nullable id)object forKey:(NSString *)key withBlock:(void(^)(void))block; /** Removes the value of the specified key in the cache. @@ -242,11 +250,11 @@ /** Removes the value of the specified key in the cache. - This method returns immediately and revoke the passed block in background queue + This method returns immediately and invoke the passed block in background queue when the operation finished. @param key The key identifying the value to be removed. If nil, this method has no effect. - @param block A block which will be revoked in background queue when finished. + @param block A block which will be invoked in background queue when finished. */ - (void)removeObjectForKey:(NSString *)key withBlock:(void(^)(NSString *key))block; @@ -258,10 +266,10 @@ /** Empties the cache. - This method returns immediately and revoke the passed block in background queue + This method returns immediately and invoke the passed block in background queue when the operation finished. - @param block A block which will be revoked in background queue when finished. + @param block A block which will be invoked in background queue when finished. */ - (void)removeAllObjectsWithBlock:(void(^)(void))block; @@ -270,11 +278,11 @@ This method returns immediately and executes the clear operation with block in background. @warning You should not send message to this instance in these blocks. - @param progress This block will be revoked during removing, pass nil to ignore. - @param end This block will be revoked at the end, pass nil to ignore. + @param progress This block will be invoked during removing, pass nil to ignore. + @param end This block will be invoked at the end, pass nil to ignore. */ -- (void)removeAllObjectsWithProgressBlock:(void(^)(int removedCount, int totalCount))progress - endBlock:(void(^)(BOOL error))end; +- (void)removeAllObjectsWithProgressBlock:(nullable void(^)(int removedCount, int totalCount))progress + endBlock:(nullable void(^)(BOOL error))end; /** @@ -287,10 +295,10 @@ /** Get the number of objects in this cache. - This method returns immediately and revoke the passed block in background queue + This method returns immediately and invoke the passed block in background queue when the operation finished. - @param block A block which will be revoked in background queue when finished. + @param block A block which will be invoked in background queue when finished. */ - (void)totalCountWithBlock:(void(^)(NSInteger totalCount))block; @@ -304,10 +312,10 @@ /** Get the total cost (in bytes) of objects in this cache. - This method returns immediately and revoke the passed block in background queue + This method returns immediately and invoke the passed block in background queue when the operation finished. - @param block A block which will be revoked in background queue when finished. + @param block A block which will be invoked in background queue when finished. */ - (void)totalCostWithBlock:(void(^)(NSInteger totalCost))block; @@ -327,11 +335,11 @@ /** Removes objects from the cache use LRU, until the `totalCount` is below the specified value. - This method returns immediately and revoke the passed block in background queue + This method returns immediately and invoke the passed block in background queue when the operation finished. @param count The total count allowed to remain after the cache has been trimmed. - @param block A block which will be revoked in background queue when finished. + @param block A block which will be invoked in background queue when finished. */ - (void)trimToCount:(NSUInteger)count withBlock:(void(^)(void))block; @@ -345,11 +353,11 @@ /** Removes objects from the cache use LRU, until the `totalCost` is below the specified value. - This method returns immediately and revoke the passed block in background queue + This method returns immediately and invoke the passed block in background queue when the operation finished. @param cost The total cost allowed to remain after the cache has been trimmed. - @param block A block which will be revoked in background queue when finished. + @param block A block which will be invoked in background queue when finished. */ - (void)trimToCost:(NSUInteger)cost withBlock:(void(^)(void))block; @@ -363,11 +371,11 @@ /** Removes objects from the cache use LRU, until all expiry objects removed by the specified value. - This method returns immediately and revoke the passed block in background queue + This method returns immediately and invoke the passed block in background queue when the operation finished. @param age The maximum age of the object. - @param block A block which will be revoked in background queue when finished. + @param block A block which will be invoked in background queue when finished. */ - (void)trimToAge:(NSTimeInterval)age withBlock:(void(^)(void))block; @@ -385,7 +393,7 @@ @param object An object. @return The extended data. */ -+ (NSData *)getExtendedDataFromObject:(id)object; ++ (nullable NSData *)getExtendedDataFromObject:(id)object; /** Set extended data to an object. @@ -397,6 +405,8 @@ @param extendedData The extended data (pass nil to remove). @param object The object. */ -+ (void)setExtendedData:(NSData *)extendedData toObject:(id)object; ++ (void)setExtendedData:(nullable NSData *)extendedData toObject:(id)object; @end + +NS_ASSUME_NONNULL_END diff --git a/YYWebImage/Cache/YYDiskCache.m b/YYWebImage/Cache/YYDiskCache.m index 437f60c..735cc5d 100644 --- a/YYWebImage/Cache/YYDiskCache.m +++ b/YYWebImage/Cache/YYDiskCache.m @@ -11,12 +11,13 @@ #import "YYDiskCache.h" #import "YYKVStorage.h" +#import #import #import #import -#define Lock() dispatch_semaphore_wait(_lock, DISPATCH_TIME_FOREVER) -#define Unlock() dispatch_semaphore_signal(_lock) +#define Lock() dispatch_semaphore_wait(self->_lock, DISPATCH_TIME_FOREVER) +#define Unlock() dispatch_semaphore_signal(self->_lock) static const int extended_data_key; @@ -45,6 +46,36 @@ static int64_t _YYDiskSpaceFree() { ]; } +/// weak reference for all instances +static NSMapTable *_globalInstances; +static dispatch_semaphore_t _globalInstancesLock; + +static void _YYDiskCacheInitGlobal() { + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + _globalInstancesLock = dispatch_semaphore_create(1); + _globalInstances = [[NSMapTable alloc] initWithKeyOptions:NSPointerFunctionsStrongMemory valueOptions:NSPointerFunctionsWeakMemory capacity:0]; + }); +} + +static YYDiskCache *_YYDiskCacheGetGlobal(NSString *path) { + if (path.length == 0) return nil; + _YYDiskCacheInitGlobal(); + dispatch_semaphore_wait(_globalInstancesLock, DISPATCH_TIME_FOREVER); + id cache = [_globalInstances objectForKey:path]; + dispatch_semaphore_signal(_globalInstancesLock); + return cache; +} + +static void _YYDiskCacheSetGlobal(YYDiskCache *cache) { + if (cache.path.length == 0) return; + _YYDiskCacheInitGlobal(); + dispatch_semaphore_wait(_globalInstancesLock, DISPATCH_TIME_FOREVER); + [_globalInstances setObject:cache forKey:cache.path]; + dispatch_semaphore_signal(_globalInstancesLock); +} + + @implementation YYDiskCache { YYKVStorage *_kv; @@ -67,12 +98,12 @@ - (void)_trimInBackground { dispatch_async(_queue, ^{ __strong typeof(_self) self = _self; if (!self) return; - dispatch_semaphore_wait(self->_lock, DISPATCH_TIME_FOREVER); - [self _trimToCost:self.countLimit]; + Lock(); + [self _trimToCost:self.costLimit]; [self _trimToCount:self.countLimit]; [self _trimToAge:self.ageLimit]; [self _trimToFreeDiskSpace:self.freeDiskSpaceLimit]; - dispatch_semaphore_signal(self->_lock); + Unlock(); }); } @@ -114,16 +145,26 @@ - (void)_trimToFreeDiskSpace:(NSUInteger)targetFreeDiskSpace { - (NSString *)_filenameForKey:(NSString *)key { NSString *filename = nil; - if (_customFilenameBlock) filename = _customFilenameBlock(key); + if (_customFileNameBlock) filename = _customFileNameBlock(key); if (!filename) filename = _YYNSStringMD5(key); return filename; } +- (void)_appWillBeTerminated { + Lock(); + _kv = nil; + Unlock(); +} + #pragma mark - public +- (void)dealloc { + [[NSNotificationCenter defaultCenter] removeObserver:self name:UIApplicationWillTerminateNotification object:nil]; +} + - (instancetype)init { @throw [NSException exceptionWithName:@"YYDiskCache init error" reason:@"YYDiskCache must be initialized with a path. Use 'initWithPath:' or 'initWithPath:inlineThreshold:' instead." userInfo:nil]; - return [self initWithPath:nil inlineThreshold:0]; + return [self initWithPath:@"" inlineThreshold:0]; } - (instancetype)initWithPath:(NSString *)path { @@ -135,6 +176,9 @@ - (instancetype)initWithPath:(NSString *)path self = [super init]; if (!self) return nil; + YYDiskCache *globalCache = _YYDiskCacheGetGlobal(path); + if (globalCache) return globalCache; + YYKVStorageType type; if (threshold == 0) { type = YYKVStorageTypeFile; @@ -159,6 +203,9 @@ - (instancetype)initWithPath:(NSString *)path _autoTrimInterval = 60; [self _trimRecursively]; + _YYDiskCacheSetGlobal(self); + + [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(_appWillBeTerminated) name:UIApplicationWillTerminateNotification object:nil]; return self; } @@ -295,9 +342,9 @@ - (void)removeAllObjectsWithProgressBlock:(void(^)(int removedCount, int totalCo if (end) end(YES); return; } - dispatch_semaphore_wait(self->_lock, DISPATCH_TIME_FOREVER); + Lock(); [_kv removeAllItemsWithProgressBlock:progress endBlock:end]; - dispatch_semaphore_signal(self->_lock); + Unlock(); }); } @@ -395,4 +442,17 @@ - (NSString *)description { else return [NSString stringWithFormat:@"<%@: %p> (%@)", self.class, self, _path]; } +- (BOOL)errorLogsEnabled { + Lock(); + BOOL enabled = _kv.errorLogsEnabled; + Unlock(); + return enabled; +} + +- (void)setErrorLogsEnabled:(BOOL)errorLogsEnabled { + Lock(); + _kv.errorLogsEnabled = errorLogsEnabled; + Unlock(); +} + @end diff --git a/YYWebImage/Cache/YYKVStorage.h b/YYWebImage/Cache/YYKVStorage.h index 9194968..939a6e4 100644 --- a/YYWebImage/Cache/YYKVStorage.h +++ b/YYWebImage/Cache/YYKVStorage.h @@ -11,17 +11,20 @@ #import +NS_ASSUME_NONNULL_BEGIN + /** YYKVStorageItem is used by `YYKVStorage` to store key-value pair and meta data. + Typically, you should not use this class directly. */ @interface YYKVStorageItem : NSObject -@property (nonatomic, strong) NSString *key; ///< key -@property (nonatomic, strong) NSData *value; ///< value -@property (nonatomic, strong) NSString *filename; ///< filename (nil if inline) -@property (nonatomic, assign) int size; ///< value's size in bytes -@property (nonatomic, assign) int modTime; ///< modification unix timestamp -@property (nonatomic, assign) int accessTime; ///< last access unix timestamp -@property (nonatomic, strong) NSData *extendedData; ///< extended data (nil if no extended data) +@property (nonatomic, strong) NSString *key; ///< key +@property (nonatomic, strong) NSData *value; ///< value +@property (nullable, nonatomic, strong) NSString *filename; ///< filename (nil if inline) +@property (nonatomic) int size; ///< value's size in bytes +@property (nonatomic) int modTime; ///< modification unix timestamp +@property (nonatomic) int accessTime; ///< last access unix timestamp +@property (nullable, nonatomic, strong) NSData *extendedData; ///< extended data (nil if no extended data) @end /** @@ -56,12 +59,13 @@ typedef NS_ENUM(NSUInteger, YYKVStorageType) { /** YYKVStorage is a key-value storage based on sqlite and file system. + Typically, you should not use this class directly. @discussion The designated initializer for YYKVStorage is `initWithPath:type:`. After initialized, a directory is created based on the `path` to hold key-value data. Once initialized you should not read or write this directory without the instance. - You may compile the lastest version of sqlite and ignore the libsqlite3.dylib in + You may compile the latest version of sqlite and ignore the libsqlite3.dylib in iOS system to get 2x~4x speed up. @warning The instance of this class is *NOT* thread safe, you need to make sure @@ -78,7 +82,7 @@ typedef NS_ENUM(NSUInteger, YYKVStorageType) { @property (nonatomic, readonly) NSString *path; ///< The path of this storage. @property (nonatomic, readonly) YYKVStorageType type; ///< The type of this storage. -@property (nonatomic, assign) BOOL errorLogsEnabled; ///< Set `YES` to enable error logs for debug. +@property (nonatomic) BOOL errorLogsEnabled; ///< Set `YES` to enable error logs for debug. #pragma mark - Initializer ///============================================================================= @@ -98,7 +102,7 @@ typedef NS_ENUM(NSUInteger, YYKVStorageType) { @return A new storage object, or nil if an error occurs. @warning Multiple instances with the same path will make the storage unstable. */ -- (instancetype)initWithPath:(NSString *)path type:(YYKVStorageType)type NS_DESIGNATED_INITIALIZER; +- (nullable instancetype)initWithPath:(NSString *)path type:(YYKVStorageType)type NS_DESIGNATED_INITIALIZER; #pragma mark - Save Items @@ -153,8 +157,8 @@ typedef NS_ENUM(NSUInteger, YYKVStorageType) { */ - (BOOL)saveItemWithKey:(NSString *)key value:(NSData *)value - filename:(NSString *)filename - extendedData:(NSData *)extendedData; + filename:(nullable NSString *)filename + extendedData:(nullable NSData *)extendedData; #pragma mark - Remove Items ///============================================================================= @@ -176,7 +180,7 @@ typedef NS_ENUM(NSUInteger, YYKVStorageType) { @return Whether succeed. */ -- (BOOL)removeItemForKeys:(NSArray *)keys; +- (BOOL)removeItemForKeys:(NSArray *)keys; /** Remove all items which `value` is larger than a specified size. @@ -227,11 +231,11 @@ typedef NS_ENUM(NSUInteger, YYKVStorageType) { Remove all items. @warning You should not send message to this instance in these blocks. - @param progress This block will be revoked during removing, pass nil to ignore. - @param end This block will be revoked at the end, pass nil to ignore. + @param progress This block will be invoked during removing, pass nil to ignore. + @param end This block will be invoked at the end, pass nil to ignore. */ -- (void)removeAllItemsWithProgressBlock:(void(^)(int removedCount, int totalCount))progress - endBlock:(void(^)(BOOL error))end; +- (void)removeAllItemsWithProgressBlock:(nullable void(^)(int removedCount, int totalCount))progress + endBlock:(nullable void(^)(BOOL error))end; #pragma mark - Get Items @@ -245,7 +249,7 @@ typedef NS_ENUM(NSUInteger, YYKVStorageType) { @param key A specified key. @return Item for the key, or nil if not exists / error occurs. */ -- (YYKVStorageItem *)getItemForKey:(NSString *)key; +- (nullable YYKVStorageItem *)getItemForKey:(NSString *)key; /** Get item information with a specified key. @@ -254,7 +258,7 @@ typedef NS_ENUM(NSUInteger, YYKVStorageType) { @param key A specified key. @return Item information for the key, or nil if not exists / error occurs. */ -- (YYKVStorageItem *)getItemInfoForKey:(NSString *)key; +- (nullable YYKVStorageItem *)getItemInfoForKey:(NSString *)key; /** Get item value with a specified key. @@ -262,7 +266,7 @@ typedef NS_ENUM(NSUInteger, YYKVStorageType) { @param key A specified key. @return Item's value, or nil if not exists / error occurs. */ -- (NSData *)getItemValueForKey:(NSString *)key; +- (nullable NSData *)getItemValueForKey:(NSString *)key; /** Get items with an array of keys. @@ -270,7 +274,7 @@ typedef NS_ENUM(NSUInteger, YYKVStorageType) { @param keys An array of specified keys. @return An array of `YYKVStorageItem`, or nil if not exists / error occurs. */ -- (NSArray *)getItemForKeys:(NSArray *)keys; +- (nullable NSArray *)getItemForKeys:(NSArray *)keys; /** Get item infomartions with an array of keys. @@ -279,7 +283,7 @@ typedef NS_ENUM(NSUInteger, YYKVStorageType) { @param keys An array of specified keys. @return An array of `YYKVStorageItem`, or nil if not exists / error occurs. */ -- (NSArray *)getItemInfoForKeys:(NSArray *)keys; +- (nullable NSArray *)getItemInfoForKeys:(NSArray *)keys; /** Get items value with an array of keys. @@ -288,7 +292,7 @@ typedef NS_ENUM(NSUInteger, YYKVStorageType) { @return A dictionary which key is 'key' and value is 'value', or nil if not exists / error occurs. */ -- (NSDictionary *)getItemValueForKeys:(NSArray *)keys; +- (nullable NSDictionary *)getItemValueForKeys:(NSArray *)keys; #pragma mark - Get Storage Status ///============================================================================= @@ -317,3 +321,5 @@ typedef NS_ENUM(NSUInteger, YYKVStorageType) { - (int)getItemsSize; @end + +NS_ASSUME_NONNULL_END diff --git a/YYWebImage/Cache/YYKVStorage.m b/YYWebImage/Cache/YYKVStorage.m index 0e507f4..501dfdd 100644 --- a/YYWebImage/Cache/YYKVStorage.m +++ b/YYWebImage/Cache/YYKVStorage.m @@ -11,7 +11,6 @@ #import "YYKVStorage.h" #import -#import #import #if __has_include() @@ -20,6 +19,9 @@ #import "sqlite3.h" #endif + +static const NSUInteger kMaxErrorRetryCount = 8; +static const NSTimeInterval kMinRetryTimeInterval = 2.0; static const int kPathLengthMax = PATH_MAX - 64; static NSString *const kDBFileName = @"manifest.sqlite"; static NSString *const kDBShmFileName = @"manifest.sqlite-shm"; @@ -27,7 +29,19 @@ static NSString *const kDataDirectoryName = @"data"; static NSString *const kTrashDirectoryName = @"trash"; + /* + File: + /path/ + /manifest.sqlite + /manifest.sqlite-shm + /manifest.sqlite-wal + /data/ + /e10adc3949ba59abbe56e057f20f883e + /e10adc3949ba59abbe56e057f20f883e + /trash/ + /unused_file_or_folder + SQL: create table if not exists manifest ( key text, @@ -42,6 +56,22 @@ primary key(key) create index if not exists last_access_time_idx on manifest(last_access_time); */ +/// Returns nil in App Extension. +static UIApplication *_YYSharedApplication() { + static BOOL isAppExtension = NO; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + Class cls = NSClassFromString(@"UIApplication"); + if(!cls || ![cls respondsToSelector:@selector(sharedApplication)]) isAppExtension = YES; + if ([[[NSBundle mainBundle] bundlePath] hasSuffix:@".appex"]) isAppExtension = YES; + }); +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wundeclared-selector" + return isAppExtension ? nil : [UIApplication performSelector:@selector(sharedApplication)]; +#pragma clang diagnostic pop +} + + @implementation YYKVStorageItem @end @@ -55,54 +85,40 @@ @implementation YYKVStorage { sqlite3 *_db; CFMutableDictionaryRef _dbStmtCache; - - BOOL _invalidated; ///< If YES, then the db should not open again, all read/write should be ignored. - BOOL _dbIsClosing; ///< If YES, then the db is during closing. - OSSpinLock _dbStateLock; + NSTimeInterval _dbLastOpenErrorTime; + NSUInteger _dbOpenErrorCount; } #pragma mark - db - (BOOL)_dbOpen { - BOOL shouldOpen = YES; - OSSpinLockLock(&_dbStateLock); - if (_invalidated) { - shouldOpen = NO; - } else if (_dbIsClosing) { - shouldOpen = NO; - } else if (_db){ - shouldOpen = NO; - } - OSSpinLockUnlock(&_dbStateLock); - if (!shouldOpen) return YES; + if (_db) return YES; int result = sqlite3_open(_dbPath.UTF8String, &_db); if (result == SQLITE_OK) { - CFDictionaryKeyCallBacks keyCallbacks = kCFTypeDictionaryKeyCallBacks; + CFDictionaryKeyCallBacks keyCallbacks = kCFCopyStringDictionaryKeyCallBacks; CFDictionaryValueCallBacks valueCallbacks = {0}; _dbStmtCache = CFDictionaryCreateMutable(CFAllocatorGetDefault(), 0, &keyCallbacks, &valueCallbacks); + _dbLastOpenErrorTime = 0; + _dbOpenErrorCount = 0; return YES; } else { - NSLog(@"%s line:%d sqlite open failed (%d).", __FUNCTION__, __LINE__, result); + _db = NULL; + if (_dbStmtCache) CFRelease(_dbStmtCache); + _dbStmtCache = NULL; + _dbLastOpenErrorTime = CACurrentMediaTime(); + _dbOpenErrorCount++; + + if (_errorLogsEnabled) { + NSLog(@"%s line:%d sqlite open failed (%d).", __FUNCTION__, __LINE__, result); + } return NO; } } - (BOOL)_dbClose { - BOOL needClose = YES; - OSSpinLockLock(&_dbStateLock); - if (!_db) { - needClose = NO; - } else if (_invalidated) { - needClose = NO; - } else if (_dbIsClosing) { - needClose = NO; - } else { - _dbIsClosing = YES; - } - OSSpinLockUnlock(&_dbStateLock); - if (!needClose) return YES; + if (!_db) return YES; int result = 0; BOOL retry = NO; @@ -124,20 +140,25 @@ - (BOOL)_dbClose { } } } else if (result != SQLITE_OK) { - NSLog(@"%s line:%d sqlite close failed (%d).", __FUNCTION__, __LINE__, result); + if (_errorLogsEnabled) { + NSLog(@"%s line:%d sqlite close failed (%d).", __FUNCTION__, __LINE__, result); + } } } while (retry); _db = NULL; - - OSSpinLockLock(&_dbStateLock); - _dbIsClosing = NO; - OSSpinLockUnlock(&_dbStateLock); - return YES; } -- (BOOL)_dbIsReady { - return (_db && !_dbIsClosing && !_invalidated); +- (BOOL)_dbCheck { + if (!_db) { + if (_dbOpenErrorCount < kMaxErrorRetryCount && + CACurrentMediaTime() - _dbLastOpenErrorTime > kMinRetryTimeInterval) { + return [self _dbOpen] && [self _dbInitialize]; + } else { + return NO; + } + } + return YES; } - (BOOL)_dbInitialize { @@ -145,9 +166,15 @@ - (BOOL)_dbInitialize { return [self _dbExecute:sql]; } +- (void)_dbCheckpoint { + if (![self _dbCheck]) return; + // Cause a checkpoint to occur, merge `sqlite-wal` file to `sqlite` file. + sqlite3_wal_checkpoint(_db, NULL); +} + - (BOOL)_dbExecute:(NSString *)sql { if (sql.length == 0) return NO; - if (![self _dbIsReady]) return NO; + if (![self _dbCheck]) return NO; char *error = NULL; int result = sqlite3_exec(_db, sql.UTF8String, NULL, NULL, &error); @@ -160,7 +187,7 @@ - (BOOL)_dbExecute:(NSString *)sql { } - (sqlite3_stmt *)_dbPrepareStmt:(NSString *)sql { - if (![self _dbIsReady]) return NULL; + if (![self _dbCheck] || sql.length == 0 || !_dbStmtCache) return NULL; sqlite3_stmt *stmt = (sqlite3_stmt *)CFDictionaryGetValue(_dbStmtCache, (__bridge const void *)(sql)); if (!stmt) { int result = sqlite3_prepare_v2(_db, sql.UTF8String, -1, &stmt, NULL); @@ -175,6 +202,24 @@ - (sqlite3_stmt *)_dbPrepareStmt:(NSString *)sql { return stmt; } +- (NSString *)_dbJoinedKeys:(NSArray *)keys { + NSMutableString *string = [NSMutableString new]; + for (NSUInteger i = 0,max = keys.count; i < max; i++) { + [string appendString:@"?"]; + if (i + 1 != max) { + [string appendString:@","]; + } + } + return string; +} + +- (void)_dbBindJoinedKeys:(NSArray *)keys stmt:(sqlite3_stmt *)stmt fromIndex:(int)index{ + for (int i = 0, max = (int)keys.count; i < max; i++) { + NSString *key = keys[i]; + sqlite3_bind_text(stmt, index + i, key.UTF8String, -1, NULL); + } +} + - (BOOL)_dbSaveWithKey:(NSString *)key value:(NSData *)value fileName:(NSString *)fileName extendedData:(NSData *)extendedData { NSString *sql = @"insert or replace into manifest (key, filename, size, inline_data, modification_time, last_access_time, extended_data) values (?1, ?2, ?3, ?4, ?5, ?6, ?7);"; sqlite3_stmt *stmt = [self _dbPrepareStmt:sql]; @@ -216,9 +261,9 @@ - (BOOL)_dbUpdateAccessTimeWithKey:(NSString *)key { } - (BOOL)_dbUpdateAccessTimeWithKeys:(NSArray *)keys { - if (![self _dbIsReady]) return NO; + if (![self _dbCheck]) return NO; int t = (int)time(NULL); - NSString *sql = [NSString stringWithFormat:@"update manifest set last_access_time = %d where key in (%@);", t, [keys componentsJoinedByString:@","]]; + NSString *sql = [NSString stringWithFormat:@"update manifest set last_access_time = %d where key in (%@);", t, [self _dbJoinedKeys:keys]]; sqlite3_stmt *stmt = NULL; int result = sqlite3_prepare_v2(_db, sql.UTF8String, -1, &stmt, NULL); @@ -227,6 +272,7 @@ - (BOOL)_dbUpdateAccessTimeWithKeys:(NSArray *)keys { return NO; } + [self _dbBindJoinedKeys:keys stmt:stmt fromIndex:1]; result = sqlite3_step(stmt); sqlite3_finalize(stmt); if (result != SQLITE_DONE) { @@ -251,8 +297,8 @@ - (BOOL)_dbDeleteItemWithKey:(NSString *)key { } - (BOOL)_dbDeleteItemWithKeys:(NSArray *)keys { - if (![self _dbIsReady]) return NO; - NSString *sql = [NSString stringWithFormat:@"delete from manifest where key in (%@);", [keys componentsJoinedByString:@","]]; + if (![self _dbCheck]) return NO; + NSString *sql = [NSString stringWithFormat:@"delete from manifest where key in (%@);", [self _dbJoinedKeys:keys]]; sqlite3_stmt *stmt = NULL; int result = sqlite3_prepare_v2(_db, sql.UTF8String, -1, &stmt, NULL); if (result != SQLITE_OK) { @@ -260,6 +306,7 @@ - (BOOL)_dbDeleteItemWithKeys:(NSArray *)keys { return NO; } + [self _dbBindJoinedKeys:keys stmt:stmt fromIndex:1]; result = sqlite3_step(stmt); sqlite3_finalize(stmt); if (result == SQLITE_ERROR) { @@ -337,12 +384,12 @@ - (YYKVStorageItem *)_dbGetItemWithKey:(NSString *)key excludeInlineData:(BOOL)e } - (NSMutableArray *)_dbGetItemWithKeys:(NSArray *)keys excludeInlineData:(BOOL)excludeInlineData { - if (![self _dbIsReady]) return nil; + if (![self _dbCheck]) return nil; NSString *sql; if (excludeInlineData) { - sql = [NSString stringWithFormat:@"select key, filename, size, modification_time, last_access_time, extended_data from manifest where key in (%@);", [keys componentsJoinedByString:@","]]; + sql = [NSString stringWithFormat:@"select key, filename, size, modification_time, last_access_time, extended_data from manifest where key in (%@);", [self _dbJoinedKeys:keys]]; } else { - sql = [NSString stringWithFormat:@"select key, filename, size, inline_data, modification_time, last_access_time, extended_data from manifest where key in (%@)", [keys componentsJoinedByString:@","]]; + sql = [NSString stringWithFormat:@"select key, filename, size, inline_data, modification_time, last_access_time, extended_data from manifest where key in (%@)", [self _dbJoinedKeys:keys]]; } sqlite3_stmt *stmt = NULL; @@ -352,6 +399,7 @@ - (NSMutableArray *)_dbGetItemWithKeys:(NSArray *)keys excludeInlineData:(BOOL)e return nil; } + [self _dbBindJoinedKeys:keys stmt:stmt fromIndex:1]; NSMutableArray *items = [NSMutableArray new]; do { result = sqlite3_step(stmt); @@ -410,8 +458,8 @@ - (NSString *)_dbGetFilenameWithKey:(NSString *)key { } - (NSMutableArray *)_dbGetFilenameWithKeys:(NSArray *)keys { - if (![self _dbIsReady]) return nil; - NSString *sql = [NSString stringWithFormat:@"select filename from manifest where key in (%@);", [keys componentsJoinedByString:@","]]; + if (![self _dbCheck]) return nil; + NSString *sql = [NSString stringWithFormat:@"select filename from manifest where key in (%@);", [self _dbJoinedKeys:keys]]; sqlite3_stmt *stmt = NULL; int result = sqlite3_prepare_v2(_db, sql.UTF8String, -1, &stmt, NULL); if (result != SQLITE_OK) { @@ -419,6 +467,7 @@ - (NSMutableArray *)_dbGetFilenameWithKeys:(NSArray *)keys { return nil; } + [self _dbBindJoinedKeys:keys stmt:stmt fromIndex:1]; NSMutableArray *filenames = [NSMutableArray new]; do { result = sqlite3_step(stmt); @@ -492,8 +541,8 @@ - (NSMutableArray *)_dbGetFilenamesWithTimeEarlierThan:(int)time { return filenames; } -- (NSMutableArray *)_dbGetItemSizeInfoOrderByTimeDescWithLimit:(int)count { - NSString *sql = @"select key, filename, size from manifest order by last_access_time desc limit ?1;"; +- (NSMutableArray *)_dbGetItemSizeInfoOrderByTimeAscWithLimit:(int)count { + NSString *sql = @"select key, filename, size from manifest order by last_access_time asc limit ?1;"; sqlite3_stmt *stmt = [self _dbPrepareStmt:sql]; if (!stmt) return nil; sqlite3_bind_int(stmt, 1, count); @@ -505,11 +554,14 @@ - (NSMutableArray *)_dbGetItemSizeInfoOrderByTimeDescWithLimit:(int)count { char *key = (char *)sqlite3_column_text(stmt, 0); char *filename = (char *)sqlite3_column_text(stmt, 1); int size = sqlite3_column_int(stmt, 2); - YYKVStorageItem *item = [YYKVStorageItem new]; - item.key = key ? [NSString stringWithUTF8String:key] : nil; - item.filename = filename ? [NSString stringWithUTF8String:filename] : nil; - item.size = size; - [items addObject:item]; + NSString *keyStr = key ? [NSString stringWithUTF8String:key] : nil; + if (keyStr) { + YYKVStorageItem *item = [YYKVStorageItem new]; + item.key = key ? [NSString stringWithUTF8String:key] : nil; + item.filename = filename ? [NSString stringWithUTF8String:filename] : nil; + item.size = size; + [items addObject:item]; + } } else if (result == SQLITE_DONE) { break; } else { @@ -562,26 +614,22 @@ - (int)_dbGetTotalItemCount { #pragma mark - file - (BOOL)_fileWriteWithName:(NSString *)filename data:(NSData *)data { - if (_invalidated) return NO; NSString *path = [_dataPath stringByAppendingPathComponent:filename]; return [data writeToFile:path atomically:NO]; } - (NSData *)_fileReadWithName:(NSString *)filename { - if (_invalidated) return nil; NSString *path = [_dataPath stringByAppendingPathComponent:filename]; NSData *data = [NSData dataWithContentsOfFile:path]; return data; } - (BOOL)_fileDeleteWithName:(NSString *)filename { - if (_invalidated) return NO; NSString *path = [_dataPath stringByAppendingPathComponent:filename]; return [[NSFileManager defaultManager] removeItemAtPath:path error:NULL]; } - (BOOL)_fileMoveAllToTrash { - if (_invalidated) return NO; CFUUIDRef uuidRef = CFUUIDCreate(NULL); CFStringRef uuid = CFUUIDCreateString(NULL, uuidRef); CFRelease(uuidRef); @@ -595,7 +643,6 @@ - (BOOL)_fileMoveAllToTrash { } - (void)_fileEmptyTrashInBackground { - if (_invalidated) return; NSString *trashPath = _trashPath; dispatch_queue_t queue = _trashQueue; dispatch_async(queue, ^{ @@ -623,17 +670,11 @@ - (void)_reset { [self _fileEmptyTrashInBackground]; } -- (void)_appWillBeTerminated { - OSSpinLockLock(&_dbStateLock); - _invalidated = YES; - OSSpinLockUnlock(&_dbStateLock); -} - #pragma mark - public - (instancetype)init { @throw [NSException exceptionWithName:@"YYKVStorage init error" reason:@"Please use the designated initializer and pass the 'path' and 'type'." userInfo:nil]; - return [self initWithPath:nil type:YYKVStorageTypeFile]; + return [self initWithPath:@"" type:YYKVStorageTypeFile]; } - (instancetype)initWithPath:(NSString *)path type:(YYKVStorageType)type { @@ -653,7 +694,6 @@ - (instancetype)initWithPath:(NSString *)path type:(YYKVStorageType)type { _trashPath = [path stringByAppendingPathComponent:kTrashDirectoryName]; _trashQueue = dispatch_queue_create("com.ibireme.cache.disk.trash", DISPATCH_QUEUE_SERIAL); _dbPath = [path stringByAppendingPathComponent:kDBFileName]; - _dbStateLock = OS_SPINLOCK_INIT; _errorLogsEnabled = YES; NSError *error = nil; if (![[NSFileManager defaultManager] createDirectoryAtPath:path @@ -679,17 +719,19 @@ - (instancetype)initWithPath:(NSString *)path type:(YYKVStorageType)type { if (![self _dbOpen] || ![self _dbInitialize]) { [self _dbClose]; NSLog(@"YYKVStorage init error: fail to open sqlite db."); + return nil; } - return nil; } [self _fileEmptyTrashInBackground]; // empty the trash if failed at last time - [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(_appWillBeTerminated) name:UIApplicationWillTerminateNotification object:nil]; return self; } - (void)dealloc { - [[NSNotificationCenter defaultCenter] removeObserver:self name:UIApplicationWillTerminateNotification object:nil]; + UIBackgroundTaskIdentifier taskID = [_YYSharedApplication() beginBackgroundTaskWithExpirationHandler:^{}]; [self _dbClose]; + if (taskID != UIBackgroundTaskInvalid) { + [_YYSharedApplication() endBackgroundTask:taskID]; + } } - (BOOL)saveItem:(YYKVStorageItem *)item { @@ -768,7 +810,10 @@ - (BOOL)removeItemsLargerThanSize:(int)size { switch (_type) { case YYKVStorageTypeSQLite: { - return [self _dbDeleteItemsWithSizeLargerThan:size]; + if ([self _dbDeleteItemsWithSizeLargerThan:size]) { + [self _dbCheckpoint]; + return YES; + } } break; case YYKVStorageTypeFile: case YYKVStorageTypeMixed: { @@ -776,7 +821,10 @@ - (BOOL)removeItemsLargerThanSize:(int)size { for (NSString *name in filenames) { [self _fileDeleteWithName:name]; } - return [self _dbDeleteItemsWithSizeLargerThan:size]; + if ([self _dbDeleteItemsWithSizeLargerThan:size]) { + [self _dbCheckpoint]; + return YES; + } } break; } return NO; @@ -788,7 +836,10 @@ - (BOOL)removeItemsEarlierThanTime:(int)time { switch (_type) { case YYKVStorageTypeSQLite: { - return [self _dbDeleteItemsWithTimeEarlierThan:time]; + if ([self _dbDeleteItemsWithTimeEarlierThan:time]) { + [self _dbCheckpoint]; + return YES; + } } break; case YYKVStorageTypeFile: case YYKVStorageTypeMixed: { @@ -796,7 +847,10 @@ - (BOOL)removeItemsEarlierThanTime:(int)time { for (NSString *name in filenames) { [self _fileDeleteWithName:name]; } - return [self _dbDeleteItemsWithTimeEarlierThan:time]; + if ([self _dbDeleteItemsWithTimeEarlierThan:time]) { + [self _dbCheckpoint]; + return YES; + } } break; } return NO; @@ -814,7 +868,7 @@ - (BOOL)removeItemsToFitSize:(int)maxSize { BOOL suc = NO; do { int perCount = 16; - items = [self _dbGetItemSizeInfoOrderByTimeDescWithLimit:perCount]; + items = [self _dbGetItemSizeInfoOrderByTimeAscWithLimit:perCount]; for (YYKVStorageItem *item in items) { if (total > maxSize) { if (item.filename) { @@ -828,6 +882,7 @@ - (BOOL)removeItemsToFitSize:(int)maxSize { if (!suc) break; } } while (total > maxSize && items.count > 0 && suc); + if (suc) [self _dbCheckpoint]; return suc; } @@ -843,7 +898,7 @@ - (BOOL)removeItemsToFitCount:(int)maxCount { BOOL suc = NO; do { int perCount = 16; - items = [self _dbGetItemSizeInfoOrderByTimeDescWithLimit:perCount]; + items = [self _dbGetItemSizeInfoOrderByTimeAscWithLimit:perCount]; for (YYKVStorageItem *item in items) { if (total > maxCount) { if (item.filename) { @@ -857,6 +912,7 @@ - (BOOL)removeItemsToFitCount:(int)maxCount { if (!suc) break; } } while (total > maxCount && items.count > 0 && suc); + if (suc) [self _dbCheckpoint]; return suc; } @@ -880,7 +936,7 @@ - (void)removeAllItemsWithProgressBlock:(void(^)(int removedCount, int totalCoun NSArray *items = nil; BOOL suc = NO; do { - items = [self _dbGetItemSizeInfoOrderByTimeDescWithLimit:perCount]; + items = [self _dbGetItemSizeInfoOrderByTimeAscWithLimit:perCount]; for (YYKVStorageItem *item in items) { if (left > 0) { if (item.filename) { @@ -895,6 +951,7 @@ - (void)removeAllItemsWithProgressBlock:(void(^)(int removedCount, int totalCoun } if (progress) progress(total - left, total); } while (left > 0 && items.count > 0 && suc); + if (suc) [self _dbCheckpoint]; if (end) end(!suc); } } diff --git a/YYWebImage/Cache/YYMemoryCache.h b/YYWebImage/Cache/YYMemoryCache.h index a4c62c8..ded8440 100644 --- a/YYWebImage/Cache/YYMemoryCache.h +++ b/YYWebImage/Cache/YYMemoryCache.h @@ -11,6 +11,8 @@ #import +NS_ASSUME_NONNULL_BEGIN + /** YYMemoryCache is a fast in-memory cache that stores key-value pairs. In contrast to NSDictionary, keys are retained and not copied. @@ -18,7 +20,7 @@ YYMemoryCache objects differ from NSCache in a few ways: - * It uses LRU (least-recently-used) to remove objects; NSCache's eviction method + * It uses LRU (least-recently-used) to remove objects; NSCache's eviction method is non-deterministic. * It can be controlled by cost, count and age; NSCache's limits are imprecise. * It can be configured to automatically evict objects when receive memory @@ -34,7 +36,7 @@ ///============================================================================= /** The name of the cache. Default is nil. */ -@property (copy) NSString *name; +@property (nullable, copy) NSString *name; /** The number of objects in the cache (read-only) */ @property (readonly) NSUInteger totalCount; @@ -55,7 +57,7 @@ This is not a strict limit—if the cache goes over the limit, some objects in the cache could be evicted later in backgound thread. */ -@property (assign) NSUInteger countLimit; +@property NSUInteger countLimit; /** The maximum total cost that the cache can hold before it starts evicting objects. @@ -64,7 +66,7 @@ This is not a strict limit—if the cache goes over the limit, some objects in the cache could be evicted later in backgound thread. */ -@property (assign) NSUInteger costLimit; +@property NSUInteger costLimit; /** The maximum expiry time of objects in cache. @@ -73,7 +75,7 @@ This is not a strict limit—if an object goes over the limit, the object could be evicted later in backgound thread. */ -@property (assign) NSTimeInterval ageLimit; +@property NSTimeInterval ageLimit; /** The auto trim check time interval in seconds. Default is 5.0. @@ -81,31 +83,31 @@ @discussion The cache holds an internal timer to check whether the cache reaches its limits, and if the limit is reached, it begins to evict objects. */ -@property (assign) NSTimeInterval autoTrimInterval; +@property NSTimeInterval autoTrimInterval; /** If `YES`, the cache will remove all objects when the app receives a memory warning. The default value is `YES`. */ -@property (assign) BOOL shouldRemoveAllObjectsOnMemoryWarning; +@property BOOL shouldRemoveAllObjectsOnMemoryWarning; /** If `YES`, The cache will remove all objects when the app enter background. The default value is `YES`. */ -@property (assign) BOOL shouldRemoveAllObjectsWhenEnteringBackground; +@property BOOL shouldRemoveAllObjectsWhenEnteringBackground; /** A block to be executed when the app receives a memory warning. The default value is nil. */ -@property (copy) void(^didReceiveMemoryWarningBlock)(YYMemoryCache *cache); +@property (nullable, copy) void(^didReceiveMemoryWarningBlock)(YYMemoryCache *cache); /** A block to be executed when the app enter background. The default value is nil. */ -@property (copy) void(^didEnterBackgroundBlock)(YYMemoryCache *cache); +@property (nullable, copy) void(^didEnterBackgroundBlock)(YYMemoryCache *cache); /** If `YES`, the key-value pair will be released on main thread, otherwise on @@ -114,14 +116,14 @@ @discussion You may set this value to `YES` if the key-value object contains the instance which should be released in main thread (such as UIView/CALayer). */ -@property (assign) BOOL releaseOnMainThread; +@property BOOL releaseOnMainThread; /** If `YES`, the key-value pair will be released asynchronously to avoid blocking the access methods, otherwise it will be released in the access method (such as removeObjectForKey:). Default is YES. */ -@property (assign) BOOL releaseAsynchronously; +@property BOOL releaseAsynchronously; #pragma mark - Access Methods @@ -143,7 +145,7 @@ @param key An object identifying the value. If nil, just return nil. @return The value associated with key, or nil if no value is associated with key. */ -- (id)objectForKey:(id)key; +- (nullable id)objectForKey:(id)key; /** Sets the value of the specified key in the cache (0 cost). @@ -153,7 +155,7 @@ @discussion Unlike an NSMutableDictionary object, a cache does not copy the key objects that are put into it. */ -- (void)setObject:(id)object forKey:(id)key; +- (void)setObject:(nullable id)object forKey:(id)key; /** Sets the value of the specified key in the cache, and associates the key-value @@ -165,7 +167,7 @@ @discussion Unlike an NSMutableDictionary object, a cache does not copy the key objects that are put into it. */ -- (void)setObject:(id)object forKey:(id)key withCost:(NSUInteger)cost; +- (void)setObject:(nullable id)object forKey:(id)key withCost:(NSUInteger)cost; /** Removes the value of the specified key in the cache. @@ -207,3 +209,5 @@ - (void)trimToAge:(NSTimeInterval)age; @end + +NS_ASSUME_NONNULL_END diff --git a/YYWebImage/Cache/YYMemoryCache.m b/YYWebImage/Cache/YYMemoryCache.m index 9d32909..9042d9b 100644 --- a/YYWebImage/Cache/YYMemoryCache.m +++ b/YYWebImage/Cache/YYMemoryCache.m @@ -13,24 +13,12 @@ #import #import #import -#import #import -#if __has_include("YYDispatchQueuePool.h") -#import "YYDispatchQueuePool.h" -#else -#import -#endif -#ifdef YYDispatchQueuePool_h -static inline dispatch_queue_t YYMemoryCacheGetReleaseQueue() { - return YYDispatchQueueGetForQOS(NSQualityOfServiceUtility); -} -#else static inline dispatch_queue_t YYMemoryCacheGetReleaseQueue() { return dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_LOW, 0); } -#endif /** A node in linked map. @@ -185,7 +173,7 @@ - (void)removeAll { @implementation YYMemoryCache { - OSSpinLock _lock; + pthread_mutex_t _lock; _YYLinkedMap *_lru; dispatch_queue_t _queue; } @@ -210,26 +198,26 @@ - (void)_trimInBackground { - (void)_trimToCost:(NSUInteger)costLimit { BOOL finish = NO; - OSSpinLockLock(&_lock); + pthread_mutex_lock(&_lock); if (costLimit == 0) { [_lru removeAll]; finish = YES; } else if (_lru->_totalCost <= costLimit) { finish = YES; } - OSSpinLockUnlock(&_lock); + pthread_mutex_unlock(&_lock); if (finish) return; NSMutableArray *holder = [NSMutableArray new]; while (!finish) { - if (OSSpinLockTry(&_lock)) { + if (pthread_mutex_trylock(&_lock) == 0) { if (_lru->_totalCost > costLimit) { _YYLinkedMapNode *node = [_lru removeTailNode]; if (node) [holder addObject:node]; } else { finish = YES; } - OSSpinLockUnlock(&_lock); + pthread_mutex_unlock(&_lock); } else { usleep(10 * 1000); //10 ms } @@ -244,26 +232,26 @@ - (void)_trimToCost:(NSUInteger)costLimit { - (void)_trimToCount:(NSUInteger)countLimit { BOOL finish = NO; - OSSpinLockLock(&_lock); + pthread_mutex_lock(&_lock); if (countLimit == 0) { [_lru removeAll]; finish = YES; } else if (_lru->_totalCount <= countLimit) { finish = YES; } - OSSpinLockUnlock(&_lock); + pthread_mutex_unlock(&_lock); if (finish) return; NSMutableArray *holder = [NSMutableArray new]; while (!finish) { - if (OSSpinLockTry(&_lock)) { + if (pthread_mutex_trylock(&_lock) == 0) { if (_lru->_totalCount > countLimit) { _YYLinkedMapNode *node = [_lru removeTailNode]; if (node) [holder addObject:node]; } else { finish = YES; } - OSSpinLockUnlock(&_lock); + pthread_mutex_unlock(&_lock); } else { usleep(10 * 1000); //10 ms } @@ -279,26 +267,26 @@ - (void)_trimToCount:(NSUInteger)countLimit { - (void)_trimToAge:(NSTimeInterval)ageLimit { BOOL finish = NO; NSTimeInterval now = CACurrentMediaTime(); - OSSpinLockLock(&_lock); + pthread_mutex_lock(&_lock); if (ageLimit <= 0) { [_lru removeAll]; finish = YES; } else if (!_lru->_tail || (now - _lru->_tail->_time) <= ageLimit) { finish = YES; } - OSSpinLockUnlock(&_lock); + pthread_mutex_unlock(&_lock); if (finish) return; NSMutableArray *holder = [NSMutableArray new]; while (!finish) { - if (OSSpinLockTry(&_lock)) { + if (pthread_mutex_trylock(&_lock) == 0) { if (_lru->_tail && (now - _lru->_tail->_time) > ageLimit) { _YYLinkedMapNode *node = [_lru removeTailNode]; if (node) [holder addObject:node]; } else { finish = YES; } - OSSpinLockUnlock(&_lock); + pthread_mutex_unlock(&_lock); } else { usleep(10 * 1000); //10 ms } @@ -333,7 +321,7 @@ - (void)_appDidEnterBackgroundNotification { - (instancetype)init { self = super.init; - _lock = OS_SPINLOCK_INIT; + pthread_mutex_init(&_lock, NULL); _lru = [_YYLinkedMap new]; _queue = dispatch_queue_create("com.ibireme.cache.memory", DISPATCH_QUEUE_SERIAL); @@ -355,65 +343,66 @@ - (void)dealloc { [[NSNotificationCenter defaultCenter] removeObserver:self name:UIApplicationDidReceiveMemoryWarningNotification object:nil]; [[NSNotificationCenter defaultCenter] removeObserver:self name:UIApplicationDidEnterBackgroundNotification object:nil]; [_lru removeAll]; + pthread_mutex_destroy(&_lock); } - (NSUInteger)totalCount { - OSSpinLockLock(&_lock); + pthread_mutex_lock(&_lock); NSUInteger count = _lru->_totalCount; - OSSpinLockUnlock(&_lock); + pthread_mutex_unlock(&_lock); return count; } - (NSUInteger)totalCost { - OSSpinLockLock(&_lock); + pthread_mutex_lock(&_lock); NSUInteger totalCost = _lru->_totalCost; - OSSpinLockUnlock(&_lock); + pthread_mutex_unlock(&_lock); return totalCost; } -- (BOOL)releaseInMainThread { - OSSpinLockLock(&_lock); - BOOL releaseInMainThread = _lru->_releaseOnMainThread; - OSSpinLockUnlock(&_lock); - return releaseInMainThread; +- (BOOL)releaseOnMainThread { + pthread_mutex_lock(&_lock); + BOOL releaseOnMainThread = _lru->_releaseOnMainThread; + pthread_mutex_unlock(&_lock); + return releaseOnMainThread; } -- (void)setReleaseInMainThread:(BOOL)releaseInMainThread { - OSSpinLockLock(&_lock); - _lru->_releaseOnMainThread = releaseInMainThread; - OSSpinLockUnlock(&_lock); +- (void)setReleaseOnMainThread:(BOOL)releaseOnMainThread { + pthread_mutex_lock(&_lock); + _lru->_releaseOnMainThread = releaseOnMainThread; + pthread_mutex_unlock(&_lock); } - (BOOL)releaseAsynchronously { - OSSpinLockLock(&_lock); + pthread_mutex_lock(&_lock); BOOL releaseAsynchronously = _lru->_releaseAsynchronously; - OSSpinLockUnlock(&_lock); + pthread_mutex_unlock(&_lock); return releaseAsynchronously; } - (void)setReleaseAsynchronously:(BOOL)releaseAsynchronously { - OSSpinLockLock(&_lock); + pthread_mutex_lock(&_lock); _lru->_releaseAsynchronously = releaseAsynchronously; - OSSpinLockUnlock(&_lock); + pthread_mutex_unlock(&_lock); } - (BOOL)containsObjectForKey:(id)key { if (!key) return NO; - OSSpinLockLock(&_lock); + pthread_mutex_lock(&_lock); BOOL contains = CFDictionaryContainsKey(_lru->_dic, (__bridge const void *)(key)); - OSSpinLockUnlock(&_lock); + pthread_mutex_unlock(&_lock); return contains; } - (id)objectForKey:(id)key { if (!key) return nil; - OSSpinLockLock(&_lock); + pthread_mutex_lock(&_lock); _YYLinkedMapNode *node = CFDictionaryGetValue(_lru->_dic, (__bridge const void *)(key)); if (node) { node->_time = CACurrentMediaTime(); [_lru bringNodeToHead:node]; } - OSSpinLockUnlock(&_lock); + pthread_mutex_unlock(&_lock); return node ? node->_value : nil; } @@ -427,7 +416,7 @@ - (void)setObject:(id)object forKey:(id)key withCost:(NSUInteger)cost { [self removeObjectForKey:key]; return; } - OSSpinLockLock(&_lock); + pthread_mutex_lock(&_lock); _YYLinkedMapNode *node = CFDictionaryGetValue(_lru->_dic, (__bridge const void *)(key)); NSTimeInterval now = CACurrentMediaTime(); if (node) { @@ -463,16 +452,15 @@ - (void)setObject:(id)object forKey:(id)key withCost:(NSUInteger)cost { }); } } - OSSpinLockUnlock(&_lock); + pthread_mutex_unlock(&_lock); } - (void)removeObjectForKey:(id)key { if (!key) return; - OSSpinLockLock(&_lock); + pthread_mutex_lock(&_lock); _YYLinkedMapNode *node = CFDictionaryGetValue(_lru->_dic, (__bridge const void *)(key)); if (node) { [_lru removeNode:node]; - _YYLinkedMapNode *node = [_lru removeTailNode]; if (_lru->_releaseAsynchronously) { dispatch_queue_t queue = _lru->_releaseOnMainThread ? dispatch_get_main_queue() : YYMemoryCacheGetReleaseQueue(); dispatch_async(queue, ^{ @@ -484,13 +472,13 @@ - (void)removeObjectForKey:(id)key { }); } } - OSSpinLockUnlock(&_lock); + pthread_mutex_unlock(&_lock); } - (void)removeAllObjects { - OSSpinLockLock(&_lock); + pthread_mutex_lock(&_lock); [_lru removeAll]; - OSSpinLockUnlock(&_lock); + pthread_mutex_unlock(&_lock); } - (void)trimToCount:(NSUInteger)count { diff --git a/YYWebImage/Categories/CALayer+YYWebImage.h b/YYWebImage/Categories/CALayer+YYWebImage.h index e59f2cc..722edd8 100644 --- a/YYWebImage/Categories/CALayer+YYWebImage.h +++ b/YYWebImage/Categories/CALayer+YYWebImage.h @@ -18,6 +18,7 @@ #import "YYWebImageManager.h" #endif +NS_ASSUME_NONNULL_BEGIN /** Web image methods for CALayer. @@ -25,7 +26,6 @@ */ @interface CALayer (YYWebImage) - #pragma mark - image /** @@ -35,7 +35,7 @@ operation and create a new request operation to fetch image. Set nil to clear the image and image URL. */ -@property (nonatomic, strong) NSURL *yy_imageURL; +@property (nullable, nonatomic, strong) NSURL *yy_imageURL; /** Set the view's `image` with a specified URL. @@ -43,7 +43,7 @@ @param imageURL The image url (remote or local file path). @param placeholder The image to be set initially, until the image request finishes. */ -- (void)yy_setImageWithURL:(NSURL *)imageURL placeholder:(UIImage *)placeholder; +- (void)yy_setImageWithURL:(nullable NSURL *)imageURL placeholder:(nullable UIImage *)placeholder; /** Set the view's `image` with a specified URL. @@ -51,7 +51,7 @@ @param imageURL The image url (remote or local file path). @param options The options to use when request the image. */ -- (void)yy_setImageWithURL:(NSURL *)imageURL options:(YYWebImageOptions)options; +- (void)yy_setImageWithURL:(nullable NSURL *)imageURL options:(YYWebImageOptions)options; /** Set the view's `image` with a specified URL. @@ -61,10 +61,10 @@ @param options The options to use when request the image. @param completion The block invoked (on main thread) when image request completed. */ -- (void)yy_setImageWithURL:(NSURL *)imageURL - placeholder:(UIImage *)placeholder +- (void)yy_setImageWithURL:(nullable NSURL *)imageURL + placeholder:(nullable UIImage *)placeholder options:(YYWebImageOptions)options - completion:(YYWebImageCompletionBlock)completion; + completion:(nullable YYWebImageCompletionBlock)completion; /** Set the view's `image` with a specified URL. @@ -76,12 +76,12 @@ @param transform The block invoked (on background thread) to do additional image process. @param completion The block invoked (on main thread) when image request completed. */ -- (void)yy_setImageWithURL:(NSURL *)imageURL - placeholder:(UIImage *)placeholder +- (void)yy_setImageWithURL:(nullable NSURL *)imageURL + placeholder:(nullable UIImage *)placeholder options:(YYWebImageOptions)options - progress:(YYWebImageProgressBlock)progress - transform:(YYWebImageTransformBlock)transform - completion:(YYWebImageCompletionBlock)completion; + progress:(nullable YYWebImageProgressBlock)progress + transform:(nullable YYWebImageTransformBlock)transform + completion:(nullable YYWebImageCompletionBlock)completion; /** Set the view's `image` with a specified URL. @@ -94,13 +94,13 @@ @param transform The block invoked (on background thread) to do additional image process. @param completion The block invoked (on main thread) when image request completed. */ -- (void)yy_setImageWithURL:(NSURL *)imageURL - placeholder:(UIImage *)placeholder +- (void)yy_setImageWithURL:(nullable NSURL *)imageURL + placeholder:(nullable UIImage *)placeholder options:(YYWebImageOptions)options - manager:(YYWebImageManager *)manager - progress:(YYWebImageProgressBlock)progress - transform:(YYWebImageTransformBlock)transform - completion:(YYWebImageCompletionBlock)completion; + manager:(nullable YYWebImageManager *)manager + progress:(nullable YYWebImageProgressBlock)progress + transform:(nullable YYWebImageTransformBlock)transform + completion:(nullable YYWebImageCompletionBlock)completion; /** Cancel the current image request. @@ -108,3 +108,5 @@ - (void)yy_cancelCurrentImageRequest; @end + +NS_ASSUME_NONNULL_END diff --git a/YYWebImage/Categories/CALayer+YYWebImage.m b/YYWebImage/Categories/CALayer+YYWebImage.m index 2d4d12a..8309a0c 100644 --- a/YYWebImage/Categories/CALayer+YYWebImage.m +++ b/YYWebImage/Categories/CALayer+YYWebImage.m @@ -145,12 +145,15 @@ - (void)yy_setImageWithURL:(NSURL *)imageURL }); }; + __block int32_t newSentinel = 0; + __block __weak typeof(setter) weakSetter = nil; YYWebImageCompletionBlock _completion = ^(UIImage *image, NSURL *url, YYWebImageFromType from, YYWebImageStage stage, NSError *error) { __strong typeof(_self) self = _self; BOOL setImage = (stage == YYWebImageStageFinished || stage == YYWebImageStageProgress) && image && !(options & YYWebImageOptionAvoidSetImage); BOOL showFade = (options & YYWebImageOptionSetImageWithFadeAnimation); dispatch_async(dispatch_get_main_queue(), ^{ - if (setImage && self) { + BOOL sentinelChanged = weakSetter && weakSetter.sentinel != newSentinel; + if (setImage && self && !sentinelChanged) { if (showFade) { CATransition *transition = [CATransition animation]; transition.duration = stage == YYWebImageStageFinished ? _YYWebImageFadeTime : _YYWebImageProgressiveFadeTime; @@ -160,11 +163,18 @@ - (void)yy_setImageWithURL:(NSURL *)imageURL } self.contents = (id)image.CGImage; } - if (completion) completion(image, url, from, stage, error); + if (completion) { + if (sentinelChanged) { + completion(nil, url, YYWebImageFromNone, YYWebImageStageCancelled, nil); + } else { + completion(image, url, from, stage, error); + } + } }); }; - [setter setOperationWithSentinel:sentinel url:imageURL options:options manager:manager progress:_progress transform:transform completion:_completion]; + newSentinel = [setter setOperationWithSentinel:sentinel url:imageURL options:options manager:manager progress:_progress transform:transform completion:_completion]; + weakSetter = setter; }); diff --git a/YYWebImage/Categories/MKAnnotationView+YYWebImage.h b/YYWebImage/Categories/MKAnnotationView+YYWebImage.h index 17bbdc5..b9bce0b 100644 --- a/YYWebImage/Categories/MKAnnotationView+YYWebImage.h +++ b/YYWebImage/Categories/MKAnnotationView+YYWebImage.h @@ -18,6 +18,7 @@ #import "YYWebImageManager.h" #endif +NS_ASSUME_NONNULL_BEGIN /** Web image methods for MKAnnotationView. @@ -31,7 +32,7 @@ operation and create a new request operation to fetch image. Set nil to clear the image and image URL. */ -@property (nonatomic, strong) NSURL *imageURL; +@property (nullable, nonatomic, strong) NSURL *yy_imageURL; /** Set the view's `image` with a specified URL. @@ -39,7 +40,7 @@ @param imageURL The image url (remote or local file path). @param placeholder The image to be set initially, until the image request finishes. */ -- (void)setImageWithURL:(NSURL *)imageURL placeholder:(UIImage *)placeholder; +- (void)yy_setImageWithURL:(nullable NSURL *)imageURL placeholder:(nullable UIImage *)placeholder; /** Set the view's `image` with a specified URL. @@ -47,7 +48,7 @@ @param imageURL The image url (remote or local file path). @param options The options to use when request the image. */ -- (void)setImageWithURL:(NSURL *)imageURL options:(YYWebImageOptions)options; +- (void)yy_setImageWithURL:(nullable NSURL *)imageURL options:(YYWebImageOptions)options; /** Set the view's `image` with a specified URL. @@ -57,10 +58,10 @@ @param options The options to use when request the image. @param completion The block invoked (on main thread) when image request completed. */ -- (void)setImageWithURL:(NSURL *)imageURL - placeholder:(UIImage *)placeholder - options:(YYWebImageOptions)options - completion:(YYWebImageCompletionBlock)completion; +- (void)yy_setImageWithURL:(nullable NSURL *)imageURL + placeholder:(nullable UIImage *)placeholder + options:(YYWebImageOptions)options + completion:(nullable YYWebImageCompletionBlock)completion; /** Set the view's `image` with a specified URL. @@ -72,12 +73,12 @@ @param transform The block invoked (on background thread) to do additional image process. @param completion The block invoked (on main thread) when image request completed. */ -- (void)setImageWithURL:(NSURL *)imageURL - placeholder:(UIImage *)placeholder - options:(YYWebImageOptions)options - progress:(YYWebImageProgressBlock)progress - transform:(YYWebImageTransformBlock)transform - completion:(YYWebImageCompletionBlock)completion; +- (void)yy_setImageWithURL:(nullable NSURL *)imageURL + placeholder:(nullable UIImage *)placeholder + options:(YYWebImageOptions)options + progress:(nullable YYWebImageProgressBlock)progress + transform:(nullable YYWebImageTransformBlock)transform + completion:(nullable YYWebImageCompletionBlock)completion; /** Set the view's `image` with a specified URL. @@ -90,17 +91,19 @@ @param transform The block invoked (on background thread) to do additional image process. @param completion The block invoked (on main thread) when image request completed. */ -- (void)setImageWithURL:(NSURL *)imageURL - placeholder:(UIImage *)placeholder - options:(YYWebImageOptions)options - manager:(YYWebImageManager *)manager - progress:(YYWebImageProgressBlock)progress - transform:(YYWebImageTransformBlock)transform - completion:(YYWebImageCompletionBlock)completion; +- (void)yy_setImageWithURL:(nullable NSURL *)imageURL + placeholder:(nullable UIImage *)placeholder + options:(YYWebImageOptions)options + manager:(nullable YYWebImageManager *)manager + progress:(nullable YYWebImageProgressBlock)progress + transform:(nullable YYWebImageTransformBlock)transform + completion:(nullable YYWebImageCompletionBlock)completion; /** Cancel the current image request. */ -- (void)cancelCurrentImageRequest; +- (void)yy_cancelCurrentImageRequest; @end + +NS_ASSUME_NONNULL_END diff --git a/YYWebImage/Categories/MKAnnotationView+YYWebImage.m b/YYWebImage/Categories/MKAnnotationView+YYWebImage.m index 3170609..d9afff4 100644 --- a/YYWebImage/Categories/MKAnnotationView+YYWebImage.m +++ b/YYWebImage/Categories/MKAnnotationView+YYWebImage.m @@ -23,13 +23,13 @@ @implementation MKAnnotationView_YYWebImage @end @implementation MKAnnotationView (YYWebImage) -- (NSURL *)imageURL { +- (NSURL *)yy_imageURL { _YYWebImageSetter *setter = objc_getAssociatedObject(self, &_YYWebImageSetterKey); return setter.imageURL; } -- (void)setImageURL:(NSURL *)imageURL { - [self setImageWithURL:imageURL +- (void)setYy_imageURL:(NSURL *)imageURL { + [self yy_setImageWithURL:imageURL placeholder:nil options:kNilOptions manager:nil @@ -38,61 +38,61 @@ - (void)setImageURL:(NSURL *)imageURL { completion:nil]; } -- (void)setImageWithURL:(NSURL *)imageURL placeholder:(UIImage *)placeholder { - [self setImageWithURL:imageURL - placeholder:placeholder - options:kNilOptions - manager:nil - progress:nil - transform:nil - completion:nil]; +- (void)yy_setImageWithURL:(NSURL *)imageURL placeholder:(UIImage *)placeholder { + [self yy_setImageWithURL:imageURL + placeholder:placeholder + options:kNilOptions + manager:nil + progress:nil + transform:nil + completion:nil]; } -- (void)setImageWithURL:(NSURL *)imageURL options:(YYWebImageOptions)options { - [self setImageWithURL:imageURL - placeholder:nil - options:options - manager:nil - progress:nil - transform:nil - completion:nil]; +- (void)yy_setImageWithURL:(NSURL *)imageURL options:(YYWebImageOptions)options { + [self yy_setImageWithURL:imageURL + placeholder:nil + options:options + manager:nil + progress:nil + transform:nil + completion:nil]; } -- (void)setImageWithURL:(NSURL *)imageURL - placeholder:(UIImage *)placeholder - options:(YYWebImageOptions)options - completion:(YYWebImageCompletionBlock)completion { - [self setImageWithURL:imageURL - placeholder:placeholder - options:options - manager:nil - progress:nil - transform:nil - completion:completion]; +- (void)yy_setImageWithURL:(NSURL *)imageURL + placeholder:(UIImage *)placeholder + options:(YYWebImageOptions)options + completion:(YYWebImageCompletionBlock)completion { + [self yy_setImageWithURL:imageURL + placeholder:placeholder + options:options + manager:nil + progress:nil + transform:nil + completion:completion]; } -- (void)setImageWithURL:(NSURL *)imageURL - placeholder:(UIImage *)placeholder - options:(YYWebImageOptions)options - progress:(YYWebImageProgressBlock)progress - transform:(YYWebImageTransformBlock)transform - completion:(YYWebImageCompletionBlock)completion { - [self setImageWithURL:imageURL - placeholder:placeholder - options:options - manager:nil - progress:progress - transform:transform - completion:completion]; +- (void)yy_setImageWithURL:(NSURL *)imageURL + placeholder:(UIImage *)placeholder + options:(YYWebImageOptions)options + progress:(YYWebImageProgressBlock)progress + transform:(YYWebImageTransformBlock)transform + completion:(YYWebImageCompletionBlock)completion { + [self yy_setImageWithURL:imageURL + placeholder:placeholder + options:options + manager:nil + progress:progress + transform:transform + completion:completion]; } -- (void)setImageWithURL:(NSURL *)imageURL - placeholder:(UIImage *)placeholder - options:(YYWebImageOptions)options - manager:(YYWebImageManager *)manager - progress:(YYWebImageProgressBlock)progress - transform:(YYWebImageTransformBlock)transform - completion:(YYWebImageCompletionBlock)completion { +- (void)yy_setImageWithURL:(NSURL *)imageURL + placeholder:(UIImage *)placeholder + options:(YYWebImageOptions)options + manager:(YYWebImageManager *)manager + progress:(YYWebImageProgressBlock)progress + transform:(YYWebImageTransformBlock)transform + completion:(YYWebImageCompletionBlock)completion { if ([imageURL isKindOfClass:[NSString class]]) imageURL = [NSURL URLWithString:(id)imageURL]; manager = manager ? manager : [YYWebImageManager sharedManager]; @@ -145,12 +145,15 @@ - (void)setImageWithURL:(NSURL *)imageURL }); }; + __block int32_t newSentinel = 0; + __block __weak typeof(setter) weakSetter = nil; YYWebImageCompletionBlock _completion = ^(UIImage *image, NSURL *url, YYWebImageFromType from, YYWebImageStage stage, NSError *error) { __strong typeof(_self) self = _self; BOOL setImage = (stage == YYWebImageStageFinished || stage == YYWebImageStageProgress) && image && !(options & YYWebImageOptionAvoidSetImage); BOOL showFade = ((options & YYWebImageOptionSetImageWithFadeAnimation) && !self.highlighted); dispatch_async(dispatch_get_main_queue(), ^{ - if (setImage && self) { + BOOL sentinelChanged = weakSetter && weakSetter.sentinel != newSentinel; + if (setImage && self && !sentinelChanged) { if (showFade) { CATransition *transition = [CATransition animation]; transition.duration = stage == YYWebImageStageFinished ? _YYWebImageFadeTime : _YYWebImageProgressiveFadeTime; @@ -160,16 +163,23 @@ - (void)setImageWithURL:(NSURL *)imageURL } self.image = image; } - if (completion) completion(image, url, from, stage, error); + if (completion) { + if (sentinelChanged) { + completion(nil, url, YYWebImageFromNone, YYWebImageStageCancelled, nil); + } else { + completion(image, url, from, stage, error); + } + } }); }; - [setter setOperationWithSentinel:sentinel url:imageURL options:options manager:manager progress:_progress transform:transform completion:_completion]; + newSentinel = [setter setOperationWithSentinel:sentinel url:imageURL options:options manager:manager progress:_progress transform:transform completion:_completion]; + weakSetter = setter; }); }); } -- (void)cancelCurrentImageRequest { +- (void)yy_cancelCurrentImageRequest { _YYWebImageSetter *setter = objc_getAssociatedObject(self, &_YYWebImageSetterKey); if (setter) [setter cancel]; } diff --git a/YYWebImage/Categories/UIButton+YYWebImage.h b/YYWebImage/Categories/UIButton+YYWebImage.h index 28f4937..7ad6eff 100644 --- a/YYWebImage/Categories/UIButton+YYWebImage.h +++ b/YYWebImage/Categories/UIButton+YYWebImage.h @@ -17,6 +17,7 @@ #import "YYWebImageManager.h" #endif +NS_ASSUME_NONNULL_BEGIN /** Web image methods for UIButton. @@ -29,7 +30,7 @@ Current image URL for the specified state. @return The image URL, or nil. */ -- (NSURL *)yy_imageURLForState:(UIControlState)state; +- (nullable NSURL *)yy_imageURLForState:(UIControlState)state; /** Set the button's image with a specified URL for the specified state. @@ -38,9 +39,9 @@ @param state The state that uses the specified image. @param placeholder The image to be set initially, until the image request finishes. */ -- (void)yy_setImageWithURL:(NSURL *)imageURL +- (void)yy_setImageWithURL:(nullable NSURL *)imageURL forState:(UIControlState)state - placeholder:(UIImage *)placeholder; + placeholder:(nullable UIImage *)placeholder; /** Set the button's image with a specified URL for the specified state. @@ -49,7 +50,7 @@ @param state The state that uses the specified image. @param options The options to use when request the image. */ -- (void)yy_setImageWithURL:(NSURL *)imageURL +- (void)yy_setImageWithURL:(nullable NSURL *)imageURL forState:(UIControlState)state options:(YYWebImageOptions)options; @@ -62,11 +63,11 @@ @param options The options to use when request the image. @param completion The block invoked (on main thread) when image request completed. */ -- (void)yy_setImageWithURL:(NSURL *)imageURL +- (void)yy_setImageWithURL:(nullable NSURL *)imageURL forState:(UIControlState)state - placeholder:(UIImage *)placeholder + placeholder:(nullable UIImage *)placeholder options:(YYWebImageOptions)options - completion:(YYWebImageCompletionBlock)completion; + completion:(nullable YYWebImageCompletionBlock)completion; /** Set the button's image with a specified URL for the specified state. @@ -79,13 +80,13 @@ @param transform The block invoked (on background thread) to do additional image process. @param completion The block invoked (on main thread) when image request completed. */ -- (void)yy_setImageWithURL:(NSURL *)imageURL +- (void)yy_setImageWithURL:(nullable NSURL *)imageURL forState:(UIControlState)state - placeholder:(UIImage *)placeholder + placeholder:(nullable UIImage *)placeholder options:(YYWebImageOptions)options - progress:(YYWebImageProgressBlock)progress - transform:(YYWebImageTransformBlock)transform - completion:(YYWebImageCompletionBlock)completion; + progress:(nullable YYWebImageProgressBlock)progress + transform:(nullable YYWebImageTransformBlock)transform + completion:(nullable YYWebImageCompletionBlock)completion; /** Set the button's image with a specified URL for the specified state. @@ -99,14 +100,14 @@ @param transform The block invoked (on background thread) to do additional image process. @param completion The block invoked (on main thread) when image request completed. */ -- (void)yy_setImageWithURL:(NSURL *)imageURL +- (void)yy_setImageWithURL:(nullable NSURL *)imageURL forState:(UIControlState)state - placeholder:(UIImage *)placeholder + placeholder:(nullable UIImage *)placeholder options:(YYWebImageOptions)options - manager:(YYWebImageManager *)manager - progress:(YYWebImageProgressBlock)progress - transform:(YYWebImageTransformBlock)transform - completion:(YYWebImageCompletionBlock)completion; + manager:(nullable YYWebImageManager *)manager + progress:(nullable YYWebImageProgressBlock)progress + transform:(nullable YYWebImageTransformBlock)transform + completion:(nullable YYWebImageCompletionBlock)completion; /** Cancel the current image request for a specified state. @@ -122,7 +123,7 @@ Current backgroundImage URL for the specified state. @return The image URL, or nil. */ -- (NSURL *)yy_backgroundImageURLForState:(UIControlState)state; +- (nullable NSURL *)yy_backgroundImageURLForState:(UIControlState)state; /** Set the button's backgroundImage with a specified URL for the specified state. @@ -131,9 +132,9 @@ @param state The state that uses the specified image. @param placeholder The image to be set initially, until the image request finishes. */ -- (void)yy_setBackgroundImageWithURL:(NSURL *)imageURL +- (void)yy_setBackgroundImageWithURL:(nullable NSURL *)imageURL forState:(UIControlState)state - placeholder:(UIImage *)placeholder; + placeholder:(nullable UIImage *)placeholder; /** Set the button's backgroundImage with a specified URL for the specified state. @@ -142,7 +143,7 @@ @param state The state that uses the specified image. @param options The options to use when request the image. */ -- (void)yy_setBackgroundImageWithURL:(NSURL *)imageURL +- (void)yy_setBackgroundImageWithURL:(nullable NSURL *)imageURL forState:(UIControlState)state options:(YYWebImageOptions)options; @@ -155,11 +156,11 @@ @param options The options to use when request the image. @param completion The block invoked (on main thread) when image request completed. */ -- (void)yy_setBackgroundImageWithURL:(NSURL *)imageURL +- (void)yy_setBackgroundImageWithURL:(nullable NSURL *)imageURL forState:(UIControlState)state - placeholder:(UIImage *)placeholder + placeholder:(nullable UIImage *)placeholder options:(YYWebImageOptions)options - completion:(YYWebImageCompletionBlock)completion; + completion:(nullable YYWebImageCompletionBlock)completion; /** Set the button's backgroundImage with a specified URL for the specified state. @@ -172,13 +173,13 @@ @param transform The block invoked (on background thread) to do additional image process. @param completion The block invoked (on main thread) when image request completed. */ -- (void)yy_setBackgroundImageWithURL:(NSURL *)imageURL +- (void)yy_setBackgroundImageWithURL:(nullable NSURL *)imageURL forState:(UIControlState)state - placeholder:(UIImage *)placeholder + placeholder:(nullable UIImage *)placeholder options:(YYWebImageOptions)options - progress:(YYWebImageProgressBlock)progress - transform:(YYWebImageTransformBlock)transform - completion:(YYWebImageCompletionBlock)completion; + progress:(nullable YYWebImageProgressBlock)progress + transform:(nullable YYWebImageTransformBlock)transform + completion:(nullable YYWebImageCompletionBlock)completion; /** Set the button's backgroundImage with a specified URL for the specified state. @@ -192,14 +193,14 @@ @param transform The block invoked (on background thread) to do additional image process. @param completion The block invoked (on main thread) when image request completed. */ -- (void)yy_setBackgroundImageWithURL:(NSURL *)imageURL +- (void)yy_setBackgroundImageWithURL:(nullable NSURL *)imageURL forState:(UIControlState)state - placeholder:(UIImage *)placeholder + placeholder:(nullable UIImage *)placeholder options:(YYWebImageOptions)options - manager:(YYWebImageManager *)manager - progress:(YYWebImageProgressBlock)progress - transform:(YYWebImageTransformBlock)transform - completion:(YYWebImageCompletionBlock)completion; + manager:(nullable YYWebImageManager *)manager + progress:(nullable YYWebImageProgressBlock)progress + transform:(nullable YYWebImageTransformBlock)transform + completion:(nullable YYWebImageCompletionBlock)completion; /** Cancel the current backgroundImage request for a specified state. @@ -208,3 +209,5 @@ - (void)yy_cancelBackgroundImageRequestForState:(UIControlState)state; @end + +NS_ASSUME_NONNULL_END diff --git a/YYWebImage/Categories/UIButton+YYWebImage.m b/YYWebImage/Categories/UIButton+YYWebImage.m index 06c6f76..8cc21d5 100644 --- a/YYWebImage/Categories/UIButton+YYWebImage.m +++ b/YYWebImage/Categories/UIButton+YYWebImage.m @@ -12,7 +12,6 @@ #import "UIButton+YYWebImage.h" #import "YYWebImageOperation.h" #import "_YYWebImageSetter.h" -#import #import // Dummy class for category @@ -46,29 +45,29 @@ - (_YYWebImageSetter *)lazySetterForState:(NSNumber *)state; @implementation _YYWebImageSetterDicForButton { NSMutableDictionary *_dic; - OSSpinLock _lock; + dispatch_semaphore_t _lock; } - (instancetype)init { self = [super init]; - _lock = OS_SPINLOCK_INIT; + _lock = dispatch_semaphore_create(1); _dic = [NSMutableDictionary new]; return self; } - (_YYWebImageSetter *)setterForState:(NSNumber *)state { - OSSpinLockLock(&_lock); + dispatch_semaphore_wait(_lock, DISPATCH_TIME_FOREVER); _YYWebImageSetter *setter = _dic[state]; - OSSpinLockUnlock(&_lock); + dispatch_semaphore_signal(_lock); return setter; } - (_YYWebImageSetter *)lazySetterForState:(NSNumber *)state { - OSSpinLockLock(&_lock); + dispatch_semaphore_wait(_lock, DISPATCH_TIME_FOREVER); _YYWebImageSetter *setter = _dic[state]; if (!setter) { setter = [_YYWebImageSetter new]; _dic[state] = setter; } - OSSpinLockUnlock(&_lock); + dispatch_semaphore_signal(_lock); return setter; } @end @@ -134,18 +133,28 @@ - (void)_yy_setImageWithURL:(NSURL *)imageURL }); }; + __block int32_t newSentinel = 0; + __block __weak typeof(setter) weakSetter = nil; YYWebImageCompletionBlock _completion = ^(UIImage *image, NSURL *url, YYWebImageFromType from, YYWebImageStage stage, NSError *error) { __strong typeof(_self) self = _self; BOOL setImage = (stage == YYWebImageStageFinished || stage == YYWebImageStageProgress) && image && !(options & YYWebImageOptionAvoidSetImage); dispatch_async(dispatch_get_main_queue(), ^{ - if (setImage && self) { + BOOL sentinelChanged = weakSetter && weakSetter.sentinel != newSentinel; + if (setImage && self && !sentinelChanged) { [self setImage:image forState:state.integerValue]; } - if (completion) completion(image, url, from, stage, error); + if (completion) { + if (sentinelChanged) { + completion(nil, url, YYWebImageFromNone, YYWebImageStageCancelled, nil); + } else { + completion(image, url, from, stage, error); + } + } }); }; - [setter setOperationWithSentinel:sentinel url:imageURL options:options manager:manager progress:_progress transform:transform completion:_completion]; + newSentinel = [setter setOperationWithSentinel:sentinel url:imageURL options:options manager:manager progress:_progress transform:transform completion:_completion]; + weakSetter = setter; }); }); } @@ -305,18 +314,28 @@ - (void)_yy_setBackgroundImageWithURL:(NSURL *)imageURL }); }; + __block int32_t newSentinel = 0; + __block __weak typeof(setter) weakSetter = nil; YYWebImageCompletionBlock _completion = ^(UIImage *image, NSURL *url, YYWebImageFromType from, YYWebImageStage stage, NSError *error) { __strong typeof(_self) self = _self; BOOL setImage = (stage == YYWebImageStageFinished || stage == YYWebImageStageProgress) && image && !(options & YYWebImageOptionAvoidSetImage); dispatch_async(dispatch_get_main_queue(), ^{ - if (setImage && self) { + BOOL sentinelChanged = weakSetter && weakSetter.sentinel != newSentinel; + if (setImage && self && !sentinelChanged) { [self setBackgroundImage:image forState:state.integerValue]; } - if (completion) completion(image, url, from, stage, error); + if (completion) { + if (sentinelChanged) { + completion(nil, url, YYWebImageFromNone, YYWebImageStageCancelled, nil); + } else { + completion(image, url, from, stage, error); + } + } }); }; - [setter setOperationWithSentinel:sentinel url:imageURL options:options manager:manager progress:_progress transform:transform completion:_completion]; + newSentinel = [setter setOperationWithSentinel:sentinel url:imageURL options:options manager:manager progress:_progress transform:transform completion:_completion]; + weakSetter = setter; }); }); } diff --git a/YYWebImage/Categories/UIImage+YYWebImage.h b/YYWebImage/Categories/UIImage+YYWebImage.h index a02329e..26f2af1 100644 --- a/YYWebImage/Categories/UIImage+YYWebImage.h +++ b/YYWebImage/Categories/UIImage+YYWebImage.h @@ -11,6 +11,8 @@ #import +NS_ASSUME_NONNULL_BEGIN + /** Provide some commen method for `UIImage`. Image process is based on CoreGraphic and vImage. @@ -38,14 +40,14 @@ @return A new image created from GIF, or nil when an error occurs. */ -+ (UIImage *)yy_imageWithSmallGIFData:(NSData *)data scale:(CGFloat)scale; ++ (nullable UIImage *)yy_imageWithSmallGIFData:(NSData *)data scale:(CGFloat)scale; /** Create and return a 1x1 point size image with the given color. @param color The color. */ -+ (UIImage *)yy_imageWithColor:(UIColor *)color; ++ (nullable UIImage *)yy_imageWithColor:(UIColor *)color; /** Create and return a pure color image with the given color and size. @@ -53,7 +55,7 @@ @param color The color. @param size New image's type. */ -+ (UIImage *)yy_imageWithColor:(UIColor *)color size:(CGSize)size; ++ (nullable UIImage *)yy_imageWithColor:(UIColor *)color size:(CGSize)size; /** Create and return an image with custom draw code. @@ -63,7 +65,7 @@ @return The new image. */ -+ (UIImage *)yy_imageWithSize:(CGSize)size drawBlock:(void (^)(CGContextRef context))drawBlock; ++ (nullable UIImage *)yy_imageWithSize:(CGSize)size drawBlock:(void (^)(CGContextRef context))drawBlock; #pragma mark - Image Info ///============================================================================= @@ -107,7 +109,7 @@ @return The new image with the given size. */ -- (UIImage *)yy_imageByResizeToSize:(CGSize)size; +- (nullable UIImage *)yy_imageByResizeToSize:(CGSize)size; /** Returns a new image which is scaled from this image. @@ -119,7 +121,7 @@ @return The new image with the given size. */ -- (UIImage *)yy_imageByResizeToSize:(CGSize)size contentMode:(UIViewContentMode)contentMode; +- (nullable UIImage *)yy_imageByResizeToSize:(CGSize)size contentMode:(UIViewContentMode)contentMode; /** Returns a new image which is cropped from this image. @@ -128,7 +130,7 @@ @return The new image, or nil if an error occurs. */ -- (UIImage *)yy_imageByCropToRect:(CGRect)rect; +- (nullable UIImage *)yy_imageByCropToRect:(CGRect)rect; /** Returns a new image which is edge inset from this image. @@ -139,7 +141,7 @@ @return The new image, or nil if an error occurs. */ -- (UIImage *)yy_imageByInsetEdge:(UIEdgeInsets)insets withColor:(UIColor *)color; +- (nullable UIImage *)yy_imageByInsetEdge:(UIEdgeInsets)insets withColor:(nullable UIColor *)color; /** Rounds a new image with a given corner size. @@ -148,7 +150,24 @@ rectangle's width or height are clamped appropriately to half the width or height. */ -- (UIImage *)yy_imageByRoundCornerRadius:(CGFloat)radius; +- (nullable UIImage *)yy_imageByRoundCornerRadius:(CGFloat)radius; + +/** + Rounds a new image with a given corner size. + + @param radius The radius of each corner oval. Values larger than half the + rectangle's width or height are clamped appropriately to + half the width or height. + + @param borderWidth The inset border line width. Values larger than half the rectangle's + width or height are clamped appropriately to half the width + or height. + + @param borderColor The border stroke color. nil means clear color. + */ +- (nullable UIImage *)yy_imageByRoundCornerRadius:(CGFloat)radius + borderWidth:(CGFloat)borderWidth + borderColor:(nullable UIColor *)borderColor; /** Rounds a new image with a given corner size. @@ -161,13 +180,19 @@ rounded. You can use this parameter to round only a subset of the corners of the rectangle. - @param borderWidth The inset border with clear color. Values larger than half - the rectangle's width or height are clamped appropriately - to half the width or height. + @param borderWidth The inset border line width. Values larger than half the rectangle's + width or height are clamped appropriately to half the width + or height. + + @param borderColor The border stroke color. nil means clear color. + + @param borderLineJoin The border line join. */ -- (UIImage *)yy_imageByRoundCornerRadius:(CGFloat)radius - corners:(UIRectCorner)corners - borderWidth:(CGFloat)borderWidth; +- (nullable UIImage *)yy_imageByRoundCornerRadius:(CGFloat)radius + corners:(UIRectCorner)corners + borderWidth:(CGFloat)borderWidth + borderColor:(nullable UIColor *)borderColor + borderLineJoin:(CGLineJoin)borderLineJoin; /** Returns a new rotated image (relative to the center). @@ -177,34 +202,34 @@ @param fitSize YES: new image's size is extend to fit all content. NO: image's size will not change, content may be clipped. */ -- (UIImage *)yy_imageByRotate:(CGFloat)radians fitSize:(BOOL)fitSize; +- (nullable UIImage *)yy_imageByRotate:(CGFloat)radians fitSize:(BOOL)fitSize; /** Returns a new image rotated counterclockwise by a quarter‑turn (90°). ⤺ The width and height will be exchanged. */ -- (UIImage *)yy_imageByRotateLeft90; +- (nullable UIImage *)yy_imageByRotateLeft90; /** Returns a new image rotated clockwise by a quarter‑turn (90°). ⤼ The width and height will be exchanged. */ -- (UIImage *)yy_imageByRotateRight90; +- (nullable UIImage *)yy_imageByRotateRight90; /** Returns a new image rotated 180° . ↻ */ -- (UIImage *)yy_imageByRotate180; +- (nullable UIImage *)yy_imageByRotate180; /** Returns a vertically flipped image. ⥯ */ -- (UIImage *)yy_imageByFlipVertical; +- (nullable UIImage *)yy_imageByFlipVertical; /** Returns a horizontally flipped image. ⇋ */ -- (UIImage *)yy_imageByFlipHorizontal; +- (nullable UIImage *)yy_imageByFlipHorizontal; #pragma mark - Image Effect @@ -217,42 +242,42 @@ @param color The color. */ -- (UIImage *)yy_imageByTintColor:(UIColor *)color; +- (nullable UIImage *)yy_imageByTintColor:(UIColor *)color; /** Returns a grayscaled image. */ -- (UIImage *)yy_imageByGrayscale; +- (nullable UIImage *)yy_imageByGrayscale; /** Applies a blur effect to this image. Suitable for blur any content. */ -- (UIImage *)yy_imageByBlurSoft; +- (nullable UIImage *)yy_imageByBlurSoft; /** Applies a blur effect to this image. Suitable for blur any content except pure white. (same as iOS Control Panel) */ -- (UIImage *)yy_imageByBlurLight; +- (nullable UIImage *)yy_imageByBlurLight; /** Applies a blur effect to this image. Suitable for displaying black text. (same as iOS Navigation Bar White) */ -- (UIImage *)yy_imageByBlurExtraLight; +- (nullable UIImage *)yy_imageByBlurExtraLight; /** Applies a blur effect to this image. Suitable for displaying white text. (same as iOS Notification Center) */ -- (UIImage *)yy_imageByBlurDark; +- (nullable UIImage *)yy_imageByBlurDark; /** Applies a blur and tint color to this image. @param tintColor The tint color. */ -- (UIImage *)yy_imageByBlurWithTint:(UIColor *)tintColor; +- (nullable UIImage *)yy_imageByBlurWithTint:(UIColor *)tintColor; /** Applies a blur, tint color, and saturation adjustment to this image, @@ -280,10 +305,12 @@ @return image with effect, or nil if an error occurs (e.g. no enough memory). */ -- (UIImage *)yy_imageByBlurRadius:(CGFloat)blurRadius - tintColor:(UIColor *)tintColor - tintMode:(CGBlendMode)tintBlendMode - saturation:(CGFloat)saturation - maskImage:(UIImage *)maskImage; +- (nullable UIImage *)yy_imageByBlurRadius:(CGFloat)blurRadius + tintColor:(nullable UIColor *)tintColor + tintMode:(CGBlendMode)tintBlendMode + saturation:(CGFloat)saturation + maskImage:(nullable UIImage *)maskImage; @end + +NS_ASSUME_NONNULL_END diff --git a/YYWebImage/Categories/UIImage+YYWebImage.m b/YYWebImage/Categories/UIImage+YYWebImage.m index 6da134a..2cb0496 100644 --- a/YYWebImage/Categories/UIImage+YYWebImage.m +++ b/YYWebImage/Categories/UIImage+YYWebImage.m @@ -49,11 +49,18 @@ static CGRect _YYCGRectFitWithContentMode(CGRect rect, CGSize size, UIViewConten rect.size = CGSizeZero; } else { CGFloat scale; - if (size.width / size.height < rect.size.width / rect.size.height && - mode == UIViewContentModeScaleAspectFit) { - scale = rect.size.height / size.height; + if (mode == UIViewContentModeScaleAspectFit) { + if (size.width / size.height < rect.size.width / rect.size.height) { + scale = rect.size.height / size.height; + } else { + scale = rect.size.width / size.width; + } } else { - scale = rect.size.width / size.width; + if (size.width / size.height < rect.size.width / rect.size.height) { + scale = rect.size.width / size.width; + } else { + scale = rect.size.height / size.height; + } } size.width *= scale; size.height *= scale; @@ -214,7 +221,7 @@ + (UIImage *)yy_imageWithSmallGIFData:(NSData *)data scale:(CGFloat)scale { CFRelease(imageRef); return nil; } - UIImage *image = image = [UIImage imageWithCGImage:decoded scale:scale orientation:UIImageOrientationUp]; + UIImage *image = [UIImage imageWithCGImage:decoded scale:scale orientation:UIImageOrientationUp]; CGImageRelease(imageRef); CGImageRelease(decoded); if (!image) { @@ -337,10 +344,30 @@ - (UIImage *)yy_imageByInsetEdge:(UIEdgeInsets)insets withColor:(UIColor *)color } - (UIImage *)yy_imageByRoundCornerRadius:(CGFloat)radius { - return [self yy_imageByRoundCornerRadius:radius corners:UIRectCornerAllCorners borderWidth:0]; + return [self yy_imageByRoundCornerRadius:radius borderWidth:0 borderColor:nil]; } -- (UIImage *)yy_imageByRoundCornerRadius:(CGFloat)radius corners:(UIRectCorner)corners borderWidth:(CGFloat)borderWidth { +- (UIImage *)yy_imageByRoundCornerRadius:(CGFloat)radius + borderWidth:(CGFloat)borderWidth + borderColor:(UIColor *)borderColor { + return [self yy_imageByRoundCornerRadius:radius corners:UIRectCornerAllCorners borderWidth:borderWidth borderColor:borderColor borderLineJoin:kCGLineJoinMiter]; +} + +- (UIImage *)yy_imageByRoundCornerRadius:(CGFloat)radius + corners:(UIRectCorner)corners + borderWidth:(CGFloat)borderWidth + borderColor:(UIColor *)borderColor + borderLineJoin:(CGLineJoin)borderLineJoin { + + if (corners != UIRectCornerAllCorners) { + UIRectCorner tmp = 0; + if (corners & UIRectCornerTopLeft) tmp |= UIRectCornerBottomLeft; + if (corners & UIRectCornerTopRight) tmp |= UIRectCornerBottomRight; + if (corners & UIRectCornerBottomLeft) tmp |= UIRectCornerTopLeft; + if (corners & UIRectCornerBottomRight) tmp |= UIRectCornerTopRight; + corners = tmp; + } + UIGraphicsBeginImageContextWithOptions(self.size, NO, self.scale); CGContextRef context = UIGraphicsGetCurrentContext(); CGRect rect = CGRectMake(0, 0, self.size.width, self.size.height); @@ -349,9 +376,28 @@ - (UIImage *)yy_imageByRoundCornerRadius:(CGFloat)radius corners:(UIRectCorner)c CGFloat minSize = MIN(self.size.width, self.size.height); if (borderWidth < minSize / 2) { - [[UIBezierPath bezierPathWithRoundedRect:CGRectInset(rect, borderWidth, borderWidth) byRoundingCorners:corners cornerRadii:CGSizeMake(radius, borderWidth)] addClip]; + UIBezierPath *path = [UIBezierPath bezierPathWithRoundedRect:CGRectInset(rect, borderWidth, borderWidth) byRoundingCorners:corners cornerRadii:CGSizeMake(radius, borderWidth)]; + [path closePath]; + + CGContextSaveGState(context); + [path addClip]; CGContextDrawImage(context, rect, self.CGImage); + CGContextRestoreGState(context); + } + + if (borderColor && borderWidth < minSize / 2 && borderWidth > 0) { + CGFloat strokeInset = (floor(borderWidth * self.scale) + 0.5) / self.scale; + CGRect strokeRect = CGRectInset(rect, strokeInset, strokeInset); + CGFloat strokeRadius = radius > self.scale / 2 ? radius - self.scale / 2 : 0; + UIBezierPath *path = [UIBezierPath bezierPathWithRoundedRect:strokeRect byRoundingCorners:corners cornerRadii:CGSizeMake(strokeRadius, borderWidth)]; + [path closePath]; + + path.lineWidth = borderWidth; + path.lineJoinStyle = borderLineJoin; + [borderColor setStroke]; + [path stroke]; } + UIImage *image = UIGraphicsGetImageFromCurrentImageContext(); UIGraphicsEndImageContext(); return image; diff --git a/YYWebImage/Categories/UIImageView+YYWebImage.h b/YYWebImage/Categories/UIImageView+YYWebImage.h index 11f32c1..6a66233 100644 --- a/YYWebImage/Categories/UIImageView+YYWebImage.h +++ b/YYWebImage/Categories/UIImageView+YYWebImage.h @@ -17,6 +17,7 @@ #import "YYWebImageManager.h" #endif +NS_ASSUME_NONNULL_BEGIN /** Web image methods for UIImageView. @@ -32,7 +33,7 @@ operation and create a new request operation to fetch image. Set nil to clear the image and image URL. */ -@property (nonatomic, strong) NSURL *yy_imageURL; +@property (nullable, nonatomic, strong) NSURL *yy_imageURL; /** Set the view's `image` with a specified URL. @@ -40,7 +41,7 @@ @param imageURL The image url (remote or local file path). @param placeholder The image to be set initially, until the image request finishes. */ -- (void)yy_setImageWithURL:(NSURL *)imageURL placeholder:(UIImage *)placeholder; +- (void)yy_setImageWithURL:(nullable NSURL *)imageURL placeholder:(nullable UIImage *)placeholder; /** Set the view's `image` with a specified URL. @@ -48,7 +49,7 @@ @param imageURL The image url (remote or local file path). @param options The options to use when request the image. */ -- (void)yy_setImageWithURL:(NSURL *)imageURL options:(YYWebImageOptions)options; +- (void)yy_setImageWithURL:(nullable NSURL *)imageURL options:(YYWebImageOptions)options; /** Set the view's `image` with a specified URL. @@ -58,10 +59,10 @@ @param options The options to use when request the image. @param completion The block invoked (on main thread) when image request completed. */ -- (void)yy_setImageWithURL:(NSURL *)imageURL - placeholder:(UIImage *)placeholder +- (void)yy_setImageWithURL:(nullable NSURL *)imageURL + placeholder:(nullable UIImage *)placeholder options:(YYWebImageOptions)options - completion:(YYWebImageCompletionBlock)completion; + completion:(nullable YYWebImageCompletionBlock)completion; /** Set the view's `image` with a specified URL. @@ -73,12 +74,12 @@ @param transform The block invoked (on background thread) to do additional image process. @param completion The block invoked (on main thread) when image request completed. */ -- (void)yy_setImageWithURL:(NSURL *)imageURL - placeholder:(UIImage *)placeholder +- (void)yy_setImageWithURL:(nullable NSURL *)imageURL + placeholder:(nullable UIImage *)placeholder options:(YYWebImageOptions)options - progress:(YYWebImageProgressBlock)progress - transform:(YYWebImageTransformBlock)transform - completion:(YYWebImageCompletionBlock)completion; + progress:(nullable YYWebImageProgressBlock)progress + transform:(nullable YYWebImageTransformBlock)transform + completion:(nullable YYWebImageCompletionBlock)completion; /** Set the view's `image` with a specified URL. @@ -91,13 +92,13 @@ @param transform The block invoked (on background thread) to do additional image process. @param completion The block invoked (on main thread) when image request completed. */ -- (void)yy_setImageWithURL:(NSURL *)imageURL - placeholder:(UIImage *)placeholder +- (void)yy_setImageWithURL:(nullable NSURL *)imageURL + placeholder:(nullable UIImage *)placeholder options:(YYWebImageOptions)options - manager:(YYWebImageManager *)manager - progress:(YYWebImageProgressBlock)progress - transform:(YYWebImageTransformBlock)transform - completion:(YYWebImageCompletionBlock)completion; + manager:(nullable YYWebImageManager *)manager + progress:(nullable YYWebImageProgressBlock)progress + transform:(nullable YYWebImageTransformBlock)transform + completion:(nullable YYWebImageCompletionBlock)completion; /** Cancel the current image request. @@ -115,7 +116,7 @@ operation and create a new request operation to fetch image. Set nil to clear the highlighted image and image URL. */ -@property (nonatomic, strong) NSURL *yy_highlightedImageURL; +@property (nullable, nonatomic, strong) NSURL *yy_highlightedImageURL; /** Set the view's `highlightedImage` with a specified URL. @@ -123,7 +124,7 @@ @param imageURL The image url (remote or local file path). @param placeholder The image to be set initially, until the image request finishes. */ -- (void)yy_setHighlightedImageWithURL:(NSURL *)imageURL placeholder:(UIImage *)placeholder; +- (void)yy_setHighlightedImageWithURL:(nullable NSURL *)imageURL placeholder:(nullable UIImage *)placeholder; /** Set the view's `highlightedImage` with a specified URL. @@ -131,7 +132,7 @@ @param imageURL The image url (remote or local file path). @param options The options to use when request the image. */ -- (void)yy_setHighlightedImageWithURL:(NSURL *)imageURL options:(YYWebImageOptions)options; +- (void)yy_setHighlightedImageWithURL:(nullable NSURL *)imageURL options:(YYWebImageOptions)options; /** Set the view's `highlightedImage` with a specified URL. @@ -141,10 +142,10 @@ @param options The options to use when request the image. @param completion The block invoked (on main thread) when image request completed. */ -- (void)yy_setHighlightedImageWithURL:(NSURL *)imageURL - placeholder:(UIImage *)placeholder +- (void)yy_setHighlightedImageWithURL:(nullable NSURL *)imageURL + placeholder:(nullable UIImage *)placeholder options:(YYWebImageOptions)options - completion:(YYWebImageCompletionBlock)completion; + completion:(nullable YYWebImageCompletionBlock)completion; /** Set the view's `highlightedImage` with a specified URL. @@ -156,31 +157,31 @@ @param transform The block invoked (on background thread) to do additional image process. @param completion The block invoked (on main thread) when image request completed. */ -- (void)yy_setHighlightedImageWithURL:(NSURL *)imageURL - placeholder:(UIImage *)placeholder +- (void)yy_setHighlightedImageWithURL:(nullable NSURL *)imageURL + placeholder:(nullable UIImage *)placeholder options:(YYWebImageOptions)options - progress:(YYWebImageProgressBlock)progress - transform:(YYWebImageTransformBlock)transform - completion:(YYWebImageCompletionBlock)completion; + progress:(nullable YYWebImageProgressBlock)progress + transform:(nullable YYWebImageTransformBlock)transform + completion:(nullable YYWebImageCompletionBlock)completion; /** Set the view's `highlightedImage` with a specified URL. @param imageURL The image url (remote or local file path). - @param placeholder he image to be set initially, until the image request finishes. + @param placeholder The image to be set initially, until the image request finishes. @param options The options to use when request the image. @param manager The manager to create image request operation. @param progress The block invoked (on main thread) during image request. @param transform The block invoked (on background thread) to do additional image process. @param completion The block invoked (on main thread) when image request completed. */ -- (void)yy_setHighlightedImageWithURL:(NSURL *)imageURL - placeholder:(UIImage *)placeholder +- (void)yy_setHighlightedImageWithURL:(nullable NSURL *)imageURL + placeholder:(nullable UIImage *)placeholder options:(YYWebImageOptions)options - manager:(YYWebImageManager *)manager - progress:(YYWebImageProgressBlock)progress - transform:(YYWebImageTransformBlock)transform - completion:(YYWebImageCompletionBlock)completion; + manager:(nullable YYWebImageManager *)manager + progress:(nullable YYWebImageProgressBlock)progress + transform:(nullable YYWebImageTransformBlock)transform + completion:(nullable YYWebImageCompletionBlock)completion; /** Cancel the current highlighed image request. @@ -188,3 +189,5 @@ - (void)yy_cancelCurrentHighlightedImageRequest; @end + +NS_ASSUME_NONNULL_END diff --git a/YYWebImage/Categories/UIImageView+YYWebImage.m b/YYWebImage/Categories/UIImageView+YYWebImage.m index ff15de7..1719a12 100644 --- a/YYWebImage/Categories/UIImageView+YYWebImage.m +++ b/YYWebImage/Categories/UIImageView+YYWebImage.m @@ -149,12 +149,15 @@ - (void)yy_setImageWithURL:(NSURL *)imageURL }); }; + __block int32_t newSentinel = 0; + __block __weak typeof(setter) weakSetter = nil; YYWebImageCompletionBlock _completion = ^(UIImage *image, NSURL *url, YYWebImageFromType from, YYWebImageStage stage, NSError *error) { __strong typeof(_self) self = _self; BOOL setImage = (stage == YYWebImageStageFinished || stage == YYWebImageStageProgress) && image && !(options & YYWebImageOptionAvoidSetImage); - BOOL showFade = ((options & YYWebImageOptionSetImageWithFadeAnimation) && !self.highlighted); dispatch_async(dispatch_get_main_queue(), ^{ - if (setImage && self) { + BOOL sentinelChanged = weakSetter && weakSetter.sentinel != newSentinel; + if (setImage && self && !sentinelChanged) { + BOOL showFade = ((options & YYWebImageOptionSetImageWithFadeAnimation) && !self.highlighted); if (showFade) { CATransition *transition = [CATransition animation]; transition.duration = stage == YYWebImageStageFinished ? _YYWebImageFadeTime : _YYWebImageProgressiveFadeTime; @@ -164,11 +167,18 @@ - (void)yy_setImageWithURL:(NSURL *)imageURL } self.image = image; } - if (completion) completion(image, url, from, stage, error); + if (completion) { + if (sentinelChanged) { + completion(nil, url, YYWebImageFromNone, YYWebImageStageCancelled, nil); + } else { + completion(image, url, from, stage, error); + } + } }); }; - [setter setOperationWithSentinel:sentinel url:imageURL options:options manager:manager progress:_progress transform:transform completion:_completion]; + newSentinel = [setter setOperationWithSentinel:sentinel url:imageURL options:options manager:manager progress:_progress transform:transform completion:_completion]; + weakSetter = setter; }); }); } @@ -303,12 +313,15 @@ - (void)yy_setHighlightedImageWithURL:(NSURL *)imageURL }); }; + __block int32_t newSentinel = 0; + __block __weak typeof(setter) weakSetter = nil; YYWebImageCompletionBlock _completion = ^(UIImage *image, NSURL *url, YYWebImageFromType from, YYWebImageStage stage, NSError *error) { __strong typeof(_self) self = _self; BOOL setImage = (stage == YYWebImageStageFinished || stage == YYWebImageStageProgress) && image && !(options & YYWebImageOptionAvoidSetImage); BOOL showFade = ((options & YYWebImageOptionSetImageWithFadeAnimation) && self.highlighted); dispatch_async(dispatch_get_main_queue(), ^{ - if (setImage && self) { + BOOL sentinelChanged = weakSetter && weakSetter.sentinel != newSentinel; + if (setImage && self && !sentinelChanged) { if (showFade) { CATransition *transition = [CATransition animation]; transition.duration = stage == YYWebImageStageFinished ? _YYWebImageFadeTime : _YYWebImageProgressiveFadeTime; @@ -318,11 +331,18 @@ - (void)yy_setHighlightedImageWithURL:(NSURL *)imageURL } self.highlightedImage = image; } - if (completion) completion(image, url, from, stage, error); + if (completion) { + if (sentinelChanged) { + completion(nil, url, YYWebImageFromNone, YYWebImageStageCancelled, nil); + } else { + completion(image, url, from, stage, error); + } + } }); }; - [setter setOperationWithSentinel:sentinel url:imageURL options:options manager:manager progress:_progress transform:transform completion:_completion]; + newSentinel = [setter setOperationWithSentinel:sentinel url:imageURL options:options manager:manager progress:_progress transform:transform completion:_completion]; + weakSetter = setter; }); }); } diff --git a/YYWebImage/Categories/_YYWebImageSetter.h b/YYWebImage/Categories/_YYWebImageSetter.h index 2764cfa..cf5a118 100644 --- a/YYWebImage/Categories/_YYWebImageSetter.h +++ b/YYWebImage/Categories/_YYWebImageSetter.h @@ -17,6 +17,7 @@ #import "YYWebImageManager.h" #endif +NS_ASSUME_NONNULL_BEGIN /** Submits a block for execution on a main queue and waits until the block completes. @@ -39,24 +40,28 @@ extern const NSTimeInterval _YYWebImageProgressiveFadeTime; */ @interface _YYWebImageSetter : NSObject /// Current image url. -@property (nonatomic, readonly) NSURL *imageURL; +@property (nullable, nonatomic, readonly) NSURL *imageURL; +/// Current sentinel. +@property (nonatomic, readonly) int32_t sentinel; -/// Create new operation for web image. -- (void)setOperationWithSentinel:(int32_t)sentinel - url:(NSURL *)imageURL - options:(YYWebImageOptions)options - manager:(YYWebImageManager *)manager - progress:(YYWebImageProgressBlock)progress - transform:(YYWebImageTransformBlock)transform - completion:(YYWebImageCompletionBlock)completion; +/// Create new operation for web image and return a sentinel value. +- (int32_t)setOperationWithSentinel:(int32_t)sentinel + url:(nullable NSURL *)imageURL + options:(YYWebImageOptions)options + manager:(YYWebImageManager *)manager + progress:(nullable YYWebImageProgressBlock)progress + transform:(nullable YYWebImageTransformBlock)transform + completion:(nullable YYWebImageCompletionBlock)completion; /// Cancel and return a sentinel value. The imageURL will be set to nil. - (int32_t)cancel; /// Cancel and return a sentinel value. The imageURL will be set to new value. -- (int32_t)cancelWithNewURL:(NSURL *)imageURL; +- (int32_t)cancelWithNewURL:(nullable NSURL *)imageURL; /// A queue to set operation. + (dispatch_queue_t)setterQueue; @end + +NS_ASSUME_NONNULL_END diff --git a/YYWebImage/Categories/_YYWebImageSetter.m b/YYWebImage/Categories/_YYWebImageSetter.m index 6052471..ec3c99b 100644 --- a/YYWebImage/Categories/_YYWebImageSetter.m +++ b/YYWebImage/Categories/_YYWebImageSetter.m @@ -19,7 +19,7 @@ @implementation _YYWebImageSetter { - OSSpinLock _lock; + dispatch_semaphore_t _lock; NSURL *_imageURL; NSOperation *_operation; int32_t _sentinel; @@ -27,14 +27,14 @@ @implementation _YYWebImageSetter { - (instancetype)init { self = [super init]; - _lock = OS_SPINLOCK_INIT; + _lock = dispatch_semaphore_create(1); return self; } - (NSURL *)imageURL { - OSSpinLockLock(&_lock); + dispatch_semaphore_wait(_lock, DISPATCH_TIME_FOREVER); NSURL *imageURL = _imageURL; - OSSpinLockUnlock(&_lock); + dispatch_semaphore_signal(_lock); return imageURL; } @@ -43,16 +43,16 @@ - (void)dealloc { [_operation cancel]; } -- (void)setOperationWithSentinel:(int32_t)sentinel - url:(NSURL *)imageURL - options:(YYWebImageOptions)options - manager:(YYWebImageManager *)manager - progress:(YYWebImageProgressBlock)progress - transform:(YYWebImageTransformBlock)transform - completion:(YYWebImageCompletionBlock)completion { +- (int32_t)setOperationWithSentinel:(int32_t)sentinel + url:(NSURL *)imageURL + options:(YYWebImageOptions)options + manager:(YYWebImageManager *)manager + progress:(YYWebImageProgressBlock)progress + transform:(YYWebImageTransformBlock)transform + completion:(YYWebImageCompletionBlock)completion { if (sentinel != _sentinel) { if (completion) completion(nil, imageURL, YYWebImageFromNone, YYWebImageStageCancelled, nil); - return; + return _sentinel; } NSOperation *operation = [manager requestImageWithURL:imageURL options:options progress:progress transform:transform completion:completion]; @@ -61,15 +61,16 @@ - (void)setOperationWithSentinel:(int32_t)sentinel completion(nil, imageURL, YYWebImageFromNone, YYWebImageStageFinished, [NSError errorWithDomain:@"com.ibireme.webimage" code:-1 userInfo:userInfo]); } - OSSpinLockLock(&_lock); + dispatch_semaphore_wait(_lock, DISPATCH_TIME_FOREVER); if (sentinel == _sentinel) { if (_operation) [_operation cancel]; _operation = operation; - OSAtomicIncrement32(&_sentinel); + sentinel = OSAtomicIncrement32(&_sentinel); } else { [operation cancel]; } - OSSpinLockUnlock(&_lock); + dispatch_semaphore_signal(_lock); + return sentinel; } - (int32_t)cancel { @@ -78,14 +79,14 @@ - (int32_t)cancel { - (int32_t)cancelWithNewURL:(NSURL *)imageURL { int32_t sentinel; - OSSpinLockLock(&_lock); + dispatch_semaphore_wait(_lock, DISPATCH_TIME_FOREVER); if (_operation) { [_operation cancel]; _operation = nil; } _imageURL = imageURL; sentinel = OSAtomicIncrement32(&_sentinel); - OSSpinLockUnlock(&_lock); + dispatch_semaphore_signal(_lock); return sentinel; } diff --git a/YYWebImage/Image/YYAnimatedImageView.h b/YYWebImage/Image/YYAnimatedImageView.h index 7448a3a..e70a654 100644 --- a/YYWebImage/Image/YYAnimatedImageView.h +++ b/YYWebImage/Image/YYAnimatedImageView.h @@ -11,6 +11,8 @@ #import +NS_ASSUME_NONNULL_BEGIN + /** An image view for displaying animated image. @@ -38,7 +40,7 @@ The default value is `YES`. */ -@property (nonatomic, assign) BOOL autoPlayAnimatedImage; +@property (nonatomic) BOOL autoPlayAnimatedImage; /** Index of the currently displayed frame (index from 0). @@ -48,7 +50,7 @@ You can add an observer to this property to observe the playing status. */ -@property (nonatomic, assign) NSUInteger currentAnimatedImageIndex; +@property (nonatomic) NSUInteger currentAnimatedImageIndex; /** Whether the image view is playing animation currently. @@ -76,7 +78,7 @@ When receive memory warning or app enter background, the buffer will be released immediately, and may grow back at the right time. */ -@property (nonatomic, assign) NSUInteger maxBufferSize; +@property (nonatomic) NSUInteger maxBufferSize; @end @@ -107,7 +109,7 @@ /// Returns the frame image from a specified index. /// This method may be called on background thread. /// @param index Frame index (zero based). -- (UIImage *)animatedImageFrameAtIndex:(NSUInteger)index; +- (nullable UIImage *)animatedImageFrameAtIndex:(NSUInteger)index; /// Returns the frames's duration from a specified index. /// @param index Frame index (zero based). @@ -119,3 +121,5 @@ /// It may used to display sprite animation with a single image (sprite sheet). - (CGRect)animatedImageContentsRectAtIndex:(NSUInteger)index; @end + +NS_ASSUME_NONNULL_END diff --git a/YYWebImage/Image/YYAnimatedImageView.m b/YYWebImage/Image/YYAnimatedImageView.m index 9f9a2e3..07ee652 100644 --- a/YYWebImage/Image/YYAnimatedImageView.m +++ b/YYWebImage/Image/YYAnimatedImageView.m @@ -12,19 +12,18 @@ #import "YYAnimatedImageView.h" #import "YYImageCoder.h" #import -#import #import #define BUFFER_SIZE (10 * 1024 * 1024) // 10MB (minimum memory buffer size) -#define LOCK(...) OSSpinLockLock(&self->_lock); \ +#define LOCK(...) dispatch_semaphore_wait(self->_lock, DISPATCH_TIME_FOREVER); \ __VA_ARGS__; \ -OSSpinLockUnlock(&self->_lock); +dispatch_semaphore_signal(self->_lock); -#define LOCK_VIEW(...) OSSpinLockLock(&view->_lock); \ +#define LOCK_VIEW(...) dispatch_semaphore_wait(view->_lock, DISPATCH_TIME_FOREVER); \ __VA_ARGS__; \ -OSSpinLockUnlock(&view->_lock); +dispatch_semaphore_signal(view->_lock); static int64_t _YYDeviceMemoryTotal() { @@ -113,20 +112,19 @@ - (NSString *)debugDescription { -typedef NS_ENUM(NSUInteger, YYAnimagedImageType) { - YYAnimagedImageTypeNone = 0, - YYAnimagedImageTypeImage, - YYAnimagedImageTypeHighlightedImage, - YYAnimagedImageTypeImages, - YYAnimagedImageTypeHighlightedImages, +typedef NS_ENUM(NSUInteger, YYAnimatedImageType) { + YYAnimatedImageTypeNone = 0, + YYAnimatedImageTypeImage, + YYAnimatedImageTypeHighlightedImage, + YYAnimatedImageTypeImages, + YYAnimatedImageTypeHighlightedImages, }; @interface YYAnimatedImageView() { @package UIImage *_curAnimatedImage; - dispatch_once_t _onceToken; - OSSpinLock _lock; ///< lock for _buffer + dispatch_semaphore_t _lock; ///< lock for _buffer NSOperationQueue *_requestQueue; ///< image request queue, serial CADisplayLink *_link; ///< ticker for change frame @@ -136,7 +134,7 @@ @interface YYAnimatedImageView() { NSUInteger _curIndex; ///< current frame index (from 0) NSUInteger _totalFrameCount; ///< total frame count - BOOL _loopEnd; ///< weather the loop is end. + BOOL _loopEnd; ///< whether the loop is end. NSUInteger _curLoop; ///< current loop count (from 0) NSUInteger _totalLoop; ///< total loop count, 0 means infinity @@ -166,22 +164,28 @@ - (void)main { if ([self isCancelled]) return; view->_incrBufferCount++; if (view->_incrBufferCount == 0) [view calcMaxBufferCount]; - if ((int)view->_incrBufferCount > (int)view->_maxBufferCount) { + if (view->_incrBufferCount > (NSInteger)view->_maxBufferCount) { view->_incrBufferCount = view->_maxBufferCount; } NSUInteger idx = _nextIndex; NSUInteger max = view->_incrBufferCount < 1 ? 1 : view->_incrBufferCount; NSUInteger total = view->_totalFrameCount; + view = nil; + for (int i = 0; i < max; i++, idx++) { @autoreleasepool { if (idx >= total) idx = 0; if ([self isCancelled]) break; + __strong YYAnimatedImageView *view = _view; + if (!view) break; LOCK_VIEW(BOOL miss = (view->_buffer[@(idx)] == nil)); + if (miss) { UIImage *img = [_curImage animatedImageFrameAtIndex:idx]; - img = [img yy_imageByDecoded]; + img = img.yy_imageByDecoded; if ([self isCancelled]) break; LOCK_VIEW(view->_buffer[@(idx)] = img ? img : [NSNull null]); + view = nil; } } } @@ -197,6 +201,13 @@ - (instancetype)init { return self; } +- (instancetype)initWithFrame:(CGRect)frame { + self = [super initWithFrame:frame]; + _runloopMode = NSRunLoopCommonModes; + _autoPlayAnimatedImage = YES; + return self; +} + - (instancetype)initWithImage:(UIImage *)image { self = [super init]; _runloopMode = NSRunLoopCommonModes; @@ -219,8 +230,8 @@ - (instancetype)initWithImage:(UIImage *)image highlightedImage:(UIImage *)highl // init the animated params. - (void)resetAnimated { - dispatch_once(&_onceToken, ^{ - _lock = OS_SPINLOCK_INIT; + if (!_link) { + _lock = dispatch_semaphore_create(1); _buffer = [NSMutableDictionary new]; _requestQueue = [[NSOperationQueue alloc] init]; _requestQueue.maxConcurrentOperationCount = 1; @@ -232,7 +243,7 @@ - (void)resetAnimated { [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(didReceiveMemoryWarning:) name:UIApplicationDidReceiveMemoryWarningNotification object:nil]; [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(didEnterBackground:) name:UIApplicationDidEnterBackgroundNotification object:nil]; - }); + } [_requestQueue cancelAllOperations]; LOCK( @@ -265,22 +276,22 @@ - (void)resetAnimated { - (void)setImage:(UIImage *)image { if (self.image == image) return; - [self setImage:image withType:YYAnimagedImageTypeImage]; + [self setImage:image withType:YYAnimatedImageTypeImage]; } - (void)setHighlightedImage:(UIImage *)highlightedImage { if (self.highlightedImage == highlightedImage) return; - [self setImage:highlightedImage withType:YYAnimagedImageTypeHighlightedImage]; + [self setImage:highlightedImage withType:YYAnimatedImageTypeHighlightedImage]; } - (void)setAnimationImages:(NSArray *)animationImages { if (self.animationImages == animationImages) return; - [self setImage:animationImages withType:YYAnimagedImageTypeImages]; + [self setImage:animationImages withType:YYAnimatedImageTypeImages]; } - (void)setHighlightedAnimationImages:(NSArray *)highlightedAnimationImages { if (self.highlightedAnimationImages == highlightedAnimationImages) return; - [self setImage:highlightedAnimationImages withType:YYAnimagedImageTypeHighlightedImages]; + [self setImage:highlightedAnimationImages withType:YYAnimatedImageTypeHighlightedImages]; } - (void)setHighlighted:(BOOL)highlighted { @@ -289,46 +300,46 @@ - (void)setHighlighted:(BOOL)highlighted { [self imageChanged]; } -- (id)imageForType:(YYAnimagedImageType)type { +- (id)imageForType:(YYAnimatedImageType)type { switch (type) { - case YYAnimagedImageTypeNone: return nil; - case YYAnimagedImageTypeImage: return self.image; - case YYAnimagedImageTypeHighlightedImage: return self.highlightedImage; - case YYAnimagedImageTypeImages: return self.animationImages; - case YYAnimagedImageTypeHighlightedImages: return self.highlightedAnimationImages; + case YYAnimatedImageTypeNone: return nil; + case YYAnimatedImageTypeImage: return self.image; + case YYAnimatedImageTypeHighlightedImage: return self.highlightedImage; + case YYAnimatedImageTypeImages: return self.animationImages; + case YYAnimatedImageTypeHighlightedImages: return self.highlightedAnimationImages; } return nil; } -- (YYAnimagedImageType)currentImageType { - YYAnimagedImageType curType = YYAnimagedImageTypeNone; +- (YYAnimatedImageType)currentImageType { + YYAnimatedImageType curType = YYAnimatedImageTypeNone; if (self.highlighted) { - if (self.highlightedAnimationImages.count) curType = YYAnimagedImageTypeHighlightedImages; - else if (self.highlightedImage) curType = YYAnimagedImageTypeHighlightedImage; + if (self.highlightedAnimationImages.count) curType = YYAnimatedImageTypeHighlightedImages; + else if (self.highlightedImage) curType = YYAnimatedImageTypeHighlightedImage; } - if (curType == YYAnimagedImageTypeNone) { - if (self.animationImages.count) curType = YYAnimagedImageTypeImages; - else if (self.image) curType = YYAnimagedImageTypeImage; + if (curType == YYAnimatedImageTypeNone) { + if (self.animationImages.count) curType = YYAnimatedImageTypeImages; + else if (self.image) curType = YYAnimatedImageTypeImage; } return curType; } -- (void)setImage:(id)image withType:(YYAnimagedImageType)type { +- (void)setImage:(id)image withType:(YYAnimatedImageType)type { [self stopAnimating]; if (_link) [self resetAnimated]; _curFrame = nil; switch (type) { - case YYAnimagedImageTypeNone: break; - case YYAnimagedImageTypeImage: super.image = image; break; - case YYAnimagedImageTypeHighlightedImage: super.highlightedImage = image; break; - case YYAnimagedImageTypeImages: super.animationImages = image; break; - case YYAnimagedImageTypeHighlightedImages: super.highlightedAnimationImages = image; break; + case YYAnimatedImageTypeNone: break; + case YYAnimatedImageTypeImage: super.image = image; break; + case YYAnimatedImageTypeHighlightedImage: super.highlightedImage = image; break; + case YYAnimatedImageTypeImages: super.animationImages = image; break; + case YYAnimatedImageTypeHighlightedImages: super.highlightedAnimationImages = image; break; } [self imageChanged]; } - (void)imageChanged { - YYAnimagedImageType newType = [self currentImageType]; + YYAnimatedImageType newType = [self currentImageType]; id newVisibleImage = [self imageForType:newType]; NSUInteger newImageFrameCount = 0; BOOL hasContentsRect = NO; @@ -367,16 +378,18 @@ - (void)imageChanged { // dynamically adjust buffer size for current memory. - (void)calcMaxBufferCount { - NSUInteger bytes = _curAnimatedImage.animatedImageBytesPerFrame; - if (bytes == 0) bytes = 1; + int64_t bytes = (int64_t)_curAnimatedImage.animatedImageBytesPerFrame; + if (bytes == 0) bytes = 1024; int64_t total = _YYDeviceMemoryTotal(); int64_t free = _YYDeviceMemoryFree(); int64_t max = MIN(total * 0.2, free * 0.6); max = MAX(max, BUFFER_SIZE); if (_maxBufferSize) max = max > _maxBufferSize ? _maxBufferSize : max; - _maxBufferCount = (float)max / (float)bytes; - if (_maxBufferCount == 0) _maxBufferCount = 1; + double maxBufferCount = (double)max / (double)bytes; + if (maxBufferCount < 1) maxBufferCount = 1; + else if (maxBufferCount > 512) maxBufferCount = 512; + _maxBufferCount = maxBufferCount; } - (void)dealloc { @@ -392,13 +405,14 @@ - (BOOL)isAnimating { - (void)stopAnimating { [super stopAnimating]; + [_requestQueue cancelAllOperations]; _link.paused = YES; self.currentIsPlayingAnimation = NO; } - (void)startAnimating { - YYAnimagedImageType type = [self currentImageType]; - if (type == YYAnimagedImageTypeImages || type == YYAnimagedImageTypeHighlightedImages) { + YYAnimatedImageType type = [self currentImageType]; + if (type == YYAnimatedImageTypeImages || type == YYAnimatedImageTypeHighlightedImages) { NSArray *images = [self imageForType:type]; if (images.count > 0) { [super startAnimating]; @@ -605,7 +619,7 @@ - (void)setRunloopMode:(NSString *)runloopMode { _runloopMode = runloopMode.copy; } -#pragma mark - Overrice NSObject(NSKeyValueObservingCustomization) +#pragma mark - Override NSObject(NSKeyValueObservingCustomization) + (BOOL)automaticallyNotifiesObserversForKey:(NSString *)key { if ([key isEqualToString:@"currentAnimatedImageIndex"]) { @@ -620,17 +634,21 @@ - (instancetype)initWithCoder:(NSCoder *)aDecoder { self = [super initWithCoder:aDecoder]; _runloopMode = [aDecoder decodeObjectForKey:@"runloopMode"]; if (_runloopMode.length == 0) _runloopMode = NSRunLoopCommonModes; - _autoPlayAnimatedImage = [aDecoder decodeBoolForKey:@"autoPlayAnimatedImage"]; + if ([aDecoder containsValueForKey:@"autoPlayAnimatedImage"]) { + _autoPlayAnimatedImage = [aDecoder decodeBoolForKey:@"autoPlayAnimatedImage"]; + } else { + _autoPlayAnimatedImage = YES; + } UIImage *image = [aDecoder decodeObjectForKey:@"YYAnimatedImage"]; UIImage *highlightedImage = [aDecoder decodeObjectForKey:@"YYHighlightedAnimatedImage"]; if (image) { self.image = image; - [self setImage:image withType:YYAnimagedImageTypeImage]; + [self setImage:image withType:YYAnimatedImageTypeImage]; } if (highlightedImage) { self.highlightedImage = highlightedImage; - [self setImage:highlightedImage withType:YYAnimagedImageTypeHighlightedImage]; + [self setImage:highlightedImage withType:YYAnimatedImageTypeHighlightedImage]; } return self; } diff --git a/YYWebImage/Image/YYFrameImage.h b/YYWebImage/Image/YYFrameImage.h index 182a2ee..5795cc5 100644 --- a/YYWebImage/Image/YYFrameImage.h +++ b/YYWebImage/Image/YYFrameImage.h @@ -19,6 +19,8 @@ #import "YYAnimatedImageView.h" #endif +NS_ASSUME_NONNULL_BEGIN + /** An image to display frame-based animation. @@ -49,7 +51,9 @@ @return An initialized YYFrameImage object, or nil when an error occurs. */ -- (instancetype)initWithImagePaths:(NSArray *)paths oneFrameDuration:(NSTimeInterval)oneFrameDuration loopCount:(NSUInteger)loopCount; +- (nullable instancetype)initWithImagePaths:(NSArray *)paths + oneFrameDuration:(NSTimeInterval)oneFrameDuration + loopCount:(NSUInteger)loopCount; /** Create a frame animated image from files. @@ -65,7 +69,9 @@ @return An initialized YYFrameImage object, or nil when an error occurs. */ -- (instancetype)initWithImagePaths:(NSArray *)paths frameDurations:(NSArray *)frameDurations loopCount:(NSUInteger)loopCount; +- (nullable instancetype)initWithImagePaths:(NSArray *)paths + frameDurations:(NSArray *)frameDurations + loopCount:(NSUInteger)loopCount; /** Create a frame animated image from an array of data. @@ -78,7 +84,9 @@ @return An initialized YYFrameImage object, or nil when an error occurs. */ -- (instancetype)initWithImageDataArray:(NSArray *)dataArray oneFrameDuration:(NSTimeInterval)oneFrameDuration loopCount:(NSUInteger)loopCount; +- (nullable instancetype)initWithImageDataArray:(NSArray *)dataArray + oneFrameDuration:(NSTimeInterval)oneFrameDuration + loopCount:(NSUInteger)loopCount; /** Create a frame animated image from an array of data. @@ -92,6 +100,10 @@ @return An initialized YYFrameImage object, or nil when an error occurs. */ -- (instancetype)initWithImageDataArray:(NSArray *)dataArray frameDurations:(NSArray *)frameDurations loopCount:(NSUInteger)loopCount; +- (nullable instancetype)initWithImageDataArray:(NSArray *)dataArray + frameDurations:(NSArray *)frameDurations + loopCount:(NSUInteger)loopCount; @end + +NS_ASSUME_NONNULL_END diff --git a/YYWebImage/Image/YYImage.h b/YYWebImage/Image/YYImage.h index 41bfb15..0361026 100644 --- a/YYWebImage/Image/YYImage.h +++ b/YYWebImage/Image/YYImage.h @@ -30,7 +30,7 @@ FOUNDATION_EXPORT const unsigned char YYImageVersionString[]; #import "YYAnimatedImageView.h" #endif - +NS_ASSUME_NONNULL_BEGIN /** @@ -53,10 +53,10 @@ FOUNDATION_EXPORT const unsigned char YYImageVersionString[]; */ @interface YYImage : UIImage -+ (YYImage *)imageNamed:(NSString *)name; // no cache! -+ (YYImage *)imageWithContentsOfFile:(NSString *)path; -+ (YYImage *)imageWithData:(NSData *)data; -+ (YYImage *)imageWithData:(NSData *)data scale:(CGFloat)scale; ++ (nullable YYImage *)imageNamed:(NSString *)name; // no cache! ++ (nullable YYImage *)imageWithContentsOfFile:(NSString *)path; ++ (nullable YYImage *)imageWithData:(NSData *)data; ++ (nullable YYImage *)imageWithData:(NSData *)data scale:(CGFloat)scale; /** If the image is created from data or file, then the value indicates the data type. @@ -67,7 +67,7 @@ FOUNDATION_EXPORT const unsigned char YYImageVersionString[]; If the image is created from animated image data (multi-frame GIF/APNG/WebP), this property stores the original image data. */ -@property (nonatomic, readonly) NSData *animatedImageData; +@property (nullable, nonatomic, readonly) NSData *animatedImageData; /** The total memory usage (in bytes) if all frame images was loaded into memory. @@ -85,6 +85,8 @@ FOUNDATION_EXPORT const unsigned char YYImageVersionString[]; See `animatedImageMemorySize` for memory cost. */ -@property (nonatomic, assign) BOOL preloadAllAnimatedImageFrames; +@property (nonatomic) BOOL preloadAllAnimatedImageFrames; @end + +NS_ASSUME_NONNULL_END diff --git a/YYWebImage/Image/YYImage.m b/YYWebImage/Image/YYImage.m index 29bb69f..9fa7efc 100644 --- a/YYWebImage/Image/YYImage.m +++ b/YYWebImage/Image/YYImage.m @@ -10,7 +10,6 @@ // #import "YYImage.h" -#import /** An array of NSNumber objects, shows the best order for path scale search. @@ -88,7 +87,7 @@ static CGFloat _NSStringPathScale(NSString *string) { @implementation YYImage { YYImageDecoder *_decoder; NSArray *_preloadedFrames; - OSSpinLock _preloadedLock; + dispatch_semaphore_t _preloadedLock; NSUInteger _bytesPerFrame; } @@ -101,12 +100,12 @@ + (YYImage *)imageNamed:(NSString *)name { NSString *path = nil; CGFloat scale = 1; + // If no extension, guess by system supported (same as UIImage). + NSArray *exts = ext.length > 0 ? @[ext] : @[@"", @"png", @"jpeg", @"jpg", @"gif", @"webp", @"apng"]; NSArray *scales = _NSBundlePreferredScales(); for (int s = 0; s < scales.count; s++) { scale = ((NSNumber *)scales[s]).floatValue; NSString *scaledName = _NSStringByAppendingNameScale(res, scale); - // If no extension, guess by system supported (same as UIImage). - NSArray *exts = ext.length > 0 ? @[ext] : @[@"", @"png", @"jpeg", @"jpg", @"gif", @"webp"]; for (NSString *e in exts) { path = [[NSBundle mainBundle] pathForResource:scaledName ofType:e]; if (path) break; @@ -144,8 +143,8 @@ - (instancetype)initWithData:(NSData *)data { - (instancetype)initWithData:(NSData *)data scale:(CGFloat)scale { if (data.length == 0) return nil; - if (scale <= 0) scale = 1; - _preloadedLock = OS_SPINLOCK_INIT; + if (scale <= 0) scale = [UIScreen mainScreen].scale; + _preloadedLock = dispatch_semaphore_create(1); @autoreleasepool { YYImageDecoder *decoder = [YYImageDecoder decoderWithData:data scale:scale]; YYImageFrame *frame = [decoder frameAtIndex:0 decodeForDisplay:YES]; @@ -180,13 +179,13 @@ - (void)setPreloadAllAnimatedImageFrames:(BOOL)preloadAllAnimatedImageFrames { [frames addObject:[NSNull null]]; } } - OSSpinLockLock(&_preloadedLock); + dispatch_semaphore_wait(_preloadedLock, DISPATCH_TIME_FOREVER); _preloadedFrames = frames; - OSSpinLockUnlock(&_preloadedLock); + dispatch_semaphore_signal(_preloadedLock); } else { - OSSpinLockLock(&_preloadedLock); + dispatch_semaphore_wait(_preloadedLock, DISPATCH_TIME_FOREVER); _preloadedFrames = nil; - OSSpinLockUnlock(&_preloadedLock); + dispatch_semaphore_signal(_preloadedLock); } } } @@ -213,6 +212,10 @@ - (void)encodeWithCoder:(NSCoder *)aCoder { } } ++ (BOOL)supportsSecureCoding { + return YES; +} + #pragma mark - protocol YYAnimatedImage - (NSUInteger)animatedImageFrameCount { @@ -229,9 +232,9 @@ - (NSUInteger)animatedImageBytesPerFrame { - (UIImage *)animatedImageFrameAtIndex:(NSUInteger)index { if (index >= _decoder.frameCount) return nil; - OSSpinLockLock(&_preloadedLock); + dispatch_semaphore_wait(_preloadedLock, DISPATCH_TIME_FOREVER); UIImage *image = _preloadedFrames[index]; - OSSpinLockUnlock(&_preloadedLock); + dispatch_semaphore_signal(_preloadedLock); if (image) return image == (id)[NSNull null] ? nil : image; return [_decoder frameAtIndex:index decodeForDisplay:YES].image; } diff --git a/YYWebImage/Image/YYImageCoder.h b/YYWebImage/Image/YYImageCoder.h index 6330b1e..31299e7 100644 --- a/YYWebImage/Image/YYImageCoder.h +++ b/YYWebImage/Image/YYImageCoder.h @@ -11,6 +11,8 @@ #import +NS_ASSUME_NONNULL_BEGIN + /** Image file type. */ @@ -76,15 +78,15 @@ typedef NS_ENUM(NSUInteger, YYImageBlendOperation) { An image frame object. */ @interface YYImageFrame : NSObject -@property (nonatomic, assign) NSUInteger index; ///< Frame index (zero based) -@property (nonatomic, assign) NSUInteger width; ///< Frame width -@property (nonatomic, assign) NSUInteger height; ///< Frame height -@property (nonatomic, assign) NSUInteger offsetX; ///< Frame origin.x in canvas (left-bottom based) -@property (nonatomic, assign) NSUInteger offsetY; ///< Frame origin.y in canvas (left-bottom based) -@property (nonatomic, assign) NSTimeInterval duration; ///< Frame duration in seconds -@property (nonatomic, assign) YYImageDisposeMethod dispose; ///< Frame dispose method. -@property (nonatomic, assign) YYImageBlendOperation blend; ///< Frame blend operation. -@property (nonatomic, strong) UIImage *image; ///< The image. +@property (nonatomic) NSUInteger index; ///< Frame index (zero based) +@property (nonatomic) NSUInteger width; ///< Frame width +@property (nonatomic) NSUInteger height; ///< Frame height +@property (nonatomic) NSUInteger offsetX; ///< Frame origin.x in canvas (left-bottom based) +@property (nonatomic) NSUInteger offsetY; ///< Frame origin.y in canvas (left-bottom based) +@property (nonatomic) NSTimeInterval duration; ///< Frame duration in seconds +@property (nonatomic) YYImageDisposeMethod dispose; ///< Frame dispose method. +@property (nonatomic) YYImageBlendOperation blend; ///< Frame blend operation. +@property (nullable, nonatomic, strong) UIImage *image; ///< The image. + (instancetype)frameWithImage:(UIImage *)image; @end @@ -124,9 +126,9 @@ typedef NS_ENUM(NSUInteger, YYImageBlendOperation) { */ @interface YYImageDecoder : NSObject -@property (nonatomic, readonly) NSData *data; ///< Image data. -@property (nonatomic, readonly) YYImageType type; ///< Image data type. -@property (nonatomic, readonly) CGFloat scale; ///< Image scale. +@property (nullable, nonatomic, readonly) NSData *data; ///< Image data. +@property (nonatomic, readonly) YYImageType type; ///< Image data type. +@property (nonatomic, readonly) CGFloat scale; ///< Image scale. @property (nonatomic, readonly) NSUInteger frameCount; ///< Image frame count. @property (nonatomic, readonly) NSUInteger loopCount; ///< Image loop count, 0 means infinite. @property (nonatomic, readonly) NSUInteger width; ///< Image canvas width. @@ -158,7 +160,7 @@ typedef NS_ENUM(NSUInteger, YYImageBlendOperation) { @return Whether succeed. */ -- (BOOL)updateData:(NSData *)data final:(BOOL)final; +- (BOOL)updateData:(nullable NSData *)data final:(BOOL)final; /** Convenience method to create a decoder with specified data. @@ -166,7 +168,7 @@ typedef NS_ENUM(NSUInteger, YYImageBlendOperation) { @param scale Image's scale. @return A new decoder, or nil if an error occurs. */ -+ (instancetype)decoderWithData:(NSData *)data scale:(CGFloat)scale; ++ (nullable instancetype)decoderWithData:(NSData *)data scale:(CGFloat)scale; /** Decodes and returns a frame from a specified index. @@ -175,7 +177,7 @@ typedef NS_ENUM(NSUInteger, YYImageBlendOperation) { If NO, it will try to returns the original frame data without blend. @return A new frame with image, or nil if an error occurs. */ -- (YYImageFrame *)frameAtIndex:(NSUInteger)index decodeForDisplay:(BOOL)decodeForDisplay; +- (nullable YYImageFrame *)frameAtIndex:(NSUInteger)index decodeForDisplay:(BOOL)decodeForDisplay; /** Returns the frame duration from a specified index. @@ -191,13 +193,13 @@ typedef NS_ENUM(NSUInteger, YYImageBlendOperation) { @param index Frame image index (zero-based). @return The ImageIO frame property. */ -- (NSDictionary *)framePropertiesAtIndex:(NSUInteger)index; +- (nullable NSDictionary *)framePropertiesAtIndex:(NSUInteger)index; /** Returns the image's properties. See "CGImageProperties.h" in ImageIO.framework for more information. */ -- (NSDictionary *)imageProperties; +- (nullable NSDictionary *)imageProperties; @end @@ -231,10 +233,10 @@ typedef NS_ENUM(NSUInteger, YYImageBlendOperation) { */ @interface YYImageEncoder : NSObject -@property (nonatomic, readonly) YYImageType type; ///< Image type. -@property (nonatomic, assign) NSUInteger loopCount; ///< Loop count, 0 means infinit, only available for GIF/APNG/WebP. -@property (nonatomic, assign) BOOL lossless; ///< Lossless, only available for WebP. -@property (nonatomic, assign) CGFloat quality; ///< Compress quality, 0.0~1.0, only available for JPG/JP2/WebP. +@property (nonatomic, readonly) YYImageType type; ///< Image type. +@property (nonatomic) NSUInteger loopCount; ///< Loop count, 0 means infinit, only available for GIF/APNG/WebP. +@property (nonatomic) BOOL lossless; ///< Lossless, only available for WebP. +@property (nonatomic) CGFloat quality; ///< Compress quality, 0.0~1.0, only available for JPG/JP2/WebP. - (instancetype)init UNAVAILABLE_ATTRIBUTE; + (instancetype)new UNAVAILABLE_ATTRIBUTE; @@ -244,7 +246,7 @@ typedef NS_ENUM(NSUInteger, YYImageBlendOperation) { @param type Image type. @return A new encoder, or nil if an error occurs. */ -- (instancetype)initWithType:(YYImageType)type NS_DESIGNATED_INITIALIZER; +- (nullable instancetype)initWithType:(YYImageType)type NS_DESIGNATED_INITIALIZER; /** Add an image to encoder. @@ -262,7 +264,7 @@ typedef NS_ENUM(NSUInteger, YYImageBlendOperation) { /** Add an image from a file path to encoder. - @param image Image file path. + @param path Image file path. @param duration Image duration for animation. Pass 0 to ignore this parameter. */ - (void)addImageWithFile:(NSString *)path duration:(NSTimeInterval)duration; @@ -271,7 +273,7 @@ typedef NS_ENUM(NSUInteger, YYImageBlendOperation) { Encodes the image and returns the image data. @return The image data, or nil if an error occurs. */ -- (NSData *)encode; +- (nullable NSData *)encode; /** Encodes the image to a file. @@ -287,7 +289,7 @@ typedef NS_ENUM(NSUInteger, YYImageBlendOperation) { @param quality Image quality, 0.0~1.0. @return The image data, or nil if an error occurs. */ -+ (NSData *)encodeImage:(UIImage *)image type:(YYImageType)type quality:(CGFloat)quality; ++ (nullable NSData *)encodeImage:(UIImage *)image type:(YYImageType)type quality:(CGFloat)quality; /** Convenience method to encode image from a decoder. @@ -296,7 +298,7 @@ typedef NS_ENUM(NSUInteger, YYImageBlendOperation) { @param quality Image quality, 0.0~1.0. @return The image data, or nil if an error occurs. */ -+ (NSData *)encodeImageWithDecoder:(YYImageDecoder *)decoder type:(YYImageType)type quality:(CGFloat)quality; ++ (nullable NSData *)encodeImageWithDecoder:(YYImageDecoder *)decoder type:(YYImageType)type quality:(CGFloat)quality; @end @@ -319,7 +321,7 @@ typedef NS_ENUM(NSUInteger, YYImageBlendOperation) { Wherher the image can be display on screen without additional decoding. @warning It just a hint for your code, change it has no other effect. */ -@property (nonatomic, assign) BOOL yy_isDecodedForDisplay; +@property (nonatomic) BOOL yy_isDecodedForDisplay; /** Saves this image to iOS Photos Album. @@ -332,7 +334,7 @@ typedef NS_ENUM(NSUInteger, YYImageBlendOperation) { assetURL: An URL that identifies the saved image file. If the image is not saved, assetURL is nil. error: If the image is not saved, an error object that describes the reason for failure, otherwise nil. */ -- (void)yy_saveToAlbumWithCompletionBlock:(void(^)(NSURL *assetURL, NSError *error))completionBlock; +- (void)yy_saveToAlbumWithCompletionBlock:(nullable void(^)(NSURL * _Nullable assetURL, NSError * _Nullable error))completionBlock; /** Return a 'best' data representation for this image. @@ -343,7 +345,7 @@ typedef NS_ENUM(NSUInteger, YYImageBlendOperation) { @return Image data, or nil if an error occurs. */ -- (NSData *)yy_imageDataRepresentation; +- (nullable NSData *)yy_imageDataRepresentation; @end @@ -355,13 +357,13 @@ typedef NS_ENUM(NSUInteger, YYImageBlendOperation) { CG_EXTERN YYImageType YYImageDetectType(CFDataRef data); /// Convert YYImageType to UTI (such as kUTTypeJPEG). -CG_EXTERN CFStringRef YYImageTypeToUTType(YYImageType type); +CG_EXTERN CFStringRef _Nullable YYImageTypeToUTType(YYImageType type); /// Convert UTI (such as kUTTypeJPEG) to YYImageType. CG_EXTERN YYImageType YYImageTypeFromUTType(CFStringRef uti); /// Get image type's file extension (such as @"jpg"). -CG_EXTERN NSString *YYImageTypeGetExtension(YYImageType type); +CG_EXTERN NSString *_Nullable YYImageTypeGetExtension(YYImageType type); @@ -402,7 +404,7 @@ CG_EXTERN NSInteger YYUIImageOrientationToEXIFValue(UIImageOrientation orientati @return A decoded image, or NULL if an error occurs. */ -CG_EXTERN CGImageRef YYCGImageCreateDecodedCopy(CGImageRef imageRef, BOOL decodeForDisplay); +CG_EXTERN CGImageRef _Nullable YYCGImageCreateDecodedCopy(CGImageRef imageRef, BOOL decodeForDisplay); /** Create an image copy with an orientation. @@ -412,9 +414,9 @@ CG_EXTERN CGImageRef YYCGImageCreateDecodedCopy(CGImageRef imageRef, BOOL decode @param destBitmapInfo Destimation image bitmap, only support 32bit format (such as ARGB8888). @return A new image, or NULL if an error occurs. */ -CG_EXTERN CGImageRef YYCGImageCreateCopyWithOrientation(CGImageRef imageRef, - UIImageOrientation orientation, - CGBitmapInfo destBitmapInfo); +CG_EXTERN CGImageRef _Nullable YYCGImageCreateCopyWithOrientation(CGImageRef imageRef, + UIImageOrientation orientation, + CGBitmapInfo destBitmapInfo); /** Create an image copy with CGAffineTransform. @@ -425,10 +427,10 @@ CG_EXTERN CGImageRef YYCGImageCreateCopyWithOrientation(CGImageRef imageRef, @param destBitmapInfo Destimation image bitmap, only support 32bit format (such as ARGB8888). @return A new image, or NULL if an error occurs. */ -CG_EXTERN CGImageRef YYCGImageCreateAffineTransformCopy(CGImageRef imageRef, - CGAffineTransform transform, - CGSize destSize, - CGBitmapInfo destBitmapInfo); +CG_EXTERN CGImageRef _Nullable YYCGImageCreateAffineTransformCopy(CGImageRef imageRef, + CGAffineTransform transform, + CGSize destSize, + CGBitmapInfo destBitmapInfo); /** Encode an image to data with CGImageDestination. @@ -438,7 +440,7 @@ CG_EXTERN CGImageRef YYCGImageCreateAffineTransformCopy(CGImageRef imageRef, @param quality The quality (0.0~1.0) @return A new image data, or nil if an error occurs. */ -CG_EXTERN CFDataRef YYCGImageCreateEncodedData(CGImageRef imageRef, YYImageType type, CGFloat quality); +CG_EXTERN CFDataRef _Nullable YYCGImageCreateEncodedData(CGImageRef imageRef, YYImageType type, CGFloat quality); /** @@ -468,12 +470,11 @@ CG_EXTERN NSUInteger YYImageGetWebPFrameCount(CFDataRef webpData); (speed down, and may lose some details). @return The decoded image, or NULL if an error occurs. */ -CG_EXTERN CGImageRef YYCGImageCreateWithWebPData(CFDataRef webpData, - BOOL decodeForDisplay, - BOOL useThreads, - BOOL bypassFiltering, - BOOL noFancyUpsampling); - +CG_EXTERN CGImageRef _Nullable YYCGImageCreateWithWebPData(CFDataRef webpData, + BOOL decodeForDisplay, + BOOL useThreads, + BOOL bypassFiltering, + BOOL noFancyUpsampling); typedef NS_ENUM(NSUInteger, YYImagePreset) { YYImagePresetDefault = 0, ///< default preset. @@ -495,8 +496,10 @@ typedef NS_ENUM(NSUInteger, YYImagePreset) { @param preset Preset for different image type, default is YYImagePresetDefault. @return WebP data, or nil if an error occurs. */ -CG_EXTERN CFDataRef YYCGImageCreateEncodedWebPData(CGImageRef imageRef, - BOOL lossless, - CGFloat quality, - int compressLevel, - YYImagePreset preset); +CG_EXTERN CFDataRef _Nullable YYCGImageCreateEncodedWebPData(CGImageRef imageRef, + BOOL lossless, + CGFloat quality, + int compressLevel, + YYImagePreset preset); + +NS_ASSUME_NONNULL_END diff --git a/YYWebImage/Image/YYImageCoder.m b/YYWebImage/Image/YYImageCoder.m index fd5c598..66cf46e 100644 --- a/YYWebImage/Image/YYImageCoder.m +++ b/YYWebImage/Image/YYImageCoder.m @@ -19,7 +19,6 @@ #import #import #import -#import #import @@ -823,7 +822,7 @@ Try convert with vImageConvert_AnyToAny() (avaliable since iOS 7.0). } else { contextBitmapInfo |= alphaFirst ? kCGImageAlphaPremultipliedFirst : kCGImageAlphaPremultipliedLast; } - CGContextRef context = CGBitmapContextCreate(NULL, width, height, 8, 32, YYCGColorSpaceGetDeviceRGB(), contextBitmapInfo); + CGContextRef context = CGBitmapContextCreate(NULL, width, height, 8, 0, YYCGColorSpaceGetDeviceRGB(), contextBitmapInfo); if (!context) goto fail; CGContextDrawImage(context, CGRectMake(0, 0, width, height), srcImage); // decode and convert @@ -924,7 +923,7 @@ CGImageRef YYCGImageCreateAffineTransformCopy(CGImageRef imageRef, CGAffineTrans if (srcWidth == 0 || srcHeight == 0 || destWidth == 0 || destHeight == 0) return NULL; CGDataProviderRef tmpProvider = NULL, destProvider = NULL; - CGImageRef tmpImage = NULL, destImage = NULL;; + CGImageRef tmpImage = NULL, destImage = NULL; vImage_Buffer src = {0}, tmp = {0}, dest = {0}; if(!YYCGImageDecodeToBitmapBufferWith32BitFormat(imageRef, &src, kCGImageAlphaFirst | kCGBitmapByteOrderDefault)) return NULL; @@ -1400,13 +1399,14 @@ Call WebPDecode() on a multi-frame webp data will get an error (VP8_STATUS_UNSUP config.output.u.RGBA.stride = (int)bytesPerRow; config.output.u.RGBA.size = destLength; - if (WebPDecode(payload, payloadSize, &config) != VP8_STATUS_OK) goto fail; + VP8StatusCode result = WebPDecode(payload, payloadSize, &config); + if ((result != VP8_STATUS_OK) && (result != VP8_STATUS_NOT_ENOUGH_DATA)) goto fail; if (iter.x_offset != 0 || iter.y_offset != 0) { void *tmp = calloc(1, destLength); if (tmp) { vImage_Buffer src = {destBytes, canvasHeight, canvasWidth, bytesPerRow}; - vImage_Buffer dest = {destBytes, canvasHeight, canvasWidth, bytesPerRow}; + vImage_Buffer dest = {tmp, canvasHeight, canvasWidth, bytesPerRow}; vImage_CGAffineTransform transform = {1, 0, 0, 1, iter.x_offset, -iter.y_offset}; uint8_t backColor[4] = {0}; vImageAffineWarpCG_ARGB8888(&src, &dest, NULL, &transform, backColor, kvImageBackgroundColorFill); @@ -1506,7 +1506,7 @@ - (id)copyWithZone:(NSZone *)zone { @implementation YYImageDecoder { - pthread_mutex_t _lock; + pthread_mutex_t _lock; // recursive lock BOOL _sourceTypeDetected; CGImageSourceRef _source; @@ -1516,7 +1516,7 @@ @implementation YYImageDecoder { #endif UIImageOrientation _orientation; - OSSpinLock _framesLock; + dispatch_semaphore_t _framesLock; NSArray *_frames; ///< Array, without image BOOL _needBlend; NSUInteger _blendFrameIndex; @@ -1530,6 +1530,7 @@ - (void)dealloc { if (_webpSource) WebPDemuxDelete(_webpSource); #endif if (_blendCanvas) CFRelease(_blendCanvas); + pthread_mutex_destroy(&_lock); } + (instancetype)decoderWithData:(NSData *)data scale:(CGFloat)scale { @@ -1548,7 +1549,7 @@ - (instancetype)initWithScale:(CGFloat)scale { self = [super init]; if (scale <= 0) scale = 1; _scale = scale; - _framesLock = OS_SPINLOCK_INIT; + _framesLock = dispatch_semaphore_create(1); pthread_mutexattr_t attr; pthread_mutexattr_init (&attr); @@ -1577,11 +1578,11 @@ - (YYImageFrame *)frameAtIndex:(NSUInteger)index decodeForDisplay:(BOOL)decodeFo - (NSTimeInterval)frameDurationAtIndex:(NSUInteger)index { NSTimeInterval result = 0; - OSSpinLockLock(&_framesLock); // for better performance when play animation... + dispatch_semaphore_wait(_framesLock, DISPATCH_TIME_FOREVER); if (index < _frames.count) { result = ((_YYImageDecoderFrame *)_frames[index]).duration; } - OSSpinLockUnlock(&_framesLock); + dispatch_semaphore_signal(_framesLock); return result; } @@ -1746,9 +1747,9 @@ - (void)_updateSourceWebP { _loopCount = 0; if (_webpSource) WebPDemuxDelete(_webpSource); _webpSource = NULL; - OSSpinLockLock(&_framesLock); + dispatch_semaphore_wait(_framesLock, DISPATCH_TIME_FOREVER); _frames = nil; - OSSpinLockUnlock(&_framesLock); + dispatch_semaphore_signal(_framesLock); /* https://developers.google.com/speed/webp/docs/api @@ -1832,9 +1833,16 @@ When using WebPDecode() to decode multi-frame webp, we will get the error _loopCount = webpLoopCount; _needBlend = needBlend; _webpSource = demuxer; - OSSpinLockLock(&_framesLock); + dispatch_semaphore_wait(_framesLock, DISPATCH_TIME_FOREVER); _frames = frames; - OSSpinLockUnlock(&_framesLock); + dispatch_semaphore_signal(_framesLock); +#else + static const char *func = __FUNCTION__; + static const int line = __LINE__; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + NSLog(@"[%s: %d] WebP is not available, check the documentation to see how to install WebP component: https://github.com/ibireme/YYImage#installation", func, line); + }); #endif } @@ -1930,9 +1938,9 @@ - (void)_updateSourceAPNG { _loopCount = apng->apng_loop_num; _needBlend = needBlend; _apngSource = apng; - OSSpinLockLock(&_framesLock); + dispatch_semaphore_wait(_framesLock, DISPATCH_TIME_FOREVER); _frames = frames; - OSSpinLockUnlock(&_framesLock); + dispatch_semaphore_signal(_framesLock); } - (void)_updateSourceImageIO { @@ -1940,9 +1948,9 @@ - (void)_updateSourceImageIO { _height = 0; _orientation = UIImageOrientationUp; _loopCount = 0; - OSSpinLockLock(&_framesLock); + dispatch_semaphore_wait(_framesLock, DISPATCH_TIME_FOREVER); _frames = nil; - OSSpinLockUnlock(&_framesLock); + dispatch_semaphore_signal(_framesLock); if (!_source) { if (_finalized) { @@ -1968,13 +1976,16 @@ - (void)_updateSourceImageIO { if (_type == YYImageTypeGIF) { // get gif loop count CFDictionaryRef properties = CGImageSourceCopyProperties(_source, NULL); if (properties) { - CFTypeRef loop = CFDictionaryGetValue(properties, kCGImagePropertyGIFLoopCount); - if (loop) CFNumberGetValue(loop, kCFNumberNSIntegerType, &_loopCount); + CFDictionaryRef gif = CFDictionaryGetValue(properties, kCGImagePropertyGIFDictionary); + if (gif) { + CFTypeRef loop = CFDictionaryGetValue(gif, kCGImagePropertyGIFLoopCount); + if (loop) CFNumberGetValue(loop, kCFNumberNSIntegerType, &_loopCount); + } CFRelease(properties); } } } - + /* ICO, GIF, APNG may contains multi-frame. */ @@ -2026,9 +2037,9 @@ - (void)_updateSourceImageIO { CFRelease(properties); } } - OSSpinLockLock(&_framesLock); + dispatch_semaphore_wait(_framesLock, DISPATCH_TIME_FOREVER); _frames = frames; - OSSpinLockUnlock(&_framesLock); + dispatch_semaphore_signal(_framesLock); } - (CGImageRef)_newUnblendedImageAtIndex:(NSUInteger)index @@ -2151,7 +2162,8 @@ - (CGImageRef)_newUnblendedImageAtIndex:(NSUInteger)index config.output.u.RGBA.rgba = pixels; config.output.u.RGBA.stride = (int)bytesPerRow; config.output.u.RGBA.size = length; - if (WebPDecode(payload, payloadSize, &config) != VP8_STATUS_OK) { // decode + VP8StatusCode result = WebPDecode(payload, payloadSize, &config); // decode + if ((result != VP8_STATUS_OK) && (result != VP8_STATUS_NOT_ENOUGH_DATA)) { WebPDemuxReleaseIterator(&iter); free(pixels); return NULL; @@ -2310,10 +2322,16 @@ - (instancetype)init { } - (instancetype)initWithType:(YYImageType)type { - if (type == YYImageTypeUnknown || type >= YYImageTypeOther) return nil; + if (type == YYImageTypeUnknown || type >= YYImageTypeOther) { + NSLog(@"[%s: %d] Unsupported image type:%d",__FUNCTION__, __LINE__, (int)type); + return nil; + } #if !YYIMAGE_WEBP_ENABLED - if (type == YYImageTypeWebP) return nil; + if (type == YYImageTypeWebP) { + NSLog(@"[%s: %d] WebP is not available, check the documentation to see how to install WebP component: https://github.com/ibireme/YYImage#installation", __FUNCTION__, __LINE__); + return nil; + } #endif self = [super init]; @@ -2416,27 +2434,38 @@ - (void)_encodeImageWithDestination:(CGImageDestinationRef)destination imageCoun } for (int i = 0; i < count; i++) { - id imageSrc = _images[i]; - NSDictionary *frameProperty = NULL; - if (_type == YYImageTypeGIF && count > 1) { - frameProperty = @{(NSString *)kCGImagePropertyGIFDictionary : @{(NSString *) kCGImagePropertyGIFDelayTime:_durations[i]}}; - } else { - frameProperty = @{(id)kCGImageDestinationLossyCompressionQuality : @(_quality)}; - } - - if ([imageSrc isKindOfClass:[UIImage class]]) { - CGImageDestinationAddImage(destination, ((UIImage *)imageSrc).CGImage, (CFDictionaryRef)frameProperty); - } else if ([imageSrc isKindOfClass:[NSURL class]]) { - CGImageSourceRef source = CGImageSourceCreateWithURL((CFURLRef)imageSrc, NULL); - if (source) { - CGImageDestinationAddImageFromSource(destination, source, i, (CFDictionaryRef)frameProperty); - CFRelease(source); + @autoreleasepool { + id imageSrc = _images[i]; + NSDictionary *frameProperty = NULL; + if (_type == YYImageTypeGIF && count > 1) { + frameProperty = @{(NSString *)kCGImagePropertyGIFDictionary : @{(NSString *) kCGImagePropertyGIFDelayTime:_durations[i]}}; + } else { + frameProperty = @{(id)kCGImageDestinationLossyCompressionQuality : @(_quality)}; } - } else if ([imageSrc isKindOfClass:[NSData class]]) { - CGImageSourceRef source = CGImageSourceCreateWithData((CFDataRef)imageSrc, NULL); - if (source) { - CGImageDestinationAddImageFromSource(destination, source, i, (CFDictionaryRef)frameProperty); - CFRelease(source); + + if ([imageSrc isKindOfClass:[UIImage class]]) { + UIImage *image = imageSrc; + if (image.imageOrientation != UIImageOrientationUp && image.CGImage) { + CGBitmapInfo info = CGImageGetBitmapInfo(image.CGImage) | CGImageGetAlphaInfo(image.CGImage); + CGImageRef rotated = YYCGImageCreateCopyWithOrientation(image.CGImage, image.imageOrientation, info); + if (rotated) { + image = [UIImage imageWithCGImage:rotated]; + CFRelease(rotated); + } + } + if (image.CGImage) CGImageDestinationAddImage(destination, ((UIImage *)imageSrc).CGImage, (CFDictionaryRef)frameProperty); + } else if ([imageSrc isKindOfClass:[NSURL class]]) { + CGImageSourceRef source = CGImageSourceCreateWithURL((CFURLRef)imageSrc, NULL); + if (source) { + CGImageDestinationAddImageFromSource(destination, source, 0, (CFDictionaryRef)frameProperty); + CFRelease(source); + } + } else if ([imageSrc isKindOfClass:[NSData class]]) { + CGImageSourceRef source = CGImageSourceCreateWithData((CFDataRef)imageSrc, NULL); + if (source) { + CGImageDestinationAddImageFromSource(destination, source, 0, (CFDictionaryRef)frameProperty); + CFRelease(source); + } } } } @@ -2601,7 +2630,7 @@ - (NSData *)_encodeAPNG { chunk_fcTL.sequence_number = apngSequenceIndex; chunk_fcTL.width = frame->header.width; chunk_fcTL.height = frame->header.height; - yy_png_delay_to_fraction([(NSNumber *)_durations[0] doubleValue], &chunk_fcTL.delay_num, &chunk_fcTL.delay_den); + yy_png_delay_to_fraction([(NSNumber *)_durations[i] doubleValue], &chunk_fcTL.delay_num, &chunk_fcTL.delay_den); chunk_fcTL.delay_num = chunk_fcTL.delay_num; chunk_fcTL.delay_den = chunk_fcTL.delay_den; chunk_fcTL.dispose_op = YY_PNG_DISPOSE_OP_BACKGROUND; @@ -2725,7 +2754,7 @@ + (NSData *)encodeImage:(UIImage *)image type:(YYImageType)type quality:(CGFloat } + (NSData *)encodeImageWithDecoder:(YYImageDecoder *)decoder type:(YYImageType)type quality:(CGFloat)quality { - if (!decoder || !decoder.frameCount == 0) return nil; + if (!decoder || decoder.frameCount == 0) return nil; YYImageEncoder *encoder = [[YYImageEncoder alloc] initWithType:type]; encoder.quality = quality; for (int i = 0; i < decoder.frameCount; i++) { @@ -2754,7 +2783,7 @@ - (instancetype)yy_imageByDecoded { } - (BOOL)yy_isDecodedForDisplay { - if (self.images.count > 1) return YES; + if (self.images.count > 1 || [self isKindOfClass:[YYSpriteSheetImage class]]) return YES; NSNumber *num = objc_getAssociatedObject(self, @selector(yy_isDecodedForDisplay)); return [num boolValue]; } diff --git a/YYWebImage/Image/YYSpriteSheetImage.h b/YYWebImage/Image/YYSpriteSheetImage.h index 403168c..403bbf5 100644 --- a/YYWebImage/Image/YYSpriteSheetImage.h +++ b/YYWebImage/Image/YYSpriteSheetImage.h @@ -19,6 +19,8 @@ #import "YYAnimatedImageView.h" #endif +NS_ASSUME_NONNULL_BEGIN + /** An image to display sprite sheet animation. @@ -79,13 +81,13 @@ @return An image object, or nil if an error occurs. */ -- (instancetype)initWithSpriteSheetImage:(UIImage *)image - contentRects:(NSArray *)contentRects - frameDurations:(NSArray *)frameDurations - loopCount:(NSUInteger)loopCount; +- (nullable instancetype)initWithSpriteSheetImage:(UIImage *)image + contentRects:(NSArray *)contentRects + frameDurations:(NSArray *)frameDurations + loopCount:(NSUInteger)loopCount; -@property (nonatomic, readonly) NSArray *contentRects; -@property (nonatomic, readonly) NSArray *frameDurations; +@property (nonatomic, readonly) NSArray *contentRects; +@property (nonatomic, readonly) NSArray *frameDurations; @property (nonatomic, readonly) NSUInteger loopCount; /** @@ -98,3 +100,5 @@ - (CGRect)contentsRectForCALayerAtIndex:(NSUInteger)index; @end + +NS_ASSUME_NONNULL_END diff --git a/YYWebImage/YYImageCache.h b/YYWebImage/YYImageCache.h index 0422605..ad38288 100644 --- a/YYWebImage/YYImageCache.h +++ b/YYWebImage/YYImageCache.h @@ -13,6 +13,8 @@ @class YYMemoryCache, YYDiskCache; +NS_ASSUME_NONNULL_BEGIN + /// Image cache type typedef NS_OPTIONS(NSUInteger, YYImageCacheType) { /// No value. @@ -52,7 +54,7 @@ typedef NS_OPTIONS(NSUInteger, YYImageCacheType) { ///============================================================================= /** The name of the cache. Default is nil. */ -@property (copy) NSString *name; +@property (nullable, copy) NSString *name; /** The underlying memory cache. see `YYMemoryCache` for more information.*/ @property (strong, readonly) YYMemoryCache *memoryCache; @@ -66,7 +68,7 @@ typedef NS_OPTIONS(NSUInteger, YYImageCacheType) { @discussion When fetch image from disk cache, it will use 'YYImage' to decode animated image such as WebP/APNG/GIF. Set to 'NO' to ignore animated image. */ -@property (assign) BOOL allowAnimatedImage; +@property BOOL allowAnimatedImage; /** Whether decode the image to memory bitmap. Default is YES. @@ -74,7 +76,7 @@ typedef NS_OPTIONS(NSUInteger, YYImageCacheType) { @discussion If the value is YES, then the image will be decoded to memory bitmap for better display performance, but may cost more memory. */ -@property (assign) BOOL decodeForDisplay; +@property BOOL decodeForDisplay; #pragma mark - Initializer @@ -98,7 +100,7 @@ typedef NS_OPTIONS(NSUInteger, YYImageCacheType) { Once initialized you should not read and write to this directory. @result A new cache object, or nil if an error occurs. */ -- (instancetype)initWithPath:(NSString *)path NS_DESIGNATED_INITIALIZER; +- (nullable instancetype)initWithPath:(NSString *)path NS_DESIGNATED_INITIALIZER; #pragma mark - Access Methods @@ -129,7 +131,10 @@ typedef NS_OPTIONS(NSUInteger, YYImageCacheType) { @param key The key with which to associate the image. If nil, this method has no effect. @param type The cache type to store image. */ -- (void)setImage:(UIImage *)image imageData:(NSData *)imageData forKey:(NSString *)key withType:(YYImageCacheType)type; +- (void)setImage:(nullable UIImage *)image + imageData:(nullable NSData *)imageData + forKey:(NSString *)key + withType:(YYImageCacheType)type; /** Removes the image of the specified key in the cache (both memory and disk). @@ -177,7 +182,7 @@ typedef NS_OPTIONS(NSUInteger, YYImageCacheType) { @param key A string identifying the image. If nil, just return nil. @return The image associated with key, or nil if no image is associated with key. */ -- (UIImage *)getImageForKey:(NSString *)key; +- (nullable UIImage *)getImageForKey:(NSString *)key; /** Returns the image associated with a given key. @@ -187,7 +192,7 @@ typedef NS_OPTIONS(NSUInteger, YYImageCacheType) { @param key A string identifying the image. If nil, just return nil. @return The image associated with key, or nil if no image is associated with key. */ -- (UIImage *)getImageForKey:(NSString *)key withType:(YYImageCacheType)type; +- (nullable UIImage *)getImageForKey:(NSString *)key withType:(YYImageCacheType)type; /** Asynchronously get the image associated with a given key. @@ -196,7 +201,9 @@ typedef NS_OPTIONS(NSUInteger, YYImageCacheType) { @param type The cache type. @param block A completion block which will be called on main thread. */ -- (void)getImageForKey:(NSString *)key withType:(YYImageCacheType)type withBlock:(void(^)(UIImage *image, YYImageCacheType type))block; +- (void)getImageForKey:(NSString *)key + withType:(YYImageCacheType)type + withBlock:(void(^)(UIImage * _Nullable image, YYImageCacheType type))block; /** Returns the image data associated with a given key. @@ -205,7 +212,7 @@ typedef NS_OPTIONS(NSUInteger, YYImageCacheType) { @param key A string identifying the image. If nil, just return nil. @return The image data associated with key, or nil if no image is associated with key. */ -- (NSData *)getImageDataForKey:(NSString *)key; +- (nullable NSData *)getImageDataForKey:(NSString *)key; /** Asynchronously get the image data associated with a given key. @@ -213,6 +220,9 @@ typedef NS_OPTIONS(NSUInteger, YYImageCacheType) { @param key A string identifying the image. If nil, just return nil. @param block A completion block which will be called on main thread. */ -- (void)getImageDataForKey:(NSString *)key withBlock:(void(^)(NSData *imageData))block; +- (void)getImageDataForKey:(NSString *)key + withBlock:(void(^)(NSData * _Nullable imageData))block; @end + +NS_ASSUME_NONNULL_END diff --git a/YYWebImage/YYImageCache.m b/YYWebImage/YYImageCache.m index 95a637d..65b2779 100644 --- a/YYWebImage/YYImageCache.m +++ b/YYWebImage/YYImageCache.m @@ -25,25 +25,14 @@ #import "YYCache.h" #endif -#if __has_include("YYDispatchQueuePool.h") -#import "YYDispatchQueuePool.h" -#endif static inline dispatch_queue_t YYImageCacheIOQueue() { -#ifdef YYDispatchQueuePool_h - return YYDispatchQueueGetForQOS(NSQualityOfServiceDefault); -#else return dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); -#endif } static inline dispatch_queue_t YYImageCacheDecodeQueue() { -#ifdef YYDispatchQueuePool_h - return YYDispatchQueueGetForQOS(NSQualityOfServiceUtility); -#else return dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_LOW, 0); -#endif } @@ -100,7 +89,7 @@ + (instancetype)sharedCache { - (instancetype)init { @throw [NSException exceptionWithName:@"YYImageCache init error" reason:@"YYImageCache must be initialized with a path. Use 'initWithPath:' instead." userInfo:nil]; - return [self initWithPath:nil]; + return [self initWithPath:@""]; } - (instancetype)initWithPath:(NSString *)path { @@ -148,7 +137,7 @@ - (void)setImage:(UIImage *)image imageData:(NSData *)imageData forKey:(NSString __strong typeof(_self) self = _self; if (!self) return; UIImage *newImage = [self imageFromData:imageData]; - [self.memoryCache setObject:[self imageFromData:imageData] forKey:key withCost:[self imageCost:newImage]]; + [self.memoryCache setObject:newImage forKey:key withCost:[self imageCost:newImage]]; }); } } diff --git a/YYWebImage/YYWebImageManager.h b/YYWebImage/YYWebImageManager.h index 8864da3..30ba223 100644 --- a/YYWebImage/YYWebImageManager.h +++ b/YYWebImage/YYWebImageManager.h @@ -19,6 +19,7 @@ @class YYWebImageOperation; +NS_ASSUME_NONNULL_BEGIN /// The options to control image operation. typedef NS_OPTIONS(NSUInteger, YYWebImageOptions) { @@ -69,6 +70,10 @@ typedef NS_OPTIONS(NSUInteger, YYWebImageOptions) { /// Do not set the image to the view when image fetch complete. /// You may set the image manually. YYWebImageOptionAvoidSetImage = 1 << 13, + + /// This flag will add the URL to a blacklist (in memory) when the URL fail to be downloaded, + /// so the library won't keep trying. + YYWebImageOptionIgnoreFailedURL = 1 << 14, }; /// Indicated where the image came from. @@ -93,7 +98,7 @@ typedef NS_ENUM(NSUInteger, YYWebImageFromType) { }; /// Indicated image fetch complete stage. -typedef NS_ENUM(NSUInteger, YYWebImageStage) { +typedef NS_ENUM(NSInteger, YYWebImageStage) { /// Incomplete, progressive image. YYWebImageStageProgress = -1, @@ -134,7 +139,7 @@ typedef void(^YYWebImageProgressBlock)(NSInteger receivedSize, NSInteger expecte @param url The image url (remote or local file path). @return The transformed image. */ -typedef UIImage *(^YYWebImageTransformBlock)(UIImage *image, NSURL *url); +typedef UIImage * _Nullable (^YYWebImageTransformBlock)(UIImage *image, NSURL *url); /** The block invoked when image fetch finished or cancelled. @@ -142,10 +147,14 @@ typedef UIImage *(^YYWebImageTransformBlock)(UIImage *image, NSURL *url); @param image The image. @param url The image url (remote or local file path). @param from Where the image came from. + @param stage Current download stage. @param error Error during image fetching. - @param finished If the operation is cancelled, this value is NO, otherwise YES. */ -typedef void (^YYWebImageCompletionBlock)(UIImage *image, NSURL *url, YYWebImageFromType from, YYWebImageStage stage, NSError *error); +typedef void (^YYWebImageCompletionBlock)(UIImage * _Nullable image, + NSURL *url, + YYWebImageFromType from, + YYWebImageStage stage, + NSError * _Nullable error); @@ -170,7 +179,8 @@ typedef void (^YYWebImageCompletionBlock)(UIImage *image, NSURL *url, YYWebImage (pass nil to make the new operation start immediately without queue). @return A new manager. */ -- (instancetype)initWithCache:(YYImageCache *)cache queue:(NSOperationQueue *)queue NS_DESIGNATED_INITIALIZER; +- (instancetype)initWithCache:(nullable YYImageCache *)cache + queue:(nullable NSOperationQueue *)queue NS_DESIGNATED_INITIALIZER; - (instancetype)init UNAVAILABLE_ATTRIBUTE; + (instancetype)new UNAVAILABLE_ATTRIBUTE; @@ -185,17 +195,17 @@ typedef void (^YYWebImageCompletionBlock)(UIImage *image, NSURL *url, YYWebImage @param completion Completion block which will be invoked on background thread (pass nil to avoid). @return A new image operation. */ -- (YYWebImageOperation *)requestImageWithURL:(NSURL *)url - options:(YYWebImageOptions)options - progress:(YYWebImageProgressBlock)progress - transform:(YYWebImageTransformBlock)transform - completion:(YYWebImageCompletionBlock)completion; +- (nullable YYWebImageOperation *)requestImageWithURL:(NSURL *)url + options:(YYWebImageOptions)options + progress:(nullable YYWebImageProgressBlock)progress + transform:(nullable YYWebImageTransformBlock)transform + completion:(nullable YYWebImageCompletionBlock)completion; /** The image cache used by image operation. You can set it to nil to avoid image cache. */ -@property (nonatomic, strong) YYImageCache *cache; +@property (nullable, nonatomic, strong) YYImageCache *cache; /** The operation queue on which image operations are scheduled and run. @@ -204,7 +214,7 @@ typedef void (^YYWebImageCompletionBlock)(UIImage *image, NSURL *url, YYWebImage You can use this queue to control maximum number of concurrent operations, to obtain the status of the current operations, or to cancel all operations in this manager. */ -@property (nonatomic, strong) NSOperationQueue *queue; +@property (nullable, nonatomic, strong) NSOperationQueue *queue; /** The shared transform block to process image. Default is nil. @@ -212,27 +222,27 @@ typedef void (^YYWebImageCompletionBlock)(UIImage *image, NSURL *url, YYWebImage When called `requestImageWithURL:options:progress:transform:completion` and the `transform` is nil, this block will be used. */ -@property (nonatomic, copy) YYWebImageTransformBlock sharedTransformBlock; +@property (nullable, nonatomic, copy) YYWebImageTransformBlock sharedTransformBlock; /** The image request timeout interval in seconds. Default is 15. */ -@property (nonatomic, assign) NSTimeInterval timeout; +@property (nonatomic) NSTimeInterval timeout; /** The username used by NSURLCredential, default is nil. */ -@property (nonatomic, strong) NSString *username; +@property (nullable, nonatomic, copy) NSString *username; /** The password used by NSURLCredential, default is nil. */ -@property (nonatomic, strong) NSString *password; +@property (nullable, nonatomic, copy) NSString *password; /** The image HTTP request header. Default is "Accept:image/webp,image/\*;q=0.8". */ -@property (nonatomic, copy) NSDictionary *headers; +@property (nullable, nonatomic, copy) NSDictionary *headers; /** A block which will be invoked for each image HTTP request to do additional @@ -240,14 +250,14 @@ typedef void (^YYWebImageCompletionBlock)(UIImage *image, NSURL *url, YYWebImage Use this block to add or remove HTTP header field for a specified URL. */ -@property (nonatomic, copy) NSDictionary *(^headersFilter)(NSURL *url, NSDictionary *header); +@property (nullable, nonatomic, copy) NSDictionary *(^headersFilter)(NSURL *url, NSDictionary * _Nullable header); /** A block which will be invoked for each image operation. Default is nil. Use this block to provide a custom image cache key for a specified URL. */ -@property (nonatomic, copy) NSString *(^cacheKeyFilter)(NSURL *url); +@property (nullable, nonatomic, copy) NSString *(^cacheKeyFilter)(NSURL *url); /** Returns the HTTP headers for a specified URL. @@ -255,7 +265,7 @@ typedef void (^YYWebImageCompletionBlock)(UIImage *image, NSURL *url, YYWebImage @param url A specified URL. @return HTTP headers. */ -- (NSDictionary *)headersForURL:(NSURL *)url; +- (nullable NSDictionary *)headersForURL:(NSURL *)url; /** Returns the cache key for a specified URL. @@ -266,13 +276,14 @@ typedef void (^YYWebImageCompletionBlock)(UIImage *image, NSURL *url, YYWebImage - (NSString *)cacheKeyForURL:(NSURL *)url; - /** Increments the number of active network requests. If this number was zero before incrementing, this will start animating the status bar network activity indicator. This method is thread safe. + + This method has no effect in App Extension. */ + (void)incrementNetworkActivityCount; @@ -282,6 +293,8 @@ typedef void (^YYWebImageCompletionBlock)(UIImage *image, NSURL *url, YYWebImage status bar network activity indicator. This method is thread safe. + + This method has no effect in App Extension. */ + (void)decrementNetworkActivityCount; @@ -289,7 +302,11 @@ typedef void (^YYWebImageCompletionBlock)(UIImage *image, NSURL *url, YYWebImage Get current number of active network requests. This method is thread safe. + + This method has no effect in App Extension. */ + (NSInteger)currentNetworkActivityCount; @end + +NS_ASSUME_NONNULL_END diff --git a/YYWebImage/YYWebImageManager.m b/YYWebImage/YYWebImageManager.m index 0faa6a6..784fd8b 100644 --- a/YYWebImage/YYWebImageManager.m +++ b/YYWebImage/YYWebImageManager.m @@ -12,14 +12,33 @@ #import "YYWebImageManager.h" #import "YYImageCache.h" #import "YYWebImageOperation.h" +#import "YYImageCoder.h" #import #define kNetworkIndicatorDelay (1/30.0) -@interface _YYUIApplicationNetworkIndicatorInfo : NSObject + + +/// Returns nil in App Extension. +static UIApplication *_YYSharedApplication() { + static BOOL isAppExtension = NO; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + Class cls = NSClassFromString(@"UIApplication"); + if(!cls || ![cls respondsToSelector:@selector(sharedApplication)]) isAppExtension = YES; + if ([[[NSBundle mainBundle] bundlePath] hasSuffix:@".appex"]) isAppExtension = YES; + }); +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wundeclared-selector" + return isAppExtension ? nil : [UIApplication performSelector:@selector(sharedApplication)]; +#pragma clang diagnostic pop +} + + +@interface _YYWebImageApplicationNetworkIndicatorInfo : NSObject @property (nonatomic, assign) NSInteger count; @property (nonatomic, strong) NSTimer *timer; @end -@implementation _YYUIApplicationNetworkIndicatorInfo +@implementation _YYWebImageApplicationNetworkIndicatorInfo @end @implementation YYWebImageManager @@ -49,7 +68,11 @@ - (instancetype)initWithCache:(YYImageCache *)cache queue:(NSOperationQueue *)qu _cache = cache; _queue = queue; _timeout = 15.0; - _headers = @{ @"Accept" : @"image/webp,image/*;q=0.8" }; + if (YYImageWebPAvailable()) { + _headers = @{ @"Accept" : @"image/webp,image/*;q=0.8" }; + } else { + _headers = @{ @"Accept" : @"image/*;q=0.8" }; + } return self; } @@ -103,27 +126,32 @@ - (NSString *)cacheKeyForURL:(NSURL *)url { #pragma mark Network Indicator -+ (_YYUIApplicationNetworkIndicatorInfo *)_networkIndicatorInfo { ++ (_YYWebImageApplicationNetworkIndicatorInfo *)_networkIndicatorInfo { return objc_getAssociatedObject(self, @selector(_networkIndicatorInfo)); } -+ (void)_setNetworkIndicatorInfo:(_YYUIApplicationNetworkIndicatorInfo *)info { ++ (void)_setNetworkIndicatorInfo:(_YYWebImageApplicationNetworkIndicatorInfo *)info { objc_setAssociatedObject(self, @selector(_networkIndicatorInfo), info, OBJC_ASSOCIATION_RETAIN); } + (void)_delaySetActivity:(NSTimer *)timer { + UIApplication *app = _YYSharedApplication(); + if (!app) return; + NSNumber *visiable = timer.userInfo; - if ([UIApplication sharedApplication].networkActivityIndicatorVisible != visiable.boolValue) { - [[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:visiable.boolValue]; + if (app.networkActivityIndicatorVisible != visiable.boolValue) { + [app setNetworkActivityIndicatorVisible:visiable.boolValue]; } [timer invalidate]; } + (void)_changeNetworkActivityCount:(NSInteger)delta { + if (!_YYSharedApplication()) return; + void (^block)() = ^{ - _YYUIApplicationNetworkIndicatorInfo *info = [self _networkIndicatorInfo]; + _YYWebImageApplicationNetworkIndicatorInfo *info = [self _networkIndicatorInfo]; if (!info) { - info = [_YYUIApplicationNetworkIndicatorInfo new]; + info = [_YYWebImageApplicationNetworkIndicatorInfo new]; [self _setNetworkIndicatorInfo:info]; } NSInteger count = info.count; @@ -149,7 +177,7 @@ + (void)decrementNetworkActivityCount { } + (NSInteger)currentNetworkActivityCount { - _YYUIApplicationNetworkIndicatorInfo *info = [self _networkIndicatorInfo]; + _YYWebImageApplicationNetworkIndicatorInfo *info = [self _networkIndicatorInfo]; return info.count; } diff --git a/YYWebImage/YYWebImageOperation.h b/YYWebImage/YYWebImageOperation.h index 8235cf7..d15eb3b 100644 --- a/YYWebImage/YYWebImageOperation.h +++ b/YYWebImage/YYWebImageOperation.h @@ -19,6 +19,8 @@ #import "YYWebImageManager.h" #endif +NS_ASSUME_NONNULL_BEGIN + /** The YYWebImageOperation class is an NSOperation subclass used to fetch image from URL request. @@ -28,20 +30,20 @@ operation is started, it will: 1. Get the image from the cache, if exist, return it with `completion` block. - 2. Start an URL connection to fetch image from the request, revoke the `progress` - to notify request progress (and revoke `completion` block to return the + 2. Start an URL connection to fetch image from the request, invoke the `progress` + to notify request progress (and invoke `completion` block to return the progressive image if enabled by progressive option). - 3. Process the image by revoke the `transform` block. + 3. Process the image by invoke the `transform` block. 4. Put the image to cache and return it with `completion` block. */ @interface YYWebImageOperation : NSOperation -@property (nonatomic, strong, readonly) NSURLRequest *request; ///< The image URL request. -@property (nonatomic, strong, readonly) NSURLResponse *response; ///< The response for request. -@property (nonatomic, assign, readonly) YYWebImageOptions options; ///< The operation's option. -@property (nonatomic, strong, readonly) YYImageCache *cache; ///< The image cache. -@property (nonatomic, strong, readonly) NSString *cacheKey; ///< The image cache key. +@property (nonatomic, strong, readonly) NSURLRequest *request; ///< The image URL request. +@property (nullable, nonatomic, strong, readonly) NSURLResponse *response; ///< The response for request. +@property (nullable, nonatomic, strong, readonly) YYImageCache *cache; ///< The image cache. +@property (nonatomic, strong, readonly) NSString *cacheKey; ///< The image cache key. +@property (nonatomic, readonly) YYWebImageOptions options; ///< The operation's option. /** Whether the URL connection should consult the credential storage for authenticating @@ -50,7 +52,7 @@ @discussion This is the value that is returned in the `NSURLConnectionDelegate` method `-connectionShouldUseCredentialStorage:`. */ -@property (nonatomic, assign) BOOL shouldUseCredentialStorage; +@property (nonatomic) BOOL shouldUseCredentialStorage; /** The credential used for authentication challenges in `-connection:didReceiveAuthenticationChallenge:`. @@ -58,7 +60,7 @@ @discussion This will be overridden by any shared credentials that exist for the username or password of the request URL, if present. */ -@property (nonatomic, strong) NSURLCredential *credential; +@property (nullable, nonatomic, strong) NSURLCredential *credential; /** Creates and returns a new operation. @@ -81,13 +83,15 @@ */ - (instancetype)initWithRequest:(NSURLRequest *)request options:(YYWebImageOptions)options - cache:(YYImageCache *)cache - cacheKey:(NSString *)cacheKey - progress:(YYWebImageProgressBlock)progress - transform:(YYWebImageTransformBlock)transform - completion:(YYWebImageCompletionBlock)completion NS_DESIGNATED_INITIALIZER; + cache:(nullable YYImageCache *)cache + cacheKey:(nullable NSString *)cacheKey + progress:(nullable YYWebImageProgressBlock)progress + transform:(nullable YYWebImageTransformBlock)transform + completion:(nullable YYWebImageCompletionBlock)completion NS_DESIGNATED_INITIALIZER; - (instancetype)init UNAVAILABLE_ATTRIBUTE; + (instancetype)new UNAVAILABLE_ATTRIBUTE; @end + +NS_ASSUME_NONNULL_END diff --git a/YYWebImage/YYWebImageOperation.m b/YYWebImage/YYWebImageOperation.m index bec9b7b..30ac1eb 100644 --- a/YYWebImage/YYWebImageOperation.m +++ b/YYWebImage/YYWebImageOperation.m @@ -12,6 +12,7 @@ #import "YYWebImageOperation.h" #import "UIImage+YYWebImage.h" #import +#import #if __has_include() #import @@ -19,15 +20,26 @@ #import "YYImage.h" #endif -#if __has_include("YYDispatchQueuePool.h") -#import "YYDispatchQueuePool.h" -#else -#import -#endif #define MIN_PROGRESSIVE_TIME_INTERVAL 0.2 #define MIN_PROGRESSIVE_BLUR_TIME_INTERVAL 0.4 + +/// Returns nil in App Extension. +static UIApplication *_YYSharedApplication() { + static BOOL isAppExtension = NO; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + Class cls = NSClassFromString(@"UIApplication"); + if(!cls || ![cls respondsToSelector:@selector(sharedApplication)]) isAppExtension = YES; + if ([[[NSBundle mainBundle] bundlePath] hasSuffix:@".appex"]) isAppExtension = YES; + }); +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wundeclared-selector" + return isAppExtension ? nil : [UIApplication performSelector:@selector(sharedApplication)]; +#pragma clang diagnostic pop +} + /// Returns YES if the right-bottom pixel is filled. static BOOL YYCGImageLastPixelFilled(CGImageRef image) { if (!image) return NO; @@ -56,6 +68,35 @@ static BOOL YYCGImageLastPixelFilled(CGImageRef image) { } +static NSMutableSet *URLBlacklist; +static dispatch_semaphore_t URLBlacklistLock; + +static void URLBlacklistInit() { + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + URLBlacklist = [NSMutableSet new]; + URLBlacklistLock = dispatch_semaphore_create(1); + }); +} + +static BOOL URLBlackListContains(NSURL *url) { + if (!url || url == (id)[NSNull null]) return NO; + URLBlacklistInit(); + dispatch_semaphore_wait(URLBlacklistLock, DISPATCH_TIME_FOREVER); + BOOL contains = [URLBlacklist containsObject:url]; + dispatch_semaphore_signal(URLBlacklistLock); + return contains; +} + +static void URLInBlackListAdd(NSURL *url) { + if (!url || url == (id)[NSNull null]) return; + URLBlacklistInit(); + dispatch_semaphore_wait(URLBlacklistLock, DISPATCH_TIME_FOREVER); + [URLBlacklist addObject:url]; + dispatch_semaphore_signal(URLBlacklistLock); +} + + /// A proxy used to hold a weak object. @interface _YYWebImageWeakProxy : NSProxy @property (nonatomic, weak, readonly) id target; @@ -172,9 +213,6 @@ + (NSThread *)_networkThread { /// Global image queue, used for image reading and decoding. + (dispatch_queue_t)_imageQueue { -#ifdef YYDispatchQueuePool_h - return YYDispatchQueueGetForQOS(NSQualityOfServiceUtility); -#else #define MAX_QUEUE_COUNT 16 static int queueCount; static dispatch_queue_t queues[MAX_QUEUE_COUNT]; @@ -199,12 +237,11 @@ + (dispatch_queue_t)_imageQueue { if (cur < 0) cur = -cur; return queues[(cur) % queueCount]; #undef MAX_QUEUE_COUNT -#endif } - (instancetype)init { @throw [NSException exceptionWithName:@"YYWebImageOperation init error" reason:@"YYWebImageOperation must be initialized with a request. Use the designated initializer to init." userInfo:nil]; - return [self initWithRequest:nil options:0 cache:nil cacheKey:nil progress:nil transform:nil completion:nil]; + return [self initWithRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:@""]] options:0 cache:nil cacheKey:nil progress:nil transform:nil completion:nil]; } - (instancetype)initWithRequest:(NSURLRequest *)request @@ -229,13 +266,14 @@ - (instancetype)initWithRequest:(NSURLRequest *)request _finished = NO; _cancelled = NO; _taskID = UIBackgroundTaskInvalid; + _lock = [NSRecursiveLock new]; return self; } - (void)dealloc { [_lock lock]; if (_taskID != UIBackgroundTaskInvalid) { - [[UIApplication sharedApplication] endBackgroundTask:_taskID]; + [_YYSharedApplication() endBackgroundTask:_taskID]; _taskID = UIBackgroundTaskInvalid; } if ([self isExecuting]) { @@ -259,7 +297,7 @@ - (void)dealloc { - (void)_endBackgroundTask { [_lock lock]; if (_taskID != UIBackgroundTaskInvalid) { - [[UIApplication sharedApplication] endBackgroundTask:_taskID]; + [_YYSharedApplication() endBackgroundTask:_taskID]; _taskID = UIBackgroundTaskInvalid; } [_lock unlock]; @@ -285,7 +323,7 @@ - (void)_startOperation { if (image) { [_lock lock]; if (![self isCancelled]) { - if (_completion) _completion(image, _request.URL, YYWebImageFromMemoryCache, YYWebImageStageCancelled, nil); + if (_completion) _completion(image, _request.URL, YYWebImageFromMemoryCache, YYWebImageStageFinished, nil); } [self _finish]; [_lock unlock]; @@ -315,11 +353,22 @@ - (void)_startOperation { - (void)_startRequest:(id)object { if ([self isCancelled]) return; @autoreleasepool { + if ((_options & YYWebImageOptionIgnoreFailedURL) && URLBlackListContains(_request.URL)) { + NSError *error = [NSError errorWithDomain:NSURLErrorDomain code:NSURLErrorFileDoesNotExist userInfo:@{ NSLocalizedDescriptionKey : @"Failed to load URL, blacklisted." }]; + [_lock lock]; + if (![self isCancelled]) { + if (_completion) _completion(nil, _request.URL, YYWebImageFromNone, YYWebImageStageFinished, error); + } + [self _finish]; + [_lock unlock]; + return; + } + if (_request.URL.isFileURL) { NSArray *keys = @[NSURLFileSizeKey]; NSDictionary *attr = [_request.URL resourceValuesForKeys:keys error:nil]; NSNumber *fileSize = attr[NSURLFileSizeKey]; - _expectedSize = fileSize ? fileSize.unsignedIntegerValue : -1; + _expectedSize = (fileSize != nil) ? fileSize.unsignedIntegerValue : -1; } // request image from web @@ -374,7 +423,8 @@ - (void)_didReceiveImageFromWeb:(UIImage *)image { if (image || (_options & YYWebImageOptionRefreshImageCache)) { NSData *data = _data; dispatch_async([YYWebImageOperation _imageQueue], ^{ - [_cache setImage:image imageData:data forKey:_cacheKey withType:YYImageCacheTypeAll]; + YYImageCacheType cacheType = (_options & YYWebImageOptionIgnoreDiskCache) ? YYImageCacheTypeMemory : YYImageCacheTypeAll; + [_cache setImage:image imageData:data forKey:_cacheKey withType:cacheType]; }); } } @@ -382,6 +432,13 @@ - (void)_didReceiveImageFromWeb:(UIImage *)image { NSError *error = nil; if (!image) { error = [NSError errorWithDomain:@"com.ibireme.image" code:-1 userInfo:@{ NSLocalizedDescriptionKey : @"Web image decode fail." }]; + if (_options & YYWebImageOptionIgnoreFailedURL) { + if (URLBlackListContains(_request.URL)) { + error = [NSError errorWithDomain:NSURLErrorDomain code:NSURLErrorFileDoesNotExist userInfo:@{ NSLocalizedDescriptionKey : @"Failed to load URL, blacklisted." }]; + } else { + URLInBlackListAdd(_request.URL); + } + } } if (_completion) _completion(image, _request.URL, YYWebImageFromRemote, YYWebImageStageFinished, error); [self _finish]; @@ -426,8 +483,7 @@ - (NSCachedURLResponse *)connection:(NSURLConnection *)connection willCacheRespo return cachedResponse; } else { // ignore NSURLCache - NSCachedURLResponse *response = [[NSCachedURLResponse alloc] initWithResponse:cachedResponse.response data:cachedResponse.data userInfo:cachedResponse.userInfo ? cachedResponse.userInfo : @{} storagePolicy:NSURLCacheStorageNotAllowed]; - return response; + return nil; } } @@ -452,7 +508,7 @@ - (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLRespon _data = [NSMutableData dataWithCapacity:_expectedSize > 0 ? _expectedSize : 0]; if (_progress) { [_lock lock]; - if ([self isCancelled]) _progress(0, _expectedSize); + if (![self isCancelled]) _progress(0, _expectedSize); [_lock unlock]; } } @@ -666,6 +722,16 @@ - (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)err [YYWebImageManager decrementNetworkActivityCount]; } [self _finish]; + + if (_options & YYWebImageOptionIgnoreFailedURL) { + if (error.code != NSURLErrorNotConnectedToInternet && + error.code != NSURLErrorCancelled && + error.code != NSURLErrorTimedOut && + error.code != NSURLErrorUserCancelledAuthentication && + error.code != NSURLErrorNetworkConnectionLost) { + URLInBlackListAdd(_request.URL); + } + } } [_lock unlock]; } @@ -690,10 +756,10 @@ - (void)start { } else { self.executing = YES; [self performSelector:@selector(_startOperation) onThread:[[self class] _networkThread] withObject:nil waitUntilDone:NO modes:@[NSDefaultRunLoopMode]]; - if (_options & YYWebImageOptionAllowBackgroundTask) { + if ((_options & YYWebImageOptionAllowBackgroundTask) && _YYSharedApplication()) { __weak __typeof__ (self) _self = self; if (_taskID == UIBackgroundTaskInvalid) { - _taskID = [[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler:^{ + _taskID = [_YYSharedApplication() beginBackgroundTaskWithExpirationHandler:^{ __strong __typeof (_self) self = _self; if (self) { [self cancel];