In my traditional Swift/UIKit applications, I use IQKeyboardManager to make sure that the on-screen keyboard does not obscure the text field (or text view) being edited.What is the situation in SwiftUI? Is this something that is part of the "it just works" part of the framework, or do I still have to implement it? And if the latter, any thoughts as to how to approach the problem?Thanks,Rick Aurbach
Post
Replies
Boosts
Views
Activity
I have some custom controls I developed in my traditional Swift/UIKit applications and am thinking about migrating them to SwiftUI. However, the controls are currently iOS-specific. When implemented on macOS, I'd probably choose a different approach.I have yet to see any guidance (from Apple or from the numerous SwiftUI blog posts) as to the best way to approach building a custom control that have device-specific implementations.Can someone offer guidance or suggestions for getting started? I'm assuming that the solution is to provide device-specific conditional compilation, but a list of which methods need to be overridden would be a great start.Thanks,Rick Aurbach
I am beginning work on my first SwiftUI application, which uses CoreData as its data-store. And I have an issue I'm having trouble wrapping my head around.If I use an @ObservedObject property wrapper on a CoreData record, then use $property to bind an attribute in the record to a UI element, I understand that this sets up a two-way binding, which is good.BUT, in the case of a non-modal view, what strategies are recommended for knowing when to save context?Let me demonstrate my ignorance. This example is based on what I think I know (which is likely completely wrong):@ObservedObject var obj: MyCoreDataObject
var body : some View {
Toggle(isOn: obj.$active) {
Text("Is it active?")
}
}Because of the binding ($active), the value of the toggle and the attribute in Core Data object ought to be synchronized. But if the user actually taps the toggle, thus causing the obj.active attribute to change, that change needs to be saved. So, what are some ways to make sure that happens? Or have I missed the point?Rick
Let's suppose I want to provide a new user with some sample data which they can use to familiarize themselves with my app. In the NSPersistentContainer (i.e., local-only) case, I use one-time initialization logic to manually populate my app with this sample data. Then, over time, the user can keep that data, modify it, or delete it, as they choose.Now if I want to do the same thing with NSPersistentCloudKitContainer, this should be fine with my user's first device. But let's further suppose that (after using my app [and changing the CoreData database contents), my user load my app on a second device and runs it. On the second device, it will ALSO build an initial database containing sample data.What happens now? Does the content of the second device superceed the contents of the first? Suppose the user deleted a same record on device 1, but that sample record is loaded onto device 2 (as part of it's one-time initialization). Does that record reappear on device 1? And if a sample record is modified on device 1 (but appears initially unmodified on device 2), what happens? Who wins?What is the "best practices" technique for dealing with correct synchronization of a new device (that contains sample records) with the iCloud store?
According to the documentation, trailingSwipeActionsConfigurationForRowAt() is supported for MacCatalyst, but I can't seem to get it to work there.
On iOS, my tableView has rows with detail accessories, so the user can (all without entering "editMode") tap for more information
swipe-left to delete
swipe-right to edit (in some cases)
When running on the Mac via MacCatalyst, the swipe gestures do not seem to work and only clicks (i.e., to show detail) have any effect.
How can I retain the desired behavior?
I have been working to update a storyboard-based iOS app to run on iOS13+ and iOS14 (on both iPad and iPhone). While the new features appear to be very nice, there are some braking behavior changes that have been introduced, particularly with respect to iPhone. I'll list the major ones I've seen below.
My Question: are there any available workarounds? Or am I simply observing bugs in the Simulator and/or SDK from Xcode 12 beta 3?
Breaking Changes: On iPhone, using .primary and .secondary columns, I have found no way to force the controller to display the .master column initially. (I tried lots of things; details on request.)
So, I thought to assign the .compact viewController to the .primary controller. But that doesn't work because the .compact viewController ignores "show-detail" segues. (Unlike previous behavior, they are NOT simply translated into push segues.)
Originally, one purpose of the UISplitViewController was to provide a "smart" interface that would work on both iPad and iPhone, so that the application needn't be written twice. It appears that iOS14 has broken with this idea.
Am I seeing bugs? (If so, I'll happily provide feedback.) Or do I actually have to engineer iPhone-specific code?
I have what must be a common problem, and am looking for some architectural suggestions.
Over the years, I've built custom objects (e.g., popup calendars, button menus, etc) which have now been added to iOS as of iOS 14. This presents a problem for me, because I want my apps to support pre-14 systems. What I want to implement is:
An @IBDesignable object which implements a custom class on pre-14 systems, but implements the new iOS-14 objects on 14+.
The object must compile and build with a deployment target of 12.0. Obviously this means that I need to use @available and #available to make the link work.
I expect to use adaptor (wrapper) patterns to present a common external API that is iOS-version independent.
BUT, I can't figure out how to make this happen. I have some thoughts about making the @IBDesignable class a proxy for an implementation class (which is factory-constructed in the proxy's init methods). The implementation object would be intalled as a subview of the proxy object so all UI would go to it. But I'm sure I'm not thinking of all of the potential issues here.
Have you done something similar to this? Can you give any help or advice about such an undertaking before I sit down and get mired in code? (Maybe even a design pattern to share?)
Any help would be welcome.
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.
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?
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...)
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?
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?
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.
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?
The 'unique' attribute is a really nice feature, BUT. In some of my apps, the unique identifier for an object is a combination of multiple attributes. (Example: a book title is not unique, but a combination of book title and author list is.)
How do I model this with SwiftData? I cannot use @Attribute(.unique) on either the title OR the author list, but I want SwiftData to provide the same "insert or update" logic.
Is this possible?