0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

Objective-Cクラスを継承したSwiftクラスで、継承元のメンバ変数を扱う方法

Posted at

はじめに

古くから存在するアプリでは、Objective-CとSwiftが共存していることがよくあります。はじめはObjective-Cで作られ、Swiftが発表された後はSwiftで作っている、というパターンですね。こういったアプリでは、Objective-Cで書かれたクラスをSwiftで継承する、という実装を行う場面が出てくると思います。そのときのメンバ変数の取り扱いで少し手間取ったので、備忘録として残します。

サンプルファイル

以下に、この記事で扱うファイルを記載します。

継承元のObjective-Cファイル

継承元のクラスが書かれたファイルは以下であるとします。

SampleParentViewController.h
 
#import <UIKit/UIKit.h>

@protocol SampleDelegate

- (void) delegateMethod;

@end

@interface SampleParentViewController: UIViewController {
    id<SampleDelegate> sampleDelegate;
}

- (instancetype)initWithDelegate:(id<SampleDelegate>)delegate;

@end
SampleParentViewController.m
 
#import "SampleParentViewController.h"

@implementation SampleParentViewController

- (instancetype)initWithDelegate:(id<SampleDelegate>)delegate
{
    self = [super init];
    if (self) {
        sampleDelegate = delegate;
    }
    return self;
}

- (void)viewDidLoad {
    [super viewDidLoad];
    [sampleDelegate delegateMethod];
}

@end

継承先のSwiftファイル

以下のように、継承するクラスをSwiftで書いたとします。

SampleChildViewController.swift
import UIKit

class SampleChildViewController: SampleParentViewController {
    
    let otherViewController: SampleDelegate = OtherViewController()

    override func viewDidLoad() {
        self.sampleDelegate = otherViewController
        super.viewDidLoad()
    }
}

しかし、このSwiftファイルをつくるとコンパイルエラーになります。以下で、このファイルの実装するための変更手順を示していきます。

変更手順

段階を追って、意図通りに動くための手順を示していきます。

プロパティを追加

まずこのsampleDelegateはメンバ変数として定義されているため、クラスの外から参照することはできません。参照できるようにするには、メンバ変数ではなくプロパティに変更する必要があります。そのために、まずはヘッダファイルにプロパティの宣言を追加します。

SampleParentViewController.h
 
#import <UIKit/UIKit.h>

@protocol SampleDelegate

- (void) delegateMethod;

@end

@interface SampleParentViewController: UIViewController {
    id<SampleDelegate> sampleDelegate;
}

@property id<SampleDelegate> sampleDelegate;

- (instancetype)initWithDelegate:(id<SampleDelegate>)delegate;

@end

一応、これだけでコンパイルエラーは解消します。しかし、実行してみるとotherViewControllerのdelegateMethodは実行されず、sampleDelegateは書き換えられていないことがわかります。これはヘッダファイルで新しくプロパティを宣言し変数を追加しましたが、もともとのsampleDelegateには何の変更も加わっていないためです。

Objective-Cのプロパティ

Objective-Cでは、ヘッダファイルでプロパティを宣言すると、メソッドファイルでは頭に_がついて扱われます。そのため現時点では、もともと存在していたsampleDelegateと新しく追加した_sampleDelegateが存在していることになっています。今回はsampleDelegateをプロパティに置き換えるのが目的なので、メソッドファイルに書かれているsampleDelegateを_sampleDelegateに書き換えていきます。

SampleParentViewController.m
 
#import "SampleParentViewController.h"

@implementation SampleParentViewController

- (instancetype)initWithDelegate:(id<SampleDelegate>)delegate
{
    self = [super init];
    if (self) {
        _sampleDelegate = delegate;
    }
    return self;
}

- (void)viewDidLoad {
    [super viewDidLoad];
    [_sampleDelegate delegateMethod];
}

@end

これで、sampleDelegateが完全にプロパティに置き換わりました。したがって継承先のファイルからsampleDelegateが扱えるようになっています。一応、使わなくなったメンバ変数のsampleDelegateの宣言を消しておきましょう。

SampleParentViewController.h
 
#import <UIKit/UIKit.h>

@protocol SampleDelegate

- (void) delegateMethod;

@end

@interface SampleParentViewController: UIViewController

@property id<SampleDelegate> sampleDelegate;

- (instancetype)initWithDelegate:(id<SampleDelegate>)delegate;

@end

まとめ

メンバ変数が定義されているObjective-CファイルをSwiftファイルで継承してその変数を扱うために、プロパティで宣言し直してメソッドファイルを書き換える手順を記載しました。Objective-Cはハマると解決に時間がかかる仕様が多いと思います。そんな人の助けになれると幸いです。

0
0
0

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
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?