Il codice obiettivo-c può chiamare un'estensione rapida in classe?


94

Ho cercato alcuni post, penso di non poter scrivere un'estensione sotto swift e chiamarla dal codice Objective-C, giusto?

@objc come gli attributi supportano solo metodi, classi, protocolli?


1
Perché non provi?
HA

7
ide si è lamentato dell'errore, ma voglio avere una risposta definitiva.
Sprhawk

Risposte:


84

Puoi scrivere un'estensione Swift e usarla nel codice Objective-C. Testato con XCode 6.1.1.

Tutto quello che devi fare è:

  • crea la tua estensione in Swift (nessuna @objcannotazione)

  • #import "ProjectTarget-Swift.h" nella tua classe Objective-C (dove "ProjectTarget" rappresenta il target XCode a cui è associata l'estensione Swift)

  • chiama i metodi dall'estensione Swift

Aggiornamento: come indicato da @Rizwan Ahmed, è necessario aggiungere @objcun'annotazione:

A partire da Swift 4.0.3, l'annotazione @objc è necessaria se si desidera utilizzare l'estensione nei file di classe Objective C.


6
Ho fatto esattamente questo ma è ancora un errore in fase di compilazione. Hmmm. EDIT: ho importato la mia intestazione di bridging, invece di "ProjectTarget-Swift.h". Der.
Jason Renaldo

Entrambi sono intestazioni di collegamento. La differenza è che uno è per l'utilizzo del codice Swift in ObjC e l'altro è per l'utilizzo del codice ObjC in Swift. L'intestazione Swift è invisibile. L'altro, dovrebbe essere gestito da te.
marius bardan

William Hu, guarda la risposta di mclaughlinj!
appleitung

39
A partire da Swift 4.0.3, l'annotazione @objc è necessaria se si desidera utilizzare l'estensione nei file di classe Objective C.
Rizwan Ahmed

68

Ho scoperto che in Swift 4.0 dovevo aggiungere @objcdavanti alla mia parola chiave di estensione in modo che i metodi di estensione Swift diventassero visibili da un'istanza della classe Objc che stavo estendendo.

In breve:

Configurazione della configurazione dei file:

CustomClass.h
CustomClass.m
CustomClassExtension.swift

In CustomClassExtension:

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

Nella mia AppDelegate.m:

self.customClass = [[CustomClass alloc] init];
[self.customClass method1];

2
Se un metodo utilizza generici, non può essere utilizzato da Objective-C e dovrai aggiungere l' @nonobjcannotazione.
ThomasW

Solo una nota a margine, @objcMembers non funziona in questo caso. Non so perché .. :-(
Raunak

46

Questa soluzione funziona per Swift 2.2 e Swift 3 . Nota che solo le estensioni per le classi (non per strutture o enumerazioni) saranno accessibili da 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)
    }
}

Quindi #import "ProductModuleName-Swift.h" nel file 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)
    }
}

Non è "YourProjectsNameHere ..." ma piuttosto "YourTargetsNameHere ...": per condividere gli obiettivi, devi bloccarlo al nome: dr2050.postach.io/post/…
Dan Rosenstark

1
@DanRosenstark Hai ragione. Lo sto cambiando in "ProductModuleName-Swift.h" come suggerisce Apple: developer.apple.com/library/ios/documentation/Swift/Conceptual/…
Foti Dim

1
Funziona bene per Swift 3.
Viktor Kucera

C'è un motivo per cui dici che publicè necessario? Funziona bene senza publicmodificatore per me. Presumiamo che l'estensione non sia nello stesso progetto ma venga importata da un altro progetto?
Lee Kang

Devo utilizzare un'intestazione di bridging?
jegadeesh

42

Come spiegato nelle altre risposte, l'importazione dell'intestazione Swift generata funziona nella maggior parte dei casi .

Un'eccezione è quando la categoria è definita su un tipo con ponte (cioè l'estensione è definita su Stringe non NSString). Queste categorie non verranno automaticamente collegate alle loro controparti Objective-C. Per aggirare questo problema, dovrai utilizzare il tipo Objective-C (ed eseguire il cast del valore restituito nel codice Swift con as String) o definire un'estensione per entrambi i tipi Swift e Objective-C.


2
Aggiungendo alla risposta sopra, dovresti rendere pubblica la tua estensione rapida e impostarne il tipo come NSString es public extension NSString. Se si ottiene un identificatore non risolto o un errore simile in fase di compilazione, è possibile eseguire nuovamente il cast su String eg let sVal = self as Stringe quindi chiamare il codice necessario susVal
RunLoop

@RunLoop in realtà non hai bisogno di public, funzionerà senza lo specificatore di ambito. E (esportazione in Obj-C, intendo) non funziona per le stringhe, perché sono strutture, non classi e sono disponibili solo da Swift. Quindi, sì - puoi scrivere estensioni per NSString e usare cast, o scrivere estensioni, come mclaughlinjdetto, sia per la classe NSString che per la struttura String
Alex Nazarsky

3

Importa l' intestazione "#import" ProductModuleName-Swift.h " nel file goal -c e aggiungi @objc davanti alla tua estensione nel file swift. Funzionerà bene in swift 4.2 e swift 5

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.