0

How to assign updated value to Text value in Extension SwiftUIenter image description here

extension Text {
    
    public func translate(text: String) -> Text{
        var translated = ""
        let conditions = ModelDownloadConditions(allowsCellularAccess: true, allowsBackgroundDownloading: true)
        GoogleTranslatorManager.shared.translator?.downloadModelIfNeeded(with: conditions) { error in
            guard error == nil else { return }
            GoogleTranslatorManager.shared.translator?.translate(text) { translatedText, error in
                guard error == nil, let translatedText = translatedText else {
                    //                    uiView.text = text
                    return
                }
                print(translatedText)
                translated = translatedText

               //**Here: How to assign updated Value to Text ** \\ 
           
            }
        }
        
        return Text(verbatim: translated)
    }
}
Paulw11
  • 108,386
  • 14
  • 159
  • 186
Akshay
  • 1
  • 1
  • 1
    First, it doesn't make much sense to put this extension on `Text`, you would put it on `String`. Second, the translation operation is asynchronous, so you can't return a value, you would need to pass a completion handler or use async/await. Third, if you were going to implement this sort of function as an extension you would typically just have it operate on `self`, not accept an argument or return a value. – Paulw11 May 23 '23 at 05:16
  • @Paulw11 That comment would make a fine answer. – Caleb May 23 '23 at 05:18

1 Answers1

0

There are a few issues that I see with your approach.

First, it doesn't make much sense to put this extension on Text - Text is a view that displays a String. It makes more sense to put the extension on String.

Second, if you make an extension on String it would be more typical for the function to operate on self - that is the String instance itself, rather than accept an argument.

And the final issue is that the translation operations are asynchronous so you can't return a value.

As an extension on String it could look something like:

extension String {
   func translated(completionHandler: @escaping (Result<String, Error>) -> Void) ) {
       let conditions = ModelDownloadConditions(allowsCellularAccess: true, allowsBackgroundDownloading: true)
           
       GoogleTranslatorManager.shared.translator?.downloadModelIfNeeded(with: conditions) { error in
            guard error == nil else { 
               completionHandler(.failure(error))
            }
            GoogleTranslatorManager.shared.translator?.translate(self) { translatedText, error in
                guard error == nil, let translatedText else {
                   completionHandler(.failure(error))
                }
                completionHandler(.success(translatedText))
            }
        }
    }
}

And you would call it something like:

let someString = "parlez vous français"
someString.translated { result in 
    switch result {
        case .failure(let error):
            print("There was an error \(error)")
        case .success(let translated):
            print("The translated string is: \(translated)"
     }
}

Now, you still have the problem of actually updating the Text view on the screen. You would use an @State string property or an @Published property in some model and update that string value and the view will update (You may need to dispatch this onto the main queue).

However, I don't see the value in creating this as an extension on String. Is it really a new behaviour that you want all strings to have? It is probably best implemented as a function in your translation manager object.

Paulw11
  • 108,386
  • 14
  • 159
  • 186