瀏覽代碼

Move some internal classes into private header files, make it easy to maintain the code

DreamPiggy 7 年之前
父節點
當前提交
6bab2de69a

+ 8 - 8
Examples/SDWebImage Demo.xcodeproj/project.pbxproj

@@ -634,7 +634,7 @@
 			files = (
 			);
 			inputPaths = (
-				"${SRCROOT}/Pods/Target Support Files/Pods-SDWebImage OSX Demo/Pods-SDWebImage OSX Demo-frameworks.sh",
+				"${PODS_ROOT}/Target Support Files/Pods-SDWebImage OSX Demo/Pods-SDWebImage OSX Demo-frameworks.sh",
 				"${BUILT_PRODUCTS_DIR}/SDWebImage-macOS/SDWebImage.framework",
 				"${BUILT_PRODUCTS_DIR}/SDWebImageWebPCoder-macOS/SDWebImageWebPCoder.framework",
 				"${BUILT_PRODUCTS_DIR}/libwebp-macOS/libwebp.framework",
@@ -647,7 +647,7 @@
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 			shellPath = /bin/sh;
-			shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-SDWebImage OSX Demo/Pods-SDWebImage OSX Demo-frameworks.sh\"\n";
+			shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-SDWebImage OSX Demo/Pods-SDWebImage OSX Demo-frameworks.sh\"\n";
 			showEnvVarsInLog = 0;
 		};
 		8425DD76050A8A49F8DAF736 /* [CP] Embed Pods Frameworks */ = {
@@ -656,7 +656,7 @@
 			files = (
 			);
 			inputPaths = (
-				"${SRCROOT}/Pods/Target Support Files/Pods-SDWebImage iOS Demo/Pods-SDWebImage iOS Demo-frameworks.sh",
+				"${PODS_ROOT}/Target Support Files/Pods-SDWebImage iOS Demo/Pods-SDWebImage iOS Demo-frameworks.sh",
 				"${BUILT_PRODUCTS_DIR}/SDWebImage-iOS/SDWebImage.framework",
 				"${BUILT_PRODUCTS_DIR}/SDWebImageWebPCoder-iOS/SDWebImageWebPCoder.framework",
 				"${BUILT_PRODUCTS_DIR}/libwebp-iOS/libwebp.framework",
@@ -669,7 +669,7 @@
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 			shellPath = /bin/sh;
-			shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-SDWebImage iOS Demo/Pods-SDWebImage iOS Demo-frameworks.sh\"\n";
+			shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-SDWebImage iOS Demo/Pods-SDWebImage iOS Demo-frameworks.sh\"\n";
 			showEnvVarsInLog = 0;
 		};
 		85F5B7F46D00990FBEBF0377 /* [CP] Embed Pods Frameworks */ = {
@@ -678,7 +678,7 @@
 			files = (
 			);
 			inputPaths = (
-				"${SRCROOT}/Pods/Target Support Files/Pods-SDWebImage Watch Demo Extension/Pods-SDWebImage Watch Demo Extension-frameworks.sh",
+				"${PODS_ROOT}/Target Support Files/Pods-SDWebImage Watch Demo Extension/Pods-SDWebImage Watch Demo Extension-frameworks.sh",
 				"${BUILT_PRODUCTS_DIR}/SDWebImage-watchOS/SDWebImage.framework",
 				"${BUILT_PRODUCTS_DIR}/SDWebImageWebPCoder-watchOS/SDWebImageWebPCoder.framework",
 				"${BUILT_PRODUCTS_DIR}/libwebp-watchOS/libwebp.framework",
@@ -691,7 +691,7 @@
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 			shellPath = /bin/sh;
-			shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-SDWebImage Watch Demo Extension/Pods-SDWebImage Watch Demo Extension-frameworks.sh\"\n";
+			shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-SDWebImage Watch Demo Extension/Pods-SDWebImage Watch Demo Extension-frameworks.sh\"\n";
 			showEnvVarsInLog = 0;
 		};
 		A50199B809E737E017D7DF1C /* [CP] Check Pods Manifest.lock */ = {
@@ -772,7 +772,7 @@
 			files = (
 			);
 			inputPaths = (
-				"${SRCROOT}/Pods/Target Support Files/Pods-SDWebImage TV Demo/Pods-SDWebImage TV Demo-frameworks.sh",
+				"${PODS_ROOT}/Target Support Files/Pods-SDWebImage TV Demo/Pods-SDWebImage TV Demo-frameworks.sh",
 				"${BUILT_PRODUCTS_DIR}/SDWebImage-tvOS/SDWebImage.framework",
 				"${BUILT_PRODUCTS_DIR}/SDWebImageWebPCoder-tvOS/SDWebImageWebPCoder.framework",
 				"${BUILT_PRODUCTS_DIR}/libwebp-tvOS/libwebp.framework",
@@ -785,7 +785,7 @@
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 			shellPath = /bin/sh;
-			shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-SDWebImage TV Demo/Pods-SDWebImage TV Demo-frameworks.sh\"\n";
+			shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-SDWebImage TV Demo/Pods-SDWebImage TV Demo-frameworks.sh\"\n";
 			showEnvVarsInLog = 0;
 		};
 /* End PBXShellScriptBuildPhase section */

+ 72 - 0
SDWebImage.xcodeproj/project.pbxproj

@@ -63,6 +63,30 @@
 		3257EAFC21898AED0097B271 /* SDImageGraphics.m in Sources */ = {isa = PBXBuildFile; fileRef = 3257EAF821898AED0097B271 /* SDImageGraphics.m */; };
 		3257EAFD21898AED0097B271 /* SDImageGraphics.m in Sources */ = {isa = PBXBuildFile; fileRef = 3257EAF821898AED0097B271 /* SDImageGraphics.m */; };
 		3257EAFE21898AED0097B271 /* SDImageGraphics.m in Sources */ = {isa = PBXBuildFile; fileRef = 3257EAF821898AED0097B271 /* SDImageGraphics.m */; };
+		325C460222339330004CAE11 /* SDImageAssetManager.h in Headers */ = {isa = PBXBuildFile; fileRef = 325C460022339330004CAE11 /* SDImageAssetManager.h */; settings = {ATTRIBUTES = (Private, ); }; };
+		325C460322339330004CAE11 /* SDImageAssetManager.h in Headers */ = {isa = PBXBuildFile; fileRef = 325C460022339330004CAE11 /* SDImageAssetManager.h */; settings = {ATTRIBUTES = (Private, ); }; };
+		325C460422339330004CAE11 /* SDImageAssetManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 325C460122339330004CAE11 /* SDImageAssetManager.m */; };
+		325C460522339330004CAE11 /* SDImageAssetManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 325C460122339330004CAE11 /* SDImageAssetManager.m */; };
+		325C460822339426004CAE11 /* SDWeakProxy.h in Headers */ = {isa = PBXBuildFile; fileRef = 325C460622339426004CAE11 /* SDWeakProxy.h */; settings = {ATTRIBUTES = (Private, ); }; };
+		325C460922339426004CAE11 /* SDWeakProxy.h in Headers */ = {isa = PBXBuildFile; fileRef = 325C460622339426004CAE11 /* SDWeakProxy.h */; settings = {ATTRIBUTES = (Private, ); }; };
+		325C460A22339426004CAE11 /* SDWeakProxy.m in Sources */ = {isa = PBXBuildFile; fileRef = 325C460722339426004CAE11 /* SDWeakProxy.m */; };
+		325C460B22339426004CAE11 /* SDWeakProxy.m in Sources */ = {isa = PBXBuildFile; fileRef = 325C460722339426004CAE11 /* SDWeakProxy.m */; };
+		325C460E223394D8004CAE11 /* SDImageCachesManagerOperation.h in Headers */ = {isa = PBXBuildFile; fileRef = 325C460C223394D8004CAE11 /* SDImageCachesManagerOperation.h */; settings = {ATTRIBUTES = (Private, ); }; };
+		325C460F223394D8004CAE11 /* SDImageCachesManagerOperation.h in Headers */ = {isa = PBXBuildFile; fileRef = 325C460C223394D8004CAE11 /* SDImageCachesManagerOperation.h */; settings = {ATTRIBUTES = (Private, ); }; };
+		325C4610223394D8004CAE11 /* SDImageCachesManagerOperation.m in Sources */ = {isa = PBXBuildFile; fileRef = 325C460D223394D8004CAE11 /* SDImageCachesManagerOperation.m */; };
+		325C4611223394D8004CAE11 /* SDImageCachesManagerOperation.m in Sources */ = {isa = PBXBuildFile; fileRef = 325C460D223394D8004CAE11 /* SDImageCachesManagerOperation.m */; };
+		325C4614223399F7004CAE11 /* SDImageGIFCoder+Private.h in Headers */ = {isa = PBXBuildFile; fileRef = 325C4612223399F7004CAE11 /* SDImageGIFCoder+Private.h */; settings = {ATTRIBUTES = (Private, ); }; };
+		325C4615223399F7004CAE11 /* SDImageGIFCoder+Private.h in Headers */ = {isa = PBXBuildFile; fileRef = 325C4612223399F7004CAE11 /* SDImageGIFCoder+Private.h */; settings = {ATTRIBUTES = (Private, ); }; };
+		325C461A22339B5F004CAE11 /* SDImageAPNGCoder+Private.h in Headers */ = {isa = PBXBuildFile; fileRef = 325C461822339B5F004CAE11 /* SDImageAPNGCoder+Private.h */; settings = {ATTRIBUTES = (Private, ); }; };
+		325C461B22339B5F004CAE11 /* SDImageAPNGCoder+Private.h in Headers */ = {isa = PBXBuildFile; fileRef = 325C461822339B5F004CAE11 /* SDImageAPNGCoder+Private.h */; settings = {ATTRIBUTES = (Private, ); }; };
+		325C46202233A02E004CAE11 /* UIColor+HexString.h in Headers */ = {isa = PBXBuildFile; fileRef = 325C461E2233A02E004CAE11 /* UIColor+HexString.h */; settings = {ATTRIBUTES = (Private, ); }; };
+		325C46212233A02E004CAE11 /* UIColor+HexString.h in Headers */ = {isa = PBXBuildFile; fileRef = 325C461E2233A02E004CAE11 /* UIColor+HexString.h */; settings = {ATTRIBUTES = (Private, ); }; };
+		325C46222233A02E004CAE11 /* UIColor+HexString.m in Sources */ = {isa = PBXBuildFile; fileRef = 325C461F2233A02E004CAE11 /* UIColor+HexString.m */; };
+		325C46232233A02E004CAE11 /* UIColor+HexString.m in Sources */ = {isa = PBXBuildFile; fileRef = 325C461F2233A02E004CAE11 /* UIColor+HexString.m */; };
+		325C46262233A0A8004CAE11 /* NSBezierPath+RoundedCorners.h in Headers */ = {isa = PBXBuildFile; fileRef = 325C46242233A0A8004CAE11 /* NSBezierPath+RoundedCorners.h */; settings = {ATTRIBUTES = (Private, ); }; };
+		325C46272233A0A8004CAE11 /* NSBezierPath+RoundedCorners.h in Headers */ = {isa = PBXBuildFile; fileRef = 325C46242233A0A8004CAE11 /* NSBezierPath+RoundedCorners.h */; settings = {ATTRIBUTES = (Private, ); }; };
+		325C46282233A0A8004CAE11 /* NSBezierPath+RoundedCorners.m in Sources */ = {isa = PBXBuildFile; fileRef = 325C46252233A0A8004CAE11 /* NSBezierPath+RoundedCorners.m */; };
+		325C46292233A0A8004CAE11 /* NSBezierPath+RoundedCorners.m in Sources */ = {isa = PBXBuildFile; fileRef = 325C46252233A0A8004CAE11 /* NSBezierPath+RoundedCorners.m */; };
 		327054D4206CD8B3006EA328 /* SDImageAPNGCoder.h in Headers */ = {isa = PBXBuildFile; fileRef = 327054D2206CD8B3006EA328 /* SDImageAPNGCoder.h */; settings = {ATTRIBUTES = (Public, ); }; };
 		327054D6206CD8B3006EA328 /* SDImageAPNGCoder.h in Headers */ = {isa = PBXBuildFile; fileRef = 327054D2206CD8B3006EA328 /* SDImageAPNGCoder.h */; settings = {ATTRIBUTES = (Public, ); }; };
 		327054DA206CD8B3006EA328 /* SDImageAPNGCoder.m in Sources */ = {isa = PBXBuildFile; fileRef = 327054D3206CD8B3006EA328 /* SDImageAPNGCoder.m */; };
@@ -259,6 +283,18 @@
 		325312C7200F09910046BF1E /* SDWebImageTransition.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SDWebImageTransition.m; sourceTree = "<group>"; };
 		3257EAF721898AED0097B271 /* SDImageGraphics.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SDImageGraphics.h; sourceTree = "<group>"; };
 		3257EAF821898AED0097B271 /* SDImageGraphics.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SDImageGraphics.m; sourceTree = "<group>"; };
+		325C460022339330004CAE11 /* SDImageAssetManager.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SDImageAssetManager.h; sourceTree = "<group>"; };
+		325C460122339330004CAE11 /* SDImageAssetManager.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SDImageAssetManager.m; sourceTree = "<group>"; };
+		325C460622339426004CAE11 /* SDWeakProxy.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SDWeakProxy.h; sourceTree = "<group>"; };
+		325C460722339426004CAE11 /* SDWeakProxy.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SDWeakProxy.m; sourceTree = "<group>"; };
+		325C460C223394D8004CAE11 /* SDImageCachesManagerOperation.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SDImageCachesManagerOperation.h; sourceTree = "<group>"; };
+		325C460D223394D8004CAE11 /* SDImageCachesManagerOperation.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SDImageCachesManagerOperation.m; sourceTree = "<group>"; };
+		325C4612223399F7004CAE11 /* SDImageGIFCoder+Private.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "SDImageGIFCoder+Private.h"; sourceTree = "<group>"; };
+		325C461822339B5F004CAE11 /* SDImageAPNGCoder+Private.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "SDImageAPNGCoder+Private.h"; sourceTree = "<group>"; };
+		325C461E2233A02E004CAE11 /* UIColor+HexString.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "UIColor+HexString.h"; sourceTree = "<group>"; };
+		325C461F2233A02E004CAE11 /* UIColor+HexString.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = "UIColor+HexString.m"; sourceTree = "<group>"; };
+		325C46242233A0A8004CAE11 /* NSBezierPath+RoundedCorners.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "NSBezierPath+RoundedCorners.h"; sourceTree = "<group>"; };
+		325C46252233A0A8004CAE11 /* NSBezierPath+RoundedCorners.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = "NSBezierPath+RoundedCorners.m"; sourceTree = "<group>"; };
 		327054D2206CD8B3006EA328 /* SDImageAPNGCoder.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDImageAPNGCoder.h; sourceTree = "<group>"; };
 		327054D3206CD8B3006EA328 /* SDImageAPNGCoder.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SDImageAPNGCoder.m; sourceTree = "<group>"; };
 		328BB69A2081FED200760D6C /* SDWebImageCacheKeyFilter.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SDWebImageCacheKeyFilter.h; sourceTree = "<group>"; };
@@ -449,6 +485,18 @@
 			children = (
 				32B5CC5E222F89C2005EB74E /* SDAsyncBlockOperation.h */,
 				32B5CC5F222F89C2005EB74E /* SDAsyncBlockOperation.m */,
+				325C460622339426004CAE11 /* SDWeakProxy.h */,
+				325C460722339426004CAE11 /* SDWeakProxy.m */,
+				325C460022339330004CAE11 /* SDImageAssetManager.h */,
+				325C460122339330004CAE11 /* SDImageAssetManager.m */,
+				325C460C223394D8004CAE11 /* SDImageCachesManagerOperation.h */,
+				325C460D223394D8004CAE11 /* SDImageCachesManagerOperation.m */,
+				325C4612223399F7004CAE11 /* SDImageGIFCoder+Private.h */,
+				325C461822339B5F004CAE11 /* SDImageAPNGCoder+Private.h */,
+				325C461E2233A02E004CAE11 /* UIColor+HexString.h */,
+				325C461F2233A02E004CAE11 /* UIColor+HexString.m */,
+				325C46242233A0A8004CAE11 /* NSBezierPath+RoundedCorners.h */,
+				325C46252233A0A8004CAE11 /* NSBezierPath+RoundedCorners.m */,
 			);
 			path = Private;
 			sourceTree = "<group>";
