pythonnative 0.25.0__py3-none-any.whl → 0.26.0__py3-none-any.whl

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.
Files changed (44) hide show
  1. pythonnative/__init__.py +1 -1
  2. pythonnative/cli/pn.py +172 -12
  3. pythonnative/diagnostics.py +27 -0
  4. pythonnative/native_modules/app_state.py +2 -1
  5. pythonnative/native_modules/battery.py +3 -2
  6. pythonnative/native_modules/biometrics.py +2 -1
  7. pythonnative/native_modules/camera.py +16 -7
  8. pythonnative/native_modules/clipboard.py +3 -2
  9. pythonnative/native_modules/file_system.py +3 -2
  10. pythonnative/native_modules/haptics.py +7 -6
  11. pythonnative/native_modules/linking.py +62 -6
  12. pythonnative/native_modules/location.py +11 -8
  13. pythonnative/native_modules/net_info.py +2 -1
  14. pythonnative/native_modules/notifications.py +97 -6
  15. pythonnative/native_modules/permissions.py +3 -2
  16. pythonnative/native_modules/share.py +2 -1
  17. pythonnative/native_views/android.py +142 -122
  18. pythonnative/native_views/desktop.py +50 -49
  19. pythonnative/native_views/ios.py +228 -160
  20. pythonnative/project/android.py +15 -3
  21. pythonnative/project/builder.py +172 -70
  22. pythonnative/project/config.py +28 -6
  23. pythonnative/project/devices.py +291 -0
  24. pythonnative/project/doctor.py +5 -4
  25. pythonnative/project/ios.py +51 -77
  26. pythonnative/project/permissions.py +19 -1
  27. pythonnative/project/runtime_assets.py +78 -166
  28. pythonnative/templates/android_template/app/build.gradle +5 -0
  29. pythonnative/templates/android_template/app/src/main/AndroidManifest.xml +1 -0
  30. pythonnative/templates/android_template/app/src/main/java/com/pythonnative/android_template/MainActivity.kt +88 -12
  31. pythonnative/templates/ios_template/ios_template/AppDelegate.swift +41 -17
  32. pythonnative/templates/ios_template/ios_template/BridgingHeader.h +14 -0
  33. pythonnative/templates/ios_template/ios_template/Info.plist +0 -2
  34. pythonnative/templates/ios_template/ios_template/PythonRuntime.swift +397 -0
  35. pythonnative/templates/ios_template/ios_template/SceneDelegate.swift +31 -20
  36. pythonnative/templates/ios_template/ios_template/ViewController.swift +77 -198
  37. pythonnative/templates/ios_template/ios_template.xcodeproj/project.pbxproj +72 -47
  38. {pythonnative-0.25.0.dist-info → pythonnative-0.26.0.dist-info}/METADATA +1 -1
  39. {pythonnative-0.25.0.dist-info → pythonnative-0.26.0.dist-info}/RECORD +43 -41
  40. pythonnative/templates/ios_template/ios_template/Base.lproj/Main.storyboard +0 -24
  41. {pythonnative-0.25.0.dist-info → pythonnative-0.26.0.dist-info}/WHEEL +0 -0
  42. {pythonnative-0.25.0.dist-info → pythonnative-0.26.0.dist-info}/entry_points.txt +0 -0
  43. {pythonnative-0.25.0.dist-info → pythonnative-0.26.0.dist-info}/licenses/LICENSE +0 -0
  44. {pythonnative-0.25.0.dist-info → pythonnative-0.26.0.dist-info}/top_level.txt +0 -0
@@ -42,6 +42,7 @@ from typing import Any, Callable, Dict, List, Optional, Tuple
42
42
 
43
43
  from rubicon.objc import SEL, ObjCClass, ObjCInstance, objc_method
44
44
 
45
+ from .. import diagnostics
45
46
  from ..events import dispatch_event, event_names
46
47
  from . import _tripwire_log
47
48
  from .base import ViewHandler, _safe_max, parse_color_int
@@ -80,7 +81,7 @@ try:
80
81
  _UIView = ObjCClass("UIView")
81
82
  _UIView.declare_property("superview")
82
83
  except Exception:
83
- pass
84
+ diagnostics.swallowed("ios.<module>")
84
85
 
85
86
 
86
87
  def _objc_ptr(obj: Any) -> Optional[int]:
@@ -267,17 +268,17 @@ def _apply_border(layer: Any, props: Dict[str, Any]) -> None:
267
268
  # asks for corners (matches iOS UIKit common practice).
268
269
  layer.setMasksToBounds_(True)
269
270
  except Exception:
270
- pass
271
+ diagnostics.swallowed("ios._apply_border")
271
272
  if "border_width" in props and props["border_width"] is not None:
272
273
  try:
273
274
  layer.setBorderWidth_(float(props["border_width"]))
274
275
  except Exception:
275
- pass
276
+ diagnostics.swallowed("ios._apply_border")
276
277
  if "border_color" in props and props["border_color"] is not None:
277
278
  try:
278
279
  layer.setBorderColor_(_cgcolor(props["border_color"]))
279
280
  except Exception:
280
- pass
281
+ diagnostics.swallowed("ios._apply_border")
281
282
 
282
283
 
283
284
  def _apply_view_border(view: Any, props: Dict[str, Any]) -> None:
@@ -294,13 +295,13 @@ def _apply_view_border(view: Any, props: Dict[str, Any]) -> None:
294
295
  if width > 0.0 and height > 0.0:
295
296
  radius = min(requested, min(width, height) / 2.0)
296
297
  except Exception:
297
- pass
298
+ diagnostics.swallowed("ios._apply_view_border")
298
299
  border_props = dict(props)
299
300
  border_props["border_radius"] = radius
300
301
  _apply_border(view.layer, border_props)
301
302
  return
302
303
  except Exception:
303
- pass
304
+ diagnostics.swallowed("ios._apply_view_border")
304
305
  _apply_border(view.layer, props)
305
306
 
306
307
 
@@ -344,7 +345,7 @@ def _apply_side_borders(view: Any, props: Dict[str, Any]) -> None:
344
345
  try:
345
346
  view.layer.setBorderWidth_(0.0)
346
347
  except Exception:
347
- pass
348
+ diagnostics.swallowed("ios._apply_side_borders")
348
349
  try:
349
350
  bounds = view.bounds
350
351
  w = float(bounds.size.width)
@@ -352,7 +353,7 @@ def _apply_side_borders(view: Any, props: Dict[str, Any]) -> None:
352
353
  if w > 0.0 and h > 0.0:
353
354
  _update_side_border_layers(view, w, h)
354
355
  except Exception:
355
- pass
356
+ diagnostics.swallowed("ios._apply_side_borders")
356
357
 
357
358
 
358
359
  def _update_side_border_layers(view: Any, width: float, height: float) -> None:
@@ -377,7 +378,7 @@ def _update_side_border_layers(view: Any, width: float, height: float) -> None:
377
378
  try:
378
379
  layer.removeFromSuperlayer()
379
380
  except Exception:
380
- pass
381
+ diagnostics.swallowed("ios._update_side_border_layers")
381
382
  layers[i] = None
382
383
  continue
383
384
  try:
@@ -388,7 +389,7 @@ def _update_side_border_layers(view: Any, width: float, height: float) -> None:
388
389
  layer.setBackgroundColor_(_cgcolor(entry["colors"][i]))
389
390
  layer.setFrame_(frames[i])
390
391
  except Exception:
391
- pass
392
+ diagnostics.swallowed("ios._update_side_border_layers")
392
393
 
393
394
 
394
395
  def _clamp_view_corner_radius(view: Any, width: float, height: float) -> None:
@@ -402,7 +403,7 @@ def _clamp_view_corner_radius(view: Any, width: float, height: float) -> None:
402
403
  try:
403
404
  view.layer.setCornerRadius_(min(float(requested), max_radius))
404
405
  except Exception:
405
- pass
406
+ diagnostics.swallowed("ios._clamp_view_corner_radius")
406
407
 
407
408
 
408
409
  def _clamp_layer_corner_radius(layer: Any, width: float, height: float) -> None:
@@ -418,7 +419,7 @@ def _clamp_layer_corner_radius(layer: Any, width: float, height: float) -> None:
418
419
  try:
419
420
  layer.setCornerRadius_(min(requested, max_radius))
420
421
  except Exception:
421
- pass
422
+ diagnostics.swallowed("ios._clamp_layer_corner_radius")
422
423
 
423
424
 
424
425
  def _apply_shadow(view: Any, props: Dict[str, Any]) -> None:
@@ -434,22 +435,22 @@ def _apply_shadow(view: Any, props: Dict[str, Any]) -> None:
434
435
  layer.setMasksToBounds_(False)
435
436
  view.setClipsToBounds_(False)
436
437
  except Exception:
437
- pass
438
+ diagnostics.swallowed("ios._apply_shadow")
438
439
  if "shadow_color" in props and props["shadow_color"] is not None:
439
440
  try:
440
441
  layer.setShadowColor_(_cgcolor(props["shadow_color"]))
441
442
  except Exception:
442
- pass
443
+ diagnostics.swallowed("ios._apply_shadow")
443
444
  if "shadow_opacity" in props and props["shadow_opacity"] is not None:
444
445
  try:
445
446
  layer.setShadowOpacity_(float(props["shadow_opacity"]))
446
447
  except Exception:
447
- pass
448
+ diagnostics.swallowed("ios._apply_shadow")
448
449
  if "shadow_radius" in props and props["shadow_radius"] is not None:
449
450
  try:
450
451
  layer.setShadowRadius_(float(props["shadow_radius"]))
451
452
  except Exception:
