2014-10-14 15 views
50

Sto tentando di accedere a una proprietà della classe Swift Double? da Objective-C.Impossibile accedere alla proprietà di tipo Swift da Objective-C

class BusinessDetailViewController: UIViewController { 

    var lat : Double? 
    var lon : Double? 

    // Other elements... 
} 

In un altro controller di vista, sto cercando di accedere lat come segue:

#import "i5km-Swift.h" 
@interface ViewController() 

@property (strong, nonatomic) BusinessDetailViewController *businessDetailViewController; 

@end 

@implementation ViewController 

- (void)viewDidLoad 
{ 
    [super viewDidLoad]; 
    self.businessDetailViewController = [[BusinessDetailViewController alloc] initWithNibName:@"BusinessDetailViewController" bundle:nil]; 
    self.businessDetailViewController.lat = businessArray[1]; /* THIS GIVES ME AN ERROR */ 
} 

e sto ottenendo

Proprietà 'lat' non trovato in oggetto di tipo 'BusinessDetailViewController * '

Perché non posso ccess questa proprietà? Cosa mi manca?

+0

non so perché in businessDetailViewController, ho anche una presa '@IBOutlet var MapView: MKMapView ? 'e posso accedervi dall'esterno ma non ha' public' – tranvutuan

+0

Penso che le strutture opzionali non siano visibili in Objective-C. Convaliderà. –

risposta

95

I valori facoltativi dei tipi non-Objective-C non vengono sottoposti a ponte in Objective-C. Cioè, le prime tre proprietà di TestClass sotto sarebbero essere disponibile in Objective-C, ma il quarto non sarebbe:

class TestClass: NSObject { 
    var nsNumberVar: NSNumber = 0  // obj-c type, ok 
    var nsNumberOpt: NSNumber?   // optional obj-c type, ok 
    var doubleVar: Double = 0   // bridged Swift-native type, ok 
    var doubleOpt: Double?    // not bridged, inaccessible 
} 

Nel codice Objective-C, che ci si accede a questi primi tre immobili come questo:

TestClass *optTest = [[TestClass alloc] init]; 
optTest.nsNumberOpt = @1.0; 
optTest.nsNumberVar = @2.0; 
optTest.doubleVar = 3.0; 

Nel tuo caso, è possibile convertire lat e long essere non facoltativa o passare loro di essere casi di NSNumber.


Si noti che è necessario essere attenti a vostro codice Objective-C se si prende il secondo approccio (commutazione lat e lon per immobili non opzionali di tipo NSNumber) - mentre il compilatore Swift vi impedirà assegnando nil a proprietà non opzionali, il compilatore Objective-C non ha remore a permetterlo, lasciando che i valori di nil si introducano nel codice Swift senza possibilità di catturarli in fase di runtime. Considerate questo metodo su TestClass:

extension TestClass { 
    func badIdea() { 
     // print the string value if it exists, or 'nil' otherwise 
     println(nsNumberOpt?.stringValue ?? "nil") 

     // non-optional: must have a value, right? 
     println(nsNumberVar.stringValue) 
    } 
} 

Questo funziona bene se invocato con valori in entrambe le proprietà, ma se nsNumberVar è impostato su nil dal codice Objective-C, questo andrà in crash in fase di esecuzione. Nota che c'è non c'è modo di controllare se nsNumberVar è o meno nil prima di usarlo!

TestClass *optTest = [[TestClass alloc] init]; 
optTest.nsNumberOpt = @1.0; 
optTest.nsNumberVar = @2.0; 
[optTest badIdea]; 
// prints 1, 2 

optTest.nsNumberOpt = nil; 
optTest.nsNumberVar = nil; 
[optTest badIdea]; 
// prints nil, then crashes with an EXC_BAD_ACCESS exception 
+0

Non ho potuto rintracciarlo nei documenti ma il compilatore ti dirà che non è rappresentabile con il protocollo '@objc FooProtocol {var lat: Double? {get}} ' –

+1

La documentazione su questo è patchy - per esempio, [questa pagina] (https://developer.apple.com/library/ios/documentation/swift/conceptual/buildingcocoaapps/MixandMatch.html) dice che le enumerazioni e le strutture definite in Swift non sono disponibili in Obj-C, ma non menzionano che Optionals (che sono implementati come un 'enum') e la maggior parte dei tipi costruiti' struct' si collegano correttamente finché non si arriva a [la pagina su Tipi di dati di cacao] (https://developer.apple.com/library/ios/documentation/swift/conceptual/buildingcocoaapps/WorkingWithCocoaDataTypes.html#//apple_ref/doc/uid/TP40014216-CH6-XID_41). –

+0

@NateCook Non riesco a dimostrarlo, ma penso che un 'NSNumber' opzionale è collegato a ponte e un' Int 'o' Float' opzionale non è perché 'NSNumber' è un tipo di riferimento, e' .None' è mappato a ' nil', mentre un tipo di valore non ha una controparte 'nil' in objc. Non ti sto correggendo, mi chiedo solo se sei d'accordo – Antonio

3

Optionals è una funzione specifica rapida, non disponibile in ogg-c. Le istanze di classe facoltative funzionano perché un valore nil facoltativo può essere associato a un valore nullo, ma i tipi di valore (int, float, ecc.) Sono non tipi di riferimento, quindi una variabile di questi tipi non memorizza un riferimento, ma il valore stesso .

non so se c'è una soluzione - una soluzione possibile è la creazione di oggetti non opzionali mappatura del valore nil ad un valore di tipo dati non utilizzati (ad esempio -1 quando rappresentano un indice o 999999 per una coordinata):

class Test { 
    var lat : Double? { 
     didSet { 
      self._lat = self.lat != nil ? self.lat! : 999999 
     } 
    } 
    var lon : Double? { 
     didSet { 
      self._lon = self.lon != nil ? self.lon! : 999999 
     } 
    } 

    var _lat: Double = 99999999 
    var _lon: Double = 99999999 
} 

Che dovrebbe esporre le proprietà _lat e _lon a obj-c.

Nota che non l'ho mai provato, quindi fateci sapere se funziona.

+0

provalo e sì, possiamo accedere a _lat e _lon dall'esterno. Grazie. – tranvutuan

+0

Cool - grazie per averlo condiviso. – Antonio

8

Se la proprietà è un tipo di protocollo Swift, è sufficiente aggiungere @objc di fronte ad esso.

Esempio:

class Foo: UIViewController { 
    var delegate: FooDelegate? 
    ... 
} 

@objc protocol FooDelegate { 
    func bar() 
} 
0

[UInt?Int? o Double? proprietà] non può essere contrassegnato @objc perché il tipo non può essere rappresentato in Objective-C.

E ', tuttavia, possibile "avvolgere" loro in un NSNumber in questo modo:

class Foo { 
    var bar:Double? 
} 

// MARK: Objective-C Support 
extension Foo { 
    /// bar is `Double?` in Swift and `(NSNumber * _Nullable)` in Objective-C 
    @objc(bar) 
    var z_objc_bar:NSNumber? { 
     get { 
      return bar as NSNumber? 
     } 
     set(value) { 
      bar = value?.doubleValue ?? nil 
     } 
    } 
} 
Problemi correlati