├── .github
└── workflows
│ └── swift.yml
├── .gitignore
├── .spi.yml
├── LICENSE
├── Package.swift
├── README.md
├── Sources
└── URLCompatibilityKit
│ ├── InstanceMethods.swift
│ ├── TypeMethods.swift
│ └── TypeProperties.swift
└── Tests
└── URLCompatibilityKitTests
├── AppendTests.swift
└── DirectoryTests.swift
/.github/workflows/swift.yml:
--------------------------------------------------------------------------------
1 | name: Swift
2 |
3 | on:
4 | push:
5 | branches: [ "main" ]
6 | pull_request:
7 | branches: [ "main" ]
8 |
9 | jobs:
10 | build:
11 |
12 | runs-on: macos-latest
13 |
14 | steps:
15 | - uses: actions/checkout@v3
16 | - name: Build
17 | run: swift build -v
18 | - name: Run tests
19 | run: swift test -v
20 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Xcode
2 | #
3 | # gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore
4 |
5 | ## User settings
6 | xcuserdata/
7 |
8 | ## compatibility with Xcode 8 and earlier (ignoring not required starting Xcode 9)
9 | *.xcscmblueprint
10 | *.xccheckout
11 |
12 | ## compatibility with Xcode 3 and earlier (ignoring not required starting Xcode 4)
13 | build/
14 | DerivedData/
15 | *.moved-aside
16 | *.pbxuser
17 | !default.pbxuser
18 | *.mode1v3
19 | !default.mode1v3
20 | *.mode2v3
21 | !default.mode2v3
22 | *.perspectivev3
23 | !default.perspectivev3
24 |
25 | ## Obj-C/Swift specific
26 | *.hmap
27 |
28 | ## App packaging
29 | *.ipa
30 | *.dSYM.zip
31 | *.dSYM
32 |
33 | ## Playgrounds
34 | timeline.xctimeline
35 | playground.xcworkspace
36 |
37 | # Swift Package Manager
38 | #
39 | # Add this line if you want to avoid checking in source code from Swift Package Manager dependencies.
40 | # Packages/
41 | # Package.pins
42 | # Package.resolved
43 | # *.xcodeproj
44 | #
45 | # Xcode automatically generates this directory with a .xcworkspacedata file and xcuserdata
46 | # hence it is not needed unless you have added a package configuration file to your project
47 | # .swiftpm
48 |
49 | .build/
50 |
51 | # CocoaPods
52 | #
53 | # We recommend against adding the Pods directory to your .gitignore. However
54 | # you should judge for yourself, the pros and cons are mentioned at:
55 | # https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control
56 | #
57 | # Pods/
58 | #
59 | # Add this line if you want to avoid checking in source code from the Xcode workspace
60 | # *.xcworkspace
61 |
62 | # Carthage
63 | #
64 | # Add this line if you want to avoid checking in source code from Carthage dependencies.
65 | # Carthage/Checkouts
66 |
67 | Carthage/Build/
68 |
69 | # Accio dependency management
70 | Dependencies/
71 | .accio/
72 |
73 | # fastlane
74 | #
75 | # It is recommended to not store the screenshots in the git repo.
76 | # Instead, use fastlane to re-generate the screenshots whenever they are needed.
77 | # For more information about the recommended setup visit:
78 | # https://docs.fastlane.tools/best-practices/source-control/#source-control
79 |
80 | fastlane/report.xml
81 | fastlane/Preview.html
82 | fastlane/screenshots/**/*.png
83 | fastlane/test_output
84 |
85 | # Code Injection
86 | #
87 | # After new code Injection tools there's a generated folder /iOSInjectionProject
88 | # https://github.com/johnno1962/injectionforxcode
89 |
90 | iOSInjectionProject/
91 |
--------------------------------------------------------------------------------
/.spi.yml:
--------------------------------------------------------------------------------
1 | version: 1
2 | builder:
3 | configs:
4 | - documentation_targets: [URLCompatibilityKit]
5 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2022 Marco Eidinger
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/Package.swift:
--------------------------------------------------------------------------------
1 | // swift-tools-version: 5.5
2 |
3 | import PackageDescription
4 |
5 | let package = Package(
6 | name: "URLCompatibilityKit",
7 | platforms: [.iOS(.v11), .macOS(.v10_13), .tvOS(.v10), .watchOS(.v3)],
8 | products: [
9 | .library(
10 | name: "URLCompatibilityKit",
11 | targets: ["URLCompatibilityKit"]
12 | ),
13 | ],
14 | dependencies: [],
15 | targets: [
16 | .target(
17 | name: "URLCompatibilityKit",
18 | dependencies: []
19 | ),
20 | .testTarget(
21 | name: "URLCompatibilityKitTests",
22 | dependencies: ["URLCompatibilityKit"]
23 | ),
24 | ]
25 | )
26 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # URLCompatibilityKit
2 |
3 | **URLCompatibilityKit** is a lightweight Swift package that adds compatible backports of commonly used type properties, type and instance properties for `URL` that are only available from iOS 16.0+ / macOS 13.0+ / tvOS 16.0+ / watchOS 9.0+.
4 |
5 | Avoid conditional compiler directives in your code!
6 |
7 |
8 |
9 |
10 | Without URLCompatibilityKit |
11 | With URLCompatibilityKit |
12 |
13 |
14 |
15 |
16 |
17 |
18 | ```swift
19 | let fileURL: URL
20 |
21 | if #available(iOS 16.0, *) {
22 | fileURL = URL
23 | .documentsDirectory
24 | .appending(path: "myfile")
25 | } else {
26 | fileURL = try FileManager.default
27 | .url(
28 | for: .documentDirectory,
29 | in: .userDomainMask,
30 | appropriateFor: nil,
31 | create: false
32 | )
33 | .appendingPathComponent(
34 | "myfile", isDirectory: false
35 | )
36 | }
37 | ```
38 |
39 | |
40 |
41 |
42 | ```swift
43 | import URLCompatibilityKit
44 |
45 | let fileURL = URL
46 | .documentsDirectory
47 | .appending(path: "myfile")
48 | ```
49 |
50 | |
51 |
52 |
53 |
54 |
55 | It currently includes backward-compatible versions of the following APIs:
56 |
57 | **Type Properties**
58 |
59 | - `URL.applicationDirectory`
60 | - `URL.applicationSupportDirectory`
61 | - `URL.cachesDirectory`
62 | - `URL.desktopDirectory`
63 | - `URL.documentsDirectory`
64 | - `URL.downloadsDirectory`
65 | - `URL.homeDirectory`
66 | - `URL.libraryDirectory`
67 | - `URL.moviesDirectory`
68 | - `URL.musicDirectory`
69 | - `URL.picturesDirectory`
70 | - `URL.sharedPublicDirectory`
71 | - `URL.temporaryDirectory`
72 | - `URL.trashDirectory`
73 | - `URL.userDirectory`
74 |
75 | **Type Methods**
76 |
77 | - `URL.currentDirectory() -> URL`
78 | - `homeDirectory(forUser: String) -> URL?`
79 |
80 | **Instance Methods**
81 | - `append(path:)` // equivalent to using URL.DirectoryHint = .inferFromPath
82 | - `appending(path:)` // equivalent to using URL.DirectoryHint = .inferFromPath
83 |
84 |
85 | Once you're ready to make iOS 16 your minimum deployment target, you can safely unlink URLCompatibilityKit from your project without making any additional changes to your code base (besides removing all `import URLCompatibilityKit` statements).
86 |
87 | URLCompatibilityKit marks its added APIs either as obsolete or as deprecated when integrated into an iOS 16-based project, so you'll get a reminder that it's no longer needed once you're able to use the matching system APIs directly.
88 |
89 | ## Installation
90 |
91 | URLCompatibilityKit is distributed using the [Swift Package Manager](https://swift.org/package-manager). To install it, use Xcode’s `File > Add Packages...` menu command to add it to your iOS app project.
92 |
93 | Then import URLCompatibilityKit wherever you’d like to use it:
94 |
95 | ```swift
96 | import URLCompatibilityKit
97 | ```
98 |
--------------------------------------------------------------------------------
/Sources/URLCompatibilityKit/InstanceMethods.swift:
--------------------------------------------------------------------------------
1 | import Foundation
2 |
3 | // @available on extension level sufficient as added functions do not match upcoming APIs exactly
4 | @available(iOS, deprecated: 16.0, message: "URLCompatibilityKit is only useful when targeting iOS versions earlier than 16")
5 | @available(macOS, deprecated: 13.0, message: "URLCompatibilityKit is only useful when targeting macOS versions earlier than 13")
6 | @available(tvOS, deprecated: 16.0, message: "URLCompatibilityKit is only useful when targeting tvOS versions earlier than 16")
7 | @available(watchOS, deprecated: 9.0, message: "URLCompatibilityKit is only useful when targeting watchOS versions earlier than 9")
8 | public extension URL {
9 | /// Appends a path (inferring if it is directory or not) to the receiver.
10 | mutating func append(path: S) where S: StringProtocol {
11 | if path.hasSuffix("/") {
12 | appendPathComponent("\(path)", isDirectory: true)
13 | } else {
14 | appendPathComponent("\(path)", isDirectory: false)
15 | }
16 | }
17 |
18 | /// Returns a URL constructed by appending the given path (inferring if it is directory or not) to self
19 | func appending(path: S) -> URL where S: StringProtocol {
20 | if path.hasSuffix("/") {
21 | return appendingPathComponent("\(path)", isDirectory: true)
22 | } else {
23 | return appendingPathComponent("\(path)", isDirectory: false)
24 | }
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/Sources/URLCompatibilityKit/TypeMethods.swift:
--------------------------------------------------------------------------------
1 | import Foundation
2 |
3 | // @available on method level needed to avoid "`Ambiguous use of ..." compiler error as added function/property does match upcoming API
4 | public extension URL {
5 | /// The URL to the program’s current directory.
6 | @available(iOS, introduced: 11.0, obsoleted: 16.0)
7 | @available(macOS, introduced: 10.12, obsoleted: 13.0)
8 | @available(tvOS, introduced: 10.0, obsoleted: 16.0)
9 | @available(watchOS, introduced: 3.0, obsoleted: 9.0)
10 | static func currentDirectory() -> URL {
11 | URL(fileURLWithPath: FileManager.default.currentDirectoryPath)
12 | }
13 |
14 | #if os(macOS)
15 | /// Home directory for the specified user.
16 | @available(iOS, introduced: 11.0, obsoleted: 16.0)
17 | @available(macOS, introduced: 10.12, obsoleted: 13.0)
18 | @available(tvOS, introduced: 10.0, obsoleted: 16.0)
19 | @available(watchOS, introduced: 3.0, obsoleted: 9.0)
20 | static func homeDirectory(forUser user: String) -> URL? {
21 | FileManager.default.homeDirectory(forUser: user)
22 | }
23 | #endif
24 | }
25 |
--------------------------------------------------------------------------------
/Sources/URLCompatibilityKit/TypeProperties.swift:
--------------------------------------------------------------------------------
1 | import Foundation
2 |
3 | // @available on method level needed to avoid "`Ambiguous use of ..." compiler error as added function/property does match upcoming API
4 | public extension URL {
5 | /// Supported applications (/Applications).
6 | @available(iOS, introduced: 11.0, obsoleted: 16.0)
7 | @available(macOS, introduced: 10.12, obsoleted: 13.0)
8 | @available(tvOS, introduced: 10.0, obsoleted: 16.0)
9 | @available(watchOS, introduced: 3.0, obsoleted: 9.0)
10 | static var applicationDirectory: URL {
11 | FileManager.default.urls(for: .applicationDirectory, in: .userDomainMask).first!
12 | }
13 |
14 | /// Application support files (Library/Application Support).
15 | @available(iOS, introduced: 11.0, obsoleted: 16.0)
16 | @available(macOS, introduced: 10.12, obsoleted: 13.0)
17 | @available(tvOS, introduced: 10.0, obsoleted: 16.0)
18 | @available(watchOS, introduced: 3.0, obsoleted: 9.0)
19 | static var applicationSupportDirectory: URL {
20 | FileManager.default.urls(for: .applicationSupportDirectory, in: .userDomainMask).first!
21 | }
22 |
23 | /// Discardable cache files (Library/Caches).
24 | @available(iOS, introduced: 11.0, obsoleted: 16.0)
25 | @available(macOS, introduced: 10.12, obsoleted: 13.0)
26 | @available(tvOS, introduced: 10.0, obsoleted: 16.0)
27 | @available(watchOS, introduced: 3.0, obsoleted: 9.0)
28 | static var cachesDirectory: URL {
29 | FileManager.default.urls(for: .cachesDirectory, in: .userDomainMask).first!
30 | }
31 |
32 | /// The user’s desktop directory.
33 | @available(iOS, introduced: 11.0, obsoleted: 16.0)
34 | @available(macOS, introduced: 10.12, obsoleted: 13.0)
35 | @available(tvOS, introduced: 10.0, obsoleted: 16.0)
36 | @available(watchOS, introduced: 3.0, obsoleted: 9.0)
37 | static var desktopDirectory: URL {
38 | FileManager.default.urls(for: .desktopDirectory, in: .userDomainMask).first!
39 | }
40 |
41 | /// Document directory.
42 | @available(iOS, introduced: 11.0, obsoleted: 16.0)
43 | @available(macOS, introduced: 10.12, obsoleted: 13.0)
44 | @available(tvOS, introduced: 10.0, obsoleted: 16.0)
45 | @available(watchOS, introduced: 3.0, obsoleted: 9.0)
46 | static var documentsDirectory: URL {
47 | FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first!
48 | }
49 |
50 | /// The user’s downloads directory.
51 | @available(iOS, introduced: 11.0, obsoleted: 16.0)
52 | @available(macOS, introduced: 10.12, obsoleted: 13.0)
53 | @available(tvOS, introduced: 10.0, obsoleted: 16.0)
54 | @available(watchOS, introduced: 3.0, obsoleted: 9.0)
55 | static var downloadsDirectory: URL {
56 | FileManager.default.urls(for: .downloadsDirectory, in: .userDomainMask).first!
57 | }
58 |
59 | @available(iOS, introduced: 11.0, obsoleted: 16.0)
60 | @available(macOS, introduced: 10.12, obsoleted: 13.0)
61 | @available(tvOS, introduced: 10.0, obsoleted: 16.0)
62 | @available(watchOS, introduced: 3.0, obsoleted: 9.0)
63 | static var homeDirectory: URL {
64 | URL(fileURLWithPath: NSHomeDirectory())
65 | }
66 |
67 | /// Various user-visible documentation, support, and configuration files (/Library).
68 | @available(iOS, introduced: 11.0, obsoleted: 16.0)
69 | @available(macOS, introduced: 10.12, obsoleted: 13.0)
70 | @available(tvOS, introduced: 10.0, obsoleted: 16.0)
71 | @available(watchOS, introduced: 3.0, obsoleted: 9.0)
72 | static var libraryDirectory: URL {
73 | FileManager.default.urls(for: .libraryDirectory, in: .userDomainMask).first!
74 | }
75 |
76 | /// The user’s Movies directory (~/Movies).
77 | @available(iOS, introduced: 11.0, obsoleted: 16.0)
78 | @available(macOS, introduced: 10.12, obsoleted: 13.0)
79 | @available(tvOS, introduced: 10.0, obsoleted: 16.0)
80 | @available(watchOS, introduced: 3.0, obsoleted: 9.0)
81 | static var moviesDirectory: URL {
82 | FileManager.default.urls(for: .moviesDirectory, in: .userDomainMask).first!
83 | }
84 |
85 | /// The user’s Music directory (~/Music).
86 | @available(iOS, introduced: 11.0, obsoleted: 16.0)
87 | @available(macOS, introduced: 10.12, obsoleted: 13.0)
88 | @available(tvOS, introduced: 10.0, obsoleted: 16.0)
89 | @available(watchOS, introduced: 3.0, obsoleted: 9.0)
90 | static var musicDirectory: URL {
91 | FileManager.default.urls(for: .musicDirectory, in: .userDomainMask).first!
92 | }
93 |
94 | /// The user’s Pictures directory (~/Pictures).
95 | @available(iOS, introduced: 11.0, obsoleted: 16.0)
96 | @available(macOS, introduced: 10.12, obsoleted: 13.0)
97 | @available(tvOS, introduced: 10.0, obsoleted: 16.0)
98 | @available(watchOS, introduced: 3.0, obsoleted: 9.0)
99 | static var picturesDirectory: URL {
100 | FileManager.default.urls(for: .picturesDirectory, in: .userDomainMask).first!
101 | }
102 |
103 | /// The user’s Public sharing directory (~/Public).
104 | @available(iOS, introduced: 11.0, obsoleted: 16.0)
105 | @available(macOS, introduced: 10.12, obsoleted: 13.0)
106 | @available(tvOS, introduced: 10.0, obsoleted: 16.0)
107 | @available(watchOS, introduced: 3.0, obsoleted: 9.0)
108 | static var sharedPublicDirectory: URL {
109 | FileManager.default.urls(for: .sharedPublicDirectory, in: .userDomainMask).first!
110 | }
111 |
112 | /// The temporary directory for the current user.
113 | @available(iOS, introduced: 11.0, obsoleted: 16.0)
114 | @available(macOS, introduced: 10.12, obsoleted: 13.0)
115 | @available(tvOS, introduced: 10.0, obsoleted: 16.0)
116 | @available(watchOS, introduced: 3.0, obsoleted: 9.0)
117 | static var temporaryDirectory: URL {
118 | URL(fileURLWithPath: NSTemporaryDirectory())
119 | }
120 |
121 | #if os(macOS)
122 | /// The trash directory.
123 | @available(iOS, introduced: 11.0, obsoleted: 16.0)
124 | @available(macOS, introduced: 10.12, obsoleted: 13.0)
125 | @available(tvOS, introduced: 10.0, obsoleted: 16.0)
126 | @available(watchOS, introduced: 3.0, obsoleted: 9.0)
127 | static var trashDirectory: URL {
128 | FileManager.default.urls(for: .trashDirectory, in: .localDomainMask).first!
129 | }
130 | #endif
131 |
132 | /// User home directories (/Users).
133 | @available(iOS, introduced: 11.0, obsoleted: 16.0)
134 | @available(macOS, introduced: 10.12, obsoleted: 13.0)
135 | @available(tvOS, introduced: 10.0, obsoleted: 16.0)
136 | @available(watchOS, introduced: 3.0, obsoleted: 9.0)
137 | static var userDirectory: URL {
138 | FileManager.default.urls(for: .userDirectory, in: .localDomainMask).first!
139 | }
140 | }
141 |
--------------------------------------------------------------------------------
/Tests/URLCompatibilityKitTests/AppendTests.swift:
--------------------------------------------------------------------------------
1 | @testable import URLCompatibilityKit
2 | import XCTest
3 |
4 | final class AppendTests: XCTestCase {
5 | func testAppendingFile() {
6 | let fileURLFromNewAPI = URL.documentsDirectory.appending(path: "myFile")
7 | let fileURLFromOldAPI = try! FileManager.default
8 | .url(
9 | for: .documentDirectory,
10 | in: .userDomainMask,
11 | appropriateFor: nil,
12 | create: false
13 | )
14 | .appendingPathComponent(
15 | "myFile", isDirectory: false
16 | )
17 | XCTAssertEqual(fileURLFromNewAPI, fileURLFromOldAPI)
18 | }
19 |
20 | func testAppendingDirectory() {
21 | let fileURLFromNewAPI = URL.documentsDirectory.appending(path: "myDir/")
22 | let fileURLFromOldAPI = try! FileManager.default
23 | .url(
24 | for: .documentDirectory,
25 | in: .userDomainMask,
26 | appropriateFor: nil,
27 | create: false
28 | )
29 | .appendingPathComponent(
30 | "myDir", isDirectory: true
31 | )
32 | XCTAssertEqual(fileURLFromNewAPI, fileURLFromOldAPI)
33 | }
34 |
35 | func testAppendFile() {
36 | var fileURLFromNewAPI = URL.documentsDirectory
37 | fileURLFromNewAPI.append(path: "myFile")
38 | let fileURLFromOldAPI = try! FileManager.default
39 | .url(
40 | for: .documentDirectory,
41 | in: .userDomainMask,
42 | appropriateFor: nil,
43 | create: false
44 | )
45 | .appendingPathComponent(
46 | "myFile", isDirectory: false
47 | )
48 | XCTAssertEqual(fileURLFromNewAPI, fileURLFromOldAPI)
49 | }
50 |
51 | func testAppendDirectory() {
52 | var fileURLFromNewAPI = URL.documentsDirectory
53 | fileURLFromNewAPI.append(path: "myDir/")
54 | let fileURLFromOldAPI = try! FileManager.default
55 | .url(
56 | for: .documentDirectory,
57 | in: .userDomainMask,
58 | appropriateFor: nil,
59 | create: false
60 | )
61 | .appendingPathComponent(
62 | "myDir", isDirectory: true
63 | )
64 | XCTAssertEqual(fileURLFromNewAPI, fileURLFromOldAPI)
65 | }
66 | }
67 |
--------------------------------------------------------------------------------
/Tests/URLCompatibilityKitTests/DirectoryTests.swift:
--------------------------------------------------------------------------------
1 | @testable import URLCompatibilityKit
2 | import XCTest
3 |
4 | final class DirectoryTests: XCTestCase {
5 | func testApplicationDirectory() {
6 | XCTAssertTrue(URL.applicationDirectory.absoluteString.hasSuffix("/Applications/"))
7 | }
8 |
9 | func testApplicationSupportDirectory() {
10 | XCTAssertTrue(URL.applicationSupportDirectory.absoluteString.hasSuffix("/Application%20Support/"))
11 | }
12 |
13 | func testCachesDirectory() {
14 | XCTAssertTrue(URL.cachesDirectory.absoluteString.hasSuffix("/Caches/"))
15 | }
16 |
17 | func testDesktopDirectory() {
18 | XCTAssertTrue(URL.desktopDirectory.absoluteString.hasSuffix("/Desktop/"))
19 | }
20 |
21 | func testDocumentsDirectory() {
22 | XCTAssertTrue(URL.documentsDirectory.absoluteString.hasSuffix("/Documents/"))
23 | }
24 |
25 | func testDownloadsDirectory() {
26 | XCTAssertTrue(URL.downloadsDirectory.absoluteString.hasSuffix("/Downloads/"))
27 | }
28 |
29 | func testHomeDirectory() {
30 | XCTAssertEqual(URL.homeDirectory, URL(fileURLWithPath: NSHomeDirectory()))
31 | }
32 |
33 | func testLibraryDirectory() {
34 | XCTAssertTrue(URL.libraryDirectory.absoluteString.hasSuffix("Library/"))
35 | }
36 |
37 | func testMoviesDirectory() {
38 | XCTAssertTrue(URL.moviesDirectory.absoluteString.hasSuffix("Movies/"))
39 | }
40 |
41 | func testMusicDirectory() {
42 | XCTAssertTrue(URL.musicDirectory.absoluteString.hasSuffix("Music/"))
43 | }
44 |
45 | func testPicturesDirectory() {
46 | XCTAssertTrue(URL.picturesDirectory.absoluteString.hasSuffix("/Pictures/"))
47 | }
48 |
49 | func testSharedPublicDirectory() {
50 | XCTAssertTrue(URL.sharedPublicDirectory.absoluteString.hasSuffix("/Public/"))
51 | }
52 |
53 | func testTemporaryDirectory() {
54 | XCTAssertTrue(URL.temporaryDirectory.absoluteString.hasSuffix("/T/") || URL.temporaryDirectory.absoluteString.hasSuffix("/tmp/"))
55 | }
56 |
57 | #if os(macOS)
58 | func testTrashDirectory() {
59 | XCTAssertTrue(URL.trashDirectory.absoluteString.hasSuffix("/.Trash/"))
60 | }
61 | #endif
62 |
63 | func testUserDirectory() {
64 | XCTAssertTrue(URL.userDirectory.absoluteString.hasSuffix("/Users/"))
65 | }
66 |
67 | func testCurrentDirectory() {
68 | XCTAssertEqual(URL.currentDirectory(), URL(fileURLWithPath: FileManager.default.currentDirectoryPath))
69 | }
70 |
71 | func testAppendingFile() {
72 | let fileURLFromNewAPI = URL.documentsDirectory.appending(path: "myFile")
73 | let fileURLFromOldAPI = try! FileManager.default
74 | .url(
75 | for: .documentDirectory,
76 | in: .userDomainMask,
77 | appropriateFor: nil,
78 | create: false
79 | )
80 | .appendingPathComponent(
81 | "myFile", isDirectory: false
82 | )
83 | XCTAssertEqual(fileURLFromNewAPI, fileURLFromOldAPI)
84 | }
85 |
86 | func testAppendingDirectory() {
87 | let fileURLFromNewAPI = URL.documentsDirectory.appending(path: "myDir/")
88 | let fileURLFromOldAPI = try! FileManager.default
89 | .url(
90 | for: .documentDirectory,
91 | in: .userDomainMask,
92 | appropriateFor: nil,
93 | create: false
94 | )
95 | .appendingPathComponent(
96 | "myDir", isDirectory: true
97 | )
98 | XCTAssertEqual(fileURLFromNewAPI, fileURLFromOldAPI)
99 | }
100 | }
101 |
--------------------------------------------------------------------------------