Como usar a estrutura Swift em Objective-C

97

Simplesmente tenho uma estrutura que armazena as constantes do aplicativo conforme abaixo:

struct Constant {

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

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

Essas constantes podem ser usadas em código Swift chamando, Constant.ParseClientKeypor exemplo. Mas em meu código, ele também contém algumas classes Objective-C. Portanto, minha pergunta é como usar essas constantes no código Objective-C?

Se esta maneira de declarar constantes não é boa, então qual é a melhor maneira de criar constantes globais para serem usadas no código Swift e Objective-C?

Dinh Quan
fonte
22
Siga o estilo de código swift comum e use uma letra minúscula para iniciar seus identificadores let / var.
Nikolai Ruhe
4
@NikolaiRuhe Este não seria o estilo correto para propriedades estáticas de uma estrutura? Muito parecido UIControlEvents.TouchUpInside?
Luke Rogers
1
@NikolaiRuhe Dê uma olhada na declaração do Swift: developer.apple.com/library/ios/documentation/UIKit/Reference/… - é definitivamente uma estrutura.
Luke Rogers
1
@LukeRogers Isso se deve à mudança na maneira como o Swift 2.0 de importar NS_OPTIONSenums de estilo. Semanticamente UIControlEventainda é um tipo de enumeração.
Nikolai Ruhe
5
@NikolaiRuhe LukeRogers: Dinh não perguntou sobre esse assunto, e a maioria de nós, espectadores, não clicou aqui para ler sobre isso.
original_username

Respostas:

114

É triste dizer, mas não é possível expor structnem variáveis ​​globais ao Objective-C. veja a documentação .

A partir de agora, IMHO, a melhor maneira é algo assim:

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 }
}

Em Objective-C, você pode usá-los assim:

NSString *appklicationId = [Constant parseApplicationId];
NSString *clientKey = [Constant parseClientKey];
UIColor *greenColor = [Constant appGreenColor];
Rintaro
fonte
Acessível ao Swift também?
khunshan
@khunshan Sim. Acessível diretamente ParseClientKeyou pela classeConstant.clientKey()
Fabian
7
Deve usar@objc class Constant: NSObject
William Hu
1
Isso funciona, mas no Swift 4, também precisei colocar @objcna frente de todos class funcpara poder chamá-los a partir do código Objective C.
ElectroBuddha
2
@ElectroBuddha Você pode fazer @objcMembersna classe para revelar toda a classe para o código Objective-C.
user1898712
19

Por que não criar um arquivo com um structe um @objc class, algo assim:

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 uso em arquivos Objective-C, adicione isto quando precisar usar constantes:

#import "ProjectModuleName-Swift.h"

Uso rápido:

self.view.backgroundColor = Constant.kAppGreenColor

Uso do Objective-C:

self.view.backgroundColor = [Constants appGreenColor];

Dessa forma, você pode atualizar cores, texto padrão e urls de serviços da web para todo o aplicativo em um só lugar.

Marijan V.
fonte
1
Não ficou imediatamente claro para mim que poderíamos rolar sua resposta para descobrir a parte objetiva-c!
Cœur
1

Você deve tornar as instruções let privadas se quiser tornar outros tipos Swift em seu código para acessar essas constantes apenas por meio da classe:

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 }
}

No Swift, você pode usá-los assim:

UIColor *greenColor = Constant.appGreenColor

A linha a seguir não será mais compilada agora, pois a instrução let é privada:

UIColor *greenColor = appGreenColor
Koira
fonte
1

Embora isso possa ser atrasado ou redundante, eu poderia fazer funcionar com o seguinte código:

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

Obviamente, para usar em código objc c, você deve fazer #import "ProjectModuleName-Swift.h"

Anil Arigela
fonte