Kann Objective-C-Code eine schnelle Erweiterung für Class aufrufen?

94

Ich habe einige Beiträge durchsucht, ich glaube, ich kann unter swift keine Erweiterung schreiben und sie aus Objective-C-Code aufrufen, oder?

@objc wie Attribute unterstützen nur Methoden, Klassen, Protokolle?

Sprhawk
quelle
1
Warum probierst du es nicht einfach aus?
HAT
7
Ich habe mich über einen Fehler beschwert, aber ich möchte eine eindeutige Antwort bekommen.
Sprhawk

Antworten:

83

Sie können eine Swift-Erweiterung schreiben und in Objective-C-Code verwenden. Getestet mit XCode 6.1.1.

Alles was Sie tun müssen ist:

  • Erstellen Sie Ihre Erweiterung in Swift (keine @objcAnmerkung)

  • #import "ProjectTarget-Swift.h" in Ihrer Objective-C-Klasse (wobei "ProjectTarget" das XCode-Ziel darstellt, dem die Swift-Erweiterung zugeordnet ist)

  • Rufen Sie die Methoden aus der Swift-Erweiterung auf

Update: Ab @Rizwan Ahmed müssen Sie eine @objcAnmerkung hinzufügen :

Ab Swift 4.0.3 wird die Annotation @objc benötigt, wenn Sie die Erweiterung in Objective C-Klassendateien verwenden möchten.

Marius Bardan
quelle
6
Ich habe genau das getan, aber es ist immer noch ein Fehler bei der Kompilierung. Hmmm. BEARBEITEN: Ich habe meinen Bridging-Header anstelle von "ProjectTarget-Swift.h" importiert. Der.
Jason Renaldo
Beide überbrücken Header. Der Unterschied besteht darin, dass einer für die Verwendung von Swift-Code in ObjC und der andere für die Verwendung von ObjC-Code in Swift vorgesehen ist. Der Swift-Header ist unsichtbar. Der andere sollte von Ihnen verwaltet werden.
Marius Bardan
William Hu, siehe mclaughlinjs Antwort!
Appleitung
39
Ab Swift 4.0.3 wird die Annotation @objc benötigt, wenn Sie die Erweiterung in Objective C-Klassendateien verwenden möchten.
Rizwan Ahmed
68

Ich fand heraus, dass ich in Swift 4.0@objc vor meinem Erweiterungsschlüsselwort hinzufügen musste, damit die Swift-Erweiterungsmethoden für eine Instanz der von mir erweiterten Objc-Klasse sichtbar wurden.

Zusamenfassend:

Setup der Dateikonfiguration:

CustomClass.h
CustomClass.m
CustomClassExtension.swift

In CustomClassExtension:

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

In meinem AppDelegate.m:

self.customClass = [[CustomClass alloc] init];
[self.customClass method1];
Andrey P.
quelle
2
Wenn eine Methode Generika verwendet, kann sie von Objective-C nicht verwendet werden, und Sie müssen die @nonobjcAnmerkung hinzufügen .
ThomasW
Nur eine Randnotiz, @objcMembers funktioniert in diesem Fall nicht. Ich weiß nicht warum .. :-(
Raunak
46

Diese Lösung funktioniert für Swift 2.2 und Swift 3 . Beachten Sie, dass von Objective-C nur auf Erweiterungen für Klassen (nicht für Strukturen oder Aufzählungen) zugegriffen werden kann.

import UIKit

extension UIColor {

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

Dann #import "ProductModuleName-Swift.h" in Ihre ObjC-Datei.

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
quelle
Es ist nicht "YourProjectsNameHere ...", sondern "YourTargetsNameHere ...": Um Ziele zu teilen, müssen Sie es sperren, um den Namen zu erhalten: dr2050.postach.io/post/…
Dan Rosenstark
1
@ DanRosenstark Du bist richtig. Ich ändere es in "ProductModuleName-Swift.h", wie Apple vorschlägt: developer.apple.com/library/ios/documentation/Swift/Conceptual/…
Foti Dim
1
Funktioniert gut für schnelle 3.
Viktor Kucera
Gibt es einen Grund, warum Sie sagen, dass publices nötig ist? Funktioniert gut ohne publicModifikator für mich. Gehen wir davon aus, dass sich die Erweiterung nicht im selben Projekt befindet, sondern aus einem anderen Projekt importiert wird?
Lee Kang
Muss ich einen Bridging-Header verwenden?
Jegadeesh
42

Wie in den anderen Antworten beschrieben, funktioniert das Importieren des generierten Swift-Headers in den meisten Fällen .

Eine Ausnahme bildet, wenn die Kategorie für einen überbrückten Typ definiert ist (dh die Erweiterung ist für definiert Stringund nicht NSString). Diese Kategorien werden nicht automatisch mit ihren Objective-C-Gegenstücken verknüpft. Um dies zu umgehen, müssen Sie entweder den Objective-C-Typ verwenden (und den Rückgabewert in Ihren Swift-Code umwandeln as String) oder eine Erweiterung für den Swift- und den Objective-C-Typ definieren.

mclaughlinj
quelle
2
Wenn Sie die obige Antwort ergänzen, sollten Sie Ihre schnelle Erweiterung öffentlich machen und ihren Typ als NSString festlegen, z public extension NSString. Sollten Sie beim Kompilieren einen ungelösten Bezeichner oder einen ähnlichen Fehler erhalten, können Sie erneut auf String zurückgreifen, z. B. let sVal = self as Stringden erforderlichen Code sVal
aufrufen
@ RunLoop Eigentlich brauchst du kein öffentliches, es funktioniert ohne Scope Specifier. Und es (Export nach Obj-C, meine ich) funktioniert nicht für Strings, da es sich um Strukturen handelt, nicht um Klassen, die nur von Swift verfügbar sind. Also, ja - Sie können eine Erweiterung für NSString schreiben und cast verwenden oder Erweiterungen schreiben, wie mclaughlinjgesagt, sowohl für die NSString-Klasse als auch für die String-Struktur
Alex Nazarsky
3

Importieren Sie den Header "#import" ProductModuleName-Swift.h " in die Objective-C-Datei und fügen Sie @objc vor Ihrer Erweiterung in die Swift-Datei ein. In Swift 4.2 und Swift 5 funktioniert dies einwandfrei

Ranjani
quelle