web-dev-qa-db-ja.com

Objective-CではSwiftクラスを使用できません

私は自分のアプリにSwiftコードを統合しようとしています。私のアプリはObjective-Cで書かれていて、私はSwiftクラスを追加しました。私は ここで と記述されているすべてを終えました。しかし、私の問題は、Xcode-Swift.hファイルを作成しておらず、ブリッジヘッダーだけが作成されていることです。だから私はそれを作成しましたが、実際は空です。すべてのObjCクラスをSwiftで使用できますが、その逆はできません。私のSwiftクラスに@objcのマークを付けましたが、役に立ちませんでした。今何ができる?

編集:Appleは言う: "あなたがObjective - CにSwiftコードをインポートするとき、あなたはそれらのファイルをObjective - Cに公開するためにXcode-generatedヘッダーファイルに依存しています。 「-Swift.h」

そのファイルをインポートしようとするとエラーになります。

    //MainMenu.m

    #import "myProjectModule-Swift.h" //Error: 'myProjectModule-Swift.h' file not found

    @implementation MainMenu

これが私のFBManager.Swiftファイルです。

@objc class FBManager: NSObject {

    var descr = "FBManager class"

    init() {
        super.init()
    }

    func desc(){
        println(descr)
    }

    func getSharedGameState() -> GameState{
        return GameState.sharedGameState() //OK! GameState is written in Objective-C and no error here
    }
}
241
dnnagy

Swift Objective-CベースのプロジェクトでXcodeを有効にするために約4時間を費やしました。私の "myproject-Swift.h"ファイルは正常に作成されましたが、私のXcodeは私のSwift-classesを見ませんでした。それで、私は新しいXcode Objcベースのプロジェクトを作成することにしました、そしてついに私は正しい答えを見つけました!この投稿が誰かに役立つことを願っています:-)

Xcode Objcベースのプロジェクトのステップバイステップの迅速な統合:

  1. 新しい*.Swiftファイルを(Xcodeで)作成するか、またはFinderを使用して追加します。
  2. Xcodeがそれについて尋ねてきたときにObjective-C bridging headerを作成してください
  3. Swiftクラスを実装します。

    import Foundation
    
    // use @objc or @objcMembers annotation if necessary
    class Foo {
        //..
    }
    
  4. ビルド設定を開き、以下のパラメータを確認してください。

    • モジュールを定義します。 YES

      検索バーにパラメータ名をコピーして貼り付ける

    • 製品モジュール名: myproject

      製品モジュール名に特殊文字が含まれていないことを確認してください。

    • Objective-C互換ヘッダーをインストールします。 YES

      *.Swiftファイルをプロジェクトに追加すると、このプロパティはビルド設定に表示されます。

    • Objective-Cが生成したインタフェースヘッダ: myproject-Swift.h

      このヘッダはXcodeによって自動生成されます

    • Objective-Cブリッジヘッダー: $(SRCROOT)/myproject-Bridging-Header.h
  5. * .mファイルにSwiftインターフェースヘッダーをインポートする

    #import "myproject-Swift.h"
    

    エラーや警告に注意を払わないでください。

  6. Xcodeプロジェクトをクリーンアップして再構築する
  7. 利益!
493
sig

自分でヘッダファイルを作成しないでください。作成したものを削除します。

Swiftクラスが@objcでタグ付けされているか、NSObjectから(直接的または間接的に)派生するクラスから継承していることを確認してください。

プロジェクトにコンパイラエラーがある場合、Xcodeはファイルを生成しません - プロジェクトが正しくビルドされていることを確認してください。

61
Bill

Xcodeに作業を許可します。Swiftヘッダーを手動で追加/作成しないでください。 Swiftクラスの前に@objcを追加するだけです。

@objc class YourSwiftClassName: UIViewController

プロジェクト設定で、以下のフラグを検索し、それをYESに変更します(プロジェクトとターゲットの両方)。

Defines Module : YES
Always Embed Swift Standard Libraries : YES
Install Objective-C Compatibility Header : YES

その後、プロジェクトをクリーンアップして、ビルドが成功した後に1回ビルドします(おそらくはそれを実行する必要があります)。

#import "YourProjectName-Swift.h" 

ブー!

34
Bharat Modi

フレームワークターゲット を持つあなたにとってもおそらく役に立つでしょう。

自動生成されたヘッダファイルの import文 は、 アプリのターゲットとは少し異なる に見えます。他の答えで述べられている他のことに加えて

#import <ProductName/ProductModuleName-Swift.h>

