O código objetivo-c pode chamar a extensão rápida na aula?

94

Pesquisei alguns posts, acho que não consigo escrever uma extensão no swift, e chamá-la do código Objective-C, certo?

Os atributos do tipo @objc suportam apenas métodos, classes, protocolos?

Sprhawk
fonte
1
Por que você simplesmente não tenta?
TEM
7
ide reclamou de erro, mas eu quero obter uma resposta definitiva.
sprhawk

Respostas:

84

Você pode escrever uma extensão Swift e usá-la no código Objective-C. Testado com XCode 6.1.1.

Tudo que você precisa fazer é:

  • crie sua extensão em Swift (sem @objcanotação)

  • #import "ProjectTarget-Swift.h" em sua classe Objective-C (onde "ProjectTarget" representa o alvo XCode ao qual a extensão Swift está associada)

  • chame os métodos da extensão Swift

Atualização: como @Rizwan Ahmed mencionado, você precisa adicionar uma @objcanotação:

A partir do Swift 4.0.3, a anotação @objc é necessária se você quiser usar a extensão em arquivos de classe C Objective.

marius bardan
fonte
6
Fiz exatamente isso, mas ainda é um erro de tempo de compilação. Hmmm. EDITAR: importei meu cabeçalho de ponte, em vez de "ProjectTarget-Swift.h". Der.
Jason Renaldo
Ambos são cabeçalhos de ponte. A diferença é que um é para usar o código Swift no ObjC e o outro é para usar o código ObjC no Swift. O cabeçalho do Swift é invisível. O outro deve ser gerenciado por você.
marius bardan
William Hu, veja a resposta de mclaughlinj!
appleitung
39
A partir do Swift 4.0.3, a anotação @objc é necessária se você quiser usar a extensão em arquivos de classe C Objective.
Rizwan Ahmed
68

Eu descobri que no Swift 4.0 eu tinha que adicionar a palavra-chave à @objcfrente da minha extensão para que os métodos de extensão do Swift se tornassem visíveis por uma instância da classe Objc que eu estava estendendo.

Em resumo:

Configuração de arquivo:

CustomClass.h
CustomClass.m
CustomClassExtension.swift

Em CustomClassExtension:

@objc extension CustomClass
{
    func method1() 
    {
        ...
    }
}

Em meu AppDelegate.m:

self.customClass = [[CustomClass alloc] init];
[self.customClass method1];
Andrey P.
fonte
2
Se um método usa genéricos, ele não pode ser usado por Objective-C e você precisará adicionar a @nonobjcanotação.
ThomasW 01 de
Apenas uma nota: @objcMembers não funciona neste caso. Não sei por quê .. :-(
Raunak
46

Esta solução funciona para Swift 2.2 e Swift 3 . Observe que apenas extensões para classes (não para structs ou enums) estarão acessíveis a partir do Objective-C.

import UIKit

extension UIColor {

    //Custom colours
    class func otherEventColor() -> UIColor {
        return UIColor(red:0.525, green:0.49, blue:0.929, alpha:1)
    }
}

Em seguida, #import "ProductModuleName-Swift.h" em seu arquivo ObjC.

Swift 4

extension UIColor {

    // As of Swift 4.0.3, the @objc annotation is needed if you want to use the extension in Objective-C files
    @objc
    class func otherEventColor() -> UIColor {
        return UIColor(red:0.525, green:0.49, blue:0.929, alpha:1)
    }
}
Foti Dim
fonte
Não é "YourProjectsNameHere ...", mas sim "YourTargetsNameHere ...": para compartilhar alvos, você deve bloqueá-lo para name: dr2050.postach.io/post/…
Dan Rosenstark
1
@DanRosenstark Você está correto. Estou mudando para "ProductModuleName-Swift.h" como a Apple sugere: developer.apple.com/library/ios/documentation/Swift/Conceptual/…
Foti Dim
1
Funciona bem para o swift 3.
Viktor Kucera
Existe uma razão pela qual você diz que publicé necessário? Funciona bem sem publicmodificador para mim. Estamos presumindo que a extensão não está no mesmo projeto, mas sendo importada de outro projeto?
Lee Kang
Eu preciso usar o cabeçalho de ponte?
jegadeesh
42

Conforme abordado nas outras respostas, a importação do cabeçalho Swift gerado funciona na maioria dos casos .

Uma exceção a isso é quando a categoria é definida em um tipo com ponte (ou seja, a extensão é definida como ativada Stringe não NSString). Essas categorias não serão automaticamente vinculadas a suas contrapartes Objective-C. Para contornar isso, você precisará usar o tipo Objective-C (e lançar o valor de retorno em seu código Swift com as String) ou definir uma extensão para os tipos Swift e Objective-C.

mclaughlinj
fonte
2
Adicionando à resposta acima, você deve tornar pública sua extensão swift e definir seu tipo como NSString, por exemplo public extension NSString. Se você obtiver um identificador não resolvido ou erro semelhante em tempo de compilação, você pode converter novamente para String, por exemplo, let sVal = self as Stringe chamar o código necessário emsVal
RunLoop
@RunLoop na verdade você não precisa de public, ele funcionará sem especificador de escopo. E (exportar para Obj-C, quero dizer) não funciona para Strings, porque são structs, não classes e só estão disponíveis no Swift. Então, sim - você pode escrever extensão para NSString e usar elenco, ou escrever extensões, como mclaughlinjdito, para a classe NSString e a estrutura String
Alex Nazarsky
3

Importe o cabeçalho "#import" ProductModuleName-Swift.h " no arquivo object -c e adicione @objc na frente de sua extensão no arquivo swift. Ele funcionará bem no swift 4.2 e no swift 5

Ranjani
fonte