Tips

Objective-C 文字列,NSString 【初級編 第16回】

Manage.m

#import <Foundation/Foundation.h>
#import <math.h>
#import "Manage.h"
#import "Bmi.h"

@implementation Manage
-(Person*)person{
    return person;
}
-(void)setPerson:(Person*)newPerson{
    double num;
    if(person!=nil){
        num = fabs(22 - [Bmi calcBmi:[person weight] height:[person height]]) -
            fabs(22 - [Bmi calcBmi:[newPerson weight] height:[newPerson height]]);
        if( num > 0){
            [person release];
            person=newPerson;
            [person retain];
        }
    }else{
        person=newPerson;
        [person retain];
    }
}
-(void)showBestPerson
{
    printf("Best Person is %sn",[[person name] UTF8String]);
    printf("weight:%2.1fn",[person weight]);
    printf("height:%2.1fn",[person height]);
    printf("Bmi:%2.1fn",[Bmi calcBmi:[person weight] height:[person height]]);
}
-(void)dealloc{
    [person release];
    [super dealloc];
}
@end

ちょっとした変更をしています。理想のBMIに近い人を表示させるときに名前も出すようにしただけです。
27行目で文字列を表示させている部分がありますが、
printfのフォーマット指定子(%dとか%fとかです)で「%s」を指定することによって、文字列を表示できます。
しかしこのフォーマット指定子はそのままでは使用できません。
cでの文字列表示用の関数なのでchar型の文字列である必要があります。
そこでObjective-CのNSStringを変換するために「UTF8String」メッセージを送信して変換を行います。
ちなみに「UTF8String」は「NSString.h」内で以下のように定義されています。
頭についている「const」は修飾子と呼ばれるもので定数を表しています。
    参考 NSString.h
    - (const char *)UTF8String

main.m

#import <Foundation/Foundation.h>
#import "Bmi.h"
#import "Person.h"
#import "Manage.h"

int main(void){
    Person *teacher = [[Person alloc] initWithWeight:56.0 height:1.72 name:@"Yamada"];
    printf("name:%sn",[[teacher name] UTF8String]);
    printf("retainCount:%dn",[[teacher name] retainCount]);
    Manage *manage = [[Manage alloc] init];
    [manage setPerson:teacher];
    [teacher release];
    [manage showBestPerson];
    [manage release];
    return 0;
}

前回までで使用していたオブジェクトの所有権につけていた検証のためのコードを外しています。
代わりに今回作成したNSStringに関する検証のためのコードをつけています。
順番に見ていきます。
7行目で新しい指定イニシャライザによりオブジェクトの作成および初期化しています。
8行目はとりあえず作成されて名前がちゃんと表示されるのかを確認しています。
9行目ではその文字列の所有権を見るためにretainCountを表示させています。
後は以前のコードと特に変わっていません。

実行結果

では実行してみます。

名前は問題なく表示されていますが、その次の行の名前に対するretainCountを見てみると「134522453」となっています。
「@”文字列”」の場合、上の方でも述べたようにオブジェクトとして扱われます。
コンパイラの方でNXConstantString、Cocoaの場合はNSConstantStringというクラスで扱われるようです。
このクラス私の環境では「NSString.h」内で定義されていましたが、
NSStringクラスのサブクラスとなっていましたのでNSStringのメソッドは使用できるわけです。
参考程度ですが以下のようになっていました。
    参考 NSString.h
    @interface NXConstantString : NSString

またこのオブジェクトは定数扱いとなることはいいましたが、定数なので解放できません。
そこで解放する必要がないということを表すために変な値を返すようです。
しかしその場合UINT_MAXの値である「2147483647」になるらしいのですが「134522713」とかになっています。
すいません。現状では不明です。

実際nameを解放する処理を入れてみます。
Person.mでdeallocをオーバライドして解放処理を入れてみます。
付け加えるのは以下になります。

-(void)dealloc{
        printf("before release %d",[name retainCount]);
        [name release];
        printf("after release %d",[name retainCount]);
        [super dealloc];
}



解放前と解放後でカウントは変わりませんが、retainCountがまた変な値になっています。

今回のまとめとしては

  • Objective-Cでは文字列を表すNSStringクラスが用意されている
  • NSStringクラスはimmutable Stringなので状態の変更ができない
  • @”文字列”とやることでオブジェクトとして扱うことができるが定数のオブジェクトとなる
  • 定数は解放できないのでreleaseを送る必要がないしretainCountも変な値となる
  • といったところでしょうか。

    このretainCountはなんやろ・・・。

    TechProjin 開発系基礎講座 連載リンク

    基礎からPHPWEBアプリ解発を学ぶなら・・
    PHP基礎 連載

    AIなどで注目急上昇!これから学ぶならPython!!
    独学で学ぶ-pythonプログラミング 連載

    汎用性◎ 定番プログラミング言語JAVA
    Java基礎講座 連載

    Recent News

    Recent Tips

    Tag Search