@@ -655,12 +703,14 @@
 				3257EAFA21898AED0097B271 /* SDImageGraphics.h in Headers */,
 				32D3CDD121DDE87300C4DB49 /* UIImage+MemoryCacheCost.h in Headers */,
 				328BB6AC2081FEE500760D6C /* SDWebImageCacheSerializer.h in Headers */,
+				325C46272233A0A8004CAE11 /* NSBezierPath+RoundedCorners.h in Headers */,
 				321B378F2083290E00C0EA77 /* SDImageLoadersManager.h in Headers */,
 				329A185B1FFF5DFD008C9A2F /* UIImage+Metadata.h in Headers */,
 				4369C2791D9807EC007E863A /* UIView+WebCache.h in Headers */,
 				32F21B5320788D8C0036B1D5 /* SDWebImageDownloaderRequestModifier.h in Headers */,
 				321E60961F38E8ED00405457 /* SDImageIOCoder.h in Headers */,
 				4A2CAE041AB4BB5400B6BC39 /* SDWebImage.h in Headers */,
+				325C460322339330004CAE11 /* SDImageAssetManager.h in Headers */,
 				327054D6206CD8B3006EA328 /* SDImageAPNGCoder.h in Headers */,
 				80B6DF842142B44600BCB334 /* NSButton+WebCache.h in Headers */,
 				43A918661D8308FE00B3925F /* SDImageCacheConfig.h in Headers */,
