Skip to content

Commit 6d5aa9b

Browse files
authored
fix: πŸ› [JIRA:HCPSDKFIORIUIKIT-2840] fix onChange deprecated (SAP#911)
'onChange(of:perform:)' was deprecated in iOS 17.0: Use `onChange` with a two or zero parameter action closure instead. βœ… Closes: HCPSDKFIORIUIKIT-2840
1 parent 75b24eb commit 6d5aa9b

21 files changed

+194
-86
lines changed

β€ŽSources/FioriSwiftUICore/DataTable/DataTable.swiftβ€Ž

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -102,7 +102,11 @@ public struct DataTable: View {
102102
}
103103
}
104104
#endif
105-
.onChange(of: self.dynamicTypeSize) { newValue in
105+
.setOnChange(of: self.dynamicTypeSize, action1: { newValue in
106+
self.layoutManager.dynamicTypeSize = newValue
107+
self.layoutManager.cacheLayoutDataForMeasurement = nil
108+
self.layoutManager.layoutData = nil
109+
}) { _, newValue in
106110
self.layoutManager.dynamicTypeSize = newValue
107111
self.layoutManager.cacheLayoutDataForMeasurement = nil
108112
self.layoutManager.layoutData = nil

β€ŽSources/FioriSwiftUICore/DataTable/InlineEditingView.swiftβ€Ž

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -134,14 +134,18 @@ struct InlineEditingView: View {
134134
self.focusState = true
135135
}
136136
}
137-
.onChange(of: self.editingText, perform: { _ in
137+
.setOnChange(of: self.editingText) {
138138
self.layoutManager.cacheEditingText = self.editingText
139-
})
140-
.onChange(of: self.focusState) { newValue in
139+
}
140+
.setOnChange(of: self.focusState, action1: { newValue in
141141
// lost focus
142142
if !newValue {
143143
self.updateText(self.editingText)
144144
}
145+
}) { _, newValue in
146+
if !newValue {
147+
self.updateText(self.editingText)
148+
}
145149
}
146150
}
147151

β€ŽSources/FioriSwiftUICore/DataTable/ItemView.swiftβ€Ž

Lines changed: 56 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -228,53 +228,65 @@ struct FocusedEditingView: View {
228228
EmptyView()
229229
}
230230
}
231-
.onChange(of: self.editingDate) { newValue in
232-
guard let layoutData = self.layoutManager.layoutData else { return }
233-
234-
var dataItem = layoutData.allDataItems[self.rowIndex][self.columnIndex]
235-
dataItem.date = newValue
236-
self.isValid = self.layoutManager.checkIsValid(for: dataItem)
237-
let errorChange: Int = dataItem.isValid != self.isValid.0 ? (self.isValid.0 ? -1 : 1) : 0
238-
layoutData.numOfErrors += errorChange
239-
dataItem.isValid = self.isValid.0
240-
if let value = dataItem.string(for: layoutManager.model.columnAttribute(for: columnIndex)) {
241-
self.editingText = value
242-
dataItem.text = value
243-
dataItem.size = layoutData.calcDataItemSize(dataItem)
244-
}
245-
246-
layoutData.allDataItems[self.rowIndex][self.columnIndex] = dataItem
247-
layoutData.updateCellLayout(for: self.rowIndex, columnIndex: self.columnIndex)
248-
self.layoutManager.needRefresh.toggle()
249-
self.layoutManager.isValid = self.isValid
250-
self.showBanner = !self.isValid.0
251-
252-
self.layoutManager.model.valueDidChange?(DataTableChange(rowIndex: self.rowIndex, columnIndex: self.columnIndex, value: .date(newValue), text: self.editingText))
231+
.setOnChange(of: self.editingDate, action1: { newValue in
232+
self.onEditingDateChange(newValue)
233+
}) { _, newValue in
234+
self.onEditingDateChange(newValue)
253235
}
254-
.onChange(of: self.editingDuration) { newValue in
255-
guard let layoutData = self.layoutManager.layoutData else { return }
256-
257-
var dataItem = layoutData.allDataItems[self.rowIndex][self.columnIndex]
258-
dataItem.ti = TimeInterval(newValue * 60)
259-
self.isValid = self.layoutManager.checkIsValid(for: dataItem)
260-
let errorChange: Int = dataItem.isValid != self.isValid.0 ? (self.isValid.0 ? -1 : 1) : 0
261-
layoutData.numOfErrors += errorChange
262-
dataItem.isValid = self.isValid.0
263-
if let value = dataItem.string(for: layoutManager.model.columnAttribute(for: columnIndex)) {
264-
self.editingText = value
265-
dataItem.text = value
266-
dataItem.size = layoutData.calcDataItemSize(dataItem)
267-
}
268-
layoutData.allDataItems[self.rowIndex][self.columnIndex] = dataItem
269-
layoutData.updateCellLayout(for: self.rowIndex, columnIndex: self.columnIndex)
270-
self.layoutManager.needRefresh.toggle()
271-
self.layoutManager.isValid = self.isValid
272-
self.showBanner = !self.isValid.0
273-
274-
self.layoutManager.model.valueDidChange?(DataTableChange(rowIndex: self.rowIndex, columnIndex: self.columnIndex, value: .duration(TimeInterval(newValue * 60)), text: self.editingText))
236+
.setOnChange(of: self.editingDuration, action1: { newValue in
237+
self.onEditingDurationChange(newValue)
238+
}) { _, newValue in
239+
self.onEditingDurationChange(newValue)
275240
}
276241
}
277-
242+
243+
func onEditingDateChange(_ newValue: Date) {
244+
guard let layoutData = self.layoutManager.layoutData else { return }
245+
246+
var dataItem = layoutData.allDataItems[self.rowIndex][self.columnIndex]
247+
dataItem.date = newValue
248+
self.isValid = self.layoutManager.checkIsValid(for: dataItem)
249+
let errorChange: Int = dataItem.isValid != self.isValid.0 ? (self.isValid.0 ? -1 : 1) : 0
250+
layoutData.numOfErrors += errorChange
251+
dataItem.isValid = self.isValid.0
252+
if let value = dataItem.string(for: layoutManager.model.columnAttribute(for: columnIndex)) {
253+
self.editingText = value
254+
dataItem.text = value
255+
dataItem.size = layoutData.calcDataItemSize(dataItem)
256+
}
257+
258+
layoutData.allDataItems[self.rowIndex][self.columnIndex] = dataItem
259+
layoutData.updateCellLayout(for: self.rowIndex, columnIndex: self.columnIndex)
260+
self.layoutManager.needRefresh.toggle()
261+
self.layoutManager.isValid = self.isValid
262+
self.showBanner = !self.isValid.0
263+
264+
self.layoutManager.model.valueDidChange?(DataTableChange(rowIndex: self.rowIndex, columnIndex: self.columnIndex, value: .date(newValue), text: self.editingText))
265+
}
266+
267+
func onEditingDurationChange(_ newValue: Int) {
268+
guard let layoutData = self.layoutManager.layoutData else { return }
269+
270+
var dataItem = layoutData.allDataItems[self.rowIndex][self.columnIndex]
271+
dataItem.ti = TimeInterval(newValue * 60)
272+
self.isValid = self.layoutManager.checkIsValid(for: dataItem)
273+
let errorChange: Int = dataItem.isValid != self.isValid.0 ? (self.isValid.0 ? -1 : 1) : 0
274+
layoutData.numOfErrors += errorChange
275+
dataItem.isValid = self.isValid.0
276+
if let value = dataItem.string(for: layoutManager.model.columnAttribute(for: columnIndex)) {
277+
self.editingText = value
278+
dataItem.text = value
279+
dataItem.size = layoutData.calcDataItemSize(dataItem)
280+
}
281+
layoutData.allDataItems[self.rowIndex][self.columnIndex] = dataItem
282+
layoutData.updateCellLayout(for: self.rowIndex, columnIndex: self.columnIndex)
283+
self.layoutManager.needRefresh.toggle()
284+
self.layoutManager.isValid = self.isValid
285+
self.showBanner = !self.isValid.0
286+
287+
self.layoutManager.model.valueDidChange?(DataTableChange(rowIndex: self.rowIndex, columnIndex: self.columnIndex, value: .duration(TimeInterval(newValue * 60)), text: self.editingText))
288+
}
289+
278290
func pickerView() -> some View {
279291
let data = self.layoutManager.model.listItemDataAndTitle?(self.rowIndex, self.columnIndex) ?? ([self.editingText], "")
280292
let indexData: [Int] = (0 ..< data.0.count).map { $0 }

β€ŽSources/FioriSwiftUICore/Experimental/Popover/PopoverModifier.swiftβ€Ž

Lines changed: 17 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -13,17 +13,10 @@ struct PopoverModifier<PopView: View>: ViewModifier {
1313
.frameReader(rect: { rect in
1414
self.sourceFrame = rect
1515
})
16-
.onChange(of: self.isPresented) { newValue in
17-
if newValue {
18-
let popover = Popover(popView: AnyView(popView()), isPresented: $isPresented)
19-
popover.context.sourceFrame = self.sourceFrame
20-
popover.context.windowFrame = window?.bounds ?? .zero
21-
popover.present(in: window)
22-
self.popover = popover
23-
} else {
24-
guard let popover else { return }
25-
popover.dismiss()
26-
}
16+
.setOnChange(of: self.isPresented, action1: { newValue in
17+
self.onIsPresentedChange(newValue, window: window)
18+
}) { _, newValue in
19+
self.onIsPresentedChange(newValue, window: window)
2720
}
2821
#if !os(visionOS)
2922
.onReceive(NotificationCenter.default.publisher(for: UIDevice.orientationDidChangeNotification)) { _ in
@@ -33,4 +26,17 @@ struct PopoverModifier<PopView: View>: ViewModifier {
3326
#endif
3427
}
3528
}
29+
30+
func onIsPresentedChange(_ newValue: Bool, window: UIWindow?) {
31+
if newValue {
32+
let popover = Popover(popView: AnyView(popView()), isPresented: $isPresented)
33+
popover.context.sourceFrame = self.sourceFrame
34+
popover.context.windowFrame = window?.bounds ?? .zero
35+
popover.present(in: window)
36+
self.popover = popover
37+
} else {
38+
guard let popover else { return }
39+
popover.dismiss()
40+
}
41+
}
3642
}

β€ŽSources/FioriSwiftUICore/Toast/ToastView.swiftβ€Ž

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@ struct ToastModifier: ViewModifier {
7878
}
7979
}
8080
)
81-
.onChange(of: self.toast) { _ in
81+
.setOnChange(of: self.toast) {
8282
self.showToast()
8383
}
8484
}

β€ŽSources/FioriSwiftUICore/Utils/View+Extensions.swiftβ€Ž

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,3 +54,38 @@ extension View {
5454
return false
5555
}
5656
}
57+
58+
extension View {
59+
nonisolated func setOnChange<V>(
60+
of value: V,
61+
initial: Bool = false,
62+
action1: @escaping (V) -> Void,
63+
action2: @escaping (V, V) -> Void
64+
) -> some View where V: Equatable {
65+
if #available(iOS 17.0, *) {
66+
return self.onChange(of: value, initial: initial) {
67+
action2($0, $1)
68+
}
69+
} else {
70+
return self.onChange(of: value) {
71+
action1($0)
72+
}
73+
}
74+
}
75+
76+
nonisolated func setOnChange(
77+
of value: some Equatable,
78+
initial: Bool = false,
79+
_ action: @escaping () -> Void
80+
) -> some View {
81+
if #available(iOS 17.0, *) {
82+
return self.onChange(of: value, initial: initial) {
83+
action()
84+
}
85+
} else {
86+
return self.onChange(of: value) { _ in
87+
action()
88+
}
89+
}
90+
}
91+
}

