こんにちは。きんくまです。
今回はenum, typedef, #defineについてです。
その前に、今回説明する用に新規ヘッダーファイルをつくります。
File > New > File
iOSでもOS Xのどちらでも > C and C++ > Header File を選択
Nextボタンを押してファイル名を適当にいれて保存します。
今回は KKHeader.hとしました。
そのあと、main.m からいま作ったファイルを読み込めるようにします。
#import <Foundation/Foundation.h>
とかいてあるすぐしたに
#import “KKHeader.h”
と書きます。これで読み込めるようになります。
main.m
#import <Foundation/Foundation.h> #import "KKHeader.h" int main(int argc, const char * argv[]) { //以下mainの中身がつづくが省略
#importを書くと外部ファイルを読み込むことができます。
新しく作ったヘッダーファイルを見てみます。
KKHeader.h
#ifndef HelloProject_KKHeader_h #define HelloProject_KKHeader_h //ここにいろいろと書く #endif
#ifndef, #define, #endifと書いてある行は、C言語で二重にヘッダーファイルが読み込まれるのを防ぐのによく使われる方法です。C言語では#importではなく、#includeで外部ファイルを読み込みます。そのとき、このやり方をしないと何度もヘッダーファイルが読み込まれることになって、変数や定数が何度も定義されてしまい、コンパイルエラーになるのです。
一方Objective-Cでは#importで読み込みます。これは#includeと違って、コンパイラが自動で二重にヘッダーファイルを読み込むことを防いでくれます。なのでこの3行はObjective-Cでコンパイルするときは必要ないのですが、今回はそのままにしておきます。
プログラム的な用語の意味は、#ifndefはそのマクロが#define(定義)されていなければ、#endifまでを読み込みます。今回の場合はHelloProject_KKHeader_hというものが定義されてなければという意味になります。その次の行で、#define HelloProject_KKHeader_hと書いてあるので、マクロを定義しています。これで1度マクロ定義されてしまえば、#ifndefでそこを通らなくなるので、ヘッダーファイルの多重読み込みを防ぐことが可能になります。
こんな感じに、コンパイラにコンパイルするときの動作を振り分けたりすることがあります。例えば、開発用とリリース(本番公開)用で分けるといった感じです。
#define
ついでなので#defineについて説明します。さきほどはコンパイラの動作を振り分けたのですが、よく使われるものに変数おきかえマクロがあります。
KKHeader.h
#define MY_NUMBER 230 #define KKMyString @"Hello message"
これらを定義しておいて、別のファイルの中で参照することができます。よく使う定数などを1カ所にまとめておけば、あとから変更になった場合もその1部分だけを修正するだけで、読み込んであるファイル全部に反映させることができます。
main.m
@autoreleasepool { NSLog(@"num = %d", MY_NUMBER); NSLog(@"message = %@", KKMyString); }
#defineや次で説明するenumの中で使うマクロやタグの名前は、プロジェクト全体で共通して使うため他とかぶらないようにします。
・英語2文字からはじめる(適当な接頭子。AppleではNSやUIをつけているものがある)-> 例)SPSampleString
・小文字のkからはじまるもの -> 例)kSampleString
・全部大文字で_でつなげる -> 例)SAMPLE_STRING
などの方法があります。いろいろなプログラムを参考にしたり、自分でプログラムを書くときのルールを決めておくとよいです。今回はサンプルなので、混ぜこぜにしてあります。あまりよくない例です、、w。
あと、マクロで関数を使う方法もあるのですが、ここでは省略します。
enum
enumは簡単にいうと数値に変数名をつけることができます。
例をみてみます。
KKHeader.h
enum KKWeekday{ KKWeekdayMonday = 0, KKWeekdayTuesday, KKWeekdayWednesday = 9, KKWeekdayThursday };
enum + タグ名をかいた後に、中身をかいていきます。最後の} の後に;(セミコロン)を書くのを忘れないようにします。
= のあとに書いた数値がその定数の値になります。もし、=を省略してある場合は、次の行で1ずつ数値が足されていきます。
使ってみます。
main.m
//enumのタグKKWeekdayの変数myWeekdayを宣言 //変数名は好きにきめてよい enum KKWeekday myWeekday; myWeekday = KKWeekdayMonday; NSLog(@"weekday %d", myWeekday); //0 myWeekday = KKWeekdayTuesday; NSLog(@"weekday %d", myWeekday); //1 myWeekday = KKWeekdayWednesday; NSLog(@"weekday %d", myWeekday); //9 myWeekday = KKWeekdayThursday; NSLog(@"weekday %d", myWeekday); //10
enumを使うことで、数値に文字の意味をもたせることが可能になります。前回説明したswitch文で使ってみます。
main.m
enum KKWeekday myWeekday = KKWeekdayMonday; switch (myWeekday) { case KKWeekdayMonday: NSLog(@"monday"); break; case KKWeekdayTuesday: NSLog(@"tuesday"); break; case KKWeekdayWednesday: NSLog(@"wednesday"); break; case KKWeekdayThursday: NSLog(@"thursday"); break; default: break; }
こうやって書くことで、数値で表されたときよりもプログラムの流れが大分わかりやすくなります。
typedef
typedefを使うと、enum+タグを独自の型として定義できます。
さきほどのものをさしかえてみます。
KKHeader.h
typedef enum : NSInteger{ KKWeekdayMonday = 0, KKWeekdayTuesday, KKWeekdayWednesday = 9, KKWeekdayThursday }KKWeekday;
ちょっと書き方が変わって、NSIntegerが追加されました。enumの中身が何型の変数なのかを表します。負の数まで入るNSIntegerか0以上のNSUIntegerを書きます。このNSIntegerは省略できますが、私はつけて書いてます。
さきほどのswitch文を変更してみます。
main.m
KKWeekday myWeekday = KKWeekdayMonday; switch (myWeekday) { case KKWeekdayMonday: NSLog(@"monday"); break; case KKWeekdayTuesday: NSLog(@"tuesday"); break; case KKWeekdayWednesday: NSLog(@"wednesday"); break; case KKWeekdayThursday: NSLog(@"thursday"); break; default: break; }
最初のenum KKWeekdayがKKWeekdayだけになったところだけが変わりました。
enumとtypedef enumはいろいろと書き方があります。このあたりもお好みでどうぞ。
>> typedef enumの使い方を教えてください
今回Objective-Cではあまり使わないため説明しなかったのですが、structやunionというものがCの文法であります。もし見かけたときは調べてみてください。
■ 自作iPhoneアプリ 好評発売中!
・フォルメモ - シンプルなフォルダつきメモ帳
・ジッピー電卓 - 消費税や割引もサクサク計算!
■ LINEスタンプ作りました!
毎日使える。とぼけたウサギ