たまたんのぶろぐ

たまたんが時たま言いたいことを書いてます。ジャンルはめっちゃええ加減ですwソフトやプログラムのことが多いかもしれませんが。。。。。

UITableViewをアコーディオンっぽくする方法(簡易版)

またまた投稿!!\(^-^)/バンザーイ、/( )\モヒトツ\(^o^)/バンザーイ

 

今回も、またまた、iOSですなのだ!!

 

一時期、UITableViewのアコーディオンが流行りましたが、

そん時は全く興味がなかったのでスルーしてましたw

 

今、ちょうど、自作アプリを作っている最中に、オープンソースとかで簡単に作れるようなのないかなぁって、見てみたら、表示ばかりを気にするものが多く、自分で装飾を変えるのがめんどくさそうなのばかりでした。だから、自作しようかと思い、多階層を作る前に簡単な2階層までのアコーディオンを作ってみました。

 

まぁ、当たり前のソースなんでだれでも、作れるとは思いますがね。

ミソは、カテゴリを作るところだけですので、

説明せんでもわかるでしょうから今回はソースだけです。w

 

 動作はこんなんになります。

 

 

ではでは。<(_ _)>

 

 

Objective-CでCSVをプロパティリストに変換する方法

珍しく2日連続で投稿w

 

昨日、Cocoa勉強会関西ビギナーズに参加してきました。

