-1

Swift 4 : >> operator is unavailable Looking for replacement operator for converting HexColor to UIColor in Swift 4.0 :

Here is sample code for earlier code version in Swift 3.0.

public extension UIColor {
    convenience init(hex: String) {
        var red:   CGFloat = 0.0
        var green: CGFloat = 0.0
        var blue:  CGFloat = 0.0
        var alpha: CGFloat = 1.0

        if hex.hasPrefix("#") {
            let index   = hex.characters.index(hex.startIndex, offsetBy: 1)
            let hex     = hex.substring(from: index)
            let scanner = Scanner(string: hex)
            var hexValue: CUnsignedLongLong = 0
            if scanner.scanHexInt64(&hexValue) {
                switch (hex.characters.count) {
                case 3:
                    red   = CGFloat((hexValue & 0xF00) >> 8)       / 15.0
                    green = CGFloat((hexValue & 0x0F0) >> 4)       / 15.0
                    blue  = CGFloat(hexValue & 0x00F)              / 15.0
                case 4:
                    red   = CGFloat((hexValue & 0xF000) >> 12)     / 15.0
                    green = CGFloat((hexValue & 0x0F00) >> 8)      / 15.0
                    blue  = CGFloat((hexValue & 0x00F0) >> 4)      / 15.0
                    alpha = CGFloat(hexValue & 0x000F)             / 15.0
                case 6:
                    red   = CGFloat((hexValue & 0xFF0000) >> 16)   / 255.0
                    green = CGFloat((hexValue & 0x00FF00) >> 8)    / 255.0
                    blue  = CGFloat(hexValue & 0x0000FF)           / 255.0
                case 8:
                    red   = CGFloat((hexValue & 0xFF000000) >> 24) / 255.0
                    green = CGFloat((hexValue & 0x00FF0000) >> 16) / 255.0
                    blue  = CGFloat((hexValue & 0x0000FF00) >> 8)  / 255.0
                    alpha = CGFloat(hexValue & 0x000000FF)         / 255.0
                default:
                    print("Invalid RGB string, number of characters after '#' should be either 3, 4, 6 or 8", terminator: "")
                }
            } else {
//                print("Scan hex error")
            }
        } else {
//            print("Invalid RGB string, missing '#' as prefix", terminator: "")
        }
        self.init(red:red, green:green, blue:blue, alpha:alpha)
    }
}

Thanks in advance.

  • 3
    According to https://developer.apple.com/library/content/documentation/Swift/Conceptual/Swift_Programming_Language/AdvancedOperators.html the `>>` operator is still available, please show a MCVE. – luk2302 Sep 22 '17 at 14:39
  • Your code is working for me without any error in Swift 4. Is it throwing any error? – Vini App Sep 22 '17 at 16:36
  • @ViniApp - I'm surprised you didn't get any warnings in Swift 4. The `hex.substring(from: index)` syntax is now deprecated. – Rob Sep 22 '17 at 17:59
  • I said that its not throwing any error. But warning is there. – Vini App Sep 22 '17 at 18:03
  • https://stackoverflow.com/a/31782490/2303865 – Leo Dabus Sep 22 '17 at 22:21

1 Answers1

0

This code has no problems with >> operator in Swift 4. The only issue is the string handling. I might replace

let index   = hex.characters.index(hex.startIndex, offsetBy: 1)
let hex     = hex.substring(from: index)

with

let index   = hex.index(hex.startIndex, offsetBy: 1)
let hex     = String(hex[index...])

Personally, I'd make a few other changes to that routine:

  1. I'd make it failable initializer (e.g. init?(...) returning an optional). Right now the calling code has no way of knowing if the conversion to UIColor failed.

  2. I'd simplify the above string handling, reducing it to:

    let hex = hex.replacingOccurrences(of: "^#", with: "", options: .regularExpression)
    

    Not only does that reduce it to a single line which removes any leading # present, but it also means that this code will now also work if you pass it a hex string that doesn't have the leading #.

  3. I'd use UInt64(_:radix:) instead of the scanner. It's just a little simpler.

Thus:

public extension UIColor {
    convenience init?(hex: String) {
        var red:   CGFloat = 0.0
        var green: CGFloat = 0.0
        var blue:  CGFloat = 0.0
        var alpha: CGFloat = 1.0

        let hex = hex.replacingOccurrences(of: "^#", with: "", options: .regularExpression)
        guard let hexValue = UInt64(hex, radix: 16) else {
            print("invalid hex string")
            return nil
        }

        switch (hex.count) {
        case 3:
            red   = CGFloat((hexValue & 0xF00) >> 8)       / 15.0
            green = CGFloat((hexValue & 0x0F0) >> 4)       / 15.0
            blue  = CGFloat(hexValue & 0x00F)              / 15.0
        case 4:
            red   = CGFloat((hexValue & 0xF000) >> 12)     / 15.0
            green = CGFloat((hexValue & 0x0F00) >> 8)      / 15.0
            blue  = CGFloat((hexValue & 0x00F0) >> 4)      / 15.0
            alpha = CGFloat(hexValue & 0x000F)             / 15.0
        case 6:
            red   = CGFloat((hexValue & 0xFF0000) >> 16)   / 255.0
            green = CGFloat((hexValue & 0x00FF00) >> 8)    / 255.0
            blue  = CGFloat(hexValue & 0x0000FF)           / 255.0
        case 8:
            red   = CGFloat((hexValue & 0xFF000000) >> 24) / 255.0
            green = CGFloat((hexValue & 0x00FF0000) >> 16) / 255.0
            blue  = CGFloat((hexValue & 0x0000FF00) >> 8)  / 255.0
            alpha = CGFloat(hexValue & 0x000000FF)         / 255.0
        default:
            print("Invalid RGB string, number of characters after '#' should be either 3, 4, 6 or 8", terminator: "")
            return nil
        }

        self.init(red: red, green: green, blue: blue, alpha: alpha)
    }
}
Rob
  • 415,655
  • 72
  • 787
  • 1,044