@@ -678,12 +728,16 @@
 				4A2CAE2B1AB4BB7500B6BC39 /* UIButton+WebCache.h in Headers */,
 				4A2CAE251AB4BB7000B6BC39 /* SDWebImagePrefetcher.h in Headers */,
 				328BB6CF2082581100760D6C /* SDMemoryCache.h in Headers */,
+				325C460F223394D8004CAE11 /* SDImageCachesManagerOperation.h in Headers */,
+				325C461B22339B5F004CAE11 /* SDImageAPNGCoder+Private.h in Headers */,
 				321E60881F38E8C800405457 /* SDImageCoder.h in Headers */,
 				4A2CAE371AB4BB7500B6BC39 /* UIView+WebCacheOperation.h in Headers */,
 				321B37832083290E00C0EA77 /* SDImageLoader.h in Headers */,
 				32484777201775F600AF9E5A /* SDAnimatedImage.h in Headers */,
+				325C460922339426004CAE11 /* SDWeakProxy.h in Headers */,
 				80B6DF812142B43B00BCB334 /* SDAnimatedImageRep.h in Headers */,
 				4A2CAE2F1AB4BB7500B6BC39 /* UIImage+MultiFormat.h in Headers */,
+				325C46212233A02E004CAE11 /* UIColor+HexString.h in Headers */,
 				325312CA200F09910046BF1E /* SDWebImageTransition.h in Headers */,
 				4A2CAE1A1AB4BB6400B6BC39 /* SDWebImageOperation.h in Headers */,
 				32484765201775F600AF9E5A /* SDAnimatedImageView+WebCache.h in Headers */,
@@ -692,6 +746,7 @@
 				4A2CAE1B1AB4BB6800B6BC39 /* SDWebImageDownloader.h in Headers */,
 				3248476B201775F600AF9E5A /* SDAnimatedImageView.h in Headers */,
 				32D122322080B2EB003685A3 /* SDImageCachesManager.h in Headers */,
+				325C4615223399F7004CAE11 /* SDImageGIFCoder+Private.h in Headers */,
 				32F7C0862030719600873181 /* UIImage+Transform.h in Headers */,
 				321E60C01F38E91700405457 /* UIImage+ForceDecode.h in Headers */,
 				80B6DF7F2142B43300BCB334 /* NSImage+Compatibility.h in Headers */,
@@ -713,12 +768,14 @@
 				3257EAF921898AED0097B271 /* SDImageGraphics.h in Headers */,
 				32D3CDD021DDE87300C4DB49 /* UIImage+MemoryCacheCost.h in Headers */,
 				53761316155AD0D5005750A4 /* SDImageCache.h in Headers */,
+				325C46262233A0A8004CAE11 /* NSBezierPath+RoundedCorners.h in Headers */,
 				325312C8200F09910046BF1E /* SDWebImageTransition.h in Headers */,
 				32C0FDE12013426C001B8F2D /* SDWebImageIndicator.h in Headers */,
 				321E60A21F38E8F600405457 /* SDImageGIFCoder.h in Headers */,
 				5D5B9142188EE8DD006D06BD /* NSData+ImageContentType.h in Headers */,
 				328BB6C12082581100760D6C /* SDDiskCache.h in Headers */,
 				53761318155AD0D5005750A4 /* SDWebImageCompat.h in Headers */,
+				325C460222339330004CAE11 /* SDImageAssetManager.h in Headers */,
 				3290FA041FA478AF0047D20C /* SDImageFrame.h in Headers */,
 				80B6DF852142B44700BCB334 /* NSButton+WebCache.h in Headers */,
 				807A12281F89636300EC2A9B /* SDImageCodersManager.h in Headers */,
@@ -736,12 +793,16 @@
 				321E60BE1F38E91700405457 /* UIImage+ForceDecode.h in Headers */,
 				5376131E155AD0D5005750A4 /* SDWebImagePrefetcher.h in Headers */,
 				32F7C06F2030114C00873181 /* SDImageTransformer.h in Headers */,
+				325C460E223394D8004CAE11 /* SDImageCachesManagerOperation.h in Headers */,
+				325C461A22339B5F004CAE11 /* SDImageAPNGCoder+Private.h in Headers */,
 				321B378D2083290E00C0EA77 /* SDImageLoadersManager.h in Headers */,
 				32FDE8A220888789008D7530 /* SDWebImage.h in Headers */,
 				324DF4B4200A14DC008A84CC /* SDWebImageDefine.h in Headers */,
 				5376131F155AD0D5005750A4 /* UIButton+WebCache.h in Headers */,
+				325C460822339426004CAE11 /* SDWeakProxy.h in Headers */,
 				80B6DF802142B43A00BCB334 /* SDAnimatedImageRep.h in Headers */,
 				327054D4206CD8B3006EA328 /* SDImageAPNGCoder.h in Headers */,
+				325C46202233A02E004CAE11 /* UIColor+HexString.h in Headers */,
 				53761320155AD0D5005750A4 /* UIImageView+WebCache.h in Headers */,
 				328BB69C2081FED200760D6C /* SDWebImageCacheKeyFilter.h in Headers */,
 				530E49E816464C25002868E7 /* SDWebImageOperation.h in Headers */,
@@ -750,6 +811,7 @@
 				ABBE71A718C43B4D00B75E91 /* UIImageView+HighlightedWebCache.h in Headers */,
 				320CAE152086F50500CFFC80 /* SDWebImageError.h in Headers */,
 				321B37812083290E00C0EA77 /* SDImageLoader.h in Headers */,
+				325C4614223399F7004CAE11 /* SDImageGIFCoder+Private.h in Headers */,
 				321E60861F38E8C800405457 /* SDImageCoder.h in Headers */,
 				32484763201775F600AF9E5A /* SDAnimatedImageView+WebCache.h in Headers */,
 				80B6DF7E2142B43300BCB334 /* NSImage+Compatibility.h in Headers */,
