DJSwiftHelpers is a Swift library containing useful Swift extensions. It allows you to perform many tasks easily.
Add the package [email protected]:ddaddy/DJSwiftHelpers.git
to your project.
For most helpers you can import DJSwiftHelpers
however for additional UIKit
or SwiftUI
helpers that are not extension friendly, also import DJSwiftHelpers_UIKit
or import DJSwiftHelpers_SwiftUI
Install Carthage if not already installed
Change to the directory of your Xcode project, and Create and Edit your Cartfile and add DJSwiftHelpers:
$ cd /path/to/MyProject
$ touch Cartfile
$ open Cartfile
Add the following line to your Cartfile
github "ddaddy/DJSwiftHelpers"
Save and then run:
$ carthage update --use-xcframeworks
Once complete, drag libraries as required
- Carthage/Build/iOS/DJSwiftHelpers
- Carthage/Build/iOS/DJSwiftHelpers_Extension
- Carthage/Build/iOS/DJSwiftHelpers_SwiftUI
into the Frameworks, Libraries & Embeded Content
section of your project.
If adding to an extension, select Do not embed
but also add to your main iOS
or watchOS
app and select Embed & Sign
.
Removes an element from an Array
. If the element occurs multiple times in the array, only the first element will be removed.
remove(element: Element)
Moves an element to a new index
move(_ element: Element, to newIndex: Index)
move(from oldIndex: Index, to newIndex: Index)
Split an Array
into multiple arrays of size
chunked(into size: Int) -> [[Element]]
Filters an array to return one of each item where the keyPath elements are unique
uniques<T: Hashable>(by keyPath: KeyPath<Element, T>) -> [Element]
Example:
.uniques(by: \.surname)
Filters an array to return one of each item where the combined keyPath elements are unique
uniques<T: Hashable, U: Hashable>(by keyPath: KeyPath<Element, T>, and secondKeyPath: KeyPath<Element, U>) -> [Element]
Example:
.uniques(by: \.firstName, and: \.surname)
Adds a listener to array elements
elementChangeListener(cancellables: inout [AnyCancellable], change: @escaping (Element)->())
Determine if a location is within a bounding rect
locationIsInside(minLat:Double, maxLat:Double, minLong:Double, maxLong:Double) -> Bool
Removes the risk of indexOutOfBounds
crashes.
subscript(safe index: Index) -> Element?
// array[safe: 5]
Create a Date
from some date elements
Date.from(year: Int, month: Int, day: Int) -> Date?
Create a Date
from a date string. Be careful using this because DateFormatter
's can be
very expensive for performance.
Date.parse(_ string: String, format: String = "yyyy-MM-dd") -> Date?
Adds additional seconds or minutes to a Date
adding(seconds: Int) -> Date
adding(minutes: Int) -> Date
Deduct one Date
from another
- (lhs: Date, rhs: Date) -> TimeInterval
Converts an iso8601 string with or without milliseconds 2020-11-11T11:39:00Z
ro 2020-11-11T11:39:00.000Z
WARNING! These are expensive operations so probably best not to use in a loop
var iso8601: String
var iso8601withFractionalSeconds: String
var iso8601: Date?
var iso8601withFractionalSeconds: Date?
Skips to the next container whilst iterating over an unkeyed decoding container using while !container.isAtEnd { }
skip()
Property wrapper that allows a Decodable
var
to be decoded from either a String
or an Int
struct GeneralProduct: Decodable {
var price: Double
// These can be decoded from either String or Int
@Flexible var intId: Int
@Flexible var stringId: String
}
Round doubles for less accurate comparisons
static func equal(_ lhs: Double, _ rhs: Double, precise value: Int? = nil) -> Bool
func precised(_ value: Int = 1) -> Double
Determines if running inside an app extension or not
static var isExtension:Bool
Fetches all contents (files & folders) in a specified file path and all subfolders
allContents(path: String) -> [URL]
Fetch contents (files & folders) in a specifies file path, none recursive
urls(for directory: FileManager.SearchPathDirectory, skipsHiddenFiles: Bool = true ) -> [URL]?
urls(for directory: URL, skipsHiddenFiles: Bool = true ) -> [URL]?
Parse a json
file into the specified object type
readJSONFromFile<T: Decodable>(fileURL: URL, type: T.Type) -> T?
A UIView
subclass with a gradient background.
Can be used in a storyboard as it supports IBDesignable
however to use IBDesignable
from an external framework you need to add this small class to your project:
@IBDesignable
class GradientView: Gradient {
@IBInspectable override var startColor: UIColor {get { return super.startColor }set { super.startColor = newValue }}
@IBInspectable override var endColor: UIColor {get { return super.endColor }set { super.endColor = newValue }}
@IBInspectable override var startLocation: Double {get { return super.startLocation }set { super.startLocation = newValue }}
@IBInspectable override var endLocation: Double {get { return super.endLocation }set { super.endLocation = newValue }}
@IBInspectable override var horizontalMode: Bool {get { return super.horizontalMode }set { super.horizontalMode = newValue }}
@IBInspectable override var diagonalMode: Bool {get { return super.diagonalMode }set { super.diagonalMode = newValue }}
}
Return the emoji flag for the given Locale
var emojiFlag: String
Change the colour of certain text within an NSMutableAttributedString
func setColorForText(textToFind: String, withColor color: UIColor)
Truncate a string by removing all characters at the position
truncated(limit: Int, position: TruncationPosition = .tail, leader: String = "") -> String
Delete a prefix if it exists
deletingPrefix(_ prefix: String) -> String
Allows you to use [8] subscript to get 1 character from a String
subscript(_ i: Int) -> String
Allows you to use [0..<9] subscript to truncate a String
subscript (r: Range<Int>) -> String
Allows you to use [0...8] subscript to truncate a String
subscript (r: CountableClosedRange<Int>) -> String
Convert a String into a Bool by looking for the relevant type texts (Yes, No, True etc..)
var bool: Bool?
Convert a String into a Double
toDouble() -> Double?
Convert a String to Data then saves it to the given URL path
save(path:URL) -> Bool
index<S: StringProtocol>(of string: S, options: String.CompareOptions = []) -> Index?
endIndex<S: StringProtocol>(of string: S, options: String.CompareOptions = []) -> Index?
indices<S: StringProtocol>(of string: S, options: String.CompareOptions = []) -> [Index]
ranges<S: StringProtocol>(of string: S, options: String.CompareOptions = []) -> [Range<Index>]
Splits a string into an array of lines
var lines: [SubSequence]
Returns a string that appears between 2 strings
func slice(from: String? = nil, to: String? = nil) -> String?
Creates a recurring Task
that executes until success
static func retrying(priority: TaskPriority? = nil, maxRetryCount: Int = .max, retryDelay: TimeInterval = 1, operation: @Sendable @escaping () async throws -> Success) -> Task
Return the top most ViewController regardless if embeded in a navigation stack or not
class getTopViewController(base: UIViewController? = UIApplication.shared.keyWindow?.rootViewController) -> UIViewController?
Display an alert regardless of what's on the screen
class displayGlobalAlert(title:String, message:String, completion: (() -> Void)? = nil)
Dismiss back to the root view controller
class dismisstoRoot(animated:Bool, completion:(() -> Void)? = nil)
Add an underline style to the title label
underlineText()
Convert a hex string to a UIColor
init?(hex: String)
Find the opposite colour of a UIColor
var inverted: UIColor
var isPhone: Bool
var isPad: Bool
var isTV: Bool
var isCarPlay: Bool
Specify a font weight to a dynamic font style
static func preferredFont(for style: TextStyle, weight: Weight) -> UIFont
use like:
label.font = UIFont.preferredFont(for: .title2, weight: .medium)
Convert a String to Data then save it to the given URL path
saveAsPNG(path:URL) -> Bool
Save an image to a temporary file
tempURLForImage(named name: String) -> URL?
Resize an image
resize(width: CGFloat) -> UIImage
resize(height: CGFloat) -> UIImage
resize(size: CGSize) -> UIImage
Adds an SFSymbol
image to the beginning or end of a UILabel
's text
addSFSymbol(named:String, position:UILabel.SFSymbolPosition = .beginning, fontWeight weight:UIFont.Weight = .bold, fontDescriptorDesign design:UIFontDescriptor.SystemDesign = .rounded)
Remove and dealloc all subviews from a UIStackView
safelyRemoveArrangedSubviews()
Add a background color to a UIStackView
addBackground(color: UIColor)
Sets up the autolayout constraints to pin a view to it's superview
pinToSuperview(with insets: UIEdgeInsets = .zero, edges: UIRectEdge = .all)
Add a border to the insied of a UIView
at a specific edge
addBorder(_ edge: UIRectEdge, color: UIColor, thickness: CGFloat)
Displays a UIAlertController
message with an "Ok" cancel button
displayAlert(title:String?, message:String?)
displayAlert(title:String?, message:String?, buttonAction:((UIAlertAction)->())?)
Add's & removes a child UIViewController
to a continer view
addChild(_ child: UIViewController, in containerView: UIView)
removeChild(_ child: UIViewController)
Fetches the key window
var key: UIWindow?
Generates a URLRequest
whilst automatically converting headers and body to the correct formats
init?(url:URL, headers:[String:String], postBody:[String:Any], json:Bool = true, timeout:TimeInterval = 60.0)
init?(url:URL, headers:[String:String], postString:String, timeout:TimeInterval = 60.0)
init?(url:URL, headers:[String:String], parameters:[String:String], timeout:TimeInterval = 60.0)
Returns the HTTP status code from a URLResponse
statusCode() -> Int?
A URLSession that will bypass an SSL certificate check.
static var selfSignedSSLSession:URLSession
Save to UserDefaults or remove it if nil
setOrDelete(value:String?, forKey key:String)
setOrDelete(value:Int?, forKey key:String)
Delete all UserDefault
's for the containing bundleIdentifier
func resetDefaults()
A backward compatible NavigationStack
NavigationStackPre16() {
SomeRootView()
}
A SwiftUI view to display the share sheet with Open in Safari
Example:
.background(
// Share button action
SafariActivityView(isPresented: $activityPresented, url: url)
)
A UIActivityViewController
used to present a Share Sheet
Example:
struct ShareItem: Identifiable {
let id = UUID()
let data: Data
}
SomeView()
.sheet(item: $shareItem) { shareItem in
ActivityView(item: shareItem.data)
.presentationDetents([.medium])
}
A SwiftUI view modifier that executes a block of code only once during the first display of the view
.onFirstAppear(_ action: @escaping () -> ()) -> some View
Copyright (c) 2020 Darren Jones (Dappological Ltd.)