On iOS 13 I used to use optional @State properties to adapt views. In my case, the presented view would either create a new object (an assignment) if the state that is passed into it is nil, or edit the assignment if an assignment was passed in. This would be done in the action block of a Button and it worked beautifully.
On iOS 14 / Xcode 12 this no longer seems to work. Given the following code which creates a new assignment and passes it into the editor view when the user taps a "New Assignment" button, the value of assignment remains nil. Is anyone else experiencing similar behaviour?
struct ContentView: View {
		@Environment(\.managedObjectContext) var context
		@State var assignmentEditorIsPresented = false
		@State var assignment: Assignment? = nil
		var Body: some View {
				[...]
				Button("New Assignment", action: {
						self.assignment = Assignment(context: context)
						self.assignmentEditorIsPresented = true
				})
				.sheet(isPresented: assignmentEditorIsPresented) {
						[...]
				}
		}
}
What's even weirder is that I tried adding a random piece of state, an Int, to this view and modifying it right before the assignment state (between lines 9 and 10) and it didn't change either.
Post
Replies
Boosts
Views
Activity
I have a configurable widget that can be configured as automatically selecting which user data to display, or allowing the user to choose which data they want to see. In the edit widget menu, this shows up as "Automatic" and then the list of data to display. I'd like for the automatic option to be selected by default when the user adds the widget for the first time. My timeline provider behaves this way but it doesn't show up like that on the edit widget page. It simply says "Choose."
Has anyone figured out a way to select a default configuration for a widget when it is first added to the Home Screen?
See the following excerpt of a crash log from a release build of my app:
Hardware Model:			iPhone11,8
Process:						 Pupl [45462]
Path:								/private/var/containers/Bundle/Application/3D8B69C4-8AE5-40E7-BBDF-93CC12D79E1C/Pupl.app/Pupl
Identifier:					com.kevinolmats.Pupl
Version:						 285 (1.0.1)
AppStoreTools:			 12A7402a
AppVariant:					1:iPhone11,8:14
Code Type:					 ARM-64 (Native)
Role:								Foreground
Parent Process:			launchd [1]
Coalition:					 com.kevinolmats.Pupl [2248]
Date/Time:					 2020-10-25 13:38:09.3546 -0700
Launch Time:				 2020-10-25 13:33:01.8074 -0700
OS Version:					iPhone OS 14.0.1 (18A393)
Release Type:				User
Baseband Version:		3.00.01
Report Version:			104
Exception Type:	EXC_CRASH (SIGABRT)
Exception Codes: 0x0000000000000000, 0x0000000000000000
Exception Note:	EXC_CORPSE_NOTIFY
Triggered by Thread:	0
Application Specific Information:
abort() called
Last Exception Backtrace:
0	 CoreFoundation								 0x1884d65ac 0x1883b5000 + 1185196
1	 libobjc.A.dylib							 0x19c55042c 0x19c546000 + 42028
2	 CoreData											 0x18e58a648 0x18e460000 + 1222216
3	 CoreData											 0x18e58f6f4 0x18e460000 + 1242868
4	 Pupl													 0x100a56cac specialized WeightCategoryEditorViewModel.init(course:color:context:) + 339116 (WeightCategoryEditorViewModel.swift:30)
5	 Pupl													 0x100a4d7a0 closure #1 in closure #1 in closure #1 in CourseEditorWeightCategoryView.body.getter + 300960 (CourseEditorViewModel.swift:0)
6	 SwiftUI											 0x18ee430b0 0x18e864000 + 6156464
7	 SwiftUI											 0x18ed4b9c4 0x18e864000 + 5142980
8	 SwiftUI											 0x18edd0e90 0x18e864000 + 5688976
9	 SwiftUI											 0x18ee6b3f8 0x18e864000 + 6321144
10	SwiftUI											 0x18ee6b6e4 0x18e864000 + 6321892
11	UIKitCore										 0x18aff60d0 0x18a273000 + 14168272
12	UIKitCore										 0x18aff5c8c 0x18a273000 + 14167180
13	UIKitCore										 0x18aff6438 0x18a273000 + 14169144
14	UIKitCore										 0x18b2bb544 0x18a273000 + 17073476
15	UIKitCore										 0x18ae00400 0x18a273000 + 12112896
16	UIKitCore										 0x18adef1bc 0x18a273000 + 12042684
17	UIKitCore										 0x18ae22648 0x18a273000 + 12252744
18	CoreFoundation								 0x188452444 0x1883b5000 + 644164
19	CoreFoundation								 0x18844c858 0x1883b5000 + 620632
20	CoreFoundation								 0x18844ce08 0x1883b5000 + 622088
21	CoreFoundation								 0x18844c4bc 0x1883b5000 + 619708
22	GraphicsServices							 0x19eed1820 0x19eece000 + 14368
23	UIKitCore										 0x18adf0734 0x18a273000 + 12048180
24	UIKitCore										 0x18adf5e10 0x18a273000 + 12070416
25	SwiftUI											 0x18f1ad32c 0x18e864000 + 9737004
26	SwiftUI											 0x18f1ad2b8 0x18e864000 + 9736888
27	SwiftUI											 0x18ed26b08 0x18e864000 + 4991752
28	Pupl													 0x100a1311c main + 61724 (Assignment.swift:0)
29	libdyld.dylib								 0x188113e60 0x188113000 + 3680
The problem is, after I symbolicate in Xcode using the Devices window, it only symbolicates calls from my app (Pupl), not any of the system frameworks. Any ideas as to how I can fix this?
A couple of users have been getting these odd crashes that I can't reproduce on my end. This happens the first time they try to create anything in my app, then never again. But it happens once for each type of entity. Here's an excerpt of the crash log: Crash Log - https://developer.apple.com/forums/content/attachment/ec27017d-0ec0-428b-97da-2abf17a567a1
Frame 5 of the last exception backtrace is the user pushing the save button, which takes a generic view model that conforms to the EditorViewModel protocol, like so:
struct AddSaveNavigationBarItem<T: EditorViewModel>: View {
@ObservedObject var viewModel: T
@Binding var presentationMode: PresentationMode
var body: some View {
Button(saveAddButtonTitle) {
if let assignmentEditorViewModel = viewModel as? AssignmentEditorViewModel {
guard !assignmentEditorViewModel.shouldWarnDenominator() else {
return
}
guard !assignmentEditorViewModel.shouldWarnDisableGrades() else {
return
}
}
viewModel.save()
presentationMode.dismiss()
}
.disabled(viewModel.name.isEmpty)
}
}
The next frame is the save method on the view model which saves the changes made to the assignment entity in Core Data:
func save() {
assignment.name = name
assignment.course = course
assignment.isTest = isTest
assignment.isDueOnDate = isDueOnDate
assignment.isDueAtTime = isDueAtTime
if !isDueAtTime && isDueOnDate {
assignment.dueDate = Calendar.current.date(bySettingHour: 23, minute: 59, second: 59, of: dueDate)
} else {
assignment.dueDate = dueDate
}
assignment.notes = notes
if willRecieveGrade {
assignment.gradeNumerator = Double(gradeNumerator) ?? Assignment.defaultNumerator
assignment.gradeDenominator = Double(gradeDenominator) ?? Assignment.defaultDenominator
if !isUsingCustomWeight && weightCategory != nil {
assignment.weight = Assignment.defaultWeight
assignment.weightCategory = weightCategory!
} else {
assignment.weight = Double(weight) ?? Assignment.defaultWeight
assignment.weightCategory = nil
}
} else {
assignment.gradeNumerator = Assignment.defaultNumerator
assignment.gradeDenominator = Assignment.defaultDenominator
assignment.weight = Assignment.defaultWeight
assignment.weightCategory = nil
}
assignment.willRecieveGrade = willRecieveGrade
do {
try context.save()
AssignmentEditorViewModel.logger.info("Saved changes to assignment \(self.assignment.id, privacy: .public)")
} catch {
AssignmentEditorViewModel.logger.error("Failed to save context: \(error.localizedDescription, privacy: .public)")
}
for subtask in assignment.subtasks {
subtask.objectWillChange.send()
}
assignment.objectWillChange.send()
}
I'm a pretty new developer, and this app is a pet project of mine so I'm really struggling to figure out what the issue could be, especially since I can't reproduce it on my end. Any suggestions would be much appreciated!
I’ve been trying to figure out a way to copy adjustments made in the native Photos app on macOS to a different photo using PhotoKit or Swift.
My DSLR sends lower quality versions of every photo it takes right to my phone as it takes them, but when I get around to importing the high res copies from the SD card, I’d like to be able to easily copy the favourited status and any edits I may have made to the high res versions.
Copying the isFavourite status and removing the duplicate files was easy, but I can’t figure out a way to copy edits over to the higher quality file. I figured since it’s an easy copy/paste in Photos that it shouldn’t be too difficult with code.
Has anyone managed to pull this off?
I'm working on an app that uses HomeKit-enabled accessories such as wall plugs to control a photographic enlarger in a darkroom. This requires precise timing when toggling the power state of the plug. For example, the timer in my app might be set to 5 seconds, so I turn on the plug using writeValue() on the plugs power state characteristic, wait 5 seconds, then turn it off again.
I want to be able to measure if the plug actually responded to the command and if there was any delay in the plug actually turning on/off so I can display a warning to the user if network latency resulted in the plug being on for longer than the set time.
Does writeValue() (in my case, the async/await version) only return when the plug has been turned on, or does it return as soon as the command has been sent, regardless of if it has been received/acted on? Is there a way I can (a) quickly verify that the plug has been turned on/off, and (b) measure how long it took for the plug to act on the request, that is, the time elapsed between when writeValue() is called and when the plug actually updates to the corresponding value?
I'm experiencing a new error in SwiftData since updating to Xcode 16/iOS 17 DB1. When passing in a model (Student) to a view and then displaying an array of Points using ForEach, I get the following fatal error:
SwiftData/ModelCoders.swift:2438: Fatal error: Failed to locate relationship for StringCodingKey(stringValue: "group", intValue: nil) on Entity - name: Point
superentity:
subentities:
storedProperties:
CompositeAttribute - name: type, options: [], valueType: PointType, defaultValue: nil
Properties:
Attribute - name: type, options: [], valueType: String, defaultValue: nil, hashModifier: nil
Relationship - name: outcome, options: [], valueType: Outcome, destination: Outcome, inverseName: nil, inverseKeypath: nil
CompositeAttribute - name: proficiency, options: [], valueType: Proficiency, defaultValue: nil
Properties:
Attribute - name: proficiency, options: [], valueType: String, defaultValue: nil, hashModifier: nil
Attribute - name: date, options: [], valueType: Date, defaultValue: nil, hashModifier: nil
Attribute - name: note, options: [], valueType: String, defaultValue: nil, hashModifier: nil
Relationship - name: student, options: [], valueType: Optional<Student>, destination: Student, inverseName: points, inverseKeypath: Optional(\Student.points)
Attribute - name: group, options: [], valueType: Array<PersistentIdentifier>, defaultValue: [], hashModifier: nil
inheritedProperties:
uniquenessConstraints:
indices:
Xcode flags this line of the macro-generated getter of the outcome property on Point:
@storageRestrictions(accesses: _$backingData, initializes: _outcome)
init(initialValue) {
_$backingData.setValue(forKey: \.outcome, to: initialValue)
_outcome = _SwiftDataNoType()
}
get {
_$observationRegistrar.access(self, keyPath: \.outcome)
return self.getValue(forKey: \.outcome) // Fatal error: Failed to locate relationship for StringCodingKey...
}
set {
_$observationRegistrar.withMutation(of: self, keyPath: \.outcome) {
self.setValue(forKey: \.outcome, to: newValue)
}
}
This worked just fine in iOS 17. Here's a snippet of the Student implementation:
@Model
class Student: Identifiable, Comparable {
var name: String
var number: Int
@Relationship(deleteRule: .cascade, inverse: \Point.student) var points: [Point]
@Relationship(deleteRule: .cascade, inverse: \Mark.student) var marks: [Mark]
@Relationship(deleteRule: .nullify, inverse: \StudentGroup.students) var groups: [StudentGroup] = []
var archived: Bool
}
and the implementation of Point:
@Model
class Point: Identifiable, Comparable {
var student: Student?
var type: PointType
var outcome: Outcome
var proficiency: Proficiency
var group: [Student.ID] = []
var date: Date
var note: String
}
and finally the implementation for Outcome:
@Model
class Outcome: Identifiable, Comparable {
var name: String
var index: Int
var rubric: Rubric?
var proficiencies: [Proficiency]
}
I've tried adding a relationship in Outcome as an inverse of the outcomes property on Points (although this does not make sense in my implementation, which is why I initially did not set a relationship here) and the problem persisted.
Any ideas what this error means and how I might go about fixing it?
I wanted to be able to install both an App Store/Release version and a development version of my app on the same device and have them access different persistent stores, so I changed the bundle identifier of my app for the debug build configuration to "com.kevinolmats.Guru.debug", while the release configuration stayed as "com.kevinolmats.Guru". Since then, Xcode previews have completely stopped working. After a long build time, the canvas displays Cannot show preview: check whether the preview is compiled for the current scheme and OS of the device used for previewing.
The only things I have changed are:
the bundle identifier for the debug configuration
the product and bundle names (debug config is now Guru (debug))
added a new entitlements file for the debug configuration
Any ideas as to why my previews have stopped working? Enable previews is set to on, and the usual troubleshooting steps (restarting Xcode, my computer, deleting DerivedData) have not helped. The app runs perfectly fine otherwise--it's just previews that are broken.