@@ -903,6 +965,7 @@
 			files = (
 				3257EAFD21898AED0097B271 /* SDImageGraphics.m in Sources */,
 				3290FA0C1FA478AF0047D20C /* SDImageFrame.m in Sources */,
+				325C46232233A02E004CAE11 /* UIColor+HexString.m in Sources */,
 				321E60C61F38E91700405457 /* UIImage+ForceDecode.m in Sources */,
 				328BB6A42081FED200760D6C /* SDWebImageCacheKeyFilter.m in Sources */,
 				4A2CAE2E1AB4BB7500B6BC39 /* UIImage+GIF.m in Sources */,
@@ -929,6 +992,7 @@
 				32D1222C2080B2EB003685A3 /* SDImageCachesManager.m in Sources */,
 				32B9B53F206ED4230026769D /* SDWebImageDownloaderConfig.m in Sources */,
 				43A9186D1D8308FE00B3925F /* SDImageCacheConfig.m in Sources */,
+				325C46292233A0A8004CAE11 /* NSBezierPath+RoundedCorners.m in Sources */,
 				3248477D201775F600AF9E5A /* SDAnimatedImageView+WebCache.m in Sources */,
 				321E60AA1F38E8F600405457 /* SDImageGIFCoder.m in Sources */,
 				321E608E1F38E8C800405457 /* SDImageCoder.m in Sources */,
@@ -937,11 +1001,13 @@
 				4A2CAE2A1AB4BB7500B6BC39 /* NSData+ImageContentType.m in Sources */,
 				4A2CAE221AB4BB7000B6BC39 /* SDWebImageManager.m in Sources */,
 				4A2CAE191AB4BB6400B6BC39 /* SDWebImageCompat.m in Sources */,
+				325C460B22339426004CAE11 /* SDWeakProxy.m in Sources */,
 				321B37892083290E00C0EA77 /* SDImageLoader.m in Sources */,
 				32484771201775F600AF9E5A /* SDAnimatedImage.m in Sources */,
 				807A12301F89636300EC2A9B /* SDImageCodersManager.m in Sources */,
 				4A2CAE2C1AB4BB7500B6BC39 /* UIButton+WebCache.m in Sources */,
 				32D122262080B2EB003685A3 /* SDImageCacheDefine.m in Sources */,
+				325C460522339330004CAE11 /* SDImageAssetManager.m in Sources */,
 				324DF4BC200A14DC008A84CC /* SDWebImageDefine.m in Sources */,
 				4A2CAE381AB4BB7500B6BC39 /* UIView+WebCacheOperation.m in Sources */,
 				32EB6D8E206D132E005CAEF6 /* SDAnimatedImageRep.m in Sources */,
@@ -950,6 +1016,7 @@
 				4369C2801D9807EC007E863A /* UIView+WebCache.m in Sources */,
 				329A18611FFF5DFD008C9A2F /* UIImage+Metadata.m in Sources */,
 				328BB6B22081FEE500760D6C /* SDWebImageCacheSerializer.m in Sources */,
+				325C4611223394D8004CAE11 /* SDImageCachesManagerOperation.m in Sources */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};
@@ -959,6 +1026,7 @@
 			files = (
 				3257EAFC21898AED0097B271 /* SDImageGraphics.m in Sources */,
 				3290FA0A1FA478AF0047D20C /* SDImageFrame.m in Sources */,
+				325C46222233A02E004CAE11 /* UIColor+HexString.m in Sources */,
 				321E60C41F38E91700405457 /* UIImage+ForceDecode.m in Sources */,
 				328BB6A22081FED200760D6C /* SDWebImageCacheKeyFilter.m in Sources */,
 				53761309155AD0D5005750A4 /* SDImageCache.m in Sources */,
@@ -985,6 +1053,7 @@
 				32D1222A2080B2EB003685A3 /* SDImageCachesManager.m in Sources */,
 				32B9B53D206ED4230026769D /* SDWebImageDownloaderConfig.m in Sources */,
 				43A9186B1D8308FE00B3925F /* SDImageCacheConfig.m in Sources */,
+				325C46282233A0A8004CAE11 /* NSBezierPath+RoundedCorners.m in Sources */,
 				3248477B201775F600AF9E5A /* SDAnimatedImageView+WebCache.m in Sources */,
 				321E60A81F38E8F600405457 /* SDImageGIFCoder.m in Sources */,
 				321E608C1F38E8C800405457 /* SDImageCoder.m in Sources */,
@@ -993,11 +1062,13 @@
 				530E49EC16464C84002868E7 /* SDWebImageDownloaderOperation.m in Sources */,
 				53406750167780C40042B59E /* SDWebImageCompat.m in Sources */,
 				321B37872083290E00C0EA77 /* SDImageLoader.m in Sources */,
+				325C460A22339426004CAE11 /* SDWeakProxy.m in Sources */,
 				3248476F201775F600AF9E5A /* SDAnimatedImage.m in Sources */,
 				807A122E1F89636300EC2A9B /* SDImageCodersManager.m in Sources */,
 				A18A6CC9172DC28500419892 /* UIImage+GIF.m in Sources */,
 				32D122242080B2EB003685A3 /* SDImageCacheDefine.m in Sources */,
 				324DF4BA200A14DC008A84CC /* SDWebImageDefine.m in Sources */,
+				325C460422339330004CAE11 /* SDImageAssetManager.m in Sources */,
 				AB615306192DA24600A2D8E9 /* UIView+WebCacheOperation.m in Sources */,
 				32EB6D91206D132E005CAEF6 /* SDAnimatedImageRep.m in Sources */,
 				5D5B9145188EE8DD006D06BD /* NSData+ImageContentType.m in Sources */,
@@ -1006,6 +1077,7 @@
 				4369C27E1D9807EC007E863A /* UIView+WebCache.m in Sources */,
 				329A185F1FFF5DFD008C9A2F /* UIImage+Metadata.m in Sources */,
 				328BB6B02081FEE500760D6C /* SDWebImageCacheSerializer.m in Sources */,
+				325C4610223394D8004CAE11 /* SDImageCachesManagerOperation.m in Sources */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};

+ 24 - 0
SDWebImage/Private/NSBezierPath+RoundedCorners.h

@@ -0,0 +1,24 @@
+/*
+ * This file is part of the SDWebImage package.
+ * (c) Olivier Poitrey <rs@dailymotion.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+#import "SDWebImageCompat.h"
+
+#if SD_MAC
+
+#import "UIImage+Transform.h"
+
+@interface NSBezierPath (RoundedCorners)
+
+/**
+ Convenience way to create a bezier path with the specify rounding corners on macOS. Same as the one on `UIBezierPath`.
+ */
++ (nonnull instancetype)sd_bezierPathWithRoundedRect:(NSRect)rect byRoundingCorners:(SDRectCorner)corners cornerRadius:(CGFloat)cornerRadius;
+
+@end
+
+#endif

+ 42 - 0
SDWebImage/Private/NSBezierPath+RoundedCorners.m

