Update extension documentation

This commit is contained in:
Daniel Saidi 2021-09-08 11:55:41 +02:00
parent 7410d89f87
commit 8bc1f18e12
22 changed files with 121 additions and 13 deletions

View File

@ -21,6 +21,7 @@ This version also cleans up the code and makes changes to conform to the latest
* All previously deprecated features have been removed.
* `ApiService` moves the `type` param before the `httpMethod`, since `httpMethod` now has a default value.
* `ApiRoute` and `ApiService` now use enum-based HTTP methods instead of string-based ones.
* `DispatchQueue+Async` now requires that you explicitly define `seconds` when using that `asyncAfter` function.
* `URL+Global` `appStoreUrl(forAppId:)` now returns an optional url.

View File

@ -13,12 +13,18 @@ import Foundation
*/
extension Bundle: BundleInformation {
/**
Get the bundle build number.
*/
public var buildNumber: String {
let key = String(kCFBundleVersionKey)
let version = infoDictionary?[key] as? String
return version ?? ""
}
/**
Get the bundle version number.
*/
public var versionNumber: String {
let key = "CFBundleShortVersionString"
let version = infoDictionary?[key] as? String

View File

@ -10,6 +10,10 @@ import Foundation
public extension Array where Element: Comparable & Strideable {
/**
Create an array using a set of values from the provided
`range`, stepping `stepSize` between each value.
*/
init(_ range: ClosedRange<Element>, stepSize: Element.Stride) {
self = Array(stride(from: range.lowerBound, through: range.upperBound, by: stepSize))
}
@ -17,6 +21,10 @@ public extension Array where Element: Comparable & Strideable {
public extension Array where Element == Double {
/**
Create an array using a set of values from the provided
`range`, stepping `stepSize` between each value.
*/
init(_ range: ClosedRange<Element>, stepSize: Element.Stride) {
self = Array(stride(from: range.lowerBound, through: range.upperBound, by: stepSize))
.map { $0.roundedWithPrecision(from: stepSize) }

View File

@ -10,5 +10,8 @@ import Foundation
public extension Collection {
/**
Check whether or not the collection has any elements.
*/
var hasContent: Bool { !isEmpty }
}

View File

@ -10,6 +10,10 @@ import Foundation
public extension Collection where Element: Hashable {
/**
Get distinct values from the collection, preserving the
original order.
*/
func distinct() -> [Element] {
reduce([]) { $0.contains($1) ? $0 : $0 + [$1] }
}

View File

@ -11,7 +11,7 @@ import Foundation
public extension Sequence {
/**
Batch the sequence into groups of a certain max size.
Batch the sequence into groups of a certain batch size.
*/
func batched(withBatchSize size: Int) -> [[Element]] {
var result: [[Element]] = []

View File

@ -15,6 +15,11 @@ public enum PreferredClosestValue {
public extension Comparable {
/**
Get the closest value in the provided `collection`. The
provided `preferred` value whether to prefer a `greater`
or a `lower` value if no exact match was found.
*/
func closest(in collection: [Self], preferred: PreferredClosestValue) -> Self? {
if collection.contains(self) { return self }
let sorted = collection.sorted()

View File

@ -11,14 +11,14 @@ import Foundation
public extension Comparable {
/**
Limit the value to a range.
Limit the value to a closed range.
*/
mutating func limit(to range: ClosedRange<Self>) {
self = limited(to: range)
}
/**
Return the value limited to a range.
Return the value limited to a closed range.
This could be implemented in a oneliner, but that would
make the code less readable.

View File

@ -1,5 +1,5 @@
//
// Comparable+Limit.swift
// ComparisonResult+Shortcuts.swift
// SwiftKit
//
// Created by Daniel Saidi on 2020-06-09.
@ -10,6 +10,17 @@ import Foundation
public extension ComparisonResult {
static var ascending: ComparisonResult { return .orderedAscending }
static var descending: ComparisonResult { return .orderedDescending }
/**
This is a shorthand to `.orderedAscending`
*/
static var ascending: ComparisonResult {
.orderedAscending
}
/**
This is a shorthand to `.orderedDescending`
*/
static var descending: ComparisonResult {
.orderedDescending
}
}

View File

@ -26,7 +26,7 @@ public extension DispatchQueue {
Perform an operation after a time interval.
*/
func asyncAfter(
_ seconds: TimeInterval,
seconds: TimeInterval,
execute: @escaping () -> Void) {
let milli = Int(seconds * 1000)
asyncAfter(.milliseconds(milli), execute: execute)

View File

@ -10,6 +10,9 @@ import Foundation
public extension Decimal {
/**
The value's `Double` value representation.
*/
var doubleValue: Double {
Double(truncating: self as NSNumber)
}

View File

@ -10,6 +10,13 @@ import Foundation
public extension Optional {
/**
Whether or not the value is `nil`.
*/
var isNil: Bool { self == nil }
/**
Whether or not the value is set and not `nil`.
*/
var isSet: Bool { self != nil }
}

View File

@ -12,11 +12,17 @@ import Foundation
public extension String {
/**
Base64 decode the string.
*/
func base64Decoded() -> String? {
guard let data = Data(base64Encoded: self) else { return nil }
return String(data: data, encoding: .utf8)
}
/**
Base64 encode the string.
*/
func base64Encoded() -> String? {
data(using: .utf8)?.base64EncodedString()
}

View File

@ -12,6 +12,9 @@ import Foundation
public extension String {
/**
Check whether or not the string contains another string.
*/
func contains(_ string: String, caseSensitive: Bool) -> Bool {
caseSensitive
? contains(string)

View File

@ -10,10 +10,17 @@ import Foundation
public extension String {
/**
Check whether or not the string has any content.
*/
var hasContent: Bool {
!isEmpty
}
/**
Check whether or not the string has any trimmed content
after leading and trailing whitespaces are removed.
*/
var hasTrimmedContent: Bool {
!trimmingCharacters(in: .whitespaces).isEmpty
}

View File

@ -14,6 +14,11 @@ public extension String {
This function cleans up the string from space and other
strange characters that can be added to the string when
the user performs a dictation.
This happens on the Apple TV, when a user uses a remote
to dictate text into a text field. The resulting string
contains a bunch of additional information and not just
the plain string.
*/
func cleanedUpAfterDictation() -> String {
self

View File

@ -8,11 +8,6 @@
import Foundation
/**
This extension is internally used by `TagTextView` and will
not be public in order to not collide with the extension in
`SwiftKit`. If you want to use the logic, import `SwiftKit`.
*/
public extension String {
private static let allowedCharacters = NSCharacterSet(charactersIn: "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-")

View File

@ -10,6 +10,9 @@ import Foundation
public extension String {
/**
Split the string using a list of separators.
*/
func split(by separators: [String]) -> [String] {
let separators = CharacterSet(charactersIn: separators.joined())
return components(separatedBy: separators)

View File

@ -12,6 +12,13 @@ import Foundation
public extension String {
/**
URL encode the string.
This will first call `addingPercentEncoding`, using the
`.urlPathAllowed` character set, then replace every `&`
with `%26`.
*/
func urlEncoded() -> String? {
addingPercentEncoding(withAllowedCharacters: .urlPathAllowed)?
.replacingOccurrences(of: "&", with: "%26")

View File

@ -10,8 +10,15 @@ import Foundation
public extension URL {
/**
This url leads to the Apple subscription screen for the
currently logged in account.
*/
static let userSubscriptions = URL(string: "https://apps.apple.com/account/subscriptions")
/**
This url leads to the App Store page for a certain app.
*/
static func appStoreUrl(forAppId appId: Int) -> URL? {
URL(string: "https://itunes.apple.com/app/id\(appId)")

View File

@ -10,21 +10,35 @@ import Foundation
public extension URL {
/**
Get the url's query parameters.
*/
var queryParameters: [URLQueryItem] {
URLComponents(string: absoluteString)?.queryItems ?? [URLQueryItem]()
}
/**
Get the url's query parameters as a dictionary.
*/
var queryParametersDictionary: [String: String] {
var result = [String: String]()
queryParameters.forEach { result[$0.name] = $0.value ?? "" }
return result
}
/**
Get a certain query parameter by name.
*/
func queryParameter(named name: String) -> URLQueryItem? {
queryParameters.first { $0.isNamed(name) }
}
/**
Set the value of a certain query parameter.
This will return a new url where the query parameter is
either updated or added.
*/
func setQueryParameter(name: String, value: String, urlEncode: Bool = true) -> URL? {
guard let urlString = absoluteString.components(separatedBy: "?").first else { return self }
let param = queryParameter(named: name)
@ -34,6 +48,12 @@ public extension URL {
return URL(string: "\(urlString)?\(dictionary.queryString)")
}
/**
Set the value of a certain set of query parameters.
This will return a new url, where every query parameter
in the dictionary is either updated or added.
*/
func setQueryParameters(_ dict: [String: String], urlEncode: Bool = true) -> URL? {
var result = self
dict.forEach {

View File

@ -10,12 +10,19 @@ import Foundation
public extension UserDefaults {
/**
Returns the codable object associated with the provided
key, provided that the persisted value can be decoded.
*/
func codable<T: Codable>(forKey key: String) -> T? {
guard let data = object(forKey: key) as? Data else { return nil }
let value = try? JSONDecoder().decode(T.self, from: data)
return value
}
/**
Persist a codable item.
*/
func setCodable<T: Codable>(_ codable: T, forKey key: String) {
let data = try? JSONEncoder().encode(codable)
set(data, forKey: key)