の代わりに

#import "ProductModuleName-Swift.h"

Mix&Match のフレームワークターゲット用のApplesドキュメントのとおり。

27
Dschee

プロジェクトでモジュールが定義されていること、およびモジュールに名前が付けられていることを確認してください。それから再構築すれば、Xcodeは-Swift.hヘッダーファイルを作成し、あなたはインポートすることができるでしょう。

プロジェクト設定でモジュール定義とモジュール名を設定できます。

14
Leo Natan

詳細: Xcode 8.1のSwift 3コードを含むObjective-Cプロジェクト

タスク:

  1. Objective-CクラスでSwift列挙型を使う
  2. Swiftクラスでobject-c enumを使う

フルサンプル

1. Swift enumを使ったObjective-Cクラス

ObjcClass.h

#import <Foundation/Foundation.h>

typedef NS_ENUM(NSInteger, ObjcEnum) {
    ObjcEnumValue1,
    ObjcEnumValue2,
    ObjcEnumValue3
};

@interface ObjcClass : NSObject

+ (void) PrintEnumValues;

@end

ObjcClass.m

#import "ObjcClass.h"
#import "SwiftCode.h"

@implementation ObjcClass

+ (void) PrintEnumValues {
    [self PrintEnumValue:SwiftEnumValue1];
    [self PrintEnumValue:SwiftEnumValue2];
    [self PrintEnumValue:SwiftEnumValue3];
}

+ (void) PrintEnumValue:(SwiftEnum) value {
    switch (value) {
        case SwiftEnumValue1:
            NSLog(@"-- SwiftEnum: SwiftEnumValue1");
            break;

        case SwiftEnumValue2:
        case SwiftEnumValue3:
            NSLog(@"-- SwiftEnum: long value = %ld", (long)value);
            break;
    }
}

@end

Objective-CコードでSwiftコードを検出する

私のサンプルでは、​​Objective-CのSwiftコードを検出するためにSwiftCode.hを使用しています。このファイルは自動的に生成され(私はプロジェクト内でこのヘッダファイルの物理的なコピーを作成しませんでした)、あなたはこのファイルの名前しか設定できません:

enter image description here

enter image description here

コンパイラがヘッダファイルのSwiftコードを見つけられない場合は、プロジェクトをコンパイルしてみてください。

2. Objective-Cのenumを使ったスイフトクラス

import Foundation

@objc
enum SwiftEnum: Int {
    case Value1, Value2, Value3
}

@objc
class SwiftClass: NSObject {

    class func PrintEnumValues() {
        PrintEnumValue(.Value1)
        PrintEnumValue(.Value2)
        PrintEnumValue(.Value3)
    }

    class func PrintEnumValue(value: ObjcEnum) {
        switch value {
        case .Value1, .Value2:
            NSLog("-- ObjcEnum: int value = \(value.rawValue)")

        case .Value3:
            NSLog("-- ObjcEnum: Value3")
            break
        }

    }
}

SwiftコードでObjective-Cコードを検出する

ブリッジングヘッダファイルを作成する必要があります。 Objective-CプロジェクトにSwiftファイルを追加する場合、またはSwiftプロジェクトにObjective-Cファイルを追加する場合は、ブリッジヘッダーを作成することをお勧めします。

enter image description here

ここでブリッジングヘッダファイル名を変更できます。

enter image description here

Bridging-Header.h

#import "ObjcClass.h"

使用法

#import "SwiftCode.h"
...
[ObjcClass PrintEnumValues];
[SwiftClass PrintEnumValues];
[SwiftClass PrintEnumValue:ObjcEnumValue3];

結果

enter image description here


より多くのサンプル

上記の完全積分ステップObjective-cとSwift 。それでは、他のいくつかのコード例を書きます。

3. Objective-CのコードからSwiftクラスを呼び出す

スイフトクラス

import Foundation

@objc
class SwiftClass:NSObject {

    private var _stringValue: String
    var stringValue: String {
        get {
            print("SwiftClass get stringValue")
            return _stringValue
        }
        set {
            print("SwiftClass set stringValue = \(newValue)")
            _stringValue = newValue
        }
    }

    init (stringValue: String) {
        print("SwiftClass init(String)")
        _stringValue = stringValue
    }

    func printValue() {
        print("SwiftClass printValue()")
        print("stringValue = \(_stringValue)")
    }

}

Objective-Cコード(呼び出しコード)

SwiftClass *obj = [[SwiftClass alloc] initWithStringValue: @"Hello World!"];
[obj printValue];
NSString * str = obj.stringValue;
obj.stringValue = @"HeLLo wOrLd!!!";

