react-native-swipeable-actions 0.1.10-canary.0 → 0.1.11
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/ios/SwipeableView.swift +38 -8
- package/package.json +1 -1
package/ios/SwipeableView.swift
CHANGED
|
@@ -66,8 +66,25 @@ public class SwipeableView: ExpoView {
|
|
|
66
66
|
registryQueue.async(flags: .barrier) { _viewRegistry[key] = WeakRef(view) }
|
|
67
67
|
}
|
|
68
68
|
|
|
69
|
-
private static func unregisterView(for key: String) {
|
|
70
|
-
|
|
69
|
+
private static func unregisterView(_ view: SwipeableView, for key: String) {
|
|
70
|
+
// Identity-check: a newer SwipeableView may have already taken over this
|
|
71
|
+
// key (FlashList remounts a new instance before the old one's deinit
|
|
72
|
+
// fires). Without this guard the old view's deinit blindly removes the
|
|
73
|
+
// key, leaving the new view orphaned in the registry — closeByKey for
|
|
74
|
+
// that key then returns nil and the visible row can't be closed.
|
|
75
|
+
//
|
|
76
|
+
// Capture identity as a *value* (ObjectIdentifier), never reference
|
|
77
|
+
// `view` inside the async closure. Callers include `deinit`, where
|
|
78
|
+
// `self` is mid-deallocation; strongly capturing it in an escaping
|
|
79
|
+
// closure produces a zombie reference and crashes (EXC_BAD_ACCESS) when
|
|
80
|
+
// the barrier finally runs after the object has been freed.
|
|
81
|
+
let identity = ObjectIdentifier(view)
|
|
82
|
+
registryQueue.async(flags: .barrier) {
|
|
83
|
+
if let registered = _viewRegistry[key]?.value,
|
|
84
|
+
ObjectIdentifier(registered) == identity {
|
|
85
|
+
_viewRegistry.removeValue(forKey: key)
|
|
86
|
+
}
|
|
87
|
+
}
|
|
71
88
|
}
|
|
72
89
|
|
|
73
90
|
private static func clearOpenState(for key: String) {
|
|
@@ -88,7 +105,15 @@ public class SwipeableView: ExpoView {
|
|
|
88
105
|
|
|
89
106
|
static func closeByKey(_ key: String, animated: Bool = true) {
|
|
90
107
|
DispatchQueue.main.async {
|
|
91
|
-
getView(for: key)
|
|
108
|
+
if let view = getView(for: key) {
|
|
109
|
+
view.close(animated: animated)
|
|
110
|
+
} else {
|
|
111
|
+
// View was recycled away (or unregistered) before this close
|
|
112
|
+
// could run. Update the cache directly so a future cell binding
|
|
113
|
+
// to this key starts closed instead of inheriting a stale open
|
|
114
|
+
// state — see recyclingKey setter for the matching invariant.
|
|
115
|
+
setOpenState(for: key, isOpen: false)
|
|
116
|
+
}
|
|
92
117
|
}
|
|
93
118
|
}
|
|
94
119
|
|
|
@@ -229,10 +254,15 @@ public class SwipeableView: ExpoView {
|
|
|
229
254
|
let shouldOpen = recyclingKey.map { Self.getOpenState(for: $0) } ?? false
|
|
230
255
|
pendingShouldOpen = shouldOpen
|
|
231
256
|
|
|
232
|
-
//
|
|
257
|
+
// Unregister from the old key. We intentionally do NOT write back
|
|
258
|
+
// `isOpen` here: open() and close() already maintain the cache when
|
|
259
|
+
// the user actually triggers the state change. Writing the view's
|
|
260
|
+
// current `isOpen` at reassignment time captures stale state when a
|
|
261
|
+
// pending async close hasn't run yet, leaving the old key cached as
|
|
262
|
+
// open forever — the next cell binding to it would snap open
|
|
263
|
+
// without any user intent.
|
|
233
264
|
if let old = oldValue {
|
|
234
|
-
Self.
|
|
235
|
-
Self.unregisterView(for: old)
|
|
265
|
+
Self.unregisterView(self, for: old)
|
|
236
266
|
}
|
|
237
267
|
|
|
238
268
|
// Thread-safe register with new key
|
|
@@ -307,7 +337,7 @@ public class SwipeableView: ExpoView {
|
|
|
307
337
|
removeGestureRecognizer(panGesture)
|
|
308
338
|
// Thread-safe deregister from view registry
|
|
309
339
|
if let key = recyclingKey {
|
|
310
|
-
Self.unregisterView(for: key)
|
|
340
|
+
Self.unregisterView(self, for: key)
|
|
311
341
|
}
|
|
312
342
|
}
|
|
313
343
|
|
|
@@ -340,7 +370,7 @@ public class SwipeableView: ExpoView {
|
|
|
340
370
|
|
|
341
371
|
// Unregister from static registry and clear cached state
|
|
342
372
|
if let key = recyclingKey {
|
|
343
|
-
Self.unregisterView(for: key)
|
|
373
|
+
Self.unregisterView(self, for: key)
|
|
344
374
|
Self.clearOpenState(for: key)
|
|
345
375
|
}
|
|
346
376
|
}
|
package/package.json
CHANGED