Objective-Cのクラス名取得!初心者でも理解できる10選の方法

Objective-Cのクラス名取得のイラスト付きガイドObjctive-C
この記事は約27分で読めます。

 

【サイト内のコードはご自由に個人利用・商用利用いただけます】

この記事では、プログラムの基礎知識を前提に話を進めています。

説明のためのコードや、サンプルコードもありますので、もちろん初心者でも理解できるように表現してあります。

基本的な知識があればカスタムコードを使って機能追加、目的を達成できるように作ってあります。

※この記事は、一般的にプロフェッショナルの指標とされる『実務経験10,000時間以上』を凌駕する現役のプログラマチームによって監修されています。

サイト内のコードを共有する場合は、参照元として引用して下さいますと幸いです

※Japanシーモアは、常に解説内容のわかりやすさや記事の品質に注力しております。不具合、分かりにくい説明や不適切な表現、動かないコードなど気になることがございましたら、記事の品質向上の為にお問い合わせフォームにてご共有いただけますと幸いです。
(送信された情報は、プライバシーポリシーのもと、厳正に取扱い、処分させていただきます。)

はじめに

Objective-Cは、AppleのiOSやmacOSの開発で長らく使用されてきたプログラミング言語です。

Objective-Cを使用してアプリケーションを開発する際、クラス名の取得は多くのシチュエーションで役立ちます。

本記事では、Objective-Cでのクラス名の取得方法を初心者にも分かりやすく解説します。10の具体的な方法とそれに伴うサンプルコードを通して、安心して学びましょう。

●Objective-Cとは

Objective-Cは、C言語にオブジェクト指向の機能を追加した言語であり、1980年代にNeXT社で開発されました。

AppleがNeXTを買収したことをきっかけに、macOSやiOSの主要な開発言語として採用されるようになりました。

Objective-Cは、高い拡張性と柔軟性を持つことで知られ、多くの開発者に愛されています。

○Objective-Cの基本

Objective-Cのプログラムは、クラスとインスタンスの概念を中心に構築されます。

クラスはオブジェクトの設計図のようなもので、インスタンスはその設計図をもとに作られた実体を指します。

Objective-Cでは、メソッド呼び出しを行う際にブラケット記法を使用します。

例えば、あるインスタンスのメソッドを呼び出す際は [インスタンス メソッド名] のように記述します。

○クラス名とは

クラス名とは、オブジェクト指向プログラミングにおいて、クラスの識別子として使用される名前のことを指します。

Objective-Cにおいて、クラス名はそのクラスの特性や役割を表すための重要な情報となります。

例えば、画像を扱うクラスであればUIImage、文字列を扱うクラスであればNSStringといった具体的な名前がつけられます。

クラス名を適切に設定することで、他の開発者がコードを読む際の理解を助け、効率的な開発を促進することができます。

●Objective-Cでのクラス名取得の基礎知識

Objective-Cは、C言語にオブジェクト指向機能を追加したプログラミング言語として知られています。

多くのiOSアプリケーションはこの言語を使用して開発されてきました。

Objective-Cにおける「クラス」という概念は、オブジェクト指向プログラミングの基本中の基本です。

今回は、そんなObjective-Cでのクラス名取得の基礎について、初心者向けにわかりやすく解説します。

○クラスの意味と役割

クラスとは、オブジェクト指向プログラミングの中心となる概念で、オブジェクトの設計図のようなものです。この設計図を元に、具体的なオブジェクトを作成することができます。

これをインスタンスと呼びます。

クラスは属性(変数)と動作(メソッド)を持っており、これによりオブジェクトがどのようなデータを持ち、どのような動作をするのかを定義します。

たとえば、自動車を表すクラスがあったとします。

このクラスは「色」や「最高速度」といった属性と、「走る」や「止まる」といった動作を持つでしょう。

クラスをもとに具体的な自動車のオブジェクト(インスタンス)を作成することで、それぞれ異なる色や最高速度を持った自動車を表現することができます。

○クラス名の必要性

それでは、なぜクラス名を取得する必要があるのでしょうか。

クラス名は、クラスの識別子として機能します。

Objective-Cにおいて、クラス名はそのクラスを一意に特定する情報として扱われます。

これにより、クラス名を知っていればそのクラスのインスタンスを動的に生成したり、特定のクラスのメソッドを呼び出したりすることができます。

