1

I have this code that I need to make reusable by other apps.

This code shows messages where the localized app's name is present.

So, I have localized strings like this:

"DoYou" = "Do you really want to close $$$?";
"Quit" = "Quit $$$";
"Keep Running" = "Keep $$$ Running";

Where $$$ must be replaced with the localized app's name at run time.

Because I want to learn about property wrappers, I have tried to create this one:

extension String {

  func findReplace(_ target: String, withString: String) -> String
  {
    return self.replacingOccurrences(of: target,
                                     with: withString,
                                     options: NSString.CompareOptions.literal,
                                     range: nil)
  }
}


  @propertyWrapper
  struct AdjustTextWithAppName<String> {
    private var value: String?


    init(wrappedValue: String?) {
      self.value = wrappedValue
    }

    var wrappedValue: String? {
      get { value }
      set {
        if let localizedAppName = Bundle.main.localizedInfoDictionary?["CFBundleName"] as? String {
          let replaced = value.findReplace("$$$", withString: localizedAppName)

        }
        value = nil
      }
    }

  }

I get this error on the replaced line:

Value of type String? has no name findReplace

I have also tried to use this line

 let replaced = value!.findReplace("$$$", withString: localizedAppName)

Same error...


The string may contain the app's name more than once. This is why I have that extension to String.

Duck
  • 34,902
  • 47
  • 248
  • 470
  • Your function doesn't match the call to it, you need to replace `findReplace(target: String, withString: String)` with `findReplace(_ target: String, withString: String)` – Maximilian Jan 29 '20 at 11:35
  • @Maximilian - sorry that was a typo. Just did that and the error persists. – Duck Jan 29 '20 at 11:39
  • The built-in localization system already has support for placeholders like this. – Alexander Jan 29 '20 at 18:50

1 Answers1

4

To solve this your property wrapper can't have a genereic type named String because that shadows the built-in type String that your extension belongs to. So change the struct declaration to not be generic

@propertyWrapper
struct AdjustTextWithAppName {

or name the type to something else

@propertyWrapper
struct AdjustTextWithAppName<T> {

and fix the set method

set {
    guard let str = newValue, let localizedAppName = Bundle.main.localizedInfoDictionary?["CFBundleName"] as? String else {
        value = nil
     } 

     value = str.findReplace(target: "$$$", withString: localizedAppName)
  }
Joakim Danielson
  • 43,251
  • 5
  • 22
  • 52