@@ -0,0 +1,42 @@
+/*
+ * This file is part of the SDWebImage package.
+ * (c) Olivier Poitrey <rs@dailymotion.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+#import "NSBezierPath+RoundedCorners.h"
+
+#if SD_MAC
+
+@implementation NSBezierPath (RoundedCorners)
+
++ (instancetype)sd_bezierPathWithRoundedRect:(NSRect)rect byRoundingCorners:(SDRectCorner)corners cornerRadius:(CGFloat)cornerRadius {
+    NSBezierPath *path = [NSBezierPath bezierPath];
+    
+    CGFloat maxCorner = MIN(NSWidth(rect), NSHeight(rect)) / 2;
+    
+    CGFloat topLeftRadius = MIN(maxCorner, (corners & SDRectCornerTopLeft) ? cornerRadius : 0);
+    CGFloat topRightRadius = MIN(maxCorner, (corners & SDRectCornerTopRight) ? cornerRadius : 0);
+    CGFloat bottomLeftRadius = MIN(maxCorner, (corners & SDRectCornerBottomLeft) ? cornerRadius : 0);
+    CGFloat bottomRightRadius = MIN(maxCorner, (corners & SDRectCornerBottomRight) ? cornerRadius : 0);
+    
+    NSPoint topLeft = NSMakePoint(NSMinX(rect), NSMaxY(rect));
+    NSPoint topRight = NSMakePoint(NSMaxX(rect), NSMaxY(rect));
+    NSPoint bottomLeft = NSMakePoint(NSMinX(rect), NSMinY(rect));
+    NSPoint bottomRight = NSMakePoint(NSMaxX(rect), NSMinY(rect));
+    
+    [path moveToPoint:NSMakePoint(NSMidX(rect), NSMaxY(rect))];
+    [path appendBezierPathWithArcFromPoint:topLeft toPoint:bottomLeft radius:topLeftRadius];
+    [path appendBezierPathWithArcFromPoint:bottomLeft toPoint:bottomRight radius:bottomLeftRadius];
+    [path appendBezierPathWithArcFromPoint:bottomRight toPoint:topRight radius:bottomRightRadius];
+    [path appendBezierPathWithArcFromPoint:topRight toPoint:topLeft radius:topRightRadius];
+    [path closePath];
+    
+    return path;
+}
+
+@end
+
+#endif

+ 17 - 0
SDWebImage/Private/SDImageAPNGCoder+Private.h

@@ -0,0 +1,17 @@
+/*
+ * This file is part of the SDWebImage package.
+ * (c) Olivier Poitrey <rs@dailymotion.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+#import "SDWebImageCompat.h"
+#import "SDImageAPNGCoder.h"
+
+@interface SDImageAPNGCoder ()
+
+- (float)sd_frameDurationAtIndex:(NSUInteger)index source:(nonnull CGImageSourceRef)source;
+- (NSUInteger)sd_imageLoopCountWithSource:(nonnull CGImageSourceRef)source;
+
+@end

+ 23 - 0
SDWebImage/Private/SDImageAssetManager.h

@@ -0,0 +1,23 @@
+/*
+ * This file is part of the SDWebImage package.
+ * (c) Olivier Poitrey <rs@dailymotion.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+#import <Foundation/Foundation.h>
+#import "SDWebImageCompat.h"
+
+// Apple parse the Asset Catalog compiled file(`Assets.car`) by CoreUI.framework, however it's a private framework and there are no other ways to directly get the data. So we just process the normal bundle files :)
+
+@interface SDImageAssetManager : NSObject
+
+@property (nonatomic, strong, nonnull) NSMapTable<NSString *, UIImage *> *imageTable;
+
++ (nonnull instancetype)sharedAssetManager;
+- (nullable NSString *)getPathForName:(nonnull NSString *)name bundle:(nonnull NSBundle *)bundle preferredScale:(nonnull CGFloat *)scale;
+- (nullable UIImage *)imageForName:(nonnull NSString *)name;
+- (void)storeImage:(nonnull UIImage *)image forName:(nonnull NSString *)name;
+
+@end

+ 157 - 0
SDWebImage/Private/SDImageAssetManager.m

@@ -0,0 +1,157 @@
+/*
+ * This file is part of the SDWebImage package.
+ * (c) Olivier Poitrey <rs@dailymotion.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+#import "SDImageAssetManager.h"
+
+static NSArray *SDBundlePreferredScales() {
+    static NSArray *scales;
+    static dispatch_once_t onceToken;
+    dispatch_once(&onceToken, ^{
+#if SD_WATCH
+        CGFloat screenScale = [WKInterfaceDevice currentDevice].screenScale;
+#elif SD_UIKIT
+        CGFloat screenScale = [UIScreen mainScreen].scale;
+#elif SD_MAC
+        CGFloat screenScale = [NSScreen mainScreen].backingScaleFactor;
+#endif
+        if (screenScale <= 1) {
+            scales = @[@1,@2,@3];
+        } else if (screenScale <= 2) {
+            scales = @[@2,@3,@1];
+        } else {
+            scales = @[@3,@2,@1];
+        }
+    });
+    return scales;
+}
+
+@implementation SDImageAssetManager {
+    dispatch_semaphore_t _lock;
+}
+
++ (instancetype)sharedAssetManager {
+    static dispatch_once_t onceToken;
+    static SDImageAssetManager *assetManager;
+    dispatch_once(&onceToken, ^{
+        assetManager = [[SDImageAssetManager alloc] init];
+    });
+    return assetManager;
+}
+
+- (instancetype)init {
+    self = [super init];
+    if (self) {
+        NSPointerFunctionsOptions valueOptions;
+#if SD_MAC
+        // Apple says that NSImage use a weak reference to value
+        valueOptions = NSPointerFunctionsWeakMemory;
+#else
+        // Apple says that UIImage use a strong reference to value
+        valueOptions = NSPointerFunctionsStrongMemory;
+#endif
+        _imageTable = [NSMapTable mapTableWithKeyOptions:NSPointerFunctionsCopyIn valueOptions:valueOptions];
+        _lock = dispatch_semaphore_create(1);
+#if SD_UIKIT
+        [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(didReceiveMemoryWarning:) name:UIApplicationDidReceiveMemoryWarningNotification object:nil];
+#endif
+    }
+    return self;
+}
+
+- (void)dealloc {
+#if SD_UIKIT
+    [[NSNotificationCenter defaultCenter] removeObserver:self name:UIApplicationDidReceiveMemoryWarningNotification object:nil];
+#endif
+}
+
+- (void)didReceiveMemoryWarning:(NSNotification *)notification {
+    SD_LOCK(_lock);
+    [self.imageTable removeAllObjects];
+    SD_UNLOCK(_lock);
+}
+
+- (NSString *)getPathForName:(NSString *)name bundle:(NSBundle *)bundle preferredScale:(CGFloat *)scale {
+    NSParameterAssert(name);
+    NSParameterAssert(bundle);
+    NSString *path;
+    if (name.length == 0) {
+        return path;
+    }
+    if ([name hasSuffix:@"/"]) {
+        return path;
+    }
+    NSString *extension = name.pathExtension;
+    if (extension.length == 0) {
+        // If no extension, follow Apple's doc, check PNG format
+        extension = @"png";
+    }
+    name = [name stringByDeletingPathExtension];
+    
+    CGFloat providedScale = *scale;
+    NSArray *scales = SDBundlePreferredScales();
+    
+    // Check if file name contains scale
+    for (size_t i = 0; i < scales.count; i++) {
+        NSNumber *scaleValue = scales[i];
+        if ([name hasSuffix:[NSString stringWithFormat:@"@%@x", scaleValue]]) {
+            path = [bundle pathForResource:name ofType:extension];
+            if (path) {
+                *scale = scaleValue.doubleValue; // override
+                return path;
+            }
+        }
+    }
+    
+    // Search with provided scale first
+    if (providedScale != 0) {
+        NSString *scaledName = [name stringByAppendingFormat:@"@%@x", @(providedScale)];
+        path = [bundle pathForResource:scaledName ofType:extension];
+        if (path) {
+            return path;
+        }
+    }
+    
+    // Search with preferred scale
+    for (size_t i = 0; i < scales.count; i++) {
+        NSNumber *scaleValue = scales[i];
+        if (scaleValue.doubleValue == providedScale) {
+            // Ignore provided scale
+            continue;
+        }
+        NSString *scaledName = [name stringByAppendingFormat:@"@%@x", scaleValue];
+        path = [bundle pathForResource:scaledName ofType:extension];
+        if (path) {
+            *scale = scaleValue.doubleValue; // override
+            return path;
+        }
+    }
+    
+    // Search without scale
+    path = [bundle pathForResource:name ofType:extension];
+    
+    return path;
+}
+
+- (UIImage *)imageForName:(NSString *)name {
+    NSParameterAssert(name);
+    UIImage *image;
+    SD_LOCK(_lock);
+    image = [self.imageTable objectForKey:name];
+    SD_UNLOCK(_lock);
+    return image;
+}
+
+- (void)storeImage:(UIImage *)image forName:(NSString *)name {
+    NSParameterAssert(image);
+    NSParameterAssert(name);
+    SD_LOCK(_lock);
+    [self.imageTable setObject:image forKey:name];
+    SD_UNLOCK(_lock);
+}
+
+@end

+ 21 - 0
SDWebImage/Private/SDImageCachesManagerOperation.h

@@ -0,0 +1,21 @@
+/*
+ * This file is part of the SDWebImage package.
+ * (c) Olivier Poitrey <rs@dailymotion.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+#import <Foundation/Foundation.h>
+#import "SDWebImageCompat.h"
+
+// This is used for operation management, but not for operation queue execute
+@interface SDImageCachesManagerOperation : NSOperation
+
+@property (nonatomic, assign, readonly) NSUInteger pendingCount;
+
+- (void)beginWithTotalCount:(NSUInteger)totalCount;
+- (void)completeOne;
+- (void)done;
+
+@end

+ 60 - 0
SDWebImage/Private/SDImageCachesManagerOperation.m

@@ -0,0 +1,60 @@
+/*
+ * This file is part of the SDWebImage package.
+ * (c) Olivier Poitrey <rs@dailymotion.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+#import "SDImageCachesManagerOperation.h"
+
+@implementation SDImageCachesManagerOperation
+
+@synthesize executing = _executing;
+@synthesize finished = _finished;
+@synthesize cancelled = _cancelled;
+
+- (void)beginWithTotalCount:(NSUInteger)totalCount {
+    self.executing = YES;
+    self.finished = NO;
+    _pendingCount = totalCount;
+}
+
+- (void)completeOne {
+    _pendingCount = _pendingCount > 0 ? _pendingCount - 1 : 0;
+}
+
+- (void)cancel {
+    self.cancelled = YES;
+    [self reset];
+}
+
+- (void)done {
+    self.finished = YES;
+    self.executing = NO;
+    [self reset];
+}
+
+- (void)reset {
+    _pendingCount = 0;
+}
+
+- (void)setFinished:(BOOL)finished {
+    [self willChangeValueForKey:@"isFinished"];
+    _finished = finished;
+    [self didChangeValueForKey:@"isFinished"];
+}
+
+- (void)setExecuting:(BOOL)executing {
+    [self willChangeValueForKey:@"isExecuting"];
+    _executing = executing;
+    [self didChangeValueForKey:@"isExecuting"];
+}
+
+- (void)setCancelled:(BOOL)cancelled {
+    [self willChangeValueForKey:@"isCancelled"];
+    _cancelled = cancelled;
+    [self didChangeValueForKey:@"isCancelled"];
+}
+
+@end

+ 16 - 0
SDWebImage/Private/SDImageGIFCoder+Private.h

@@ -0,0 +1,16 @@
+/*
+ * This file is part of the SDWebImage package.
+ * (c) Olivier Poitrey <rs@dailymotion.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+#import "SDWebImageCompat.h"
+#import "SDImageGIFCoder.h"
+
+@interface SDImageGIFCoder ()
+
+- (float)sd_frameDurationAtIndex:(NSUInteger)index source:(nonnull CGImageSourceRef)source;
+
+@end

+ 19 - 0
SDWebImage/Private/SDWeakProxy.h

@@ -0,0 +1,19 @@
+/*
+ * This file is part of the SDWebImage package.
+ * (c) Olivier Poitrey <rs@dailymotion.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+#import <Foundation/Foundation.h>
+#import "SDWebImageCompat.h"
+
+@interface SDWeakProxy : NSProxy
+
+@property (nonatomic, weak, readonly, nullable) id target;
+
+- (nonnull instancetype)initWithTarget:(nonnull id)target;
++ (nonnull instancetype)proxyWithTarget:(nonnull id)target;
+
+@end

+ 79 - 0
SDWebImage/Private/SDWeakProxy.m

@@ -0,0 +1,79 @@
+/*
+ * This file is part of the SDWebImage package.
+ * (c) Olivier Poitrey <rs@dailymotion.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+#import "SDWeakProxy.h"
+
+@implementation SDWeakProxy
+
+- (instancetype)initWithTarget:(id)target {
+    _target = target;
+    return self;
+}
+
++ (instancetype)proxyWithTarget:(id)target {
+    return [[SDWeakProxy alloc] initWithTarget:target];
+}
+
+- (id)forwardingTargetForSelector:(SEL)selector {
+    return _target;
+}
+
+- (void)forwardInvocation:(NSInvocation *)invocation {
+    void *null = NULL;
+    [invocation setReturnValue:&null];
+}
+
+- (NSMethodSignature *)methodSignatureForSelector:(SEL)selector {
+    return [NSObject instanceMethodSignatureForSelector:@selector(init)];
+}
+
+- (BOOL)respondsToSelector:(SEL)aSelector {
+    return [_target respondsToSelector:aSelector];
+}
+
+- (BOOL)isEqual:(id)object {
+    return [_target isEqual:object];
+}
+
+- (NSUInteger)hash {
+    return [_target hash];
+}
+
+- (Class)superclass {
+    return [_target superclass];
+}
+
+- (Class)class {
+    return [_target class];
+}
+
+- (BOOL)isKindOfClass:(Class)aClass {
+    return [_target isKindOfClass:aClass];
+}
+
+- (BOOL)isMemberOfClass:(Class)aClass {
+    return [_target isMemberOfClass:aClass];
+}
+
+- (BOOL)conformsToProtocol:(Protocol *)aProtocol {
+    return [_target conformsToProtocol:aProtocol];
+}
+
+- (BOOL)isProxy {
+    return YES;
+}
+
+- (NSString *)description {
+    return [_target description];
+}
+
+- (NSString *)debugDescription {
+    return [_target debugDescription];
+}
+
+@end

+ 18 - 0
SDWebImage/Private/UIColor+HexString.h

@@ -0,0 +1,18 @@
+/*
+ * This file is part of the SDWebImage package.
+ * (c) Olivier Poitrey <rs@dailymotion.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+#import "SDWebImageCompat.h"
+
+@interface UIColor (HexString)
+
+/**
+ Convenience way to get hex string from color. The output should always be 32-bit RGBA hex string like `#00000000`.
+ */
+@property (nonatomic, copy, readonly, nonnull) NSString *sd_hexString;
+
+@end