クラス名の取得は、次のような場面で役立ちます。

  1. デバッグ時に、オブジェクトがどのクラスのインスタンスであるのかを確認したい場合。
  2. リフレクションや動的なオブジェクト生成を行いたい場合。
  3. 複数のクラスが同じインターフェース(メソッド)を持つ場合に、どのクラスのインスタンスであるのかを判別したい場合。

これらの場面では、クラス名を取得することで、プログラムの動作を柔軟に制御することが可能となります。

●クラス名取得の具体的な方法

Objective-Cにおけるクラス名の取得は、多様な手段を通じて実現可能です。

今回は、初心者の方々でも理解できるように、2つの代表的な方法を中心に解説していきます。

○サンプルコード1:基本的なクラス名の取得方法

Objective-Cでのクラス名の取得は非常に簡単です。

特定のオブジェクトのクラス名を取得する基本的な方法を見てみましょう。

// オブジェクトを作成
NSString *sampleString = @"Hello, Objective-C!";
// クラス名を取得
NSString *className = NSStringFromClass([sampleString class]);
// クラス名を出力
NSLog(@"クラス名: %@", className);

このコードではNSStringを使って文字列オブジェクトを作成しています。

この例では「Hello, Objective-C!」という文字列を持つsampleStringというオブジェクトを作成しています。

そして、NSStringFromClass関数を用いて、そのオブジェクトのクラス名を取得しています。

このコードを実行すると、次のような結果が得られます。

クラス名: NSString

○サンプルコード2:継承されたクラス名の取得

Objective-Cではクラスが継承されることがよくあります。

例えば、特定のカスタムクラスが基本のクラスを継承している場合、そのクラスのクラス名も取得したい場合があります。

// カスタムクラスを作成し、NSObjectを継承
@interface CustomClass : NSObject
@end

@implementation CustomClass
@end

CustomClass *sampleObject = [[CustomClass alloc] init];
NSString *className = NSStringFromClass([sampleObject class]);
NSLog(@"クラス名: %@", className);

このコードでは、まずCustomClassという新しいクラスを作成しています。

そして、このクラスは基本的なNSObjectクラスを継承しています。

その後、このカスタムクラスからオブジェクトを生成し、そのオブジェクトのクラス名を取得しています。

このコードを実行すると、次のような結果が得られます。

クラス名: CustomClass

○サンプルコード3:動的に生成されたクラスのクラス名取得

Objective-Cにおいては、クラスは動的に生成することも可能です。動的に生成されたクラスのクラス名を取得する場面も考えられます。そういった場面でのクラス名の取得方法を見ていきましょう。

#import <Foundation/Foundation.h>

int main(int argc, const char * argv[]) {
    @autoreleasepool {
        // 動的にクラスを生成
        Class DynamicClass = objc_allocateClassPair([NSObject class], "MyDynamicClass", 0);
        objc_registerClassPair(DynamicClass);

        // 生成したクラスのクラス名を取得
        NSString *className = NSStringFromClass(DynamicClass);
        NSLog(@"クラス名: %@", className);
    }
    return 0;
}

このコードでは、objc_allocateClassPairを使ってNSObjectを親クラスとするMyDynamicClassというクラスを動的に生成しています。その後、objc_registerClassPairを使ってクラスを登録しています。

そして、NSStringFromClass関数を用いて動的に生成されたクラスのクラス名を取得し、NSLogで出力しています。

この例では、NSObjectを基に新しいクラスを動的に作成し、そのクラスの名前を取得して表示しています。

このコードを実行すると、出力内容は、クラス名: MyDynamicClassとなります。これにより、動的に生成したクラスの名前を正確に取得することが確認できます。

○サンプルコード4:特定のインスタンスからクラス名を取得

Objective-Cでは、あるインスタンスからそのインスタンスが所属するクラスの名前を取得することもよく行われます。

ここでは、インスタンスを基にそのクラス名を取得する方法を表すサンプルコードを紹介します。

#import <Foundation/Foundation.h>

@interface SampleClass : NSObject
@end
@implementation SampleClass
@end

