57638


Swift5で開発をしているのですが、既存のobjective-cソースを混在させて、データを共有したり、相互にメソッドコールをしたいです。  
そこで教えて頂きたい質問が3点あります。

  1. データ共有する場合は、どの方法がよいのでしょうか？ 
    1. AppDelegate.swiftに変数をおく
    2. AppDelegate.swiftに共有クラス（シングルトン？）を作る
    3. 共有用のクラス（新規ファイル）を作る
  2. Objective-cからSwiftメソッド（引数あり）がコール出来ませんでした。  
引数なしだとコール出来ました。  
抜粋になりますが、下記の感じです。

sampleSwift.swift

[code]

        @objc func test1(string:String)
        {
            print(string)
        }
        @objc func test2()
        {
             print("test2")
        }
    
[/code]

sampleObj.m

[code]

        sampleSwift * obj = [sampleSwift alloc];
        [sampleSwift test1:@"abc"]; // NG
        [sampleSwift test2]; // OK
    
[/code]

NGの所は、「`NO Visible @interface for 'sampleSwift' declares the selector
'test1:string:'`」  
と赤メッセージ表示が出ます。

  3. swiftのほうにある配列に、Objective-c側のメソッドからセットしたいのですが  
（１の共有にもからむのですが）、swiftで共有の配列変数として定義しても  
Objective-cでは配列の定義が違うため、共有変数にセット出来ませんでした。

swiftで共有定義

[code]

    　　var hairetu:[Int] = [] // 共有定義と仮定して・・・
    
[/code]

objective-c側で

[code]

    　　hairetu.append(1)
    
[/code]

のように追加したいのですが、可能でしょうか？  
直接が難しい場合は、質問２に戻りますが、引数で渡せるようになれば  
それでも良いのですが、もっと効率的に出来る方法があれば助かります。

ご教授のほど、よろしくお願いいたします。


CC BY-SA 4.0
2019-08-27T07:29:57.210
57633
2019-08-27T11:43:42.740
2019-08-27T09:32:53.093
3068
35619
question
swift objective-c
swiftとobjective-c混在プロジェクトについて


ご掲載のコードにはおかしいところがあるので、ご質問用に適当に作られたものでしょうか?
プログラミングでは、たった1文字の違いでも動作が全く変わってくるわけですから、ご質問を書かれるにあたって簡略化する場合でも、必ずプロジェクトを作成し、(「同じエラーが起こる」と言った)動作が確認されたコードを修正せずにご掲載された方が、正しい回答をより早く得ることにつながります。

ここでは、Command Line Toolプロジェクトで確認してもらう前提で回答させていただきます。

main.swift:

[code]

    import Foundation
    
    @objc class SampleSwift: NSObject {
        @objc func test1(string:String)
        {
            print(string)
        }
        @objc func test2()
        {
            print("test2")
        }
    }
    
[/code]

(Swiftのクラス名は大文字で始めます。非常によく守られている慣習ですので、無視されるとコードが極めて読みにくくなってしまいます。あなたのObjective-
Cのコードでクラス名とインスタンス名がごっちゃになっているのも、そう言った習慣が身についていれば防げたはずです。

MyClass.h:

[code]

    #import <Foundation/Foundation.h>
    
    NS_ASSUME_NONNULL_BEGIN
    
    @interface MyClass : NSObject
    
    @end
    
    NS_ASSUME_NONNULL_END
    
[/code]

(Cocoa Classの作成を実行して、できた.hファイルそのまま。)

MyClass.m:

[code]

    #import "MyClass.h"
    
    #import "{MyProjectName}-Swift.h"
    
    @implementation MyClass
    
    @end
    
[/code]

SwiftのクラスをObjctive-
Cから使用するためのimport行を追加してあります。簡単な例では成功しているので、ご自分の場合どう書けば良いかはお分かりかと思います。

一度ビルドを成功させた後で、このimport行の上でCmd-Clickし、ポップアップからJump to
Definitionを選ぶと、内容が表示されます。(他にもやり方はあります。)

{MyProjectName}-Swift.h:

[code]

    (略)
    @interface SampleSwift : NSObject
    - (void)test1WithString:(NSString * _Nonnull)string;
    - (void)test2;
    - (nonnull instancetype)init OBJC_DESIGNATED_INITIALIZER;
    @end
    (略)
    
[/code]

Swift側の`test1(string:)`メソッドが、Objective-
C側では`test1WithString:`というセレクタになっていることがわかるでしょうか?

* * *

一般にSwiftの`methodName(label1:label2:)`メソッドは、Objective-
C側に移出された時に、`methodNameWithLabel1:label2:`と言うセレクタになります。いろいろ特別ルールが適用される場合もあるので、正確には上記の方法などで`...-Swift.h`ファイルの中身を確認してください。

と言うわけで、ご質問2の回答としては、「Objective-C側の正しいセレクタを使えば呼び出せるはず」と言うことになります。

[code]

    - (void)test {
        SampleSwift *sample = [[SampleSwift alloc] init];
        [sample test1WithString:@"abc"];
        [sample test2];
    }
    
[/code]

* * *

質問３についてですが、プロパティにも`@objc`を付けてみてください。Objective-Cに持っていけないものにはエラーが出ます。

[code]

    @objc class SampleSwift: NSObject {
    
        @objc var hairetu:[Int] = []
    
        @objc func test1(string:String)
        {
            print(string)
        }
        @objc func test2()
        {
            print("test2")
        }
    }
    
[/code]

この場合エラーは出ず、Objective-C側ではこんな風になります。

[code]

    @interface SampleSwift : NSObject
    @property (nonatomic, copy) NSArray<NSNumber *> * _Nonnull hairetu;
    - (void)test1WithString:(NSString * _Nonnull)string;
    - (void)test2;
    - (nonnull instancetype)init OBJC_DESIGNATED_INITIALIZER;
    @end
    
[/code]

SwiftのArrayをObjective-Cに持っていくと(Swift側は`var`であっても)Objective-
C側では中身の変更ができない`NSArray`型になってしまいます。Objective-C側で配列の操作をしたい場合には、Objective-
Cから利用できるようなメソッドを定義してやった方が良いでしょう。

[code]

        @objc func appendHairetu(_ value: Int) {
            hairetu.append(value)
        }
    
[/code]

[code]

        [sample appendHairetu:123];
    
[/code]

* * *

ご質問１については、特にSwiftとObjective-
Cを混在させるプロジェクトに限った話ではありませんので、回答は控えておきます。Swiftオンリーのプロジェクトなら、複数のクラスから参照されるデータをどのような方法で作られてきたのでしょうか?


CC BY-SA 4.0
2019-08-27T11:43:42.740
57638
2019-08-27T11:43:42.740
13972
57633
answer