+ 42 - 0
SDWebImage/Private/UIColor+HexString.m

@@ -0,0 +1,42 @@
+/*
+ * This file is part of the SDWebImage package.
+ * (c) Olivier Poitrey <rs@dailymotion.com>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+#import "UIColor+HexString.h"
+
+@implementation UIColor (HexString)
+
+- (NSString *)sd_hexString {
+    CGFloat red, green, blue, alpha;
+#if SD_UIKIT
+    if (![self getRed:&red green:&green blue:&blue alpha:&alpha]) {
+        [self getWhite:&red alpha:&alpha];
+        green = red;
+        blue = red;
+    }
+#else
+    @try {
+        [self getRed:&red green:&green blue:&blue alpha:&alpha];
+    }
+    @catch (NSException *exception) {
+        [self getWhite:&red alpha:&alpha];
+        green = red;
+        blue = red;
+    }
+#endif
+    
+    red = roundf(red * 255.f);
+    green = roundf(green * 255.f);
+    blue = roundf(blue * 255.f);
+    alpha = roundf(alpha * 255.f);
+    
+    uint hex = ((uint)alpha << 24) | ((uint)red << 16) | ((uint)green << 8) | ((uint)blue);
+    
+    return [NSString stringWithFormat:@"#%08x", hex];
+}
+
+@end

+ 1 - 163
SDWebImage/SDAnimatedImage.m

@@ -12,6 +12,7 @@
 #import "SDImageCodersManager.h"
 #import "SDImageFrame.h"
 #import "UIImage+MemoryCacheCost.h"
+#import "SDImageAssetManager.h"
 #import "objc/runtime.h"
 
 static CGFloat SDImageScaleFromPath(NSString *string) {
@@ -29,169 +30,6 @@ static CGFloat SDImageScaleFromPath(NSString *string) {
     return scale;
 }
 
-static NSArray *SDBundlePreferredScales() {
-    static NSArray *scales;
-    static dispatch_once_t onceToken;
-    dispatch_once(&onceToken, ^{
-#if SD_WATCH
-        CGFloat screenScale = [WKInterfaceDevice currentDevice].screenScale;
-#elif SD_UIKIT
-        CGFloat screenScale = [UIScreen mainScreen].scale;
-#elif SD_MAC
-        CGFloat screenScale = [NSScreen mainScreen].backingScaleFactor;
-#endif
-        if (screenScale <= 1) {
-            scales = @[@1,@2,@3];
-        } else if (screenScale <= 2) {
-            scales = @[@2,@3,@1];
-        } else {
-            scales = @[@3,@2,@1];
-        }
-    });
-    return scales;
-}
-
-#pragma mark - UIImage cache for bundle
-
-// Apple parse the Asset Catalog compiled file(`Assets.car`) by CoreUI.framework, however it's a private framework and there are no other ways to directly get the data. So we just process the normal bundle files :)
-
-@interface SDImageAssetManager : NSObject {
-    dispatch_semaphore_t _lock;
-}
-
-@property (nonatomic, strong) NSMapTable<NSString *, UIImage *> *imageTable;
-
-+ (instancetype)sharedAssetManager;
-- (nullable NSString *)getPathForName:(nonnull NSString *)name bundle:(nonnull NSBundle *)bundle preferredScale:(CGFloat *)scale;
-- (nullable UIImage *)imageForName:(nonnull NSString *)name;
-- (void)storeImage:(nonnull UIImage *)image forName:(nonnull NSString *)name;
-
-@end
-
-@implementation SDImageAssetManager
-
-+ (instancetype)sharedAssetManager {
-    static dispatch_once_t onceToken;
-    static SDImageAssetManager *assetManager;
-    dispatch_once(&onceToken, ^{
-        assetManager = [[SDImageAssetManager alloc] init];
-    });
-    return assetManager;
-}
-
-- (instancetype)init {
-    self = [super init];
-    if (self) {
-        NSPointerFunctionsOptions valueOptions;
-#if SD_MAC
-        // Apple says that NSImage use a weak reference to value
-        valueOptions = NSPointerFunctionsWeakMemory;
-#else
-        // Apple says that UIImage use a strong reference to value
-        valueOptions = NSPointerFunctionsStrongMemory;
-#endif
-        _imageTable = [NSMapTable mapTableWithKeyOptions:NSPointerFunctionsCopyIn valueOptions:valueOptions];
-        _lock = dispatch_semaphore_create(1);
-#if SD_UIKIT
-        [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(didReceiveMemoryWarning:) name:UIApplicationDidReceiveMemoryWarningNotification object:nil];
-#endif
-    }
-    return self;
-}
-
-- (void)dealloc {
-#if SD_UIKIT
-    [[NSNotificationCenter defaultCenter] removeObserver:self name:UIApplicationDidReceiveMemoryWarningNotification object:nil];
-#endif
-}
-
-- (void)didReceiveMemoryWarning:(NSNotification *)notification {
-    SD_LOCK(_lock);
-    [self.imageTable removeAllObjects];
-    SD_UNLOCK(_lock);
-}
-
-- (NSString *)getPathForName:(NSString *)name bundle:(NSBundle *)bundle preferredScale:(CGFloat *)scale {
-    NSParameterAssert(name);
-    NSParameterAssert(bundle);
-    NSString *path;
-    if (name.length == 0) {
-        return path;
-    }
-    if ([name hasSuffix:@"/"]) {
-        return path;
-    }
-    NSString *extension = name.pathExtension;
-    if (extension.length == 0) {
-        // If no extension, follow Apple's doc, check PNG format
-        extension = @"png";
-    }
-    name = [name stringByDeletingPathExtension];
-    
-    CGFloat providedScale = *scale;
-    NSArray *scales = SDBundlePreferredScales();
-    
-    // Check if file name contains scale
-    for (size_t i = 0; i < scales.count; i++) {
-        NSNumber *scaleValue = scales[i];
-        if ([name hasSuffix:[NSString stringWithFormat:@"@%@x", scaleValue]]) {
-            path = [bundle pathForResource:name ofType:extension];
-            if (path) {
-                *scale = scaleValue.doubleValue; // override
-                return path;
-            }
-        }
-    }
-    
-    // Search with provided scale first
-    if (providedScale != 0) {
-        NSString *scaledName = [name stringByAppendingFormat:@"@%@x", @(providedScale)];
-        path = [bundle pathForResource:scaledName ofType:extension];
-        if (path) {
-            return path;
-        }
-    }
-    
-    // Search with preferred scale
-    for (size_t i = 0; i < scales.count; i++) {
-        NSNumber *scaleValue = scales[i];
-        if (scaleValue.doubleValue == providedScale) {
-            // Ignore provided scale
-            continue;
-        }
-        NSString *scaledName = [name stringByAppendingFormat:@"@%@x", scaleValue];
-        path = [bundle pathForResource:scaledName ofType:extension];
-        if (path) {
-            *scale = scaleValue.doubleValue; // override
-            return path;
-        }
-    }
-    
-    // Search without scale
-    path = [bundle pathForResource:name ofType:extension];
-    
-    return path;
-}
-
-- (UIImage *)imageForName:(NSString *)name {
-    NSParameterAssert(name);
-    UIImage *image;
-    SD_LOCK(_lock);
-    image = [self.imageTable objectForKey:name];
-    SD_UNLOCK(_lock);
-    return image;
-}
-
-- (void)storeImage:(UIImage *)image forName:(NSString *)name {
-    NSParameterAssert(image);
-    NSParameterAssert(name);
-    SD_LOCK(_lock);
-    [self.imageTable setObject:image forKey:name];
-    SD_UNLOCK(_lock);
-}
-
-@end
-
 @interface SDAnimatedImage ()
 
 @property (nonatomic, strong) id<SDAnimatedImageCoder> coder;

+ 2 - 15
SDWebImage/SDAnimatedImageRep.m

@@ -10,21 +10,8 @@
 
 #if SD_MAC
 
-#import "SDImageGIFCoder.h"
-#import "SDImageAPNGCoder.h"
-
-@interface SDImageGIFCoder ()
-
-- (float)sd_frameDurationAtIndex:(NSUInteger)index source:(CGImageSourceRef)source;
-
-@end
-
-@interface SDImageAPNGCoder ()
-
-- (float)sd_frameDurationAtIndex:(NSUInteger)index source:(CGImageSourceRef)source;
-- (NSUInteger)sd_imageLoopCountWithSource:(CGImageSourceRef)source;
-
-@end
+#import "SDImageGIFCoder+Private.h"
+#import "SDImageAPNGCoder+Private.h"
 
 @interface SDAnimatedImageRep ()
 

+ 1 - 79
SDWebImage/SDAnimatedImageView.m

@@ -12,6 +12,7 @@
 
 #import "UIImage+Metadata.h"
 #import "NSImage+Compatibility.h"
+#import "SDWeakProxy.h"
 #import <mach/mach.h>
 #import <objc/runtime.h>
 
@@ -38,85 +39,6 @@ static NSUInteger SDDeviceFreeMemory() {
     return vm_stat.free_count * page_size;
 }
 
-@interface SDWeakProxy : NSProxy
-
-@property (nonatomic, weak, readonly) id target;
-
-- (instancetype)initWithTarget:(id)target;
-+ (instancetype)proxyWithTarget:(id)target;
-
-@end
-
-@implementation SDWeakProxy
-
-- (instancetype)initWithTarget:(id)target {
-    _target = target;
-    return self;
-}
-
-+ (instancetype)proxyWithTarget:(id)target {
-    return [[SDWeakProxy alloc] initWithTarget:target];
-}
-
-- (id)forwardingTargetForSelector:(SEL)selector {
-    return _target;
-}
-
-- (void)forwardInvocation:(NSInvocation *)invocation {
-    void *null = NULL;
-    [invocation setReturnValue:&null];
-}
-
-- (NSMethodSignature *)methodSignatureForSelector:(SEL)selector {
-    return [NSObject instanceMethodSignatureForSelector:@selector(init)];
-}
-
-- (BOOL)respondsToSelector:(SEL)aSelector {
-    return [_target respondsToSelector:aSelector];
-}
-
-- (BOOL)isEqual:(id)object {
-    return [_target isEqual:object];
-}
-
-- (NSUInteger)hash {
-    return [_target hash];
-}
-
-- (Class)superclass {
-    return [_target superclass];
-}
-
-- (Class)class {
-    return [_target class];
-}
-
-- (BOOL)isKindOfClass:(Class)aClass {
-    return [_target isKindOfClass:aClass];
-}
-
-- (BOOL)isMemberOfClass:(Class)aClass {
-    return [_target isMemberOfClass:aClass];
-}
-
-- (BOOL)conformsToProtocol:(Protocol *)aProtocol {
-    return [_target conformsToProtocol:aProtocol];
-}
-
-- (BOOL)isProxy {
-    return YES;
-}
-
-- (NSString *)description {
-    return [_target description];
-}
-
-- (NSString *)debugDescription {
-    return [_target debugDescription];
-}
-
-@end
-
 @interface SDAnimatedImageView () <CALayerDelegate>
 
 @property (nonatomic, strong, readwrite) UIImage *currentFrame;

+ 1 - 62
SDWebImage/SDImageCachesManager.m

@@ -7,68 +7,7 @@
  */
 
 #import "SDImageCachesManager.h"
