@@ -18,19 +18,39 @@ extension Array where Element == URL {
18
18
/// Sorts the elements in alphabetical order.
19
19
/// - Parameter foldersOnTop: if set to `true` folders will always be on top of files.
20
20
/// - Returns: A sorted array of `URL`
21
- func sortItems( foldersOnTop: Bool ) -> Self {
22
- var alphabetically = sorted { $0. lastPathComponent < $1. lastPathComponent }
21
+ func sortItems( foldersOnTop: Bool ) -> [ URL ] {
22
+ return self . sorted { lhs, rhs in
23
+ let lhsIsDir = ( try ? lhs. resourceValues ( forKeys: [ . isDirectoryKey] ) . isDirectory) ?? false
24
+ let rhsIsDir = ( try ? rhs. resourceValues ( forKeys: [ . isDirectoryKey] ) . isDirectory) ?? false
23
25
24
- if foldersOnTop {
25
- var foldersOnTop = alphabetically. filter { $0. isFolder }
26
- alphabetically. removeAll { $0. isFolder }
26
+ if foldersOnTop {
27
+ if lhsIsDir != rhsIsDir {
28
+ return lhsIsDir
29
+ }
30
+ }
27
31
28
- foldersOnTop. append ( contentsOf: alphabetically)
32
+ return compareNaturally ( lhs. lastPathComponent, rhs. lastPathComponent)
33
+ }
34
+ }
29
35
30
- return foldersOnTop
31
- } else {
32
- return alphabetically
36
+ /// Compare two strings using natural sorting.
37
+ /// - Parameters:
38
+ /// - lhs: The left-hand string.
39
+ /// - rhs: The right-hand string.
40
+ /// - Returns: `true` if `lhs` should be ordered before `rhs`.
41
+ private func compareNaturally( _ lhs: String , _ rhs: String ) -> Bool {
42
+ let lhsComponents = lhs. components ( separatedBy: CharacterSet . decimalDigits. inverted)
43
+ let rhsComponents = rhs. components ( separatedBy: CharacterSet . decimalDigits. inverted)
44
+
45
+ for (lhsPart, rhsPart) in zip ( lhsComponents, rhsComponents) where lhsPart != rhsPart {
46
+ if let lhsNum = Int ( lhsPart) , let rhsNum = Int ( rhsPart) {
47
+ return lhsNum < rhsNum
48
+ } else {
49
+ return lhsPart < rhsPart
50
+ }
33
51
}
52
+
53
+ return lhs < rhs
34
54
}
35
55
}
36
56
0 commit comments