結果

enter image description here

4. SwiftコードからObjective-cクラスを呼び出す

Objective-Cクラス(ObjcClass.h)

#import <Foundation/Foundation.h>

@interface ObjcClass : NSObject
@property NSString* stringValue;
- (instancetype) initWithStringValue:(NSString*)stringValue;
- (void) printValue;
@end

ObjcClass.m

#import "ObjcClass.h"

@interface ObjcClass()

@property NSString* strValue;

@end

@implementation ObjcClass

- (instancetype) initWithStringValue:(NSString*)stringValue {
    NSLog(@"ObjcClass initWithStringValue");
    _strValue = stringValue;
    return self;
}

- (void) printValue {
    NSLog(@"ObjcClass printValue");
    NSLog(@"stringValue = %@", _strValue);
}

- (NSString*) stringValue {
    NSLog(@"ObjcClass get stringValue");
    return _strValue;
}

- (void) setStringValue:(NSString*)newValue {
    NSLog(@"ObjcClass set stringValue = %@", newValue);
    _strValue = newValue;
}

@end

迅速なコード(呼び出しコード)

if let obj = ObjcClass(stringValue:  "Hello World!") {
    obj.printValue()
    let str = obj.stringValue;
    obj.stringValue = "HeLLo wOrLd!!!";
}

結果

enter image description here

5. Objective-cコードでSwift拡張を使う

迅速な拡張

extension UIView {
    static func swiftExtensionFunc() {
        NSLog("UIView swiftExtensionFunc")
    }
}

Objective-Cコード(呼び出しコード)

[UIView swiftExtensionFunc];

6. SwiftコードでObjective-c拡張子を使う

Objective-Cの拡張機能(UIViewExtension.h)

#import <UIKit/UIKit.h>

@interface UIView (ObjcAdditions)
+ (void)objcExtensionFunc;
@end

UIViewExtension.m

@implementation UIView (ObjcAdditions)
+ (void)objcExtensionFunc {
    NSLog(@"UIView objcExtensionFunc");
}
@end

迅速なコード(呼び出しコード)

UIView.objcExtensionFunc()
13

私は同じ問題を抱えていました、そしてそれはモジュール名の中の特別なシンボルがxcodeによって置き換えられることが判明しました(私の場合ダッシュはアンダースコアになってしまいました)。プロジェクト設定で "module name"をチェックしてあなたのプロジェクトのモジュール名を見つけてください。その後、ModuleName-Swift.hを使用するか、設定でモジュールの名前を変更してください。

11
Max Mikheyenko

ファイルは自動的に作成されます(ここでXcode 6.3.2について話しています)。それはあなたの派生データフォルダーにあるので、あなたはそれを見ることができません。 Swiftクラスを@objcでマークしたら、コンパイルしてからDerived DataフォルダでSwift.hを検索します。あなたはそこにSwiftヘッダを見つけるべきです。

私は問題を抱えていました、Xcodeが私のmy-Project-Swift.hmy_Project-Swift.h Xcodeに改名したのは"." "-"などのシンボルが好きではなかったということです。上記の方法でファイル名を見つけてそれをObjective-Cクラスにインポートすることができます。

9
brainray

.mまたは.hファイルに#import "myProject-Swift.h"を含めるだけです。

P.S。ファイルインスペクタに "myProject-Swift.h"は隠れています。しかし、それはアプリによって自動的に生成されます。

8
Svitlana

@sigの答えは最も良いものの1つですが、古いプロジェクトではうまくいきませんでした(新しいものではありません!)たくさんのバリエーションの後、私は私のためのレシピを見つけました(XCode 7.2を使って):

  1. 商品モジュール名:$(PRODUCT_NAME:c99extidentifier)
  2. モジュールを定義します:NO
  3. 埋め込みコンテンツにSwiftが含まれる:NO
  4. Objective-C互換ヘッダーをインストールする:YES
  5. Objective-Cブリッジヘッダ:ProjectName-Bridging-Header.h

最後のポイント(5)が非常に重要でした。 2番目のセクション(Targetsフィールド)にのみ置いています。Projectフィールドは空のままにしてください: enter image description here そうでなければ、それは私にとって正しい "Project-Swift.h"ファイルを生成しませんでした(それはSwiftメソッドを含みませんでした)。

4

2つの条件があります、

  • Objective CファイルでSwiftファイルを使用してください。
  • SwiftファイルでObjective Cファイルを使用してください。

