Не удается получить доступ к свойству типа Swift из Objective-C
Я пытаюсь получить доступ к Swift класса Double? свойство от Objective-C.
class BusinessDetailViewController: UIViewController {
var lat : Double?
var lon : Double?
// Other elements...
}
в другом контроллере вида, я пытаюсь получить доступ lat следующее:
#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 */
}
и
свойство ' lat 'не найдено на объекте типа' BusinessDetailViewController *'
Почему я не могу получить доступ к этому свойству? Чего мне не хватает?
4 ответов:
необязательные значения типов Non-Objective-C не соединяются в Objective-C. То есть первые три свойства
TestClassниже б будет доступен в Objective-C, но четвертый не будет: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 }в вашем коде Objective-C вы получите доступ к этим первым трем свойствам следующим образом:
TestClass *optTest = [[TestClass alloc] init]; optTest.nsNumberOpt = @1.0; optTest.nsNumberVar = @2.0; optTest.doubleVar = 3.0;в вашем случае, вы можете либо преобразовать
latиlongбыть необязательным или переключать их на экземплярыNSNumber.
обратите внимание, что вы должны быть осторожны с вашим кодом Objective-C, если вы используете второй подход (переключение
latиlonк необязательным свойствам типаNSNumber) -- в то время как компилятор Swift не позволит вам назначитьnilк необязательным свойствам компилятор Objective-C не сомневается в том, чтобы разрешить его, позволяяnilзначения проникают в ваш Swift-код без шансов поймать их во время выполнения. Рассмотрим этот метод на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) } }это прекрасно работает, если вызывается со значениями в обоих свойствах, но если
nsNumberVarустановлено значениеnilиз кода Objective-C это приведет к сбою во время выполнения. Обратите внимание, что есть нет возможности проверить лиnsNumberVarиnilперед его использованием!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
Если ваше свойство является типом протокола Swift, просто добавьте
@objcперед ним.пример:
class Foo: UIViewController { var delegate: FooDelegate? ... } @objc protocol FooDelegate { func bar() }
Optionals-это специфическая функция swift, недоступная в obj-c. дополнительные экземпляры класса работают, потому что nil optional может быть сопоставлен с нулевым значением, но типы значений (int, floats и т. д.) есть не ссылочные типы, следовательно, переменная этих типов не хранит ссылку, но само значение.
Я не знаю, есть ли решение - возможным обходным путем является создание необязательных свойств отображения
nilзначение для неиспользуемого значения типа данных (например, -1, когда представляя индекс, или 999999 для координаты):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 }это должно разоблачить
_latи_lonсвойства для obj-c.обратите внимание, что я никогда не пробовал, поэтому, пожалуйста, дайте нам знать, если это работает.
[
UInt?Int?илиDouble?свойства] не могут быть отмечены @objc, потому что его тип не может быть представлен в Objective-C.однако можно "обернуть" их в NSNumber следующим образом:
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 } } }
Comments