私は自分のアプリに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
}
}
Swift
Objective-CベースのプロジェクトでXcode
を有効にするために約4時間を費やしました。私の "myproject-Swift.h
"ファイルは正常に作成されましたが、私のXcode
は私のSwift-classes
を見ませんでした。それで、私は新しいXcode
Objcベースのプロジェクトを作成することにしました、そしてついに私は正しい答えを見つけました!この投稿が誰かに役立つことを願っています:-)
*.Swift
ファイルを(Xcodeで)作成するか、またはFinderを使用して追加します。Objective-C bridging header
を作成してくださいSwiftクラスを実装します。
import Foundation
// use @objc or @objcMembers annotation if necessary
class Foo {
//..
}
ビルド設定を開き、以下のパラメータを確認してください。
YES
検索バーにパラメータ名をコピーして貼り付ける
myproject
製品モジュール名に特殊文字が含まれていないことを確認してください。
YES
*.Swift
ファイルをプロジェクトに追加すると、このプロパティはビルド設定に表示されます。
myproject-Swift.h
このヘッダはXcodeによって自動生成されます
$(SRCROOT)/myproject-Bridging-Header.h
* .mファイルにSwiftインターフェースヘッダーをインポートする
#import "myproject-Swift.h"
エラーや警告に注意を払わないでください。
自分でヘッダファイルを作成しないでください。作成したものを削除します。
Swiftクラスが@objc
でタグ付けされているか、NSObject
から(直接的または間接的に)派生するクラスから継承していることを確認してください。
プロジェクトにコンパイラエラーがある場合、Xcodeはファイルを生成しません - プロジェクトが正しくビルドされていることを確認してください。
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"
ブー!
フレームワークターゲット を持つあなたにとってもおそらく役に立つでしょう。
自動生成されたヘッダファイルの import文 は、 アプリのターゲットとは少し異なる に見えます。他の答えで述べられている他のことに加えて
#import <ProductName/ProductModuleName-Swift.h>
の代わりに
#import "ProductModuleName-Swift.h"
Mix&Match のフレームワークターゲット用のApplesドキュメントのとおり。
プロジェクトでモジュールが定義されていること、およびモジュールに名前が付けられていることを確認してください。それから再構築すれば、Xcodeは-Swift.h
ヘッダーファイルを作成し、あなたはインポートすることができるでしょう。
プロジェクト設定でモジュール定義とモジュール名を設定できます。
詳細: Xcode 8.1のSwift 3コードを含む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を使用しています。このファイルは自動的に生成され(私はプロジェクト内でこのヘッダファイルの物理的なコピーを作成しませんでした)、あなたはこのファイルの名前しか設定できません:
コンパイラがヘッダファイルの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
}
}
}
ブリッジングヘッダファイルを作成する必要があります。 Objective-CプロジェクトにSwiftファイルを追加する場合、またはSwiftプロジェクトにObjective-Cファイルを追加する場合は、ブリッジヘッダーを作成することをお勧めします。
ここでブリッジングヘッダファイル名を変更できます。
Bridging-Header.h
#import "ObjcClass.h"
#import "SwiftCode.h"
...
[ObjcClass PrintEnumValues];
[SwiftClass PrintEnumValues];
[SwiftClass PrintEnumValue:ObjcEnumValue3];
上記の完全積分ステップ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!!!";
結果
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!!!";
}
結果
迅速な拡張
extension UIView {
static func swiftExtensionFunc() {
NSLog("UIView swiftExtensionFunc")
}
}
Objective-Cコード(呼び出しコード)
[UIView swiftExtensionFunc];
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()
私は同じ問題を抱えていました、そしてそれはモジュール名の中の特別なシンボルがxcodeによって置き換えられることが判明しました(私の場合ダッシュはアンダースコアになってしまいました)。プロジェクト設定で "module name"をチェックしてあなたのプロジェクトのモジュール名を見つけてください。その後、ModuleName-Swift.h
を使用するか、設定でモジュールの名前を変更してください。
ファイルは自動的に作成されます(ここでXcode 6.3.2について話しています)。それはあなたの派生データフォルダーにあるので、あなたはそれを見ることができません。 Swiftクラスを@objc
でマークしたら、コンパイルしてからDerived DataフォルダでSwift.h
を検索します。あなたはそこにSwiftヘッダを見つけるべきです。
私は問題を抱えていました、Xcodeが私のmy-Project-Swift.h
をmy_Project-Swift.h
Xcodeに改名したのは"." "-"
などのシンボルが好きではなかったということです。上記の方法でファイル名を見つけてそれをObjective-Cクラスにインポートすることができます。
.mまたは.hファイルに#import "myProject-Swift.h"を含めるだけです。
P.S。ファイルインスペクタに "myProject-Swift.h"は隠れています。しかし、それはアプリによって自動的に生成されます。
@sigの答えは最も良いものの1つですが、古いプロジェクトではうまくいきませんでした(新しいものではありません!)たくさんのバリエーションの後、私は私のためのレシピを見つけました(XCode 7.2を使って):
最後のポイント(5)が非常に重要でした。 2番目のセクション(Targetsフィールド)にのみ置いています。Projectフィールドは空のままにしてください: そうでなければ、それは私にとって正しい "Project-Swift.h"ファイルを生成しませんでした(それはSwiftメソッドを含みませんでした)。
2つの条件があります、
だから、そのためには、この手順に従う必要があります:
ビルド設定 に移動し、検索で以下の手順を実行します。
その後、プロジェクトをクリーンアップして再構築します。
その場合は、まずSwiftファイルのクラスの前に "@objc"を書き込みます。
その後、Objective Cのファイルに、
#import "YourProjectName-Swift.h"
その場合は、ヘッダファイルに次のように書きます。
#import "YourObjective-c_FileName.h"
これがお役に立てば幸いです。
私の場合は、これらのステップとは別に:
productName-Swift.h fileを作成するには、クラスを public にする必要があります。
import UIKit
@objc public class TestSwift: NSObject {
func sayHello() {
print("Hi there!")
}
}
私は同じ問題を抱えていましたが、ついにそれらは同じターゲットにアタッチされていないようでした。 ObjCクラスはTarget1とTarget2に接続されています。SwiftクラスはTarget1にのみ接続されており、ObjCクラス内には表示されません。
これが誰かに役立つことを願っています。
プロジェクトにSwiftファイルのディレクトリを追加してもうまくいかないことを発見しました。最初にディレクトリ用のグループを作成してからSwiftファイルを追加する必要があります。
Objective-CでSwiftクラスを使用する
アプリターゲット内にコードをインポートする場合(1つのプロジェクトでObjective-CとSwiftを混合)、次のインポート行#import "<#YourProjectName#>-Swift.h"
を使用してSwiftコードを公開する必要がありますObjective-Cコードへ [プロジェクトでのSwiftとObjective-Cコードの混合]
この投稿では、Swift静的ライブラリをObjective-Cコードにインポートする方法について説明します
Xcodeバージョン10.2.1
ライブラリプロジェクトを作成するか、ライブラリターゲットを作成します
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 APIを公開します。 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
ファイルを見つける必要があります [ファイルが見つかりません]
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"
Swift 5の場合:
@objc
キーワードを追加します。public
キーワードを追加するNSObject
から継承するようにしましょうObjective-Cファイルに#import "MyProject-Swift.h"
を入れてください
@objc
public class MyClass: NSObject {
@objc
public func myMethod() {
}
}
Objective-Cブリッジングヘッダにクラスを追加するという問題があり、インポートされたObjective-CヘッダではSwiftヘッダをインポートしようとしていました。それは好きではありませんでした。
したがって、Swiftを使用していてもブリッジされているすべてのObjective-Cクラスで重要なのは、ヘッダーで前方クラス宣言を使用し、次に "* - Swift.h"ファイルを.mファイルにインポートすることです。
ビルドの設定を変更したり、クラスに@objを追加したりする必要はありませんでした。
私がしなければならなかったのは、SwiftクラスをObjective-cプロジェクトに作成したときに自動的に作成されたブリッジヘッダを作成することだけでした。それから私はしなければならなかった
新しいSwiftファイルをプロジェクトに追加するときは、正しいターゲットに追加するようにしてください。使用するすべてのSwiftファイルがNSObjectクラスを継承し、オプションALWAYS_EMBED_Swift_STANDARD_LIBRARIESの下のビルド設定内で@ObjCMembers Changeに注釈が付けられていることを確認してください。オプションDEFINES_MODULEの下のビルド設定内でYESに変更します。
私の問題は、xcodeがブリッジファイルを作成した後に動かなくなったことですが、それでもヘッダーファイル名MYPROJECTNAME-Swift.hにエラーが発生しました。
1.端末をチェックインし、自動作成されたすべてのSwift bridgeファイルを検索します。
find ~/library/Developer/Xcode/DerivedData/ -name "*-Swift.h"|xargs basename|sort -
あなたはxcodeが作成したものを見ます。
私の問題は、-Swift.hファイルの自動生成がCustomDebugStringConvertibleのサブクラスを理解できなかったことです。代わりにclassをNSObjectのサブクラスに変更しました。その後、-Swift.hファイルにクラスが正しくインクルードされました。
すべてのコメントを読み、もう一度読んでからもう一度試してみると、Big obj-cプロジェクトにSwiftクラスを含めることができました。だから、すべての助けをありがとう。私は私がプロセスをよりよく理解するのを助けた1つの先端を共有したかったです。 .mクラスで、Swiftターゲット名#import "myTargetName-Swift.h"のインポート行に移動して、キーをクリックしました。
Swiftからobj-cへのすべての変換を見ることができ、そこにはさまざまな関数がobj-cで再宣言されています。この助言がそれが私を助けたのと同じくらいあなたを助けることを願っています。
同じエラーがあります:myProjectModule-Swift.h
ファイルが見つかりません "が、私の場合、本当の理由はデプロイメントターゲットが間違っていたためです:" Swift
は10.9より前のOS Xでは使用できません。 MACOSX_DEPLOYMENT_TARGET
を10.9以降に設定してください(現在は '10。7'です) "ので、デプロイメントターゲットを10.9に変更すると、プロジェクトは正常にコンパイルされました。