ios - 呼び出し - swift objective-c 混在




Objective-Cの内部でSwiftクラスを使用することはできません (14)

私は私のアプリにObjective-C書かれたSwiftコードを統合しようとしました。私はSwiftクラスを追加しました。 私はhere説明しhereすべてをやっhere 。 しかし、私の問題は、 Xcode-Swift.hファイルを作成しておらず、ブリッジヘッダーだけであることです。 だから私はそれを作成しましたが、実際には空です。 私はSwiftのすべてのObjCクラスを使うことができますが、私はそれを行うことはできません。 私は@objc素早くクラスをマークし@objcが、それは助けになりませんでした。 私は今何をすることができますか?

EDIT:アップルはこう言います:「SwiftコードをObjective-Cにインポートすると、 Xcode-generatedヘッダーファイルを使ってObjective-Cにファイルを公開します。[...]このヘッダーの名前は、 "-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
    }
}

.mファイルまたは.hファイルに#import "myProject-Swift.h"を含めてください

PSあなたは隠されているファイルインスペクターで "myProject-Swift.h"を見つけられません。 しかし、それは自動的にアプリによって生成されます。


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

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

最後のポイント(5)が重要でした。 私はそれを2番目のセクション(ターゲットフィールド)にだけ置くと、プロジェクトフィールドは空のままにしておかなければなりません: さもなければ、それは私のために正しい "Project-Swift.h"ファイルを生成しませんでした(それは迅速な方法を含んでいませんでした)。


2つの条件がありますが、

  • 目的のCファイルでスウィフトファイルを使用します。
  • あなたの目的のCファイルを迅速なファイルで使用してください。

そのためには、この手順に従わなければなりません:

  • 迅速なファイルをObjective-Cプロジェクトに追加するか、その逆もできます。
  • ヘッダー(.h)ファイルを作成します。
  • [ビルド設定]に移動し、以下の手順を検索、

    1. このテキスト "brid"を検索し、ヘッダファイルのパスを設定します。
    2. "Defines Module":はい。
    3. 「Swift Standard Librariesを常に埋め込む」:はい。
    4. "Objective-C互換性ヘッダーのインストール":はい。

その後、プロジェクトをきれいにして再構築します。

目的のCファイルでスウィフトファイルを使用します。

その場合は、クラスの前にまず "@objc"と入力してください。

その後、あなたの目的のCファイルで、これを書いて、

  #import "YourProjectName-Swift.h"

あなたの目的のCファイルを迅速なファイルで使用してください。

その場合、ヘッダーファイルに次のように記述します。

  #import "YourObjective-c_FileName.h"

これがあなたに役立つことを願っています。


詳細: Xcode 8.1でSwift 3コードを使用したObjective-Cプロジェクト

タスク:

  1. 高速なenumをobjective-cクラスで使用する
  2. 高速クラスでobjective-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コードを検出する

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

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

2. Objective-C enumを使用するSwiftクラス

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ファイルを追加したり、迅速なプロジェクトにObjective-Cファイルを追加すると、Xcodeはブリッジヘッダーを作成するように指示します。

ここでは、ブリッジヘッダーファイル名を変更することができます:

Bridging-Header.h

#import "ObjcClass.h"

使用法

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

結果

その他のサンプル

上で説明した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)")
    }

}

客観的なCコード(呼び出しコード)

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

結果

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!!!";
}

結果

5. Objective-cコードでSwift拡張を使用する

スウィフトエクステンション

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

客観的なCコード(呼び出しコード)

[UIView swiftExtensionFunc];

6.スウィフトコードで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()

また、おそらくFrameworkターゲットのあなたのために役立ちます:

自動生成されたヘッダーファイルのimportステートメントは、アプリターゲットとは少し違って見えます。 他の答えに記載されている他のものに加えて、

#import <ProductName/ProductModuleName-Swift.h>

の代わりに

#import "ProductModuleName-Swift.h"

フレームワークターゲットのためのMix&Matchに関するApplesのドキュメントを参照してください。


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

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


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

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

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


上記のすべてを行った後、私はまだエラーがあります。 私の問題は、必要なSwiftファイルが何らかの理由でバンドルリソースに追加されていないということでした。

[MyTarget]> [ビルド段階]> [バンドルリソースのコピー]に移動し、プラスボタンをクリックしてSwiftファイルを追加することで修正しました。


私の問題は、xcodeがブリッジファイルを作成した後もスタックしてしまったが、ヘッダファイル名MYPROJECTNAME-swift.hにエラーがある

1.ターミナルをチェックインし、自動作成されたすべてのスウィフトブリッジファイルを検索します。

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

あなたはxcodeが作成したものを見ることができます。

  1. 私の場合、プロジェクト名にスペースがあり、xcodeはこれを '_'に置き換えます

私の場合は、次のステップを除いて:

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

productName-Swift.hファイルを作成するために、クラスを公開する必要がありました。

import UIKit

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

私は、私が目的のcブリッジヘッダーにクラスを追加するという点で問題があり、インポートされた目的のcヘッダーでは、迅速なヘッダーをインポートしようとしていました。 それはそれを好まなかった。

だから、すべての私の目的クラスでは、クラスを迅速に使用されますが、またブリッジされ、キーは、ヘッダーで前方クラス宣言を使用して、 "* -Swift.h"ファイルを.mファイルにインポートすることを確認することでした。


私はちょうどプロジェクトに迅速なファイルのディレクトリを追加することは動作しないことを発見した。 最初にディレクトリのグループを作成してから、スワイプファイルを追加する必要があります...


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


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





swift