2014-10-01 9 views
12

Biorąc pod uwagę deklarację szybkiej klasie jakNazwa Swift klasie pod wpływem kod Objective-C nie przestrzega @objc zmiana nazwy

@objc(NSFoo) public class Foo { 
    public func bar() ->() {} 
} 

chciałbym oczekiwać od mojego czytania dokumentacji, że na Obiektywne strony C, które moglibyśmy odnieść do tej klasy, używając identyfikatora NSFoo. Nie wydaje mi się, że to się dzieje. Wygenerowany w ProjectName-Swift.h definicja brzmi:

SWIFT_CLASS("NSFoo") 
@interface Foo 
- (void)bar; 
- (instancetype)init OBJC_DESIGNATED_INITIALIZER; 
@end 

natomiast co by się spodziewać jest

SWIFT_CLASS("Foo") 
@interface NSFoo 
... 

Używam Xcode 6.0.1.

Brakuje mi czegoś, czy to tylko błąd Xcode?

+0

Czy rzeczywiście wypróbowane i nie udało się utworzyć instancji w Objective C jako 'NSFoo'? – milos

+1

@milos Tak. Kompilator nie zgadza się z użyciem "Niezadeklarowanego identyfikatora" NSFoo "' – Manav

+0

Tylko notatkę. Unikałbym używania już używanych prefiksów klas, takich jak NS, CA, UI, itp. ... – Fogmeister

Odpowiedz

13

Uwaga: Rzeczy zmieniły się od czasu, kiedy ta odpowiedź została napisana po raz pierwszy - zobacz aktualizacje na końcu!

Tak, to robi szew być błąd ... choć, kontrolowanie Obj-C nazwy uruchomieniowe metod działa:

Say definiujemy parę minimalnych klas Obj-C i Swift, które współdziałają z siebie:

Foo.swift

import Foundation 

@objc(SwiftFoo) 
class Foo { // inheriting from NSObject makes no difference in this case 

    @objc(postcardFromSwift) 
    class func postcard() -> String { 
     return "Postcard from Swift!" 
    } 

    @objc(getMailInSwift) 
    class func getMail() { 
     if let hello = NSBar.postcard() { // NSBar is an Obj-C class (see below) 
      println("Printed in Swift: \(hello)") 
     } 
    } 
} 

NSBar.h

#import <Foundation/Foundation.h> 

@interface NSBar : NSObject 
+ (NSString *)postcard; 
+ (void)getMail; 
@end 

NSBar.m

#import "NSBar.h" 
#import "ObjS-Swift.h" 

@implementation NSBar 
+ (void)getMail { 
    // notice that I am not referring to SwiftFoo in spite of @objc(SwiftFoo) 
    printf("Printed in Objective C: %s", [[Foo postcardFromSwift] UTF8String]); 
} 
+ (NSString *)postcard { 
    return @"Postcard from Objective C!"; 
} 
@end 

Jeśli obecnie nazywamy ich metody klasy, powiedzmy, od main.m:

#import <Cocoa/Cocoa.h> 
#import "NSBar.h" 
#import "ObjS-Swift.h" 

int main(int argc, const char * argv[]) { 

    // notice that I am not referring to SwiftFoo in spite of @objc(SwiftFoo) 
    [Foo getMailInSwift]; 
    [NSBar getMail]; 

    return NSApplicationMain(argc, argv); 
} 

Drukuje następujące:

// --> Printed in Swift: Postcard from Objective C! 
// --> Printed in Objective C: Postcard from Swift! 

Ale to nie powinno mieć! Foo powinien być widoczny tylko dla Obj-C jako SwiftFoo, ponieważ jest to obiecująca opcja dla @objc(SwiftFoo). Rzeczywiście, użycie SwiftFoo wyzwala błąd kompilatora Use of undeclared identifier. Fakt, że działa to w przypadku nazw metod, nie pozostawia wątpliwości, że jest to błąd. Jestem zdumiony, że pierwszy o to pytasz! Plus jeden za to!

I tak:..

// <#ModuleName#>-Swift.h 
SWIFT_CLASS("SwiftFoo") 
@interface Foo 
+ (NSString *)postcardFromSwift; 
+ (void)getMailInSwift; 

... czy szew być odwrócone przez nazwę klasy, ale to jest, jak to działa makro - zobacz wideo Swift Interoperability In Depth WWDC (C 45 min i 48 min do c wideo). Odpowiednia dokumentacja to Exposing Swift Interfaces in Objective-C.

Xcode 7 beta 4

Kwestia ta jest już ustalona (dzięki @ScottBerrevoets dla komentarzu).

Xcode 7,1

(dzięki @Pang za komentarz)

@objc class C { } // error: only classes that inherit from NSObject can be declared @objc 
+0

Naprawiono to na Xcode 7 beta 4 –

+0

Dzięki @ScottBerrevoets. Zaktualizowałem odpowiedź. – milos

+0

W Xcode 7.1 kompilator mówi: * "Tylko klasy dziedziczące z NSObject mogą być deklarowane jako @objc" *. – Pang

3

Obecnie (w XCode8) to wydaje się, że zostały rozwiązane.

Zdefiniowane w XYZLogger.h i XYZLogger.m

NS_ASSUME_NONNULL_BEGIN 

NS_SWIFT_NAME(Logger) 
@interface XYZLogger : NSObject 

+ (void)verbose:(NSString *)logString; 
+ (void)debug:(NSString *)logString; 
+ (void)info:(NSString *)logString; 
+ (void)warn:(NSString *)logString; 
+ (void)error:(NSString *)logString; 

@end 

NS_ASSUME_NONNULL_END 

Używany w ObjC tak:

[XYZLogger debug:@"Hi from objective C"]; 

Używany w Swift tak:

Logger.debug("Hi from swift");