int main(int argc, const char * argv[]) {
    @autoreleasepool {
        // SampleClassのインスタンスを生成
        SampleClass *sampleInstance = [[SampleClass alloc] init];

        // インスタンスからクラス名を取得
        NSString *className = NSStringFromClass([sampleInstance class]);
        NSLog(@"クラス名: %@", className);
    }
    return 0;
}

このコードでは、まずSampleClassというシンプルなクラスを定義しています。

その後、このクラスのインスタンスを生成し、そのインスタンスから[sampleInstance class]を用いてクラスオブジェクトを取得しています。

そして、NSStringFromClass関数を使ってクラス名を取得し、NSLogで出力しています。

この例では、SampleClassという名前のクラスのインスタンスを生成し、そのインスタンスからクラス名を取得して表示しています。

このコードを実行すると、出力内容は、クラス名: SampleClassとなります。

これにより、特定のインスタンスからクラス名を取得する方法を確認することができます。

○サンプルコード5:ライブラリやフレームワークのクラス名取得

Objective-Cのライブラリやフレームワークには、多くのクラスが含まれています。

これらのクラス名を取得することで、利用可能なクラスの一覧や特定のクラスが存在するかどうかを確認することができます。

ここでは、ライブラリやフレームワークからクラス名を取得するサンプルコードを紹介します。

#import <Foundation/Foundation.h>

int main(int argc, const char * argv[]) {
    @autoreleasepool {
        int numClasses;
        Class * classes = NULL;

        numClasses = objc_getClassList(NULL, 0);
        if (numClasses > 0) {
            classes = (__unsafe_unretained Class *)malloc(sizeof(Class) * numClasses);
            numClasses = objc_getClassList(classes, numClasses);
            for (int i = 0; i < numClasses; i++) {
                NSLog(@"Class name: %s", class_getName(classes[i]));
            }
            free(classes);
        }
    }
    return 0;
}

このコードでは、objc_getClassList関数を使って、現在の実行環境にロードされているクラスのリストを取得しています。

この例では、ライブラリやフレームワーク内のすべてのクラス名をコンソールに出力しています。

実際にこのコードを実行すると、多数のクラス名が出力されることが確認できます。

ただし、出力されるクラス名の数や内容は、実行環境やリンクしているライブラリによって異なります。

○サンプルコード6:外部リソースからのクラス名取得

Objective-Cのアプリケーションでは、外部のリソースやデータベース、APIから取得した情報を元に動的にクラスを生成することがあります。

その際に、クラス名を文字列として取得し、それを元に動的にクラスのインスタンスを生成することができます。

ここでは、外部リソースから取得したクラス名を元に、クラスのインスタンスを生成するサンプルコードを紹介します。

#import <Foundation/Foundation.h>

int main(int argc, const char * argv[]) {
    @autoreleasepool {
        // 例として、外部リソースから取得したクラス名を模倣
        NSString * classNameFromResource = @"NSString";

        Class dynamicClass = NSClassFromString(classNameFromResource);
        if (dynamicClass) {
            id instanceOfDynamicClass = [[dynamicClass alloc] init];
            NSLog(@"Successfully created instance of %@", classNameFromResource);
        } else {
            NSLog(@"Failed to find class named %@", classNameFromResource);
        }
    }
    return 0;
}

このコードでは、NSClassFromString関数を使って、文字列として与えられたクラス名に対応するクラスオブジェクトを取得しています。

この例では、外部リソースから取得したと仮定したNSStringクラスを元にインスタンスを生成しています。

このコードを実行すると、「Successfully created instance of NSString」というメッセージがコンソールに出力されます。

もし、存在しないクラス名が指定された場合、エラーメッセージが出力されることが確認できます。

○サンプルコード7:カテゴリーを利用したクラス名の取得

Objective-Cでは、既存のクラスに新しいメソッドを追加するためのカテゴリという機能が提供されています。

カテゴリを使用して、クラスに新たな機能を追加することができるのですが、このカテゴリを利用してクラス名を取得する方法について見ていきましょう。

このコードでは、NSStringクラスにカテゴリを使用してクラス名を取得する新しいメソッドを追加するコードを表しています。

この例では、NSStringのカテゴリとしてClassNameCategoryを追加し、その中でcategoryClassNameメソッドを定義してクラス名を取得しています。

#import <Foundation/Foundation.h>

@interface NSString (ClassNameCategory)

- (NSString *)categoryClassName;

