SwiftUI not all strings are localized - ios

SwiftUI didn't translate the string in variable.
I have added:
"Name" = "姓名";
if I wrote:
Text("Name")
works good. I can see the label with 姓名.
If I define a variable like:
#State var title = "Name"
Text(title)
Then the localization doesn't work. Still in Chinese. Any tips?

You have to explicitly indicate that your title variable is a LocalizedStringKey, not a String.
#State var title: LocalizedStringKey = "Name"

Related

How to use optional #State variable with binding parameter in SwiftUI

I am trying to use an optional #State variable with a TextField. This is my code:
struct StorageView: View {
#State private var storedValue: String?
var body: some View {
VStack {
TextField("Type a value", text: $storedValue)
}
}
}
When I use this code, I get the following error:
Cannot convert value of type 'Binding<String?>' to expected argument type 'Binding<String>'
I have tried the following code for both the values to be optional, but nothing seems to work:
TextField("Type a value", text: $storedValue ?? "")
TextField("Type a value", text: Binding($storedValue)!)
How would I go about using an optional #State variable with a binding? Any help with this is appreciated.
How would I go about using an optional #State variable with a binding? Any help with this is appreciated.
It looks like you are using an optional state variable with a binding. You get an error because TextField's initializer expects a Binding<String> rather than a Binding<String?>. I guess you could solve the problem by adding another initializer that accepts Binding<String?>, or maybe making an adapter that converts between Binding<String?> and Binding<String>, but a better option might be to have a good think about why you need your state variable to be optional in the first place. After all this string something that will be displayed in your UI -- what do you expect your TextField to display if storedValue is nil?

SwiftUI: .onOpenURL action closure is not updating #State property which is of type URL

I am implementing my first iOS Application with SwiftUI, in which I want users to be able of clicking on an invitation link for joining a topic group (DeepLinking).
Like joining a WhatsApp-Group with a link.
Therefore I associated my Domain (lets say: https://invite.example.com/) with my Swift-Project.
Whenever I click/open a URL (e.g. https://invite.example.com/313bceff-58e7-40ae-a1bd-b67be466ef72) my app opens and if the user is logged in an the .onOpenURL action method is triggered as expected.
However, if I try to save the url in a #State URL property in the called closure, it gets not stored.
The #State boolean property for showing the sheet is set to true though.
That is my code in the #main struct.
import SwiftUI
#main
struct MyApp: App {
#StateObject private var appRouter: AppRouter = AppRouter()
#State private var openAcceptInvitationSheet: Bool = false
#State private var invitationURL: URL? = nil
var body: some Scene {
WindowGroup {
switch appRouter.currentScreen {
case .launch:
EmptyView()
case .login:
LoginSignupNavigationView()
case let .home(authenticatedUser):
HomeTabView()
.environmentObject(authenticatedUser)
.onOpenURL { url in
invitationURL = url //Gets not set -> url is not nil here!
openAcceptInvitationSheet = true //Is working and sheet will be presented
}
.sheet(isPresented: $openAcceptInvitationSheet) {
//invitationURL is nil -> Why?
AcceptInvitationNavigationView(invitationURL: invitationURL!)
}
}
}
}
}
Everything else is working here as expected. I guess I have a misconception of how the #State properties work. However in all my other views I managed assigning values to #State properties in closures which later can be used.
Rather than using two variables for your sheet, use one – the optional URL.
.sheet(item: $invitationURL) { url in
AcceptInvitationNavigationView(invitationURL: url)
}
The optionality of your URL? state variable takes the place of the boolean value in determining whether the sheet should display, and the sheet receives the unwrapped URL value.
I don't think that your URL is not being set – it's more a question of it's not set at the time the original sheet's closure is evaluated, which is a subtly different SwiftUI object life cycle thing! Sticking to a single object massively simplifies everything. You'll also be able to change your code in AcceptInvitationNavigationView to expect a URL rather than having to deal with being passed an optional URL.
As noted in comments, this only works if URL conforms to Identifiable, which it doesn't by default. But you can use a URL's hashValue to synthesize a unique identifier:
extension URL: Identifiable {
var id: Int { hashValue }
}

How can I initialize attributes in SwiftUI?

So this block of code allows me to initialize a data model
struct MockMessage: Identifiable {
let id: Int
let imageName: String
let messageText: String
let isCurrentUser: Bool
}
let MOCK_MESSAGES: [MockMessage] = [
.init(id: 0, imageName: "user", messageText: "Hey, what's up?", isCurrentUser: false),
.init(id: iCouldSetANewOne, imageName: iCouldSetANewOne, messageText: iCouldSetANewOne, isCurrentUser: iCouldSetANewOne)]
My question is
1- How can I replicate/initialize attributes instead of manually writing the same attributes over and over again
2- How can I modify it, let's say, the default rotation effect is set to a degree: 25 and I'd like to change it.
Example of Image attributes
Image(systemName: tabs[index].image)
.frame(height: 20)
.rotationEffect(.degrees(-25))
.foregroundColor(.yellow).scaleEffect(1.25)
If I understand correctly, you want to group a commonly used set of modifiers into 1 simple modifier. You can easily do it like this:
extension View {
func myStyle() -> some View {
self
.frame(...)
.rotationEffect(...)
.foregroundColor(...)
}
}
You can even parametrize this function if the values can be different.
About the "changing the rotation effect that is set to 25 degrees" I believe you can have multiple of the same effects, so if you want to rotate some view that is already rotated, just put another .rotationEffect() view modifier on top.

SwiftUI Localisation not working with #State Strings

I have implemented Localisation in my SwiftUI app. Everything works fine but I'm having issues with localising #State var. Localisation is not working and I'm getting only the keys printed out. Any idea how to fix this issue?
The value of type is already in my Localizable.strings
#State var type: String
var body: some View {
VStack {
Text(self.type) // not working
Text("test") // working
}
}
You can take convert the string into a NSLocalizedString
Text(NSLocalizedString(type, comment: ""))
or change the type of type into a LocalizedStringKey
#State var type: LocalizedStringKey
When a string literal is passed to Text its type needs to be inferred (Since it isn't explicitly stated). Literal text is probably a fixed part of your UI, so it is interpreted as a LocalizedStringKey.
When you pass the property self.type, it has an explicit type - String, so the Text(_ verbatim:) initialiser is used resulting in non-localised text.
If you want that property to be localised you can use the LocalizedStringKey(_ string: String) initialiser:
Text(LocalizedStringKey(self.type))

How can I add some custom Text to my LocalizedStringKey?

let sometext: LocalizedStringKey = "sometext"
var body: some View {
Text(sometext + " some more text") // Error: Binary operator '+' cannot be applied to operands of type 'LocalizedStringKey' and 'String'
}
Why does this not work and how can I fix it?
I also found that, but I as a beginner do not really understand the answer
https://www.reddit.com/r/swift/comments/d50afb/localizedstringkey_to_string/
This is how you add text together in swiftUI.
var body: some View {
Text(sometext) + Text("some more text")
}

Resources