Не удается получить доступ к свойству типа 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 *'




Почему я не могу получить доступ к этому свойству? Чего мне не хватает?

646   4  

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

    Ничего не найдено.