Post

Replies

Boosts

Views

Activity

Reply to iOS 15 Notification Content not working?
I found the default project that Xcode 13 beta 1 creates for Notification Content with the incorrect filtering of platforms for the UserNotification framework and was crashing with this: Unable to find NSExtensionContextClass (_UNNotificationContentExtensionVendorContext) in extension bundle - did you link the framework that declares the extension point? What fixed is selecting all platforms for the framework:
Jun ’21
Reply to Localization in Xcode
Discussed this more with cross-functional teams and not using keys a no-go. This will not work if you want to share localization efforts across platforms beyond Apple which is more of a real-world scenario especially in enterprise settings. For example, Android requires localization keys to not have dots and other kinds of characters, also we found many 3rd party localization services had a character limit on key length. And when looking at very long localization entries, using the value as the key just doesn't make sense. I think sticking with my first intuition in using localization keys is the right way despite all the Apple sessions and samples showing otherwise. Also, just to share I was able to achieve isolating localization configurations by extending Text views to initialize from other Text views. This way, I can offload the localization configurations off the view by creating a bunch of static Text views and let the rest of the app pick them off the shelf. First I create the simple but awkward Text extension: public extension Text {     /// Creates a text view from another text view for isolating localization entries.     init(_ text: Text) {         self = text     } } Then create the static Text views with all localization configurations: extension Text {     static let notificationTitle = Text(         "Notifications",         tableName: "NotificationSettings",         comment: "The section title for notifications group on the settings screen"     )     static let snoozeTime = Text(         "Snooze time",         tableName: "NotificationSettings",         comment: "The title of the snooze time in the notifications section of the settings screen"     )     static let snoozeHelp = Text(         "The number of minutes to remind you again later for action, like the functionality of an alarm clock.",         tableName: "NotificationSettings",         comment: "This is the comment for this localized entry"     ) } Then elsewhere in a view, I can do this: struct ContentView: View { var body: some View { VStack { Text(.snoozeTime) Text(.snoozeHelp) } .navigationTitle(.notificationTitle) } } This still lets the localization to be exported properly since the static Text views aren't dynamically generated from variables. I still wish the localization configurations weren't in the Text view itself but in the LocalizedStringKey or a new type such as LocalizedString, since this is the way that String(localized:table:bundle:locale:comments:) works and would just need a SwiftUI counterpart to it.
Jun ’21
Reply to Localization in Xcode
I was surprised from this too when I saw the Apple examples not using keys, ever since SwiftUI was released and even in Xcode 13. I've always used strongly-typed keys in production apps because changing the text would break all my translations. I'm really trying to see how Apple sees it and use the English translations right in the view as the keys. I even refactored one of my production apps like this to get a true sense. Translation breaks much more frequently on copy changes, but I can see the argument that it's expected since the other languages should change too, and importing them gives the warning to catch those that break, although a compiler warning would be nice because Missing Localizability never really catches anything because LocalizedStringKey conforms to ExpressibleByStringLiteral so Xcode will always assume you're using a localized entry. The other thing from here that's hard to accept is the localization comments crowding up the views badly. I've wondered why the localization comments and even table names weren't applied to LocalizedStringKey instead of the Text view so I can do something like below which seems to be the best of both worlds while also keeping views succinct. It also allows me to distribute and pass around the localization entry even in places that don't accept a Text view (so I don't have to make a Label the long way for example): extension LocalizedStringKey {     static let fuelPurchase = LocalizedStringKey(         "This purchase gives you fuel for your car",         tableName: "StoreProducts",         bundle: .storeProducts, comments: "This is the text that's displayed for fuel purchases"     ) } Text(.fuelPurchase) Label(.fuelPurchase, systemImage: "bell") I submitted this feedback in #FB9169281 but wanted to share here to get thoughts from others and if maybe there's something I'm missing. PS - I'm not sure if the Apple team has examined how Android Studio handles localizations but it has always been a dream. It allows you to right click on English words and extract to localization. It uses keys behind the scenes to keep all the languages in sync, but during development time, the real English value get super imposed in the editor. So even in my example, I would see Text("This purchase gives you fuel for your car") in the editor based on my dev environment, but clicking on it would show the true code of Text(.fuelPurchase).
Jun ’21
Reply to SwiftUI NavigationLink pops out by itself
Another approach to the navigation link workaround collection is placing a hidden NavigationLink in the background that is shared across a few buttons, instead of each button being a NavigationLink: swift extension View {     func navigateDestination: View(         isActive: BindingBool,         destination: Destination?     ) - some View {         background(             NavigationLink(                 destination: destination,                 isActive: isActive,                 label: EmptyView.init             )             .hidden()         )     } } extension View {     func navigateItem, Destination: View(         item: BindingItem?,         destination: (Item) - Destination     ) - some View {         navigate(             isActive: Binding(                 get: { item.wrappedValue != nil },                 set: { if !$0 { item.wrappedValue = nil } }             ),             destination: Group {                 if let item = item.wrappedValue {                     destination(item)                 }             }         )     } } Then you can use it like this: swift struct ShowMoreView: View {     @State private var isLinkActive = false     var body: some View {         List {             Button(action: { isLinkActive = true })                 Text("Start navigation 1")             }             Button(action: { isLinkActive = true })                 Text("Start navigation 2")             }             Button(action: { isLinkActive = true })                 Text("Start navigation 3")             }         }         .navigate(isActive: $isLinkActive, destination: makeDestination())     } } struct ShowMoreView: View {     @State private var date: Date?     var body: some View {         List {             Button(action: { date = Date() })                 Text("Start navigation 1")             }             Button(action: { date = Date() + 100 })                 Text("Start navigation 2")             }             Button(action: { date = Date() + 1000 })                 Text("Start navigation 3")             }         }         .navigate(item: $date, destination: makeDestination)     }     func makeDestination(for date: Date) - some View {         ...     } } This source is from SwiftWithMajid's blog (for some reason the forums is not allowing me to link to it, but search for "swiftui majid lazy navigation" and you'll find it).
May ’21
Reply to Apple Pay with SwiftUI
Turns out you don't even need to use UIViewControllerRepresentable, or UIKit at all in SwiftUI! The trick is to use PKPaymentAuthorizationController - https://developer.apple.com/documentation/passkit/pkpaymentauthorizationcontroller, NOT the view controller version - https://developer.apple.com/documentation/passkit/pkpaymentauthorizationviewcontroller. From the docs: The PKPaymentAuthorizationController class performs the same role as the PKPaymentAuthorizationViewController class, but it does not depend on the UIKit framework. This means that the authorization controller can be used in places where a view controller cannot (for example, in watchOS apps or in SiriKit extensions). Apply Pay integration on SwiftUI should be approached more like a watchOS or Siri integration than a UIKit app. Below is a sample of the implementation: let request = PKPaymentRequest() request.paymentSummaryItems = ... let controller = PKPaymentAuthorizationController(paymentRequest: request) controller.delegate = self controller.present { [weak self] presented in 	 // Apple Pay presented from scene window } The controller automatically finds the scene window to present from. No more porting to UIKit or dismissal memory leaks!
Oct ’20