web-dev-qa-db-ja.com

Objective-CからSwift 4クラスにアクセスできません:「プロパティがタイプのオブジェクトで見つかりません」

最新のXcode 9ベータ版を使用すると、Swiftクラスのプロパティにアクセスできないように見えます。さらに奇妙なことに、クラス自体にアクセスしてインスタンス化することもできますが、そのプロパティに完全にアクセスすることはできません。

したがって、このSwiftクラスがある場合:

import UIKit

class TestViewController: UIViewController {
    var foobar = true
}

そして、私はこれをしようとします:

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

私は正確に何を間違っていますか? Xcode 9を使用した新しいプロジェクト。

50
Doug Smith

SwiftコードをObjective-Cに公開するルールは、Swift 4.で変更されました。代わりにこれを試してください。

@objc var foobar = true

最適化として、@objc推論はSwift 4で削減されました。たとえば、NSObjectなどのTestViewController派生クラス内のプロパティはnoは、デフォルトで@objcを推測します(Swift 3で行ったように)。

あるいは、@objcMembersを使用して、Objective-Cにallメンバーを一度に公開することもできます。

@objcMembers class TestViewController: UIViewController {
    ...
}

新しい設計の詳細は、 対応するSwift Evolution提案 に記載されています。

126
Paulo Mattos

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ファイルでは、「ローカル」クラスヘッダーの前に常にsystem/general * hファイルを置きます。)

Swift 4

クラスの前に@objcMembersを追加するだけです@ objcMembersclass MyClassObject:NSObject {var s1:String! var s2:文字列!

} Swift evolution リンクの説明をここに入力

12
ingconti
  1. Objective-CプロジェクトにSwiftファイルを追加すると、XcodeはObjective-Cブリッジングヘッダーファイルの追加を要求するため、ヘッダーファイルを作成した。
  2. TestViewControllerプロパティfoobarにアクセスするObjective-C実装ファイル内。次のインポート構文を使用して、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 をご覧ください。

1
Rahul Kumar

Swift 3.0でもこの問題に遭遇しました。

クラス宣言はそのようなものでした

class ClassA {
//statements
}

上記のクラスはObjective Cコードではアクセスできず、-Swift.hにも登録されていませんでした

nSObjectから次のように継承したら:

class ClassA : NSObject {
//statements
} 

クラスはObjective Cでアクセス可能で、-Swift.hで登録されました

このソリューションは、NSobjectクラスからの継承を避けたくない場合に役立ちます。

0
Prabhat Kasera