Cómo usar la estructura Swift en Objective-C

97

Simplemente tengo una estructura que almacena las constantes de la aplicación de la siguiente manera:

struct Constant {

    static let ParseApplicationId = "xxx"
    static let ParseClientKey = "xxx"

    static var AppGreenColor: UIColor {
        return UIColor(hexString: "67B632")
    }
}

Estas constantes se pueden usar en código Swift llamando, Constant.ParseClientKeypor ejemplo, a. Pero en mi código, también contiene algunas clases Objective-C. Entonces, mi pregunta es ¿cómo usar estas constantes en el código Objective-C?

Si esta forma de declarar constantes no es buena, ¿cuál es la mejor manera de crear constantes globales para usar en código Swift y Objective-C?

Dinh Quan
fuente
22
Siga el estilo de código rápido común y use una letra minúscula para iniciar sus identificadores let / var.
Nikolai Ruhe
4
@NikolaiRuhe ¿No sería este el estilo correcto para las propiedades estáticas de una estructura? Mucho como UIControlEvents.TouchUpInside?
Luke Rogers
1
@NikolaiRuhe Eche un vistazo a la declaración Swift: developer.apple.com/library/ios/documentation/UIKit/Reference/… - definitivamente es una estructura.
Luke Rogers
1
@LukeRogers Eso se debe a que Swift 2.0 cambió la forma de importar NS_OPTIONSenumeraciones de estilo. Semánticamente UIControlEventsigue siendo un tipo de enumeración.
Nikolai Ruhe
5
@NikolaiRuhe LukeRogers: Dinh no preguntó sobre ese tema, y ​​la mayoría de los espectadores no hicimos clic aquí para leer al respecto.
original_username

Respuestas:

114

Es triste decirlo, no puede exponer struct, ni variables globales a Objective-C. ver la documentación .

A partir de ahora, en mi humilde opinión, la mejor manera es algo como esto:

let ParseApplicationId = "xxx"
let ParseClientKey = "xxx"
let AppGreenColor = UIColor(red: 0.2, green: 0.7, blue: 0.3 alpha: 1.0)

@objc class Constant: NSObject {
    private init() {}

    class func parseApplicationId() -> String { return ParseApplicationId }
    class func parseClientKey() -> String { return ParseClientKey }
    class func appGreenColor() -> UIColor { return AppGreenColor }
}

En Objective-C, puede usarlos así:

NSString *appklicationId = [Constant parseApplicationId];
NSString *clientKey = [Constant parseClientKey];
UIColor *greenColor = [Constant appGreenColor];
rintaro
fuente
¿Accesible también para Swift?
Khunshan
@khunshan Sí. Accesible directamente ParseClientKeyo a través de la claseConstant.clientKey()
Fabian
7
Debería usar@objc class Constant: NSObject
William Hu
1
Esto funciona, pero en Swift 4, también necesitaba poner @objcdelante de cada class funcpara poder llamarlos desde el código Objective C.
ElectroBuddha
2
@ElectroBuddha Puede hacer @objcMembersen la clase para revelar toda la clase al código Objective-C.
user1898712
19

¿Por qué no crear un archivo con una structy una @objc class, algo como esto:

import UIKit

extension UIColor {
    convenience init(hex: Int) {
        let components = (
            R: CGFloat((hex >> 16) & 0xff) / 255,
            G: CGFloat((hex >> 08) & 0xff) / 255,
            B: CGFloat((hex >> 00) & 0xff) / 255
        )
        self.init(red: components.R, green: components.G, blue: components.B, alpha: 1)
    }
}

extension CGColor {
    class func colorWithHex(hex: Int) -> CGColorRef {
        return UIColor(hex: hex).CGColor
    }
}

struct Constant {
    static let kParseApplicationId = "5678"
    static let kParseClientKey = "1234"
    static var kAppGreenColor: UIColor { return UIColor(hex:0x67B632) }
    static var kTextBlackColor: UIColor { return UIColor(hex:0x000000) }
    static var kSomeBgBlueColor: UIColor { return UIColor(hex:0x0000FF) }
    static var kLineGrayCGColor: CGColor { return CGColor.colorWithHex(0xCCCCCC) }
    static var kLineRedCGColor: CGColor { return CGColor.colorWithHex(0xFF0000) }
}


@objc class Constants: NSObject {
    private override init() {}

    class func parseApplicationId() -> String { return Constant.kParseApplicationId }
    class func parseClientKey() -> String { return Constant.kParseClientKey }
    class func appGreenColor() -> UIColor { return Constant.kAppGreenColor }
    class func textBlackColor() -> UIColor { return Constant.kTextBlackColor }
    class func someBgBlueColor() -> UIColor { return Constant.kSomeBgBlueColor }
    class func lineGrayCGColor() -> CGColor { return Constant.kLineGrayCGColor }
    class func lineRedCGColor() -> CGColor { return Constant.kLineRedCGColor }
}

Para usar en archivos Objective-C, agregue esto cuando necesite usar constantes:

#import "ProjectModuleName-Swift.h"

Uso rápido:

self.view.backgroundColor = Constant.kAppGreenColor

Uso de Objective-C:

self.view.backgroundColor = [Constants appGreenColor];

De esta manera, puede actualizar los colores, el texto predeterminado y las URL de servicios web para toda la aplicación en un solo lugar.

Marijan V.
fuente
1
¡No me quedó claro de inmediato que podríamos desplazarnos por tu respuesta para descubrir la parte objetivo-c!
Cœur
1

Debe hacer que las declaraciones let sean privadas si desea que otros tipos de Swift en su código accedan a estas constantes solo a través de la clase:

private let AppGreenColor = UIColor(red: 0.2, green: 0.7, blue: 0.3 alpha: 1.0)

@objc class Constant {
    class func appGreenColor() -> UIColor { return AppGreenColor }
}

En Swift, puedes usarlos así:

UIColor *greenColor = Constant.appGreenColor

La siguiente línea ya no se compilará ya que la declaración let es privada:

UIColor *greenColor = appGreenColor
koira
fuente
1

Aunque esto puede ser tardío o redundante, podría hacerlo funcionar con el siguiente código:

@objcMembers class Flags: NSObject {
    static let abcEnabled = false
    static let pqrEnabled = false
    .
    .
    .
}

Obviamente, para usar en código objc c, debe hacer #import "ProjectModuleName-Swift.h"

Anil Arigela
fuente