I'm not sure where to report this, so here it is.
If you have a list of items and you make them clickable and movable, moving one or more items in the list and then clicking will cause them to move. This is yet another reason that SwiftData needs to track onMove.
Minimal reproducible code:
//
// ContentView.swift
// exampleBug
//
// Create a new project.
// Replace the default Item class with the one below, and replace ContentView with its class below
// Run the app and add a few items a few seconds apart so you can tell them apart.
// Drag an item to a new position in the list.
// Click one of the checkboxes and watch the list positions change for no reason!
//
import SwiftUI
import SwiftData
@Model
final class Item {
var timestamp: Date
var checkbox: Bool = false
init(timestamp: Date) {
self.timestamp = timestamp
}
}
struct ContentView: View {
@Environment(\.modelContext) private var modelContext
@State private var editMode = EditMode.inactive
@Query private var items: [Item]
var body: some View {
NavigationStack {
List {
ForEach(items) { item in
HStack {
Text(item.timestamp, format: Date.FormatStyle(date: .numeric, time: .standard))
Button("", systemImage: item.checkbox ? "checkmark.circle.fill" : "circle") {
item.checkbox.toggle()
try? modelContext.save()
}
}
}
.onMove(perform: { indices, newOffset in
var theItems = items
theItems.move(fromOffsets: indices, toOffset: newOffset)
})
}
.environment(\.editMode, $editMode)
.moveDisabled(false)
.toolbar {
ToolbarItem(placement: .navigationBarTrailing) {
EditButton()
}
ToolbarItem {
Button(action: addItem) {
Label("Add Item", systemImage: "plus")
}
}
}
}
}
func addItem() {
withAnimation {
let newItem = Item(timestamp: Date())
modelContext.insert(newItem)
}
}
func deleteItems(offsets: IndexSet) {
withAnimation {
for index in offsets {
modelContext.delete(items[index])
}
}
}
}
#Preview {
ContentView()
.modelContainer(for: Item.self, inMemory: true)
}
code-block
Post
Replies
Boosts
Views
Activity
`
init() {
nextOrder = self.AllItems.map{$0.order}.max()
if nextOrder == nil {
nextOrder = 0
}
nextOrder! += 1 // <--- Thread 1: Fatal error: Unexpectedly found nil while unwrapping an Optional value
}
`
I have to say, Swift is great - when it works!
I see this error in the debugger:
#FactoryInstall Unable to query results, error: 5
IPCAUClient.cpp:129 IPCAUClient: bundle display name is nil
Error in destroying pipe Error Domain=NSCocoaErrorDomain Code=4099 "The connection from pid 5476 on anonymousListener or serviceListener was invalidated from this process." UserInfo={NSDebugDescription=The connection from pid 5476 on anonymousListener or serviceListener was invalidated from this process.}
on this function:
func speakItem() {
let utterance = AVSpeechUtterance(string: item.toString())
utterance.voice = AVSpeechSynthesisVoice(language: "en-GB")
try? AVAudioSession.sharedInstance().setCategory(.playback)
utterance.rate = 0.3
let synthesizer = AVSpeechSynthesizer()
synthesizer.speak(utterance)
}
When running without the debugger, it will (usually) speak once, then it won't speak unless I tap the button that calls this function many times.
I know AVSpeech has problems that Apple is long aware of, but I'm wondering if anyone has a work around. I was thinking there might be a way to call the destructor for AVSpeechUtterance and generate a new object each time speech is needed, but utterance.deinit() shows: "Deinitializers cannot be accessed"
I'd like to use ScrollViewReader, but on a list of static text that has formatting such as font colors and bold text. Essentially, my list has a bunch of:
Text("some text ") + Text(" and more text").fontWeight(.bold).foregroundStyle(boldColor)
Switching to AttributedString would be a pain, and I'm not so sure ScrollViewReader is working correctly. It seems like there are a lot of bugs reports about it. Plus, do we really need a separate string format, just to have proper formatting? Really?
Is there another version I'm missing? One that can scroll to anchor points that I could set?
The build status has a green check in Xcode Cloud, but TestFlight see no builds and suggest that I submit one. Then it provides a link to an incredibly unhelpful list of upload tools, at least one of which suggests creating a developer account!!!
The code below works, in that it successfully creates an item and attached it to the parent item, but the parent view doesn't show the new child until you navigate away from the parent and then back to it.
Parent:
Child1
Child2
// Add Child 3 and this does not refresh when returning through the dismiss() call, but if I navigate to the grand Parent, and then back to the Parent, Child 3 is there. Any ideas?
NavigationStack {
Form {
LabeledContent {
TextField("Item", text: $name)
} label: {
Text("Item:")
}
}
.navigationTitle("Add New Item")
.toolbar {
Button("Save") {
var tmp = Item(timestamp: Date(), name: name, parent: itemParent)
if(itemParent != nil) {
itemParent!.children.append(tmp)
}
context.insert(tmp)
try? context.save()
dismiss()
}
}
}
If I add items at the root level, this code works, but if I attempt to add a child to any item, it runs an infinite loop where it goes from the AddItemView back to the SubItemView and starts all over. I suspect it has something to do with the Predicate in SubItemView, but the debugger is crap, so I'm just guessing.
Minimal code:
@Model
final class Item {
var id: String
var name: String
var children: [Item] = []
@Relationship(deleteRule: .cascade) var parent: Item?
init(name: String, parent: Item?, id: String = UUID().uuidString) {
self.name = name
self.parent = parent
self.id = id
}
}
struct ContentView: View {
@Environment(\.modelContext) private var modelContext
@Query(
filter: #Predicate<Item> {
item in
item.parent == nil
}, sort: \Item.name
) public var rootItems: [Item]
var body: some View {
NavigationStack {
List {
ForEach(rootItems) { item in
HStack {
NavigationLink ( destination: SubItemView(parent: item)) {
Text(item.name) }
}
}
}
.toolbar {
ToolbarItem(placement: .navigationBarTrailing) {
EditButton()
}
ToolbarItem {
NavigationLink(destination: AddItemView(itemParent: nil)) {
Text("Add To Do")
}
}
}
}
}
}
struct SubItemView: View {
@Environment(\.dismiss) private var dismiss
@Environment(\.modelContext) private var modelContext
@State var parent: Item
@State private var todo: String = ""
@State var selectedDate = Date()
@State var showPicker: Bool = false
@Query var children: [Item]
init(parent: Item) {
self.parent = parent
let parentID = parent.id
_children = Query(filter: #Predicate<Item> {
$0.parent.flatMap(\.id) == parentID && $0.parent.flatMap(\.id) != nil
}, sort: \Item.name )
}
var body: some View {
Form {
LabeledContent {
TextField("Name", text: $parent.name)
} label: {
Text("Name:")
}
}
Text("Parent: \(parent.name)\n")
NavigationStack {
Text("Child count: \(children.count)")
List(children) { child in
HStack {
if(child.children.isEmpty) {
Text(child.name)
NavigationLink ( destination: SubItemView(parent: child)) {
Text("").foregroundColor(.white).background(Color.blue)
}
.opacity(0)
.background(
Text("")
)
} else {
Text(child.name)
NavigationLink(destination: SubItemView(parent: child)) {
Text("")
}
}
}
}
}
.navigationTitle("Sub Items")
.toolbar {
ToolbarItem(placement: .navigationBarTrailing) {
EditButton()
}
ToolbarItem {
NavigationLink(destination: AddItemView(itemParent: parent)) {
Text("Add To Do")
}
}
ToolbarItem {
Button("Save") {
try? modelContext.save()
dismiss()
}
}
}
}
}
struct AddItemView: View {
@Environment(\.dismiss) private var dismiss
@Environment(\.modelContext) private var context
@State var itemParent: Item?
@State private var name = ""
@State private var showWarning: Bool = false
@State var child = Item(name: "", parent: nil)
var body: some View {
NavigationStack {
Form {
LabeledContent {
TextField("Item", text: $name)
} label: {
Text("Todo:")
}
}
.navigationTitle("Add New Item")
.toolbar {
Button("Save") {
let tmp = Item(name: name, parent: itemParent)
if(itemParent != nil) {
itemParent!.children.append(tmp)
}
context.insert(tmp)
try? context.save()
dismiss()
}
}
}
}
}
Xcode is crashing various extensions on my system, most often the Accessibility extension. It's a pain because it pops up a window - usually while I'm doing something else - that takes up most of the screen and the focus.
Am I the only one this is happening to?
I have a build, but Distribution won't add it because it doesn't see encryption info in the Info.plist file, but that's hidden in Xcode. How do I find/update it?
I’ve noticed a good number of strange problems in the IOS development process, so I’m going to track them here. If they’re resolved at some point, I’ll note it.
At least in my first attempt, letting Appleconnect build my code resulted in a build with no errors that could not be submitted for review. The solution for me was to build from Xcode. It took a while to stumble on that, so if you have problems with one way, try the other.
Xcode doesn’t show Info.plist by default. This is a particularly nasty bug that caused a great deal of trouble, being the biggest reason I had so much trouble getting my first app submitted for review. The only way I found to get around it was to make a small change to one of the items under the Info tab under the project name/icon in Xcode. Then, the Info.plist showed up!
SwiftUI and SwiftData are siloed off from each other, so if you have a list, the view is controlled by SwiftUI. This means that if a user moves an item in a list, SwiftData is not informed. If the user quits the app, the order will revert to the last saved version! So you must resort to tracking the order in your code and adjusting your query accordingly.
Apple is pushing to use AdAttributionKit, but when I look at various ad networks, their sample code isn't using it. I'd like to find a simple example using a banner add and a third party ad network like admob.
Also, I'm not clear on what post backs really do, or if I need them at all. If anyone can point me to clear documentation that is up to date, that would be great!
I'm adding Admob ads to my app, and Admob needs to know the width of the view, so I'm using GeometryReader for that. To prevent GeometryReader from grabbing screen space, I've wrapped the main view in GeometryReader { }. I then use geometry.size.width in my call to the adView.
This all works fine. I have two main screens where I show ads, and they both work, until I rotate the device. Then the app crashes!
If I comment out the GeometryReader code and pass a fixed value to the ad view, I can rotate the device with no fear of a crash.
My question is: Do I have to accept that GeometryReader will crash the app when it's rotated, or is there another, stable way to get view dimensions?