@end

@implementation NSString (ClassNameCategory)

- (NSString *)categoryClassName {
    return NSStringFromClass([self class]);
}

@end

int main() {
    NSString *sampleString = @"Hello, World!";
    NSLog(@"%@", [sampleString categoryClassName]);
}

上記のコードを実行すると、NSStringオブジェクトのクラス名がコンソールに出力されることが期待されます。

具体的には、”NSString”という文字列が出力されるでしょう。

○サンプルコード8:プロトコルを用いたクラス名取得

プロトコルは、Objective-Cにおいて、特定のメソッド群の実装を約束するためのものです。

クラスが特定のプロトコルに準拠している場合、そのプロトコルで定義されているメソッドを必ず実装しなければならないというルールがあります。

この特性を利用して、クラス名を取得する方法を考えることができます。

このコードでは、ClassNameProtocolというプロトコルを定義し、その中でprotocolClassNameというメソッドを宣言しています。

この例では、SampleClassというクラスがこのプロトコルに準拠しており、実際にprotocolClassNameメソッドを実装してクラス名を取得しています。

#import <Foundation/Foundation.h>

@protocol ClassNameProtocol <NSObject>

- (NSString *)protocolClassName;

@end

@interface SampleClass : NSObject <ClassNameProtocol>

@end

@implementation SampleClass

- (NSString *)protocolClassName {
    return NSStringFromClass([self class]);
}

@end

int main() {
    SampleClass *sampleObject = [[SampleClass alloc] init];
    NSLog(@"%@", [sampleObject protocolClassName]);
}

このコードを実行すると、SampleClassオブジェクトのクラス名がコンソールに出力されることが期待されます。

具体的には、”SampleClass”という文字列が出力されるでしょう。

○サンプルコード9:メタクラスを使用したクラス名の取得

Objective-Cでは、各クラスはメタクラスという、クラスに関する情報を持つクラスを持っています

メタクラスを使用することで、クラス名を取得することが可能です。

このコードでは、メタクラスを介してクラス名を取得するコードを表しています。

この例では、NSStringクラスのメタクラスを取得し、そのメタクラスからクラス名を取得しています。

#import <Foundation/Foundation.h>

int main(int argc, const char * argv[]) {
    @autoreleasepool {
        // NSStringのメタクラスを取得
        Class stringMetaClass = object_getClass([NSString class]);

        // メタクラスからクラス名を取得
        const char *className = class_getName(stringMetaClass);
        NSLog(@"クラス名: %s", className);
    }
    return 0;
}

このコードを実行すると、NSStringのメタクラス名が表示されます。

Objective-Cのメタクラス名は、通常のクラス名に_metaという接尾辞がつきます。

そのため、実行するとNSString_metaという結果が表示されるはずです。

○サンプルコード10:runtime関数を用いた高度なクラス名の取得方法

Objective-Cは動的な言語であり、runtimeという仕組みを用いて、実行時に様々な操作を行うことができます。

このruntime関数を使用して、より高度な方法でクラス名を取得することが可能です。

このコードでは、runtime関数を使って、すべての登録されているクラス名を取得するコードを表しています。

この例では、アプリケーション内で利用可能なすべてのクラス名を取得し、それをログに出力しています。

#import <Foundation/Foundation.h>
#import <objc/runtime.h>

int main(int argc, const char * argv[]) {
    @autoreleasepool {
        // 登録されているクラスの数を取得
        int numClasses = objc_getClassList(NULL, 0);
        Class *classes = (Class *)malloc(sizeof(Class) * numClasses);

        // すべてのクラスを取得
        numClasses = objc_getClassList(classes, numClasses);

        // すべてのクラス名をログに出力
        for (int index = 0; index < numClasses; index++) {
            NSLog(@"%s", class_getName(classes[index]));
        }

        free(classes);
    }
    return 0;
}

このコードを実行すると、アプリケーション内で利用可能なすべてのクラス名がログに出力されます。

数が多いので、実際に実行すると多くのクラス名が表示されることでしょう。

これを用いることで、アプリケーション内のクラス構造を確認する際などに役立ちます。

●クラス名取得の応用例

Objective-Cのクラス名取得技術を習得した後、さらに進んでその応用例を考えてみると、さまざまなシチュエーションでの利用が考えられます。

