chronotruck / FlagPhoneNumber

A formatted phone number UITextField with country flag picker.
Apache License 2.0
437 stars 318 forks source link

Use Apple's country flag emojis when the FPNCountry flag property is nil #122

Closed lsamaria closed 4 years ago

lsamaria commented 4 years ago
public struct FPNCountry {
    public var code: FPNCountryCode
    public var name: String
    public var phoneCode: String
    var flag: UIImage?

    init(code: String, name: String, phoneCode: String) {
        self.name = name
        self.phoneCode = phoneCode
        self.code = FPNCountryCode(rawValue: code)!

        if let flag = UIImage(named: code, in: Bundle.FlagIcons, compatibleWith: nil) {
            self.flag = flag
        } else {

            let appleCountryEmojiStr = flag(from: code)

            if let countryFlag = appleCountryEmojiStr.image() {

                self.flag = countryFlag

            } else {

                self.flag = UIImage(named: "unknown", in: Bundle.FlagIcons, compatibleWith: nil)
            }
        }
    }

    func flag(from twoDigitCountryCode: String) -> String {
        let base : UInt32 = 127397
        var s = ""
        for v in twoDigitCountryCode.uppercased().unicodeScalars {
            s.unicodeScalars.append(UnicodeScalar(base + v.value)!)
        }
        return s
    }
}

extension String {

    func image() -> UIImage? {
        let size = CGSize(width: 40, height: 40)
        UIGraphicsBeginImageContextWithOptions(size, false, 0)
        UIColor.white.set()
        let rect = CGRect(origin: .zero, size: size)
        UIRectFill(CGRect(origin: .zero, size: size))
        (self as AnyObject).draw(in: rect, withAttributes: [.font: UIFont.systemFont(ofSize: 40)])
        let image = UIGraphicsGetImageFromCurrentImageContext()
        UIGraphicsEndImageContext()
        return image
    }
}
lsamaria commented 4 years ago

For some reason the flag was't showing in certain classes. I couldn't find the exact issue as to why the UIImage(named: code, in: Bundle.FlagIcons, compatibleWith: nil) was nil but I realized there aren't any alternatives for the FPNCountry flag property other than the UIImage(named: "unknown".... Considering Apple has its own country flag emojis I decided to use them as an alternative. I followed these answers from Stack Overflow

Swift turn a country code into a emoji flag via unicode

Convert Apple Emoji (String) to UIImage

If the FPNCountry flag property is nil instead of creating an image namedUIImage(named: "unknown"... I took the 2 digit country value from the code property and passed it into a function that converts it into an emoji flag of type String.

I extended the String class to add an image() function that converts a String to an Image. If the image isn't nil I pass the image to the flag property. If for some reason it is nil then I use the UIImage(named: "unknown"... as a final alternative.

It should be noted that both functions 100% work but because this is a pod I wasn't able to get the FPNCountry class to recognize the changes. Assuming the author accepts and tests them this is a decent backup plan.

grifas commented 4 years ago

I'm agree with the concept but like I said in an other issue (https://github.com/chronotruck/FlagPhoneNumber/issues/70) I'm afraid Apple will be rejected apps with emojis that don't come from the user.

lsamaria commented 4 years ago

Oh that sucks, I didn’t know that. Ok I’m filing an issue later. The “unknown” flag doesn’t appear. I looked into your assets and there are warning ⚠️ labels on it but also on all the other flag images. Thanks for responding.

lsamaria commented 4 years ago

what about using this pod as an alternative?

https://github.com/madebybowtie/FlagKit

public struct FPNCountry {
    public var code: FPNCountryCode
    public var name: String
    public var phoneCode: String
    var flag: UIImage?

    init(code: String, name: String, phoneCode: String) {
        self.name = name
        self.phoneCode = phoneCode
        self.code = FPNCountryCode(rawValue: code)!

        if let flag = UIImage(named: code, in: Bundle.FlagIcons, compatibleWith: nil) {
            self.flag = flag
        } else {

                                 // use it here
            if let countryFlag = Flag(countryCode: countryCode) {

                self.flag = countryFlag

            } else {

                self.flag = UIImage(named: "unknown", in: Bundle.FlagIcons, compatibleWith: nil)
            }
        }
    }
}
grifas commented 4 years ago

At start I used FlagKit but I removed it because the minimum deployment target is 10.0. I'm working on a new release. I think it will fix a lot of issue. Thanks to propose things.