【问题标题】:Unable to access Swift 4 class from Objective-C: "Property not found on object of type"无法从 Objective-C 访问 Swift 4 类:“在类型的对象上找不到属性”
【发布时间】:2018-01-21 05:43:50
【问题描述】:

使用最新的 Xcode 9 测试版,我似乎完全无法访问 Swift 类的属性。更奇怪的是,我可以访问类本身来实例化它或其他什么,但完全无法访问它的属性。

如果我有这个 Swift 类:

import UIKit

class TestViewController: UIViewController {
    var foobar = true
}

我尝试这样做:

TestViewController *testViewController = [[TestViewController alloc] init]; // success
testViewController.foobar; // error

我到底做错了什么?使用 Xcode 9 的新项目。

【问题讨论】:

标签: ios objective-c swift xcode swift4


【解决方案1】:

至于 Swift 5.1 我发现“@objc”还不够,还要公开“@objc public”:

@objc public class SomeClass: NSObject {
    @objc public let amount: NSNumber
...

【讨论】:

  • String 对我不起作用?具有显式 setget 块的属性。有人也遇到过这种情况吗?
  • @Dan 我相信 optional 是一个结构体,这意味着它不能暴露于 Obj-C 运行时
【解决方案2】:

将 Swift 代码公开给 Objective-C 的规则在 Swift 4 中发生了变化。试试这个吧:

@objc var foobar = true

作为一项优化,@objc 推断在 Swift 4 中已减少。例如,NSObject 派生类中的属性(例如您的 TestViewController)将不会再推断@objc 默认情况下(就像在 Swift 3 中所做的那样)。

或者,您也可以使用@objcMembers所有成员一次性暴露给Objective-C:

@objcMembers class TestViewController: UIViewController {
    ...
}

the corresponding Swift Evolution proposal 中详细介绍了这一新设计。

【讨论】:

  • 我仍然面临从 Swift 到 Objective-C 访问 Int 和 Bool 属性的问题......并得到这个错误:属性不能被标记为@objc,因为它的类型不能在 Objective 中表示-C ,有什么建议吗? ..我使用了标题“MyProject-Swift.h
  • 只能访问字符串属性
  • 愚蠢的升级。现在,如果在 Objective C 类上使用它,我必须在每个变量和方法声明上添加 @objc 预处理器
  • 非常感谢,你拯救了我的一天 :)
  • 非常感谢!这让我整个早上都发疯了,但是你的帖子澄清了几点,并以@objcMembers 的形式给出了解决方案,这在我的情况下非常有效,这是一个具有各种 String、Int、Float 和 CLLocationDegrees 属性的类。
【解决方案3】:

Swift 3.2/4.0 / XCode 9.1

您在项目设置中设置了 swift3.2 ( //:configuration = Debug SWIFT_VERSION = 3.2 )

您可以使用您的代码,(在 objc 中使用正确的导入文件,见下文)。 如果您将项目设置为 swift 4.0 ( //:configuration = Debug SWIFT_VERSION = 4.0 )

您必须为每个属性添加 @objc。

所以:

Swift 3.2:

// MyClass.swift

@objc class MyClass: NSObject{

    var s1: String?
    @objc var s2 : String?
}


//

//  ViewController.m

import "MixingObjCAndSwift-Swift.h"
#import "ViewController.h"

@interface ViewController ()

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];        
    MyClass * mc = [MyClass new];
    NSString * s1 = mc.s1;
    NSString * s2 = mc.s2;
}

有效。

Swift 4.0:

// MyClass.swift

@objc class MyClass: NSObject{

    var s1: String?
    @objc var s2 : String?
}


.....  
- (void)viewDidLoad {
    [super viewDidLoad];        
    MyClass * mc = [MyClass new];
    NSString * s1 = mc.s1;
    NSString * s2 = mc.s2;
}

不起作用:编译器失败:

/Users....ViewController.m:24:21:在“MyClass *”类型的对象上找不到属性“s1”

因为 s1 没有以 @objc 开头。

你必须写:

@objc class MyClass: NSObject{

    @objc var s1: String?
    @objc var s2 : String?
}

(附带说明:在 C/C++/ObJC 文件中,始终将系统/通用 *h 文件放在“本地”类头文件之前。)

斯威夫特 4

只需在课前添加@objcMembers @objcMembers 类 MyClassObject: NSObject { var s1:字符串! var s2: 字符串!

} 迅捷进化enter link description here

【讨论】:

    【解决方案4】:

    Xcode 10.2 |斯威夫特 4 在课前添加@objcMembers 解决了我的问题。

    @objcMembers class MyClass:NSObject {
       var s1: String!
       var s2: NSMutableArray!
    }
    

    【讨论】:

      【解决方案5】:

      我在swift 3.0中也遇到过这个问题

      类声明是这样的

      class ClassA {
      //statements
      }
      

      Objective C 代码中无法访问上述类,并且它也未在 -Swift.h 中注册

      一旦我像这样从 NSObject 继承:

      class ClassA : NSObject {
      //statements
      } 
      

      该类可在 Objective c 中访问并在 -Swift.h 中注册

      当您不想避免从 NSobject 类继承时,此解决方案很有用。

      【讨论】:

        【解决方案6】:
        1. 当你在Objective-C项目中添加swift文件时,Xcode会提示添加Objective-C bridging header文件,所以允许创建头文件。
        2. 在您想要访问 TestViewController 属性的 Objective-C 实现文件中foobar。使用以下导入语法并将 ProjectName 替换为您的项目。

        #import "ProjectName-Swift.h"

        Objective-C 实现文件:

        #import "ViewController.h"
        #import "ProjectName-Swift.h"
        
        @implementation ViewController
        
        - (void)viewDidLoad {
            [super viewDidLoad];
            // Do any additional setup after loading the view, typically from a nib.
        
            TestViewController *testViewController = [[TestViewController alloc] init]; // success
            BOOL prop = testViewController.foobar;
            NSLog(@"Property: %d", prop);
        }
        
        @end
        

        更多详情请通过Apple Documents

        【讨论】:

          猜你喜欢
          • 2014-12-09
          • 1970-01-01
          • 2021-02-12
          • 1970-01-01
          • 2016-03-07
          • 2016-05-11
          • 1970-01-01
          相关资源
          最近更新 更多