ここでは、クラス名取得の応用例として3つのシナリオを紹介します。

それぞれのシナリオには、実際に使用するサンプルコードとその説明、そして実行結果を交えて詳しく解説していきます。

○サンプルコード応用1:クラス名を用いた動的生成

Objective-Cでは、クラス名を文字列として取得した後、そのクラス名を元に動的にクラスのインスタンスを生成することができます。

NSString *className = @"MyClass";
Class classObj = NSClassFromString(className);
id instanceOfMyClass;
if (classObj) {
    instanceOfMyClass = [[classObj alloc] init];
}

このコードでは、MyClassというクラス名を文字列として持つclassName変数を用意しています。

次に、NSClassFromString関数を使用して、そのクラス名からクラスオブジェクトを取得しています。

取得したクラスオブジェクトがnilでなければ、そのクラスのインスタンスを動的に生成しています。

この技術を用いると、プログラムの実行中に動的にクラスのインスタンスを生成することができ、柔軟なプログラムの設計が可能になります。

○サンプルコード応用2:クラス名からの動的メソッド呼び出し

クラス名を用いて動的にインスタンスを生成した後、そのインスタンスのメソッドを動的に呼び出すこともできます。

NSString *methodName = @"printHello";
SEL selector = NSSelectorFromString(methodName);
if ([instanceOfMyClass respondsToSelector:selector]) {
    [instanceOfMyClass performSelector:selector];
}

こちらのコードでは、printHelloというメソッド名を文字列として持つmethodName変数を用意しています。

次に、NSSelectorFromString関数を使用して、そのメソッド名からセレクタを取得しています。

そして、動的に生成したinstanceOfMyClassインスタンスがそのセレクタに応答するかどうかをチェックした上で、performSelector:メソッドを使用して動的にメソッドを呼び出しています。

このように、クラス名だけでなく、メソッド名も動的に扱うことで、さらに高度なプログラミングが可能となります。

○サンプルコード応用3:クラス名の比較を使った処理の分岐

Objective-Cのインスタンスから取得したクラス名を、文字列として比較することで、特定のクラスのインスタンスかどうかを判定し、それに応じた処理を行うことも可能です。

id someObject = // 何らかの方法で取得;
NSString *nameOfTheClass = NSStringFromClass([someObject class]);
if ([nameOfTheClass isEqualToString:@"MyClass"]) {
    // MyClassのインスタンスに対する処理
} else {
    // その他のインスタンスに対する処理
}

このコードでは、someObjectという変数に格納されているインスタンスのクラス名をNSStringFromClass関数で取得しています。

そして、取得したクラス名がMyClassかどうかを文字列として比較し、それに応じて異なる処理を実行しています。

このテクニックを使用すると、インスタンスの型に基づいた条件分岐を実現することができ、さまざまなシチュエーションで有効に活用することができます。

●クラス名取得時の注意点と対処法

Objective-Cのクラス名を取得する際には、いくつかの注意点と対処法が存在します。

これらの点を理解しておくことで、安全かつ効果的にクラス名を取得することが可能になります。

○命名規則との整合性

Objective-Cでは、クラス名やメソッド名には命名規則が存在します。

これは、コードの可読性や保守性を高めるためのもので、命名規則を無視してクラス名を取得すると、期待した結果を得られないことがあります。

このコードではNSStringクラスのクラス名を取得するコードを表しています。

この例ではNSStringのクラス名をNSStringFromClass関数を使って取得しています。

NSString *className = NSStringFromClass([NSString class]);
NSLog(@"%@", className);

上記のコードを実行すると、コンソールには”NSString”という文字列が表示されます。

しかし、命名規則に従わないクラス名を取得しようとすると、期待した結果が得られない場合があります。

そのため、常に命名規則に従った方法でクラス名を取得するよう心掛けることが大切です。

○パフォーマンス上の注意点

Objective-Cのクラス名を頻繁に取得すると、アプリケーションのパフォーマンスに影響を与える可能性があります。

特に大規模なアプリケーションや多数のクラスが存在する場合には、クラス名の取得を最小限に抑えることが推奨されます。

このコードではNSArrayクラスのクラス名を取得するコードを表しています。

この例ではNSArrayのクラス名を取得していますが、頻繁にこのような操作を行うとパフォーマンスの低下を招くことが考えられます。

