LoginSignup
4
4

More than 5 years have passed since last update.

Objective-cのNSMutableArrayとNSMutableDictionaryをSwiftで使う際にはまったこと

Posted at

前提

Swiftではこのメソッドが呼び出したい。

func hoge(object: [String: AnyObject?]) {
}

Objective-cではこんな定義されているメソッド/プロパティを呼び出したい。
(気づく人は気づくかもしれませんが、TiledMap関連のコードです。。。)

@interface CCTiledMapObjectGroup : NSObject

@property (nonatomic,readwrite,strong) NSMutableArray *objects;
-(NSMutableDictionary*) objectNamed:(NSString *)objectName;

@end

NSMutableArray

これでいけそう・・・

let group = CCTiledMapObjectGroup()   // ※実際はこんな感じでインスタンスを作ることは出来ないないクラス。(例として記載)
for object in group.objects {
    hoge(object as! [String: AnyObject?])
}

コンパイルは通るが、実行時に以下のエラーが出力される。

Could not cast value of type '__NSDictionaryM' (0x799fa80c) to 'Swift.Dictionary<Swift.String, Swift.Optional<Swift.AnyObject>>' (0x7d4bf16c).

ということで、以下のメソッドでは受け取れないことがわかった。

func hoge(object: [String: AnyObject?]) {
}

なので指示通りSwift側のメソッドのAnyObject?→AnyObjectに変更。

let group = CCTiledMapObjectGroup()   // ※実際はこんな感じでインスタンスを作ることは出来ないないクラス。(例として記載)
for object in group.objects {
    hoge(object as! [String: AnyObject])
}

func hoge(object: [String: AnyObject]) {
}

いけた!

NSMutableDictionary

で、NSMutableDictionary。
NSMutableArrayができたのでハマることは無いと思っていた。
なぜならObjective-cで取得するobjectsの中身をピンポイントで取得する以下のobjectNamedを呼び出すだけですから。

@interface CCTiledMapObjectGroup : NSObject

-(NSMutableDictionary*) objectNamed:(NSString *)objectName;

@end

これを以下のように取り出そうとした。

let group = CCTiledMapObjectGroup()   // ※実際はこんな感じでインスタンスを作ることは出来ないないクラス。(例として記載)
if let object = group.objectNamed("name") {
    hoge(object as! [String: AnyObject])
}

まさかのコンパイルエラー・・・

Cannot invoke 'hoge' with an argument list of type '([String : AnyObject])'

これではダメなのでAnyObject?へ元に戻してみた。
(このメソッドは上記のNSMutableArrayと共通で使うので、この例はダメなのだが検証のためやってみる。)

let group = CCTiledMapObjectGroup()
if let object = group.objectNamed("name") {
    hoge(object as! [String: AnyObject?])
}

func hoge(object: [String: AnyObject?]) {
}

なんか、どっかで見たような警告文が表示されている・・・。

Cast from 'NSMutableDictionary' to unrelated type '[String : AnyObject?]' always fails

構わず実行!

Could not cast value of type 'NSMutableDictionary' (0x7fcd189c) to 'Swift.Dictionary<Swift.String, Swift.Optional<Swift.AnyObject>>' (0x7fcd176c).

まぁ、当然の結果。
うーん。とりあえず、以下のコードで出来たがなぞが残る。

let group = CCTiledMapObjectGroup()
if let object:NSDictionary = group.objectNamed("name") {
    hoge(object as! [String: AnyObject])
}

func hoge(object: [String: AnyObject]) {
}

NSMutableDictionaryだとダメな模様。
NSDictionaryとして処理をさせればNSMutableArrayのところと同じようにキャストができる。

はじめはletの定義がダメなのかと思ってvarに変えてみたりしたけど、、、関係ないみたい。

まとめ

SwiftからObjective-cのコードを呼び出すことは多々あるかと思います。
こういうケースに引っかかる人の役に立てればと思います。

4
4
3

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
4