だから、そのためには、この手順に従う必要があります:

  • SwiftファイルをObjective-Cプロジェクトまたはその逆に追加します。
  • ヘッダー(.h)ファイルを作成します。
  • ビルド設定 に移動し、検索で以下の手順を実行します。

    1. このテキスト "brid"を検索して、あなたのヘッダファイルのパスを設定してください。
    2. "モジュールの定義":YES。
    3. "常に標準ライブラリを埋め込む":はい。
    4. "Objective-C互換ヘッダーをインストールする":はい。

その後、プロジェクトをクリーンアップして再構築します。

Objective CファイルでSwiftファイルを使用してください。

その場合は、まずSwiftファイルのクラスの前に "@objc"を書き込みます。

その後、Objective Cのファイルに、

  #import "YourProjectName-Swift.h"

SwiftファイルでObjective Cファイルを使用してください。

その場合は、ヘッダファイルに次のように書きます。

  #import "YourObjective-c_FileName.h"

これがお役に立てば幸いです。

4
vikas prajapati

私の場合は、これらのステップとは別に:

  1. 製品モジュール名:myproject
  2. モジュールを定義します:YES
  3. 埋め込みコンテンツにSwiftが含まれる:YES
  4. Objective-C互換ヘッダーをインストールする:YES
  5. Objective-Cブリッジングヘッダ:$(SRCROOT)/ Sources/SwiftBridging.h

productName-Swift.h fileを作成するには、クラスを public にする必要があります。

import UIKit

   @objc public class TestSwift: NSObject {
       func sayHello() {
          print("Hi there!")
       }
   }
3

私は同じ問題を抱えていましたが、ついにそれらは同じターゲットにアタッチされていないようでした。 ObjCクラスはTarget1とTarget2に接続されています。SwiftクラスはTarget1にのみ接続されており、ObjCクラス内には表示されません。

これが誰かに役立つことを願っています。

2
Dani.Rangelov

プロジェクトにSwiftファイルのディレクトリを追加してもうまくいかないことを発見しました。最初にディレクトリ用のグループを作成してからSwiftファイルを追加する必要があります。

2
Darren Ehlers

Objective-CでSwiftクラスを使用する

アプリターゲット内にコードをインポートする場合(1つのプロジェクトでObjective-CとSwiftを混合)、次のインポート行#import "<#YourProjectName#>-Swift.h"を使用してSwiftコードを公開する必要がありますObjective-Cコードへ [プロジェクトでのSwiftとObjective-Cコードの混合]

この投稿では、Swift静的ライブラリをObjective-Cコードにインポートする方法について説明します

Objective-Cコンシューマ-> Swift静的ライブラリ

Xcodeバージョン10.2.1

Swift静的ライブラリを作成します

ライブラリプロジェクトを作成するか、ライブラリターゲットを作成します

File -> New -> Project... -> Cocoa Touch Static Library
//or
Project editor -> Add a Target -> Cocoa Touch Static Library 

ファイルを追加.Swift

Select `.Swift` file -> Select File Inspectors Tab -> Target Membership -> Select the target
//or
Project editor -> select a target -> Build Phases -> Compile Sources -> add files

Swift AP​​Iを公開します。 Objective-CからSwiftの関数を使用するには [約]

ビルドライブラリ- ⌘ Command + B またはProduct -> Build

注:クライアントコードと同じプロセスアーキテクチャのライブラリをビルドしてください。

生成された出力を見つける [ビルド場所]

Products group -> lib<product_name>.a -> Show in Finder

ディレクトリに含まれるもの

  • lib<product_name>.a –構築された静的ライブラリ
  • <product_name>.swiftmoduleフォルダーには以下が含まれます。
    • .swiftdoc-ドキュメント
    • .swiftmodule-パブリックインターフェイス/定義

また、DerivedSourcesに配置する必要がある<product_name>-Swift.hファイルを見つける必要があります [ファイルが見つかりません]

Swift静的ライブラリの使用

Drag and drop Xcodeプロジェクトへのバイナリ [約]

Link Library[未定義のシンボル][リンクと埋め込み]

Project editor -> select a target -> General -> Linked Frameworks and Libraries -> add -> Add Others... -> point to `lib<product_name>.a` file
//or
Project editor -> select a target -> Build Phases -> Link Binary With Libraries -> add -> Add Others... -> point to `lib<product_name>.a` file

Library Search paths[ライブラリが見つかりません][再帰パス]

Project editor -> select a target -> Build Settings -> Search Paths -> Library Search paths -> add path to the parent of `lib<product_name>.a` file

