A collection of SwiftUI extensions, designed for organizing and reformatting data without sacrificing legibility.
Divides an array into sub-arrays based on a given integer value.
let array: [Int] = [1, 2, 3, 4, 5, 6]
print(array.chunked(into: 2)) // Returns [[1, 2, 3], [4, 5, 6]]
print(array.chunked(into: 3)) // Returns [[1, 2], [3, 4], [5, 6]]Returns the unique elements of an array.
let genres: [String] = ["drama", "comedy", "horror", "drama", "horror", "musical"]
print(genres.unique) // Returns ["drama", "comedy", "horror", "musical"Translates an integer into roman numeral format.
Represent an amount of seconds in the HH:mm:ss format.
Parameters
dynamic:A boolean value indicating if the output is shortened. Set to TRUE by default.
let time = 581
print(time.hhmmss()) // Returns "9:41"
print(time.hhmmss(dynamic: false)) // Returns "00:09:41"Shortens the decimal points of a floating value.
var longFilesize: Double = 265.452340679
let filesize: String = longFilesize.shorten()
print(filesize) // Returns "265.45"Returns the hexidecimal value of a color.
Returns the color of a hexidecimal value.
This always returns as an optional
Color.
Returns a given date in a specified format as a string.
Returns the year of a given date.
Outputs a non-diacritic, lowercased, article-less version of the string value.
var songNames = [
"Zebra Pattern",
"The Best of the Best",
"Apple of My Eye",
"untitled",
"Èl Camino",
]
print(songNames.sorted{ $0.neutral < $1.neutral })
// ["Apple of My Eye", "The Best of the Best", "Él Camino", "untitled", "Zebra Pattern"]Pluralizes text based on an integer value.
Parameters
of: The integer whose value decides whether or not the string is pluralized.es: A boolean value indicating whether or not the word is pluralized with an "es" at the end. Set to FALSE by default.unique: An optional string value for unique pluralizations.
var pizzaCount: Int = 3
var sandwichCount: Int = 4
var pizzas: String = "\(pizzaCount) pizza".plural(of: pizzaCount)
var sandwiches: String = "\(sandwichCount) sandwich".plural(of: sandwichCount, es: true)
print("\(pizzas) and \(sandwiches) ordered")
// Returns "3 pizzas and 4 sandwiches ordered"var userCount: Int = 67
var onlineUsers: String = "\(onlineUserCount) person".plural(of: userCount, unique: "people")
print("\(onlineUsers) are online")
// Returns "67 people are online"Sorts an array of names in alphabetical order of last name.
let credits: [String] = [
"Robert De Niro",
"Joe Pesci",
"Ray Liotta",
"Frank Vincent"
]
print(credits.sortedByLastName)
// ["Robert De Niro", "Ray Liotta", "Joe Pesci", "Frank Vincent"]Translates a string in any valid date format to a date.
Returns the year of a given string date, if the string is in a valid date format.
Adds a radial blur to an image.
Adds a pixelated filter to an image.
Crops an image from a given direction.
Changes a view if a given array is empty.
@State private var items: [Item] = 5
var body: some View {
List {
Section {
ForEach(items) { item in
Text(item.name)
}
}
.ifEmpty(items) { Text("No items found.") }
}
}To hide the view altogether, just return the function without a closure type.
Section {
ForEach(items) { item in
Text(item.name)
}
}
.ifEmpty(items)Saves Encodable types into a URL or a UserDefaults key-value pair.
The save() function takes encoding and writing operations such as this:
@Published var allItems: [Item] = // ...
private let itemsURL: URL
do {
let data = try JSONEncoder().encode(allItems)
try data.write(to: itemsURL)
}
catch {
print(error)
}...and executes them in a single line:
try allItems.save(toURL: itemsURL)Works identically for UserDefaults keys, so instead of this:
let encoded = try JSONEncoder().encode(allItems)
UserDefaults.standard.set(encoded, forKey: userDefaultsKey)...just do this!
try allItems.save(toUserDefaultsKey: "items")save() can also be used directly on URLs and UserDefault keys.
@Published var items: [Item] = // ...
private let itemsURL: URL
try itemsURL.save(items)
private let key: String = "itemsData"
try key.save(items)Loads Decodable types from a URL, String key, or directly from Data.
// Instead of doing this to decode a ```URL```...
@Published var allItems: [Item] = // ...
private let itemsURL: URL
do {
let data = try Data(contentsOf: itemsURL)
try JSONDecoder().decode([Item].self, from: data)
}
catch {
print(error)
}
/// ...simply do this!
try itemsURL.load([Item].self)Same goes for String and Data:
// Instead of this...
if let userDefaults = UserDefaults.standard.data(forKey: "items") {
let decoded = try JSONDecoder().decode([Item].self, from: userDefault)
allItems = decoded
}
// ...do this!
try "items".load(into: allItems)let data = try Data(contentsOf: itemsURL)
/// Instead of this...
let decoded = try JSONDecoder().decode([Item].self, from: data)
return decoded
/// ...do this!
try data.load([Item].self)NOTE: Each save and load function has a "soft-throw" variation for instances where normal
throwswould be inconvienent.
item.save(toURL: itemURL) { error in print(error) }Conforms any collection into an Array.
Designed for variables that conform to more rigid types, such as SubSequence or ArraySlice.
@State private var infiniteScroll: Bool = false
func filterItems(_ arr: [Item]) -> [Item] {
return arr.filter { $0.in_stock == false }
}
let allItems: [Item] = user.items
let firstPageItems: ArraySlice<Item> = allItems[0...9]
var firstPageResults: [Item] {
if infiniteScroll {
return filterItems(allItems)
}
else {
return filterItems(firstPageItems.array)
// No type mismatch, returns as [Item]
}
}Clamps the output of a value between a minimum and maximum value.
let currentExp = 187
let expBar = clamp(0, 100) { currentExp }
print(expBar) // Returns 100Dialogue is available under the MIT license. See the LICENSE file for more info.