gist

ラベル Objective-C の投稿を表示しています。 すべての投稿を表示
ラベル Objective-C の投稿を表示しています。 すべての投稿を表示

2012年2月29日水曜日

[Objective-C] NSMutableArrayのremoveObjectでハマった

    NSNumber *n1 = [NSNumber numberWithInt:1];
    NSNumber *n2 = [NSNumber numberWithInt:2];
    NSNumber *n3 = [NSNumber numberWithInt:3];
    NSNumber *n4 = [NSNumber numberWithFloat:1.00000f];
    
    // ポインタを表示
    NSLog(@"n1=%p", n1);
    NSLog(@"n2=%p", n2);
    NSLog(@"n3=%p", n3);
    NSLog(@"n4=%p", n4);
    // それぞれ違うポインタが表示される
    
    // arr作成。
    NSMutableArray *arr = [NSMutableArray arrayWithObjects:n1, n2, n3, n4, nil];
    
    NSLog(@"削除前:%@", arr); // 1,2,3,4
    
    // arrから最後のオブジェクトを取得する
    id n = [arr lastObject];
    // そのオブジェクトをarrから削除する
    [arr removeObject:n];
    
    NSLog(@"削除後:%@", arr); // 2,3
    
    // removeObjectでは、ポインタが同じものを削除するのではなく、
    // 値が同じオブジェクトを削除する。


最後のオブジェクトだけを削除したい時は、


[arr removeLastObject];

を使うべし。

5時間ハマった。コアな箇所だったので特定に時間がかかってしまいました。ドキュメントを良く調べてなかったのが今日の教訓。おやすみなさい。

2012年2月28日火曜日

[Objective-C] Association Referenceでカテゴリにプロパティを追加する方法

カテゴリにプロパティを追加できれば、継承のように型が変わることなく、もとのクラスの性質を引き継ぎつつ、ちょっとした機能を追加できるので便利です。例えばTAG。

Objective-CのAssociation Referenceを使うと、以下のようなコードで実現できます。

#import <objc/runtime.h>

static char const * const TagKey = "TagKey";

@interface NSObject(TAG) 
+(id)objectWithString:(NSString*)string;
@property(nonatomic,retain) id tag;
@end

@implementation NSObject(TAG)
@dynamic tag;

+(id)objectWithString:(NSString *)string
{
    self = (id)[[[NSObject alloc] init] autorelease];
    [self setTag:string];
    return self;
}

- (id)tag 
{
    return objc_getAssociatedObject(self, TagKey);
}

