Merge pull request #227 from SDWebImage/refactor_xcode14_state_update

Refactor WebImage/AnimatedImage using SwiftUIBackports and StateObject
This commit is contained in:
DreamPiggy 2022-09-15 21:08:01 +08:00 committed by GitHub
commit 3258812caa
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
29 changed files with 1657 additions and 898 deletions

187
.github/workflows/CI.yml vendored Normal file
View File

@ -0,0 +1,187 @@
name: "SDWebImageSwiftUI CI"
on:
push:
branches:
- master
pull_request:
branches:
- '*'
permissions:
contents: read
jobs:
Pods:
name: Cocoapods Lint
runs-on: macos-11
env:
DEVELOPER_DIR: /Applications/Xcode_13.2.1.app
steps:
- name: Checkout
uses: actions/checkout@v2
- name: Install Cocoapods
run: gem install cocoapods --no-document --quiet
- name: Install Xcpretty
run: gem install xcpretty --no-document --quiet
- name: Run SDWebImageSwiftUI podspec lint
run: |
set -o pipefail
pod lib lint SDWebImageSwiftUI.podspec --allow-warnings --skip-tests
Demo:
name: Run Demo
runs-on: macos-11
env:
DEVELOPER_DIR: /Applications/Xcode_13.2.1.app
WORKSPACE_NAME: SDWebImageSwiftUI.xcworkspace
OSXSCHEME: SDWebImageSwiftUIDemo-macOS
iOSSCHEME: SDWebImageSwiftUIDemo
TVSCHEME: SDWebImageSwiftUIDemo-tvOS
WATCHSCHEME: SDWebImageSwiftUIDemo-watchOS WatchKit App
strategy:
matrix:
iosDestination: ["name=iPhone 13 Pro"]
tvOSDestination: ["name=Apple TV 4K"]
watchOSDestination: ["platform=watchOS Simulator,name=Apple Watch Series 7 - 45mm"]
macOSDestination: ["platform=macOS"]
macCatalystDestination: ["platform=macOS,arch=x86_64,variant=Mac Catalyst"]
steps:
- name: Checkout
uses: actions/checkout@v2
- name: Clean DerivedData
run: |
rm -rf ~/Library/Developer/Xcode/DerivedData/
mkdir DerivedData
- name: Install Cocoapods
run: gem install cocoapods --no-document --quiet
- name: Install Xcpretty
run: gem install xcpretty --no-document --quiet
- name: Pod Update
run: pod repo update --silent
- name: Pod Install
run: pod install
- name: Run demo for OSX
run: |
set -o pipefail
xcodebuild build -workspace "${{ env.WORKSPACE_NAME }}" -scheme "${{ env.OSXSCHEME }}" -destination "${{ matrix.macOSDestination }}" -configuration Debug CODE_SIGNING_ALLOWED=NO | xcpretty -c
- name: Run demo for iOS
run: |
set -o pipefail
xcodebuild build -workspace "${{ env.WORKSPACE_NAME }}" -scheme "${{ env.iOSSCHEME }}" -destination "${{ matrix.iosDestination }}" -configuration Debug CODE_SIGNING_ALLOWED=NO | xcpretty -c
- name: Run demo for TV
run: |
set -o pipefail
xcodebuild build -workspace "${{ env.WORKSPACE_NAME }}" -scheme "${{ env.TVSCHEME }}" -destination "${{ matrix.tvOSDestination }}" -configuration Debug CODE_SIGNING_ALLOWED=NO | xcpretty -c
- name: Run demo for Watch
run: |
set -o pipefail
xcodebuild build -workspace "${{ env.WORKSPACE_NAME }}" -scheme "${{ env.WATCHSCHEME }}" -destination "${{ matrix.watchOSDestination }}" -configuration Debug CODE_SIGNING_ALLOWED=NO | xcpretty -c
Test:
name: Unit Test
runs-on: macos-11
env:
DEVELOPER_DIR: /Applications/Xcode_13.2.1.app
WORKSPACE_NAME: SDWebImageSwiftUI.xcworkspace
OSXSCHEME: SDWebImageSwiftUITests macOS
iOSSCHEME: SDWebImageSwiftUITests
TVSCHEME: SDWebImageSwiftUITests tvOS
strategy:
matrix:
iosDestination: ["platform=iOS Simulator,name=iPhone 13 Pro"]
macOSDestination: ["platform=macOS,arch=x86_64"]
tvOSDestination: ["platform=tvOS Simulator,name=Apple TV 4K"]
steps:
- name: Checkout
uses: actions/checkout@v2
- name: Clean DerivedData
run: |
rm -rf ~/Library/Developer/Xcode/DerivedData/
mkdir DerivedData
- name: Install Cocoapods
run: gem install cocoapods --no-document --quiet
- name: Install Xcpretty
run: gem install xcpretty --no-document --quiet
- name: Pod Update
run: pod repo update --silent
- name: Pod Install
run: pod install
- name: Test - ${{ matrix.iosDestination }}
run: |
set -o pipefail
xcodebuild test -workspace "${{ env.WORKSPACE_NAME }}" -scheme "${{ env.iOSSCHEME }}" -destination "${{ matrix.iosDestination }}" -configuration Debug CODE_SIGNING_ALLOWED=NO | xcpretty -c
mv ~/Library/Developer/Xcode/DerivedData/ ./DerivedData/iOS
- name: Test - ${{ matrix.macOSDestination }}
run: |
set -o pipefail
xcodebuild test -workspace "${{ env.WORKSPACE_NAME }}" -scheme "${{ env.OSXSCHEME }}" -destination "${{ matrix.macOSDestination }}" -configuration Debug CODE_SIGNING_ALLOWED=NO | xcpretty -c
mv ~/Library/Developer/Xcode/DerivedData/ ./DerivedData/macOS
- name: Test - ${{ matrix.tvOSDestination }}
run: |
set -o pipefail
xcodebuild test -workspace "${{ env.WORKSPACE_NAME }}" -scheme "${{ env.TVSCHEME }}" -destination "${{ matrix.tvOSDestination }}" -configuration Debug CODE_SIGNING_ALLOWED=NO | xcpretty -c
mv ~/Library/Developer/Xcode/DerivedData/ ./DerivedData/tvOS
- name: Code Coverage
run: |
set -o pipefail
export PATH="/usr/local/opt/curl/bin:$PATH"
curl --version
bash <(curl -s https://codecov.io/bash) -D './DerivedData/macOS' -J '^SDWebImageSwiftUI$' -c -X gcov -F macos
bash <(curl -s https://codecov.io/bash) -D './DerivedData/iOS' -J '^SDWebImageSwiftUI$' -c -X gcov -F ios
bash <(curl -s https://codecov.io/bash) -D './DerivedData/tvOS' -J '^SDWebImageSwiftUI$' -c -X gcov -F tvos
Build:
name: Build Library
runs-on: macos-11
env:
DEVELOPER_DIR: /Applications/Xcode_13.2.1.app
PROJECT_NAME: SDWebImageSwiftUI.xcodeproj
OSXSCHEME: SDWebImageSwiftUI macOS
iOSSCHEME: SDWebImageSwiftUI
TVSCHEME: SDWebImageSwiftUI tvOS
WATCHSCHEME: SDWebImageSwiftUI watchOS
steps:
- name: Checkout
uses: actions/checkout@v2
- name: Build the SwiftPM
run: |
set -o pipefail
swift build
rm -rf ~/.build
- name: Install Carthage
run: brew install carthage
- name: Carthage Update
run: ./carthage.sh update --platform "iOS, tvOS, macOS, watchOS"
- name: Build as dynamic frameworks
run: |
set -o pipefail
xcodebuild build -project "${{ env.PROJECT_NAME }}" -scheme "${{ env.OSXSCHEME }}" -sdk macosx -configuration Release | xcpretty -c
xcodebuild build -project "${{ env.PROJECT_NAME }}" -scheme "${{ env.iOSSCHEME }}" -sdk iphoneos -configuration Release | xcpretty -c
xcodebuild build -project "${{ env.PROJECT_NAME }}" -scheme "${{ env.TVSCHEME }}" -sdk appletvos -configuration Release | xcpretty -c
xcodebuild build -project "${{ env.PROJECT_NAME }}" -scheme "${{ env.WATCHSCHEME }}" -sdk watchos -configuration Release | xcpretty -c

1
.gitignore vendored
View File

@ -41,3 +41,4 @@ Podfile.lock
# SwiftPM
.build
.swiftpm
Package.resolved

View File

@ -1,28 +0,0 @@
use_frameworks!
def all_pods
pod 'SDWebImageSwiftUI', :path => '../'
pod 'SDWebImageWebPCoder'
pod 'SDWebImageSVGCoder'
pod 'SDWebImagePDFCoder'
end
target 'SDWebImageSwiftUIDemo' do
platform :ios, '13.0'
all_pods
end
target 'SDWebImageSwiftUIDemo-macOS' do
platform :osx, '10.15'
all_pods
end
target 'SDWebImageSwiftUIDemo-tvOS' do
platform :tvos, '13.0'
all_pods
end
target 'SDWebImageSwiftUIDemo-watchOS WatchKit Extension' do
platform :watchos, '7.0'
all_pods
end

View File

@ -3,18 +3,38 @@
archiveVersion = 1;
classes = {
};
objectVersion = 46;
objectVersion = 52;
objects = {
/* Begin PBXBuildFile section */
1794840F9DF6D50ADA448C9B /* Pods_SDWebImageSwiftUIDemo_macOS.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 473D7886C23B6FC5AFE35842 /* Pods_SDWebImageSwiftUIDemo_macOS.framework */; };
2E3D81A12C757E01A3C420F2 /* Pods_SDWebImageSwiftUITests_tvOS.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 83FA763A8587C065798A274B /* Pods_SDWebImageSwiftUITests_tvOS.framework */; };
320CDC2C22FADB44007CF858 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 320CDC2B22FADB44007CF858 /* AppDelegate.swift */; };
320CDC2E22FADB44007CF858 /* SceneDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 320CDC2D22FADB44007CF858 /* SceneDelegate.swift */; };
320CDC3022FADB44007CF858 /* ContentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 320CDC2F22FADB44007CF858 /* ContentView.swift */; };
320CDC3222FADB45007CF858 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 320CDC3122FADB45007CF858 /* Assets.xcassets */; };
320CDC3522FADB45007CF858 /* Preview Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 320CDC3422FADB45007CF858 /* Preview Assets.xcassets */; };
320CDC3822FADB45007CF858 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 320CDC3622FADB45007CF858 /* LaunchScreen.storyboard */; };
322E0DF728D331A20003A55F /* IndicatorTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 322E0DF028D331A20003A55F /* IndicatorTests.swift */; };
322E0DF828D331A20003A55F /* WebImageTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 322E0DF128D331A20003A55F /* WebImageTests.swift */; };
322E0DF928D331A20003A55F /* Images.bundle in Resources */ = {isa = PBXBuildFile; fileRef = 322E0DF228D331A20003A55F /* Images.bundle */; };
322E0DFA28D331A20003A55F /* ImageManagerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 322E0DF328D331A20003A55F /* ImageManagerTests.swift */; };
322E0DFB28D331A20003A55F /* AnimatedImageTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 322E0DF428D331A20003A55F /* AnimatedImageTests.swift */; };
322E0DFD28D331A20003A55F /* TestUtils.swift in Sources */ = {isa = PBXBuildFile; fileRef = 322E0DF628D331A20003A55F /* TestUtils.swift */; };
322E0E1828D3320D0003A55F /* ImageManagerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 322E0DF328D331A20003A55F /* ImageManagerTests.swift */; };
322E0E1928D3320D0003A55F /* IndicatorTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 322E0DF028D331A20003A55F /* IndicatorTests.swift */; };
322E0E1A28D3320D0003A55F /* WebImageTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 322E0DF128D331A20003A55F /* WebImageTests.swift */; };
322E0E1B28D3320D0003A55F /* AnimatedImageTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 322E0DF428D331A20003A55F /* AnimatedImageTests.swift */; };
322E0E1C28D3320D0003A55F /* TestUtils.swift in Sources */ = {isa = PBXBuildFile; fileRef = 322E0DF628D331A20003A55F /* TestUtils.swift */; };
322E0E1D28D3320D0003A55F /* ImageManagerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 322E0DF328D331A20003A55F /* ImageManagerTests.swift */; };
322E0E1E28D3320D0003A55F /* IndicatorTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 322E0DF028D331A20003A55F /* IndicatorTests.swift */; };
322E0E1F28D3320D0003A55F /* WebImageTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 322E0DF128D331A20003A55F /* WebImageTests.swift */; };
322E0E2028D3320D0003A55F /* AnimatedImageTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 322E0DF428D331A20003A55F /* AnimatedImageTests.swift */; };
322E0E2128D3320D0003A55F /* TestUtils.swift in Sources */ = {isa = PBXBuildFile; fileRef = 322E0DF628D331A20003A55F /* TestUtils.swift */; };
322E0E2228D332130003A55F /* Images.bundle in Resources */ = {isa = PBXBuildFile; fileRef = 322E0DF228D331A20003A55F /* Images.bundle */; };
322E0E2328D332130003A55F /* Images.bundle in Resources */ = {isa = PBXBuildFile; fileRef = 322E0DF228D331A20003A55F /* Images.bundle */; };
326B0D712345C01900D28269 /* DetailView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 326B0D702345C01900D28269 /* DetailView.swift */; };
32DCFE9528D333E8001A17BF /* ViewInspector in Frameworks */ = {isa = PBXBuildFile; productRef = 32DCFE9428D333E8001A17BF /* ViewInspector */; };
32E5290C2348A0C700EA46FF /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 32E5290B2348A0C700EA46FF /* AppDelegate.swift */; };
32E529102348A0C900EA46FF /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 32E5290F2348A0C900EA46FF /* Assets.xcassets */; };
32E529132348A0C900EA46FF /* Preview Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 32E529122348A0C900EA46FF /* Preview Assets.xcassets */; };
@ -38,11 +58,34 @@
32E529682348A10C00EA46FF /* ContentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 320CDC2F22FADB44007CF858 /* ContentView.swift */; };
32E529692348A10C00EA46FF /* DetailView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 326B0D702345C01900D28269 /* DetailView.swift */; };
68543C9252A5BD46E9573195 /* Pods_SDWebImageSwiftUIDemo_tvOS.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 79C3538209F8065DCCFBE205 /* Pods_SDWebImageSwiftUIDemo_tvOS.framework */; };
833A61715BAAB31702D867CC /* Pods_SDWebImageSwiftUITests_macOS.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = C1A272DB5547C37A41C1238E /* Pods_SDWebImageSwiftUITests_macOS.framework */; };
8E29022B4DCBF0EFF9CF82F9 /* Pods_SDWebImageSwiftUIDemo_watchOS_WatchKit_Extension.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E25DB0256669F3B7EE7C566D /* Pods_SDWebImageSwiftUIDemo_watchOS_WatchKit_Extension.framework */; };
9E3892775FC4E348DFA66FCA /* Pods_SDWebImageSwiftUITests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 2FEDED19F84B1D678B12077A /* Pods_SDWebImageSwiftUITests.framework */; };
E61581A5A1063B0E6795157D /* Pods_SDWebImageSwiftUIDemo.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F0FCDD95C695D2F914DC9B3B /* Pods_SDWebImageSwiftUIDemo.framework */; };
/* End PBXBuildFile section */
/* Begin PBXContainerItemProxy section */
322E0DEA28D3318B0003A55F /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 607FACC81AFB9204008FA782 /* Project object */;
proxyType = 1;
remoteGlobalIDString = 320CDC2822FADB44007CF858;
remoteInfo = SDWebImageSwiftUIDemo;
};
322E0E0628D331F00003A55F /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 607FACC81AFB9204008FA782 /* Project object */;
proxyType = 1;
remoteGlobalIDString = 32E529082348A0C700EA46FF;
remoteInfo = "SDWebImageSwiftUIDemo-macOS";
};
322E0E1328D332050003A55F /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 607FACC81AFB9204008FA782 /* Project object */;
proxyType = 1;
remoteGlobalIDString = 32E5291F2348A0D300EA46FF;
remoteInfo = "SDWebImageSwiftUIDemo-tvOS";
};
32E529392348A0DD00EA46FF /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 607FACC81AFB9204008FA782 /* Project object */;
@ -85,7 +128,9 @@
/* End PBXCopyFilesBuildPhase section */
/* Begin PBXFileReference section */
0EEE88A04A9B191BD966EFC2 /* Pods-SDWebImageSwiftUITests macOS.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-SDWebImageSwiftUITests macOS.release.xcconfig"; path = "../../Pods/Target Support Files/Pods-SDWebImageSwiftUITests macOS/Pods-SDWebImageSwiftUITests macOS.release.xcconfig"; sourceTree = "<group>"; };
28546D27CDA9666E64C183FD /* SDWebImageSwiftUI.podspec */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text; name = SDWebImageSwiftUI.podspec; path = ../SDWebImageSwiftUI.podspec; sourceTree = "<group>"; xcLanguageSpecificationIdentifier = xcode.lang.ruby; };
2FEDED19F84B1D678B12077A /* Pods_SDWebImageSwiftUITests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_SDWebImageSwiftUITests.framework; sourceTree = BUILT_PRODUCTS_DIR; };
320CDC2922FADB44007CF858 /* SDWebImageSwiftUIDemo.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = SDWebImageSwiftUIDemo.app; sourceTree = BUILT_PRODUCTS_DIR; };
320CDC2B22FADB44007CF858 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
320CDC2D22FADB44007CF858 /* SceneDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SceneDelegate.swift; sourceTree = "<group>"; };
@ -94,6 +139,16 @@
320CDC3422FADB45007CF858 /* Preview Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = "Preview Assets.xcassets"; sourceTree = "<group>"; };
320CDC3722FADB45007CF858 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = "<group>"; };
320CDC3922FADB45007CF858 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
322E0DE628D3318B0003A55F /* SDWebImageSwiftUITests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = SDWebImageSwiftUITests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
322E0DF028D331A20003A55F /* IndicatorTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = IndicatorTests.swift; sourceTree = "<group>"; };
322E0DF128D331A20003A55F /* WebImageTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = WebImageTests.swift; sourceTree = "<group>"; };
322E0DF228D331A20003A55F /* Images.bundle */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.plug-in"; path = Images.bundle; sourceTree = "<group>"; };
322E0DF328D331A20003A55F /* ImageManagerTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ImageManagerTests.swift; sourceTree = "<group>"; };
322E0DF428D331A20003A55F /* AnimatedImageTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AnimatedImageTests.swift; sourceTree = "<group>"; };
322E0DF528D331A20003A55F /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
322E0DF628D331A20003A55F /* TestUtils.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TestUtils.swift; sourceTree = "<group>"; };
322E0E0228D331F00003A55F /* SDWebImageSwiftUITests macOS.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "SDWebImageSwiftUITests macOS.xctest"; sourceTree = BUILT_PRODUCTS_DIR; };
322E0E0F28D332050003A55F /* SDWebImageSwiftUITests tvOS.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "SDWebImageSwiftUITests tvOS.xctest"; sourceTree = BUILT_PRODUCTS_DIR; };
326B0D702345C01900D28269 /* DetailView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DetailView.swift; sourceTree = "<group>"; };
32E529092348A0C700EA46FF /* SDWebImageSwiftUIDemo-macOS.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "SDWebImageSwiftUIDemo-macOS.app"; sourceTree = BUILT_PRODUCTS_DIR; };
32E5290B2348A0C700EA46FF /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
@ -121,18 +176,25 @@
32E529562348A0DF00EA46FF /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
3E9F8B5F06960FFFBD1A5F99 /* README.md */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = net.daringfireball.markdown; name = README.md; path = ../README.md; sourceTree = "<group>"; };
473D7886C23B6FC5AFE35842 /* Pods_SDWebImageSwiftUIDemo_macOS.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_SDWebImageSwiftUIDemo_macOS.framework; sourceTree = BUILT_PRODUCTS_DIR; };
487B2863C76EC4CE36CEC4EA /* Pods-SDWebImageSwiftUITests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-SDWebImageSwiftUITests.debug.xcconfig"; path = "../../Pods/Target Support Files/Pods-SDWebImageSwiftUITests/Pods-SDWebImageSwiftUITests.debug.xcconfig"; sourceTree = "<group>"; };
54859B427E0A79E823713963 /* LICENSE */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text; name = LICENSE; path = ../LICENSE; sourceTree = "<group>"; };
5864FFEDE62A0630EDF26A56 /* Pods-SDWebImageSwiftUIDemo.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-SDWebImageSwiftUIDemo.release.xcconfig"; path = "Target Support Files/Pods-SDWebImageSwiftUIDemo/Pods-SDWebImageSwiftUIDemo.release.xcconfig"; sourceTree = "<group>"; };
746AF60263F54FD7E16AA7D5 /* Pods-SDWebImageSwiftUIDemo-tvOS.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-SDWebImageSwiftUIDemo-tvOS.debug.xcconfig"; path = "Target Support Files/Pods-SDWebImageSwiftUIDemo-tvOS/Pods-SDWebImageSwiftUIDemo-tvOS.debug.xcconfig"; sourceTree = "<group>"; };
5864FFEDE62A0630EDF26A56 /* Pods-SDWebImageSwiftUIDemo.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-SDWebImageSwiftUIDemo.release.xcconfig"; path = "../../Pods/Target Support Files/Pods-SDWebImageSwiftUIDemo/Pods-SDWebImageSwiftUIDemo.release.xcconfig"; sourceTree = "<group>"; };
5ABE9344AF344CCC70056CD5 /* Pods-SDWebImageSwiftUITests tvOS.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-SDWebImageSwiftUITests tvOS.debug.xcconfig"; path = "../../Pods/Target Support Files/Pods-SDWebImageSwiftUITests tvOS/Pods-SDWebImageSwiftUITests tvOS.debug.xcconfig"; sourceTree = "<group>"; };
746AF60263F54FD7E16AA7D5 /* Pods-SDWebImageSwiftUIDemo-tvOS.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-SDWebImageSwiftUIDemo-tvOS.debug.xcconfig"; path = "../../Pods/Target Support Files/Pods-SDWebImageSwiftUIDemo-tvOS/Pods-SDWebImageSwiftUIDemo-tvOS.debug.xcconfig"; sourceTree = "<group>"; };
79C3538209F8065DCCFBE205 /* Pods_SDWebImageSwiftUIDemo_tvOS.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_SDWebImageSwiftUIDemo_tvOS.framework; sourceTree = BUILT_PRODUCTS_DIR; };
7B0D9182CAD02B73E6F208F3 /* Pods-SDWebImageSwiftUIDemo-watchOS WatchKit Extension.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-SDWebImageSwiftUIDemo-watchOS WatchKit Extension.release.xcconfig"; path = "Target Support Files/Pods-SDWebImageSwiftUIDemo-watchOS WatchKit Extension/Pods-SDWebImageSwiftUIDemo-watchOS WatchKit Extension.release.xcconfig"; sourceTree = "<group>"; };
89B11BBDBAA86F760DF1EE2D /* Pods-SDWebImageSwiftUIDemo-macOS.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-SDWebImageSwiftUIDemo-macOS.debug.xcconfig"; path = "Target Support Files/Pods-SDWebImageSwiftUIDemo-macOS/Pods-SDWebImageSwiftUIDemo-macOS.debug.xcconfig"; sourceTree = "<group>"; };
95C9E0D9CE4113E5A82480B9 /* Pods-SDWebImageSwiftUIDemo-tvOS.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-SDWebImageSwiftUIDemo-tvOS.release.xcconfig"; path = "Target Support Files/Pods-SDWebImageSwiftUIDemo-tvOS/Pods-SDWebImageSwiftUIDemo-tvOS.release.xcconfig"; sourceTree = "<group>"; };
A78BA7FB5AFF53CBDD4C4CBD /* Pods-SDWebImageSwiftUIDemo.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-SDWebImageSwiftUIDemo.debug.xcconfig"; path = "Target Support Files/Pods-SDWebImageSwiftUIDemo/Pods-SDWebImageSwiftUIDemo.debug.xcconfig"; sourceTree = "<group>"; };
7B0D9182CAD02B73E6F208F3 /* Pods-SDWebImageSwiftUIDemo-watchOS WatchKit Extension.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-SDWebImageSwiftUIDemo-watchOS WatchKit Extension.release.xcconfig"; path = "../../Pods/Target Support Files/Pods-SDWebImageSwiftUIDemo-watchOS WatchKit Extension/Pods-SDWebImageSwiftUIDemo-watchOS WatchKit Extension.release.xcconfig"; sourceTree = "<group>"; };
83FA763A8587C065798A274B /* Pods_SDWebImageSwiftUITests_tvOS.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_SDWebImageSwiftUITests_tvOS.framework; sourceTree = BUILT_PRODUCTS_DIR; };
89B11BBDBAA86F760DF1EE2D /* Pods-SDWebImageSwiftUIDemo-macOS.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-SDWebImageSwiftUIDemo-macOS.debug.xcconfig"; path = "../../Pods/Target Support Files/Pods-SDWebImageSwiftUIDemo-macOS/Pods-SDWebImageSwiftUIDemo-macOS.debug.xcconfig"; sourceTree = "<group>"; };
95C9E0D9CE4113E5A82480B9 /* Pods-SDWebImageSwiftUIDemo-tvOS.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-SDWebImageSwiftUIDemo-tvOS.release.xcconfig"; path = "../../Pods/Target Support Files/Pods-SDWebImageSwiftUIDemo-tvOS/Pods-SDWebImageSwiftUIDemo-tvOS.release.xcconfig"; sourceTree = "<group>"; };
A78BA7FB5AFF53CBDD4C4CBD /* Pods-SDWebImageSwiftUIDemo.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-SDWebImageSwiftUIDemo.debug.xcconfig"; path = "../../Pods/Target Support Files/Pods-SDWebImageSwiftUIDemo/Pods-SDWebImageSwiftUIDemo.debug.xcconfig"; sourceTree = "<group>"; };
A7CD2F7825F1936052B2C65E /* Pods-SDWebImageSwiftUITests macOS.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-SDWebImageSwiftUITests macOS.debug.xcconfig"; path = "../../Pods/Target Support Files/Pods-SDWebImageSwiftUITests macOS/Pods-SDWebImageSwiftUITests macOS.debug.xcconfig"; sourceTree = "<group>"; };
B6E12746E84E9ED7FA910A24 /* Pods-SDWebImageSwiftUITests tvOS.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-SDWebImageSwiftUITests tvOS.release.xcconfig"; path = "../../Pods/Target Support Files/Pods-SDWebImageSwiftUITests tvOS/Pods-SDWebImageSwiftUITests tvOS.release.xcconfig"; sourceTree = "<group>"; };
C1A272DB5547C37A41C1238E /* Pods_SDWebImageSwiftUITests_macOS.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_SDWebImageSwiftUITests_macOS.framework; sourceTree = BUILT_PRODUCTS_DIR; };
DDE527DE0EF6B6D9B7CD8C97 /* Pods-SDWebImageSwiftUITests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-SDWebImageSwiftUITests.release.xcconfig"; path = "../../Pods/Target Support Files/Pods-SDWebImageSwiftUITests/Pods-SDWebImageSwiftUITests.release.xcconfig"; sourceTree = "<group>"; };
E25DB0256669F3B7EE7C566D /* Pods_SDWebImageSwiftUIDemo_watchOS_WatchKit_Extension.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_SDWebImageSwiftUIDemo_watchOS_WatchKit_Extension.framework; sourceTree = BUILT_PRODUCTS_DIR; };
F0FCDD95C695D2F914DC9B3B /* Pods_SDWebImageSwiftUIDemo.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_SDWebImageSwiftUIDemo.framework; sourceTree = BUILT_PRODUCTS_DIR; };
F3AACDC116F5598BC39A8573 /* Pods-SDWebImageSwiftUIDemo-macOS.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-SDWebImageSwiftUIDemo-macOS.release.xcconfig"; path = "Target Support Files/Pods-SDWebImageSwiftUIDemo-macOS/Pods-SDWebImageSwiftUIDemo-macOS.release.xcconfig"; sourceTree = "<group>"; };
FEED4964309E241D2FD8A544 /* Pods-SDWebImageSwiftUIDemo-watchOS WatchKit Extension.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-SDWebImageSwiftUIDemo-watchOS WatchKit Extension.debug.xcconfig"; path = "Target Support Files/Pods-SDWebImageSwiftUIDemo-watchOS WatchKit Extension/Pods-SDWebImageSwiftUIDemo-watchOS WatchKit Extension.debug.xcconfig"; sourceTree = "<group>"; };
F3AACDC116F5598BC39A8573 /* Pods-SDWebImageSwiftUIDemo-macOS.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-SDWebImageSwiftUIDemo-macOS.release.xcconfig"; path = "../../Pods/Target Support Files/Pods-SDWebImageSwiftUIDemo-macOS/Pods-SDWebImageSwiftUIDemo-macOS.release.xcconfig"; sourceTree = "<group>"; };
FEED4964309E241D2FD8A544 /* Pods-SDWebImageSwiftUIDemo-watchOS WatchKit Extension.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-SDWebImageSwiftUIDemo-watchOS WatchKit Extension.debug.xcconfig"; path = "../../Pods/Target Support Files/Pods-SDWebImageSwiftUIDemo-watchOS WatchKit Extension/Pods-SDWebImageSwiftUIDemo-watchOS WatchKit Extension.debug.xcconfig"; sourceTree = "<group>"; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
@ -144,6 +206,31 @@
);
runOnlyForDeploymentPostprocessing = 0;
};
322E0DE328D3318B0003A55F /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
9E3892775FC4E348DFA66FCA /* Pods_SDWebImageSwiftUITests.framework in Frameworks */,
32DCFE9528D333E8001A17BF /* ViewInspector in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
322E0DFF28D331F00003A55F /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
833A61715BAAB31702D867CC /* Pods_SDWebImageSwiftUITests_macOS.framework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
322E0E0C28D332050003A55F /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
2E3D81A12C757E01A3C420F2 /* Pods_SDWebImageSwiftUITests_tvOS.framework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
32E529062348A0C700EA46FF /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
@ -196,6 +283,12 @@
95C9E0D9CE4113E5A82480B9 /* Pods-SDWebImageSwiftUIDemo-tvOS.release.xcconfig */,
FEED4964309E241D2FD8A544 /* Pods-SDWebImageSwiftUIDemo-watchOS WatchKit Extension.debug.xcconfig */,
7B0D9182CAD02B73E6F208F3 /* Pods-SDWebImageSwiftUIDemo-watchOS WatchKit Extension.release.xcconfig */,
487B2863C76EC4CE36CEC4EA /* Pods-SDWebImageSwiftUITests.debug.xcconfig */,
DDE527DE0EF6B6D9B7CD8C97 /* Pods-SDWebImageSwiftUITests.release.xcconfig */,
A7CD2F7825F1936052B2C65E /* Pods-SDWebImageSwiftUITests macOS.debug.xcconfig */,
0EEE88A04A9B191BD966EFC2 /* Pods-SDWebImageSwiftUITests macOS.release.xcconfig */,
5ABE9344AF344CCC70056CD5 /* Pods-SDWebImageSwiftUITests tvOS.debug.xcconfig */,
B6E12746E84E9ED7FA910A24 /* Pods-SDWebImageSwiftUITests tvOS.release.xcconfig */,
);
path = Pods;
sourceTree = "<group>";
@ -223,6 +316,21 @@
path = "Preview Content";
sourceTree = "<group>";
};
322E0DEF28D331A20003A55F /* Tests */ = {
isa = PBXGroup;
children = (
322E0DF028D331A20003A55F /* IndicatorTests.swift */,
322E0DF128D331A20003A55F /* WebImageTests.swift */,
322E0DF228D331A20003A55F /* Images.bundle */,
322E0DF328D331A20003A55F /* ImageManagerTests.swift */,
322E0DF428D331A20003A55F /* AnimatedImageTests.swift */,
322E0DF528D331A20003A55F /* Info.plist */,
322E0DF628D331A20003A55F /* TestUtils.swift */,
);
name = Tests;
path = ../Tests;
sourceTree = "<group>";
};
32E5290A2348A0C700EA46FF /* SDWebImageSwiftUIDemo-macOS */ = {
isa = PBXGroup;
children = (
@ -303,6 +411,7 @@
32E529212348A0D300EA46FF /* SDWebImageSwiftUIDemo-tvOS */,
32E5293B2348A0DD00EA46FF /* SDWebImageSwiftUIDemo-watchOS WatchKit App */,
32E5294A2348A0DE00EA46FF /* SDWebImageSwiftUIDemo-watchOS WatchKit Extension */,
322E0DEF28D331A20003A55F /* Tests */,
607FACD11AFB9204008FA782 /* Products */,
1DEE67F18F512F2F2F78E283 /* Pods */,
F1EB66AFCE0A1C6D551D02DD /* Frameworks */,
@ -318,6 +427,9 @@
32E529342348A0DD00EA46FF /* SDWebImageSwiftUIDemo-watchOS.app */,
32E529372348A0DD00EA46FF /* SDWebImageSwiftUIDemo-watchOS WatchKit App.app */,
32E529462348A0DE00EA46FF /* SDWebImageSwiftUIDemo-watchOS WatchKit Extension.appex */,
322E0DE628D3318B0003A55F /* SDWebImageSwiftUITests.xctest */,
322E0E0228D331F00003A55F /* SDWebImageSwiftUITests macOS.xctest */,
322E0E0F28D332050003A55F /* SDWebImageSwiftUITests tvOS.xctest */,
);
name = Products;
sourceTree = "<group>";
@ -339,6 +451,9 @@
473D7886C23B6FC5AFE35842 /* Pods_SDWebImageSwiftUIDemo_macOS.framework */,
79C3538209F8065DCCFBE205 /* Pods_SDWebImageSwiftUIDemo_tvOS.framework */,
E25DB0256669F3B7EE7C566D /* Pods_SDWebImageSwiftUIDemo_watchOS_WatchKit_Extension.framework */,
2FEDED19F84B1D678B12077A /* Pods_SDWebImageSwiftUITests.framework */,
C1A272DB5547C37A41C1238E /* Pods_SDWebImageSwiftUITests_macOS.framework */,
83FA763A8587C065798A274B /* Pods_SDWebImageSwiftUITests_tvOS.framework */,
);
name = Frameworks;
sourceTree = "<group>";
@ -365,6 +480,70 @@
productReference = 320CDC2922FADB44007CF858 /* SDWebImageSwiftUIDemo.app */;
productType = "com.apple.product-type.application";
};
322E0DE528D3318B0003A55F /* SDWebImageSwiftUITests */ = {
isa = PBXNativeTarget;
buildConfigurationList = 322E0DEE28D3318B0003A55F /* Build configuration list for PBXNativeTarget "SDWebImageSwiftUITests" */;
buildPhases = (
C7AF6D10A677FCEBE3437F0D /* [CP] Check Pods Manifest.lock */,
322E0DE228D3318B0003A55F /* Sources */,
322E0DE328D3318B0003A55F /* Frameworks */,
322E0DE428D3318B0003A55F /* Resources */,
FBC7E7B3AE428B3A9E53818E /* [CP] Embed Pods Frameworks */,
);
buildRules = (
);
dependencies = (
32DCFE9728D333F1001A17BF /* PBXTargetDependency */,
322E0DEB28D3318B0003A55F /* PBXTargetDependency */,
);
name = SDWebImageSwiftUITests;
packageProductDependencies = (
32DCFE9428D333E8001A17BF /* ViewInspector */,
);
productName = SDWebImageSwiftUITests;
productReference = 322E0DE628D3318B0003A55F /* SDWebImageSwiftUITests.xctest */;
productType = "com.apple.product-type.bundle.unit-test";
};
322E0E0128D331F00003A55F /* SDWebImageSwiftUITests macOS */ = {
isa = PBXNativeTarget;
buildConfigurationList = 322E0E0828D331F00003A55F /* Build configuration list for PBXNativeTarget "SDWebImageSwiftUITests macOS" */;
buildPhases = (
C82E8A3FDE233B48BF0E7FD0 /* [CP] Check Pods Manifest.lock */,
322E0DFE28D331F00003A55F /* Sources */,
322E0DFF28D331F00003A55F /* Frameworks */,
322E0E0028D331F00003A55F /* Resources */,
8D8B832471DE6E5EE5ABE934 /* [CP] Embed Pods Frameworks */,
);
buildRules = (
);
dependencies = (
322E0E0728D331F00003A55F /* PBXTargetDependency */,
);
name = "SDWebImageSwiftUITests macOS";
productName = "SDWebImageSwiftUITests macOS";
productReference = 322E0E0228D331F00003A55F /* SDWebImageSwiftUITests macOS.xctest */;
productType = "com.apple.product-type.bundle.unit-test";
};
322E0E0E28D332050003A55F /* SDWebImageSwiftUITests tvOS */ = {
isa = PBXNativeTarget;
buildConfigurationList = 322E0E1528D332050003A55F /* Build configuration list for PBXNativeTarget "SDWebImageSwiftUITests tvOS" */;
buildPhases = (
8C3AFE728247BB6B9A847044 /* [CP] Check Pods Manifest.lock */,
322E0E0B28D332050003A55F /* Sources */,
322E0E0C28D332050003A55F /* Frameworks */,
322E0E0D28D332050003A55F /* Resources */,
5EA97551EBAEA1D25997F2AB /* [CP] Embed Pods Frameworks */,
);
buildRules = (
);
dependencies = (
322E0E1428D332050003A55F /* PBXTargetDependency */,
);
name = "SDWebImageSwiftUITests tvOS";
productName = "SDWebImageSwiftUITests tvOS";
productReference = 322E0E0F28D332050003A55F /* SDWebImageSwiftUITests tvOS.xctest */;
productType = "com.apple.product-type.bundle.unit-test";
};
32E529082348A0C700EA46FF /* SDWebImageSwiftUIDemo-macOS */ = {
isa = PBXNativeTarget;
buildConfigurationList = 32E5291B2348A0C900EA46FF /* Build configuration list for PBXNativeTarget "SDWebImageSwiftUIDemo-macOS" */;
@ -464,13 +643,28 @@
607FACC81AFB9204008FA782 /* Project object */ = {
isa = PBXProject;
attributes = {
LastSwiftUpdateCheck = 1100;
LastSwiftUpdateCheck = 1340;
LastUpgradeCheck = 0830;
ORGANIZATIONNAME = CocoaPods;
TargetAttributes = {
320CDC2822FADB44007CF858 = {
CreatedOnToolsVersion = 11.0;
};
322E0DE528D3318B0003A55F = {
CreatedOnToolsVersion = 13.4.1;
ProvisioningStyle = Automatic;
TestTargetID = 320CDC2822FADB44007CF858;
};
322E0E0128D331F00003A55F = {
CreatedOnToolsVersion = 13.4.1;
ProvisioningStyle = Automatic;
TestTargetID = 32E529082348A0C700EA46FF;
};
322E0E0E28D332050003A55F = {
CreatedOnToolsVersion = 13.4.1;
ProvisioningStyle = Automatic;
TestTargetID = 32E5291F2348A0D300EA46FF;
};
32E529082348A0C700EA46FF = {
CreatedOnToolsVersion = 11.0;
ProvisioningStyle = Automatic;
@ -503,6 +697,9 @@
Base,
);
mainGroup = 607FACC71AFB9204008FA782;
packageReferences = (
32DCFE8D28D333B0001A17BF /* XCRemoteSwiftPackageReference "ViewInspector.git" */,
);
productRefGroup = 607FACD11AFB9204008FA782 /* Products */;
projectDirPath = "";
projectRoot = "";
@ -513,6 +710,9 @@
32E529332348A0DD00EA46FF /* SDWebImageSwiftUIDemo-watchOS */,
32E529362348A0DD00EA46FF /* SDWebImageSwiftUIDemo-watchOS WatchKit App */,
32E529452348A0DE00EA46FF /* SDWebImageSwiftUIDemo-watchOS WatchKit Extension */,
322E0DE528D3318B0003A55F /* SDWebImageSwiftUITests */,
322E0E0128D331F00003A55F /* SDWebImageSwiftUITests macOS */,
322E0E0E28D332050003A55F /* SDWebImageSwiftUITests tvOS */,
);
};
/* End PBXProject section */
@ -528,6 +728,30 @@
);
runOnlyForDeploymentPostprocessing = 0;
};
322E0DE428D3318B0003A55F /* Resources */ = {
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
322E0DF928D331A20003A55F /* Images.bundle in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
322E0E0028D331F00003A55F /* Resources */ = {
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
322E0E2228D332130003A55F /* Images.bundle in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
322E0E0D28D332050003A55F /* Resources */ = {
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
322E0E2328D332130003A55F /* Images.bundle in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
32E529072348A0C700EA46FF /* Resources */ = {
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
@ -654,6 +878,26 @@
shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n";
showEnvVarsInLog = 0;
};
5EA97551EBAEA1D25997F2AB /* [CP] Embed Pods Frameworks */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputPaths = (
"${PODS_ROOT}/Target Support Files/Pods-SDWebImageSwiftUITests tvOS/Pods-SDWebImageSwiftUITests tvOS-frameworks.sh",
"${BUILT_PRODUCTS_DIR}/SDWebImage-tvOS/SDWebImage.framework",
"${BUILT_PRODUCTS_DIR}/SDWebImageSwiftUI-tvOS/SDWebImageSwiftUI.framework",
);
name = "[CP] Embed Pods Frameworks";
outputPaths = (
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/SDWebImage.framework",
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/SDWebImageSwiftUI.framework",
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-SDWebImageSwiftUITests tvOS/Pods-SDWebImageSwiftUITests tvOS-frameworks.sh\"\n";
showEnvVarsInLog = 0;
};
756F0513F095D448FCCD78A2 /* [CP] Embed Pods Frameworks */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
@ -704,6 +948,48 @@
shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n";
showEnvVarsInLog = 0;
};
8C3AFE728247BB6B9A847044 /* [CP] Check Pods Manifest.lock */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputFileListPaths = (
);
inputPaths = (
"${PODS_PODFILE_DIR_PATH}/Podfile.lock",
"${PODS_ROOT}/Manifest.lock",
);
name = "[CP] Check Pods Manifest.lock";
outputFileListPaths = (
);
outputPaths = (
"$(DERIVED_FILE_DIR)/Pods-SDWebImageSwiftUITests tvOS-checkManifestLockResult.txt",
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n";
showEnvVarsInLog = 0;
};
8D8B832471DE6E5EE5ABE934 /* [CP] Embed Pods Frameworks */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputPaths = (
"${PODS_ROOT}/Target Support Files/Pods-SDWebImageSwiftUITests macOS/Pods-SDWebImageSwiftUITests macOS-frameworks.sh",
"${BUILT_PRODUCTS_DIR}/SDWebImage-macOS/SDWebImage.framework",
"${BUILT_PRODUCTS_DIR}/SDWebImageSwiftUI-macOS/SDWebImageSwiftUI.framework",
);
name = "[CP] Embed Pods Frameworks";
outputPaths = (
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/SDWebImage.framework",
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/SDWebImageSwiftUI.framework",
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-SDWebImageSwiftUITests macOS/Pods-SDWebImageSwiftUITests macOS-frameworks.sh\"\n";
showEnvVarsInLog = 0;
};
A6F5B1BDEE1460B7F20E55C6 /* [CP] Embed Pods Frameworks */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
@ -754,6 +1040,50 @@
shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n";
showEnvVarsInLog = 0;
};
C7AF6D10A677FCEBE3437F0D /* [CP] Check Pods Manifest.lock */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputFileListPaths = (
);
inputPaths = (
"${PODS_PODFILE_DIR_PATH}/Podfile.lock",
"${PODS_ROOT}/Manifest.lock",
);
name = "[CP] Check Pods Manifest.lock";
outputFileListPaths = (
);
outputPaths = (
"$(DERIVED_FILE_DIR)/Pods-SDWebImageSwiftUITests-checkManifestLockResult.txt",
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n";
showEnvVarsInLog = 0;
};
C82E8A3FDE233B48BF0E7FD0 /* [CP] Check Pods Manifest.lock */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputFileListPaths = (
);
inputPaths = (
"${PODS_PODFILE_DIR_PATH}/Podfile.lock",
"${PODS_ROOT}/Manifest.lock",
);
name = "[CP] Check Pods Manifest.lock";
outputFileListPaths = (
);
outputPaths = (
"$(DERIVED_FILE_DIR)/Pods-SDWebImageSwiftUITests macOS-checkManifestLockResult.txt",
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n";
showEnvVarsInLog = 0;
};
FB46C9F77AA45C7DA1D71F7B /* [CP] Check Pods Manifest.lock */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
@ -776,6 +1106,26 @@
shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n";
showEnvVarsInLog = 0;
};
FBC7E7B3AE428B3A9E53818E /* [CP] Embed Pods Frameworks */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputPaths = (
"${PODS_ROOT}/Target Support Files/Pods-SDWebImageSwiftUITests/Pods-SDWebImageSwiftUITests-frameworks.sh",
"${BUILT_PRODUCTS_DIR}/SDWebImage-iOS/SDWebImage.framework",
"${BUILT_PRODUCTS_DIR}/SDWebImageSwiftUI-iOS/SDWebImageSwiftUI.framework",
);
name = "[CP] Embed Pods Frameworks";
outputPaths = (
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/SDWebImage.framework",
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/SDWebImageSwiftUI.framework",
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-SDWebImageSwiftUITests/Pods-SDWebImageSwiftUITests-frameworks.sh\"\n";
showEnvVarsInLog = 0;
};
/* End PBXShellScriptBuildPhase section */
/* Begin PBXSourcesBuildPhase section */
@ -790,6 +1140,42 @@
);
runOnlyForDeploymentPostprocessing = 0;
};
322E0DE228D3318B0003A55F /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
322E0DF828D331A20003A55F /* WebImageTests.swift in Sources */,
322E0DFD28D331A20003A55F /* TestUtils.swift in Sources */,
322E0DFB28D331A20003A55F /* AnimatedImageTests.swift in Sources */,
322E0DF728D331A20003A55F /* IndicatorTests.swift in Sources */,
322E0DFA28D331A20003A55F /* ImageManagerTests.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
322E0DFE28D331F00003A55F /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
322E0E1B28D3320D0003A55F /* AnimatedImageTests.swift in Sources */,
322E0E1A28D3320D0003A55F /* WebImageTests.swift in Sources */,
322E0E1828D3320D0003A55F /* ImageManagerTests.swift in Sources */,
322E0E1C28D3320D0003A55F /* TestUtils.swift in Sources */,
322E0E1928D3320D0003A55F /* IndicatorTests.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
322E0E0B28D332050003A55F /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
322E0E2028D3320D0003A55F /* AnimatedImageTests.swift in Sources */,
322E0E1F28D3320D0003A55F /* WebImageTests.swift in Sources */,
322E0E1D28D3320D0003A55F /* ImageManagerTests.swift in Sources */,
322E0E2128D3320D0003A55F /* TestUtils.swift in Sources */,
322E0E1E28D3320D0003A55F /* IndicatorTests.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
32E529052348A0C700EA46FF /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
@ -824,6 +1210,25 @@
/* End PBXSourcesBuildPhase section */
/* Begin PBXTargetDependency section */
322E0DEB28D3318B0003A55F /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
target = 320CDC2822FADB44007CF858 /* SDWebImageSwiftUIDemo */;
targetProxy = 322E0DEA28D3318B0003A55F /* PBXContainerItemProxy */;
};
322E0E0728D331F00003A55F /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
target = 32E529082348A0C700EA46FF /* SDWebImageSwiftUIDemo-macOS */;
targetProxy = 322E0E0628D331F00003A55F /* PBXContainerItemProxy */;
};
322E0E1428D332050003A55F /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
target = 32E5291F2348A0D300EA46FF /* SDWebImageSwiftUIDemo-tvOS */;
targetProxy = 322E0E1328D332050003A55F /* PBXContainerItemProxy */;
};
32DCFE9728D333F1001A17BF /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
productRef = 32DCFE9628D333F1001A17BF /* ViewInspector */;
};
32E5293A2348A0DD00EA46FF /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
target = 32E529362348A0DD00EA46FF /* SDWebImageSwiftUIDemo-watchOS WatchKit App */;
@ -892,8 +1297,11 @@
ENABLE_PREVIEWS = YES;
GCC_C_LANGUAGE_STANDARD = gnu11;
INFOPLIST_FILE = SDWebImageSwiftUIDemo/Info.plist;
IPHONEOS_DEPLOYMENT_TARGET = 13.0;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
IPHONEOS_DEPLOYMENT_TARGET = 14.0;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
);
MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
MTL_FAST_MATH = YES;
PRODUCT_BUNDLE_IDENTIFIER = com.dreampiggy.SDWebImageSwiftUIDemo;
@ -926,8 +1334,11 @@
ENABLE_PREVIEWS = YES;
GCC_C_LANGUAGE_STANDARD = gnu11;
INFOPLIST_FILE = SDWebImageSwiftUIDemo/Info.plist;
IPHONEOS_DEPLOYMENT_TARGET = 13.0;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
IPHONEOS_DEPLOYMENT_TARGET = 14.0;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
);
MTL_FAST_MATH = YES;
PRODUCT_BUNDLE_IDENTIFIER = com.dreampiggy.SDWebImageSwiftUIDemo;
PRODUCT_NAME = "$(TARGET_NAME)";
@ -939,6 +1350,191 @@
};
name = Release;
};
322E0DEC28D3318B0003A55F /* Debug */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = 487B2863C76EC4CE36CEC4EA /* Pods-SDWebImageSwiftUITests.debug.xcconfig */;
buildSettings = {
BUNDLE_LOADER = "$(TEST_HOST)";
CLANG_ANALYZER_NONNULL = YES;
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++17";
CLANG_ENABLE_OBJC_WEAK = YES;
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 1;
DEBUG_INFORMATION_FORMAT = dwarf;
GCC_C_LANGUAGE_STANDARD = gnu11;
GENERATE_INFOPLIST_FILE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 14.0;
MARKETING_VERSION = 1.0;
MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
MTL_FAST_MATH = YES;
PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.SDWebImageSwiftUITests;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
SWIFT_EMIT_LOC_STRINGS = NO;
SWIFT_VERSION = 5.0;
TARGETED_DEVICE_FAMILY = "1,2";
TEST_HOST = "$(BUILT_PRODUCTS_DIR)/SDWebImageSwiftUIDemo.app/SDWebImageSwiftUIDemo";
};
name = Debug;
};
322E0DED28D3318B0003A55F /* Release */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = DDE527DE0EF6B6D9B7CD8C97 /* Pods-SDWebImageSwiftUITests.release.xcconfig */;
buildSettings = {
BUNDLE_LOADER = "$(TEST_HOST)";
CLANG_ANALYZER_NONNULL = YES;
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++17";
CLANG_ENABLE_OBJC_WEAK = YES;
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 1;
GCC_C_LANGUAGE_STANDARD = gnu11;
GENERATE_INFOPLIST_FILE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 14.0;
MARKETING_VERSION = 1.0;
MTL_FAST_MATH = YES;
PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.SDWebImageSwiftUITests;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_EMIT_LOC_STRINGS = NO;
SWIFT_VERSION = 5.0;
TARGETED_DEVICE_FAMILY = "1,2";
TEST_HOST = "$(BUILT_PRODUCTS_DIR)/SDWebImageSwiftUIDemo.app/SDWebImageSwiftUIDemo";
};
name = Release;
};
322E0E0928D331F00003A55F /* Debug */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = A7CD2F7825F1936052B2C65E /* Pods-SDWebImageSwiftUITests macOS.debug.xcconfig */;
buildSettings = {
BUNDLE_LOADER = "$(TEST_HOST)";
CLANG_ANALYZER_NONNULL = YES;
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++17";
CLANG_ENABLE_OBJC_WEAK = YES;
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 1;
DEBUG_INFORMATION_FORMAT = dwarf;
GCC_C_LANGUAGE_STANDARD = gnu11;
GENERATE_INFOPLIST_FILE = YES;
MACOSX_DEPLOYMENT_TARGET = 11.0;
MARKETING_VERSION = 1.0;
MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
MTL_FAST_MATH = YES;
PRODUCT_BUNDLE_IDENTIFIER = "org.cocoapods.SDWebImageSwiftUITests-macOS";
PRODUCT_NAME = "$(TARGET_NAME)";
SDKROOT = macosx;
SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
SWIFT_EMIT_LOC_STRINGS = NO;
SWIFT_VERSION = 5.0;
TEST_HOST = "$(BUILT_PRODUCTS_DIR)/SDWebImageSwiftUIDemo-macOS.app/Contents/MacOS/SDWebImageSwiftUIDemo-macOS";
};
name = Debug;
};
322E0E0A28D331F00003A55F /* Release */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = 0EEE88A04A9B191BD966EFC2 /* Pods-SDWebImageSwiftUITests macOS.release.xcconfig */;
buildSettings = {
BUNDLE_LOADER = "$(TEST_HOST)";
CLANG_ANALYZER_NONNULL = YES;
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++17";
CLANG_ENABLE_OBJC_WEAK = YES;
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 1;
GCC_C_LANGUAGE_STANDARD = gnu11;
GENERATE_INFOPLIST_FILE = YES;
MACOSX_DEPLOYMENT_TARGET = 11.0;
MARKETING_VERSION = 1.0;
MTL_FAST_MATH = YES;
PRODUCT_BUNDLE_IDENTIFIER = "org.cocoapods.SDWebImageSwiftUITests-macOS";
PRODUCT_NAME = "$(TARGET_NAME)";
SDKROOT = macosx;
SWIFT_EMIT_LOC_STRINGS = NO;
SWIFT_VERSION = 5.0;
TEST_HOST = "$(BUILT_PRODUCTS_DIR)/SDWebImageSwiftUIDemo-macOS.app/Contents/MacOS/SDWebImageSwiftUIDemo-macOS";
};
name = Release;
};
322E0E1628D332050003A55F /* Debug */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = 5ABE9344AF344CCC70056CD5 /* Pods-SDWebImageSwiftUITests tvOS.debug.xcconfig */;
buildSettings = {
BUNDLE_LOADER = "$(TEST_HOST)";
CLANG_ANALYZER_NONNULL = YES;
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++17";
CLANG_ENABLE_OBJC_WEAK = YES;
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 1;
DEBUG_INFORMATION_FORMAT = dwarf;
GCC_C_LANGUAGE_STANDARD = gnu11;
GENERATE_INFOPLIST_FILE = YES;
MARKETING_VERSION = 1.0;
MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
MTL_FAST_MATH = YES;
PRODUCT_BUNDLE_IDENTIFIER = "org.cocoapods.SDWebImageSwiftUITests-tvOS";
PRODUCT_NAME = "$(TARGET_NAME)";
SDKROOT = appletvos;
SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
SWIFT_EMIT_LOC_STRINGS = NO;
SWIFT_VERSION = 5.0;
TARGETED_DEVICE_FAMILY = 3;
TEST_HOST = "$(BUILT_PRODUCTS_DIR)/SDWebImageSwiftUIDemo-tvOS.app/SDWebImageSwiftUIDemo-tvOS";
TVOS_DEPLOYMENT_TARGET = 14.0;
};
name = Debug;
};
322E0E1728D332050003A55F /* Release */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = B6E12746E84E9ED7FA910A24 /* Pods-SDWebImageSwiftUITests tvOS.release.xcconfig */;
buildSettings = {
BUNDLE_LOADER = "$(TEST_HOST)";
CLANG_ANALYZER_NONNULL = YES;
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++17";
CLANG_ENABLE_OBJC_WEAK = YES;
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 1;
GCC_C_LANGUAGE_STANDARD = gnu11;
GENERATE_INFOPLIST_FILE = YES;
MARKETING_VERSION = 1.0;
MTL_FAST_MATH = YES;
PRODUCT_BUNDLE_IDENTIFIER = "org.cocoapods.SDWebImageSwiftUITests-tvOS";
PRODUCT_NAME = "$(TARGET_NAME)";
SDKROOT = appletvos;
SWIFT_EMIT_LOC_STRINGS = NO;
SWIFT_VERSION = 5.0;
TARGETED_DEVICE_FAMILY = 3;
TEST_HOST = "$(BUILT_PRODUCTS_DIR)/SDWebImageSwiftUIDemo-tvOS.app/SDWebImageSwiftUIDemo-tvOS";
TVOS_DEPLOYMENT_TARGET = 14.0;
};
name = Release;
};
32E529192348A0C900EA46FF /* Debug */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = 89B11BBDBAA86F760DF1EE2D /* Pods-SDWebImageSwiftUIDemo-macOS.debug.xcconfig */;
@ -960,8 +1556,11 @@
ENABLE_PREVIEWS = YES;
GCC_C_LANGUAGE_STANDARD = gnu11;
INFOPLIST_FILE = "SDWebImageSwiftUIDemo-macOS/Info.plist";
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks";
MACOSX_DEPLOYMENT_TARGET = 10.15;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/../Frameworks",
);
MACOSX_DEPLOYMENT_TARGET = 11.0;
MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
MTL_FAST_MATH = YES;
PRODUCT_BUNDLE_IDENTIFIER = "com.dreampiggy.SDWebImageSwiftUIDemo-macOS";
@ -992,8 +1591,11 @@
ENABLE_PREVIEWS = YES;
GCC_C_LANGUAGE_STANDARD = gnu11;
INFOPLIST_FILE = "SDWebImageSwiftUIDemo-macOS/Info.plist";
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks";
MACOSX_DEPLOYMENT_TARGET = 10.15;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/../Frameworks",
);
MACOSX_DEPLOYMENT_TARGET = 11.0;
MTL_FAST_MATH = YES;
PRODUCT_BUNDLE_IDENTIFIER = "com.dreampiggy.SDWebImageSwiftUIDemo-macOS";
PRODUCT_NAME = "$(TARGET_NAME)";
@ -1021,7 +1623,10 @@
ENABLE_PREVIEWS = YES;
GCC_C_LANGUAGE_STANDARD = gnu11;
INFOPLIST_FILE = "SDWebImageSwiftUIDemo-tvOS/Info.plist";
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
);
MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
MTL_FAST_MATH = YES;
PRODUCT_BUNDLE_IDENTIFIER = "com.dreampiggy.SDWebImageSwiftUIDemo-tvOS";
@ -1030,7 +1635,7 @@
SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
SWIFT_VERSION = 5.0;
TARGETED_DEVICE_FAMILY = 3;
TVOS_DEPLOYMENT_TARGET = 13.0;
TVOS_DEPLOYMENT_TARGET = 14.0;
};
name = Debug;
};
@ -1052,14 +1657,17 @@
ENABLE_PREVIEWS = YES;
GCC_C_LANGUAGE_STANDARD = gnu11;
INFOPLIST_FILE = "SDWebImageSwiftUIDemo-tvOS/Info.plist";
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
);
MTL_FAST_MATH = YES;
PRODUCT_BUNDLE_IDENTIFIER = "com.dreampiggy.SDWebImageSwiftUIDemo-tvOS";
PRODUCT_NAME = "$(TARGET_NAME)";
SDKROOT = appletvos;
SWIFT_VERSION = 5.0;
TARGETED_DEVICE_FAMILY = 3;
TVOS_DEPLOYMENT_TARGET = 13.0;
TVOS_DEPLOYMENT_TARGET = 14.0;
};
name = Release;
};
@ -1082,7 +1690,11 @@
ENABLE_PREVIEWS = YES;
GCC_C_LANGUAGE_STANDARD = gnu11;
INFOPLIST_FILE = "SDWebImageSwiftUIDemo-watchOS WatchKit Extension/Info.plist";
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @executable_path/../../Frameworks";
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
"@executable_path/../../Frameworks",
);
MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
MTL_FAST_MATH = YES;
PRODUCT_BUNDLE_IDENTIFIER = "com.dreampiggy.SDWebImageSwiftUIDemo-watchOS.watchkitapp.watchkitextension";
@ -1114,7 +1726,11 @@
ENABLE_PREVIEWS = YES;
GCC_C_LANGUAGE_STANDARD = gnu11;
INFOPLIST_FILE = "SDWebImageSwiftUIDemo-watchOS WatchKit Extension/Info.plist";
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @executable_path/../../Frameworks";
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
"@executable_path/../../Frameworks",
);
MTL_FAST_MATH = YES;
PRODUCT_BUNDLE_IDENTIFIER = "com.dreampiggy.SDWebImageSwiftUIDemo-watchOS.watchkitapp.watchkitextension";
PRODUCT_NAME = "${TARGET_NAME}";
@ -1326,7 +1942,8 @@
GCC_WARN_UNUSED_VARIABLE = YES;
MTL_ENABLE_DEBUG_INFO = NO;
SDKROOT = iphoneos;
SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule";
SWIFT_COMPILATION_MODE = wholemodule;
SWIFT_OPTIMIZATION_LEVEL = "-O";
VALIDATE_PRODUCT = YES;
};
name = Release;
@ -1343,6 +1960,33 @@
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
322E0DEE28D3318B0003A55F /* Build configuration list for PBXNativeTarget "SDWebImageSwiftUITests" */ = {
isa = XCConfigurationList;
buildConfigurations = (
322E0DEC28D3318B0003A55F /* Debug */,
322E0DED28D3318B0003A55F /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
322E0E0828D331F00003A55F /* Build configuration list for PBXNativeTarget "SDWebImageSwiftUITests macOS" */ = {
isa = XCConfigurationList;
buildConfigurations = (
322E0E0928D331F00003A55F /* Debug */,
322E0E0A28D331F00003A55F /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
322E0E1528D332050003A55F /* Build configuration list for PBXNativeTarget "SDWebImageSwiftUITests tvOS" */ = {
isa = XCConfigurationList;
buildConfigurations = (
322E0E1628D332050003A55F /* Debug */,
322E0E1728D332050003A55F /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
32E5291B2348A0C900EA46FF /* Build configuration list for PBXNativeTarget "SDWebImageSwiftUIDemo-macOS" */ = {
isa = XCConfigurationList;
buildConfigurations = (
@ -1398,6 +2042,30 @@
defaultConfigurationName = Release;
};
/* End XCConfigurationList section */
/* Begin XCRemoteSwiftPackageReference section */
32DCFE8D28D333B0001A17BF /* XCRemoteSwiftPackageReference "ViewInspector.git" */ = {
isa = XCRemoteSwiftPackageReference;
repositoryURL = "https://github.com/nalexn/ViewInspector.git";
requirement = {
kind = exactVersion;
version = 0.9.1;
};
};
/* End XCRemoteSwiftPackageReference section */
/* Begin XCSwiftPackageProductDependency section */
32DCFE9428D333E8001A17BF /* ViewInspector */ = {
isa = XCSwiftPackageProductDependency;
package = 32DCFE8D28D333B0001A17BF /* XCRemoteSwiftPackageReference "ViewInspector.git" */;
productName = ViewInspector;
};
32DCFE9628D333F1001A17BF /* ViewInspector */ = {
isa = XCSwiftPackageProductDependency;
package = 32DCFE8D28D333B0001A17BF /* XCRemoteSwiftPackageReference "ViewInspector.git" */;
productName = ViewInspector;
};
/* End XCSwiftPackageProductDependency section */
};
rootObject = 607FACC81AFB9204008FA782 /* Project object */;
}

View File

@ -28,6 +28,16 @@
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
shouldUseLaunchSchemeArgsEnv = "YES">
<Testables>
<TestableReference
skipped = "NO">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "322E0E0128D331F00003A55F"
BuildableName = "SDWebImageSwiftUITests macOS.xctest"
BlueprintName = "SDWebImageSwiftUITests macOS"
ReferencedContainer = "container:SDWebImageSwiftUI.xcodeproj">
</BuildableReference>
</TestableReference>
</Testables>
</TestAction>
<LaunchAction

View File

@ -28,6 +28,16 @@
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
shouldUseLaunchSchemeArgsEnv = "YES">
<Testables>
<TestableReference
skipped = "NO">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "322E0E0E28D332050003A55F"
BuildableName = "SDWebImageSwiftUITests tvOS.xctest"
BlueprintName = "SDWebImageSwiftUITests tvOS"
ReferencedContainer = "container:SDWebImageSwiftUI.xcodeproj">
</BuildableReference>
</TestableReference>
</Testables>
</TestAction>
<LaunchAction

View File

@ -28,6 +28,16 @@
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
shouldUseLaunchSchemeArgsEnv = "YES">
<Testables>
<TestableReference
skipped = "NO">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "322E0DE528D3318B0003A55F"
BuildableName = "SDWebImageSwiftUITests.xctest"
BlueprintName = "SDWebImageSwiftUITests"
ReferencedContainer = "container:SDWebImageSwiftUI.xcodeproj">
</BuildableReference>
</TestableReference>
</Testables>
</TestAction>
<LaunchAction

View File

@ -1,39 +1,22 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "1130"
LastUpgradeVersion = "1340"
version = "1.3">
<BuildAction
parallelizeBuildables = "YES"
buildImplicitDependencies = "YES">
<BuildActionEntries>
<BuildActionEntry
buildForTesting = "YES"
buildForRunning = "YES"
buildForProfiling = "YES"
buildForArchiving = "YES"
buildForAnalyzing = "YES">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "321C1D3A23DEC17D009CF62A"
BuildableName = "SDWebImageSwiftUITests macOS.xctest"
BlueprintName = "SDWebImageSwiftUITests macOS"
ReferencedContainer = "container:SDWebImageSwiftUI.xcodeproj">
</BuildableReference>
</BuildActionEntry>
</BuildActionEntries>
</BuildAction>
<TestAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
shouldUseLaunchSchemeArgsEnv = "YES"
codeCoverageEnabled = "YES">
shouldUseLaunchSchemeArgsEnv = "YES">
<Testables>
<TestableReference
skipped = "NO">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "321C1D3A23DEC17D009CF62A"
BlueprintIdentifier = "322E0E0128D331F00003A55F"
BuildableName = "SDWebImageSwiftUITests macOS.xctest"
BlueprintName = "SDWebImageSwiftUITests macOS"
ReferencedContainer = "container:SDWebImageSwiftUI.xcodeproj">
@ -58,15 +41,6 @@
savedToolIdentifier = ""
useCustomWorkingDirectory = "NO"
debugDocumentVersioning = "YES">
<MacroExpansion>
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "321C1D3A23DEC17D009CF62A"
BuildableName = "SDWebImageSwiftUITests macOS.xctest"
BlueprintName = "SDWebImageSwiftUITests macOS"
ReferencedContainer = "container:SDWebImageSwiftUI.xcodeproj">
</BuildableReference>
</MacroExpansion>
</ProfileAction>
<AnalyzeAction
buildConfiguration = "Debug">

View File

@ -1,39 +1,22 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "1130"
LastUpgradeVersion = "1340"
version = "1.3">
<BuildAction
parallelizeBuildables = "YES"
buildImplicitDependencies = "YES">
<BuildActionEntries>
<BuildActionEntry
buildForTesting = "YES"
buildForRunning = "YES"
buildForProfiling = "YES"
buildForArchiving = "YES"
buildForAnalyzing = "YES">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "321C1D4923DEC185009CF62A"
BuildableName = "SDWebImageSwiftUITests tvOS.xctest"
BlueprintName = "SDWebImageSwiftUITests tvOS"
ReferencedContainer = "container:SDWebImageSwiftUI.xcodeproj">
</BuildableReference>
</BuildActionEntry>
</BuildActionEntries>
</BuildAction>
<TestAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
shouldUseLaunchSchemeArgsEnv = "YES"
codeCoverageEnabled = "YES">
shouldUseLaunchSchemeArgsEnv = "YES">
<Testables>
<TestableReference
skipped = "NO">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "321C1D4923DEC185009CF62A"
BlueprintIdentifier = "322E0E0E28D332050003A55F"
BuildableName = "SDWebImageSwiftUITests tvOS.xctest"
BlueprintName = "SDWebImageSwiftUITests tvOS"
ReferencedContainer = "container:SDWebImageSwiftUI.xcodeproj">
@ -58,15 +41,6 @@
savedToolIdentifier = ""
useCustomWorkingDirectory = "NO"
debugDocumentVersioning = "YES">
<MacroExpansion>
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "321C1D4923DEC185009CF62A"
BuildableName = "SDWebImageSwiftUITests tvOS.xctest"
BlueprintName = "SDWebImageSwiftUITests tvOS"
ReferencedContainer = "container:SDWebImageSwiftUI.xcodeproj">
</BuildableReference>
</MacroExpansion>
</ProfileAction>
<AnalyzeAction
buildConfiguration = "Debug">

View File

@ -1,39 +1,22 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "1130"
LastUpgradeVersion = "1340"
version = "1.3">
<BuildAction
parallelizeBuildables = "YES"
buildImplicitDependencies = "YES">
<BuildActionEntries>
<BuildActionEntry
buildForTesting = "YES"
buildForRunning = "YES"
buildForProfiling = "YES"
buildForArchiving = "YES"
buildForAnalyzing = "YES">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "3211F84323DE984D00FC757F"
BuildableName = "SDWebImageSwiftUITests.xctest"
BlueprintName = "SDWebImageSwiftUITests"
ReferencedContainer = "container:SDWebImageSwiftUI.xcodeproj">
</BuildableReference>
</BuildActionEntry>
</BuildActionEntries>
</BuildAction>
<TestAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
shouldUseLaunchSchemeArgsEnv = "YES"
codeCoverageEnabled = "YES">
shouldUseLaunchSchemeArgsEnv = "YES">
<Testables>
<TestableReference
skipped = "NO">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "3211F84323DE984D00FC757F"
BlueprintIdentifier = "322E0DE528D3318B0003A55F"
BuildableName = "SDWebImageSwiftUITests.xctest"
BlueprintName = "SDWebImageSwiftUITests"
ReferencedContainer = "container:SDWebImageSwiftUI.xcodeproj">
@ -58,15 +41,6 @@
savedToolIdentifier = ""
useCustomWorkingDirectory = "NO"
debugDocumentVersioning = "YES">
<MacroExpansion>
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "3211F84323DE984D00FC757F"
BuildableName = "SDWebImageSwiftUITests.xctest"
BlueprintName = "SDWebImageSwiftUITests"
ReferencedContainer = "container:SDWebImageSwiftUI.xcodeproj">
</BuildableReference>
</MacroExpansion>
</ProfileAction>
<AnalyzeAction
buildConfiguration = "Debug">

View File

@ -46,7 +46,6 @@ struct ContentView: View {
"https://isparta.github.io/compare-webp/image/gif_webp/webp/2.webp",
"https://nokiatech.github.io/heif/content/images/ski_jump_1440x960.heic",
"https://nokiatech.github.io/heif/content/image_sequences/starfield_animation.heic",
"https://www.sample-videos.com/img/Sample-png-image-1mb.png",
"https://nr-platform.s3.amazonaws.com/uploads/platform/published_extension/branding_icon/275/AmazonS3.png",
"https://raw.githubusercontent.com/ibireme/YYImage/master/Demo/YYImageDemo/mew_baseline.jpg",
"https://via.placeholder.com/200x200.jpg",
@ -56,7 +55,7 @@ struct ContentView: View {
"https://raw.githubusercontent.com/icons8/flat-color-icons/master/pdf/stack_of_photos.pdf",
"https://raw.githubusercontent.com/icons8/flat-color-icons/master/pdf/smartphone_tablet.pdf"
]
@State var animated: Bool = true // You can change between WebImage/AnimatedImage
@State var animated: Bool = false // You can change between WebImage/AnimatedImage
@EnvironmentObject var settings: UserSettings
var body: some View {

View File

@ -6,8 +6,8 @@
"repositoryURL": "https://github.com/SDWebImage/SDWebImage.git",
"state": {
"branch": null,
"revision": "e2285181a62daf4d1d3caf66d6d776b667092303",
"version": "5.7.0"
"revision": "3e48cb68d8e668d146dc59c73fb98cb628616236",
"version": "5.13.2"
}
}
]

60
Podfile Normal file
View File

@ -0,0 +1,60 @@
install! 'cocoapods', :warn_for_unused_master_specs_repo => false
use_frameworks!
def all_pods
pod 'SDWebImageSwiftUI', :path => './'
pod 'SDWebImageWebPCoder'
pod 'SDWebImageSVGCoder'
pod 'SDWebImagePDFCoder'
end
def all_test_pods
pod 'SDWebImageSwiftUI', :path => './'
end
example_project_path = 'Example/SDWebImageSwiftUI'
test_project_path = 'Example/SDWebImageSwiftUI'
workspace 'SDWebImageSwiftUI.xcworkspace'
target 'SDWebImageSwiftUIDemo' do
project example_project_path
platform :ios, '14.0'
all_pods
end
target 'SDWebImageSwiftUIDemo-macOS' do
project example_project_path
platform :osx, '11.0'
all_pods
end
target 'SDWebImageSwiftUIDemo-tvOS' do
project example_project_path
platform :tvos, '14.0'
all_pods
end
target 'SDWebImageSwiftUIDemo-watchOS WatchKit Extension' do
project example_project_path
platform :watchos, '7.0'
all_pods
end
# Test Project
target 'SDWebImageSwiftUITests' do
project test_project_path
platform :ios, '14.0'
all_test_pods
end
target 'SDWebImageSwiftUITests macOS' do
project test_project_path
platform :osx, '11.0'
all_test_pods
end
target 'SDWebImageSwiftUITests tvOS' do
project test_project_path
platform :tvos, '14.0'
all_test_pods
end

View File

@ -8,6 +8,8 @@
[![SwiftPM compatible](https://img.shields.io/badge/SwiftPM-compatible-brightgreen.svg)](https://swift.org/package-manager/)
[![codecov](https://codecov.io/gh/SDWebImage/SDWebImageSwiftUI/branch/master/graph/badge.svg)](https://codecov.io/gh/SDWebImage/SDWebImageSwiftUI)
> If you support iOS 15+/macOS 12+ only and don't care about animated image format, try SwiftUI's [AsyncImage](https://developer.apple.com/documentation/swiftui/asyncimage)
## What's for
SDWebImageSwiftUI is a SwiftUI image loading framework, which based on [SDWebImage](https://github.com/SDWebImage/SDWebImage).
@ -49,11 +51,10 @@ All issue reports, feature requests, contributions, and GitHub stars are welcome
## Requirements
+ Xcode 12+
+ iOS 13+
+ macOS 10.15+
+ tvOS 13+
+ watchOS 6+
+ Swift 5.2+
+ iOS 13+ (14+ Recommended)
+ macOS 10.15+ (11+ Recommended)
+ tvOS 13+ (14+ Recommended)
+ watchOS 6+ (7+ Recommended)
## SwiftUI 2.0 Compatibility
@ -73,7 +74,9 @@ var body: some View {
}
```
Note: However, many differences behavior between iOS 13/14's is hard to fixup. Due to maintain issue, in the future release, we will drop the iOS 13 supports and always match SwiftUI 2.0's behavior.
Note: However, many differences behavior between iOS 13/14's is hard to fixup. And we may break some APIs (which are not designed to be public) to fixup it.
Due to maintain issue, in the future release, we will drop the iOS 13 supports and always match SwiftUI 2.0's behavior. And **v2.1** may be the last version support iOS 13.
## Installation
@ -560,12 +563,9 @@ struct ContentView : View {
To run the example using SwiftUI, following the steps:
```
cd Example
pod install
```
Then open the Xcode Workspace to run the demo application.
1. Run `pod install` on root directory to install the dependency.
2. Open `SDWebImageSwiftUI.xcworkspace`, wait for SwiftPM finishing downloading the test dependency.
3. Choose `SDWebImageSwiftUIDemo` scheme and run the demo application.
Since SwiftUI is aimed to support all Apple platforms, our demo does this as well, one codebase including:
@ -592,8 +592,8 @@ However, since SwiftUI is State-Based and Attributed-Implemented layout system,
To run the test:
1. Run `carthage build` on root directory to install the dependency.
2. Open `SDWebImageSwiftUI.xcodeproj`, wait for SwiftPM finishing downloading the test dependency.
1. Run `pod install` on root directory to install the dependency.
2. Open `SDWebImageSwiftUI.xcworkspace`, wait for SwiftPM finishing downloading the test dependency.
3. Choose `SDWebImageSwiftUITests` scheme and start testing.
We've already setup the CI pipeline, each PR will run the test case and upload the test report to [codecov](https://codecov.io/gh/SDWebImage/SDWebImageSwiftUI).
@ -639,6 +639,7 @@ Which means, this project is one core use case and downstream dependency, which
- [Espera](https://github.com/JagCesar/Espera)
- [SwiftUI-Introspect](https://github.com/siteline/SwiftUI-Introspect)
- [ViewInspector](https://github.com/nalexn/ViewInspector)
- [SwiftUIBackports](https://github.com/shaps80/SwiftUIBackports)
## License

View File

@ -3,31 +3,10 @@
archiveVersion = 1;
classes = {
};
objectVersion = 52;
objectVersion = 50;
objects = {
/* Begin PBXBuildFile section */
3211F84723DE984D00FC757F /* AnimatedImageTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3211F84623DE984D00FC757F /* AnimatedImageTests.swift */; };
3211F84923DE984D00FC757F /* SDWebImageSwiftUI.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 32C43DCC22FD540D00BE87F5 /* SDWebImageSwiftUI.framework */; };
3211F85023DE98E300FC757F /* WebImageTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3211F84F23DE98E300FC757F /* WebImageTests.swift */; };
3211F85323DE996700FC757F /* ViewInspector in Frameworks */ = {isa = PBXBuildFile; productRef = 3211F85223DE996700FC757F /* ViewInspector */; };
321C1D3323DEA28E009CF62A /* SDWebImage.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 32C43DE922FD577300BE87F5 /* SDWebImage.framework */; };
321C1D3623DEA9E8009CF62A /* Images.bundle in Resources */ = {isa = PBXBuildFile; fileRef = 3211F85423DE9D2700FC757F /* Images.bundle */; };
321C1D4023DEC17D009CF62A /* SDWebImageSwiftUI.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 32C43DF422FD57FD00BE87F5 /* SDWebImageSwiftUI.framework */; };
321C1D4F23DEC185009CF62A /* SDWebImageSwiftUI.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 32C43E0122FD581400BE87F5 /* SDWebImageSwiftUI.framework */; };
321C1D5A23DEC207009CF62A /* ViewInspector in Frameworks */ = {isa = PBXBuildFile; productRef = 321C1D5923DEC207009CF62A /* ViewInspector */; };
321C1D5B23DEC219009CF62A /* SDWebImage.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 32C43E2522FD585300BE87F5 /* SDWebImage.framework */; };
321C1D5C23DEC221009CF62A /* Images.bundle in Resources */ = {isa = PBXBuildFile; fileRef = 3211F85423DE9D2700FC757F /* Images.bundle */; };
321C1D5D23DEC222009CF62A /* Images.bundle in Resources */ = {isa = PBXBuildFile; fileRef = 3211F85423DE9D2700FC757F /* Images.bundle */; };
321C1D5E23DEC22D009CF62A /* SDWebImage.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 32C43E2922FD586200BE87F5 /* SDWebImage.framework */; };
321C1D6023DEC231009CF62A /* ViewInspector in Frameworks */ = {isa = PBXBuildFile; productRef = 321C1D5F23DEC231009CF62A /* ViewInspector */; };
321C1D6A23DEDB98009CF62A /* AnimatedImageTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3211F84623DE984D00FC757F /* AnimatedImageTests.swift */; };
321C1D6B23DEDB98009CF62A /* WebImageTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3211F84F23DE98E300FC757F /* WebImageTests.swift */; };
321C1D6C23DEDB98009CF62A /* AnimatedImageTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3211F84623DE984D00FC757F /* AnimatedImageTests.swift */; };
321C1D6D23DEDB98009CF62A /* WebImageTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3211F84F23DE98E300FC757F /* WebImageTests.swift */; };
322E0F4823E57F09006836DC /* TestUtils.swift in Sources */ = {isa = PBXBuildFile; fileRef = 322E0F4723E57F09006836DC /* TestUtils.swift */; };
322E0F4923E57F09006836DC /* TestUtils.swift in Sources */ = {isa = PBXBuildFile; fileRef = 322E0F4723E57F09006836DC /* TestUtils.swift */; };
322E0F4A23E57F09006836DC /* TestUtils.swift in Sources */ = {isa = PBXBuildFile; fileRef = 322E0F4723E57F09006836DC /* TestUtils.swift */; };
326B84822363350C0011BDFB /* Indicator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 326B84812363350C0011BDFB /* Indicator.swift */; };
326B84832363350C0011BDFB /* Indicator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 326B84812363350C0011BDFB /* Indicator.swift */; };
326B84842363350C0011BDFB /* Indicator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 326B84812363350C0011BDFB /* Indicator.swift */; };
@ -48,9 +27,22 @@
32B933E623659A1900BB7CAD /* Transition.swift in Sources */ = {isa = PBXBuildFile; fileRef = 32B933E423659A1900BB7CAD /* Transition.swift */; };
32B933E723659A1900BB7CAD /* Transition.swift in Sources */ = {isa = PBXBuildFile; fileRef = 32B933E423659A1900BB7CAD /* Transition.swift */; };
32B933E823659A1900BB7CAD /* Transition.swift in Sources */ = {isa = PBXBuildFile; fileRef = 32B933E423659A1900BB7CAD /* Transition.swift */; };
32BD9C4723E03B08008D5F6A /* IndicatorTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 32BD9C4623E03B08008D5F6A /* IndicatorTests.swift */; };
32BD9C4823E03B08008D5F6A /* IndicatorTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 32BD9C4623E03B08008D5F6A /* IndicatorTests.swift */; };
32BD9C4923E03B08008D5F6A /* IndicatorTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 32BD9C4623E03B08008D5F6A /* IndicatorTests.swift */; };
32BC087328D23D35002451BD /* StateObject.swift in Sources */ = {isa = PBXBuildFile; fileRef = 32BC086F28D23D35002451BD /* StateObject.swift */; };
32BC087428D23D35002451BD /* StateObject.swift in Sources */ = {isa = PBXBuildFile; fileRef = 32BC086F28D23D35002451BD /* StateObject.swift */; };
32BC087528D23D35002451BD /* StateObject.swift in Sources */ = {isa = PBXBuildFile; fileRef = 32BC086F28D23D35002451BD /* StateObject.swift */; };
32BC087628D23D35002451BD /* StateObject.swift in Sources */ = {isa = PBXBuildFile; fileRef = 32BC086F28D23D35002451BD /* StateObject.swift */; };
32BC087728D23D35002451BD /* OnChange.swift in Sources */ = {isa = PBXBuildFile; fileRef = 32BC087028D23D35002451BD /* OnChange.swift */; };
32BC087828D23D35002451BD /* OnChange.swift in Sources */ = {isa = PBXBuildFile; fileRef = 32BC087028D23D35002451BD /* OnChange.swift */; };
32BC087928D23D35002451BD /* OnChange.swift in Sources */ = {isa = PBXBuildFile; fileRef = 32BC087028D23D35002451BD /* OnChange.swift */; };
32BC087A28D23D35002451BD /* OnChange.swift in Sources */ = {isa = PBXBuildFile; fileRef = 32BC087028D23D35002451BD /* OnChange.swift */; };
32BC087B28D23D35002451BD /* Overlay.swift in Sources */ = {isa = PBXBuildFile; fileRef = 32BC087128D23D35002451BD /* Overlay.swift */; };
32BC087C28D23D35002451BD /* Overlay.swift in Sources */ = {isa = PBXBuildFile; fileRef = 32BC087128D23D35002451BD /* Overlay.swift */; };
32BC087D28D23D35002451BD /* Overlay.swift in Sources */ = {isa = PBXBuildFile; fileRef = 32BC087128D23D35002451BD /* Overlay.swift */; };
32BC087E28D23D35002451BD /* Overlay.swift in Sources */ = {isa = PBXBuildFile; fileRef = 32BC087128D23D35002451BD /* Overlay.swift */; };
32BC087F28D23D35002451BD /* Backport.swift in Sources */ = {isa = PBXBuildFile; fileRef = 32BC087228D23D35002451BD /* Backport.swift */; };
32BC088028D23D35002451BD /* Backport.swift in Sources */ = {isa = PBXBuildFile; fileRef = 32BC087228D23D35002451BD /* Backport.swift */; };
32BC088128D23D35002451BD /* Backport.swift in Sources */ = {isa = PBXBuildFile; fileRef = 32BC087228D23D35002451BD /* Backport.swift */; };
32BC088228D23D35002451BD /* Backport.swift in Sources */ = {isa = PBXBuildFile; fileRef = 32BC087228D23D35002451BD /* Backport.swift */; };
32C43DE622FD54CD00BE87F5 /* SDWebImageSwiftUI.h in Headers */ = {isa = PBXBuildFile; fileRef = 32C43DE422FD54CD00BE87F5 /* SDWebImageSwiftUI.h */; settings = {ATTRIBUTES = (Public, ); }; };
32C43DEA22FD577300BE87F5 /* SDWebImage.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 32C43DE922FD577300BE87F5 /* SDWebImage.framework */; };
32C43E1622FD583700BE87F5 /* ImageManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 32C43DDC22FD54C600BE87F5 /* ImageManager.swift */; };
@ -79,57 +71,27 @@
32CBA78125E4D7D800C6A8DC /* ImagePlayer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 32CBA77E25E4D7D800C6A8DC /* ImagePlayer.swift */; };
32CBA78225E4D7D800C6A8DC /* ImagePlayer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 32CBA77E25E4D7D800C6A8DC /* ImagePlayer.swift */; };
32CBA78325E4D7D800C6A8DC /* ImagePlayer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 32CBA77E25E4D7D800C6A8DC /* ImagePlayer.swift */; };
32CBA78425E4D7D800C6A8DC /* SwiftUICompatibility.swift in Sources */ = {isa = PBXBuildFile; fileRef = 32CBA77F25E4D7D800C6A8DC /* SwiftUICompatibility.swift */; };
32CBA78525E4D7D800C6A8DC /* SwiftUICompatibility.swift in Sources */ = {isa = PBXBuildFile; fileRef = 32CBA77F25E4D7D800C6A8DC /* SwiftUICompatibility.swift */; };
32CBA78625E4D7D800C6A8DC /* SwiftUICompatibility.swift in Sources */ = {isa = PBXBuildFile; fileRef = 32CBA77F25E4D7D800C6A8DC /* SwiftUICompatibility.swift */; };
32CBA78725E4D7D800C6A8DC /* SwiftUICompatibility.swift in Sources */ = {isa = PBXBuildFile; fileRef = 32CBA77F25E4D7D800C6A8DC /* SwiftUICompatibility.swift */; };
32D26A022446B546005905DA /* Image.swift in Sources */ = {isa = PBXBuildFile; fileRef = 32D26A012446B546005905DA /* Image.swift */; };
32D26A032446B546005905DA /* Image.swift in Sources */ = {isa = PBXBuildFile; fileRef = 32D26A012446B546005905DA /* Image.swift */; };
32D26A042446B546005905DA /* Image.swift in Sources */ = {isa = PBXBuildFile; fileRef = 32D26A012446B546005905DA /* Image.swift */; };
32D26A052446B546005905DA /* Image.swift in Sources */ = {isa = PBXBuildFile; fileRef = 32D26A012446B546005905DA /* Image.swift */; };
32ED4826242A13030053338E /* ImageManagerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 32ED4825242A13030053338E /* ImageManagerTests.swift */; };
32ED4827242A13030053338E /* ImageManagerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 32ED4825242A13030053338E /* ImageManagerTests.swift */; };
32ED4828242A13030053338E /* ImageManagerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 32ED4825242A13030053338E /* ImageManagerTests.swift */; };
/* End PBXBuildFile section */
/* Begin PBXContainerItemProxy section */
3211F84A23DE984D00FC757F /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 32C43DC322FD540D00BE87F5 /* Project object */;
proxyType = 1;
remoteGlobalIDString = 32C43DCB22FD540D00BE87F5;
remoteInfo = SDWebImageSwiftUI;
};
321C1D4123DEC17D009CF62A /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 32C43DC322FD540D00BE87F5 /* Project object */;
proxyType = 1;
remoteGlobalIDString = 32C43DF322FD57FD00BE87F5;
remoteInfo = "SDWebImageSwiftUI macOS";
};
321C1D5023DEC185009CF62A /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 32C43DC322FD540D00BE87F5 /* Project object */;
proxyType = 1;
remoteGlobalIDString = 32C43E0022FD581400BE87F5;
remoteInfo = "SDWebImageSwiftUI tvOS";
};
/* End PBXContainerItemProxy section */
/* Begin PBXFileReference section */
3211F84423DE984D00FC757F /* SDWebImageSwiftUITests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = SDWebImageSwiftUITests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
3211F84623DE984D00FC757F /* AnimatedImageTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AnimatedImageTests.swift; sourceTree = "<group>"; };
3211F84823DE984D00FC757F /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
3211F84F23DE98E300FC757F /* WebImageTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WebImageTests.swift; sourceTree = "<group>"; };
3211F85423DE9D2700FC757F /* Images.bundle */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.plug-in"; path = Images.bundle; sourceTree = "<group>"; };
321C1D3B23DEC17D009CF62A /* SDWebImageSwiftUITests macOS.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "SDWebImageSwiftUITests macOS.xctest"; sourceTree = BUILT_PRODUCTS_DIR; };
321C1D4A23DEC185009CF62A /* SDWebImageSwiftUITests tvOS.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "SDWebImageSwiftUITests tvOS.xctest"; sourceTree = BUILT_PRODUCTS_DIR; };
322E0F4723E57F09006836DC /* TestUtils.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TestUtils.swift; sourceTree = "<group>"; };
326B84812363350C0011BDFB /* Indicator.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Indicator.swift; sourceTree = "<group>"; };
326B8486236335110011BDFB /* ActivityIndicator.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ActivityIndicator.swift; sourceTree = "<group>"; };
326B848B236335400011BDFB /* ProgressIndicator.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ProgressIndicator.swift; sourceTree = "<group>"; };
326E480923431C0F00C633E9 /* ImageViewWrapper.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ImageViewWrapper.swift; sourceTree = "<group>"; };
32B933E423659A1900BB7CAD /* Transition.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Transition.swift; sourceTree = "<group>"; };
32BC086F28D23D35002451BD /* StateObject.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = StateObject.swift; sourceTree = "<group>"; };
32BC087028D23D35002451BD /* OnChange.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = OnChange.swift; sourceTree = "<group>"; };
32BC087128D23D35002451BD /* Overlay.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Overlay.swift; sourceTree = "<group>"; };
32BC087228D23D35002451BD /* Backport.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Backport.swift; sourceTree = "<group>"; };
32BD9C4623E03B08008D5F6A /* IndicatorTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IndicatorTests.swift; sourceTree = "<group>"; };
32C43DCC22FD540D00BE87F5 /* SDWebImageSwiftUI.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = SDWebImageSwiftUI.framework; sourceTree = BUILT_PRODUCTS_DIR; };
32C43DDC22FD54C600BE87F5 /* ImageManager.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ImageManager.swift; sourceTree = "<group>"; };
@ -146,42 +108,11 @@
32C43E2D22FD586E00BE87F5 /* SDWebImage.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SDWebImage.framework; path = Carthage/Build/watchOS/SDWebImage.framework; sourceTree = "<group>"; };
32C43E3122FD5DE100BE87F5 /* SDWebImageSwiftUI.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SDWebImageSwiftUI.swift; sourceTree = "<group>"; };
32CBA77E25E4D7D800C6A8DC /* ImagePlayer.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ImagePlayer.swift; sourceTree = "<group>"; };
32CBA77F25E4D7D800C6A8DC /* SwiftUICompatibility.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SwiftUICompatibility.swift; sourceTree = "<group>"; };
32D26A012446B546005905DA /* Image.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Image.swift; sourceTree = "<group>"; };
32ED4825242A13030053338E /* ImageManagerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ImageManagerTests.swift; sourceTree = "<group>"; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
3211F84123DE984D00FC757F /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
321C1D3323DEA28E009CF62A /* SDWebImage.framework in Frameworks */,
3211F84923DE984D00FC757F /* SDWebImageSwiftUI.framework in Frameworks */,
3211F85323DE996700FC757F /* ViewInspector in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
321C1D3823DEC17D009CF62A /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
321C1D5B23DEC219009CF62A /* SDWebImage.framework in Frameworks */,
321C1D4023DEC17D009CF62A /* SDWebImageSwiftUI.framework in Frameworks */,
321C1D5A23DEC207009CF62A /* ViewInspector in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
321C1D4723DEC185009CF62A /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
321C1D5E23DEC22D009CF62A /* SDWebImage.framework in Frameworks */,
321C1D4F23DEC185009CF62A /* SDWebImageSwiftUI.framework in Frameworks */,
321C1D6023DEC231009CF62A /* ViewInspector in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
32C43DC922FD540D00BE87F5 /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
@ -249,6 +180,17 @@
path = Transition;
sourceTree = "<group>";
};
32BC086E28D23D35002451BD /* Backports */ = {
isa = PBXGroup;
children = (
32BC086F28D23D35002451BD /* StateObject.swift */,
32BC087028D23D35002451BD /* OnChange.swift */,
32BC087128D23D35002451BD /* Overlay.swift */,
32BC087228D23D35002451BD /* Backport.swift */,
);
path = Backports;
sourceTree = "<group>";
};
32C43DC222FD540D00BE87F5 = {
isa = PBXGroup;
children = (
@ -268,9 +210,6 @@
32C43DF422FD57FD00BE87F5 /* SDWebImageSwiftUI.framework */,
32C43E0122FD581400BE87F5 /* SDWebImageSwiftUI.framework */,
32C43E0E22FD581C00BE87F5 /* SDWebImageSwiftUI.framework */,
3211F84423DE984D00FC757F /* SDWebImageSwiftUITests.xctest */,
321C1D3B23DEC17D009CF62A /* SDWebImageSwiftUITests macOS.xctest */,
321C1D4A23DEC185009CF62A /* SDWebImageSwiftUITests tvOS.xctest */,
);
name = Products;
sourceTree = "<group>";
@ -288,9 +227,9 @@
children = (
32B933E323659A0700BB7CAD /* Transition */,
326099472362E09E006EBB22 /* Indicator */,
32BC086E28D23D35002451BD /* Backports */,
32C43DDC22FD54C600BE87F5 /* ImageManager.swift */,
32CBA77E25E4D7D800C6A8DC /* ImagePlayer.swift */,
32CBA77F25E4D7D800C6A8DC /* SwiftUICompatibility.swift */,
32C43DDE22FD54C600BE87F5 /* WebImage.swift */,
32C43DDF22FD54C600BE87F5 /* AnimatedImage.swift */,
32C43E3122FD5DE100BE87F5 /* SDWebImageSwiftUI.swift */,
@ -349,72 +288,6 @@
/* End PBXHeadersBuildPhase section */
/* Begin PBXNativeTarget section */
3211F84323DE984D00FC757F /* SDWebImageSwiftUITests */ = {
isa = PBXNativeTarget;
buildConfigurationList = 3211F84E23DE984D00FC757F /* Build configuration list for PBXNativeTarget "SDWebImageSwiftUITests" */;
buildPhases = (
3211F84023DE984D00FC757F /* Sources */,
3211F84123DE984D00FC757F /* Frameworks */,
3211F84223DE984D00FC757F /* Resources */,
321C1D3523DEA309009CF62A /* ShellScript */,
);
buildRules = (
);
dependencies = (
3211F84B23DE984D00FC757F /* PBXTargetDependency */,
);
name = SDWebImageSwiftUITests;
packageProductDependencies = (
3211F85223DE996700FC757F /* ViewInspector */,
);
productName = SDWebImageSwiftUITests;
productReference = 3211F84423DE984D00FC757F /* SDWebImageSwiftUITests.xctest */;
productType = "com.apple.product-type.bundle.unit-test";
};
321C1D3A23DEC17D009CF62A /* SDWebImageSwiftUITests macOS */ = {
isa = PBXNativeTarget;
buildConfigurationList = 321C1D4323DEC17D009CF62A /* Build configuration list for PBXNativeTarget "SDWebImageSwiftUITests macOS" */;
buildPhases = (
321C1D3723DEC17D009CF62A /* Sources */,
321C1D3823DEC17D009CF62A /* Frameworks */,
321C1D3923DEC17D009CF62A /* Resources */,
321C1D5523DEC1A9009CF62A /* ShellScript */,
);
buildRules = (
);
dependencies = (
321C1D4223DEC17D009CF62A /* PBXTargetDependency */,
);
name = "SDWebImageSwiftUITests macOS";
packageProductDependencies = (
321C1D5923DEC207009CF62A /* ViewInspector */,
);
productName = "SDWebImageSwiftUITests macOS";
productReference = 321C1D3B23DEC17D009CF62A /* SDWebImageSwiftUITests macOS.xctest */;
productType = "com.apple.product-type.bundle.unit-test";
};
321C1D4923DEC185009CF62A /* SDWebImageSwiftUITests tvOS */ = {
isa = PBXNativeTarget;
buildConfigurationList = 321C1D5223DEC185009CF62A /* Build configuration list for PBXNativeTarget "SDWebImageSwiftUITests tvOS" */;
buildPhases = (
321C1D4623DEC185009CF62A /* Sources */,
321C1D4723DEC185009CF62A /* Frameworks */,
321C1D4823DEC185009CF62A /* Resources */,
321C1D5623DEC1C7009CF62A /* ShellScript */,
);
buildRules = (
);
dependencies = (
321C1D5123DEC185009CF62A /* PBXTargetDependency */,
);
name = "SDWebImageSwiftUITests tvOS";
packageProductDependencies = (
321C1D5F23DEC231009CF62A /* ViewInspector */,
);
productName = "SDWebImageSwiftUITests tvOS";
productReference = 321C1D4A23DEC185009CF62A /* SDWebImageSwiftUITests tvOS.xctest */;
productType = "com.apple.product-type.bundle.unit-test";
};
32C43DCB22FD540D00BE87F5 /* SDWebImageSwiftUI */ = {
isa = PBXNativeTarget;
buildConfigurationList = 32C43DD422FD540D00BE87F5 /* Build configuration list for PBXNativeTarget "SDWebImageSwiftUI" */;
@ -497,15 +370,6 @@
LastUpgradeCheck = 1100;
ORGANIZATIONNAME = SDWebImage;
TargetAttributes = {
3211F84323DE984D00FC757F = {
CreatedOnToolsVersion = 11.3.1;
};
321C1D3A23DEC17D009CF62A = {
CreatedOnToolsVersion = 11.3.1;
};
321C1D4923DEC185009CF62A = {
CreatedOnToolsVersion = 11.3.1;
};
32C43DCB22FD540D00BE87F5 = {
CreatedOnToolsVersion = 11.0;
LastSwiftMigration = 1100;
@ -534,7 +398,6 @@
);
mainGroup = 32C43DC222FD540D00BE87F5;
packageReferences = (
3211F85123DE996700FC757F /* XCRemoteSwiftPackageReference "ViewInspector" */,
);
productRefGroup = 32C43DCD22FD540D00BE87F5 /* Products */;
projectDirPath = "";
@ -544,38 +407,11 @@
32C43DF322FD57FD00BE87F5 /* SDWebImageSwiftUI macOS */,
32C43E0022FD581400BE87F5 /* SDWebImageSwiftUI tvOS */,
32C43E0D22FD581C00BE87F5 /* SDWebImageSwiftUI watchOS */,
3211F84323DE984D00FC757F /* SDWebImageSwiftUITests */,
321C1D3A23DEC17D009CF62A /* SDWebImageSwiftUITests macOS */,
321C1D4923DEC185009CF62A /* SDWebImageSwiftUITests tvOS */,
);
};
/* End PBXProject section */
/* Begin PBXResourcesBuildPhase section */
3211F84223DE984D00FC757F /* Resources */ = {
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
321C1D3623DEA9E8009CF62A /* Images.bundle in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
321C1D3923DEC17D009CF62A /* Resources */ = {
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
321C1D5C23DEC221009CF62A /* Images.bundle in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
321C1D4823DEC185009CF62A /* Resources */ = {
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
321C1D5D23DEC222009CF62A /* Images.bundle in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
32C43DCA22FD540D00BE87F5 /* Resources */ = {
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
@ -606,110 +442,16 @@
};
/* End PBXResourcesBuildPhase section */
/* Begin PBXShellScriptBuildPhase section */
321C1D3523DEA309009CF62A /* ShellScript */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputFileListPaths = (
);
inputPaths = (
"$(SRCROOT)/Carthage/Build/iOS/SDWebImage.framework",
);
outputFileListPaths = (
);
outputPaths = (
"$(BUILT_PRODUCTS_DIR)/$(FRAMEWORKS_FOLDER_PATH)/SDWebImage.framework",
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "/usr/local/bin/carthage copy-frameworks\n";
};
321C1D5523DEC1A9009CF62A /* ShellScript */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputFileListPaths = (
);
inputPaths = (
"$(SRCROOT)/Carthage/Build/Mac/SDWebImage.framework",
);
outputFileListPaths = (
);
outputPaths = (
"$(BUILT_PRODUCTS_DIR)/$(FRAMEWORKS_FOLDER_PATH)/SDWebImage.framework",
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "/usr/local/bin/carthage copy-frameworks\n";
};
321C1D5623DEC1C7009CF62A /* ShellScript */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputFileListPaths = (
);
inputPaths = (
"$(SRCROOT)/Carthage/Build/tvOS/SDWebImage.framework",
);
outputFileListPaths = (
);
outputPaths = (
"$(BUILT_PRODUCTS_DIR)/$(FRAMEWORKS_FOLDER_PATH)/SDWebImage.framework",
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "/usr/local/bin/carthage copy-frameworks\n";
};
/* End PBXShellScriptBuildPhase section */
/* Begin PBXSourcesBuildPhase section */
3211F84023DE984D00FC757F /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
3211F85023DE98E300FC757F /* WebImageTests.swift in Sources */,
32BD9C4723E03B08008D5F6A /* IndicatorTests.swift in Sources */,
3211F84723DE984D00FC757F /* AnimatedImageTests.swift in Sources */,
322E0F4823E57F09006836DC /* TestUtils.swift in Sources */,
32ED4826242A13030053338E /* ImageManagerTests.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
321C1D3723DEC17D009CF62A /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
321C1D6B23DEDB98009CF62A /* WebImageTests.swift in Sources */,
32BD9C4823E03B08008D5F6A /* IndicatorTests.swift in Sources */,
321C1D6A23DEDB98009CF62A /* AnimatedImageTests.swift in Sources */,
322E0F4923E57F09006836DC /* TestUtils.swift in Sources */,
32ED4827242A13030053338E /* ImageManagerTests.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
321C1D4623DEC185009CF62A /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
321C1D6D23DEDB98009CF62A /* WebImageTests.swift in Sources */,
32BD9C4923E03B08008D5F6A /* IndicatorTests.swift in Sources */,
321C1D6C23DEDB98009CF62A /* AnimatedImageTests.swift in Sources */,
322E0F4A23E57F09006836DC /* TestUtils.swift in Sources */,
32ED4828242A13030053338E /* ImageManagerTests.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
32C43DC822FD540D00BE87F5 /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
32BC087328D23D35002451BD /* StateObject.swift in Sources */,
32BC087728D23D35002451BD /* OnChange.swift in Sources */,
32B933E523659A1900BB7CAD /* Transition.swift in Sources */,
32CBA78025E4D7D800C6A8DC /* ImagePlayer.swift in Sources */,
32CBA78425E4D7D800C6A8DC /* SwiftUICompatibility.swift in Sources */,
32BC087B28D23D35002451BD /* Overlay.swift in Sources */,
32C43E1722FD583700BE87F5 /* WebImage.swift in Sources */,
326B848C236335400011BDFB /* ProgressIndicator.swift in Sources */,
326B84822363350C0011BDFB /* Indicator.swift in Sources */,
@ -719,6 +461,7 @@
32C43E1622FD583700BE87F5 /* ImageManager.swift in Sources */,
32C43E1822FD583700BE87F5 /* AnimatedImage.swift in Sources */,
32D26A022446B546005905DA /* Image.swift in Sources */,
32BC087F28D23D35002451BD /* Backport.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@ -726,9 +469,11 @@
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
32BC087428D23D35002451BD /* StateObject.swift in Sources */,
32BC087828D23D35002451BD /* OnChange.swift in Sources */,
32B933E623659A1900BB7CAD /* Transition.swift in Sources */,
32CBA78125E4D7D800C6A8DC /* ImagePlayer.swift in Sources */,
32CBA78525E4D7D800C6A8DC /* SwiftUICompatibility.swift in Sources */,
32BC087C28D23D35002451BD /* Overlay.swift in Sources */,
32C43E1A22FD583700BE87F5 /* WebImage.swift in Sources */,
326B848D236335400011BDFB /* ProgressIndicator.swift in Sources */,
326B84832363350C0011BDFB /* Indicator.swift in Sources */,
@ -738,6 +483,7 @@
32C43E1922FD583700BE87F5 /* ImageManager.swift in Sources */,
32C43E1B22FD583700BE87F5 /* AnimatedImage.swift in Sources */,
32D26A032446B546005905DA /* Image.swift in Sources */,
32BC088028D23D35002451BD /* Backport.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@ -745,9 +491,11 @@
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
32BC087528D23D35002451BD /* StateObject.swift in Sources */,
32BC087928D23D35002451BD /* OnChange.swift in Sources */,
32B933E723659A1900BB7CAD /* Transition.swift in Sources */,
32CBA78225E4D7D800C6A8DC /* ImagePlayer.swift in Sources */,
32CBA78625E4D7D800C6A8DC /* SwiftUICompatibility.swift in Sources */,
32BC087D28D23D35002451BD /* Overlay.swift in Sources */,
32C43E1D22FD583800BE87F5 /* WebImage.swift in Sources */,
326B848E236335400011BDFB /* ProgressIndicator.swift in Sources */,
326B84842363350C0011BDFB /* Indicator.swift in Sources */,
@ -757,6 +505,7 @@
32C43E1C22FD583800BE87F5 /* ImageManager.swift in Sources */,
32C43E1E22FD583800BE87F5 /* AnimatedImage.swift in Sources */,
32D26A042446B546005905DA /* Image.swift in Sources */,
32BC088128D23D35002451BD /* Backport.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@ -764,9 +513,11 @@
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
32BC087628D23D35002451BD /* StateObject.swift in Sources */,
32BC087A28D23D35002451BD /* OnChange.swift in Sources */,
32B933E823659A1900BB7CAD /* Transition.swift in Sources */,
32CBA78325E4D7D800C6A8DC /* ImagePlayer.swift in Sources */,
32CBA78725E4D7D800C6A8DC /* SwiftUICompatibility.swift in Sources */,
32BC087E28D23D35002451BD /* Overlay.swift in Sources */,
32C43E2022FD583800BE87F5 /* WebImage.swift in Sources */,
326B848F236335400011BDFB /* ProgressIndicator.swift in Sources */,
326B84852363350C0011BDFB /* Indicator.swift in Sources */,
@ -776,166 +527,13 @@
32C43E1F22FD583800BE87F5 /* ImageManager.swift in Sources */,
32C43E2122FD583800BE87F5 /* AnimatedImage.swift in Sources */,
32D26A052446B546005905DA /* Image.swift in Sources */,
32BC088228D23D35002451BD /* Backport.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXSourcesBuildPhase section */
/* Begin PBXTargetDependency section */
3211F84B23DE984D00FC757F /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
target = 32C43DCB22FD540D00BE87F5 /* SDWebImageSwiftUI */;
targetProxy = 3211F84A23DE984D00FC757F /* PBXContainerItemProxy */;
};
321C1D4223DEC17D009CF62A /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
target = 32C43DF322FD57FD00BE87F5 /* SDWebImageSwiftUI macOS */;
targetProxy = 321C1D4123DEC17D009CF62A /* PBXContainerItemProxy */;
};
321C1D5123DEC185009CF62A /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
target = 32C43E0022FD581400BE87F5 /* SDWebImageSwiftUI tvOS */;
targetProxy = 321C1D5023DEC185009CF62A /* PBXContainerItemProxy */;
};
/* End PBXTargetDependency section */
/* Begin XCBuildConfiguration section */
3211F84C23DE984D00FC757F /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
BUILD_LIBRARY_FOR_DISTRIBUTION = NO;
CODE_SIGN_STYLE = Automatic;
FRAMEWORK_SEARCH_PATHS = (
"$(inherited)",
"$(PROJECT_DIR)/Carthage/Build/iOS",
);
INFOPLIST_FILE = Tests/Info.plist;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
"@loader_path/Frameworks",
);
PRODUCT_BUNDLE_IDENTIFIER = com.dreampiggy.SDWebImageSwiftUITests;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_VERSION = 5.0;
TARGETED_DEVICE_FAMILY = "1,2";
};
name = Debug;
};
3211F84D23DE984D00FC757F /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
BUILD_LIBRARY_FOR_DISTRIBUTION = NO;
CODE_SIGN_STYLE = Automatic;
FRAMEWORK_SEARCH_PATHS = (
"$(inherited)",
"$(PROJECT_DIR)/Carthage/Build/iOS",
);
INFOPLIST_FILE = Tests/Info.plist;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
"@loader_path/Frameworks",
);
PRODUCT_BUNDLE_IDENTIFIER = com.dreampiggy.SDWebImageSwiftUITests;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_VERSION = 5.0;
TARGETED_DEVICE_FAMILY = "1,2";
};
name = Release;
};
321C1D4423DEC17D009CF62A /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
BUILD_LIBRARY_FOR_DISTRIBUTION = NO;
CODE_SIGN_STYLE = Automatic;
COMBINE_HIDPI_IMAGES = YES;
FRAMEWORK_SEARCH_PATHS = (
"$(inherited)",
"$(PROJECT_DIR)/Carthage/Build/Mac",
);
INFOPLIST_FILE = Tests/Info.plist;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/../Frameworks",
"@loader_path/../Frameworks",
);
PRODUCT_BUNDLE_IDENTIFIER = "com.dreampiggy.SDWebImageSwiftUITests-macOS";
PRODUCT_NAME = "$(TARGET_NAME)";
SDKROOT = macosx;
SWIFT_VERSION = 5.0;
};
name = Debug;
};
321C1D4523DEC17D009CF62A /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
BUILD_LIBRARY_FOR_DISTRIBUTION = NO;
CODE_SIGN_STYLE = Automatic;
COMBINE_HIDPI_IMAGES = YES;
FRAMEWORK_SEARCH_PATHS = (
"$(inherited)",
"$(PROJECT_DIR)/Carthage/Build/Mac",
);
INFOPLIST_FILE = Tests/Info.plist;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/../Frameworks",
"@loader_path/../Frameworks",
);
PRODUCT_BUNDLE_IDENTIFIER = "com.dreampiggy.SDWebImageSwiftUITests-macOS";
PRODUCT_NAME = "$(TARGET_NAME)";
SDKROOT = macosx;
SWIFT_VERSION = 5.0;
};
name = Release;
};
321C1D5323DEC185009CF62A /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
BUILD_LIBRARY_FOR_DISTRIBUTION = NO;
CODE_SIGN_STYLE = Automatic;
FRAMEWORK_SEARCH_PATHS = (
"$(inherited)",
"$(PROJECT_DIR)/Carthage/Build/tvOS",
);
INFOPLIST_FILE = Tests/Info.plist;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
"@loader_path/Frameworks",
);
PRODUCT_BUNDLE_IDENTIFIER = "com.dreampiggy.SDWebImageSwiftUITests-tvOS";
PRODUCT_NAME = "$(TARGET_NAME)";
SDKROOT = appletvos;
SWIFT_VERSION = 5.0;
TARGETED_DEVICE_FAMILY = 3;
};
name = Debug;
};
321C1D5423DEC185009CF62A /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
BUILD_LIBRARY_FOR_DISTRIBUTION = NO;
CODE_SIGN_STYLE = Automatic;
FRAMEWORK_SEARCH_PATHS = (
"$(inherited)",
"$(PROJECT_DIR)/Carthage/Build/tvOS",
);
INFOPLIST_FILE = Tests/Info.plist;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
"@loader_path/Frameworks",
);
PRODUCT_BUNDLE_IDENTIFIER = "com.dreampiggy.SDWebImageSwiftUITests-tvOS";
PRODUCT_NAME = "$(TARGET_NAME)";
SDKROOT = appletvos;
SWIFT_VERSION = 5.0;
TARGETED_DEVICE_FAMILY = 3;
};
name = Release;
};
32C43DD222FD540D00BE87F5 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
@ -1319,33 +917,6 @@
/* End XCBuildConfiguration section */
/* Begin XCConfigurationList section */
3211F84E23DE984D00FC757F /* Build configuration list for PBXNativeTarget "SDWebImageSwiftUITests" */ = {
isa = XCConfigurationList;
buildConfigurations = (
3211F84C23DE984D00FC757F /* Debug */,
3211F84D23DE984D00FC757F /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
321C1D4323DEC17D009CF62A /* Build configuration list for PBXNativeTarget "SDWebImageSwiftUITests macOS" */ = {
isa = XCConfigurationList;
buildConfigurations = (
321C1D4423DEC17D009CF62A /* Debug */,
321C1D4523DEC17D009CF62A /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
321C1D5223DEC185009CF62A /* Build configuration list for PBXNativeTarget "SDWebImageSwiftUITests tvOS" */ = {
isa = XCConfigurationList;
buildConfigurations = (
321C1D5323DEC185009CF62A /* Debug */,
321C1D5423DEC185009CF62A /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
32C43DC622FD540D00BE87F5 /* Build configuration list for PBXProject "SDWebImageSwiftUI" */ = {
isa = XCConfigurationList;
buildConfigurations = (
@ -1392,35 +963,6 @@
defaultConfigurationName = Release;
};
/* End XCConfigurationList section */
/* Begin XCRemoteSwiftPackageReference section */
3211F85123DE996700FC757F /* XCRemoteSwiftPackageReference "ViewInspector" */ = {
isa = XCRemoteSwiftPackageReference;
repositoryURL = "https://github.com/nalexn/ViewInspector.git";
requirement = {
kind = upToNextMajorVersion;
minimumVersion = 0.3.11;
};
};
/* End XCRemoteSwiftPackageReference section */
/* Begin XCSwiftPackageProductDependency section */
3211F85223DE996700FC757F /* ViewInspector */ = {
isa = XCSwiftPackageProductDependency;
package = 3211F85123DE996700FC757F /* XCRemoteSwiftPackageReference "ViewInspector" */;
productName = ViewInspector;
};
321C1D5923DEC207009CF62A /* ViewInspector */ = {
isa = XCSwiftPackageProductDependency;
package = 3211F85123DE996700FC757F /* XCRemoteSwiftPackageReference "ViewInspector" */;
productName = ViewInspector;
};
321C1D5F23DEC231009CF62A /* ViewInspector */ = {
isa = XCSwiftPackageProductDependency;
package = 3211F85123DE996700FC757F /* XCRemoteSwiftPackageReference "ViewInspector" */;
productName = ViewInspector;
};
/* End XCSwiftPackageProductDependency section */
};
rootObject = 32C43DC322FD540D00BE87F5 /* Project object */;
}

View File

@ -1,16 +0,0 @@
{
"object": {
"pins": [
{
"package": "ViewInspector",
"repositoryURL": "https://github.com/nalexn/ViewInspector.git",
"state": {
"branch": null,
"revision": "7d55eb940242512aad2bf28db354d09d5de43893",
"version": "0.3.11"
}
}
]
},
"version": 1
}

View File

@ -2,7 +2,7 @@
<Workspace
version = "1.0">
<FileRef
location = "group:SDWebImageSwiftUI.xcodeproj">
location = "group:Example/SDWebImageSwiftUI.xcodeproj">
</FileRef>
<FileRef
location = "group:Pods/Pods.xcodeproj">

View File

@ -20,6 +20,8 @@ public final class AnimatedImageCoordinator: NSObject {
/// Any user-provided info stored into coordinator, such as status value used for coordinator
public var userInfo: [AnyHashable : Any]?
var imageLoading = AnimatedLoadingModel()
}
/// Data Binding Object, only properties in this object can support changes from user with @State and refresh
@ -39,7 +41,7 @@ final class AnimatedImageModel : ObservableObject {
/// Loading Binding Object, only properties in this object can support changes from user with @State and refresh
@available(iOS 13.0, OSX 10.15, tvOS 13.0, watchOS 6.0, *)
final class AnimatedLoadingModel : ObservableObject, IndicatorReportable {
final class AnimatedLoadingModel : ObservableObject {
@Published var image: PlatformImage? // loaded image, note when progressive loading, this will published multiple times with different partial image
@Published var isLoading: Bool = false // whether network is loading or cache is querying, should only be used for indicator binding
@Published var progress: Double = 0 // network progress, should only be used for indicator binding
@ -99,12 +101,22 @@ final class AnimatedImageConfiguration: ObservableObject {
/// A Image View type to load image from url, data or bundle. Supports animated and static image format.
@available(iOS 13.0, OSX 10.15, tvOS 13.0, watchOS 6.0, *)
public struct AnimatedImage : PlatformViewRepresentable {
@ObservedObject var imageModel = AnimatedImageModel()
@ObservedObject var imageLoading = AnimatedLoadingModel()
@SwiftUI.StateObject var imageModel_SwiftUI = AnimatedImageModel()
@Backport.StateObject var imageModel_Backport = AnimatedImageModel()
var imageModel: AnimatedImageModel {
if #available(iOS 14.0, macOS 11.0, tvOS 14.0, watchOS 7.0, *) {
return imageModel_SwiftUI
} else {
return imageModel_Backport
}
}
@ObservedObject var imageHandler = AnimatedImageHandler()
@ObservedObject var imageLayout = AnimatedImageLayout()
@ObservedObject var imageConfiguration = AnimatedImageConfiguration()
/// A observed object to pass through the image manager loading status to indicator
@ObservedObject var indicatorStatus = IndicatorStatus()
static var viewDestroyBlock: ((PlatformView, Coordinator) -> Void)?
/// A Binding to control the animation. You can bind external logic to control the animation status.
@ -127,10 +139,11 @@ public struct AnimatedImage : PlatformViewRepresentable {
/// - Parameter context: A context contains different options to perform specify changes or processes, see `SDWebImageContextOption`. This hold the extra objects which `options` enum can not hold.
/// - Parameter isAnimating: The binding for animation control
public init(url: URL?, options: SDWebImageOptions = [], context: [SDWebImageContextOption : Any]? = nil, isAnimating: Binding<Bool>) {
self._isAnimating = isAnimating
self.imageModel.url = url
self.imageModel.webOptions = options
self.imageModel.webContext = context
let imageModel = AnimatedImageModel()
imageModel.url = url
imageModel.webOptions = options
imageModel.webContext = context
self.init(imageModel: imageModel, isAnimating: isAnimating)
}
/// Create an animated image with name and bundle.
@ -147,9 +160,10 @@ public struct AnimatedImage : PlatformViewRepresentable {
/// - Parameter bundle: The bundle contains image
/// - Parameter isAnimating: The binding for animation control
public init(name: String, bundle: Bundle? = nil, isAnimating: Binding<Bool>) {
self._isAnimating = isAnimating
self.imageModel.name = name
self.imageModel.bundle = bundle
let imageModel = AnimatedImageModel()
imageModel.name = name
imageModel.bundle = bundle
self.init(imageModel: imageModel, isAnimating: isAnimating)
}
/// Create an animated image with data and scale.
@ -164,9 +178,19 @@ public struct AnimatedImage : PlatformViewRepresentable {
/// - Parameter scale: The scale factor
/// - Parameter isAnimating: The binding for animation control
public init(data: Data, scale: CGFloat = 1, isAnimating: Binding<Bool>) {
let imageModel = AnimatedImageModel()
imageModel.data = data
imageModel.scale = scale
self.init(imageModel: imageModel, isAnimating: isAnimating)
}
init(imageModel: AnimatedImageModel, isAnimating: Binding<Bool>) {
self._isAnimating = isAnimating
self.imageModel.data = data
self.imageModel.scale = scale
if #available(iOS 14.0, macOS 11.0, tvOS 14.0, watchOS 7.0, *) {
_imageModel_SwiftUI = SwiftUI.StateObject(wrappedValue: imageModel)
} else {
_imageModel_Backport = Backport.StateObject(wrappedValue: imageModel)
}
}
#if os(macOS)
@ -182,11 +206,11 @@ public struct AnimatedImage : PlatformViewRepresentable {
}
#if os(macOS)
public func makeNSView(context: NSViewRepresentableContext<AnimatedImage>) -> AnimatedImageViewWrapper {
public func makeNSView(context: Context) -> AnimatedImageViewWrapper {
makeView(context: context)
}
public func updateNSView(_ nsView: AnimatedImageViewWrapper, context: NSViewRepresentableContext<AnimatedImage>) {
public func updateNSView(_ nsView: AnimatedImageViewWrapper, context: Context) {
updateView(nsView, context: context)
}
@ -194,11 +218,11 @@ public struct AnimatedImage : PlatformViewRepresentable {
dismantleView(nsView, coordinator: coordinator)
}
#elseif os(iOS) || os(tvOS)
public func makeUIView(context: UIViewRepresentableContext<AnimatedImage>) -> AnimatedImageViewWrapper {
public func makeUIView(context: Context) -> AnimatedImageViewWrapper {
makeView(context: context)
}
public func updateUIView(_ uiView: AnimatedImageViewWrapper, context: UIViewRepresentableContext<AnimatedImage>) {
public func updateUIView(_ uiView: AnimatedImageViewWrapper, context: Context) {
updateView(uiView, context: context)
}
@ -228,16 +252,16 @@ public struct AnimatedImage : PlatformViewRepresentable {
}
func loadImage(_ view: AnimatedImageViewWrapper, context: Context) {
self.imageLoading.isLoading = true
let options = imageModel.webOptions
if options.contains(.delayPlaceholder) {
context.coordinator.imageLoading.isLoading = true
let webOptions = imageModel.webOptions
if webOptions.contains(.delayPlaceholder) {
self.imageConfiguration.placeholderView?.isHidden = true
} else {
self.imageConfiguration.placeholderView?.isHidden = false
}
var context = imageModel.webContext ?? [:]
context[.animatedImageClass] = SDAnimatedImage.self
view.wrapped.sd_internalSetImage(with: imageModel.url, placeholderImage: imageConfiguration.placeholder, options: options, context: context, setImageBlock: nil, progress: { (receivedSize, expectedSize, _) in
var webContext = imageModel.webContext ?? [:]
webContext[.animatedImageClass] = SDAnimatedImage.self
view.wrapped.sd_internalSetImage(with: imageModel.url, placeholderImage: imageConfiguration.placeholder, options: webOptions, context: webContext, setImageBlock: nil, progress: { (receivedSize, expectedSize, _) in
let progress: Double
if (expectedSize > 0) {
progress = Double(receivedSize) / Double(expectedSize)
@ -245,7 +269,7 @@ public struct AnimatedImage : PlatformViewRepresentable {
progress = 0
}
DispatchQueue.main.async {
self.imageLoading.progress = progress
context.coordinator.imageLoading.progress = progress
}
self.imageHandler.progressBlock?(receivedSize, expectedSize)
}) { (image, data, error, cacheType, finished, _) in
@ -264,9 +288,9 @@ public struct AnimatedImage : PlatformViewRepresentable {
}
}
}
self.imageLoading.image = image
self.imageLoading.isLoading = false
self.imageLoading.progress = 1
context.coordinator.imageLoading.image = image
context.coordinator.imageLoading.isLoading = false
context.coordinator.imageLoading.progress = 1
if let image = image {
self.imageConfiguration.placeholderView?.isHidden = true
self.imageHandler.successBlock?(image, data, cacheType)
@ -288,30 +312,30 @@ public struct AnimatedImage : PlatformViewRepresentable {
func updateView(_ view: AnimatedImageViewWrapper, context: Context) {
// Refresh image, imageModel is the Source of Truth, switch the type
// Although we have Source of Truth, we can check the previous value, to avoid re-generate SDAnimatedImage, which is performance-cost.
if let name = imageModel.name, name != imageLoading.imageName {
if let name = imageModel.name, name != context.coordinator.imageLoading.imageName {
#if os(macOS)
let image = SDAnimatedImage(named: name, in: imageModel.bundle)
#else
let image = SDAnimatedImage(named: name, in: imageModel.bundle, compatibleWith: nil)
#endif
imageLoading.imageName = name
context.coordinator.imageLoading.imageName = name
view.wrapped.image = image
} else if let data = imageModel.data, data != imageLoading.imageData {
} else if let data = imageModel.data, data != context.coordinator.imageLoading.imageData {
let image = SDAnimatedImage(data: data, scale: imageModel.scale)
imageLoading.imageData = data
context.coordinator.imageLoading.imageData = data
view.wrapped.image = image
} else if let url = imageModel.url {
// Determine if image already been loaded and URL is match
var shouldLoad: Bool
if url != imageLoading.imageURL {
if url != context.coordinator.imageLoading.imageURL {
// Change the URL, need new loading
shouldLoad = true
imageLoading.imageURL = url
context.coordinator.imageLoading.imageURL = url
} else {
// Same URL, check if already loaded
if imageLoading.isLoading {
if context.coordinator.imageLoading.isLoading {
shouldLoad = false
} else if let image = imageLoading.image {
} else if let image = context.coordinator.imageLoading.image {
shouldLoad = false
view.wrapped.image = image
} else {
@ -831,7 +855,7 @@ extension AnimatedImage {
/// Associate a indicator when loading image with url
/// - Parameter indicator: The indicator type, see `Indicator`
public func indicator<T>(_ indicator: Indicator<T>) -> some View where T : View {
return self.modifier(IndicatorViewModifier(reporter: self.imageLoading, indicator: indicator))
return self.modifier(IndicatorViewModifier(status: indicatorStatus, indicator: indicator))
}
/// Associate a indicator when loading image with url, convenient method with block

View File

@ -0,0 +1,59 @@
import SwiftUI
import ObjectiveC
/// Provides a convenient method for backporting API,
/// including types, functions, properties, property wrappers and more.
///
/// To backport a SwiftUI Label for example, you could apply the
/// following extension:
///
/// extension Backport where Content == Any {
/// public struct Label<Title, Icon> { }
/// }
///
/// Now if we want to provide further extensions to our backport type,
/// we need to ensure we retain the `Content == Any` generic requirement:
///
/// extension Backport.Label where Content == Any, Title == Text, Icon == Image {
/// public init<S: StringProtocol>(_ title: S, systemName: String) { }
/// }
///
/// In addition to types, we can also provide backports for properties
/// and methods:
///
/// extension Backport.Label where Content: View {
/// func onChange<Value: Equatable>(of value: Value, perform action: (Value) -> Void) -> some View {
/// // `content` provides access to the extended type
/// content.modifier(OnChangeModifier(value, action))
/// }
/// }
///
public struct Backport<Wrapped> {
/// The underlying content this backport represents.
public let content: Wrapped
/// Initializes a new Backport for the specified content.
/// - Parameter content: The content (type) that's being backported
public init(_ content: Wrapped) {
self.content = content
}
}
public extension View {
/// Wraps a SwiftUI `View` that can be extended to provide backport functionality.
var backport: Backport<Self> { .init(self) }
}
public extension NSObjectProtocol {
/// Wraps an `NSObject` that can be extended to provide backport functionality.
var backport: Backport<Self> { .init(self) }
}
public extension AnyTransition {
/// Wraps an `AnyTransition` that can be extended to provide backport functionality.
static var backport: Backport<AnyTransition>{
Backport(.identity)
}
}

View File

@ -0,0 +1,52 @@
import SwiftUI
import Combine
@available(iOS, deprecated: 14.0)
@available(macOS, deprecated: 11.0)
@available(tvOS, deprecated: 14.0)
@available(watchOS, deprecated: 7.0)
public extension Backport where Wrapped: View {
/// Adds a modifier for this view that fires an action when a specific
/// value changes.
///
/// `onChange` is called on the main thread. Avoid performing long-running
/// tasks on the main thread. If you need to perform a long-running task in
/// response to `value` changing, you should dispatch to a background queue.
///
/// The new value is passed into the closure.
///
/// - Parameters:
/// - value: The value to observe for changes
/// - action: A closure to run when the value changes.
/// - newValue: The new value that changed
///
/// - Returns: A view that fires an action when the specified value changes.
@ViewBuilder
func onChange<Value: Equatable>(of value: Value, perform action: @escaping (Value) -> Void) -> some View {
content.modifier(ChangeModifier(value: value, action: action))
}
}
private struct ChangeModifier<Value: Equatable>: ViewModifier {
let value: Value
let action: (Value) -> Void
@State var oldValue: Value?
init(value: Value, action: @escaping (Value) -> Void) {
self.value = value
self.action = action
_oldValue = .init(initialValue: value)
}
func body(content: Content) -> some View {
content
.onReceive(Just(value)) { newValue in
guard newValue != oldValue else { return }
action(newValue)
oldValue = newValue
}
}
}

View File

@ -0,0 +1,124 @@
import SwiftUI
public extension Backport where Wrapped: View {
/// Layers the views that you specify in front of this view.
///
/// Use this modifier to place one or more views in front of another view.
/// For example, you can place a group of stars on a ``RoundedRectangle``:
///
/// RoundedRectangle(cornerRadius: 8)
/// .frame(width: 200, height: 100)
/// .overlay(alignment: .topLeading) { Star(color: .red) }
/// .overlay(alignment: .topTrailing) { Star(color: .yellow) }
/// .overlay(alignment: .bottomLeading) { Star(color: .green) }
/// .overlay(alignment: .bottomTrailing) { Star(color: .blue) }
///
/// The example above assumes that you've defined a `Star` view with a
/// parameterized color:
///
/// struct Star: View {
/// var color = Color.yellow
///
/// var body: some View {
/// Image(systemName: "star.fill")
/// .foregroundStyle(color)
/// }
/// }
///
/// By setting different `alignment` values for each modifier, you make the
/// stars appear in different places on the rectangle:
///
/// ![A screenshot of a rounded rectangle with a star in each corner. The
/// star in the upper-left is red; the start in the upper-right is yellow;
/// the star in the lower-left is green; the star the lower-right is
/// blue.](View-overlay-2)
///
/// If you specify more than one view in the `content` closure, the modifier
/// collects all of the views in the closure into an implicit ``ZStack``,
/// taking them in order from back to front. For example, you can place a
/// star and a ``Circle`` on a field of ``ShapeStyle/blue``:
///
/// Color.blue
/// .frame(width: 200, height: 200)
/// .overlay {
/// Circle()
/// .frame(width: 100, height: 100)
/// Star()
/// }
///
/// Both the overlay modifier and the implicit ``ZStack`` composed from the
/// overlay content --- the circle and the star --- use a default
/// ``Alignment/center`` alignment. The star appears centered on the circle,
/// and both appear as a composite view centered in front of the square:
///
/// ![A screenshot of a star centered on a circle, which is
/// centered on a square.](View-overlay-3)
///
/// If you specify an alignment for the overlay, it applies to the implicit
/// stack rather than to the individual views in the closure. You can see
/// this if you add the ``Alignment/bottom`` alignment:
///
/// Color.blue
/// .frame(width: 200, height: 200)
/// .overlay(alignment: .bottom) {
/// Circle()
/// .frame(width: 100, height: 100)
/// Star()
/// }
///
/// The circle and the star move down as a unit to align the stack's bottom
/// edge with the bottom edge of the square, while the star remains
/// centered on the circle:
///
/// ![A screenshot of a star centered on a circle, which is on a square.
/// The circle's bottom edge is aligned with the square's bottom
/// edge.](View-overlay-3a)
///
/// To control the placement of individual items inside the `content`
/// closure, either use a different overlay modifier for each item, as the
/// earlier example of stars in the corners of a rectangle demonstrates, or
/// add an explicit ``ZStack`` inside the content closure with its own
/// alignment:
///
/// Color.blue
/// .frame(width: 200, height: 200)
/// .overlay(alignment: .bottom) {
/// ZStack(alignment: .bottom) {
/// Circle()
/// .frame(width: 100, height: 100)
/// Star()
/// }
/// }
///
/// The stack alignment ensures that the star's bottom edge aligns with the
/// circle's, while the overlay aligns the composite view with the square:
///
/// ![A screenshot of a star, a circle, and a square with all their
/// bottom edges aligned.](View-overlay-4)
///
/// You can achieve layering without an overlay modifier by putting both the
/// modified view and the overlay content into a ``ZStack``. This can
/// produce a simpler view hierarchy, but changes the layout priority that
/// SwiftUI applies to the views. Use the overlay modifier when you want the
/// modified view to dominate the layout.
///
/// If you want to specify a ``ShapeStyle`` like a ``Color`` or a
/// ``Material`` as the overlay, use
/// ``View/overlay(_:ignoresSafeAreaEdges:)`` instead. To specify a
/// ``Shape``, use ``View/overlay(_:in:fillStyle:)``.
///
/// - Parameters:
/// - alignment: The alignment that the modifier uses to position the
/// implicit ``ZStack`` that groups the foreground views. The default
/// is ``Alignment/center``.
/// - content: A ``ViewBuilder`` that you use to declare the views to
/// draw in front of this view, stacked in the order that you list them.
/// The last view that you list appears at the front of the stack.
///
/// - Returns: A view that uses the specified content as a foreground.
func overlay<Content: View>(alignment: Alignment = .center, @ViewBuilder _ content: () -> Content) -> some View {
self.content.overlay(content(), alignment: alignment)
}
}

View File

@ -0,0 +1,151 @@
import Combine
import SwiftUI
@available(iOS, deprecated: 14.0)
@available(macOS, deprecated: 11.0)
@available(tvOS, deprecated: 14.0)
@available(watchOS, deprecated: 7.0)
public extension Backport where Wrapped: ObservableObject {
/// A property wrapper type that instantiates an observable object.
///
/// Create a state object in a ``SwiftUI/View``, ``SwiftUI/App``, or
/// ``SwiftUI/Scene`` by applying the `@Backport.StateObject` attribute to a property
/// declaration and providing an initial value that conforms to the
/// <doc://com.apple.documentation/documentation/Combine/ObservableObject>
/// protocol:
///
/// @Backport.StateObject var model = DataModel()
///
/// SwiftUI creates a new instance of the object only once for each instance of
/// the structure that declares the object. When published properties of the
/// observable object change, SwiftUI updates the parts of any view that depend
/// on those properties:
///
/// Text(model.title) // Updates the view any time `title` changes.
///
/// You can pass the state object into a property that has the
/// ``SwiftUI/ObservedObject`` attribute. You can alternatively add the object
/// to the environment of a view hierarchy by applying the
/// ``SwiftUI/View/environmentObject(_:)`` modifier:
///
/// ContentView()
/// .environmentObject(model)
///
/// If you create an environment object as shown in the code above, you can
/// read the object inside `ContentView` or any of its descendants
/// using the ``SwiftUI/EnvironmentObject`` attribute:
///
/// @EnvironmentObject var model: DataModel
///
/// Get a ``SwiftUI/Binding`` to one of the state object's properties using the
/// `$` operator. Use a binding when you want to create a two-way connection to
/// one of the object's properties. For example, you can let a
/// ``SwiftUI/Toggle`` control a Boolean value called `isEnabled` stored in the
/// model:
///
/// Toggle("Enabled", isOn: $model.isEnabled)
@propertyWrapper struct StateObject: DynamicProperty {
private final class Wrapper: ObservableObject {
private var subject = PassthroughSubject<Void, Never>()
var value: Wrapped? {
didSet {
cancellable = nil
cancellable = value?.objectWillChange
.sink { [subject] _ in subject.send() }
}
}
private var cancellable: AnyCancellable?
var objectWillChange: AnyPublisher<Void, Never> {
subject.eraseToAnyPublisher()
}
}
@State private var state = Wrapper()
@ObservedObject private var observedObject = Wrapper()
private var thunk: () -> Wrapped
/// The underlying value referenced by the state object.
///
/// The wrapped value property provides primary access to the value's data.
/// However, you don't access `wrappedValue` directly. Instead, use the
/// property variable created with the `@Backport.StateObject` attribute:
///
/// @Backport.StateObject var contact = Contact()
///
/// var body: some View {
/// Text(contact.name) // Accesses contact's wrapped value.
/// }
///
/// When you change a property of the wrapped value, you can access the new
/// value immediately. However, SwiftUI updates views displaying the value
/// asynchronously, so the user interface might not update immediately.
public var wrappedValue: Wrapped {
if let object = state.value {
return object
} else {
let object = thunk()
state.value = object
return object
}
}
/// A projection of the state object that creates bindings to its
/// properties.
///
/// Use the projected value to pass a binding value down a view hierarchy.
/// To get the projected value, prefix the property variable with `$`. For
/// example, you can get a binding to a model's `isEnabled` Boolean so that
/// a ``SwiftUI/Toggle`` view can control the value:
///
/// struct MyView: View {
/// @Backport.StateObject var model = DataModel()
///
/// var body: some View {
/// Toggle("Enabled", isOn: $model.isEnabled)
/// }
/// }
public var projectedValue: ObservedObject<Wrapped>.Wrapper {
ObservedObject(wrappedValue: wrappedValue).projectedValue
}
/// Creates a new state object with an initial wrapped value.
///
/// You dont call this initializer directly. Instead, declare a property
/// with the `@Backport.StateObject` attribute in a ``SwiftUI/View``,
/// ``SwiftUI/App``, or ``SwiftUI/Scene``, and provide an initial value:
///
/// struct MyView: View {
/// @Backport.StateObject var model = DataModel()
///
/// // ...
/// }
///
/// SwiftUI creates only one instance of the state object for each
/// container instance that you declare. In the code above, SwiftUI
/// creates `model` only the first time it initializes a particular instance
/// of `MyView`. On the other hand, each different instance of `MyView`
/// receives a distinct copy of the data model.
///
/// - Parameter thunk: An initial value for the state object.
public init(wrappedValue thunk: @autoclosure @escaping () -> Wrapped) {
self.thunk = thunk
}
public mutating func update() {
if state.value == nil {
state.value = thunk()
}
if observedObject.value !== state.value {
observedObject.value = state.value
}
}
}
}

View File

@ -28,13 +28,12 @@ public final class ImageManager : ObservableObject {
/// true means during incremental loading
@Published public var isIncremental: Bool = false
var manager: SDWebImageManager
var manager: SDWebImageManager?
weak var currentOperation: SDWebImageOperation? = nil
var isFirstLoad: Bool = true // false after first call `load()`
var url: URL?
var options: SDWebImageOptions
var context: [SDWebImageContextOption : Any]?
var options: SDWebImageOptions = []
var context: [SDWebImageContextOption : Any]? = nil
var successBlock: ((PlatformImage, Data?, SDImageCacheType) -> Void)?
var failureBlock: ((Error) -> Void)?
var progressBlock: ((Int, Int) -> Void)?
@ -54,9 +53,13 @@ public final class ImageManager : ObservableObject {
}
}
init() {}
/// Start to load the url operation
public func load() {
isFirstLoad = false
guard let manager = manager else {
return
}
if currentOperation != nil {
return
}
@ -138,7 +141,3 @@ extension ImageManager {
self.progressBlock = action
}
}
// Indicator Reportor
@available(iOS 13.0, OSX 10.15, tvOS 13.0, watchOS 6.0, *)
extension ImageManager: IndicatorReportable {}

View File

@ -14,6 +14,8 @@ import SDWebImage
public final class ImagePlayer : ObservableObject {
var player: SDAnimatedImagePlayer?
var waitingPlaying = false
/// Max buffer size
public var maxBufferSize: UInt?
@ -48,6 +50,14 @@ public final class ImagePlayer : ObservableObject {
player != nil
}
/// The player is preparing to resume from previous stop state. This is intermediate status when previous frame disappear and new frame appear
public var isWaiting: Bool {
if let player = player {
return player.isPlaying && waitingPlaying
}
return false
}
/// Current playing status
public var isPlaying: Bool {
player?.isPlaying ?? false
@ -56,6 +66,12 @@ public final class ImagePlayer : ObservableObject {
/// Start the animation
public func startPlaying() {
player?.startPlaying()
waitingPlaying = true
DispatchQueue.main.async {
// This workaround `WebImage` caller
// Which previous frame onDisappear and new frame onAppear, cause player status wrong
self.waitingPlaying = false
}
}
/// Pause the animation

View File

@ -24,23 +24,23 @@ public struct Indicator<T> where T : View {
}
}
/// A protocol to report indicator progress
/// A observable model to report indicator loading status
@available(iOS 13.0, OSX 10.15, tvOS 13.0, watchOS 6.0, *)
public protocol IndicatorReportable : ObservableObject {
public class IndicatorStatus : ObservableObject {
/// whether indicator is loading or not
var isLoading: Bool { get set }
@Published var isLoading: Bool = false
/// indicator progress, should only be used for indicator binding, value between [0.0, 1.0]
var progress: Double { get set }
@Published var progress: Double = 0
}
/// A implementation detail View Modifier with indicator
/// SwiftUI View Modifier construced by using a internal View type which modify the `body`
/// It use type system to represent the view hierarchy, and Swift `some View` syntax to hide the type detail for users
@available(iOS 13.0, OSX 10.15, tvOS 13.0, watchOS 6.0, *)
public struct IndicatorViewModifier<T, V> : ViewModifier where T : View, V : IndicatorReportable {
public struct IndicatorViewModifier<T> : ViewModifier where T : View {
/// The progress reporter
@ObservedObject public var reporter: V
/// The loading status
@ObservedObject public var status: IndicatorStatus
/// The indicator
public var indicator: Indicator<T>
@ -48,8 +48,11 @@ public struct IndicatorViewModifier<T, V> : ViewModifier where T : View, V : Ind
public func body(content: Content) -> some View {
ZStack {
content
if reporter.isLoading {
indicator.content($reporter.isLoading, $reporter.progress)
.backport
.overlay {
if status.isLoading {
indicator.content($status.isLoading, $status.progress)
}
}
}
}

View File

@ -1,84 +0,0 @@
/*
* This file is part of the SDWebImage package.
* (c) DreamPiggy <lizhuoli1126@126.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
import Foundation
import SwiftUI
#if os(iOS) || os(tvOS) || os(macOS)
@available(iOS 13.0, OSX 10.15, tvOS 13.0, watchOS 6.0, *)
struct PlatformAppear: PlatformViewRepresentable {
let appearAction: () -> Void
let disappearAction: () -> Void
#if os(iOS) || os(tvOS)
func makeUIView(context: Context) -> some UIView {
let view = PlatformAppearView()
view.appearAction = appearAction
view.disappearAction = disappearAction
return view
}
func updateUIView(_ uiView: UIViewType, context: Context) {}
#endif
#if os(macOS)
func makeNSView(context: Context) -> some NSView {
let view = PlatformAppearView()
view.appearAction = appearAction
view.disappearAction = disappearAction
return view
}
func updateNSView(_ nsView: NSViewType, context: Context) {}
#endif
}
@available(iOS 13.0, OSX 10.15, tvOS 13.0, watchOS 6.0, *)
class PlatformAppearView: PlatformView {
var appearAction: () -> Void = {}
var disappearAction: () -> Void = {}
#if os(iOS) || os(tvOS)
override func willMove(toWindow newWindow: UIWindow?) {
if newWindow != nil {
appearAction()
} else {
disappearAction()
}
}
#endif
#if os(macOS)
override func viewWillMove(toWindow newWindow: NSWindow?) {
if newWindow != nil {
appearAction()
} else {
disappearAction()
}
}
#endif
}
#endif
@available(iOS 13.0, OSX 10.15, tvOS 13.0, watchOS 6.0, *)
extension View {
/// Used UIKit/AppKit behavior to detect the SwiftUI view's visibility.
/// This hack is because of SwiftUI 1.0/2.0 buggy behavior. The built-in `onAppear` and `onDisappear` is so massive on some cases. Where UIKit/AppKit is solid.
/// - Parameters:
/// - appear: The action when view appears
/// - disappear: The action when view disappears
/// - Returns: Some view
func onPlatformAppear(appear: @escaping () -> Void = {}, disappear: @escaping () -> Void = {}) -> some View {
#if os(iOS) || os(tvOS) || os(macOS)
return self.background(PlatformAppear(appearAction: appear, disappearAction: disappear))
#else
return self.onAppear(perform: appear).onDisappear(perform: disappear)
#endif
}
}

View File

@ -9,31 +9,67 @@
import SwiftUI
import SDWebImage
/// Completion Handler Binding Object, supports dynamic @State changes
@available(iOS 13.0, OSX 10.15, tvOS 13.0, watchOS 6.0, *)
final class WebImageHandler: ObservableObject {
// Completion Handler
@Published var successBlock: ((PlatformImage, Data?, SDImageCacheType) -> Void)?
@Published var failureBlock: ((Error) -> Void)?
@Published var progressBlock: ((Int, Int) -> Void)?
}
/// Configuration Binding Object, supports dynamic @State changes
@available(iOS 13.0, OSX 10.15, tvOS 13.0, watchOS 6.0, *)
final class WebImageConfiguration: ObservableObject {
var retryOnAppear: Bool = true
var cancelOnDisappear: Bool = true
var maxBufferSize: UInt?
var customLoopCount: UInt?
var runLoopMode: RunLoop.Mode = .common
var pausable: Bool = true
var purgeable: Bool = false
var playbackRate: Double = 1.0
var playbackMode: SDAnimatedImagePlaybackMode = .normal
}
/// A Image View type to load image from url. Supports static/animated image format.
@available(iOS 13.0, OSX 10.15, tvOS 13.0, watchOS 6.0, *)
public struct WebImage : View {
var configurations: [(Image) -> Image] = []
var placeholder: AnyView?
var retryOnAppear: Bool = true
var cancelOnDisappear: Bool = true
var pausable: Bool = true
var purgeable: Bool = false
@ObservedObject var imageManager: ImageManager
/// A Binding to control the animation. You can bind external logic to control the animation status.
/// True to start animation, false to stop animation.
@Binding public var isAnimating: Bool
@ObservedObject var imagePlayer: ImagePlayer
/// A observed object to pass through the image handler to manager
@ObservedObject var imageHandler = WebImageHandler()
/// Create a web image with url, placeholder, custom options and context.
/// - Parameter url: The image url
/// - Parameter options: The options to use when downloading the image. See `SDWebImageOptions` for the possible values.
/// - Parameter context: A context contains different options to perform specify changes or processes, see `SDWebImageContextOption`. This hold the extra objects which `options` enum can not hold.
public init(url: URL?, options: SDWebImageOptions = [], context: [SDWebImageContextOption : Any]? = nil) {
self.init(url: url, options: options, context: context, isAnimating: .constant(true))
/// A observed object to pass through the image configuration to player
@ObservedObject var imageConfiguration = WebImageConfiguration()
/// A observed object to pass through the image manager loading status to indicator
@ObservedObject var indicatorStatus = IndicatorStatus()
@SwiftUI.StateObject var imagePlayer_SwiftUI = ImagePlayer()
@Backport.StateObject var imagePlayer_Backport = ImagePlayer()
var imagePlayer: ImagePlayer {
if #available(iOS 14.0, macOS 11.0, tvOS 14.0, watchOS 7.0, *) {
return imagePlayer_SwiftUI
} else {
return imagePlayer_Backport
}
}
@SwiftUI.StateObject var imageManager_SwiftUI = ImageManager()
@Backport.StateObject var imageManager_Backport = ImageManager()
var imageManager: ImageManager {
if #available(iOS 14.0, macOS 11.0, tvOS 14.0, watchOS 7.0, *) {
return imageManager_SwiftUI
} else {
return imageManager_Backport
}
}
/// Create a web image with url, placeholder, custom options and context. Optional can support animated image using Binding.
@ -50,31 +86,39 @@ public struct WebImage : View {
context[.animatedImageClass] = SDAnimatedImage.self
}
}
self.imageManager = ImageManager(url: url, options: options, context: context)
self.imagePlayer = ImagePlayer()
if #available(iOS 14.0, macOS 11.0, tvOS 14.0, watchOS 7.0, *) {
_imageManager_SwiftUI = SwiftUI.StateObject(wrappedValue: ImageManager(url: url, options: options, context: context))
} else {
_imageManager_Backport = Backport.StateObject(wrappedValue: ImageManager(url: url, options: options, context: context))
}
}
/// Create a web image with url, placeholder, custom options and context.
/// - Parameter url: The image url
/// - Parameter options: The options to use when downloading the image. See `SDWebImageOptions` for the possible values.
/// - Parameter context: A context contains different options to perform specify changes or processes, see `SDWebImageContextOption`. This hold the extra objects which `options` enum can not hold.
public init(url: URL?, options: SDWebImageOptions = [], context: [SDWebImageContextOption : Any]? = nil) {
self.init(url: url, options: options, context: context, isAnimating: .constant(true))
}
public var body: some View {
// This solve the case when WebImage created with new URL, but `onAppear` not been called, for example, some transaction indeterminate state, SwiftUI :)
if imageManager.isFirstLoad {
imageManager.load()
}
return Group {
if let image = imageManager.image {
if isAnimating && !imageManager.isIncremental {
setupPlayer()
.onPlatformAppear(appear: {
self.imagePlayer.startPlaying()
}, disappear: {
if self.pausable {
self.imagePlayer.pausePlaying()
} else {
self.imagePlayer.stopPlaying()
.onDisappear {
// Only stop the player which is not intermediate status
if !imagePlayer.isWaiting {
if self.imageConfiguration.pausable {
self.imagePlayer.pausePlaying()
} else {
self.imagePlayer.stopPlaying()
}
if self.imageConfiguration.purgeable {
self.imagePlayer.clearFrameBuffer()
}
}
if self.purgeable {
self.imagePlayer.clearFrameBuffer()
}
})
}
} else {
if let currentFrame = imagePlayer.currentFrame {
configure(image: currentFrame)
@ -84,24 +128,27 @@ public struct WebImage : View {
}
} else {
setupPlaceholder()
.onPlatformAppear(appear: {
.onAppear {
self.imageManager.successBlock = self.imageHandler.successBlock
self.imageManager.failureBlock = self.imageHandler.failureBlock
self.imageManager.progressBlock = self.imageHandler.progressBlock
// Load remote image when first appear
if self.imageManager.isFirstLoad {
self.imageManager.load()
return
}
guard self.retryOnAppear else { return }
self.imageManager.load()
guard self.imageConfiguration.retryOnAppear else { return }
// When using prorgessive loading, the new partial image will cause onAppear. Filter this case
if self.imageManager.image == nil && !self.imageManager.isIncremental {
self.imageManager.load()
}
}, disappear: {
guard self.cancelOnDisappear else { return }
}.onDisappear {
guard self.imageConfiguration.cancelOnDisappear else { return }
// When using prorgessive loading, the previous partial image will cause onDisappear. Filter this case
if self.imageManager.image == nil && !self.imageManager.isIncremental {
self.imageManager.cancel()
}
})
}.onReceive(imageManager.objectWillChange) { _ in
indicatorStatus.isLoading = imageManager.isLoading
indicatorStatus.progress = imageManager.progress
}
}
}
}
@ -158,13 +205,21 @@ public struct WebImage : View {
/// Animated Image Support
func setupPlayer() -> some View {
if let currentFrame = imagePlayer.currentFrame {
return configure(image: currentFrame)
} else {
if let animatedImage = imageManager.image as? SDAnimatedImageProvider {
self.imagePlayer.setupPlayer(animatedImage: animatedImage)
return configure(image: currentFrame).onAppear {
self.imagePlayer.startPlaying()
}
return configure(image: imageManager.image!)
} else {
return configure(image: imageManager.image!).onAppear {
if let animatedImage = imageManager.image as? SDAnimatedImageProvider {
self.imagePlayer.customLoopCount = self.imageConfiguration.customLoopCount
self.imagePlayer.maxBufferSize = self.imageConfiguration.maxBufferSize
self.imagePlayer.runLoopMode = self.imageConfiguration.runLoopMode
self.imagePlayer.playbackMode = self.imageConfiguration.playbackMode
self.imagePlayer.playbackRate = self.imageConfiguration.playbackRate
self.imagePlayer.setupPlayer(animatedImage: animatedImage)
self.imagePlayer.startPlaying()
}
}
}
}
@ -231,7 +286,7 @@ extension WebImage {
/// - action: The action to perform. The first arg is the error during loading. If `action` is `nil`, the call has no effect.
/// - Returns: A view that triggers `action` when this image load fails.
public func onFailure(perform action: ((Error) -> Void)? = nil) -> WebImage {
self.imageManager.failureBlock = action
self.imageHandler.failureBlock = action
return self
}
@ -240,7 +295,7 @@ extension WebImage {
/// - action: The action to perform. The first arg is the loaded image, the second arg is the loaded image data, the third arg is the cache type loaded from. If `action` is `nil`, the call has no effect.
/// - Returns: A view that triggers `action` when this image load successes.
public func onSuccess(perform action: ((PlatformImage, Data?, SDImageCacheType) -> Void)? = nil) -> WebImage {
self.imageManager.successBlock = action
self.imageHandler.successBlock = action
return self
}
@ -249,7 +304,7 @@ extension WebImage {
/// - action: The action to perform. The first arg is the received size, the second arg is the total size, all in bytes. If `action` is `nil`, the call has no effect.
/// - Returns: A view that triggers `action` when this image load successes.
public func onProgress(perform action: ((Int, Int) -> Void)? = nil) -> WebImage {
self.imageManager.progressBlock = action
self.imageHandler.progressBlock = action
return self
}
}
@ -281,17 +336,15 @@ extension WebImage {
/// Control the behavior to retry the failed loading when view become appears again
/// - Parameter flag: Whether or not to retry the failed loading
public func retryOnAppear(_ flag: Bool) -> WebImage {
var result = self
result.retryOnAppear = flag
return result
self.imageConfiguration.retryOnAppear = flag
return self
}
/// Control the behavior to cancel the pending loading when view become disappear again
/// - Parameter flag: Whether or not to cancel the pending loading
public func cancelOnDisappear(_ flag: Bool) -> WebImage {
var result = self
result.cancelOnDisappear = flag
return result
self.imageConfiguration.cancelOnDisappear = flag
return self
}
}
@ -302,7 +355,7 @@ extension WebImage {
/// Associate a indicator when loading image with url
/// - Parameter indicator: The indicator type, see `Indicator`
public func indicator<T>(_ indicator: Indicator<T>) -> some View where T : View {
return self.modifier(IndicatorViewModifier(reporter: imageManager, indicator: indicator))
return self.modifier(IndicatorViewModifier(status: indicatorStatus, indicator: indicator))
}
/// Associate a indicator when loading image with url, convenient method with block
@ -320,7 +373,7 @@ extension WebImage {
/// - Note: Pass nil to disable customization, use the image itself loop count (`animatedImageLoopCount`) instead
/// - Parameter loopCount: The animation loop count
public func customLoopCount(_ loopCount: UInt?) -> WebImage {
self.imagePlayer.customLoopCount = loopCount
self.imageConfiguration.customLoopCount = loopCount
return self
}
@ -331,7 +384,7 @@ extension WebImage {
/// `UInt.max` means cache all the buffer. (Lowest CPU and Highest Memory)
/// - Parameter bufferSize: The max buffer size
public func maxBufferSize(_ bufferSize: UInt?) -> WebImage {
self.imagePlayer.maxBufferSize = bufferSize
self.imageConfiguration.maxBufferSize = bufferSize
return self
}
@ -340,7 +393,7 @@ extension WebImage {
/// - Note: This is useful for some cases, for example, always specify NSDefaultRunLoopMode, if you want to pause the animation when user scroll (for Mac user, drag the mouse or touchpad)
/// - Parameter runLoopMode: The runLoopMode for animation
public func runLoopMode(_ runLoopMode: RunLoop.Mode) -> WebImage {
self.imagePlayer.runLoopMode = runLoopMode
self.imageConfiguration.runLoopMode = runLoopMode
return self
}
@ -348,18 +401,16 @@ extension WebImage {
/// - Note: For some of use case, you may want to reset the frame index to 0 when stop, but some other want to keep the current frame index.
/// - Parameter pausable: Whether or not to pause the animation instead of stop the animation.
public func pausable(_ pausable: Bool) -> WebImage {
var result = self
result.pausable = pausable
return result
self.imageConfiguration.pausable = pausable
return self
}
/// Whether or not to clear frame buffer cache when stopped. Defaults is false.
/// Note: This is useful when you want to limit the memory usage during frequently visibility changes (such as image view inside a list view, then push and pop)
/// - Parameter purgeable: Whether or not to clear frame buffer cache when stopped.
public func purgeable(_ purgeable: Bool) -> WebImage {
var result = self
result.purgeable = purgeable
return result
self.imageConfiguration.purgeable = purgeable
return self
}
/// Control the animation playback rate. Default is 1.0.
@ -370,14 +421,14 @@ extension WebImage {
/// `< 0.0` is not supported currently and stop animation. (may support reverse playback in the future)
/// - Parameter playbackRate: The animation playback rate.
public func playbackRate(_ playbackRate: Double) -> WebImage {
self.imagePlayer.playbackRate = playbackRate
self.imageConfiguration.playbackRate = playbackRate
return self
}
/// Control the animation playback mode. Default is .normal
/// - Parameter playbackMode: The playback mode, including normal order, reverse order, bounce order and reversed bounce order.
public func playbackMode(_ playbackMode: SDAnimatedImagePlaybackMode) -> WebImage {
self.imagePlayer.playbackMode = playbackMode
self.imageConfiguration.playbackMode = playbackMode
return self
}
}

View File

@ -23,9 +23,9 @@ class WebImageTests: XCTestCase {
let imageView = WebImage(url: imageUrl)
let introspectView = imageView.onSuccess { image, data, cacheType in
#if os(macOS)
let displayImage = try? imageView.inspect().group().image(0).nsImage()
let displayImage = try? imageView.inspect().group().image(0).actualImage.nsImage()
#else
let displayImage = try? imageView.inspect().group().image(0).cgImage()
let displayImage = try? imageView.inspect().group().image(0).actualImage().cgImage()
#endif
XCTAssertNotNil(displayImage)
expectation.fulfill()
@ -47,10 +47,10 @@ class WebImageTests: XCTestCase {
if let animatedImage = image as? SDAnimatedImage {
XCTAssertTrue(imageView.isAnimating)
#if os(macOS)
let displayImage = try? imageView.inspect().group().image(0).nsImage()
let displayImage = try? imageView.inspect().group().image(0).actualImage().nsImage()
let size = displayImage?.size
#else
let displayImage = try? imageView.inspect().group().image(0).cgImage()
let displayImage = try? imageView.inspect().group().image(0).actualImage().cgImage()
let size = CGSize(width: displayImage?.width ?? 0, height: displayImage?.height ?? 0)
#endif
XCTAssertNotNil(displayImage)
@ -161,11 +161,11 @@ class WebImageTests: XCTestCase {
let imageView = WebImage(url: imageUrl)
let introspectView = imageView.onSuccess { image, data, cacheType in
#if os(macOS)
let displayImage = try? imageView.inspect().group().image(0).nsImage()
let displayImage = try? imageView.inspect().group().image(0).actualImage().nsImage()
XCTAssertNotNil(displayImage)
#else
let displayImage = try? imageView.inspect().group().image(0).cgImage()
let orientation = try? imageView.inspect().group().image(0).orientation()
let displayImage = try? imageView.inspect().group().image(0).actualImage().cgImage()
let orientation = try? imageView.inspect().group().image(0).actualImage().orientation()
XCTAssertNotNil(displayImage)
XCTAssertEqual(orientation, .leftMirrored)
#endif

View File

@ -2,18 +2,16 @@
# Usage example: ./carthage.sh build --platform iOS
set -euo pipefail
xcconfig=$(mktemp /tmp/static.xcconfig.XXXXXX)
trap 'rm -f "$xcconfig"' INT TERM HUP EXIT
# For Xcode 12 make sure EXCLUDED_ARCHS is set to arm architectures otherwise
# the build will fail on lipo due to duplicate architectures.
CURRENT_XCODE_VERSION=$(xcodebuild -version | grep "Build version" | cut -d' ' -f3)
echo "EXCLUDED_ARCHS__EFFECTIVE_PLATFORM_SUFFIX_simulator__NATIVE_ARCH_64_BIT_x86_64__XCODE_1200__BUILD_$CURRENT_XCODE_VERSION = arm64 arm64e armv7 armv7s armv6 armv8" >> $xcconfig
echo 'EXCLUDED_ARCHS__EFFECTIVE_PLATFORM_SUFFIX_simulator__NATIVE_ARCH_64_BIT_x86_64__XCODE_1200 = $(EXCLUDED_ARCHS__EFFECTIVE_PLATFORM_SUFFIX_simulator__NATIVE_ARCH_64_BIT_x86_64__XCODE_1200__BUILD_$(XCODE_PRODUCT_BUILD_VERSION))' >> $xcconfig
echo 'EXCLUDED_ARCHS = $(inherited) $(EXCLUDED_ARCHS__EFFECTIVE_PLATFORM_SUFFIX_$(EFFECTIVE_PLATFORM_SUFFIX)__NATIVE_ARCH_64_BIT_$(NATIVE_ARCH_64_BIT)__XCODE_$(XCODE_VERSION_MAJOR))' >> $xcconfig
echo 'EXCLUDED_ARCHS[sdk=iphonesimulator*] = arm64 arm64e armv7 armv7s armv6 armv8' >> $xcconfig
echo 'EXCLUDED_ARCHS[sdk=appletvsimulator*] = arm64 arm64e armv7 armv7s armv6 armv8' >> $xcconfig
echo 'EXCLUDED_ARCHS[sdk=watchsimulator*] = arm64 arm64e armv7 armv7s armv6 armv8' >> $xcconfig
export XCODE_XCCONFIG_FILE="$xcconfig"
carthage "$@"