452
- pass
453
+ diagnostics.swallowed("ios._apply_shadow")
453
454
  if "shadow_offset" in props and props["shadow_offset"] is not None:
454
455
  offset = props["shadow_offset"]
455
456
  try:
@@ -460,7 +461,7 @@ def _apply_shadow(view: Any, props: Dict[str, Any]) -> None:
460
461
  w, h = float(offset[0]), float(offset[1])
461
462
  layer.setShadowOffset_((w, h))
462
463
  except Exception:
463
- pass
464
+ diagnostics.swallowed("ios._apply_shadow")
464
465
 
465
466
 
466
467
  def _make_transform(spec: Any) -> Any:
@@ -534,7 +535,7 @@ def _apply_transform(view: Any, props: Dict[str, Any]) -> None:
534
535
  try:
535
536
  view.setTransform_((1.0, 0.0, 0.0, 1.0, 0.0, 0.0))
536
537
  except Exception:
537
- pass
538
+ diagnostics.swallowed("ios._apply_transform")
538
539
  return
539
540
  try:
540
541
  transform = _make_transform(spec)
@@ -565,7 +566,7 @@ def _apply_transform(view: Any, props: Dict[str, Any]) -> None:
565
566
  # rubicon-objc accepts the C struct as a tuple of its fields.
566
567
  view.setTransform_((a, b, c, d, tx, ty))
567
568
  except Exception:
568
- pass
569
+ diagnostics.swallowed("ios._apply_transform")
569
570
 
570
571
 
571
572
  # UIAccessibilityTraits bitmask values (UIKit constants).
@@ -604,25 +605,25 @@ def _apply_accessibility(view: Any, props: Dict[str, Any]) -> None:
604
605
  try:
605
606
  view.setIsAccessibilityElement_(bool(props["accessible"]))
606
607
  except Exception:
607
- pass
608
+ diagnostics.swallowed("ios._apply_accessibility")
608
609
  if "accessibility_label" in props:
609
610
  v = props["accessibility_label"]
610
611
  try:
611
612
  view.setAccessibilityLabel_(str(v) if v is not None else "")
612
613
  except Exception:
613
- pass
614
+ diagnostics.swallowed("ios._apply_accessibility")
614
615
  if "accessibility_hint" in props:
615
616
  v = props["accessibility_hint"]
616
617
  try:
617
618
  view.setAccessibilityHint_(str(v) if v is not None else "")
618
619
  except Exception:
619
- pass
620
+ diagnostics.swallowed("ios._apply_accessibility")
620
621
  if "test_id" in props:
621
622
  v = props["test_id"]
622
623
  try:
623
624
  view.setAccessibilityIdentifier_(str(v) if v is not None else None)
624
625
  except Exception:
625
- pass
626
+ diagnostics.swallowed("ios._apply_accessibility")
626
627
 
627
628
  role = props.get("accessibility_role")
628
629
  state = props.get("accessibility_state")
@@ -642,11 +643,11 @@ def _apply_accessibility(view: Any, props: Dict[str, Any]) -> None:
642
643
  try:
643
644
  view.setAccessibilityValue_("expanded" if state["expanded"] else "collapsed")
644
645
  except Exception:
645
- pass
646
+ diagnostics.swallowed("ios._apply_accessibility")
646
647
  try:
647
648
  view.setAccessibilityTraits_(traits)
648
649
  except Exception:
649
- pass
650
+ diagnostics.swallowed("ios._apply_accessibility")
650
651
 
651
652
 
652
653
  def _apply_common_visual(view: Any, props: Dict[str, Any]) -> None:
@@ -657,14 +658,14 @@ def _apply_common_visual(view: Any, props: Dict[str, Any]) -> None:
657
658
  try:
658
659
  view.layer.setBackgroundColor_(color.CGColor)
659
660
  except Exception:
660
- pass
661
+ diagnostics.swallowed("ios._apply_common_visual")
661
662
  if "overflow" in props:
662
663
  view.setClipsToBounds_(props["overflow"] == "hidden")
663
664
  if "opacity" in props and props["opacity"] is not None:
664
665
  try:
665
666
  view.setAlpha_(float(props["opacity"]))
666
667
  except Exception:
667
- pass
668
+ diagnostics.swallowed("ios._apply_common_visual")
668
669
  _apply_view_border(view, props)
669
670
  _apply_side_borders(view, props)
670
671
  _apply_shadow(view, props)
@@ -733,7 +734,7 @@ def _set_recognizer_delegate(recognizer: Any) -> None:
733
734
  rec_ptr = recognizer.ptr if hasattr(recognizer, "ptr") else recognizer
734
735
  _objc_msgSend(rec_ptr, _SEL_SET_DELEGATE, delegate)
735
736
  except Exception:
736
- pass
737
+ diagnostics.swallowed("ios._set_recognizer_delegate")
737
738
 
738
739
 
739
740
  # ======================================================================
@@ -753,6 +754,7 @@ def _set_recognizer_delegate(recognizer: Any) -> None:
753
754
  _pn_action_handlers: Dict[int, Any] = {}
754
755
 
755
756
  _ACTION_IMP_TYPE = _ct.CFUNCTYPE(None, _ct.c_void_p, _ct.c_void_p, _ct.c_void_p)
757
+ _CONTROL_ACTION_IMP_TYPE = _ct.CFUNCTYPE(None, _ct.c_void_p, _ct.c_void_p, _ct.c_void_p, _ct.c_void_p)
756
758
 
757
759
 
758
760
  def _action_imp(_self_ptr: int, _cmd_ptr: int, sender_ptr: int) -> None:
@@ -763,12 +765,70 @@ def _action_imp(_self_ptr: int, _cmd_ptr: int, sender_ptr: int) -> None:
763
765
  try:
764
766
  handler()
765
767
  except Exception:
766
- pass
768
+ diagnostics.swallowed("ios._action_imp")
767
769
 
768
770
 
769
771
  _action_imp_ref = _ACTION_IMP_TYPE(_action_imp)
770
772
 
773
+ # ----------------------------------------------------------------------
774
+ # UIControl action dedupe
775
+ # ----------------------------------------------------------------------
776
+ #
777
+ # The simulator's XCTest event-injection stack sometimes delivers a
778
+ # single synthesized tap as *two* back-to-back "send control actions"
779
+ # bursts for the same UIEvent (~1ms apart; the unified log shows one
780
+ # UIEvent delivered to one window, then the doubled sends). Every
781
+ # non-idempotent ``on_press`` then fires twice: reducer counters jump
782
+ # by two, alerts present twice, pickers reopen after selecting. The
783
+ # control action selector therefore takes the ``forEvent:`` argument
784
+ # and drops a second send whose UIEvent timestamp matches the last one
785
+ # delivered to the same control. Distinct taps (even rapid ones) carry
786
+ # distinct event timestamps, and continuous ValueChanged streams
787
+ # (slider drags) tick the timestamp per touch move, so only the
788
+ # duplicated sends are filtered. Programmatic ``sendActions...`` calls
789
+ # pass a nil event and are never deduped.
790
+
791
+ # Maps control ptr -> UIEvent.timestamp of the last delivered action.
792
+ _pn_last_control_event_ts: Dict[int, float] = {}
793
+
794
+ _objc_msgSend_double = _ct.CFUNCTYPE(_ct.c_double, _ct.c_void_p, _ct.c_void_p)(("objc_msgSend", _libobjc))
795
+
796
+ _SEL_TIMESTAMP = _sel_reg(b"timestamp")
797
+
798
+
799
+ def _control_action_imp(_self_ptr: int, _cmd_ptr: int, sender_ptr: int, event_ptr: int) -> None:
800
+ """Raw C callback for every PythonNative UIControl event action."""
801
+ key = int(sender_ptr or 0)
802
+ handler = _pn_action_handlers.get(key)
803
+ if handler is None:
804
+ return
805
+ if event_ptr:
806
+ try:
807
+ timestamp = float(_objc_msgSend_double(event_ptr, _SEL_TIMESTAMP))
808
+ except Exception:
809
+ timestamp = None
810
+ if timestamp is not None:
811
+ if _pn_last_control_event_ts.get(key) == timestamp:
812
+ diagnostics.warn_once(
813
+ "ios._control_action_imp dropped a duplicated control action "
814
+ "(one UIEvent, two sends; a simulator event-injection quirk)",
815
+ key=f"control_action_dedupe:{key}",
816
+ )
817
+ return
818
+ _pn_last_control_event_ts[key] = timestamp
819
+ try:
820
+ handler()
821
+ except Exception:
822
+ diagnostics.swallowed("ios._control_action_imp")
823
+
824
+
825
+ _control_action_imp_ref = _CONTROL_ACTION_IMP_TYPE(_control_action_imp)
826
+
827
+ # Gesture recognizers only support zero- or one-argument action
828
+ # selectors, so recognizers keep the plain variant while controls use
829
+ # the two-argument ``forEvent:`` variant for the dedupe above.
771
830
  _SEL_ON_ACTION = _sel_reg(b"onPNAction:")
831
+ _SEL_ON_CONTROL_ACTION = _sel_reg(b"onPNControlAction:forEvent:")
772
832
 
773
833
  _PN_ACTION_TARGET_CLS = _alloc_cls(_NS_OBJECT_CLS, b"_PNActionTargetCTypes", 0)
774
834
  if _PN_ACTION_TARGET_CLS:
@@ -778,6 +838,12 @@ if _PN_ACTION_TARGET_CLS:
778
838
  _ct.cast(_action_imp_ref, _ct.c_void_p),
779
839
  b"v@:@",
780
840
  )
841
+ _add_method(
842
+ _PN_ACTION_TARGET_CLS,
843
+ _SEL_ON_CONTROL_ACTION,
844
+ _ct.cast(_control_action_imp_ref, _ct.c_void_p),
845
+ b"v@:@@",
846
+ )
781
847
  _reg_cls(_PN_ACTION_TARGET_CLS)
