Skip to content

Commit 3361515

Browse files
authored
Release 1.1.0 (#4)
Release `1.1.0`
2 parents ecd9312 + 565ecd8 commit 3361515

5 files changed

Lines changed: 101 additions & 39 deletions

File tree

.github/workflows/ci.yml

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -38,10 +38,6 @@ jobs:
3838
name: "iOS 18.1"
3939
xcode: "Xcode_16.1"
4040
runsOn: macOS-14
41-
- destination: "OS=18.0,name=iPhone 16 Pro"
42-
name: "iOS 18.0"
43-
xcode: "Xcode_16.0"
44-
runsOn: macOS-14
4541
steps:
4642
- uses: actions/checkout@v4
4743
- name: ${{ matrix.name }}

CHANGELOG.md

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,17 @@
11
# Change Log
22
All notable changes to this project will be documented in this file.
33

4+
#### 1.x Releases
5+
- `1.1.x` Releases - [1.1.0](#110)
6+
- `1.0.x` Releases - [1.0.0](#100)
7+
8+
## [1.1.0](https://github.com/space-code/flare/releases/tag/1.1.0)
9+
Released on 2025-01-27.
10+
11+
#### Added
12+
- Implement adding an action to a `UITextField`.
13+
- Added in Pull Request [#3](https://github.com/space-code/flex-ui/pull/3).
14+
415
## [1.0.0](https://github.com/space-code/flex-ui/releases/tag/1.0.0)
516
Released on 2025-01-07.
617

Sources/FlexUI/Classes/Extensions/FlexUI+UIButton.swift

Lines changed: 4 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -1,41 +1,11 @@
11
//
22
// flex-ui
3-
// Copyright © 2024 Space Code. All rights reserved.
3+
// Copyright © 2025 Space Code. All rights reserved.
44
//
55

66
import UIKit
77

8-
// MARK: - ButtonCommand
9-
10-
/// A private class that wraps a closure to be executed as an action for a `UIButton`.
11-
/// This class allows associating arbitrary closure actions with buttons, and is used internally
12-
/// to manage custom button actions in the `FlexUI` extension.
13-
private final class ButtonCommand {
14-
// MARK: Properties
15-
16-
/// The closure that will be executed when the button action is triggered.
17-
let block: () -> Void
18-
19-
// MARK: Initialization
20-
21-
/// Initializes a new instance of `ButtonCommand` with the provided closure.
22-
///
23-
/// - Parameter block: The closure to be executed when the button is tapped.
24-
init(block: @escaping () -> Void) {
25-
self.block = block
26-
}
27-
28-
// MARK: Actions
29-
30-
/// The action method that is triggered when the associated button's event occurs.
31-
/// It executes the stored closure.
32-
@objc
33-
func action() {
34-
block()
35-
}
36-
}
37-
38-
@MainActor private let kMapTable = NSMapTable<AnyObject, ButtonCommand>.weakToStrongObjects()
8+
@MainActor private let kMapTable = NSMapTable<AnyObject, Command>.weakToStrongObjects()
399

4010
/// An extension to `FlexUI` that adds helper methods for configuring `UIButton` properties.
4111
/// These methods allow for fluent configuration of button properties such as title, image, alignment, and actions.
@@ -251,7 +221,7 @@ public extension FlexUI where Component: UIButton {
251221
return self
252222
}
253223

254-
let buttonCommand = ButtonCommand(block: command)
224+
let buttonCommand = Command(block: command)
255225
component.removeTarget(nil, action: nil, for: event)
256226
component.addTarget(buttonCommand, action: #selector(buttonCommand.action), for: event)
257227
kMapTable.setObject(buttonCommand, forKey: component)
@@ -271,7 +241,7 @@ public extension FlexUI where Component: UIButton {
271241
return self
272242
}
273243

274-
let buttonCommand = ButtonCommand { [weak component] in
244+
let buttonCommand = Command { [weak component] in
275245
if let component = component {
276246
command(component)
277247
}

Sources/FlexUI/Classes/Extensions/FlexUI+UITextField.swift

Lines changed: 52 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,12 @@
11
//
22
// flex-ui
3-
// Copyright © 2024 Space Code. All rights reserved.
3+
// Copyright © 2025 Space Code. All rights reserved.
44
//
55

66
import UIKit
77

8+
@MainActor private let kMapTable = NSMapTable<AnyObject, Command>.weakToStrongObjects()
9+
810
public extension FlexUI where Component: UITextField {
911
/// Sets the font of the text field.
1012
///
@@ -140,4 +142,53 @@ public extension FlexUI where Component: UITextField {
140142
component.adjustsFontSizeToFitWidth = true
141143
return self
142144
}
145+
146+
/// Adds a command to be executed when a specified event occurs on the UIControl component.
147+
/// The method is annotated with `@discardableResult` to allow the return value to be ignored,
148+
/// and `@MainActor` to ensure it runs on the main thread.
149+
///
150+
/// - Parameters:
151+
/// - command: A closure to be executed when the event occurs. Can be `nil`, in which case no action is added.
152+
/// - event: The `UIControl.Event` that triggers the command.
153+
/// - Returns: The instance of `Self` to allow method chaining.
154+
@discardableResult
155+
@MainActor
156+
func add(command: (() -> Void)?, event: UIControl.Event) -> Self {
157+
guard let command = command else {
158+
return self
159+
}
160+
161+
let buttonCommand = Command(block: command)
162+
component.removeTarget(nil, action: nil, for: event)
163+
component.addTarget(buttonCommand, action: #selector(buttonCommand.action), for: event)
164+
kMapTable.setObject(buttonCommand, forKey: component)
165+
return self
166+
}
167+
168+
/// Adds a command to be executed when a specified event occurs on the `UITextField` component.
169+
/// The method is annotated with `@discardableResult` to allow the return value to be ignored,
170+
/// and `@MainActor` to ensure it runs on the main thread.
171+
///
172+
/// - Parameters:
173+
/// - command: A closure that receives the `UITextField` as a parameter when the event occurs. Can be `nil`.
174+
/// - event: The `UIControl.Event` that triggers the command.
175+
/// - Returns: The instance of `Self` to allow method chaining.
176+
@discardableResult
177+
@MainActor
178+
func add(command: ((UITextField) -> Void)?, event: UIControl.Event) -> Self {
179+
guard let command = command else {
180+
return self
181+
}
182+
183+
let buttonCommand = Command { [weak component] in
184+
if let component = component {
185+
command(component)
186+
}
187+
}
188+
189+
component.removeTarget(nil, action: nil, for: event)
190+
component.addTarget(buttonCommand, action: #selector(buttonCommand.action), for: event)
191+
kMapTable.setObject(buttonCommand, forKey: component)
192+
return self
193+
}
143194
}
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
//
2+
// flex-ui
3+
// Copyright © 2025 Space Code. All rights reserved.
4+
//
5+
6+
import Foundation
7+
8+
/// A private class that wraps a closure to be executed as an action for a `UIControl`.
9+
/// This class allows associating arbitrary closure actions with buttons, and is used internally
10+
/// to manage custom button actions in the `FlexUI` extension.
11+
final class Command {
12+
// MARK: Properties
13+
14+
/// The closure that will be executed when the button action is triggered.
15+
let block: () -> Void
16+
17+
// MARK: Initialization
18+
19+
/// Initializes a new instance of `Command` with the provided closure.
20+
///
21+
/// - Parameter block: The closure to be executed when the button is tapped.
22+
init(block: @escaping () -> Void) {
23+
self.block = block
24+
}
25+
26+
// MARK: Actions
27+
28+
/// The action method that is triggered when the associated button's event occurs.
29+
/// It executes the stored closure.
30+
@objc
31+
func action() {
32+
block()
33+
}
34+
}

0 commit comments

Comments
 (0)