Header Search Paths[モジュールが見つかりません][再帰パス]

Project editor -> select a target -> Build Settings -> Search Paths -> Header Search Paths -> add path to generated `<product_name>-Swift.h` file 

空の.Swift fileをObjective-Cプロジェクトに追加します。 [未定義のシンボル] XcodeがBridging Header(Create module_name-Bridging-Header.hを作成します)を押して作成を要求するとき、このファイルへのパスを設定します

Project editor -> select a target -> Build Settings -> Swift Compiler - General -> Objective-C Bridging Header

Objective-Cクライアントコードへのモジュールのインポート [ファイルが見つかりません] [モジュール名]

#import "module_name-Swift.h"

その他の例はこちら

1
yoAlex5

Swift 5の場合:

  1. クラスとメソッドに@objcキーワードを追加します。
  2. クラスとメソッドにpublicキーワードを追加する
  3. あなたのクラスがNSObjectから継承するようにしましょう
  4. プロジェクトを構築
  5. Objective-Cファイルに#import "MyProject-Swift.h"を入れてください

    @objc
    public class MyClass: NSObject {
    
        @objc
        public func myMethod() {
    
        }
    }
    
0
Nico S.

Objective-Cブリッジングヘッダにクラスを追加するという問題があり、インポートされたObjective-CヘッダではSwiftヘッダをインポートしようとしていました。それは好きではありませんでした。

したがって、Swiftを使用していてもブリッジされているすべてのObjective-Cクラスで重要なのは、ヘッダーで前方クラス宣言を使用し、次に "* - Swift.h"ファイルを.mファイルにインポートすることです。

0
horseshoe7

ビルドの設定を変更したり、クラスに@objを追加したりする必要はありませんでした。

私がしなければならなかったのは、SwiftクラスをObjective-cプロジェクトに作成したときに自動的に作成されたブリッジヘッダを作成することだけでした。それから私はしなければならなかった

import "Bedtime-Swift.h" < - そのSwiftファイルを使用するために必要なObjective-Cファイル内。

0
coolcool1994

新しいSwiftファイルをプロジェクトに追加するときは、正しいターゲットに追加するようにしてください。使用するすべてのSwiftファイルがNSObjectクラスを継承し、オプションALWAYS_EMBED_Swift_STANDARD_LIBRARIESの下のビルド設定内で@ObjCMembers Changeに注釈が付けられていることを確認してください。オプションDEFINES_MODULEの下のビルド設定内でYESに変更します。

0
Boris

私の問題は、xcodeがブリッジファイルを作成した後に動かなくなったことですが、それでもヘッダーファイル名MYPROJECTNAME-Swift.hにエラーが発生しました。

1.端末をチェックインし、自動作成されたすべてのSwift bridgeファイルを検索します。

find ~/library/Developer/Xcode/DerivedData/ -name "*-Swift.h"|xargs basename|sort -

あなたはxcodeが作成したものを見ます。

  1. 私の場合は、プロジェクト名とxcodeの代わりにスペースを使用しています。これは '_'です。
0
user1105951

私の問題は、-Swift.hファイルの自動生成がCustomDebugStringConvertibleのサブクラスを理解できなかったことです。代わりにclassをNSObjectのサブクラスに変更しました。その後、-Swift.hファイルにクラスが正しくインクルードされました。

0
Justin Domnitz

すべてのコメントを読み、もう一度読んでからもう一度試してみると、Big obj-cプロジェクトにSwiftクラスを含めることができました。だから、すべての助けをありがとう。私は私がプロセスをよりよく理解するのを助けた1つの先端を共有したかったです。 .mクラスで、Swiftターゲット名#import "myTargetName-Swift.h"のインポート行に移動して、キーをクリックしました。

command +マウスクリック - >定義へジャンプ enter image description here

Swiftからobj-cへのすべての変換を見ることができ、そこにはさまざまな関数がobj-cで再宣言されています。この助言がそれが私を助けたのと同じくらいあなたを助けることを願っています。

0
Techno Mag

同じエラーがあります:myProjectModule-Swift.hファイルが見つかりません "が、私の場合、本当の理由はデプロイメントターゲットが間違っていたためです:" Swiftは10.9より前のOS Xでは使用できません。 MACOSX_DEPLOYMENT_TARGETを10.9以降に設定してください(現在は '10。7'です) "ので、デプロイメントターゲットを10.9に変更すると、プロジェクトは正常にコンパイルされました。

0
slavik