From a797da71ce147192d61a95c8207d2f25edea74eb Mon Sep 17 00:00:00 2001 From: DreamPiggy Date: Thu, 22 Jun 2023 19:00:36 +0800 Subject: [PATCH 1/2] Added support for visionOS using platform macro detection The scale using traitCollection.displayScale This only change source code --- SDWebImage/Core/SDAnimatedImage.m | 6 ++++++ SDWebImage/Core/SDGraphicsImageRenderer.m | 16 ++++++++++++---- SDWebImage/Core/SDImageCacheDefine.m | 2 +- SDWebImage/Core/SDWebImageCompat.h | 6 ++++++ SDWebImage/Core/SDWebImageDefine.m | 15 +-------------- SDWebImage/Core/SDWebImageDownloader.m | 5 +++-- SDWebImage/Core/SDWebImageIndicator.h | 2 ++ SDWebImage/Core/SDWebImageIndicator.m | 22 +++++++++++++++++++--- SDWebImage/Private/SDImageAssetManager.m | 4 +++- 9 files changed, 53 insertions(+), 25 deletions(-) diff --git a/SDWebImage/Core/SDAnimatedImage.m b/SDWebImage/Core/SDAnimatedImage.m index bf0105f7..f1f0ce15 100644 --- a/SDWebImage/Core/SDAnimatedImage.m +++ b/SDWebImage/Core/SDAnimatedImage.m @@ -54,9 +54,15 @@ static CGFloat SDImageScaleFromPath(NSString *string) { #if __has_include() + (instancetype)imageNamed:(NSString *)name inBundle:(NSBundle *)bundle compatibleWithTraitCollection:(UITraitCollection *)traitCollection { +#if SD_VISION + if (!traitCollection) { + traitCollection = UITraitCollection.currentTraitCollection; + } +#else if (!traitCollection) { traitCollection = UIScreen.mainScreen.traitCollection; } +#endif CGFloat scale = traitCollection.displayScale; return [self imageNamed:name inBundle:bundle scale:scale]; } diff --git a/SDWebImage/Core/SDGraphicsImageRenderer.m b/SDWebImage/Core/SDGraphicsImageRenderer.m index aeda97b1..b85b888e 100644 --- a/SDWebImage/Core/SDGraphicsImageRenderer.m +++ b/SDWebImage/Core/SDGraphicsImageRenderer.m @@ -72,7 +72,9 @@ #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wdeprecated-declarations" - (SDGraphicsImageRendererFormatRange)preferredRange { -#if SD_UIKIT +#if SD_VISION + return (SDGraphicsImageRendererFormatRange)self.uiformat.preferredRange; +#elif SD_UIKIT if (@available(iOS 10.0, tvOS 10.10, *)) { if (@available(iOS 12.0, tvOS 12.0, *)) { return (SDGraphicsImageRendererFormatRange)self.uiformat.preferredRange; @@ -93,7 +95,9 @@ } - (void)setPreferredRange:(SDGraphicsImageRendererFormatRange)preferredRange { -#if SD_UIKIT +#if SD_VISION + self.uiformat.preferredRange = (UIGraphicsImageRendererFormatRange)preferredRange; +#elif SD_UIKIT if (@available(iOS 10.0, tvOS 10.10, *)) { if (@available(iOS 12.0, tvOS 12.0, *)) { self.uiformat.preferredRange = (UIGraphicsImageRendererFormatRange)preferredRange; @@ -127,7 +131,9 @@ self.uiformat = uiformat; } else { #endif -#if SD_WATCH +#if SD_VISION + CGFloat screenScale = UITraitCollection.currentTraitCollection.displayScale; +#elif SD_WATCH CGFloat screenScale = [WKInterfaceDevice currentDevice].screenScale; #elif SD_UIKIT CGFloat screenScale = [UIScreen mainScreen].scale; @@ -167,7 +173,9 @@ self.uiformat = uiformat; } else { #endif -#if SD_WATCH +#if SD_VISION + CGFloat screenScale = UITraitCollection.currentTraitCollection.displayScale; +#elif SD_WATCH CGFloat screenScale = [WKInterfaceDevice currentDevice].screenScale; #elif SD_UIKIT CGFloat screenScale = [UIScreen mainScreen].scale; diff --git a/SDWebImage/Core/SDImageCacheDefine.m b/SDWebImage/Core/SDImageCacheDefine.m index 56081e89..741d57cd 100644 --- a/SDWebImage/Core/SDImageCacheDefine.m +++ b/SDWebImage/Core/SDImageCacheDefine.m @@ -23,7 +23,7 @@ SDImageCoderOptions * _Nonnull SDGetDecodeOptionsFromContext(SDWebImageContext * NSValue *thumbnailSizeValue; BOOL shouldScaleDown = SD_OPTIONS_CONTAINS(options, SDWebImageScaleDownLargeImages); NSNumber *scaleDownLimitBytesValue = context[SDWebImageContextImageScaleDownLimitBytes]; - if (!scaleDownLimitBytesValue && shouldScaleDown) { + if (scaleDownLimitBytesValue == nil && shouldScaleDown) { // Use the default limit bytes scaleDownLimitBytesValue = @(SDImageCoderHelper.defaultScaleDownLimitBytes); } diff --git a/SDWebImage/Core/SDWebImageCompat.h b/SDWebImage/Core/SDWebImageCompat.h index f47a248a..f859d792 100644 --- a/SDWebImage/Core/SDWebImageCompat.h +++ b/SDWebImage/Core/SDWebImageCompat.h @@ -47,6 +47,12 @@ #define SD_WATCH 0 #endif +// Supports Xcode 14 to suppress warning +#ifdef TARGET_OS_VISION +#if TARGET_OS_VISION + #define SD_VISION 1 +#endif +#endif #if SD_MAC #import diff --git a/SDWebImage/Core/SDWebImageDefine.m b/SDWebImage/Core/SDWebImageDefine.m index e247429f..7d6e391a 100644 --- a/SDWebImage/Core/SDWebImageDefine.m +++ b/SDWebImage/Core/SDWebImageDefine.m @@ -23,20 +23,7 @@ inline CGFloat SDImageScaleFactorForKey(NSString * _Nullable key) { if (!key) { return scale; } - // Check if target OS support scale -#if SD_WATCH - if ([[WKInterfaceDevice currentDevice] respondsToSelector:@selector(screenScale)]) -#elif SD_UIKIT - if ([[UIScreen mainScreen] respondsToSelector:@selector(scale)]) -#elif SD_MAC - NSScreen *mainScreen = nil; - if (@available(macOS 10.12, *)) { - mainScreen = [NSScreen mainScreen]; - } else { - mainScreen = [NSScreen screens].firstObject; - } - if ([mainScreen respondsToSelector:@selector(backingScaleFactor)]) -#endif + // Now all OS supports retina display scale system { // a@2x.png -> 8 if (key.length >= 8) { diff --git a/SDWebImage/Core/SDWebImageDownloader.m b/SDWebImage/Core/SDWebImageDownloader.m index 628057fc..33bb937f 100644 --- a/SDWebImage/Core/SDWebImageDownloader.m +++ b/SDWebImage/Core/SDWebImageDownloader.m @@ -104,11 +104,12 @@ static void * SDWebImageDownloaderContext = &SDWebImageDownloaderContext; _URLOperations = [NSMutableDictionary new]; NSMutableDictionary *headerDictionary = [NSMutableDictionary dictionary]; NSString *userAgent = nil; -#if SD_UIKIT // User-Agent Header; see http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.43 +#if SD_VISION + userAgent = [NSString stringWithFormat:@"%@/%@ (%@; visionOS %@; Scale/%0.2f)", [[NSBundle mainBundle] infoDictionary][(__bridge NSString *)kCFBundleExecutableKey] ?: [[NSBundle mainBundle] infoDictionary][(__bridge NSString *)kCFBundleIdentifierKey], [[NSBundle mainBundle] infoDictionary][@"CFBundleShortVersionString"] ?: [[NSBundle mainBundle] infoDictionary][(__bridge NSString *)kCFBundleVersionKey], [[UIDevice currentDevice] model], [[UIDevice currentDevice] systemVersion], UITraitCollection.currentTraitCollection.displayScale]; +#elif SD_UIKIT userAgent = [NSString stringWithFormat:@"%@/%@ (%@; iOS %@; Scale/%0.2f)", [[NSBundle mainBundle] infoDictionary][(__bridge NSString *)kCFBundleExecutableKey] ?: [[NSBundle mainBundle] infoDictionary][(__bridge NSString *)kCFBundleIdentifierKey], [[NSBundle mainBundle] infoDictionary][@"CFBundleShortVersionString"] ?: [[NSBundle mainBundle] infoDictionary][(__bridge NSString *)kCFBundleVersionKey], [[UIDevice currentDevice] model], [[UIDevice currentDevice] systemVersion], [[UIScreen mainScreen] scale]]; #elif SD_WATCH - // User-Agent Header; see http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.43 userAgent = [NSString stringWithFormat:@"%@/%@ (%@; watchOS %@; Scale/%0.2f)", [[NSBundle mainBundle] infoDictionary][(__bridge NSString *)kCFBundleExecutableKey] ?: [[NSBundle mainBundle] infoDictionary][(__bridge NSString *)kCFBundleIdentifierKey], [[NSBundle mainBundle] infoDictionary][@"CFBundleShortVersionString"] ?: [[NSBundle mainBundle] infoDictionary][(__bridge NSString *)kCFBundleVersionKey], [[WKInterfaceDevice currentDevice] model], [[WKInterfaceDevice currentDevice] systemVersion], [[WKInterfaceDevice currentDevice] screenScale]]; #elif SD_MAC userAgent = [NSString stringWithFormat:@"%@/%@ (Mac OS X %@)", [[NSBundle mainBundle] infoDictionary][(__bridge NSString *)kCFBundleExecutableKey] ?: [[NSBundle mainBundle] infoDictionary][(__bridge NSString *)kCFBundleIdentifierKey], [[NSBundle mainBundle] infoDictionary][@"CFBundleShortVersionString"] ?: [[NSBundle mainBundle] infoDictionary][(__bridge NSString *)kCFBundleVersionKey], [[NSProcessInfo processInfo] operatingSystemVersionString]]; diff --git a/SDWebImage/Core/SDWebImageIndicator.h b/SDWebImage/Core/SDWebImageIndicator.h index e1165c12..6a5fc54e 100644 --- a/SDWebImage/Core/SDWebImageIndicator.h +++ b/SDWebImage/Core/SDWebImageIndicator.h @@ -66,6 +66,7 @@ */ @interface SDWebImageActivityIndicator (Conveniences) +#if !SD_VISION /// These indicator use the fixed color without dark mode support /// gray-style activity indicator @property (nonatomic, class, nonnull, readonly) SDWebImageActivityIndicator *grayIndicator; @@ -75,6 +76,7 @@ @property (nonatomic, class, nonnull, readonly) SDWebImageActivityIndicator *whiteIndicator; /// large white-style activity indicator @property (nonatomic, class, nonnull, readonly) SDWebImageActivityIndicator *whiteLargeIndicator; +#endif /// These indicator use the system style, supports dark mode if available (iOS 13+/macOS 10.14+) /// large activity indicator @property (nonatomic, class, nonnull, readonly) SDWebImageActivityIndicator *largeIndicator; diff --git a/SDWebImage/Core/SDWebImageIndicator.m b/SDWebImage/Core/SDWebImageIndicator.m index b45a08a4..d673d8df 100644 --- a/SDWebImage/Core/SDWebImageIndicator.m +++ b/SDWebImage/Core/SDWebImageIndicator.m @@ -41,7 +41,17 @@ #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wdeprecated-declarations" - (void)commonInit { - self.indicatorView = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleWhite]; +#if SD_VISION + UIActivityIndicatorViewStyle style = UIActivityIndicatorViewStyleMedium; +#else + UIActivityIndicatorViewStyle style; + if (@available(iOS 13.0, tvOS 13.0, *)) { + style = UIActivityIndicatorViewStyleMedium; + } else { + style = UIActivityIndicatorViewStyleWhite; + } +#endif + self.indicatorView = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:style]; self.indicatorView.autoresizingMask = UIViewAutoresizingFlexibleTopMargin | UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleRightMargin | UIViewAutoresizingFlexibleBottomMargin; } #pragma clang diagnostic pop @@ -79,6 +89,7 @@ @implementation SDWebImageActivityIndicator (Conveniences) +#if !SD_VISION #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wdeprecated-declarations" + (SDWebImageActivityIndicator *)grayIndicator { @@ -134,10 +145,13 @@ #endif return indicator; } +#endif + (SDWebImageActivityIndicator *)largeIndicator { SDWebImageActivityIndicator *indicator = [SDWebImageActivityIndicator new]; -#if SD_UIKIT +#if SD_VISION + indicator.indicatorView.activityIndicatorViewStyle = UIActivityIndicatorViewStyleLarge; +#elif SD_UIKIT if (@available(iOS 13.0, tvOS 13.0, *)) { indicator.indicatorView.activityIndicatorViewStyle = UIActivityIndicatorViewStyleLarge; } else { @@ -152,7 +166,9 @@ + (SDWebImageActivityIndicator *)mediumIndicator { SDWebImageActivityIndicator *indicator = [SDWebImageActivityIndicator new]; -#if SD_UIKIT +#if SD_VISION + indicator.indicatorView.activityIndicatorViewStyle = UIActivityIndicatorViewStyleMedium; +#elif SD_UIKIT if (@available(iOS 13.0, tvOS 13.0, *)) { indicator.indicatorView.activityIndicatorViewStyle = UIActivityIndicatorViewStyleMedium; } else { diff --git a/SDWebImage/Private/SDImageAssetManager.m b/SDWebImage/Private/SDImageAssetManager.m index 13988975..269f6302 100644 --- a/SDWebImage/Private/SDImageAssetManager.m +++ b/SDWebImage/Private/SDImageAssetManager.m @@ -13,7 +13,9 @@ static NSArray *SDBundlePreferredScales(void) { static NSArray *scales; static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ -#if SD_WATCH +#if SD_VISION + CGFloat screenScale = UITraitCollection.currentTraitCollection.displayScale; +#elif SD_WATCH CGFloat screenScale = [WKInterfaceDevice currentDevice].screenScale; #elif SD_UIKIT CGFloat screenScale = [UIScreen mainScreen].scale; From 8000e239d27f556dfa98b900386af85e9bd35b8b Mon Sep 17 00:00:00 2001 From: DreamPiggy Date: Sat, 2 Sep 2023 20:11:45 +0800 Subject: [PATCH 2/2] Update readme and at least the xcconfig for visionOS --- Configs/Module-Shared.xcconfig | 7 +++++-- README.md | 8 ++++++++ 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/Configs/Module-Shared.xcconfig b/Configs/Module-Shared.xcconfig index 1b35da47..2d9dfdce 100644 --- a/Configs/Module-Shared.xcconfig +++ b/Configs/Module-Shared.xcconfig @@ -210,10 +210,10 @@ SDKROOT = macosx SKIP_INSTALL = YES // The list of supported platforms from which a base SDK can be used. This setting is used if the product can be built for multiple platforms using different SDKs. -SUPPORTED_PLATFORMS = macosx iphoneos iphonesimulator watchsimulator watchos appletvsimulator appletvos +SUPPORTED_PLATFORMS = macosx iphoneos iphonesimulator watchsimulator watchos appletvsimulator appletvos xrsimulator xros // The build system uses the selected device to set the correct value for the `UIDeviceFamily` key it adds to the target's `Info.plist` file. This also drives the --target-device flag to actool, which determines the idioms selected during catalog compilation for iOS platforms. -TARGETED_DEVICE_FAMILY = 1,2,3,4 +TARGETED_DEVICE_FAMILY = 1,2,3,4,5,6,7 // Code will load on this and later versions of tvOS. Framework APIs that are unavailable in earlier versions will be weak-linked; your code should check for null function pointers or specific system versions before calling newer APIs. TVOS_DEPLOYMENT_TARGET = 9.0 @@ -224,6 +224,9 @@ VERSIONING_SYSTEM = apple-generic // Code will load on this and later versions of watchOS. Framework APIs that are unavailable in earlier versions will be weak-linked; your code should check for null function pointers or specific system versions before calling newer APIs. WATCHOS_DEPLOYMENT_TARGET = 2.0 +// Code will load on this and later versions of visionOS. Framework APIs that are unavailable in earlier versions will be weak-linked; your code should check for null function pointers or specific system versions before calling newer APIs. +XROS_DEPLOYMENT_TARGET = 1.0 + // macOS Catalyst support SUPPORTS_MACCATALYST = YES diff --git a/README.md b/README.md index 784ab87a..bf76153c 100644 --- a/README.md +++ b/README.md @@ -37,6 +37,14 @@ Note: `SD` is the prefix for **Simple Design** (which is the team name in Daily - [x] Modern Objective-C and better Swift support - [x] Performances! +## For Apple visionOS + +From 5.18.0, SDWebImage can be compiled for visionOS platform. However, it's still in beta and may contains issues unlike the stable iOS UIKit support. Welcome to have a try and [report issue](https://github.com/SDWebImage/SDWebImage/issues). + +To build on visionOS, currently we only support the standard Xcode integration. Which means, open that `SDWebImage.xcodeproj` (Xcode 15+), then choose the target to build as library, framework or XCFramework (supports static and dynamic), and integrate to your visionOS App. + +Once the visionOS toolchain is stable, we will add the package manager support later (include CocoaPods and SwiftPM). + ## Supported Image Formats - Image formats supported by Apple system (JPEG, PNG, TIFF, BMP, ...), including [GIF](https://github.com/SDWebImage/SDWebImage/wiki/Advanced-Usage#gif-coder)/[APNG](https://github.com/SDWebImage/SDWebImage/wiki/Advanced-Usage#apng-coder) animated image