NSString *arrayClassName = NSStringFromClass([NSArray class]);
NSLog(@"%@", arrayClassName);

このように、コンソールには”NSArray”という文字列が表示されますが、頻繁なクラス名の取得は避けるようにしましょう。

○セキュリティ面での懸念

クラス名を取得することで、アプリケーションの内部構造や使用しているクラスの情報が外部に漏れる可能性が考えられます。

そのため、セキュリティを重視するアプリケーションでは、クラス名の取得を避けるか、取得した情報を外部に公開しないような対策が必要となります。

このコードでは自作のSecretClassというクラスのクラス名を取得するコードを表しています。

この例ではSecretClassのクラス名を取得していますが、この情報を外部に公開すると、アプリケーションのセキュリティに問題が生じる可能性があります。

NSString *secretClassName = NSStringFromClass([SecretClass class]);
NSLog(@"%@", secretClassName);

もし外部に”SecretClass”という情報が漏れると、攻撃者による悪意ある操作の対象となる可能性があります。

そのため、セキュリティが重要なアプリケーションでは、クラス名の取得や公開には十分注意が必要です。

●クラス名取得のカスタマイズ方法

Objective-Cでクラス名を取得する方法は多岐にわたりますが、場合によっては通常の方法では求める結果が得られないこともあります。

そのため、独自のカスタマイズが求められることも考えられます。

ここでは、クラス名の取得をカスタマイズする際の基本的な考え方と具体的なサンプルコードを紹介します。

○カスタマイズの基本概念

Objective-Cのクラス名取得は、基本的にはNSStringFromClass関数や、インスタンスから[obj class]というメソッドで取得することができます。

しかし、特定の条件下でのみ取得したい、あるいは一部の文字列を除外したいといった要件がある場合、これらの基本的な方法だけでは対応が難しいことがあります。

そうした場面で役立つのが、カスタマイズです。

○サンプルコードカスタマイズ1:カスタム関数を使用したクラス名の取得

このコードでは、NSStringFromClass関数をベースにしたカスタム関数を定義し、クラス名の末尾に”Controller”がついているもののみを取得するカスタマイズを行っています。

#import <Foundation/Foundation.h>

// カスタム関数の定義
NSString *customClassName(Class cls) {
    NSString *className = NSStringFromClass(cls);
    if ([className hasSuffix:@"Controller"]) {
        return className;
    }
    return nil;
}

int main(int argc, const char * argv[]) {
    @autoreleasepool {
        // テスト
        NSLog(@"%@", customClassName([UIViewController class])); // "UIViewController"
        NSLog(@"%@", customClassName([NSString class])); // nil
    }
    return 0;
}

この例では、customClassName関数はUIViewControllerクラスのとき”UIViewController”を返し、NSStringクラスの場合はnilを返します。

○サンプルコードカスタマイズ2:フィルタリングを適用したクラス名の取得

このコードでは、特定のプレフィックスを持つクラス名のみを取得するためのカスタマイズを行っています。

例として、”NS”で始まるクラス名のみを取得するカスタマイズを紹介します。

#import <Foundation/Foundation.h>

// カスタム関数の定義
NSString *filterClassNameWithPrefix(Class cls, NSString *prefix) {
    NSString *className = NSStringFromClass(cls);
    if ([className hasPrefix:prefix]) {
        return className;
    }
    return nil;
}

int main(int argc, const char * argv[]) {
    @autoreleasepool {
        // テスト
        NSLog(@"%@", filterClassNameWithPrefix([NSString class], @"NS")); // "NSString"
        NSLog(@"%@", filterClassNameWithPrefix([UIViewController class], @"NS")); // nil
    }
    return 0;
}

この例では、filterClassNameWithPrefix関数はNSStringクラスのとき”NSString”を返し、UIViewControllerクラスの場合はnilを返します。

まとめ

Objective-Cのクラス名取得は、様々なシチュエーションで利用することができます。

この記事では、初心者から上級者までの読者が、クラス名取得の基本からカスタマイズ方法までを学べる内容を紹介してきました。

カスタマイズの方法を通して、Objective-Cの柔軟性や拡張性の高さも理解することができるでしょう。

実際の開発の際にも、この知識を活用して、より効果的なコードを書くための参考としてください。