782
848
 
783
849
  _pn_action_target_ptr: Any = None
@@ -830,7 +896,7 @@ def _register_control_action(control: Any, events_mask: int, handler: Any) -> No
830
896
  _objc_msgSend.restype = None
831
897
  _objc_msgSend.argtypes = [_ct.c_void_p, _ct.c_void_p, _ct.c_void_p, _ct.c_ulong]
832
898
  ctl_ptr = control.ptr if hasattr(control, "ptr") else control
833
- _objc_msgSend(ctl_ptr, _SEL_ADD_TARGET_ACTION_EVENTS, target_ptr, _SEL_ON_ACTION, events_mask)
899
+ _objc_msgSend(ctl_ptr, _SEL_ADD_TARGET_ACTION_EVENTS, target_ptr, _SEL_ON_CONTROL_ACTION, events_mask)
834
900
  _pn_action_handlers[_recognizer_ptr(control)] = handler
835
901
 
836
902
 
@@ -864,11 +930,11 @@ def _make_gesture_handler(
864
930
  payload["x"] = float(location.x)
865
931
  payload["y"] = float(location.y)
866
932
  except Exception:
867
- pass
933
+ diagnostics.swallowed("ios._make_gesture_handler.handler")
868
934
  try:
869
935
  payload["pointer_count"] = int(rec.numberOfTouches)
870
936
  except Exception:
871
- pass
937
+ diagnostics.swallowed("ios._make_gesture_handler.handler")
872
938
 
873
939
  if kind == "pan":
874
940
  try:
@@ -879,17 +945,17 @@ def _make_gesture_handler(
879
945
  payload["velocity_x"] = float(velocity.x)
880
946
  payload["velocity_y"] = float(velocity.y)
881
947
  except Exception:
882
- pass
948
+ diagnostics.swallowed("ios._make_gesture_handler.handler")
883
949
  elif kind == "pinch":
884
950
  try:
885
951
  payload["scale"] = float(rec.scale)
886
952
  except Exception:
887
- pass
953
+ diagnostics.swallowed("ios._make_gesture_handler.handler")
888
954
  elif kind == "rotation":
889
955
  try:
890
956
  payload["rotation"] = float(rec.rotation)
891
957
  except Exception:
892
- pass
958
+ diagnostics.swallowed("ios._make_gesture_handler.handler")
893
959
  elif kind == "swipe":
894
960
  # Discrete: UIKit only calls us on recognition, and only the
895
961
  # recognizer whose direction matched fires, so the bound
@@ -917,7 +983,7 @@ def _make_recognizer(kind: str, spec: Dict[str, Any]) -> List[Tuple[Any, Optiona
917
983
  try:
918
984
  rec.setNumberOfTapsRequired_(max(1, int(spec.get("n_taps", 1))))
919
985
  except Exception:
920
- pass
986
+ diagnostics.swallowed("ios._make_recognizer")
921
987
  out.append((rec, None))
922
988
  elif kind == "long_press":
923
989
  rec = ObjCClass("UILongPressGestureRecognizer").alloc().init()
@@ -925,14 +991,14 @@ def _make_recognizer(kind: str, spec: Dict[str, Any]) -> List[Tuple[Any, Optiona
925
991
  rec.setMinimumPressDuration_(float(spec.get("min_duration_ms", 500.0)) / 1000.0)
926
992
  rec.setAllowableMovement_(float(spec.get("max_distance", 12.0)))
927
993
  except Exception:
928
- pass
994
+ diagnostics.swallowed("ios._make_recognizer")
929
995
  out.append((rec, None))
930
996
  elif kind == "pan":
931
997
  rec = ObjCClass("UIPanGestureRecognizer").alloc().init()
932
998
  try:
933
999
  rec.setMinimumNumberOfTouches_(max(1, int(spec.get("min_pointers", 1))))
934
1000
  except Exception:
935
- pass
1001
+ diagnostics.swallowed("ios._make_recognizer")
936
1002
  out.append((rec, None))
937
1003
  elif kind == "swipe":
938
1004
  direction = str(spec.get("direction", "any"))
@@ -942,7 +1008,7 @@ def _make_recognizer(kind: str, spec: Dict[str, Any]) -> List[Tuple[Any, Optiona
942
1008
  try:
943
1009
  rec.setDirection_(_SWIPE_DIRECTIONS[d])
944
1010
  except Exception:
945
- pass
1011
+ diagnostics.swallowed("ios._make_recognizer")
946
1012
  out.append((rec, d))
947
1013
  elif kind == "pinch":
948
1014
  out.append((ObjCClass("UIPinchGestureRecognizer").alloc().init(), None))
@@ -963,7 +1029,7 @@ def _wire_gestures(view: Any, specs: Any) -> None:
963
1029
  try:
964
1030
  view.removeGestureRecognizer_(rec)
965
1031
  except Exception:
966
- pass
1032
+ diagnostics.swallowed("ios._wire_gestures")
967
1033
  _pn_action_handlers.pop(_recognizer_ptr(rec), None)
968
1034
  state["gesture_recognizers"] = []
969
1035
  if not isinstance(specs, (list, tuple)) or not specs:
@@ -972,7 +1038,7 @@ def _wire_gestures(view: Any, specs: Any) -> None:
972
1038
  try:
973
1039
  view.setUserInteractionEnabled_(True)
974
1040
  except Exception:
975
- pass
1041
+ diagnostics.swallowed("ios._wire_gestures")
976
1042
 
977
1043
  recognizers: List[Any] = []
978
1044
  for i, spec in enumerate(specs):
@@ -985,7 +1051,7 @@ def _wire_gestures(view: Any, specs: Any) -> None:
985
1051
  try:
986
1052
  rec.setCancelsTouchesInView_(False)
987
1053
  except Exception:
988
- pass
1054
+ diagnostics.swallowed("ios._wire_gestures")
989
1055
  _set_recognizer_delegate(rec)
990
1056
  try:
991
1057
  view.addGestureRecognizer_(rec)
@@ -1082,13 +1148,13 @@ def _start_native_animation(view: Any, anim_id: int, prop_name: str, spec: Dict[
1082
1148
 
1083
1149
  native_animation_completed(anim_id, bool(finished))
1084
1150
  except Exception:
1085
- pass
1151
+ diagnostics.swallowed("ios._start_native_animation._completion")
1086
1152
 
1087
1153
  def _animations() -> None:
1088
1154
  try:
1089
1155
  applier_to(view)
1090
1156
  except Exception:
1091
- pass
1157
+ diagnostics.swallowed("ios._start_native_animation._animations")
1092
1158
 
1093
1159
  try:
1094
1160
  # Snap to the starting value so the animation covers the full
@@ -1166,12 +1232,13 @@ class IOSViewHandler(ViewHandler):
1166
1232
  # Controls register their own pointer as the action-handler key
1167
1233
  # (see _register_control_action); drop it with the view.
1168
1234
  _pn_action_handlers.pop(_recognizer_ptr(native_view), None)
1235
+ _pn_last_control_event_ts.pop(_recognizer_ptr(native_view), None)
1169
1236
  _pn_view_border_radius_map.pop(id(native_view), None)
1170
1237
  _pn_side_border_map.pop(id(native_view), None)
1171
1238
  try:
1172
1239
  native_view.removeFromSuperview()
1173
1240
  except Exception:
1174
- pass
1241
+ diagnostics.swallowed("ios.IOSViewHandler.destroy")
1175
1242
  _forget(native_view)
1176
1243
 
1177
1244
  def _build(self, props: Dict[str, Any]) -> Any:
@@ -1187,7 +1254,7 @@ class IOSViewHandler(ViewHandler):
1187
1254
  try:
1188
1255
  child.setTranslatesAutoresizingMaskIntoConstraints_(True)
1189
1256
  except Exception:
1190
- pass
1257
+ diagnostics.swallowed("ios.IOSViewHandler.insert_child")
1191
1258
  try:
1192
1259
  count = len(list(parent.subviews or []))
1193
1260
  except Exception:
@@ -1198,13 +1265,13 @@ class IOSViewHandler(ViewHandler):
1198
1265
  try:
1199
1266
  parent.addSubview_(child)
1200
1267
  except Exception:
1201
- pass
1268
+ diagnostics.swallowed("ios.IOSViewHandler.insert_child")
1202
1269
 
1203
1270
  def remove_child(self, parent: Any, child: Any) -> None:
1204
1271
  try:
1205
1272
  child.removeFromSuperview()
1206
1273
  except Exception:
1207
- pass
1274
+ diagnostics.swallowed("ios.IOSViewHandler.remove_child")
1208
1275
 
1209
1276
  def set_frame(self, native_view: Any, x: float, y: float, width: float, height: float) -> None:
1210
1277
  if native_view is None:
@@ -1221,7 +1288,7 @@ class IOSViewHandler(ViewHandler):
1221
1288
  try:
1222
1289
  _clamp_layer_corner_radius(native_view.layer, frame_w, frame_h)
1223
1290
  except Exception:
1224
- pass
1291
+ diagnostics.swallowed("ios.IOSViewHandler.set_frame")
1225
1292
  try:
1226
1293
  parent = native_view.superview
1227
1294
  parent_cls = ""
@@ -1238,9 +1305,9 @@ class IOSViewHandler(ViewHandler):
1238
1305
  content_h = max(float(bounds.size.height), frame_y + frame_h)
1239
1306
  parent.setContentSize_((content_w, content_h))
1240
1307
  except Exception:
1241
- pass
1308
+ diagnostics.swallowed("ios.IOSViewHandler.set_frame")
1242
1309
  except Exception:
1243
- pass
1310
+ diagnostics.swallowed("ios.IOSViewHandler.set_frame")
1244
1311
 
1245
1312
  def measure_intrinsic(
1246
1313
  self,
@@ -1273,7 +1340,7 @@ class IOSViewHandler(ViewHandler):
1273
1340
  try:
1274
1341
  applier(native_view)
1275
1342
  except Exception:
1276
- pass
1343
+ diagnostics.swallowed("ios.IOSViewHandler.set_animated_property")
1277
1344
 
1278
1345
  def start_animation(
1279
1346
  self,
@@ -1312,7 +1379,7 @@ class IOSViewHandler(ViewHandler):
1312
1379
  try:
1313
1380
  view.layer.removeAllAnimations()
1314
1381
  except Exception:
1315
- pass
1382
+ diagnostics.swallowed("ios.IOSViewHandler.cancel_animation")
1316
1383
  return value
1317
1384
 
1318
1385
 
@@ -1400,7 +1467,7 @@ class TextHandler(IOSViewHandler):
1400
1467
  if desc is not None:
1401
1468
  font = UIFont.fontWithDescriptor_size_(desc, size)
1402
1469
  except Exception:
1403
- pass
1470
+ diagnostics.swallowed("ios.TextHandler._font_for")
1404
1471
  return font
1405
1472
 
1406
1473
  _SPAN_REBUILD_KEYS = (
@@ -1463,7 +1530,7 @@ class TextHandler(IOSViewHandler):
1463
1530
  try:
1464
1531
  label.setAlpha_(float(props["opacity"]))
1465
1532
  except Exception:
1466
- pass
1533
+ diagnostics.swallowed("ios.TextHandler._apply")
1467
1534
 
1468
1535
  def _apply_spans(self, label: Any, merged: Dict[str, Any]) -> None:
1469
1536
  """Render a rich-text span list as one NSAttributedString.
@@ -1525,13 +1592,13 @@ class TextHandler(IOSViewHandler):
1525
1592
  elif span.get("text_decoration") == "line_through":
1526
1593
  attr.addAttribute_value_range_("NSStrikethrough", 1, rng)
1527
1594
  except Exception:
1528
- pass
1595
+ diagnostics.swallowed("ios.TextHandler._apply_spans")
1529
1596
  label.setAttributedText_(attr)
1530
1597
  except Exception:
1531
1598
  try:
1532
1599
  label.setText_(str(merged.get("text") or ""))
1533
1600
  except Exception:
1534
- pass
1601
+ diagnostics.swallowed("ios.TextHandler._apply_spans")
1535
1602
 
1536
1603
  def _apply_attributed(self, label: Any, props: Dict[str, Any]) -> None:
1537
1604
  """Re-render the label's text as an NSAttributedString.
@@ -1576,7 +1643,7 @@ class TextHandler(IOSViewHandler):
1576
1643
  attr.addAttribute_value_range_("NSStrikethrough", 1, full_range)
1577
1644
  label.setAttributedText_(attr)
1578
1645
  except Exception:
1579
- pass
1646
+ diagnostics.swallowed("ios.TextHandler._apply_attributed")
1580
1647
 
1581
1648
 
1582
1649
  class ButtonHandler(IOSViewHandler):
@@ -1632,7 +1699,7 @@ class ButtonHandler(IOSViewHandler):
1632
1699
  try:
1633
1700
  btn.setAlpha_(float(props["opacity"]))
1634
1701
  except Exception:
1635
- pass
1702
+ diagnostics.swallowed("ios.ButtonHandler._apply")
1636
1703
 
1637
1704
 
1638
1705
  # ``scrollViewDidScroll:`` hands the delegate a ``UIScrollView*``. rubicon's
@@ -1718,24 +1785,24 @@ class ScrollViewHandler(IOSViewHandler):
1718
1785
  sv.setShowsVerticalScrollIndicator_(visible)
1719
1786
  sv.setShowsHorizontalScrollIndicator_(visible)
1720
1787
  except Exception:
1721
- pass
1788
+ diagnostics.swallowed("ios.ScrollViewHandler._apply")
1722
1789
  if "paging_enabled" in props:
1723
1790
  try:
1724
1791
  sv.setPagingEnabled_(bool(props["paging_enabled"]))
1725
1792
  except Exception:
1726
- pass
1793
+ diagnostics.swallowed("ios.ScrollViewHandler._apply")
1727
1794
  if "bounces" in props:
1728
1795
  b = props["bounces"]
1729
1796
  try:
1730
1797
  sv.setBounces_(True if b is None else bool(b))
1731
1798
  except Exception:
1732
- pass
1799
+ diagnostics.swallowed("ios.ScrollViewHandler._apply")
1733
1800
  if "keyboard_dismiss_mode" in props and props["keyboard_dismiss_mode"] is not None:
1734
1801
  mapping = {"none": 0, "on_drag": 1, "interactive": 2}
1735
1802
  try:
1736
1803
  sv.setKeyboardDismissMode_(mapping.get(props["keyboard_dismiss_mode"], 0))
1737
1804
  except Exception:
1738
- pass
1805
+ diagnostics.swallowed("ios.ScrollViewHandler._apply")
1739
1806
 
1740
1807
  def command(self, native_view: Any, name: str, args: Dict[str, Any]) -> Any:
1741
1808
  if name == "scroll_to_offset":
@@ -1745,7 +1812,7 @@ class ScrollViewHandler(IOSViewHandler):
1745
1812
  try:
1746
1813
  native_view.setContentOffset_animated_((x, y), animated)
1747
1814
  except Exception:
1748
- pass
1815
+ diagnostics.swallowed("ios.ScrollViewHandler.command")
1749
1816
  return None
1750
1817
  if name == "scroll_to_end":
1751
1818
  animated = args.get("animated", True) is not False
@@ -1760,7 +1827,7 @@ class ScrollViewHandler(IOSViewHandler):
1760
1827
  offset = (target_x, 0.0) if horizontal else (0.0, target_y)
1761
1828
  native_view.setContentOffset_animated_(offset, animated)
1762
1829
  except Exception:
1763
- pass
1830
+ diagnostics.swallowed("ios.ScrollViewHandler.command")
1764
1831
  return None
1765
1832
  if name == "get_scroll_offset":
1766
1833
  try:
@@ -1796,10 +1863,11 @@ class ScrollViewHandler(IOSViewHandler):
1796
1863
  if existing is not None:
1797
1864
  existing.endRefreshing()
1798
1865
  _pn_action_handlers.pop(_recognizer_ptr(existing), None)
1866
+ _pn_last_control_event_ts.pop(_recognizer_ptr(existing), None)
1799
1867
  sv.setRefreshControl_(None)
1800
1868
  sv.setAlwaysBounceVertical_(False)
1801
1869
  except Exception:
1802
- pass
1870
+ diagnostics.swallowed("ios.ScrollViewHandler._apply_refresh")
1803
1871
  return
1804
1872
  try:
1805
1873
  existing = sv.refreshControl
@@ -1816,7 +1884,7 @@ class ScrollViewHandler(IOSViewHandler):
1816
1884
  try:
1817
1885
  sv.setAlwaysBounceVertical_(True)
1818
1886
  except Exception:
1819
- pass
1887
+ diagnostics.swallowed("ios.ScrollViewHandler._apply_refresh")
1820
1888
  existing = rc
1821
1889
  refreshing = bool(spec.get("refreshing")) if isinstance(spec, dict) else False
1822
1890
  if refreshing:
@@ -1824,7 +1892,7 @@ class ScrollViewHandler(IOSViewHandler):
1824
1892
  else:
1825
1893
  existing.endRefreshing()
1826
1894
  except Exception:
1827
- pass
1895
+ diagnostics.swallowed("ios.ScrollViewHandler._apply_refresh")
1828
1896
 
1829
1897
 
1830
1898
  class ImageHandler(IOSViewHandler):
@@ -1842,12 +1910,12 @@ class ImageHandler(IOSViewHandler):
1842
1910
  try:
1843
1911
  iv.setTintColor_(_uicolor(props["tint_color"]))
1844
1912
  except Exception:
1845
- pass
1913
+ diagnostics.swallowed("ios.ImageHandler._apply")
1846
1914
  if "placeholder_color" in props and props["placeholder_color"] is not None:
1847
1915
  try:
1848
1916
  iv.setBackgroundColor_(_uicolor(props["placeholder_color"]))
1849
1917
  except Exception:
1850
- pass
1918
+ diagnostics.swallowed("ios.ImageHandler._apply")
1851
1919
  if "source" in props and props["source"]:
1852
1920
  self._load_source(iv, str(props["source"]))
1853
1921
  if "scale_type" in props and props["scale_type"]:
@@ -1873,7 +1941,7 @@ class ImageHandler(IOSViewHandler):
1873
1941
  w, h = max_width, h * scale
1874
1942
  return (w, h)
1875
1943
  except Exception:
1876
- pass
1944
+ diagnostics.swallowed("ios.ImageHandler.measure_intrinsic")
1877
1945
  return (0.0, 0.0)
1878
1946
 
1879
1947
  def _load_source(self, iv: Any, source: str) -> None:
@@ -1894,7 +1962,7 @@ class ImageHandler(IOSViewHandler):
1894
1962
  else:
1895
1963
  _fire(iv, "on_error", f"image {source!r} not found")
1896
1964
  except Exception:
1897
- pass
1965
+ diagnostics.swallowed("ios.ImageHandler._load_source")
1898
1966
 
1899
1967
  def _load_data_uri(self, iv: Any, source: str) -> None:
1900
1968
  """Decode an inline ``data:`` URI (base64 payload) into the view."""
@@ -1942,7 +2010,7 @@ class ImageHandler(IOSViewHandler):
1942
2010
  iv.setImage_(image)
1943
2011
  _fire(iv, "on_load")
1944
2012
  except Exception:
1945
- pass
2013
+ diagnostics.swallowed("ios.ImageHandler._load_async.on_ready")
1946
2014
 
1947
2015
  def on_error(message: str) -> None:
1948
2016
  if _state_of(iv).get("pending_uri") == source:
@@ -1950,7 +2018,7 @@ class ImageHandler(IOSViewHandler):
1950
2018
 
1951
2019
  fetch(source, on_ready, on_error)
1952
2020
  except Exception:
1953
- pass
2021
+ diagnostics.swallowed("ios.ImageHandler._load_async")
1954
2022
 
1955
2023
  def _decode_downsampled(self, iv: Any, path: str) -> Any:
1956
2024
  """Decode a file, scaling down to the view's bounds if oversized.
@@ -2052,7 +2120,7 @@ def _tf_on_change_imp(self_ptr: int, _cmd: int, sender_ptr: int) -> None:
2052
2120
  try:
2053
2121
  view.setText_(text)
2054
2122
  except Exception:
2055
- pass
2123
+ diagnostics.swallowed("ios._tf_on_change_imp")
2056
2124
  finally:
2057
2125
  state["suppress"] = False
2058
2126
  _fire(view, "on_change", text)
@@ -2077,7 +2145,7 @@ def _tf_should_return_imp(self_ptr: int, _cmd: int, tf_ptr: int) -> bool:
2077
2145
  _objc_msgSend.argtypes = [_ct.c_void_p, _ct.c_void_p]
2078
2146
  _objc_msgSend(_ct.c_void_p(int(tf_ptr or 0)), _SEL_RESIGN_FIRST_RESPONDER)
2079
2147
  except Exception:
2080
- pass
2148
+ diagnostics.swallowed("ios._tf_should_return_imp")
2081
2149
  return True
2082
2150
 
2083
2151
 
@@ -2244,7 +2312,7 @@ class TextInputHandler(IOSViewHandler):
2244
2312
  )
2245
2313
  view.setAttributedPlaceholder_(attr)
2246
2314
  except Exception:
2247
- pass
2315
+ diagnostics.swallowed("ios.TextInputHandler._apply")
2248
2316
  if "font_size" in props and props["font_size"] is not None:
2249
2317
  view.setFont_(UIFont.systemFontOfSize_(float(props["font_size"])))
2250
2318
  if "color" in props and props["color"] is not None:
@@ -2255,7 +2323,7 @@ class TextInputHandler(IOSViewHandler):
2255
2323
  try:
2256
2324
  view.setSecureTextEntry_(bool(props["secure"]))
2257
2325
  except Exception:
2258
- pass
2326
+ diagnostics.swallowed("ios.TextInputHandler._apply")
2259
2327
  if "keyboard_type" in props and props["keyboard_type"] is not None:
2260
2328
  mapping = {
2261
2329
  "default": 0,
@@ -2270,19 +2338,19 @@ class TextInputHandler(IOSViewHandler):
2270
2338
  try:
2271
2339
  view.setKeyboardType_(mapping.get(props["keyboard_type"], 0))
2272
2340
  except Exception:
2273
- pass
2341
+ diagnostics.swallowed("ios.TextInputHandler._apply")
2274
2342
  if "auto_capitalize" in props and props["auto_capitalize"] is not None:
2275
2343
  # UITextAutocapitalizationType: none=0, words=1, sentences=2, all=3.
2276
2344
  mapping = {"none": 0, "words": 1, "sentences": 2, "characters": 3}
2277
2345
  try:
2278
2346
  view.setAutocapitalizationType_(mapping.get(props["auto_capitalize"], 2))
2279
2347
  except Exception:
2280
- pass
2348
+ diagnostics.swallowed("ios.TextInputHandler._apply")
2281
2349
  if "auto_correct" in props:
2282
2350
  try:
2283
2351
  view.setAutocorrectionType_(1 if props["auto_correct"] else 0)
2284
2352
  except Exception:
2285
- pass
2353
+ diagnostics.swallowed("ios.TextInputHandler._apply")
2286
2354
  if "return_key_type" in props and props["return_key_type"] is not None:
2287
2355
  mapping = {
2288
2356
  "default": 0,
@@ -2299,23 +2367,23 @@ class TextInputHandler(IOSViewHandler):
2299
2367
  try:
2300
2368
  view.setReturnKeyType_(mapping.get(props["return_key_type"], 0))
2301
2369
  except Exception:
2302
- pass
2370
+ diagnostics.swallowed("ios.TextInputHandler._apply")
2303
2371
  if "selection_color" in props and props["selection_color"] is not None:
2304
2372
  try:
2305
2373
  view.setTintColor_(_uicolor(props["selection_color"]))
2306
2374
  except Exception:
2307
- pass
2375
+ diagnostics.swallowed("ios.TextInputHandler._apply")
2308
2376
  if "text_content_type" in props:
2309
2377
  tct = props["text_content_type"]
2310
2378
  try:
2311
2379
  view.setTextContentType_(_ui_text_content_type(str(tct)) if tct is not None else None)
2312
2380
  except Exception:
2313
- pass
2381
+ diagnostics.swallowed("ios.TextInputHandler._apply")
2314
2382
  if "clear_button" in props and is_field:
2315
2383
  try:
2316
2384
  view.setClearButtonMode_(1 if props["clear_button"] else 0) # 1 = WhileEditing
2317
2385
  except Exception:
2318
- pass
2386
+ diagnostics.swallowed("ios.TextInputHandler._apply")
2319
2387
  # ``editable`` is present only when False (read-only). A removed
2320
2388
  # prop arrives as None on update, which means "editable again".
2321
2389
  if "editable" in props:
@@ -2327,12 +2395,12 @@ class TextInputHandler(IOSViewHandler):
2327
2395
  else:
2328
2396
  view.setEditable_(resolved)
2329
2397
  except Exception:
2330
- pass
2398
+ diagnostics.swallowed("ios.TextInputHandler._apply")
2331
2399
  if "auto_focus" in props and props["auto_focus"]:
2332
2400
  try:
2333
2401
  view.becomeFirstResponder()
2334
2402
  except Exception:
2335
- pass
2403
+ diagnostics.swallowed("ios.TextInputHandler._apply")
2336
2404
  _apply_view_border(view, props)
2337
2405
  _apply_shadow(view, props)
2338
2406
  _apply_transform(view, props)
@@ -2341,7 +2409,7 @@ class TextInputHandler(IOSViewHandler):
2341
2409
  try:
2342
2410
  view.setAlpha_(float(props["opacity"]))
2343
2411
  except Exception:
2344
- pass
2412
+ diagnostics.swallowed("ios.TextInputHandler._apply")
2345
2413
 
2346
2414
  def measure_intrinsic(
2347
2415
  self,
@@ -2357,13 +2425,13 @@ class TextInputHandler(IOSViewHandler):
2357
2425
  try:
2358
2426
  native_view.becomeFirstResponder()
2359
2427
  except Exception:
2360
- pass
2428
+ diagnostics.swallowed("ios.TextInputHandler.command")
2361
2429
  return None
2362
2430
  if name == "blur":
2363
2431
  try:
2364
2432
  native_view.resignFirstResponder()
2365
2433
  except Exception:
2366
- pass
2434
+ diagnostics.swallowed("ios.TextInputHandler.command")
2367
2435
  return None
2368
2436
  if name == "clear":
2369
2437
  state = _state_of(native_view)
@@ -2481,7 +2549,7 @@ class ActivityIndicatorHandler(IOSViewHandler):
2481
2549
  try:
2482
2550
  ai.setActivityIndicatorViewStyle_(style)
2483
2551
  except Exception:
2484
- pass
2552
+ diagnostics.swallowed("ios.ActivityIndicatorHandler._apply")
2485
2553
  if "color" in props and props["color"] is not None:
2486
2554
  ai.setColor_(_uicolor(props["color"]))
2487
2555
  animating = props.get("animating")
@@ -2563,7 +2631,7 @@ class PressableHandler(IOSViewHandler):
2563
2631
  try:
2564
2632
  rec.setCancelsTouchesInView_(False)
2565
2633
  except Exception:
2566
- pass
2634
+ diagnostics.swallowed("ios.PressableHandler._wire_press")
2567
2635
  _set_recognizer_delegate(rec)
2568
2636
  view.addGestureRecognizer_(rec)
2569
2637
  rec.retain()
@@ -2643,7 +2711,7 @@ def _press_feedback(view: Any, pressed: bool) -> None:
2643
2711
  UIView = ObjCClass("UIView")
2644
2712
  UIView.animateWithDuration_animations_(duration, lambda: view.setAlpha_(opacity))
2645
2713
  except Exception:
2646
- pass
2714
+ diagnostics.swallowed("ios._press_feedback")
2647
2715
 
2648
2716
 
2649
2717
  # ======================================================================
@@ -2668,7 +2736,7 @@ class ProgressBarHandler(IOSViewHandler):
2668
2736
  try:
2669
2737
  ai.startAnimating()
2670
2738
  except Exception:
2671
- pass
2739
+ diagnostics.swallowed("ios.ProgressBarHandler._build")
2672
2740
  return ai
2673
2741
  pv = ObjCClass("UIProgressView").alloc().init()
2674
2742
  pv.setTranslatesAutoresizingMaskIntoConstraints_(True)
@@ -2684,27 +2752,27 @@ class ProgressBarHandler(IOSViewHandler):
2684
2752
  try:
2685
2753
  view.setColor_(_uicolor(props["color"]))
2686
2754
  except Exception:
2687
- pass
2755
+ diagnostics.swallowed("ios.ProgressBarHandler._apply")
2688
2756
  try:
2689
2757
  view.startAnimating()
2690
2758
  except Exception:
2691
- pass
2759
+ diagnostics.swallowed("ios.ProgressBarHandler._apply")
2692
2760
  else:
2693
2761
  if "value" in props and props["value"] is not None:
2694
2762
  try:
2695
2763
  view.setProgress_(float(props["value"]))
2696
2764
  except Exception:
2697
- pass
2765
+ diagnostics.swallowed("ios.ProgressBarHandler._apply")
2698
2766
  if "color" in props and props["color"] is not None:
2699
2767
  try:
2700
2768
  view.setProgressTintColor_(_uicolor(props["color"]))
2701
2769
  except Exception:
2702
- pass
2770
+ diagnostics.swallowed("ios.ProgressBarHandler._apply")
2703
2771
  if "track_color" in props and props["track_color"] is not None:
2704
2772
  try:
2705
2773
  view.setTrackTintColor_(_uicolor(props["track_color"]))
2706
2774
  except Exception:
2707
- pass
2775
+ diagnostics.swallowed("ios.ProgressBarHandler._apply")
2708
2776
  _apply_accessibility(view, props)
2709
2777
 
2710
2778
  def measure_intrinsic(
@@ -2771,7 +2839,7 @@ def _webview_did_finish_imp(self_ptr: int, _cmd_ptr: int, _webview_ptr: int, _na
2771
2839
  try:
2772
2840
  wv.evaluateJavaScript_completionHandler_(str(js), None)
2773
2841
  except Exception:
2774
- pass
2842
+ diagnostics.swallowed("ios._webview_did_finish_imp")
2775
2843
  _fire(wv, "on_load", _webview_url(wv))
2776
2844
 
2777
2845
 
@@ -2855,7 +2923,7 @@ class WebViewHandler(IOSViewHandler):
2855
2923
  try:
2856
2924
  cls.declare_property(prop)
2857
2925
  except Exception:
2858
- pass
2926
+ diagnostics.swallowed("ios.WebViewHandler._build")
2859
2927
  _pn_wkwebview_declared = True
2860
2928
  config = WKWebViewConfiguration.alloc().init()
2861
2929
  delegate_ptr = _new_webview_delegate_ptr()
@@ -2867,14 +2935,14 @@ class WebViewHandler(IOSViewHandler):
2867
2935
  try:
2868
2936
  config.userContentController.addScriptMessageHandler_name_(delegate, "pythonnative")
2869
2937
  except Exception:
2870
- pass
2938
+ diagnostics.swallowed("ios.WebViewHandler._build")
2871
2939
  wv = WKWebView.alloc().initWithFrame_configuration_(((0, 0), (0, 0)), config)
2872
2940
  wv.setTranslatesAutoresizingMaskIntoConstraints_(True)
2873
2941
  if delegate is not None:
2874
2942
  try:
2875
2943
  wv.setNavigationDelegate_(delegate)
2876
2944
  except Exception:
2877
- pass
2945
+ diagnostics.swallowed("ios.WebViewHandler._build")
2878
2946
  if delegate_ptr:
2879
2947
  _pn_webview_state[delegate_ptr] = {"view": wv, "inject_js": None}
2880
2948
  self._delegate_ids[_objc_ptr(wv) or 0] = delegate_ptr
@@ -2907,7 +2975,7 @@ class WebViewHandler(IOSViewHandler):
2907
2975
  try:
2908
2976
  wv.loadHTMLString_baseURL_(str(props["html"]), None)
2909
2977
  except Exception:
2910
- pass
2978
+ diagnostics.swallowed("ios.WebViewHandler._apply")
2911
2979
  elif "url" in props and props["url"]:
2912
2980
  try:
2913
2981
  NSURL = ObjCClass("NSURL")
@@ -2915,38 +2983,38 @@ class WebViewHandler(IOSViewHandler):
2915
2983
  url_obj = NSURL.URLWithString_(str(props["url"]))
2916
2984
  wv.loadRequest_(NSURLRequest.requestWithURL_(url_obj))
2917
2985
  except Exception:
2918
- pass
2986
+ diagnostics.swallowed("ios.WebViewHandler._apply")
2919
2987
  if "scroll_enabled" in props:
2920
2988
  enabled = props["scroll_enabled"]
2921
2989
  try:
2922
2990
  wv.scrollView.setScrollEnabled_(True if enabled is None else bool(enabled))
2923
2991
  except Exception:
2924
- pass
2992
+ diagnostics.swallowed("ios.WebViewHandler._apply")
2925
2993
 
2926
2994
  def command(self, native_view: Any, name: str, args: Dict[str, Any]) -> Any:
2927
2995
  if name == "eval_js":
2928
2996
  try:
2929
2997
  native_view.evaluateJavaScript_completionHandler_(str(args.get("source", "")), None)
2930
2998
  except Exception:
2931
- pass
2999
+ diagnostics.swallowed("ios.WebViewHandler.command")
2932
3000
  return None
2933
3001
  if name == "reload":
2934
3002
  try:
2935
3003
  native_view.reload()
2936
3004
  except Exception:
2937
- pass
3005
+ diagnostics.swallowed("ios.WebViewHandler.command")
2938
3006
  return None
2939
3007
  if name == "go_back":
2940
3008
  try:
2941
3009
  native_view.goBack()
2942
3010
  except Exception:
2943
- pass
3011
+ diagnostics.swallowed("ios.WebViewHandler.command")
2944
3012
  return None
2945
3013
  if name == "go_forward":
2946
3014
  try:
2947
3015
  native_view.goForward()
2948
3016
  except Exception:
2949
- pass
3017
+ diagnostics.swallowed("ios.WebViewHandler.command")
2950
3018
  return None
2951
3019
  return None
2952
3020
 
@@ -3026,13 +3094,13 @@ class ModalHandler(IOSViewHandler):
3026
3094
  try:
3027
3095
  child.setTranslatesAutoresizingMaskIntoConstraints_(True)
3028
3096
  except Exception:
3029
- pass
3097
+ diagnostics.swallowed("ios.ModalHandler.insert_child")
3030
3098
  try:
3031
3099
  content = modal["content_view"]
3032
3100
  count = len(list(content.subviews or []))
3033
3101
  content.insertSubview_atIndex_(child, max(0, min(index, count)))
3034
3102
  except Exception:
3035
- pass
3103
+ diagnostics.swallowed("ios.ModalHandler.insert_child")
3036
3104
  else:
3037
3105
  buf = state.setdefault("pending_children", [])
3038
3106
  buf.insert(max(0, min(index, len(buf))), child)
@@ -3041,7 +3109,7 @@ class ModalHandler(IOSViewHandler):
3041
3109
  try:
3042
3110
  child.removeFromSuperview()
3043
3111
  except Exception:
3044
- pass
3112
+ diagnostics.swallowed("ios.ModalHandler.remove_child")
3045
3113
  buf = _state_of(parent).get("pending_children")
3046
3114
  if buf and child in buf:
3047
3115
  buf.remove(child)
@@ -3082,7 +3150,7 @@ class ModalHandler(IOSViewHandler):
3082
3150
  content.setFrame_(((0, 0), (bounds.size.width, bounds.size.height)))
3083
3151
  content.setAutoresizingMask_(2 | 16) # FlexibleWidth | FlexibleHeight
3084
3152
  except Exception:
3085
- pass
3153
+ diagnostics.swallowed("ios.ModalHandler._present")
3086
3154
 
3087
3155
  # UIModalPresentationStyle: fullScreen=0, pageSheet=1,
3088
3156
  # formSheet=2, overCurrentContext=6 (the dimmed overlay).
@@ -3091,7 +3159,7 @@ class ModalHandler(IOSViewHandler):
3091
3159
  try:
3092
3160
  controller.setModalPresentationStyle_(style_int)
3093
3161
  except Exception:
3094
- pass
3162
+ diagnostics.swallowed("ios.ModalHandler._present")
3095
3163
  # For sheet styles, ``dismiss_on_backdrop=False`` locks
3096
3164
  # interactive (swipe / outside-tap) dismissal so the modal
3097
3165
  # stays put until ``visible`` is driven back to False.
@@ -3099,7 +3167,7 @@ class ModalHandler(IOSViewHandler):
3099
3167
  try:
3100
3168
  controller.setModalInPresentation_(True)
3101
3169
  except Exception:
3102
- pass
3170
+ diagnostics.swallowed("ios.ModalHandler._present")
3103
3171
 
3104
3172
  def _on_present_complete() -> None:
3105
3173
  _fire(placeholder, "on_show")
@@ -3115,7 +3183,7 @@ class ModalHandler(IOSViewHandler):
3115
3183
  child.setTranslatesAutoresizingMaskIntoConstraints_(True)
3116
3184
  content.addSubview_(child)
3117
3185
  except Exception:
3118
- pass
3186
+ diagnostics.swallowed("ios.ModalHandler._present")
3119
3187
 
3120
3188
  top = _top_view_controller_for_alert(UIApplication.sharedApplication)
3121
3189
  if top is not None:
@@ -3133,7 +3201,7 @@ class ModalHandler(IOSViewHandler):
3133
3201
  try:
3134
3202
  controller.dismissViewControllerAnimated_completion_(True, None)
3135
3203
  except Exception:
3136
- pass
3204
+ diagnostics.swallowed("ios.ModalHandler._dismiss")
3137
3205
  _fire(placeholder, "on_dismiss")
3138
3206
 
3139
3207
 
@@ -3270,7 +3338,7 @@ class PortalHandler(IOSViewHandler):
3270
3338
  host.addSubview_(overlay)
3271
3339
  self._sync_overlay_frame(overlay, host)
3272
3340
  except Exception:
3273
- pass
3341
+ diagnostics.swallowed("ios.PortalHandler._ensure_attached")
3274
3342
 
3275
3343
  @staticmethod
3276
3344
  def _sync_overlay_frame(overlay: Any, host: Any) -> None:
@@ -3286,7 +3354,7 @@ class PortalHandler(IOSViewHandler):
3286
3354
  overlay.setFrame_(((left, top), (w, h)))
3287
3355
  overlay.setAutoresizingMask_(2 | 16) # FlexibleWidth | FlexibleHeight
3288
3356
  except Exception:
3289
- pass
3357
+ diagnostics.swallowed("ios.PortalHandler._sync_overlay_frame")
3290
3358
 
3291
3359
  def insert_child(self, parent: Any, child: Any, index: int) -> None:
3292
3360
  self._ensure_attached(parent)
@@ -3313,7 +3381,7 @@ class PortalHandler(IOSViewHandler):
3313
3381
  try:
3314
3382
  overlay.release()
3315
3383
  except Exception:
3316
- pass
3384
+ diagnostics.swallowed("ios.PortalHandler._teardown")
3317
3385
 
3318
3386
 
3319
3387
  # ======================================================================
@@ -3347,7 +3415,7 @@ class StatusBarHandler(IOSViewHandler):
3347
3415
  mapping = {"default": 3, "light": 1, "dark": 3}
3348
3416
  app.setStatusBarStyle_animated_(mapping.get(props["bar_style"], 0), True)
3349
3417
  except Exception:
3350
- pass
3418
+ diagnostics.swallowed("ios.StatusBarHandler._apply")
3351
3419
 
3352
3420
  def set_frame(self, native_view: Any, x: float, y: float, width: float, height: float) -> None:
3353
3421
  return
@@ -3413,7 +3481,7 @@ def _ensure_keyboard_observer() -> None:
3413
3481
  None,
3414
3482
  )
3415
3483
  except Exception:
3416
- pass
3484
+ diagnostics.swallowed("ios._ensure_keyboard_observer")
3417
3485
 
3418
3486
 
3419
3487
  class KeyboardAvoidingViewHandler(IOSViewHandler):
@@ -3457,7 +3525,7 @@ def _tabbar_did_select_imp(self_ptr: int, cmd_ptr: int, tabbar_ptr: int, item_pt
3457
3525
  if 0 <= index < len(items):
3458
3526
  _fire_ptr(int(tabbar_ptr), "on_tab_select", items[index].get("name", ""))
3459
3527
  except Exception:
3460
- pass
3528
+ diagnostics.swallowed("ios._tabbar_did_select_imp")
3461
3529
 
3462
3530
 
3463
3531
  _tabbar_imp_ref = _DELEGATE_IMP_TYPE(_tabbar_did_select_imp)
@@ -3543,7 +3611,7 @@ class TabBarHandler(IOSViewHandler):
3543
3611
  try:
3544
3612
  tab_bar.setItems_animated_(bar_items, False)
3545
3613
  except Exception:
3546
- pass
3614
+ diagnostics.swallowed("ios.TabBarHandler._set_bar_items")
3547
3615
 
3548
3616
  def _resolve_icon(self, UIImage: Any, icon: Any) -> Any:
3549
3617
  """Resolve a tab icon spec to a UIImage, or return None.
@@ -3577,7 +3645,7 @@ class TabBarHandler(IOSViewHandler):
3577
3645
  if i < len(all_items):
3578
3646
  tab_bar.setSelectedItem_(all_items[i])
3579
3647
  except Exception:
3580
- pass
3648
+ diagnostics.swallowed("ios.TabBarHandler._set_active")
3581
3649
  break
3582
3650
 
3583
3651
 
@@ -3600,7 +3668,7 @@ def _top_view_controller_for_alert(app: Any) -> Any:
3600
3668
  try:
3601
3669
  window = app.keyWindow
3602
3670
  except Exception:
3603
- pass
3671
+ diagnostics.swallowed("ios._top_view_controller_for_alert")
3604
3672
 
3605
3673
  if window is None:
3606
3674
  try:
@@ -3612,7 +3680,7 @@ def _top_view_controller_for_alert(app: Any) -> Any:
3612
3680
  if window is None and windows:
3613
3681
  window = windows[0]
3614
3682
  except Exception:
3615
- pass
3683
+ diagnostics.swallowed("ios._top_view_controller_for_alert")
3616
3684
 
3617
3685
  if window is None:
3618
3686
  return None
@@ -3629,7 +3697,7 @@ def _top_view_controller_for_alert(app: Any) -> Any:
3629
3697
  if visible is not None:
3630
3698
  top = visible
3631
3699
  except Exception:
3632
- pass
3700
+ diagnostics.swallowed("ios._top_view_controller_for_alert")
3633
3701
 
3634
3702
  while top is not None:
3635
3703
  try:
@@ -3677,7 +3745,7 @@ def _present_alert(
3677
3745
  try:
3678
3746
  on_result(index)
3679
3747
  except Exception:
3680
- pass
3748
+ diagnostics.swallowed("ios._present_alert._deliver")
3681
3749
 
3682
3750
  def _present_on_main() -> None:
3683
3751
  try:
@@ -3778,7 +3846,7 @@ class PickerHandler(IOSViewHandler):
3778
3846
  try:
3779
3847
  btn.setTitle_forState_(_picker_button_title(merged), 0)
3780
3848
  except Exception:
3781
- pass
3849
+ diagnostics.swallowed("ios.PickerHandler._apply")
3782
3850
  _apply_accessibility(btn, props)
3783
3851
 
3784
3852
  def measure_intrinsic(self, native_view: Any, max_width: float, max_height: float) -> Tuple[float, float]:
@@ -3814,10 +3882,10 @@ def _checkbox_set_image(btn: Any) -> None:
3814
3882
  if tinted is not None:
3815
3883
  image = tinted
3816
3884
  except Exception:
3817
- pass
3885
+ diagnostics.swallowed("ios._checkbox_set_image")
3818
3886
  btn.setImage_forState_(image, 0)
3819
3887
  except Exception:
3820
- pass
3888
+ diagnostics.swallowed("ios._checkbox_set_image")
3821
3889
 
3822
3890
 
3823
3891
  def _checkbox_toggle(btn: Any) -> None:
@@ -3855,7 +3923,7 @@ class CheckboxHandler(IOSViewHandler):
3855
3923
  btn.setTitleColor_forState_(_uicolor("#111111"), 0)
3856
3924
  btn.setTintColor_(_uicolor("#111111"))
3857
3925
  except Exception:
3858
- pass
3926
+ diagnostics.swallowed("ios.CheckboxHandler._apply")
3859
3927
  if "value" in props:
3860
3928
  state["value"] = bool(props["value"])
3861
3929
  if "label" in props:
@@ -3863,14 +3931,14 @@ class CheckboxHandler(IOSViewHandler):
3863
3931
  try:
3864
3932
  btn.setTitle_forState_(str(label) if label is not None else "", 0)
3865
3933
  except Exception:
3866
- pass
3934
+ diagnostics.swallowed("ios.CheckboxHandler._apply")
3867
3935
  # An image-bearing custom button is not exposed to the
3868
3936
  # accessibility tree by title alone; mirror the label
3869
3937
  # explicitly (an accessibility_label prop still wins below).
3870
3938
  try:
3871
3939
  btn.setAccessibilityLabel_(str(label) if label is not None else "")
3872
3940
  except Exception:
3873
- pass
3941
+ diagnostics.swallowed("ios.CheckboxHandler._apply")
3874
3942
  if "disabled" in props:
3875
3943
  # ``disabled`` is present only when True; a removed prop
3876
3944
  # (None) re-enables the control.
@@ -3878,7 +3946,7 @@ class CheckboxHandler(IOSViewHandler):
3878
3946
  try:
3879
3947
  btn.setEnabled_(not disabled)
3880
3948
  except Exception:
3881
- pass
3949
+ diagnostics.swallowed("ios.CheckboxHandler._apply")
3882
3950
  _checkbox_set_image(btn)
3883
3951
  _apply_accessibility(btn, props)
3884
3952
 
@@ -3935,7 +4003,7 @@ class SegmentedControlHandler(IOSViewHandler):
3935
4003
  for i, title in enumerate(new_segments):
3936
4004
  control.insertSegmentWithTitle_atIndex_animated_(title, i, False)
3937
4005
  except Exception:
3938
- pass
4006
+ diagnostics.swallowed("ios.SegmentedControlHandler._apply")
3939
4007
  finally:
3940
4008
  state["suppress"] = False
3941
4009
  rebuilt = True
@@ -3948,7 +4016,7 @@ class SegmentedControlHandler(IOSViewHandler):
3948
4016
  try:
3949
4017
  control.setSelectedSegmentIndex_(int(merged.get("selected_index", 0) or 0))
3950
4018
  except Exception:
3951
- pass
4019
+ diagnostics.swallowed("ios.SegmentedControlHandler._apply")
3952
4020
  finally:
3953
4021
  state["suppress"] = False
3954
4022
  if "tint_color" in props and props["tint_color"] is not None:
@@ -3956,11 +4024,11 @@ class SegmentedControlHandler(IOSViewHandler):
3956
4024
  try:
3957
4025
  control.setSelectedSegmentTintColor_(color) # iOS 13+
3958
4026
  except Exception:
3959
- pass
4027
+ diagnostics.swallowed("ios.SegmentedControlHandler._apply")
3960
4028
  try:
3961
4029
  control.setTintColor_(color)
3962
4030
  except Exception:
3963
- pass
4031
+ diagnostics.swallowed("ios.SegmentedControlHandler._apply")
3964
4032
  if "enabled" in props:
3965
4033
  # ``enabled`` is present only when False; a removed prop
3966
4034
  # (None) re-enables the control.
@@ -3968,7 +4036,7 @@ class SegmentedControlHandler(IOSViewHandler):
3968
4036
  try:
3969
4037
  control.setEnabled_(True if enabled is None else bool(enabled))
3970
4038
  except Exception:
3971
- pass
4039
+ diagnostics.swallowed("ios.SegmentedControlHandler._apply")
3972
4040
  _apply_accessibility(control, props)
3973
4041
 
3974
4042
  def measure_intrinsic(self, native_view: Any, max_width: float, max_height: float) -> Tuple[float, float]:
@@ -4007,7 +4075,7 @@ def _date_formatter(mode: str) -> Any:
4007
4075
  NSLocale = ObjCClass("NSLocale")
4008
4076
  formatter.setLocale_(NSLocale.alloc().initWithLocaleIdentifier_("en_US_POSIX"))
4009
4077
  except Exception:
4010
- pass
4078
+ diagnostics.swallowed("ios._date_formatter")
4011
4079
  formatter.retain()
4012
4080
  _pn_date_formatters[fmt] = formatter
4013
4081
  return formatter
@@ -4024,7 +4092,7 @@ class DatePickerHandler(IOSViewHandler):
4024
4092
  try:
4025
4093
  picker.setPreferredDatePickerStyle_(2) # UIDatePickerStyleCompact
4026
4094
  except Exception:
4027
- pass
4095
+ diagnostics.swallowed("ios.DatePickerHandler._build")
4028
4096
 
4029
4097
  def _on_change() -> None:
4030
4098
  state = _state_of(picker)
@@ -4049,7 +4117,7 @@ class DatePickerHandler(IOSViewHandler):
4049
4117
  try:
4050
4118
  picker.setDatePickerMode_(mode_map.get(mode, 1))
4051
4119
  except Exception:
4052
- pass
4120
+ diagnostics.swallowed("ios.DatePickerHandler._apply")
4053
4121
  if "minimum" in props:
4054
4122
  self._set_bound(picker, "setMinimumDate_", props["minimum"], mode)
4055
4123
  if "maximum" in props:
@@ -4064,7 +4132,7 @@ class DatePickerHandler(IOSViewHandler):
4064
4132
  try:
4065
4133
  picker.setDate_animated_(date, False)
4066
4134
  except Exception:
4067
- pass
4135
+ diagnostics.swallowed("ios.DatePickerHandler._apply")
4068
4136
  finally:
4069
4137
  state["suppress"] = False
4070
4138
  if "enabled" in props:
@@ -4074,7 +4142,7 @@ class DatePickerHandler(IOSViewHandler):
4074
4142
  try:
4075
4143
  picker.setEnabled_(True if enabled is None else bool(enabled))
4076
4144
  except Exception:
4077
- pass
4145
+ diagnostics.swallowed("ios.DatePickerHandler._apply")
4078
4146
  _apply_accessibility(picker, props)
4079
4147
 
4080
4148
  def _set_bound(self, picker: Any, selector: str, value: Any, mode: str) -> None:
@@ -4085,7 +4153,7 @@ class DatePickerHandler(IOSViewHandler):
4085
4153
  date = _date_formatter(mode).dateFromString_(str(value))
4086
4154
  getattr(picker, selector)(date)
4087
4155
  except Exception:
4088
- pass
4156
+ diagnostics.swallowed("ios.DatePickerHandler._set_bound")
4089
4157
 
4090
4158
  def measure_intrinsic(self, native_view: Any, max_width: float, max_height: float) -> Tuple[float, float]:
4091
4159
  try:
@@ -4230,7 +4298,7 @@ def _table_cell_imp(self_ptr: int, cmd_ptr: int, tv_ptr: int, ip_ptr: int) -> in
4230
4298
  cell.setFrame_(((0, 0), (cell_w, row_h)))
4231
4299
  cell.contentView.setFrame_(((0, 0), (cell_w, row_h)))
4232
4300
  except Exception:
4233
- pass
4301
+ diagnostics.swallowed("ios._table_cell_imp")
4234
4302
 
4235
4303
  content = cell.contentView
4236
4304
  try:
@@ -4240,7 +4308,7 @@ def _table_cell_imp(self_ptr: int, cmd_ptr: int, tv_ptr: int, ip_ptr: int) -> in
4240
4308
  for sub in list(existing_subs or []):
4241
4309
  sub.removeFromSuperview()
4242
4310
  except Exception:
4243
- pass
4311
+ diagnostics.swallowed("ios._table_cell_imp")
4244
4312
 
4245
4313
  # Only rows in (or near) the visible content window get a
4246
4314
  # mounted subtree. UITableView's accessibility container calls
@@ -4270,7 +4338,7 @@ def _table_cell_imp(self_ptr: int, cmd_ptr: int, tv_ptr: int, ip_ptr: int) -> in
4270
4338
  try:
4271
4339
  cell.setAccessibilityElementsHidden_(not in_window)
4272
4340
  except Exception:
4273
- pass
4341
+ diagnostics.swallowed("ios._table_cell_imp")
4274
4342
 
4275
4343
  if in_window and info is not None:
4276
4344
  render_row = info.get("render_row")
@@ -4289,7 +4357,7 @@ def _table_cell_imp(self_ptr: int, cmd_ptr: int, tv_ptr: int, ip_ptr: int) -> in
4289
4357
  try:
4290
4358
  root.setFrame_(((0, 0), (cell_w, row_h)))
4291
4359
  except Exception:
4292
- pass
4360
+ diagnostics.swallowed("ios._table_cell_imp")
4293
4361
  except Exception:
4294
4362
  print(f"[VirtualList][iOS] mount for row={row} raised:")
4295
4363
  _tb.print_exc()
@@ -4314,7 +4382,7 @@ def _table_did_select_imp(self_ptr: int, cmd_ptr: int, tv_ptr: int, ip_ptr: int)
4314
4382
  _objc_msgSend.argtypes = [_ct.c_void_p, _ct.c_void_p, _ct.c_void_p, _ct.c_bool]
4315
4383
  _objc_msgSend(_ct.c_void_p(tv_ptr), _SEL_DESELECT_ROW, _ct.c_void_p(ip_ptr), True)
4316
4384
  except Exception:
4317
- pass
4385
+ diagnostics.swallowed("ios._table_did_select_imp")
4318
4386
  _fire_ptr(int(tv_ptr or 0), "on_row_press", row)
4319
4387
 
4320
4388
 
@@ -4440,7 +4508,7 @@ class VirtualListHandler(IOSViewHandler):
4440
4508
  estimate = float(props.get("row_height", 44.0) or 44.0)
4441
4509
  tv.setEstimatedRowHeight_(max(1.0, estimate))
4442
4510
  except Exception:
4443
- pass
4511
+ diagnostics.swallowed("ios.VirtualListHandler._build")
4444
4512
  tv.retain()
4445
4513
  _pn_retained_views.append(tv)
4446
4514
 
@@ -4498,12 +4566,12 @@ class VirtualListHandler(IOSViewHandler):
4498
4566
  try:
4499
4567
  tv.setShowsVerticalScrollIndicator_(visible)
4500
4568
  except Exception:
4501
- pass
4569
+ diagnostics.swallowed("ios.VirtualListHandler._apply")
4502
4570
  if data_changed and not initial:
4503
4571
  try:
4504
4572
  tv.reloadData()
4505
4573
  except Exception:
4506
- pass
4574
+ diagnostics.swallowed("ios.VirtualListHandler._apply")
4507
4575
 
4508
4576
  def _teardown(self, tv: Any) -> None:
4509
4577
  info = self._source_state(tv)
@@ -4512,7 +4580,7 @@ class VirtualListHandler(IOSViewHandler):
4512
4580
  try:
4513
4581
  info["pool"].release_all()
4514
4582
  except Exception:
4515
- pass
4583
+ diagnostics.swallowed("ios.VirtualListHandler._teardown")
4516
4584
  info["tv"] = None
4517
4585
  _pn_table_state.pop(info.get("source_ptr"), None)
4518
4586
 
@@ -4536,7 +4604,7 @@ class VirtualListHandler(IOSViewHandler):
4536
4604
  try:
4537
4605
  native_view.setContentOffset_animated_((0.0, y), animated)
4538
4606
  except Exception:
4539
- pass
4607
+ diagnostics.swallowed("ios.VirtualListHandler.command")
4540
4608
  return None
4541
4609
  if name == "scroll_to_index":
4542
4610
  index = int(args.get("index", 0) or 0)
@@ -4549,7 +4617,7 @@ class VirtualListHandler(IOSViewHandler):
4549
4617
  # 1 = UITableViewScrollPositionTop
4550
4618
  native_view.scrollToRowAtIndexPath_atScrollPosition_animated_(path, 1, animated)
4551
4619
  except Exception:
4552
- pass
4620
+ diagnostics.swallowed("ios.VirtualListHandler.command")
4553
4621
  return None
4554
4622
  if name == "scroll_to_end":
4555
4623
  animated = args.get("animated", True) is not False
@@ -4559,7 +4627,7 @@ class VirtualListHandler(IOSViewHandler):
4559
4627
  target = max(0.0, content_h - bounds_h)
4560
4628
  native_view.setContentOffset_animated_((0.0, target), animated)
4561
4629
  except Exception:
4562
- pass
4630
+ diagnostics.swallowed("ios.VirtualListHandler.command")
4563
4631
  return None
4564
4632
  if name == "get_scroll_offset":
4565
4633
  try: