2016-12-15 3 views
1

Я пытаюсь преобразовать существующую программу, которая использует список предопределенных цветов от Ojective-C до Swift. Оригинальный код, используемый селектор для извлечения UIColor на его основе именем представлена ​​в виде NSStringКак преобразовать строку в UIColor в Swift 3.0?

#define UIColorFromRGB(rgbValue) [UIColor colorWithRed:((float)((rgbValue & 0xFF0000) >> 16))/255.0 green:((float)((rgbValue & 0xFF00) >> 8))/255.0 blue:((float)(rgbValue & 0xFF))/255.0 alpha:1.0] 

-(UIColor *)getColor:(NSString*)colorName 
{ 
    SEL selColor = NSSelectorFromString(colorName); 
    NSString *errorMessage = [NSString stringWithFormat:@"Invalid color name: %@ !!!", colorName]; 
    NSAssert([UIColor respondsToSelector:selColor] == YES, errorMessage); 
    UIColor *mycolor = [UIColor performSelector:selColor]; 
    return mycolor; 
} 

+ (instancetype)turquoiseColor { 
    return UIColorFromRGB(0x40E0D0); 
} 

+ (instancetype)mediumTurquoiseColor { 
    return UIColorFromRGB(0x48D1CC); 
} 

Однако я не смог работать, как для достижения той же функциональности с помощью Swift 3.0, или с использованием селектора даже лучшая техника.

func UIColorFromRGB(_ rgbValue: UInt) -> UIColor { 
    return UIColor(
     red: CGFloat((rgbValue & 0xFF0000) >> 16)/255.0, 
     green: CGFloat((rgbValue & 0x00FF00) >> 8)/255.0, 
     blue: CGFloat(rgbValue & 0x0000FF)/255.0, 
     alpha: CGFloat(1.0) 
    ) 
} 

extension UIColor { 
    public class var turquoise: UIColor { return UIColorFromRGB(0x40E0D0) } 
} 

extension UIColor { 
    public class var mediumTurquoise: UIColor { return UIColorFromRGB(0x48D1CC) } 
} 

let myColor: UIColor = .turquoise 

let name: String = "turquoise" 
let colorName = "UIColor.\(name)" 
let selector: Selector = NSSelectorFromString(colorName) 

let colorSelected: UIColor = UIColor.perform(selector!) 

Ошибка:! Нет «выполнить» кандидаты производят ожидаемого тип контекстной результаты «UIColor»

ответ

1

Вы можете создать цвет перечисление, который имеет значение по умолчанию строки:

enum Color: String { 
    case red 
    case blue 
    case green 

    var create: UIColor { 
     switch self { 
      case .red: 
      return UIColor.red 
     case .blue: 
      return UIColor.blue 
     case .green: 
      return UIColor.green 
     } 
    } 
    } 

Поскольку она имеет значение по умолчанию строки можно инициализировать перечисление со строкой:

guard let color = Color(rawValue: "red") else { "handle invalid color error"; return } 

let colorSelected = color.create //// colorSelected is now UIColor.red 
+0

Это хороший ответ, я просто конвертируются мой код, чтобы проверить это. Однако тот факт, что дублирование названий цветов делает его более громоздким в моем коде, чем другие предложения, так как у меня 230 названных цветов. – Steve

+0

Вы имеете в виду дублирование имен цветов с указанием имен перечислений? Я не уверен, что полностью понимаю, что вы подразумеваете под дублированием имен цветов. – JustinM

+0

Да, тот факт, что каждое имя цвета должно появляться дважды внутри перечисления, один раз в исходном случае, а затем снова внутри create. Таким образом, это усложняет ситуацию, когда я хочу добавить новые имена цветов и т. Д. И приводит к появлению большего количества строк кода. Поэтому, используя эти критерии, предложение словаря является самой компактной реализацией. Но, спасибо, это заставило меня рассмотреть все варианты и изучить несколько новых трюков на этом пути. – Steve

1

Вы можете написать что-то похожее на код Objective-C в Swift, как это:

extension UIColor { 
    @objc(turquoiseColor) 
    public class var turquoise: UIColor { return UIColorFromRGB(0x40E0D0) } 
} 

extension UIColor { 
    @objc(mediumTurquoiseColor) 
    public class var mediumTurquoise: UIColor { return UIColorFromRGB(0x48D1CC) } 
} 

let myColor: UIColor = .turquoise 

func getColor(_ name: String) -> UIColor? { 
    let selector = Selector("\(name)Color") 
    if UIColor.self.responds(to: selector) { 
     let color = UIColor.self.perform(selector).takeUnretainedValue() 
     return (color as! UIColor) 
    } else { 
     return nil 
    } 
} 

var name: String = "turquoise" 
if let color = getColor(name) { 
    print(color) //->UIExtendedSRGBColorSpace 0.25098 0.878431 0.815686 1 
} else { 
    print("color with name:\(name) is unavailable") 
} 

Но использование Selector не похоже на Swifty.

Вы можете просто подготовить словарь, содержащий UIColor S:

let myColors: [String: UIColor] = [ 
    "red": .red, 
    "white": .white, 
    //... 
    "turquoise": UIColorFromRGB(0x40E0D0), 
    "mediumTurquoise": UIColorFromRGB(0x48D1CC), 
] 
name = "mediumTurquoise" 
if let color = myColors[name] { 
    print(color) 
} else { 
    print("color with name:\(name) is unavailable") 
} 

Или ответ JustinM является очень хорошее предложение.

+0

Это очень полный ответ, он отклеил меня. Я опробовал оба варианта, и оба они работают. – Steve

1

Используйте это расширение UIColor, которые имеют два метода для преобразования RGBA строки и шестнадцатеричной строки в UIColor

extension UIColor { 


//Convert RGBA String to UIColor object 
//"rgbaString" must be separated by space "0.5 0.6 0.7 1.0" 50% of Red 60% of Green 70% of Blue Alpha 100% 
public convenience init?(rgbaString : String){ 
    self.init(ciColor: CIColor(string: rgbaString)) 
} 

//Convert UIColor to RGBA String 
func toRGBAString()-> String { 

    var r: CGFloat = 0 
    var g: CGFloat = 0 
    var b: CGFloat = 0 
    var a: CGFloat = 0 
    self.getRed(&r, green: &g, blue: &b, alpha: &a) 
    return "\(r) \(g) \(b) \(a)" 

} 
//return UIColor from Hexadecimal Color string 
public convenience init?(hexString: String) { 

     let r, g, b, a: CGFloat 

     if hexString.hasPrefix("#") { 
      let start = hexString.index(hexString.startIndex, offsetBy: 1) 
      let hexColor = hexString.substring(from: start) 

      if hexColor.characters.count == 8 { 
       let scanner = Scanner(string: hexColor) 
       var hexNumber: UInt64 = 0 

       if scanner.scanHexInt64(&hexNumber) { 
        r = CGFloat((hexNumber & 0xff000000) >> 24)/255 
        g = CGFloat((hexNumber & 0x00ff0000) >> 16)/255 
        b = CGFloat((hexNumber & 0x0000ff00) >> 8)/255 
        a = CGFloat(hexNumber & 0x000000ff)/255 
        self.init(red: r, green: g, blue: b, alpha: a) 
        return 
       } 
      } 
     } 

     return nil 
    } 
// Convert UIColor to Hexadecimal String 
func toHexString() -> String { 
    var r: CGFloat = 0 
    var g: CGFloat = 0 
    var b: CGFloat = 0 
    var a: CGFloat = 0 
    self.getRed(&r, green: &g, blue: &b, alpha: &a) 
    return String(
     format: "%02X%02X%02X", 
     Int(r * 0xff), 
     Int(g * 0xff), 
     Int(b * 0xff) 
    ) 
} 

}

Смежные вопросы