Невозможно получить доступ к свойству Swift от Objective-C - программирование
Подтвердить что ты не робот

Невозможно получить доступ к свойству Swift от Objective-C

Я пытаюсь вызвать var swift из объектного класса c. Что я делаю, как показано ниже:

Класс Swift

class BusinessDetailViewController: UIViewController {

    var lat : Double?
    var lon : Double?

    @IBOutlet var mapView: MKMapView?


    override func viewDidLoad() {
        super.viewDidLoad()

        // Do any additional setup after loading the view.
    }

    override init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: NSBundle?) {
        super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil)
        // Here you can init your properties
    }

    required init(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }

}

В ViewController.m, я пытаюсь вызвать lat следующим образом:

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

@property (strong, nonatomic) BusinessDetailViewController *businessDetailViewController;

@end

@implementation ViewController

- (void)viewDidLoad
{
    [super viewDidLoad];
    // Do any additional setup after loading the view from its nib.
    self.businessDetailViewController = [[BusinessDetailViewController alloc] initWithNibName:@"BusinessDetailViewController" bundle:nil];
    self.businessDetailViewController.lat = businessArray[1]; /* THIS GIVES ME AN ERROR */
}

и я получаю

Property 'lat' not found on object of type 'BusinessDetailViewController *'

Любые идеи, по которым я не могу получить доступ, или мне не хватает чего-то другого.

4b9b3361

Ответ 1

Дополнительные значения типов не 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

Ответ 2

Если ваше свойство является типом протокола Swift, просто добавьте @objc перед ним.

Пример:

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

@objc protocol FooDelegate {
   func bar()
}

Ответ 3

Опционы - это быстрая специфическая функция, недоступная в obj-c. Необязательные экземпляры классов работают, потому что необязательный параметр nil может быть сопоставлен с нулевым значением, но типы значений (int, float и т.д.) Являются not ссылочными типами, поэтому переменная этих типов не хранит ссылку, но само значение.

Я не знаю, есть ли решение - возможное обходное решение создает необязательные свойства, сопоставляющие значение 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.

Обратите внимание, что я никогда не пробовал это, поэтому, пожалуйста, сообщите нам, если он работает.