Skip to content

Commit a004908

Browse files
committed
Fix bug with standard edit action handling where original might not
get called. The logic is supposed to be that if a custom override is provided and it returns true, the original should be called, but if no override is provided then the original should be called. The previous implementation was calling the original using optional chaining which meant the original would not be called if the override was nil. This change fixes that bug and also refactors out the duplicated logic into a more general function.
1 parent 71e906c commit a004908

File tree

2 files changed

+127
-110
lines changed

2 files changed

+127
-110
lines changed

CHANGELOG.md

+3
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,9 @@
88
was fulfilled.
99
* `FirstResponderStateChangeHandler.receive(on:)` operator was not passing it's `options`
1010
to the scheduler.
11+
* Fixed a bug in standard edit action handling where the original implementation would not get
12+
called if a standard edit action handling value was given but no override for the specific edit action
13+
existed.
1114
* README and documentation fixes.
1215

1316
## 0.5.0

Sources/ResponsiveTextField/StandardEditActionHandling.swift

+124-110
Original file line numberDiff line numberDiff line change
@@ -36,33 +36,39 @@ public enum StandardEditAction: Equatable, CaseIterable {
3636
public struct StandardEditActionHandling<Responder: UIResponder> {
3737
// MARK: - Handling cut, copy and paste commands
3838

39-
public typealias StandardEditingAction = (Responder, Any?) -> Bool
40-
41-
public var cut: StandardEditingAction?
42-
public var copy: StandardEditingAction?
43-
public var paste: StandardEditingAction?
44-
public var delete: StandardEditingAction?
39+
/// A closure that can be used to customise a standard edit action.
40+
///
41+
/// - Parameters:
42+
/// - `Responder` - the control that this action is associated with, e.g. the `UITextField`
43+
/// - `Any?` - the sender of the action.
44+
///
45+
public typealias StandardEditActionHandler = (Responder, Any?) -> Bool
46+
47+
public var cut: StandardEditActionHandler?
48+
public var copy: StandardEditActionHandler?
49+
public var paste: StandardEditActionHandler?
50+
public var delete: StandardEditActionHandler?
4551

4652
// MARK: - Handling selection commands
4753

48-
public var select: StandardEditingAction?
49-
public var selectAll: StandardEditingAction?
54+
public var select: StandardEditActionHandler?
55+
public var selectAll: StandardEditActionHandler?
5056

5157
// MARK: - Handling styled text editing
5258

53-
public var toggleBoldface: StandardEditingAction?
54-
public var toggleItalics: StandardEditingAction?
55-
public var toggleUnderline: StandardEditingAction?
59+
public var toggleBoldface: StandardEditActionHandler?
60+
public var toggleItalics: StandardEditActionHandler?
61+
public var toggleUnderline: StandardEditActionHandler?
5662

5763
// MARK: - Handling writing direction changes
5864

59-
public var makeTextWritingDirectionLeftToRight: StandardEditingAction?
60-
public var makeTextWritingDirectionRightToLeft: StandardEditingAction?
65+
public var makeTextWritingDirectionLeftToRight: StandardEditActionHandler?
66+
public var makeTextWritingDirectionRightToLeft: StandardEditActionHandler?
6167

6268
// MARK: - Handling size changes
6369

64-
public var increaseSize: StandardEditingAction?
65-
public var decreaseSize: StandardEditingAction?
70+
public var increaseSize: StandardEditActionHandler?
71+
public var decreaseSize: StandardEditActionHandler?
6672

6773
// MARK: - Handling other text formatting changes
6874

@@ -71,19 +77,19 @@ public struct StandardEditActionHandling<Responder: UIResponder> {
7177
public var updateTextAttributes: ((Responder, ConversionHandler) -> Bool)?
7278

7379
public init(
74-
cut: StandardEditingAction? = nil,
75-
copy: StandardEditingAction? = nil,
76-
paste: StandardEditingAction? = nil,
77-
delete: StandardEditingAction? = nil,
78-
select: StandardEditingAction? = nil,
79-
selectAll: StandardEditingAction? = nil,
80-
toggleBoldface: StandardEditingAction? = nil,
81-
toggleItalics: StandardEditingAction? = nil,
82-
toggleUnderline: StandardEditingAction? = nil,
83-
makeTextWritingDirectionLeftToRight: StandardEditingAction? = nil,
84-
makeTextWritingDirectionRightToLeft: StandardEditingAction? = nil,
85-
increaseSize: StandardEditingAction? = nil,
86-
decreaseSize: StandardEditingAction? = nil,
80+
cut: StandardEditActionHandler? = nil,
81+
copy: StandardEditActionHandler? = nil,
82+
paste: StandardEditActionHandler? = nil,
83+
delete: StandardEditActionHandler? = nil,
84+
select: StandardEditActionHandler? = nil,
85+
selectAll: StandardEditActionHandler? = nil,
86+
toggleBoldface: StandardEditActionHandler? = nil,
87+
toggleItalics: StandardEditActionHandler? = nil,
88+
toggleUnderline: StandardEditActionHandler? = nil,
89+
makeTextWritingDirectionLeftToRight: StandardEditActionHandler? = nil,
90+
makeTextWritingDirectionRightToLeft: StandardEditActionHandler? = nil,
91+
increaseSize: StandardEditActionHandler? = nil,
92+
decreaseSize: StandardEditActionHandler? = nil,
8793
updateTextAttributes: ((Responder, ConversionHandler) -> Bool)? = nil
8894
) {
8995
self.cut = cut
@@ -147,132 +153,140 @@ extension _UnderlyingTextField {
147153
// MARK: - Standard editing action handling
148154

149155
extension _UnderlyingTextField {
150-
override func cut(_ sender: Any?) {
156+
typealias EditActionHandling = StandardEditActionHandling<UITextField>
157+
typealias EditActionHandler = EditActionHandling.StandardEditActionHandler
158+
159+
/// Performs a standard edit action function, deferring to the original implementation if there is no standard edit action handler.
160+
///
161+
/// If a standard edit action handler has been provided and it implements the specified override, it will call the override and
162+
/// if the override returns `true`, it will also call the original.
163+
///
164+
/// If a standard edit action handler has been provided and it does not implement the specified override, the original will
165+
/// be called.
166+
private func performStandardEditActionHandler(
167+
sender: Any?,
168+
original: (Any?) -> Void,
169+
override: KeyPath<EditActionHandling, EditActionHandler?>
170+
) {
151171
guard let actions = standardEditActionHandler else {
152-
super.cut(sender)
172+
original(sender)
153173
return
154174
}
155-
if actions.cut?(self, sender) == true {
156-
super.cut(sender)
175+
if let override = actions[keyPath: override] {
176+
let callOriginal = override(self, sender)
177+
if callOriginal { original(sender) }
178+
} else {
179+
original(sender)
157180
}
158181
}
159182

183+
override func cut(_ sender: Any?) {
184+
performStandardEditActionHandler(
185+
sender: sender,
186+
original: super.cut,
187+
override: \.cut
188+
)
189+
}
190+
160191
override func copy(_ sender: Any?) {
161-
guard let actions = standardEditActionHandler else {
162-
super.copy(sender)
163-
return
164-
}
165-
if actions.copy?(self, sender) == true {
166-
super.copy(sender)
167-
}
192+
performStandardEditActionHandler(
193+
sender: sender,
194+
original: super.copy,
195+
override: \.copy
196+
)
168197
}
169198

170199
override func paste(_ sender: Any?) {
171-
guard let actions = standardEditActionHandler else {
172-
super.paste(sender)
173-
return
174-
}
175-
if actions.paste?(self, sender) == true {
176-
super.paste(sender)
177-
}
200+
performStandardEditActionHandler(
201+
sender: sender,
202+
original: super.paste,
203+
override: \.paste
204+
)
178205
}
179206

180207
override func select(_ sender: Any?) {
181-
guard let actions = standardEditActionHandler else {
182-
super.select(sender)
183-
return
184-
}
185-
if actions.select?(self, sender) == true {
186-
super.select(sender)
187-
}
208+
performStandardEditActionHandler(
209+
sender: sender,
210+
original: super.select,
211+
override: \.select
212+
)
188213
}
189214

190215
override func selectAll(_ sender: Any?) {
191-
guard let actions = standardEditActionHandler else {
192-
super.selectAll(sender)
193-
return
194-
}
195-
if actions.selectAll?(self, sender) == true {
196-
super.selectAll(sender)
197-
}
216+
performStandardEditActionHandler(
217+
sender: sender,
218+
original: super.selectAll,
219+
override: \.selectAll
220+
)
198221
}
199222

200223
override func toggleBoldface(_ sender: Any?) {
201-
guard let actions = standardEditActionHandler else {
202-
super.toggleBoldface(sender)
203-
return
204-
}
205-
if actions.toggleBoldface?(self, sender) == true {
206-
super.toggleBoldface(sender)
207-
}
224+
performStandardEditActionHandler(
225+
sender: sender,
226+
original: super.toggleBoldface,
227+
override: \.toggleBoldface
228+
)
208229
}
209230

210231
override func toggleItalics(_ sender: Any?) {
211-
guard let actions = standardEditActionHandler else {
212-
super.toggleItalics(sender)
213-
return
214-
}
215-
if actions.toggleItalics?(self, sender) == true {
216-
super.toggleItalics(sender)
217-
}
232+
performStandardEditActionHandler(
233+
sender: sender,
234+
original: super.toggleItalics,
235+
override: \.toggleItalics
236+
)
218237
}
219238

220239
override func toggleUnderline(_ sender: Any?) {
221-
guard let actions = standardEditActionHandler else {
222-
super.toggleUnderline(sender)
223-
return
224-
}
225-
if actions.toggleUnderline?(self, sender) == true {
226-
super.toggleUnderline(sender)
227-
}
240+
performStandardEditActionHandler(
241+
sender: sender,
242+
original: super.toggleUnderline,
243+
override: \.toggleUnderline
244+
)
228245
}
229246

230247
override func makeTextWritingDirectionLeftToRight(_ sender: Any?) {
231-
guard let actions = standardEditActionHandler else {
232-
super.makeTextWritingDirectionLeftToRight(sender)
233-
return
234-
}
235-
if actions.makeTextWritingDirectionLeftToRight?(self, sender) == true {
236-
super.makeTextWritingDirectionLeftToRight(sender)
237-
}
248+
performStandardEditActionHandler(
249+
sender: sender,
250+
original: super.makeTextWritingDirectionLeftToRight,
251+
override: \.makeTextWritingDirectionLeftToRight
252+
)
238253
}
239254

240255
override func makeTextWritingDirectionRightToLeft(_ sender: Any?) {
241-
guard let actions = standardEditActionHandler else {
242-
super.makeTextWritingDirectionRightToLeft(sender)
243-
return
244-
}
245-
if actions.makeTextWritingDirectionRightToLeft?(self, sender) == true {
246-
super.makeTextWritingDirectionRightToLeft(sender)
247-
}
256+
performStandardEditActionHandler(
257+
sender: sender,
258+
original: super.makeTextWritingDirectionRightToLeft,
259+
override: \.makeTextWritingDirectionRightToLeft
260+
)
248261
}
249262

250263
override func increaseSize(_ sender: Any?) {
251-
guard let actions = standardEditActionHandler else {
252-
super.increaseSize(sender)
253-
return
254-
}
255-
if actions.increaseSize?(self, sender) == true {
256-
super.increaseSize(sender)
257-
}
264+
performStandardEditActionHandler(
265+
sender: sender,
266+
original: super.increaseSize,
267+
override: \.increaseSize
268+
)
258269
}
259270

260271
override func decreaseSize(_ sender: Any?) {
261-
guard let actions = standardEditActionHandler else {
262-
super.decreaseSize(sender)
263-
return
264-
}
265-
if actions.decreaseSize?(self, sender) == true {
266-
super.decreaseSize(sender)
267-
}
272+
performStandardEditActionHandler(
273+
sender: sender,
274+
original: super.decreaseSize,
275+
override: \.decreaseSize
276+
)
268277
}
269278

270279
override func updateTextAttributes(conversionHandler: ([NSAttributedString.Key : Any]) -> [NSAttributedString.Key : Any]) {
271280
guard let actions = standardEditActionHandler else {
272281
super.updateTextAttributes(conversionHandler: conversionHandler)
273282
return
274283
}
275-
if actions.updateTextAttributes?(self, conversionHandler) == true {
284+
if let override = actions.updateTextAttributes {
285+
let callOriginal = override(self, conversionHandler)
286+
if callOriginal {
287+
super.updateTextAttributes(conversionHandler: conversionHandler)
288+
}
289+
} else {
276290
super.updateTextAttributes(conversionHandler: conversionHandler)
277291
}
278292
}

0 commit comments

Comments
 (0)