无法从Objective-C访问Swift类型的属性

tra*_*uan 60 types objective-c swift objective-c-swift-bridge

我试图Double?从Objective-C 访问Swift类的属性.

class BusinessDetailViewController: UIViewController {

    var lat : Double?
    var lon : Double?

    // Other elements...
}
Run Code Online (Sandbox Code Playgroud)

在另一个视图控制器中,我试图访问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 */
}
Run Code Online (Sandbox Code Playgroud)

我正在接受

在'BusinessDetailViewController*'类型的对象上找不到属性'lat'

为什么我不能访问这个属性?我错过了什么?

Nat*_*ook 105

非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
}
Run Code Online (Sandbox Code Playgroud)

在Objective-C代码中,您将访问前三个属性,如下所示:

TestClass *optTest = [[TestClass alloc] init];
optTest.nsNumberOpt = @1.0;
optTest.nsNumberVar = @2.0;
optTest.doubleVar = 3.0;
Run Code Online (Sandbox Code Playgroud)

在您的情况下,您可以转换latlong非可选或将它们切换为实例NSNumber.


请注意,如果采用第二种方法(切换latlon类型的非可选属性NSNumber),则需要注意Objective-C代码- 而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)
    }
}
Run Code Online (Sandbox Code Playgroud)

如果使用两个属性中的值调用,这可以正常工作,但如果从Objective-C代码nsNumberVar设置为nil,则会在运行时崩溃.请注意,有没有办法检查是否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
Run Code Online (Sandbox Code Playgroud)

  • @Antonio:没错 - 在Objective-C中,任何引用类型都可以是`nil`,因此它们会自动桥接到Swift选项.实际上,有人可能会争辩说,在桥接项目中,任何引用类型都不应该是非可选的,因为您可以将"nil"分配给Objective-C中的非Optional属性,从而导致潜在的崩溃而无法追索.看我的补充...... (2认同)

dmz*_*zza 14

如果您的属性是Swift协议类型,只需@objc在它前面添加.

例:

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

@objc protocol FooDelegate {
   func bar()
}
Run Code Online (Sandbox Code Playgroud)