-
-// This is used for operation management, but not for operation queue execute
-@interface SDImageCachesManagerOperation : NSOperation
-
-@property (nonatomic, assign, readonly) NSUInteger pendingCount;
-
-- (void)beginWithTotalCount:(NSUInteger)totalCount;
-- (void)completeOne;
-- (void)done;
-
-@end
-
-@implementation SDImageCachesManagerOperation
-
-@synthesize executing = _executing;
-@synthesize finished = _finished;
-@synthesize cancelled = _cancelled;
-
-- (void)beginWithTotalCount:(NSUInteger)totalCount {
-    self.executing = YES;
-    self.finished = NO;
-    _pendingCount = totalCount;
-}
-
-- (void)completeOne {
-    _pendingCount = _pendingCount > 0 ? _pendingCount - 1 : 0;
-}
-
-- (void)cancel {
-    self.cancelled = YES;
-    [self reset];
-}
-
-- (void)done {
-    self.finished = YES;
-    self.executing = NO;
-    [self reset];
-}
-
-- (void)reset {
-    _pendingCount = 0;
-}
-
-- (void)setFinished:(BOOL)finished {
-    [self willChangeValueForKey:@"isFinished"];
-    _finished = finished;
-    [self didChangeValueForKey:@"isFinished"];
-}
-
-- (void)setExecuting:(BOOL)executing {
-    [self willChangeValueForKey:@"isExecuting"];
-    _executing = executing;
-    [self didChangeValueForKey:@"isExecuting"];
-}
-
-- (void)setCancelled:(BOOL)cancelled {
-    [self willChangeValueForKey:@"isCancelled"];
-    _cancelled = cancelled;
-    [self didChangeValueForKey:@"isCancelled"];
-}
-
-@end
+#import "SDImageCachesManagerOperation.h"
 
 @implementation SDImageCachesManager
 