- (void)setTag:(id)tag
{
    objc_setAssociatedObject(self, TagKey, tag, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}

@end

使い方

NSObject *a = [[[NSObject alloc] init] autorelease];
[a setTag:@"abc"];
NSLog(@"%@", [a tag]); // abc

NSObject *b = [NSObject objectWithString:@"def"];
NSLog(@"%@", [b tag]); //def

応用するとNSNumberに有効桁数をもたせたり、NSDateに出力形式をもたせたり、といったことを「先」に定義できます。使い過ぎはアカンですが。

2012年1月20日金曜日

XCode4でAppleDoc形式のドキュメントを自動的に作成する

前のエントリーでappledocをインストールしておきます。

プロジェクトの直下に AppledocSetting.plist という名前で設定ファイルを作成します。

AppledocSetting.plist

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN"
"http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
    <dict>
        <key>--company-id</key>
        <string>com.luckyandhappy</string>
        <key>--create-docset</key>
        <true/>
        <key>--ignore</key>
        <array>
            <string>ThirdParty</string>
            <string>Libraries</string>
            <string>Frameworks</string>
            <string>Testing</string>
        </array>
        <key>--install-docset</key>
        <true/>
        <key>--output</key>
        <string>/tmp</string>
        <key>--project-company</key>
        <string>Lucky &amp; Happy Company</string>
        <key>--project-name</key>
        <string>SOAP2JSON</string>
        <key>--keep-undocumented-objects</key>
        <true/>
        <key>--keep-undocumented-members</key>
        <true/>
        <key>--warn-undocumented-object</key>
        <false/>
        <key>--warn-undocumented-member</key>
        <false/>
        <key>--warn-empty-description</key>
        <false/>
        <key>--warn-missing-arg</key>
        <false/>
        <key>--warn-unknown-directive</key>
        <true/>
    </dict>
</plist>

--company-id, --project-name, --project-companyは自分の環境に合わせて変更して下さい。

ターゲットを追加します。

スクリプトを追加します。

プロダクトのビルドが実行されるたびに、ドキュメントを更新するには、Product/Edit Schemeを編集します。

ドキュメント化するソースコードが多い場合、ビルドするたびにスクリプトが実行されるので重くなるかもしれません。そんなときは最後の手順をやめて、ターゲットをドキュメントとプロダクトで別々にビルドできるようにしておいたほうが良いかも。

2012年1月19日木曜日

XCode4でAppleDocを使ってみる

AppleDocは、Apple公式リファレンス風のリファレンスを作成してくれるドキュメント生成ツールです。

これはカッコいい。インストールも簡単にできるようになりました。

インストールはgitでappledocのソースコードを取得して、付属のシェルスクリプトを実行するだけです。

$ git clone git://github.com/tomaz/appledoc.git
Cloning into appledoc...
remote: Counting objects: 6017, done.
remote: Compressing objects: 100% (1628/1628), done.
remote: Total 6017 (delta 4504), reused 5830 (delta 4345)
Receiving objects: 100% (6017/6017), 2.61 MiB | 196 KiB/s, done.
Resolving deltas: 100% (4504/4504), done.
$ sudo sh install-appledoc.sh -b /usr/local/bin -t ~/Library/Application\ Support/appledoc
Password:
Building...
=== BUILD NATIVE TARGET appledoc OF PROJECT appledoc WITH CONFIGURATION Release ===
Check dependencies

...

** BUILD SUCCEEDED **

Installing binary to /usr/local/bin
Copying templates to /Users/inouetomoyuki/Library/Application Support/appledoc

$ appledoc --version
appledoc version: 2.0.5 (build 752)

$

前のエントリーで書いたコードにAppleDoc用のコメントを追加してみます。

LHParser.h

//
//  LHParser.h
//  LibXML2Test
//
//  Created by 井上 智敬 on 12/01/05.
//  Copyright (c) 2012年 Lucky and Happy Company. All rights reserved.
//
#import <Foundation/Foundation.h>
#import <libxml/tree.h>
#import "NSMutableArray+StackAdditions.h"

/** LHParserクラスは、libxmlライブラリを使用してSOAP形式の文字列をJSON形式に変換するクラスです。
 */
@interface LHParser : NSObject {
    NSDictionary *_openers;
    NSDictionary *_closures;
    NSMutableArray *_closuresStack;
    NSDictionary *_charactersFoundTable;
    BOOL _isCharactersFound;
    
    xmlParserCtxtPtr _ctxt;
    NSMutableString *_json;
}
/** パースを開始します。
 */
-(void)parse;

/** パースが終了すると呼び出されます。
 */
-(void)didParse;

/** 開始タグを検出すると呼び出されます。
 
 @param localname 開始タグ名
 @param type SOAPスキーマでの型名。http://www.w3.org/2001/XMLSchema で定義されています。
 */
-(void)startElement:(NSString*)localname type:(NSString*)type;

/** 終了タグを検出すると呼び出されます。
 
 @param localname 終了タグ名
 */
-(void)endElement:(NSString*)localname;

/** パーサーが文字列を検出すると呼び出されます。
 
 @param characters 検出した文字列
 */
-(void)foundCharacter:(NSString*)characters;

@end


static void startElementSAX(void *context,
                            const xmlChar *localname,
                            const xmlChar *prefix,
                            const xmlChar *URI,
                            int nb_namespaces,
                            const xmlChar **namespaces,
                            int nb_attributes,
                            int nb_defaulted,
                            const xmlChar **atrributes);

static void endElementSAX(void *context,
                          const xmlChar *localname,
                          const xmlChar *prefix,
                          const xmlChar *URI);

static void charactersFoundSAX(void *context,
                               const xmlChar *characters,
                               int lenght);



ターミナルでappledocを実行します。


$ appledoc --project-name LibXML2Test \
> --project-company Lucky\ And\ Happy\ Company \
> --company-id com.luckyandhappy \
> --create-html --output ./Documents \
> .
appledoc version: 2.0.5 (build 752)

$

完了したらXCodeに戻って、こんな感じでクイックヘルプが出ていればOK。

オーガナイザを起動して、Documentationタブを選択すると、新しいドキュメントが増えています。

詳しいコメントの書き方は公式サイトへ