Post

Replies

Boosts

Views

Activity

CloudKit Synchronized "User Defaults"
I have a CoreData-based application, set up with a private CloudKit container and using NSPersistentCloudKitContainer. However, I need additional CloudKit-synchronized data that lives in this container, but not as part of a CoreData scheme. (I.e., I need to read/write some data to the CloudKit container BEFORE initializing the NSPersistentCloudKitContainer. (1) Is this possible? [I'm assuming that the answer is YES.] (2) Since I'm a complete neophyte with CloudKit, can you give me some guidance as to how to set this all up? One way to think about what I want to do is to create a cloud-synchronized UserDefaults that provides consistent default data to all of a user's devices.
0
0
901
Jun ’21
Help with iOS 15 UIButton?
I am trying to construct a button using the new iOS15 button API. (Xcode 13ß3, UIKit & Storyboards) The button has a title (aligned .leading) and an image (aligned .trailing). The button has the following layout constraints: a fixed leading constraint (to a label that provides prompt text) a center-vertically constraint (to that same label) a trailing constraint ( >= a margin value) What I’m trying to accomplish is that the button should adjust its width based on the title content, not wrapping until the width causes the trailing constraint to be violated. What actually happens is the the button’s text wraps. It acts as if it prefers wrapping to changing its size. There are mentions in the documentation about disabling text wrapping for the button, but the obvious things, such as button.titleLabel?.lineBreakMode = .byTruncatingMiddle don’t work. Has anyone whose tried working with iOS 15 buttons have any suggestions?
0
0
2.2k
Jul ’21
Async/await and modal dialogs
In a UIKit context, has anyone had experience/success in using async/await to synchronize a modal dialog with other logic? I've tried it a bit without success. I.e, given a presented dialog, I want to capture data in the dialog, then use the results in a simple, linear fashion. (Something that looks like "Present the dialog, wait for results, use results" -- all inline without closures.) It seems to me that async/await with @MainActor ought to make that possible, but I haven't yet figured out how. I'd really like to see a real-world example.  Can you help?
0
0
984
Sep ’21
UICollectionView with DiffableDataSource
Xcode 13.1, iOS 25 SDK I have a UICollectionView (with a custom UICollectionViewLayout) which I am updating with a DiffableDataSource. This CollectionView displays a particular data object (with a given number of sections and items). The user can choose to display a different object (with a different number of sections and items), reusing this CollectionView. When this occurs, I do the following: (pass the new data object to the custom layout) let layout = collectionView.collectionViewLayout layout.invalidateLayout() collectionView.contentSize = layout.collectionViewContentSize (calculate a new snapshot and apply it) When the new data object has FEWER sections and/or items as the first, I get a series of warning messages (one for each of the cells that are no longer in the collection view) as follows: 2021-12-07 14:29:02.239301-0600 WineCorner[82916:1921357] [CollectionView] Layout attributes <UICollectionViewLayoutAttributes: 0x7f77b3047e00> index path: (<NSIndexPath: 0xa0f0b1eb018e754a> {length = 2, path = 0 - 4}); frame = (578.118 6; 160 160); transform = [0.70710678118654757, -0.70710678118654746, 0.70710678118654746, 0.70710678118654757, 0, 0]; zIndex = 1; were received from the layout <WineCorner.WineRackLayout: 0x7f77b1f1a0c0> but are not valid for the data source counts. Attributes will be ignored. Obviously, I am not handling the situation correctly. What should I do so that these warning messages are not issued?
0
0
1.1k
Dec ’21
WidgetKit — how to send data from Widget to main app
Back in the days of NCWidgetProviding, we had a button to open our app. We included code like the following in the app's info.plist: <key>CFBundleURLTypes</key> <array> <dict> <key>CFBundleTypeRole</key> <string>Editor</string> <key>CFBundleURLName</key> <string>com.xxxx.yyyy/string> <key>CFBundleURLSchemes</key> <array> <string>yyyy</string> </array> </dict> </array> and in the widget's button, we used code like: let appURL = URL(string: "yyyy://?url=\(zzz)") extensionContext?.open(appURL, completionHandler: nil) How can I achieve the same result using WidgetKit? (I.e., sending a URI to my main app)? The use case is that the widget displays a random record from a database and when the user taps on the widget, I want to open my app, displaying THAT SAME RECORD. Thanks.
2
0
2.6k
Sep ’22
CoreData Migration for CloudKit
I am upgrading an existing (CoreData-based) iOS app to support CloudKit synchronization. This doesn't work because the app includes an ORDERED relationship. I need to perform a migration from this ordered relationship to something else that supports both CloudKit and maintains ordering. The problem is less about WHAT I need to do to support my requirements as it is HOW to perform the migration (so that my existing customers don't lose data.) Have you encountered this problem? How did you solve it?
0
0
679
Mar ’23
SwiftData - What is Best Practice for returning an object from a sheet
SwiftUI & SwiftData. I have a view that lists SwiftData objects. Tapping on a list item navigates to a detail view. The list view also has a "New Object" button. Tapping it opens a sheet used to create a new object. There are, obviously, two possible outcomes from interacting with the sheet — a new object could be created or the user could cancel without creating a new object. If the user creates a new object using the sheet, I want to open the detail view for that object. My thought was to do this in the onDismiss handler for the sheet. However, that handler takes no arguments. What is best practice for handling this situation? In UIKit, I would return a Result<Object, Error> in a closure. That won't work here. What is the "correct" way to handle this that is compatible with SwiftData and the Observation framework?
2
0
1.9k
Aug ’23
Create AVPlayer instance from Data (rather than URL)?
In my SwiftUI/SwiftData application, I want to store videos in SwiftData objects (using external storage). To display them, I need to instantiate an AVPlayer (for use in a VideoPlayer view). But AVPlayer expects a URL, not a Data object. Obviously, I can solve this problem via a file-caching scheme (i.e., by creating a local file when needed, using an LRU cache to control it's lifetime), but this results in an extra copy of the data (besides the hidden local file managed by SwiftData/CoreData). However, since videos can be quite large, I would prefer not to do that. Has anyone any thoughts about how I can avoid the extra data copy?
2
0
2.2k
Dec ’23
TextFields inside a List lose focus after each character
My problem: I tap in one of the TextFields defined below and try to type. After typing a single character, the cursor disappears from the TextField and I need to tap in the field again to enter the next character. I have the following code: @Observable final class Species { . . . public var list: [String] . . . } struct SpeciesCapture: View { @State private var species = Species() @State var trainingList: [String] = [] var body: some View { NavigationStack { VStack(alignment: .leading) { HStack { Text("some text") Spacer() Button("Add") { trainingList.append("") } } List { ForEach($trainingList, id: \.self) { $animal in TextField("Animal", text: $animal) .textCase(.lowercase) } } } .onAppear { trainingList = species.list . . . } . . . // etc. } } } It appears that I am continually losing focus. How do I fix this problem? Xcode 16.0 targeting iOS 18. The behavior appears in both Preview and the Simulator. (Haven't tried it on a physical device).
1
0
278
Sep ’24
Focus fails when TextField includes axis: .vertical
I've found another interesting issue with the Focus system. My text case is SwiftUI in Preview or Simulator (using an iPad mini case) -- I haven't tried this on other environments, so your mileage may vary. I have a Form including several TextFields. Adding the usual @FocusState logic, I observe that if I type a TAB key, then (a) If the TextFields are specified using TextField(“label”, text: $text), typing the tab key switches focus from field to field as expected, BUT (b) If the TextFields are specified using TextField(“label”, text: $text, axis: .vertical), typing the tab key adds whitespace to the field and does NOT change focus. In the latter case, I need to use an .onKeyPress(.tab) {….} modifier to achieve the desired result. Reported as FB15432840
0
0
581
Oct ’24
$FocusState and Lists with rows containing TextFields
While I've seen examples of using $FocusState with Lists containing "raw" TextFields, in my use case, the List rows are more complex than that and contain multiiple elements, including TextFields. I obviously don't understand something fundamental here, because I am completely unable to get TextField-to-TextField tabbing to work. Can someone set me straight? Sample code demonstrating the issues: // // ContentView.swift // ListElementFocus // // Created by Richard Aurbach on 10/12/24. // import SwiftUI /// NOTE: in my actual app, the data model is actually a set of SwiftData /// PresistentModel objects. Here, I'm simulating them with an Observable. @Observable final class TestModel: Identifiable { public var id: UUID public var checked: Bool = false public var title: String = "Test" public var subtitle: String = "Subtitle" init(checked: Bool = false, title: String, subtitle: String) { self.id = UUID() self.checked = checked self.title = title self.subtitle = subtitle } } struct ContentView: View { /// Instead of a @Query... @State var records: [TestModel] = [ TestModel(title: "First title", subtitle: "blah, blah, blah"), TestModel(title: "Second title", subtitle: "more nonsense"), TestModel(title: "Third title", subtitle: "even more nonsense"), ] @FocusState var focus: UUID? var body: some View { Form { Section { HStack(alignment: .top) { Text("Goal:").font(.headline) Text( "If a user taps in the TextField in any row, they should be able to tab from row to row using any keyboard which supports a tab key." ) } HStack(alignment: .top) { Text("#1:").font(.headline) Text( "While I will admit that this code is probaby total garbage, I haven't been able to find any way to make tabbing from row to row to work at all." ) } HStack(alignment: .top) { Text("#2:").font(.headline) Text( "Tapping the checkbox button causes the row to flash with the current accent color, and I can't find any way to turn that off." ) } } header: { Text("Problems").font(.title3).bold() }.headerProminence(.increased) Section { List(records) { record in ListRow(record: record, focus: focus) .onKeyPress(.tab) { focus = next(record) return .handled } } } header: { Text("Example: Selector of Editable Items").font(.title3).bold() }.headerProminence(.increased) } .padding() } private func next(_ record: TestModel) -> UUID { guard !records.isEmpty else { return UUID() } if record.id == records.last!.id { return records.first!.id } if let index = records.firstIndex(where: { $0.id == record.id }) { return records[index + 1].id } return UUID() } } struct ListRow: View { @Bindable var record: TestModel var focus: UUID? @FocusState var focusState: Bool init(record: TestModel, focus: UUID?) { self.record = record self.focus = focus self.focusState = focus == record.id } var body: some View { HStack(alignment: .top) { Button { record.checked.toggle() } label: { record.checked ? Image(systemName: "checkmark.square.fill") : Image(systemName: "square") }.font(.title2).focusable(false) VStack(alignment: .leading) { TextField("title", text: $record.title).font(.headline) .focused($focusState) Text("subtitle").italic() } } } } #Preview { ContentView() }
0
0
489
Oct ’24
SwiftData Query and optional relationships
Xcode 16.2 (16C5032a) FB16300857 Consider the following SwiftData model objects (only the relevant portions are shown) (note that all relationships are optional because eventually this app will use CloudKit): @Model final public class Team { public var animal: Animal? public var handlers: [Handler]? ... } @Model final public class Animal { public var callName: String public var familyName: String @Relationship(inverse: \Team.animal) public var teams: [Team]? ... } @Model final public class Handler { public var givenName: String @Relationship(inverse: \Team.handlers) public var teams: [Team]? } Now I want to display Team records in a list view, sorted by animal.familyName, animal.callName, and handlers.first.givenName. The following code crashes: struct TeamListView: View { @Query<Team>(sort: [SortDescriptor(\Team.animal?.familyName), SortDescriptor(\Team.animal?.callName), SortDescriptor(\Team.handlers?.first?.givenName)]) var teams : [Team] var body: some View { List { ForEach(teams) { team in ... } } } } However, if I remove the sort clause from the @Query and do the sort explicitly, the code appears to work (at least in preliminary testing): struct TeamListView: View { @Query<Team> var teams: [Team] var body: some View { let sortedTeams = sortResults() List { ForEach(sortedTeams) { team in ... } } } private func sortResults() -> [Team] { let results: [Team] = teams.sorted { team1, team2 in let fam1 = team1.animal?.familyName ?? "" let fam2 = team2.animal?.familyName ?? "" let comp1 = fam1.localizedCaseInsensitiveCompare(fam2) if comp1 == .orderedAscending { return true } if comp1 == .orderedDescending { return false } ... <proceed to callName and (if necessary) handler givenName comparisons> ... } } } While I obviously have a workaround, this is (in my mind) a serious weakness in the implementation of the Query macro.
5
0
812
Jan ’25
"Unwrapping" Scrolling
For a number of complex views in my app, I need to embed scrollable objects (like List, Form or TextEditor) in a ScrollView. To do that, I need to apply a limit to the height of the embedded object. What I would like to do is set that limit to the actual height of the content being displayed in the List, Form, TextEditor, etc. (Note that this height calculation should be dynamic, so that content changes are properly displayed. I attempted the following: @State listHeight: CGFloat = .zero List { ... content here } .onScrollGeometryChange(for: CGFloat.self, of: { geometry in return geometry.contentSize.height }, action: { oldValue, newValue in if oldValue != newValue { listHeight = newValue } }) .frame(height: listHeight) .scrollDisabled(true) This does not work because geometry.contentSize.height is always 0. So it is apparent that .onScrollGeometryChangedoes not interact with the internal scrolling mechanism of List. (Note, however, that.scrollDisabled` does work.) Does anyone have a suggestion on how I might get this to work?
3
0
141
Aug ’25
Fous, FocusState and Architecture
I am currently struggling with resolving what appear to be competing design issues, and (while I may be just demonstrating my own ignorance) I would like to share my thoughts in the hope that you may have useful insights. For purposes of discussion, consider a large and complex data entry screen with multiple sections for input. For all of the usual reasons (such as reuse, performance management, etc) each of these sections is implemented as its own, separately-compiled View. The screen is, then, composed of a sequence of reusable components. However, each of these components has internal structure and may contain multiple focusable elements (and internal use of .onKeyPress(.tab) {...} to navigate internally). And the logic of each component is such that it has an internal @FocusState variable defined with its own unique type. So, obviously what I want is on the one hand, to provide a tab-based navigation scheme for the screen as a whole, where focus moves smoothly from one component's internals to the next component, and on the other hand ,to build components that don't know anything about each other and have no cross-component dependencies, so that they can be freely reused in different situations. And that's where I'm stuck. Since focus state variables for different components can have different types, a single over-arching FocusState passed (as a binding) to each component doesn't seem possible or workable. But I don't know how else to approach this issue. (Note: in UIKit, I've done things like this by direct manipulation of the Responder Chain, but I don't see how to apply this type of thinking to SwiftUI.) Thoughts?
3
0
161
Oct ’25
Core Data: Fatal Error sorting using a computed property
I have a Core Data entity with a computed property and I want to sort the objects of this entity by this computed property. So • I build the NSFetchRequest in the normal way, including an NSSortDescriptor for sorting by this computed property. • Construct the usual NSFetchedResultController and call performFetch(). This results in a fatal error: *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'keypath score not found in entity Wine' I've tried to do this in several different ways, including (a) @objc public var score: Float { get { <getter code here> } } (b) Define score in the data model as transient, then @objc public var _score: Float { get { <getter code here> } } ... and ... public override func awakeFromFetch() { super.awakeFromFetch() score = _score } But the error persists. Is there any way to get this to work without abandoning NSFetchedResultsController, fetching unsorted records, sorting them programmatically and building the snapshot from the sorted array of objects? (I know, but it's the best I've been able to come up with so far...)
4
0
2.6k
Oct ’22