おまえビギナーだったんかいって突っ込まれそうですが、いつも心は初心者です。( ー`дー´)キリッ

それは冗談で、難しいことは教えられないですが、

初心者の方に教える力はありますので、参加させていただいております。(⌒〜⌒)ニンマリ

それで、その時に、CSVXMLからplist(プロパティリスト)に変換する方法はないかと聞かれました。

 

そもそも、plistは、XML形式になっていています。

Appleが設定しているDTDにしたがって作られています。

詳しくは、

Property List Programming Guide: Introduction to Property Lists

を参照してください。英語だけどね。。。

plistには、形式がいろいろありまして、

配列型、辞書型、文字列型、データ型、日付型、整数型、浮動小数点数型、ブーリアン型(YES/NO)があります。

今回は、配列と辞書型を変換するようにしてみます。

 

また、CSVは、カンマ区切りでやってみます。(ダブルコート「"」を使用したものとそうでないものとを扱います。)

 

ちなみに、Objective-C(NSObject)には、plistへシリアライズ化するものがあるので、簡単に変換できるようになっています。(参照

 

それを使ってプログラムを書いてみます。

小さいプログラムを作るので、ちょっと冗長なところはあるかもしれませんが、

勘弁してくらはい。<m(__)m>

ソースは、自由に使ってかまいませんが、

出来れば、Webサイトの紹介をしていただければありがたいです。<(_ _)>

 

まずは、単なるカンマ区切りのCSVを変化するプログラム

単に、1行ずつ読み込んで

行を「,」で分割して順番に辞書にほりこんでいきます。

そしてそれを配列に突っ込んで、後はシリアライズ化!!

どう?かんたんでしょ?

でもこれだと、カンマが入った文章中にのCSVだと、少々難しくなるので、

正規表現でカンマの位置を取得して、

順番にカンマ位置までのワードを取り出していき、「"」がついていたらトリムするようにしてます。

 こんな感じですね。

後者のテストデータと実行後の出力データをのしておきます。

test.csv

-----------------------------------

test1,test2,test3,test4,test5

あ,い,う,え,お

か,き,く,け,こ

"さ","し","す","せ,","そ"

た,ち,つ,て,と

-----------------------------------

test.plist

f:id:tama-jp:20140223103247p:plain

 

ちょいと、後者は難しかったかもしれないなぁ。。。。

 

NSDataを16進数の文字列に出力する関数

久しぶりに投稿。

 

NSDataを16進数の文字列に出力する関数。(ARC用)

 

- (NSString*) serializeDeviceToken:(NSData*) deviceToken

{

    NSMutableString *str = [NSMutableStringstringWithCapacity:64];

    int length = [deviceToken length];

    char *bytes = malloc(sizeof(char) * length);

    

    [deviceToken getBytes:bytes length:length];

    

    for (int i = 0; i < length; i++)

    {

    [str appendFormat:@"%02.2hhX", bytes[i]];

    }

    free(bytes);

    

    return str;

}

 

または、NSDataのカテゴリーに追加

<NSData+Hex.h>

@interface NSData (Hex)

- (NSString*)hexString ;

@end

 

<NSData+Hex.m>

#import "NSData+Hex.h"

 

@implementation NSData (Hex)

- (NSString*)hexString {

    unichar* hexChars = (unichar*)malloc(sizeof(unichar) * (self.length*2));

    unsignedchar* bytes = (unsignedchar*)self.bytes;

    for (NSUInteger i = 0; i < self.length; i++) {

        unichar c = bytes[i] / 16;

        if (c < 10) c += '0';

        else c += 'a' - 10;

        hexChars[i*2] = c;

        c = bytes[i] % 16;

        if (c < 10) c += '0';

        else c += 'a' - 10;

        hexChars[i*2+1] = c;

    }

    NSString* retVal = [[NSString alloc] initWithCharactersNoCopy:hexChars

                                                           length:self.length*2

                                                     freeWhenDone:YES];

    return retVal ;

}

@end

 

必要だったからメモした。((φ┫ ̄Д ̄ ┣ ホォホォ

GPS使用時の初期化判断の方法

 

メモ代わりに書いておきます。

 

GPSを使用するときに大半のサイトでは、

 

    locationServicesEnabled = [CLLocationManager locationServicesEnabled];

    

    if (locationServicesEnabled == nil){

     <初期化>

    ・

    ・

    ・

        

    }

と書かれてます。

しかし、iOS4から非推奨にされているlocationServicesEnabledを使用されています。

なので、これを使用するとXcodeでは、ワーニングがでます。

 

ですので、以下の方法に変更します。

    CLLocation *loc = mapView.userLocation.location;

    

    if (loc == nil){

     <初期化>

    ・

    ・

    ・

        

    }

 
これで出来ると思います。

 

以上。間違ってたらごめんなさい。

 

初心者向けのStoryBoardの画面遷移の説明についてちょっと疑問。

ドットインストールさんの#10 セグエで画面を接続するを見てみました。

 

これはあかんやろぉ〜・・・・

 

確かに画面遷移でトグルができる様にみえるんですが、

初心者にこれは簡単だからといって注意事項を書かなくて

話すのはかなり問題はありますね。

 

これって、画面遷移をしているように思うのですが、

モーダルで画面遷移と言うことは、

画面の切り替えが行われているのではなくて、

最前面に新しい画面が作成されていきます。

 

っと言うことは、ボタンを押すたびに新しい画面が

作成されていくのですからメモリがどんどん消費されていきますよね。

理論をちゃんと説明しておかないと勘違いされますよね。

 

 

指摘しようと思ったんですが、このサイトのどこに言えばいいのかな?>_<

 

 

あっ、勘違いしないでくださいね。

 

 

 

 

プログラムの方法が間違っているわけではないのですよ。

ただ、制限をなしで使用したりするのはまずいです。

要するに、勉強するサイトなのですから注釈が必要だと言っております。

 

 

 

 

 

動作するからいいじゃん!!って言う人もいるかもしれないですが、

理論がわかっていないとあとからどえらい致命的なバグにぶつかるときがあります。

趣味で作って分でしたらいいんですが、BtoCやBtoBで作り出したら責任問題に発展しますよ。

 

最近、ネットで日本語で紹介しているサイトの大半は、理論ではなくて試行錯誤でこうなったとしか書いていないのが多いと思います。

これはこれでいいのですが、使うときには、本当にこれを使用しても問題ないかを

考えた上で使ってくださいね。

 

っと、書いておきましたが、当サイトの技術もよく考えてからご使用くださいw( ̄∇ ̄)

もし間違いがあればどんどん指摘してくださいねぇm(__)m

 

ではでは。

iOSでメモリ使用量がわかるモジュール

これ使ったろーって思っていっつもどこかに行ってしまうのでメモがわりに。。。。

iOS開発の時にリアルタイムでメモリの増減の変化を見たいときありませんか?

 

そんなときに使えるモジュールです。

製品では使わないとは思いますが、デバッグ時に重宝します。

ソースはめっちゃ単純なんですが、自分で作るのがめんどくさいのでこんなのあってすっごく助かります。

 

アプリのメモリ使用量をリアルタイムに表示するクラスを公開しました

http://d.hatena.ne.jp/shu223/20110428/1303930059

 

ちなみに、Arc版じゃないので「-fno-objc-arc」をソースオプションに設定しないとエラーが出ます。

 

ん?使い方って?メモ代わりなんで。。。。めんどくさい(-。-) ボソッ

いやいや、ソースや作者のサイト見た方がわかりやすいでしょぅ。

(要望によっては・・・・・)

 

ではでは。

StoryBoardでiPhone5とその他のiPhoneを別々に作成する方法

ども、不定期的にネタを小出しにしてるため、PVが全然増えないTAMAです。

まぁ、増やす気もなくって、自分のメモ程度で書いてるだけなんですけどねw

今回は、開発のネタっす。

いつもの通り途中で適当になるかもしれませんがあしからず( ̄∇ ̄)

 

今回、iPhone5がでて、世界中で良いやら悪いやら賛否両論ですが、

たぶん、あいぽんプログラマが一番気になったのは、画面が縦長になったことでしょう。

その当時を再現すると

 

アップルさん:「新しいあいぽんでま〜す」じゃじゃ〜〜ん。

私ら    :「おぉ!!」((((o゜▽゜)o))) ドキドキ♪

アップルさん:「これです!!」つ[あいぽん5]

ユーザ1  :「ほほぉ〜〜〜!!」(*^o^*)

ユーザ2  :「ちっ、噂されてたとうりじゃん」チェ〜ッ… ( ̄、 ̄)

ユーザ3  :「ほちぃ」(@@)ウルウル

プログラマ1:「え”!!が、画面が。。。。」(゜-゜)

プログラマ2:「うにゃ?が、画面が。。。。」(ノ_・。)

プログラマ3:「げぇ?が、画面が。。。。」(O_O)

 ・

 ・ 以下同文

 ・

プログラマX:「(好きな言葉を入れてください)!!が、画面が。。。。」(×_×;)

 

 

てなかんじでしたよねぇ。(笑)<注意> 本ブログはかなり脚色が入っています。

 

っで、最近、iOS5以上のユーザが増えてきたので、StoryBoardに移行する人が多くなってきたと思いますが、どうしたら良いのだろうと思った人はいるのではないでしょうか。

 

すっげぇ〜〜〜〜簡単っすよぉ( ̄∇ ̄)

 

簡単に言うと、アプリのデリゲートで、画面判別し、画面の大きさごとにStoryBoardを作成しておき、対応するものを表示するんです。

 

( ゚Д゚)ハァ?わかるかぼけぇ!!

 

って言われそうなんで、具体的に書きましょうか。。。。。

「SingleView Aplication」で作っている前提で話します。

ここがわからない場合は他のサイトを見て勉強してください。m(__)m

 

○ 新しいプロジェクトを作成するとiPhone5用のStoryBoardで自動生成されていると思いますので、古いiPhone用のStoryBoardを作成します。

 

1.プロジェクトより右クリックする。

f:id:tama-jp:20120927100735p:plain

2.New Fileを選ぶ

f:id:tama-jp:20120927100741p:plain

3.StoryBoardを選択する。

f:id:tama-jp:20120927100834p:plain

4.あいぽんようなんで、そのままNEXT!!

f:id:tama-jp:20120927100926p:plain

5.StoryBoardの名称を入れ、次へ。

f:id:tama-jp:20120927100935p:plain

6.これで土台は出来ました。が、中身はありません。

f:id:tama-jp:20120927100949p:plain

7.UIViewコントローラを貼り付ける。

f:id:tama-jp:20120927101727p:plain

8.見た目がiPhone5のUIが張り付きます。

f:id:tama-jp:20120927101015p:plain

9.iPhone4以下のものにするには、下の方の縮まりを示すアイコンを一回押します。

f:id:tama-jp:20120927101058p:plain←これ。

10.するとiPhone4以下のUIに見た目はなります。

f:id:tama-jp:20120927101109p:plain

11.ついでなので、どっちのStoryBoardを使ったかわかるようにラベルを貼っておきましょう。

f:id:tama-jp:20120927101221p:plain

f:id:tama-jp:20120927101243p:plain

 

画面は完成です。

これで、iPhone5用、iPhone4以下用の二つのStoryBoardが出来ました

 

○次に、このStoryBoardの呼び出し方ですね。

一般的には、プロジェクトのTargetの設定でStoryBoardは呼び出されます。

f:id:tama-jp:20120927102529p:plain

それを無視して、「AppDelegate」から起動するように、ソースを変更します。

具体的には、「application:didFinishLaunchingWithOptions:」に書きます。

以下を参考にしてください。

 

 

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions

{

    // Override point for customization after application launch.

    UIStoryboard *storyboard;   // StoryBoardの型宣言

    NSString * storyBoardName;  // StoryBoardの名称設定用

    

    // 機種の取得

    NSString *modelname = [ [ UIDevice currentDevice] model];

 

    // iPadかどうか判断する

    if ( ![modelname hasPrefix:@"iPad"] ) {

        

        // Windowスクリーンのサイズを取得

        CGRect r = [[UIScreen mainScreen] bounds];

        // 縦の長さが480の場合、古いiPhoneだと判定

        if(r.size.height == 480){

            // NSLog(@"Old iPhone");

            storyBoardName = @"MainStoryboard_Old_iPhone";

        }else{

            // NSLog(@"New iPhone");

            storyBoardName =@"MainStoryboard_iPhone";

        }

    }else{

        // NSLog(@"iPad");

        storyBoardName =@"MainStoryboard_iPad";

    }

    // StoryBoardインスタンス

    storyboard = [UIStoryboard storyboardWithName:storyBoardName bundle:nil];

 

    // 画面の生成

    UIViewController *mainViewController = [storyboard instantiateInitialViewController];

    

    // ルートウィンドウにひっつける

    self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];

    self.window.rootViewController = mainViewController;

    [self.window makeKeyAndVisible];

 

    returnYES;

}

 

 

説明しなきゃいけない?見たらわかりますよねぇ。

しゃーないなぁ。。。。ちょっとだけ話すよぉ。( ̄△ ̄)

最初に機種を判断し、iPadなら「MainStoryboard_iPad」、iPhoneなら現在起動している画面の長さをmainScreenから取得して判断し、画面が480なら「MainStoryboard_Old_iPhone」、そうでなければ、「MainStoryboard_iPhone」を設定してStoryBoardインスタンスを生成します。

それを、ルート画面に貼り付けるんですよぉ。

わかったぁ?わからんかったら上のソースを貼り付けてくださいw

 

これをシミュレーションでテストすると以下のようになってます。

☆iPhone3G系

f:id:tama-jp:20120927103705p:plain

iPhone4、4S用

f:id:tama-jp:20120927103749p:plain

☆iPhone5用

f:id:tama-jp:20120927103725p:plain

簡単でしょ?

そろそろ、いつもの通り、終わりが尻切れトンボで終了します。( ̄∇ ̄)

 

あっ、ここの情報は、URLで紹介してくださいね。(⌒〜⌒)ニンマリ

転載しても良いけど、紹介はしてくださいm(__)m