NerdzUtils
is a Swift framework designed to simplify and enhance common development tasks by providing a collection of utility classes and extensions. The framework is organized into three main folders:
-
Extensions
: This folder extends the functionality of Swift'sFoundation
andUIKit
frameworks.- Foundation: Contains extensions for Foundation framework, adding utility methods and functionalities to Swift's core types.
- UIKit: Includes extensions for UIKit framework, providing additional functionality to UI components and views.
-
UI Components
: This folder houses custom UI components that can be easily integrated into your iOS projects. The components are designed to enhance user interfaces with features like loadable buttons, loadable image views, etc. -
Utils
: The Utils folder contains various utility classes that serve as building blocks for common programming patterns. Some of the included classes are SyncPropertyActor, DelayedAction, AtomicAsyncOperation, and more.
The Array+Safe
extension adds a subscript (safe
) to the Array
type, allowing safe access to elements by index. It helps prevent index out-of-range errors by returning nil
if the requested index is beyond the array bounds.
// Create an array
let myArray = [1, 2, 3, 4, 5]
// Access elements safely using the 'safe' subscript
if let element = myArray[safe: 2] {
print("Element at index 2: \(element)")
}
else {
print("Index 2 is out of range.")
}
// Try accessing an element at an out-of-range index
if let element = myArray[safe: 10] {
print("Element at index 10: \(element)")
}
else {
print("Index 10 is out of range.")
}
The Bundle+CurrentAppVersion
extension adds a computed property appVersion
to the Bundle
type. This property provides a convenient way to retrieve the current application version from the app's Info.plist
file.
let currentVersion = Bundle.main.appVersion
This extension for CGSize
provides convenient utilities for handling sizes with specific aspect ratios.
- w16_h9: Provides a minimal size with a 16:9 aspect ratio.
- w9_h16: Provides a minimal size with a 9:16 aspect ratio.
- w4_h3: Provides a minimal size with a 4:3 aspect ratio.
- w3_h4: Provides a minimal size with a 3:4 aspect ratio.
- scaled(by:): Scales the size by a given factor.
// Access aspect ratio sizes
let size16x9 = CGSize.w16_h9
let sizeScaled = CGSize(width: 10, height: 5).scaled(by: 2.0)
// ... (use other aspect ratios and methods as needed)
The DateDecodingStrategy+CustomISO8601
extension provides a custom DateDecodingStrategy
for parsing ISO 8601 dates with fractional seconds.
- customISO8601: A custom date decoding strategy for ISO 8601 dates with fractional seconds.
To use the DateDecodingStrategy+CustomISO8601
extension, follow these steps:
Use the customISO8601
strategy when configuring your JSONDecoder
instance to handle ISO 8601 dates with fractional seconds.
// Create a JSONDecoder with the custom date decoding strategy
let decoder = JSONDecoder()
decoder.dateDecodingStrategy = .customISO8601
// Use the decoder to decode JSON containing ISO 8601 dates with fractional seconds
let jsonData = """
{"date": "2024-02-05T12:34:56.789Z"}
""".data(using: .utf8)!
let decodedObject = try decoder.decode(MyObject.self, from: jsonData)
The DispatchQueue+Once
extension provides a mechanism to ensure that a block of code is executed only once, regardless of how many times it is called.
- once(per:token:action:): Execute a block of code once per provided token associated with an object.
- once(for:action:): Execute a block of code once per provided token.
-
Execute Code Once Per Token:
Use the
once(per:token:action:)
method to ensure that a block of code is executed only once per provided token associated with an object.private func requestDefaultPermissions() async { DispatchQueue.nz.once(per: self, token: permissionsToken) { [weak self] in self?.permissionsManager.requestFirstLaunchStartupPermissions() } }
-
Execute Code Once Per Token Directly:
Alternatively, use the
once(for:action:)
method to execute a block of code once per provided token directly.DispatchQueue.nz.once(for: "uniqueToken") { // Code to be executed once }
The Encodable+JsonData
extension simplifies the process of converting objects conforming to the Encodable
protocol into JSON data.
- nz_jsonData: Returns JSON data for the given object.
struct MyStruct: Encodable {
let id: Int
let title: String
}
let myObject = MyStruct(id: 1, title: "Sample Title")
// Get JSON data from the encodable object
if let jsonData = myObject.nz_jsonData {
// Use jsonData as needed
print("JSON Data: \(String(data: jsonData, encoding: .utf8) ?? "Unable to convert to string")")
}
The Formatter+iso8601
extension provides ISO8601 date formatters with and without fractional seconds.
- iso8601WithFS: ISO8601 date formatter with fractional seconds.
- iso8601: ISO8601 date formatter without fractional seconds.
// Format a date with fractional seconds
let currentDateWithFS = Date()
let formattedWithFS = Formatter.iso8601WithFS.string(from: currentDateWithFS)
// Format a date without fractional seconds
let currentDate = Date()
let formattedWithoutFS = Formatter.iso8601.string(from: currentDate)
The NZUtilsExtensionData
and NZUtilsExtensionCompatible
provide a foundation for creating Swift extensions with a fluent syntax, allowing you to add utility methods to existing types.
- NZUtilsExtensionData: A wrapper class for extending functionality.
- NZUtilsExtensionCompatible: A protocol to make types compatible with NZUtils extensions.
// Example: Creating an NZUtilsExtensionData wrapper
let myInteger = 42
let wrapper = NZUtilsExtensionData(myInteger)
// Access the base value
let baseValue = wrapper.base // This will be 42
// Example: Making a type compatible with NZUtils extensions
struct MyStruct:NZUtilsExtensionCompatible {
var value: String
}
// Use NZUtilsExtensionData for MyStruct
let myInstance = MyStruct(value: "Hello")
let wrappedInstance = myInstance.nz
// Access the base value
let baseValue = wrappedInstance.base // This will be an instance of MyStruct
The Locale+CountryList
extension provides convenient methods to retrieve a list of countries and obtain details for a specific country based on the current device locale.
- countryList: Returns a list of countries based on the current device locale.
- country(from:): Provides details for a specific country based on its region code.
// Access country list
let countries [Country] = Locale.current.countryList
// Access details for a specific country (e.g., "US")
if let countryDetails = Locale.current.country(from: "US") {
print("Country Code: \(countryDetails.code), Country Name: \(countryDetails.name)")
}
The NSObject+ClassName
extension provides convenient methods to retrieve the class name of an NSObject instance.
- className (static): Returns the class name of the NSObject class itself.
- className (instance): Returns the class name of the current instance of NSObject.
-
Access Class Name (Static):
// Access class name for MyClass let className = MyClass.className
-
Access Class Name (Instance):
// Create an instance of MyClass let myClass = MyClass() // Access class name for the instance let instanceClassName = myClass.nz.className
The String+Attributed
extension provides a convenient method to create an attributed string from a String
with specified attributes.
- attributed(with:): Forms an attributed string with the given attributes.
let originalString = "Hello, World!"
let attributes: [NSAttributedString.Key: Any] = [
.font: UIFont.boldSystemFont(ofSize: 16),
.foregroundColor: UIColor.blue
]
let attributedString = originalString.nz.attributed(with: attributes)
The String+IsWhiteSpaceOrEmpty
extension provides a convenient method to check whether a string is empty or consists only of white spaces and new lines.
- isWhiteSpaceOrEmpty: Returns
true
if the string is empty or consists only of white spaces and new lines; otherwise, returnsfalse
.
let emptyString = ""
let whitespaceString = " "
let nonEmptyString = "Hello, World!"
let isEmpty = emptyString.nz.isWhiteSpaceOrEmpty // true
let isWhitespace = whitespaceString.nz.isWhiteSpaceOrEmpty // true
let isNonEmpty = nonEmptyString.nz.isWhiteSpaceOrEmpty // false
The String+Localization
extension provides a convenient method to obtain the localized representation of a string, with support for overriding the current locale.
- localized: Returns the localized representation of the current string.
- overridenLocale (static): Property to set or retrieve an overridden locale for localization.
-
Get Localized String:
Use the
localized
property to obtain the localized representation of a string.let originalString = "hello_key" let localizedString = originalString.nz.localized
In this example, localizedString will contain the localized representation of the string with the key
"hello_key"
. -
Override Locale:
Optionally, use the overridenLocale property to set or retrieve an overridden locale for localization.
originalString.nz.overridenLocale = "fr" // Set to "fr" for French locale // Access the localized string with the overridden locale let frenchLocalizedString = originalString.nz.localized
Note: Ensure that the overridden locale is a valid locale identifier (e.g., "fr" for French).
The String+VersionCompare
extension provides methods to compare string versions to a target version, allowing for easy version comparison in Swift projects.
- isVersion(equalTo:): Returns
true
if the string version is equal to the target version. - isVersion(greaterThan:): Returns
true
if the string version is greater than the target version. - isVersion(greaterThanOrEqualTo:): Returns
true
if the string version is greater than or equal to the target version. - isVersion(lessThan:): Returns
true
if the string version is less than the target version. - isVersion(lessThanOrEqualTo:): Returns
true
if the string version is less than or equal to the target version.
// Example: Comparing string versions
let currentVersion = "1.2.3"
let targetVersion = "1.2.0"
let isEqual = currentVersion.nz.isVersion(equalTo: targetVersion) // false
let isGreater = currentVersion.nz.isVersion(greaterThan: targetVersion) // true
let isGreaterOrEqual = currentVersion.nz.isVersion(greaterThanOrEqualTo: targetVersion) // true
let isLess = currentVersion.nz.isVersion(lessThan: targetVersion) // false
let isLessOrEqual = currentVersion.nz.isVersion(lessThanOrEqualTo: targetVersion) // false
The UIApplication+OpenSettings
extension provides a convenient method to open the native settings of the app on iOS.
- openSettings: Opens the app's native settings.
let application = UIApplication.shared
application.openSettings()
The UIApplication+Jailbreak
extension provides a utility method to check whether the current device might be jailbroken.
- isJailbroken: Verifies if the current device might be jailbroken.
let application = UIApplication.shared
let isJailbroken = application.nz.isJailbroken
The UIColor+Hex
extension provides a convenient initializer to create a UIColor
instance from a hexadecimal color code.
- init(hex: String, alpha: CGFloat): Creates a
UIColor
instance from a hexadecimal color code with an optional alpha value.
let hexColor = "#FF5733"
let alphaValue: CGFloat = 1.0
let color = UIColor(hex: hexColor, alpha: alphaValue)
The UIAlertController+Extensions
provides convenient extensions to streamline the creation and presentation of UIAlertController
instances in Swift.
- action(title:handler:): Adds a default action to the alert.
- destructive(title:handler:): Adds a destructive action to the alert.
- cancel(title:handler:): Adds a cancel action to the alert.
- source(_:): Sets up the controller source view for tablets.
- show(on:): Presents the alert on a given controller.
// Example: Creating and presenting an alert
let alertController = UIAlertController(title: "Title", message: "Message", preferredStyle: .alert)
alertController.nz
.action(title: "Default Action") {
// Handle default action
}
.destructive(title: "Destructive Action") {
// Handle destructive action
}
.cancel(title: "Cancel Action") {
// Handle cancel action
}
.source(sourceView)
.show(on: presentingController)
The UIButton+Localized
extension provides a convenient way to set localized text for UIButton
instances, especially useful when working with nib files.
- textLocalization: Sets the localized text for a button.
- nz_textLocalization: An
@IBInspectable
property for setting localized text directly in Interface Builder.
-
Set Localized Text Programmatically:
let button = UIButton(type: .system) button.nz.textLocalization = "buttonTitleKey"
-
Set Localized Text in Interface Builder:
Use the @IBInspectable property nz_textLocalization to set localized text directly in Interface Builder.
The UIColor+Inversed
extension provides a simple way to obtain the inverse color of a given UIColor
. This can be useful for creating visually contrasting elements in your app.
- inversed: Computes and returns the inverse color of the current color.
-
Compute Inverse Color Programmatically:
let originalColor = UIColor.red let inverseColor = originalColor.nz.inversed
-
Apply Inverse Color in UI Elements:
let originalColor = UIColor.blue let inverseColor = originalColor.nz.inversed let myView = UIView() myView.backgroundColor = originalColor // Set the original color // ... // Apply the inverse color to another UI element someOtherElement.backgroundColor = inverseColor
The UIControl+ClosureAction
extension allows you to easily add closure-based actions to a UIControl
. This provides a more concise and expressive way to handle control events.
- addAction(for:closure:): Adds a closure-based action for a specific control event.
-
Add Closure-Based Action:
let myButton = UIButton() myButton.nz.addAction(for: .touchUpInside) { print("Button tapped!") }
-
Handle Control Events with Closures:
let mySwitch = UISwitch() mySwitch.nz.addAction(for: .valueChanged) { print("Switch value changed!") }
The UIImage+BlurHash
extension provides an easy way to initialize a UIImage
using the BlurHash algorithm. BlurHash is a compact representation of a placeholder for an image, useful for lazy loading images with a placeholder effect.
- Initialization from BlurHash: Initialize a
UIImage
using the BlurHash algorithm, providing hash information including the BlurHash string, rendering size, and punch.
let blurHashInfo = BlurHashInfo(
hash: "LEHV6nWB2yk8pyo0adR*.7kCMdnj",
size: CGSize(width: 320, height: 240)
)
if let blurredImage = UIImage(info: blurHashInfo) {
// Use the blurredImage as a placeholder or background
}
The UIImage+Scale
extension provides convenient methods for scaling UIImage
objects based on width, height, or custom size requirements.
- Scaling by Width: Scale an image to a specific width.
- Scaling by Height: Scale an image to a specific height.
- Scaling to Bigger Side: Scale an image to a specified size for the bigger side.
- Scaling to Smaller Side: Scale an image to a specified size for the smaller side.
- Scaling to Fit Size: Scale an image to fit within a target size while maintaining the aspect ratio.
- Scaling by Factor: Scale an image by a provided factor.
-
Scale Image by Width/Height:
Use the
scaled(toWidth:)
/scaled(toHeight:)
method to scale an image to a specific width/height.let originalImage: UIImage = // Some image let scaledByWidthImage = originalImage.nz.scaled(toWidth: 200) let scaledByHeightImage = originalImage.nz.scaled(toHeight: 150)
-
Scale Image to Bigger Side/Smaller Side:
Use the
scaled(toBigger:)
/scaled(toSmaller:)
method to scale an image to a specified size for the bigger/smaller side.let originalImage: UIImage = // Some image let scaledToBiggerSideImage = originalImage.nz.scaled(toBigger: 300) let scaledToSmallerSideImage = originalImage.nz.scaled(toSmaller: 120)
-
Scale Image to Fit Size:
Use the scaled(toFit:) method to scale an image to fit within a target size while maintaining the aspect ratio.
let originalImage: UIImage = // Some image let targetSize = CGSize(width: 250, height: 200) let scaledImage = originalImage.nz.scaled(toFit: targetSize)
-
Scale Image by Factor:
Use the scaled(by:) method to scale an image by a provided factor.
let originalImage: UIImage = // Some image let scaledImage = originalImage.nz.scaled(by: 1.5)
The UILabel+NibLocalized
extension provides a convenient way to set localized text for UILabel
elements directly from .nib
files.
- Localized Text: Set localized text for a
UILabel
from a.nib
file effortlessly.
-
Localized Text for UILabel:
let localizedLabel: UILabel = // Your UILabel from the Nib file localizedLabel.nz.textLocalization = "localized_key"
-
Localized Text in Nib File:
In your nib file, you can set the localized text directly from the Attributes inspector in Xcode. Set the nz_textLocalization property to the localization key. The text of the UILabel will be automatically set to the localized string corresponding to the specified key.
The UINavigationBar+Translucent
extension provides a convenient way to control the translucency of a UINavigationBar.
- Translucent State: Easily set or unset the translucency of a UINavigationBar.
let navigationBar: UINavigationBar = // Your UINavigationBar instance
navigationBar.nz.makeTranslucent(true)
navigationBar.nz.makeTranslucent(false)
The UINavigationController+Completion
extension in the NerdzUtils framework enhances the UINavigationController by providing completion closures for various navigation operations.
- Push View Controller with Completion: Execute a closure after pushing a view controller onto the navigation stack.
- Pop to View Controller with Completion: Execute a closure after popping to a specific view controller.
- Pop View Controller with Completion: Execute a closure after popping the top view controller.
- Pop to Root View Controller with Completion: Execute a closure after popping to the root view controller.
-
Push View Controller with Completion:
let navigationController: UINavigationController = // Your UINavigationController instance let viewController: UIViewController = // The view controller to push navigationController.nz.pushViewController(viewController, animated: true) { print("ViewController pushed!") }
-
Pop to View Controller with Completion:
let navigationController: UINavigationController = // Your UINavigationController instance let viewController: UIViewController = // The view controller to pop to navigationController.nz.popToViewController(viewController, animated: true) { print("Popped to ViewController!") }
-
Pop View Controller with Completion:
let navigationController: UINavigationController = // Your UINavigationController instance navigationController.nz.popViewController(animated: true) { print("Popped top ViewController!") }
-
Pop to Root View Controller with Completion:
let navigationController: UINavigationController = // Your UINavigationController instance navigationController.nz.popToRootViewController(animated: true) { print("Popped to Root ViewController!") }
The UITextField+Localized
extension enhances the UITextField by providing functionality to set localized text and placeholder directly from Interface Builder or programmatically.
- Localized Text: Set the localized text of a UITextField from nib files.
- Localized Placeholder: Set the localized placeholder of a UITextField from nib files.
-
Localized Text:
Set the localized text directly from Interface Builder or programmatically.
-
Localized Placeholder:
Set the localized placeholder directly from Interface Builder or programmatically.
The UITextField+PasswordVisibility
extension enhances the UITextField by providing a password visibility toggle.
- Password Visibility Toggle: Enable or disable a visibility toggle for the password field.
Name | Type | Accessibility | Description |
---|---|---|---|
nz_isPasswordVisibilityToggleEnabled |
Bool |
read-write IBInspectable |
Enable or disable the password visibility toggle directly from Interface Builder or programmatically. |
Set the nz_isPasswordVisibilityToggleEnabled
property in the Attributes inspector of the UITextField.

let passwordTextField: UITextField = // Your UITextField instance
passwordTextField.nz_isPasswordVisibilityToggleEnabled = true
The UIView+AddDashedBorder
extends the UIView class by providing a convenient method to add a dashed border to a view.
- Dashed Border Addition: Add a dashed border with customizable properties such as stroke color, fill color, position, line width, line join, line dash pattern, and corner radius.
func addDashedBorder(...) -> CAShapeLayer
Name | Type | Default Value | Description |
---|---|---|---|
strokeColor |
UIColor |
- | The color of the dashed border. |
fillColor |
UIColor |
UIColor.clear |
The color inside the dashed border. |
position |
CGPoint |
.zero |
The position of the dashed border. |
lineWidth |
CGFloat |
2 |
The width of the dashed border lines. |
lineJoin |
CAShapeLayerLineJoin |
.round |
The line join style of the dashed border. |
lineDashPattern |
[NSNumber] |
[6, 3] |
The dash pattern of the dashed border. |
cornerRadius |
CGFloat |
20 |
The corner radius of the dashed border. |
let myView: UIView = // Your UIView instance
let dashedBorderLayer = myView.nz.addDashedBorder(
with: .blue,
fillColor: .clear,
position: CGPoint(x: 10, y: 10),
lineWidth: 2,
lineJoin: .round,
lineDashPattern: [6, 3],
cornerRadius: 20
)
The UIView+ApplyGradient
extension enhances the UIView class by providing a method to easily apply a gradient to a view.
- applyGradient(colors:locations:type:startPoint:endPoint:): Adds a gradient to the view with customizable properties.
Name | Type | Default Value | Description |
---|---|---|---|
colors |
[UIColor] |
- | An array of UIColor objects defining the color of each gradient stop. |
locations |
[NSNumber] |
- | An array of NSNumber objects defining the location of each gradient stop as a value in the range [0,1]. |
type |
CAGradientLayerType |
.axial |
The type of gradient. |
startPoint |
CGPoint |
{0.5, 0} |
The start point of the gradient. |
endPoint |
CGPoint |
{0.5, 1} |
The end point of the gradient. |
let myView: UIView = // Your UIView instance
let gradientLayer = myView.nz.applyGradient(
colors: [.red, .blue],
locations: [0, 1],
type: .axial,
startPoint: CGPoint(x: 0.5, y: 0),
endPoint: CGPoint(x: 0.5, y: 1)
)
The UIView+ApplyShadow
extension enhances the UIView class by providing a method to easily apply a shadow to a view.
- applyShadow(color:opacity:offSet:radius:): Easily apply a shadow with customizable properties.
Name | Type | Default Value | Description |
---|---|---|---|
color |
UIColor |
- | The color of the shadow. |
opacity |
Float |
0.5 |
The opacity of the shadow. |
offSet |
CGSize |
.zero |
The offset of the shadow. |
radius |
CGFloat |
1 |
The radius of the shadow. |
let myView: UIView = // Your UIView instance
myView.nz.applyShadow(
color: .black,
opacity: 0.7,
offSet: CGSize(width: 2, height: 2),
radius: 3
)
The UIView+AsImage
extension extends the UIView class by providing a method to capture a screenshot of the view.
- asImage(): Captures a screenshot of the view.
let myView: UIView = // Your UIView instance
let screenshotImage = myView.nz.asImage()
The UIView+InspectableLayer
extension provides inspectable properties for configuring the layer of a UIView.
- Inspectable Properties: Easily configure view properties in Interface Builder without code.
Property | Type | Description |
---|---|---|
cornerRadius |
CGFloat |
View corner radius |
maskedCorners |
CACornerMask |
View masked corners (available from iOS 11.0) |
borderWidth |
CGFloat |
View border width |
borderColor |
UIColor? |
View border color |
shadowColor |
UIColor? |
View shadow color |
shadowAlpha |
Float |
View shadow opacity |
shadowOffset |
CGSize |
View shadow offset |
shadowBlur |
CGFloat |
View shadow radius |
-
From Interface Builder:
Set the inspectable properties in the Attributes Inspector of the UIView.
-
Programmatically:
let myView: UIView = // Your UIView instance // Configure properties programmatically myView.cornerRadius = 10.0 myView.maskedCorners = [.layerMinXMinYCorner, .layerMaxXMaxYCorner] myView.borderWidth = 1.0 myView.borderColor = UIColor.black myView.shadowColor = UIColor.gray myView.shadowAlpha = 0.5 myView.shadowOffset = CGSize(width: 2.0, height: 2.0) myView.shadowBlur = 5.0
The UIView+RoundCorners
extension provides a method to apply rounded corners to specific corners of a UIView and optionally add a border.
-
roundCorners(_:radius:borderColor:borderWidth:): Applies round corners to the specified corners of the view.
Name Type Default Value Description corners
CACornerMask
- The corners to which the radius is applied. radius
CGFloat
- The radius of the rounded corners. borderColor
UIColor
.clear
The color of the border. borderWidth
CGFloat
0
The width of the border.
let myView: UIView = // Your UIView instance
// Apply round corners to the top-left and top-right corners with a radius of 10
// Also, add a border with a color of red and a width of 2
myView.nz.roundCorners(
[.layerMinXMinYCorner, .layerMaxXMinYCorner],
radius: 10,
borderColor: .red,
borderWidth: 2
)
The UIViewController+AddChild
extension provides a method to easily add a child view controller with all necessary configurations.
-
easilyAddChild(_:on:configurationAction:): Adds a child view controller to the specified container with optional configuration.
Parameter Type Default Value Description childController
UIViewController
- The view controller to be added as a child. container
UIView?
nil
The container view to which the child view controller will be added. If not provided, view
of the base view controller will be used.configurationAction
((UIView, UIView) -> Void)
UIViewController.nz.setupFullscreen
The configuration action to set up constraints. If not provided, it will become full size of the container.
let parentViewController: UIViewController = // Your parent view controller
let childViewController: UIViewController = // Your child view controller
// Add child view controller to the parent view controller's view with default configuration
parentViewController.nz.easilyAddChild(childViewController)
// Add child view controller to a custom container view with custom configuration
let customContainerView: UIView = // Your custom container view
parentViewController.nz.easilyAddChild(childViewController, on: customContainerView) { childView, parentView in
// Your custom configuration code for constraints
}
The UIViewController+Overlay
extension provides methods to present and dismiss the current view controller as an overlay.
-
presentAsOverlay(): Presents the current view controller as an overlay.
-
dismissOverlay() throws: Dismisses the current view controller if it was presented as an overlay.
Throws:
OverlayPresentationError.noWindow
: If the view does not have a window available.OverlayPresentationError.notOverlay
: If the view controller was not presented as an overlay.
let viewController: UIViewController = // Your view controller
// Present the view controller as an overlay
viewController.nz.presentAsOverlay()
// Dismiss the overlay if it was presented
do {
try viewController.nz.dismissOverlay()
}
catch {
print(error.localizedDescription)
}
The UIViewController+Top
extension provides a property to get the top presented or pushed view controller.
- topController: The top presented or pushed view controller.
let viewController: UIViewController = // Your view controller
let topController = viewController.nz.topController
The LoadableButton
is a class that extends UIButton
to provide loading functionality with an activity indicator.
Name | Type | Default Value | Description |
---|---|---|---|
onStartLoading |
LoadableButtonEmptyAction |
- | A closure to be executed when the loading starts. |
onFinishLoading |
LoadableButtonEmptyAction |
- | A closure to be executed when the loading finishes. |
topBottomIndicatorPadding |
CGFloat |
10 |
The spacing for the activity indicator from the top and bottom of the button. |
isLoading |
Bool |
false |
A boolean value indicating whether the button is in the loading state. |
activityIndicatorView |
UIView |
- | The view representing the loading indicator. |
-
Set the Loading State:
let loadableButton: LoadableButton = // Your LoadableButton instance // Set the loading state loadableButton.isLoading = true
-
Customize the Loading Button:
let loadableButton: LoadableButton = // Your LoadableButton instance // Customize the loading button loadableButton.topBottomIndicatorPadding = 15 loadableButton.activityIndicatorView = customActivityIndicatorView
-
Handle Loading Events:
let loadableButton: LoadableButton = // Your LoadableButton instance loadableButton.onStartLoading = { // Code to execute when loading starts } loadableButton.onFinishLoading = { // Code to execute when loading finishes }
Represents a way of storing loaded image by LoadableImageView
class
For more information follow the documentation of
LoadableImageView
.none
No storing needed
.cache(timeout: TimeInterval? = nil)
Loaded image needs to be cached
If the timeout is not provided - an image will be cached while the target exists.
Name | Type | Default value | Description |
---|---|---|---|
timeout |
TimeInterval? |
nil |
A duration after what cached image needs to be reloaded |
-
startSpinnerLoading(with color: UIColor? = nil, size: CGFloat? = nil)
Parameter Type Default Value Description color
UIColor?
nil
The color of the loader spinner. size
CGFloat?
nil
The size of the loader spinner. Starts loading with a spinner.
-
stopSpinnerLoading()
Stops loading.
-
Start Loading with Spinner:
yourView.startSpinnerLoading(with: .white, size: 15.0)
-
Stop Loading:
yourView.stopSpinnerLoading()
A property wrapper that simplifies syncing a property with UserDefaults
, providing automatic initialization and retrieval of values.
-
init(_ key:, initial:, defaults:)
:Parameter Type Default Value Description key
String
- The key for storing the value in UserDefaults. initial
Type
- The initial value for cases when UserDefaults is empty. defaults
UserDefaults
.standard
UserDefaults instance.
wrappedValue
: Gets or sets the value of the property wrapper.
-
Basic Usage:
@DefaultsProperty("userLoggedIn", initial: false) var isUserLoggedIn: Bool
-
Custom UserDefaults:
let customUserDefaults = UserDefaults(suiteName: "com.example.app") @DefaultsProperty("darkModeEnabled", initial: false, defaults: customUserDefaults) var isDarkModeEnabled: Bool
A property wrapper facilitating the automatic synchronization of a property with the Keychain
, offering seamless initialization and retrieval of values.
-
init(_ key:, initial:, keychain:))
Parameter Type Default Value Description key
String
- The key for storing the value in Keychain. initial
Type
- The initial value for cases when Keychain is empty. keychain
Keychain
Keychain(service: Bundle.main.bundleIdentifier ?? "")
Keychain instance.
wrappedValue
: Gets or sets the value of the property wrapper.
-
Basic Usage:
@KeychainProperty("userAuthToken", initial: "") var userAuthToken: String
-
Custom UserDefaults:
let customKeychain = Keychain(service: "com.example.app.keychain") @KeychainProperty("userPassword", initial: "", keychain: customKeychain) var userPassword: String
The AtomicAsyncOperation
class encapsulates the logic of executing a single operation at a time, ensuring that the operation is not initiated concurrently by multiple requests. If an operation is already in progress, additional requests will be added to a completions list, and their closures will be invoked after the initial operation finishes. This approach minimizes redundant executions and provides a solution for scenarios such as lazy initialization of services or optimizing request execution.
NOTE: This class uses a background queue internally, so ensure that all UI actions are wrapped in the main queue.
-
init(action:)
Parameter Type Default Value Description action
Action
completion- The execution action that needs to be performed.
action
: The execution action closure.isRunning
: A boolean indicating whether the operation is currently in progress.
-
perform(completion:)
: Perform the operation if it is not running yet, or add it to the completions list if it is already running.Parameter Type Default Value Description completion
Completion?
nil A completion closure to be called when execution finishes.
let asyncOperation = AtomicAsyncOperation { completion in
// Perform your asynchronous operation logic here
// For example, fetching data from a network API
fetchDataFromAPI { result in
// Process the result
// ...
// Notify completion when finished
completion()
}
}
// Trigger the asynchronous operation
asyncOperation.perform {
// Closure to be executed when the operation completes
// This can be used to update the UI or perform additional tasks
}
The DelayedAction
class provides a mechanism to delay the execution of a closure and allows for cancellation or rescheduling if needed.
-
cancel() -> Bool
:Cancels any pending execution of the action.
Return Type Description Bool
Returns true
if the cancellation was successful,false
otherwise. -
perform(after:, queue:, action:)
:Schedules the execution of the action after a specified delay.
Parameter Type Default Value Description delay
TimeInterval
- The delay after which the action needs to be executed. queue
DispatchQueue
.main
The queue on which the action will be executed. action
() -> Void
- The action that needs to be executed.
-
Delayed Execution:
let delayedAction = DelayedAction() // Schedule an action to be executed after a delay delayedAction.perform(after: 2.0) { print("Delayed action executed!") } // Cancelling the pending execution (if needed) delayedAction.cancel()
-
Rescheduling an Action:
let delayedAction = DelayedAction() delayedAction.perform(after: 3.0) { print("Initial action executed!") } // Rescheduling the action to be executed sooner delayedAction.perform(after: 1.0) { print("Rescheduled action executed!") }
The IdType
protocol defines the requirements for types representing unique identifiers. It is commonly used when you have various types of entities (e.g., users, products, etc.) that need a standardized way to represent their identity. It ensures uniqueness and facilitates operations like equality comparisons (==)
and hashing.
-
IdType: Hashable
:The protocol requires conformance to the
Hashable
protocol, allowing instances to be used in hash-based collections. -
var id: ID { get }
:A property
id
of typeID
representing the unique identifier for an instance. An associated typeID
representing the identifier, also conforming toHashable
. This allows flexibility in the type of identifier, such asString
orInt
.
-
StringIdType: IdType
:A subprotocol of
IdType
where the associated identifier type isString
. -
IntIdType: IdType
:A subprotocol of
IdType
where the associated identifier type isInt
.
-
hash(into hasher:, inout Hasher)
:An extension method that provides a default implementation for hashing, combining the hash value of the identifier.
Parameter Type Description hasher
inout Hasher
The hasher to use when combining the hash values.
-
==
Operator Overload:An overload of the equality operator (
==
) for instances conforming toIdType
, comparing their identifiers for equality.
// Example conforming type
struct UserID: IntIdType {
let id: Int
}
// Example usage
let user1 = UserID(id: 42)
let user2 = UserID(id: 42)
// Equality comparison
let areEqual = (user1 == user2) // true
// Hashing
var hasher = Hasher()
user1.hash(into: &hasher)
let hashValue1 = hasher.finalize()
print("Hash Value for User 1: \(hashValue1)")
The SyncPropertyActor
is an actor-based container designed to provide thread-safe access to a property of a given type.
-
init(_ value: T)
: Initializes a new instance of SyncPropertyActor with the specified initial value.Parameter Type Description value
T
The initial value to be stored in the property.
-
setNewValue(_ value: T)
: Sets a new value for the property, ensuring thread safetyParameter Type Description value
T
The new value to be set. -
modify(with closure: (inout T) -> Void)
: Modifies the property's value using a closure, ensuring thread safety.Parameter Type Description closure
(inout T) -> Void
A closure that takes an inout
parameter representing the property's value. Use this closure to modify the value safely.
-
Setting a new value:
private let nextProductsPageLink = SyncPropertyActor<URL?>(nil) Task { // Use the setNewValue method to set the property to a new URL. await nextProductsPageLink.setNewValue(URL(string: "https://example.com/nextpage")) }
-
Modifying existing value:
// Example of modifying the property within a task Task { nextProductsPageLink.modify { currentURL in // Modify the current URL, for example, appending a query parameter currentURL?.appendPathComponent("additionalPath") } }
TYPE: class
Adding a possibility of having a weak reference in strong wrapper. Useful for cases when you need a weak reference for objects in Array
or Dictionary
class SomeClass {
// All objects stored in this array will be stored with weak reference
private let weekArray = Array<Weak<AnotherClass>>()
}
Name | Type | Accessibility | Description |
---|---|---|---|
object |
T? |
read-write |
Wrapped object |
init(_ object: T?)
Initialize wrapper with wrapped object
Name | Type | Default value | Description |
---|---|---|---|
object |
T? |
Wrapped object |