Running the Apple sample code “Sharing Core Data objects between iCloud users” has presented the following challenge:
After the creation of a CKRecord in a Persistent CloudKit Container private database, the owner then shares it to a participant. All works fine.
Then the Owner wants to stop sharing. That's fine too, although the CKRecord remains within the same shared zone within the owner's private database; it doesn't move back to the private database.
Then the owner wants to delete the CKRecord completely. Deletion of the record works, but evidence of the CKShare within the shared zone still remains inside the owner's private database.
It is clearly visible on the CloudKit dashboard.
Probably doesn’t take up much memory but v messy and not cool.
How to delete this CKShare completely, leaving no trace?
Any ideas would be most gratefully received!
Explore the various UI frameworks available for building app interfaces. Discuss the use cases for different frameworks, share best practices, and get help with specific framework-related questions.
Selecting any option will automatically load the page
Post
Replies
Boosts
Views
Activity
Is it just me or does running SwiftUI apps using Xcode 16 give so many warnings and errors in the console that it's impossible to debug everything? Even the simplest gestures such as a long press generate a warning. I'm starting to ignore them, which feels negligent. Any insights/tips?
Okay so I'm getting this log every time I present a UIAlertController:
Mac Catalyst: Presenting view controller <UIAlertController: 0x10f027000> from detached view controller <MyViewController: 0x10d104080> is not supported, and may result in incorrect safe area insets and a corrupt root presentation. Make sure <MyViewController: 0x10d104080> is in the view controller hierarchy before presenting from it. Will become a hard exception in a future release.
A few points:
MyViewController is not detached and the presentation shows just fine.
I specifically check for this before presenting the alert controller like so:
BOOL okayToPresentError = (self.isViewLoaded
&& self.view.window != nil);
if (okayToPresentError)
{
[self presentErrorInAlertController:error];
}
else
{
//Wait until view did appear.
self.errorToPresentInViewDidAppear = error;
}
It spews out every time an error is fed back to my app and I present the alert controller (I can turn off the network connection and I show an alert controller with a "retry" button in it which will loop the error back so I can replay the error alert presentation over and over again) .
Every time the alert controller is presented, I get this spewing in the console. Please don't start throwing hard exceptions because the check is faulty.
I noticed if I show a sheet from a List row, then remove the row the sheet isn't removed from the screen like it is if using VStack or LazyVStack.
I'd be interested to know the reason why the sheet isn't removed from the screen in the code below. It only occurs with List/Form. VStack/LazyVStack gives the expected result. I was wondering if it is an implementation issue, e.g. since List is backed by UICollectionView maybe the cells can't be the presenter of the sheet for some reason.
Launch on iPhone 16 Pro Simulator iOS 18.2
Tap "Show Button"
Tap "Show Sheet"
What is expected:
The sheet should disappear after 5 seconds. And I don't mean it should dismiss, I just mean removed from the screen. Similarly if the View that showed the sheet was re-added and its show @State was still true, then the sheet would be added back to the screen instantly without presentation animation.
What actually happens:
Sheet remains on screen despite the row that presented the sheet being removed.
Xcode 16.2
iOS Simulator 18.2.
struct ContentView: View {
@State var showButton = false
var body: some View {
Button("\(showButton ? "Hide" : "Show" ) Button") {
showButton = true
Task {
try? await Task.sleep(for: .seconds(5))
self.showButton = false
}
}
//LazyVStack { // does not have this problem
List {
if showButton {
SheetButton()
}
}
}
}
struct SheetButton: View {
@State var sheet = false
@State var counter = 0
var body: some View {
Text(counter, format: .number)
Button("\(sheet ? "Hide" : "Show") Sheet") {
counter += 1
sheet.toggle()
}
.sheet(isPresented: $sheet) {
Text("Wait... This should auto-hide in 5 secs. Does not with List but does with LazyVStack.")
Button("Hide") {
sheet = false
}
.presentationDetents([.fraction(0.3)])
}
// .onDisappear { sheet = false } // workaround
}
}
I can work around the problem with .onDisappear { sheet = false } but I would prefer the behaviour to be consistent across the container controls.
Hi,
I have a UIViewController that contains a UITextField I am presenting that view controller inside SwiftUI using a UIViewControllerRepresentable and I am able to interact with the text field fine and the view controller lifecycle executes normally if the representable is not presented on any SwiftUI container that internally uses a scroll view on the other hand if I put the representable view inside a SwiftUI view that has a scroll view internally (when the UIKit hierarchy is generated) the text field does not respond to interaction anymore and the only view controller lifecycle method invoked is the viewDidLoad from my view controller the other methods are not executed.
Anyone knows if this is a bug on SwiftUI or if there is any additional setup necessary for UIViewControllerRepresentables?
Thanks in advance.
Hi,
We have received reports about crash when creating a UIButton:
let button = UIButton(type: .infoLight)
The exception is bad access:
Exception Type: EXC_BAD_ACCESS (SIGSEGV)
Exception Subtype: KERN_INVALID_ADDRESS at 0x0000000000000074
Exception Codes: 0x0000000000000001, 0x0000000000000074
VM Region Info: 0x74 is not in any region. Bytes before following region: 4298211212
REGION TYPE START - END [ VSIZE] PRT/MAX SHRMOD REGION DETAIL
UNUSED SPACE AT START
--->
__TEXT 100318000-100324000 [ 48K] r-x/r-x SM=COW /var/containers/Bundle/Application/E8912E1B-FFD8-49AF-A78A-7AA8805FDB95/My App/My App
Termination Reason: SIGNAL 11 Segmentation fault: 11
Terminating Process: exc handler [550]
and the main thread is crashing with the following stack trace:
Thread 0 name: Dispatch queue: com.apple.main-thread
Thread 0 Crashed:
0 UIKitCore 0x197e27a58 ____UIKitSharedArtworkManager_block_invoke + 116
1 libdispatch.dylib 0x19cfe2fa8 _dispatch_client_callout + 20
2 libdispatch.dylib 0x19cfe47f4 _dispatch_once_callout + 32
3 UIKitCore 0x197c3bb10 __UIKitSharedArtworkManager + 64
4 UIKitCore 0x197c3b5b0 _UIImageWithNameAndTraitCollection + 172
5 UIKitCore 0x197cbc180 _UIImageWithName + 44
6 UIKitCore 0x197c3be80 +[UIImage _systemImageNamed:fallback:withConfiguration:] + 132
7 UIKitCore 0x197a8c550 +[UIButton _defaultImageForType:andState:withConfiguration:] + 360
8 UIKitCore 0x197c1bc38 +[UIButton buttonWithType:] + 124
9 MapboxMaps 0x105f23fdc InfoButtonOrnament.init() + 400
10 MapboxMaps 0x105f2424c @objc InfoButtonOrnament.init() + 20
11 MapboxMaps 0x105fd8d80 MapView.setupManagers() + 1476
12 MapboxMaps 0x105fd8788 MapView.commonInit(mapInitOptions:overridingStyleURI:) + 1284
13 MapboxMaps 0x105fe2bcc specialized MapView.init(frame:mapInitOptions:) + 1500
14 MapboxMaps 0x105fd78cc MapView.init(frame:mapInitOptions:) + 20
15 mapbox_maps_flutter 0x10858c1dc MapboxMapController.init(withFrame:mapInitOptions:channelSuffix:registrar:pluginVersion:eventTypes:) + 496
16 mapbox_maps_flutter 0x10858f274 specialized MapboxMapFactory.create(withFrame:viewIdentifier:arguments:) + 2312
17 mapbox_maps_flutter 0x10858e8e8 @objc MapboxMapFactory.create(withFrame:viewIdentifier:arguments:) + 128
18 Flutter 0x10a99eb88 0x10a980000 + 125832
19 Flutter 0x10af474bc 0x10a980000 + 6059196
20 Flutter 0x10a9c3d38 0x10a980000 + 277816
21 libdispatch.dylib 0x19cfe1248 _dispatch_call_block_and_release + 32
22 libdispatch.dylib 0x19cfe2fa8 _dispatch_client_callout + 20
23 libdispatch.dylib 0x19cff1a34 _dispatch_main_queue_drain + 984
24 libdispatch.dylib 0x19cff164c _dispatch_main_queue_callback_4CF + 44
25 CoreFoundation 0x19529abcc __CFRUNLOOP_IS_SERVICING_THE_MAIN_DISPATCH_QUEUE__ + 16
26 CoreFoundation 0x1952971c0 __CFRunLoopRun + 1996
27 CoreFoundation 0x1952e9284 CFRunLoopRunSpecific + 588
28 GraphicsServices 0x1e25554c0 GSEventRunModal + 164
29 UIKitCore 0x197e32674 -[UIApplication _run] + 816
30 UIKitCore 0x197a58e88 UIApplicationMain + 340
31 My App 0x1003244e8 main + 64
32 dyld 0x1bb541de8 start + 2724
Has anyone experienced this? Could it be a bug in UIKit?
Cheers,
Roman Laitarenko
Topic:
UI Frameworks
SubTopic:
UIKit
Hi,
I have noticed a major change to a SwiftUI API behavior in iOS18.4beta1 which breaks my app's functionality, and I've started hearing from users running the new beta that the app doesn't correctly work for them anymore.
The problem is with views that contain a List with multiple-selection, and the contextMenu API applied with the ‘primaryAction’ callback that is triggered when the user taps on a row. Previously, if the user tapped on a row, this callback was triggered with the 'selectedItems' showing the tapped item. With iOS18.4beta, the same callback is triggered with ‘selectedItems’ being empty.
I have the code to demonstrate the problem:
struct ListSelectionTestView: View {
@State private var items: [TimedItem] = [
TimedItem(number: 1, timestamp: "2024-11-20 10:00"),
TimedItem(number: 2, timestamp: "2024-11-20 11:00"),
TimedItem(number: 3, timestamp: "2024-11-20 12:00")
]
@State var selectedItems = Set<TimedItem.ID>()
var body: some View {
NavigationStack {
List(selection: $selectedItems) {
ForEach(items) { item in
Text("Item \(item.number) - \(item.timestamp)")
}
}
.contextMenu(forSelectionType: TimedItem.ID.self, menu: {_ in
Button(action: {
print("button called - count = \(selectedItems.count)")
}) {
Label("Add Item", systemImage: "square.and.pencil")
}
}, primaryAction: {_ in
print("primaryAction called - count = \(selectedItems.count)")
})
}
}
}
struct TimedItem: Identifiable {
let id = UUID()
let number: Int
let timestamp: String
}
#Preview {
ListSelectionTestView()
}
Running the same code on iOS18.2, and tapping on a row will print this to the console:
primaryAction called - count = 1
Running the same code on iOS18.4 beta1, and tapping on a row will print this to the console:
primaryAction called - count = 0
So users who were previously selecting an item from the row, and then seeing expected behavior with the selected item, will now suddenly tap on a row and see nothing. My app's functionality relies on the user selecting an item from a list to see another detailed view with the selected item's contents, and it doesn't work anymore.
This is a major regression issue. Please confirm and let me know. I have filed a feedback: FB16593120
Hi everyone,
I've been testing the requestGeometryUpdate() API in iOS, and I noticed something unexpected: it allows orientation changes even when the device’s orientation lock is enabled.
Test Setup:
Use requestGeometryUpdate() in a SwiftUI sample app to toggle between portrait and landscape (code below).
Manually enable orientation lock in Control Center.
Press a button to request an orientation change in sample app.
Result: The orientation changes even when orientation lock is ON, which seems to override the expected system behavior.
Questions:
Is this intended behavior?
Is there official documentation confirming whether this is expected? I haven’t found anything in Apple’s Human Interface Guidelines (HIG) or UIKit documentation that explicitly states this.
Since this behavior affects a system-wide user setting, could using requestGeometryUpdate() in this way lead to App Store rejection?
Since Apple has historically enforced respecting user settings, I want to clarify whether this approach is compliant.
Would love any official guidance or insights from Apple engineers.
Thanks!
struct ContentView: View {
@State private var isLandscape = false // Track current orientation state
var body: some View {
VStack {
Text("Orientation Test")
.font(.title)
.padding()
Button(action: toggleOrientation) {
Text(isLandscape ? "Switch to Portrait" : "Switch to Landscape")
.bold()
.padding()
.background(Color.blue)
.foregroundColor(.white)
.cornerRadius(10)
}
}
}
private func toggleOrientation() {
guard let scene = UIApplication.shared.connectedScenes.first as? UIWindowScene else {
print("No valid window scene found")
return
}
// Toggle between portrait and landscape
let newOrientation: UIInterfaceOrientationMask = isLandscape ? .portrait : .landscapeRight
let geometryPreferences = UIWindowScene.GeometryPreferences.iOS(interfaceOrientations: newOrientation)
scene.requestGeometryUpdate(geometryPreferences) { error in
print("Failed to change orientation: \(error.localizedDescription)")
}
self.isLandscape.toggle()
}
}
I've encountered an issue where using @Observable in SwiftUI causes extra initializations and deinitializations when a reference type is included as a property inside a struct. Specifically, when I include a reference type (a simple class Empty {}) inside a struct (Test), DetailsViewModel is initialized and deinitialized twice instead of once. If I remove the reference type, the behavior is correct.
This issue does not occur when using @StateObject instead of @Observable. Additionally, I've submitted a feedback report: FB16631081.
Steps to Reproduce
Run the provided SwiftUI sample code (tested on iOS 18.2 & iOS 18.3 using Xcode 16.2).
Observe the console logs when navigating to DetailsView.
Comment out var empty = Empty() in the Test struct.
Run again and compare console logs.
Change @Observable in DetailsViewModel to @StateObject and observe that the issue no longer occurs.
Expected Behavior
The DetailsViewModel should initialize once and deinitialize once, regardless of whether Test contains a reference type.
Actual Behavior
With var empty = Empty() present, DetailsViewModel initializes and deinitializes twice. However, if the reference type is removed, or when using @StateObject, the behavior is correct (one initialization, one deinitialization).
Code Sample
import SwiftUI
enum Route {
case details
}
@MainActor
@Observable
final class NavigationManager {
var path = NavigationPath()
}
struct ContentView: View {
@State private var navigationManager = NavigationManager()
var body: some View {
NavigationStack(path: $navigationManager.path) {
HomeView()
.environment(navigationManager)
}
}
}
final class Empty { }
struct Test {
var empty = Empty() // Comment this out to make it work
}
struct HomeView: View {
private let test = Test()
@Environment(NavigationManager.self) private var navigationManager
var body: some View {
Form {
Button("Go To Details View") {
navigationManager.path.append(Route.details)
}
}
.navigationTitle("Home View")
.navigationDestination(for: Route.self) { route in
switch route {
case .details:
DetailsView()
.environment(navigationManager)
}
}
}
}
@MainActor
@Observable
final class DetailsViewModel {
var fullScreenItem: Item?
init() {
print("DetailsViewModel Init")
}
deinit {
print("DetailsViewModel Deinit")
}
}
struct Item: Identifiable {
let id = UUID()
let value: Int
}
struct DetailsView: View {
@State private var viewModel = DetailsViewModel()
@Environment(NavigationManager.self) private var navigationManager
var body: some View {
ZStack {
Color.green
Button("Show Full Screen Cover") {
viewModel.fullScreenItem = .init(value: 4)
}
}
.navigationTitle("Details View")
.fullScreenCover(item: $viewModel.fullScreenItem) { item in
NavigationStack {
FullScreenView(item: item)
.navigationTitle("Full Screen Item: \(item.value)")
.toolbar {
ToolbarItem(placement: .cancellationAction) {
Button("Cancel") {
withAnimation(completionCriteria: .logicallyComplete) {
viewModel.fullScreenItem = nil
} completion: {
var transaction = Transaction()
transaction.disablesAnimations = true
withTransaction(transaction) {
navigationManager.path.removeLast()
}
}
}
}
}
}
}
}
}
struct FullScreenView: View {
@Environment(\.dismiss) var dismiss
let item: Item
var body: some View {
ZStack {
Color.red
Text("Full Screen View \(item.value)")
.navigationTitle("Full Screen View")
}
}
}
Console Output
With var empty = Empty() in Test
DetailsViewModel Init
DetailsViewModel Init
DetailsViewModel Deinit
DetailsViewModel Deinit
Without var empty = Empty() in Test
DetailsViewModel Init
DetailsViewModel Deinit
Using @StateObject Instead of @Observable
DetailsViewModel Init
DetailsViewModel Deinit
Additional Notes
This issue occurs only when using @Observable. Switching to @StateObject prevents it. This behavior suggests a possible issue with how SwiftUI handles reference-type properties inside structs when using @Observable.
Using a struct-only approach (removing Empty class) avoids the issue, but that’s not always a practical solution.
Questions for Discussion
Is this expected behavior with @Observable?
Could this be an unintended side effect of SwiftUI’s state management?
Are there any recommended workarounds apart from switching to @StateObject?
Would love to hear if anyone else has run into this or if Apple has provided any guidance!
Hello,
We are trying to move the UIKit component which is a SwiftUI component. Since our HomeScreenViewController is subclass of UIViewController we have used UIHostingController to embed this SwiftUI view by adding the hosting view controller’s sub view to HomeScreenViewController’s view’s subview which is UIStackView and also by adding the UIHostingController as the child controller of HomeScreenViewController. This works fine on iOS 16+. But it is causing the following issues on iOS 15.
Unable to activate constraint with anchors <NSLayoutYAxisAnchor:0x2807ac740 "UIStackView:0x122b0caf0.bottom"> and <NSLayoutYAxisAnchor:0x2804ff600 "TtGC7SwiftUI14_UIHostingViewV7Loyalty15LargeBannerView:0x135930690.bottom"> because they have no common ancestor. Does the constraint or its anchors reference items in different view hierarchies? That's illegal.
It crashes with the above exception inside [UIHostingController viewWillAppear] where it is trying to set some constraints in side navigationBarHidden method. Also it is messing up the navigation bar hidden status. Could you please help us with this? But this issue will not come if we don’t add UIHostingController as child of our home screen controller and only add UIHostingController’s view as subview. Please find the attached screenshot for the stack trace.
Could you please help us with this.
Thanks
Topic:
UI Frameworks
SubTopic:
SwiftUI
Okay I know, fill a bug... but here is a super simple app that will demostrate that the navigation bar chnages from Dark scheme to light scheme when you tap back after it goes to the second view.
import SwiftUI
struct ContentView: View {
var body: some View {
NavigationStack {
NavigationLink {
Text("Tap back and notice the navigation title changes to black text instead of white")
.toolbarBackground(.visible, for: .navigationBar)
.toolbarBackground(Color.orange, for: .navigationBar)
.toolbarColorScheme(.dark, for: .navigationBar)
} label: {
VStack {
Text("First page is the sweetest")
}
.padding()
}
.navigationTitle("First Page")
.toolbarBackground(.visible, for: .navigationBar)
.toolbarBackground(Color.orange, for: .navigationBar)
.toolbarColorScheme(.dark, for: .navigationBar)
}
}
}
#Preview {
ContentView()
}
IOS 12 - 18.1.1 - objective C, Xcode 16.0
App runs on both iPhone and iPad, this issue only occurs happens on iPads. For the iPhones I am able to get a decent numeric only keyboard to display.
I pulled down NumericKeypad from GitHub and used that a model on how to implement a custom keypad.
In the inputView of the delegate, a new custom text field is create and then assigned a delegate and other properties then it returns the view to the main ViewController. When the ViewControllers and the correct text field is entered my custom keyboard display and the buttons respond but nothing is displayed in the text field. This has worked for years and all of the sudden it stopped.
The original project for the example 10 key custom keyboard builds and when loaded that works on the iPad. If I comment out condition to only execute if running on an iPad and test with an iPhone the keyboards works.
It is only on a iPad that this happens.
This is the cod that creates creates the keyboard from a .xib file. I am using a storyboard for the main app.
#import "Numeric10KeyTextField.h"
#import "Numeric10KeyViewController.h"
@implementation Numeric10KeyTextField
(UIView *)inputView {
UIView *view = nil;
Numeric10KeyViewController *numVC;
// Add hook here for iPhone or other devices if needed but now return nil if iPhone so it uses the default
// if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPad) {
numVC = [[Numeric10KeyViewController alloc] initWithNibName:@"Numeric10Key" bundle:nil];
[numVC setActionSubviews:numVC.view];
numVC.delegate = self.numeric10KeyDelegate;
numVC.numpadTextField = self;
view = numVC.view;
// }
return view;
}
@end
I am using LazyVStack inside a ScrollView. I understand that lazy views are rendered only when they come into view. However, I haven’t heard much about memory deallocation.
I observed that in iOS 18 and later, when scrolling up, the bottom-most views are deallocated from memory, whereas in iOS 17, they are not (Example 1).
Additionally, I noticed a similar behavior when switching views using a switch. When switching views by pressing a button, the view was intermittently deinitialized. (Example 2).
Example 1)
struct ContentView: View {
var body: some View {
ScrollView {
LazyVStack {
ForEach(0..<40) { index in
CellView(index: index)
}
}
}
.padding()
}
}
struct CellView: View {
let index: Int
@StateObject var viewModel = CellViewModel()
var body: some View {
Rectangle()
.fill(Color.accentColor)
.frame(width: 300, height: 300)
.overlay {
Text("\(index)")
}
.onAppear {
viewModel.index = index
}
}
}
class CellViewModel: ObservableObject {
@Published var index = 0
init() {
print("init")
}
deinit {
print("\(index) deinit")
}
}
#Preview {
ContentView()
}
Example 2
struct ContentView: View {
@State var index = 0
var body: some View {
LazyVStack {
Button(action: {
if index > 5 {
index = 0
} else {
index += 1
}
}) {
Text("plus index")
}
MidCellView(index: index)
}
.padding()
}
}
struct MidCellView: View {
let index: Int
var body: some View {
switch index {
case 1:
CellView(index: 1)
case 2:
CellView(index: 2)
case 3:
CellView(index: 3)
case 4:
CellView(index: 4)
default:
CellView(index: 0)
}
}
}
struct CellView: View {
let index: Int
@StateObject var viewModel = CellViewModel()
var body: some View {
Rectangle()
.fill(Color.accentColor)
.frame(width: 300, height: 300)
.overlay {
Text("\(index)")
}
.onAppear {
viewModel.index = index
}
}
}
class CellViewModel: ObservableObject {
@Published var index = 0
init() {
print("init")
}
deinit {
print("\(index) deinit")
}
}
--------------------
init
init
init
init
init
2 deinit
3 deinit
4 deinit
init
Topic:
UI Frameworks
SubTopic:
SwiftUI
I see SwiftUI body being repeatedly called in an infinite loop in the presence of Environment variables like horizontalSizeClass or verticalSizeClass. This happens after device is rotated from portrait to landscape and then back to portrait mode. The deinit method of TestPlayerVM is repeatedly called. Minimally reproducible sample code is pasted below.
The infinite loop is not seen if I remove size class environment references, OR, if I skip addPlayerObservers call in the TestPlayerVM initialiser.
import AVKit
import Combine
struct InfiniteLoopView: View {
@Environment(\.verticalSizeClass) var verticalSizeClass
@Environment(\.horizontalSizeClass) var horizontalSizeClass
@State private var openPlayer = false
@State var playerURL: URL = URL(fileURLWithPath: Bundle.main.path(forResource: "Test_Video", ofType: ".mov")!)
var body: some View {
PlayerView(playerURL: playerURL)
.ignoresSafeArea()
}
}
struct PlayerView: View {
@Environment(\.dismiss) var dismiss
var playerURL:URL
@State var playerVM = TestPlayerVM()
var body: some View {
VideoPlayer(player: playerVM.player)
.ignoresSafeArea()
.background {
Color.black
}
.task {
let playerItem = AVPlayerItem(url: playerURL)
playerVM.playerItem = playerItem
}
}
}
@Observable
class TestPlayerVM {
private(set) public var player: AVPlayer = AVPlayer()
var playerItem:AVPlayerItem? {
didSet {
player.replaceCurrentItem(with: playerItem)
}
}
private var cancellable = Set<AnyCancellable>()
init() {
addPlayerObservers()
}
deinit {
print("Deinit Video player manager")
removeAllObservers()
}
private func removeAllObservers() {
cancellable.removeAll()
}
private func addPlayerObservers() {
player.publisher(for: \.timeControlStatus, options: [.initial, .new])
.receive(on: DispatchQueue.main)
.sink { timeControlStatus in
print("Player time control status \(timeControlStatus)")
}
.store(in: &cancellable)
}
}
When you touch down on a button in a scroll view, you can cancel the tap by scrolling. In SwiftUI, this works correctly when the scroll view is not inside a dismissible sheet.
However, if the scroll view is inside a sheet that can be dismissed with a drag gesture, scrolling does not cancel the button touch, and after scrolling, the button tap is activated.
This happens whether the modal is presented from SwiftUI using the sheet modifier, or wrapped in a UIHostingController and presented from UIKit.
This is a huge usability issue for modals with scrollable content that have buttons inside of them.
Video of behavior: https://youtube.com/shorts/w6eqsmTrYiU
Easily reproducible with this code:
import SwiftUI
struct ContentView: View {
@State private var isPresentingSheet = false
var body: some View {
ScrollView {
LazyVStack {
ForEach(0..<100, id: \.self) { index in
Button {
isPresentingSheet = true
} label: {
Text("Button \(index)")
.padding(.horizontal)
.padding(.vertical, 5)
.frame(maxWidth: .infinity, alignment: .leading)
}
}
}
.padding()
}
.sheet(isPresented: $isPresentingSheet) {
ContentView()
}
}
}
Cell Registration
lazy var headerCell: UICollectionView.SupplementaryRegistration<UICollectionReusableView> = .init(elementKind: UICollectionView.elementKindSectionHeader) { supplementaryView, elementKind, indexPath in }
and
Cell Dequeue
datasource.supplementaryViewProvider = { [weak self] collectionView, kind, indexPath in return collectionView.dequeueConfiguredReusableSupplementary(using: headerCell, for: indexPath) }
I am registering a collectionview cell or collwctionview reusable view as lazy variable. It causes a crash like
Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Attempted to dequeue a supplementary view using a registration that was created inside -collectionView:viewForSupplementaryElementOfKind:atIndexPath: or inside a UICollectionViewDiffableDataSource supplementary view provider. Creating a new registration each time a supplementary view is requested will prevent reuse and cause created supplementary views to remain inaccessible in memory for the lifetime of the collection view. Registrations should be created up front and reused. Registration: <UICollectionViewSupplementaryRegistration: 0x600001798a00>
Issue:- The characters in SearchController SearchBar are overlapping on focusing.
Steps:-
Select the System language as Arabic
Launch the tvOS app
Set the app language as English in the tvOS app
Focus on SearchController SearchBar
Focus on any characters there you can see overlapping issue.
I used the Multipeer Connectivity Framework to allow players of my game app to see the highest score along with their own score as the game progresses. It works fine running in 3 or 4 simulators in Xcode. However, I was just told by two Apple support reps that bluetooth connectivity is not allowed between two Apple devices, other than for watches, AirPods, headphones, etc.
My question is: can two iPhones or iPads connect for peer-to-peer play? Can they play offline? If the answer is yes to either or both of those questions, how do I get that to happen since I get an error message when trying to connect two iPhones via bluetooth even though they can see each other in the Other Devices list?
If the answer is no, then why does Apple provide a Multipeer Connectivity Framework and simulate that type of device to device connection with the Xcode simulators?
Topic:
UI Frameworks
SubTopic:
SwiftUI
Is there some reason UIKit's and AppKit's animate(with:changes:completion:) methods are marked deprecated in iOS 18 when they were also first made available in iOS18? If they are indeed already deprecated, is there a replacement method we are supposed to use? This method allows the developer to use SwiftUI animations to animate UIKit and AppKit views.
I am making a SwiftUI Mac app that uses navigation split view and the Observation framework. The split view has a sidebar list, a detail view, and a selection property to store the selected item in the list. I set the initial selection to the first item in the list using the .onAppear modifier.
When I select an item from the list, I get the desired behavior. The detail view shows the contents of the selected item. But the selection property’s value changes to nil. Because selection is nil, I am unable to remove items from the list.
Model Code
struct Wiki {
var pages: [Page] = []
}
@Observable
class Page: Identifiable, Equatable, Hashable {
let id = UUID()
var title: String = "Page"
var text: String
static func == (lhs: Page, rhs: Page) -> Bool {
lhs.id == rhs.id
}
func hash(into hasher: inout Hasher) {
hasher.combine(id)
hasher.combine(title)
hasher.combine(text)
}
}
Split View Code
struct ContentView: View {
@Binding var wiki: Wiki
@State private var selection: Page? = nil
var body: some View {
NavigationSplitView {
PageList(wiki: $wiki, selection: $selection)
.navigationSplitViewColumnWidth(ideal: 192)
} detail: {
if let selection {
PageView(page: selection)
} else {
Text("Select a page to view its contents.")
}
}
.onAppear {
selection = wiki.pages.first
}
}
}
List Code
struct PageList: View {
@Binding var wiki: Wiki
@Binding var selection: Page?
var body: some View {
VStack {
Text("Pages")
.font(.title)
List($wiki.pages, selection: $selection) { $page in
NavigationLink {
PageView(page: page)
} label: {
TextField("", text: $page.title)
}
}
.padding()
}
}
}
Detail View Code
struct PageView: View {
@Bindable var page: Page
var body: some View {
TextEditor(text: $page.text)
}
}
I tried changing selection in the list view from @Binding to @Bindable, but I get the following build error:
'init(wrappedValue:)' is unavailable: The wrapped value must be an object that conforms to Observable
What fix do I have to make to get the selection property to not be nil when I select an item from the list?
Topic:
UI Frameworks
SubTopic:
SwiftUI