β€ŽSources/FioriSwiftUICore/Views/SearchableListContent.swiftβ€Ž

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,9 @@ struct SearchableListContent<Data: RandomAccessCollection, ID: Hashable, RowCont
8282
}
8383
.scrollContentBackground(.hidden)
8484
.background(listBackground)
85-
.onChange(of: selectionBuffer) { newValue in
85+
.setOnChange(of: selectionBuffer, action1: { newValue in
86+
selectionUpdated?(newValue)
87+
}) { _, newValue in
8688
selectionUpdated?(newValue)
8789
}
8890
.ifApply(searchFilter != nil, content: {

β€ŽSources/FioriSwiftUICore/Views/SortFilter/FilterFeedbackBarItem+View.swiftβ€Ž

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -127,7 +127,9 @@ struct SliderMenuItem: View {
127127
.onAppear {
128128
self.barItemFrame = geometry.frame(in: .global)
129129
}
130-
.onChange(of: geometry.frame(in: .global)) { newValue in
130+
.setOnChange(of: geometry.frame(in: .global), action1: { newValue in
131+
self.barItemFrame = newValue
132+
}) { _, newValue in
131133
self.barItemFrame = newValue
132134
}
133135
})
@@ -229,7 +231,9 @@ struct PickerMenuItem: View {
229231
.onAppear {
230232
self.barItemFrame = geometry.frame(in: .global)
231233
}
232-
.onChange(of: geometry.frame(in: .global)) { newValue in
234+
.setOnChange(of: geometry.frame(in: .global), action1: { newValue in
235+
self.barItemFrame = newValue
236+
}) { _, newValue in
233237
self.barItemFrame = newValue
234238
}
235239
})
@@ -327,7 +331,9 @@ struct PickerMenuItem: View {
327331
.onAppear {
328332
self.barItemFrame = geometry.frame(in: .global)
329333
}
330-
.onChange(of: geometry.frame(in: .global)) { newValue in
334+
.setOnChange(of: geometry.frame(in: .global), action1: { newValue in
335+
self.barItemFrame = newValue
336+
}) { _, newValue in
331337
self.barItemFrame = newValue
332338
}
333339
})
@@ -490,7 +496,9 @@ struct DateTimeMenuItem: View {
490496
.onAppear {
491497
self.barItemFrame = geometry.frame(in: .global)
492498
}
493-
.onChange(of: geometry.frame(in: .global)) { newValue in
499+
.setOnChange(of: geometry.frame(in: .global), action1: { newValue in
500+
self.barItemFrame = newValue
501+
}) { _, newValue in
494502
self.barItemFrame = newValue
495503
}
496504
})
@@ -652,7 +660,9 @@ struct StepperMenuItem: View {
652660
.onAppear {
653661
self.barItemFrame = geometry.frame(in: .global)
654662
}
655-
.onChange(of: geometry.frame(in: .global)) { newValue in
663+
.setOnChange(of: geometry.frame(in: .global), action1: { newValue in
664+
self.barItemFrame = newValue
665+
}) { _, newValue in
656666
self.barItemFrame = newValue
657667
}
658668
})

β€ŽSources/FioriSwiftUICore/Views/SortFilter/_SortFilterCFGItemContainer.swiftβ€Ž

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ extension _SortFilterCFGItemContainer: View {
6767
self.height = min(scrollView.contentSize.height, maxScrollViewHeight)
6868
}
6969
})
70-
.onChange(of: self._items) { _ in
70+
.setOnChange(of: self._items) {
7171
self.checkUpdateButtonState()
7272
}
7373
.onAppear {

β€ŽSources/FioriSwiftUICore/Views/StepProgressIndicator/StepProgressIndicator+View.swiftβ€Ž

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,15 @@ extension StepProgressIndicator: View {
4848
StepProgressIndicatorContainer(selection: _selection,
4949
steps: steps)
5050
.environment(\.stepFrames, $stepFrames)
51-
.onChange(of: _selection.wrappedValue) { newValue in
51+
.setOnChange(of: _selection.wrappedValue, action1: { newValue in
52+
if let currentFrame = stepFrames[newValue],
53+
!scrollBounds.contains(currentFrame)
54+
{
55+
withAnimation {
56+
proxy.scrollTo(newValue, anchor: .leading)
57+
}
58+
}
59+
}) { _, newValue in
5260
if let currentFrame = stepFrames[newValue],
5361
!scrollBounds.contains(currentFrame)
5462
{

0 commit comments

Comments
Β (0)