0

I have gone through so many article and have a good idea how we should implement method swizzling. But I'm getting this error while writing the original #selector for UserDefault class.

extension UserDefaults {
    @objc func customSetForKey(value: Any?, forKey: String) {
        UserDefaults.standard.set(value, forKey: "test" + forKey)
    }
    
    static func swizzleMethod() {
        let orginalSelector = #selector(set(_:forKey:))
        let origanlSetMethod = class_getInstanceMethod(self, orginalSelector)
        let swizzleMethod = class_getInstanceMethod(self, #selector(customSetForKey(value:forKey:)))
    }
}

The error which I'm getting is

'Ambiguous use of 'set(_:forKey:)''

I have tried everything but don't understand how should I write a selector for the method who's first parameter is having the type-alias name empty string.

For example check this another implementation

extension Bundle {
    static func swizzleLocalization() {
        let orginalSelector = #selector(localizedString(forKey:value:table:))
        guard let orginalMethod = class_getInstanceMethod(self, orginalSelector) else { return }

        let mySelector = #selector(myLocaLizedString(forKey:value:table:))
        guard let myMethod = class_getInstanceMethod(self, mySelector) else { return }

        if class_addMethod(self, orginalSelector, method_getImplementation(myMethod), method_getTypeEncoding(myMethod)) {
            class_replaceMethod(self, mySelector, method_getImplementation(orginalMethod), method_getTypeEncoding(orginalMethod))
        } else {
            method_exchangeImplementations(orginalMethod, myMethod)
        }
    }

    @objc private func myLocaLizedString(forKey key: String,value: String?, table: String?) -> String {
        guard let appDelegate = UIApplication.shared.delegate as? AppDelegate,
            let bundlePath = Bundle.main.path(forResource: appDelegate.currentLanguage, ofType: "lproj"),
            let bundle = Bundle(path: bundlePath) else {
                return Bundle.main.myLocaLizedString(forKey: key, value: value, table: table)
        }
        return bundle.myLocaLizedString(forKey: key, value: value, table: table)
    }
}

In this case original selector localizedString(forKey:value:table:) has no type alias for any parameter but for UserDefault method set(_ value: Any?, forKey: String) has a type alias for first parameter.

So please can someone help me to understand. how we should write the selector for this case.

  • Which overload of `set` do you want exactly? – Sweeper Oct 19 '22 at 14:06
  • Possible duplicate of https://stackoverflow.com/q/35658334/1187415. – Martin R Oct 19 '22 at 14:07
  • @Sweeper I want to overload UserDefault.standard.set(_ value: Any?: forKey: String) – VIJAY SINGH RAGHAV Oct 20 '22 at 05:55
  • @MartinR Yes it helps to understand how exactly the #selector takes an argument. But still what I'm seeing is that UserDefault have a lot of Function with same name "Set" with different Parameter. So how should I give the reference let orginalSelector = #selector(UserDefaults.standard.set(_:forKey:)) This line of code generates the same error 'Ambiguous use of 'set(_:forKey:)'' – VIJAY SINGH RAGHAV Oct 20 '22 at 06:00
  • @VIJAYSINGHRAGHAV: `let orginalSelector = #selector(set(_:forKey:) as (UserDefaults) ->(Any?, String)->Void)` seems to do the trick. – Martin R Oct 21 '22 at 19:33

0 Answers0