+ 1 - 42
SDWebImage/SDImageTransformer.m

@@ -7,6 +7,7 @@
  */
 
 #import "SDImageTransformer.h"
+#import "UIColor+HexString.h"
 #if SD_UIKIT || SD_MAC
 #import <CoreImage/CoreImage.h>
 #endif
@@ -21,48 +22,6 @@ NSString * _Nullable SDTransformedKeyForKey(NSString * _Nullable key, NSString *
     return [[key stringByAppendingString:SDImageTransformerKeySeparator] stringByAppendingString:transformerKey];
 }
 
-@interface UIColor (HexString)
-
-/**
- Convenience way to get hex string from color. The output should always be 32-bit RGBA hex string like `#00000000`.
- */
-@property (nonatomic, copy, readonly, nonnull) NSString *sd_hexString;
-
-@end
-
-@implementation UIColor (HexString)
-
-- (NSString *)sd_hexString {
-    CGFloat red, green, blue, alpha;
-#if SD_UIKIT
-    if (![self getRed:&red green:&green blue:&blue alpha:&alpha]) {
-        [self getWhite:&red alpha:&alpha];
-        green = red;
-        blue = red;
-    }
-#else
-    @try {
-        [self getRed:&red green:&green blue:&blue alpha:&alpha];
-    }
-    @catch (NSException *exception) {
-        [self getWhite:&red alpha:&alpha];
-        green = red;
-        blue = red;
-    }
-#endif
-    
-    red = roundf(red * 255.f);
-    green = roundf(green * 255.f);
-    blue = roundf(blue * 255.f);
-    alpha = roundf(alpha * 255.f);
-    
-    uint hex = ((uint)alpha << 24) | ((uint)red << 16) | ((uint)green << 8) | ((uint)blue);
-    
-    return [NSString stringWithFormat:@"#%08x", hex];
-}
-
-@end
-
 @interface SDImagePipelineTransformer ()
 
 @property (nonatomic, copy, readwrite, nonnull) NSArray<id<SDImageTransformer>> *transformers;

+ 1 - 40
SDWebImage/UIImage+Transform.m

@@ -9,6 +9,7 @@
 #import "UIImage+Transform.h"
 #import "NSImage+Compatibility.h"
 #import "SDImageGraphics.h"
+#import "NSBezierPath+RoundedCorners.h"
 #import <Accelerate/Accelerate.h>
 #if SD_UIKIT || SD_MAC
 #import <CoreImage/CoreImage.h>
@@ -162,46 +163,6 @@ static inline UIColor * SDGetColorFromPixel(Pixel_8888 pixel, CGBitmapInfo bitma
     return [UIColor colorWithRed:r green:g blue:b alpha:a];
 }
 
-#if SD_MAC
-@interface NSBezierPath (RoundedCorners)
-
-/**
- Convenience way to create a bezier path with the specify rounding corners on macOS. Same as the one on `UIBezierPath`.
- */
-+ (nonnull instancetype)sd_bezierPathWithRoundedRect:(NSRect)rect byRoundingCorners:(SDRectCorner)corners cornerRadius:(CGFloat)cornerRadius;
-
-@end
-
-@implementation NSBezierPath (RoundedCorners)
-
-+ (instancetype)sd_bezierPathWithRoundedRect:(NSRect)rect byRoundingCorners:(SDRectCorner)corners cornerRadius:(CGFloat)cornerRadius {
-    NSBezierPath *path = [NSBezierPath bezierPath];
-    
-    CGFloat maxCorner = MIN(NSWidth(rect), NSHeight(rect)) / 2;
-    
-    CGFloat topLeftRadius = MIN(maxCorner, (corners & SDRectCornerTopLeft) ? cornerRadius : 0);
-    CGFloat topRightRadius = MIN(maxCorner, (corners & SDRectCornerTopRight) ? cornerRadius : 0);
-    CGFloat bottomLeftRadius = MIN(maxCorner, (corners & SDRectCornerBottomLeft) ? cornerRadius : 0);
-    CGFloat bottomRightRadius = MIN(maxCorner, (corners & SDRectCornerBottomRight) ? cornerRadius : 0);
-    
-    NSPoint topLeft = NSMakePoint(NSMinX(rect), NSMaxY(rect));
-    NSPoint topRight = NSMakePoint(NSMaxX(rect), NSMaxY(rect));
-    NSPoint bottomLeft = NSMakePoint(NSMinX(rect), NSMinY(rect));
-    NSPoint bottomRight = NSMakePoint(NSMaxX(rect), NSMinY(rect));
-    
-    [path moveToPoint:NSMakePoint(NSMidX(rect), NSMaxY(rect))];
-    [path appendBezierPathWithArcFromPoint:topLeft toPoint:bottomLeft radius:topLeftRadius];
-    [path appendBezierPathWithArcFromPoint:bottomLeft toPoint:bottomRight radius:bottomLeftRadius];
-    [path appendBezierPathWithArcFromPoint:bottomRight toPoint:topRight radius:bottomRightRadius];
-    [path appendBezierPathWithArcFromPoint:topRight toPoint:topLeft radius:topRightRadius];
-    [path closePath];
-    
-    return path;
-}
-
-@end
-#endif
-
 @implementation UIImage (Transform)
 
 - (void)sd_drawInRect:(CGRect)rect withScaleMode:(SDImageScaleMode)scaleMode clipsToBounds:(BOOL)clips {

+ 4 - 4
Tests/SDWebImage Tests.xcodeproj/project.pbxproj

@@ -408,7 +408,7 @@
 			files = (
 			);
 			inputPaths = (
-				"${SRCROOT}/Pods/Target Support Files/Pods-Tests Mac/Pods-Tests Mac-frameworks.sh",
+				"${PODS_ROOT}/Target Support Files/Pods-Tests Mac/Pods-Tests Mac-frameworks.sh",
 				"${BUILT_PRODUCTS_DIR}/Expecta-macOS/Expecta.framework",
 				"${BUILT_PRODUCTS_DIR}/KVOController-macOS/KVOController.framework",
 				"${BUILT_PRODUCTS_DIR}/SDWebImage-macOS/SDWebImage.framework",
@@ -421,7 +421,7 @@
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 			shellPath = /bin/sh;
-			shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-Tests Mac/Pods-Tests Mac-frameworks.sh\"\n";
+			shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Tests Mac/Pods-Tests Mac-frameworks.sh\"\n";
 			showEnvVarsInLog = 0;
 		};
 		A07943B19E185DC24535F340 /* [CP] Embed Pods Frameworks */ = {
@@ -430,7 +430,7 @@
 			files = (
 			);
 			inputPaths = (
-				"${SRCROOT}/Pods/Target Support Files/Pods-Tests/Pods-Tests-frameworks.sh",
+				"${PODS_ROOT}/Target Support Files/Pods-Tests/Pods-Tests-frameworks.sh",
 				"${BUILT_PRODUCTS_DIR}/Expecta-iOS/Expecta.framework",
 				"${BUILT_PRODUCTS_DIR}/KVOController-iOS/KVOController.framework",
 				"${BUILT_PRODUCTS_DIR}/SDWebImage-iOS/SDWebImage.framework",
@@ -443,7 +443,7 @@
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 			shellPath = /bin/sh;
-			shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-Tests/Pods-Tests-frameworks.sh\"\n";
+			shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Tests/Pods-Tests-frameworks.sh\"\n";
 			showEnvVarsInLog = 0;
 		};
 /* End PBXShellScriptBuildPhase section */