2011年11月30日水曜日

UIActivityIndicatorViewの使い方

重い処理を実行するときは、UIActivityIndicatorViewを表示して動作中であることを示した方がいい。

UIActivityIndicatorView *indicator=[[UIActivityIndicatorView alloc]initWithActivityIndicatorStyle:style];
表示位置は適当で良いが、viewのど真ん中に出す場合はこんな感じ
    CGRect frame;
    frame.origin=CGPointZero;
    frame.size.width=37;
    frame.size.height=37; // インジケーターのサイズ
    indicator.frame=frame;
    indicator.center=view.center;
    [view addSubview:indicator];

    [indicator startAnimating];
UIActivityIndicatorViewはRunLoopに戻らないと表示されないので、一瞬戻す。
これが非常に重要。
本来は、重い処理毎別スレッドにして並行動作させる事を意図しているから、こうなっているのかもしれない。
    [[NSRunLoop currentRunLoop]runUntilDate:[NSDate dateWithTimeIntervalSinceNow:0.0]]

    ~重い処理~
    [indicator stopAnimating];
    [indicator removeFromSuperview]; // 外す
    [indicator release];
iOS5からは色を付けられるようになった。
(iOS4まではbackgroundColorだけ。)
IB上で色を設定しててもiOS4上では無視される。







2011年11月29日火曜日

Xcode;Expression is no assignable


Xcode上でObjective-Cで式を書いていると、Expression is no assignableというエラーが出ることがある。ほとんどの場合の原因は、「構造体とクラスを混在した式を書いている」事にある。

「例」
UIImageViewのプロパティframeにアクセスする場合

    CGRect frame1=imageView.frame;        // OK
    CGSize size1 =imageView.frame.size;    // Expression is no assignable

frameはCGRect構造体を返してくる。
struct CGRect {
   CGPoint origin;  // frame.origin.x   frame.origin.y
   CGSize size;     // frame.size.width frame.size.height
};
なので、構造体のメンバーにアクセスするframe.sizeはCの式としては正しく見える。

ところが、Objective-CではimageView.frameはプロパティー式であり
    [imageView getFrame]
相当式なので、それに.sizeを付けても読み出せない。
従って、
    CGRect frame1=imageView.frame;    // OK;これはObjective-Cのプロパティー式
    CGSize size1 =frame1.size;    // OK;これはCの構造体メンバーにアクセスする式
としなければならない。

ここでは読み出し側を書いたが、書き込み側も全く同様。

Objective-C、特にUIKit上ではプロパティと構造体の命名規則に区別がないため非常にわかりにくい。
これはUIKit命名規則設計上の最大の失敗だと感じている。

Expression is no assignableが出たら、それがプロパティーなのか構造体のメンバーなのかを
確認した方が良い。

2011年11月28日月曜日

UIAlertViewとUIActionSheet利用上の注意

UIAlertViewとUIActionSheetは、常にallocとinitを同時に行う必要がある。
すなわち、そのクラスインスタンスを使い回す場合でも、allocだけ先に行い、実利用時にinitだけ行って再利用すると言うことが出来ない。

文法上は問題ないのだが、実実行時、2回目以降に表示が異常になる。

 ~~だめな書き方~~
// 初期化時
UIAlertView *alertView=[UIAlertView alloc];



// 利用場所
[alertView initWithTitle:~];


~~正常動作する書き方~~


// 初期化時

UIAlertView *alertView;
alertView=nil;

// 利用場所
if (alertView!=nil) [alertView release];

alertView=[[UIAlertView alloc]initWithTitle:~];


ちなみに、ActionSheetでは(複数の)選択項目とCancelを設定出来、iPhoneではCancelボタンが表示されるが、iPadでは表示されない。アクションシート外をタップするとキャンセル相当という操作のようである。「Cancelが表示されない!」と悩まないように(実は自分)。


UIKitでは、Objective-Cの理論上記述可能なはずなのに、実際には呼び出し順序に制約がある組み合わせが他にもあるので、実行時に異常が発生する場合は、そのあたりも要注意である。

2011年11月25日金曜日

Xcode;The service is invalid

Xcodeで実機をつないでずっと開発をしていると、

The service is invalid
Please check your setup and try again
(0XE8000022)

と出るようになることがある。
Xcode3.2.6/4.1/4.2いずれを使っても出るのでバージョンは関係ない。


これは、どうやらXcode内と実機内部で把握している状況が食い違った場合に出るようである。

こうなってしまった場合は、

  1. Xcodeを閉じる

  2. 実機を外す
  3. 実機上から開発中のアプリを削除
  4. 実機の電源を切って、再起動、再接続
  5. 実機の電源を切って、再起動
  6. Xcodeを再起動

で回復する。Macも再起動するとなおよさそう。

あくまで感覚的にではあるが、どうも複数の実機をつなぎ、複数のアプリのプロジェクトを切り替えてテストしているときに発生しやすいような気がする。シミュレーターと実機での実行を交互にやったりしてると余計。

2011/12/22追記
つないでいる実機で、アプリケーションのアップデートを行うと発生することが判明。

2011年11月24日木曜日

Xcode;Analyzeの結果行のバグ

XcodeのAnalyzeはPotential leak of an object alloc の結果行が1行下にずれるバグが居る。
3.2.x時代からずっと直ってない。
なので、示している行を信じると解らないことになる。
(ごくまれに正しいことがあるが、本当にまれ。)

他の結果はずれない。

ちなみに、この警告が出たからと言って、必ずしもプログラムが間違っているわけではない。
確保と解放が正しく一致する構造がクラス内で構築されているなら、無視して良い。

それだけ。



2011年11月21日月曜日

nib(xib)で配置したクラスのinitについて

InterfaceBuilderでカスタムクラスを配置した場合の初期化の注意事項。

InterfaceBuilderで配置したクラスは、読み込み時に自動的に初期化されている。
従って、改めてinitを発行する必要はない。
というか、「発行してはいけない」。
せっかくOSが行ってくれた初期化を無効にしてしまう。

カスタムクラスにメッセージが伝わらない場合は、これも疑ってみると良い。

初期化が必要なときは、独自に初期化メソッドを実装し、その中で[super init]を発行しないようにする。


initはプログラム的にallocした場合にのみ必要なメソッドなのである。

2011年11月15日火曜日

iOS;文字列をグラフィックに描画する

文字列をグラフィックに描画するには以下のようにする。

// 文字列
NSString *text=@"2011/11/15 20:00:00";

// フォント
UIFont *font=[UIFont fontWithName:@"Times New Roman" size:14];

// 合成位置
CGPoint point;
point.x=50;
point.y=50;

// 描画色の設定
UIColor *color=[UIColor redColor];
[color set];

// 合成表示
[text drawAtPoint:point withFont:font];

存在しない(不正確な)フォント名を与えると描画されない(正確にはサイズ=0になる)。

これはNSStringのUIKit拡張である。
表示対象は現在の「グラフィックコンテキスト」。
簡単に言えば、UIGraphicsBeginImageContext(サイズ)~UIGraphicsEndImageContext()の間なら、そのサイズにおける相対座標からに描画される。

言葉で書くとわかりにくいのだけど、やってみると解る。








2011年11月13日日曜日

Quartz2D色指定方法

Quartz2Dでは線の色と塗りつぶしの色を別に指定する必要がある。

たとえば、赤の円を塗りつぶしで描画しようとして、以下のコードをUIViewに記述して実行しても、うまく動作しない。
-(void)drawRect:(CGRect)rect
{
    CGContextRef c = UIGraphicsGetCurrentContext();
    CGContextSetLineWidth(c,1.0);
    CGContextSetStrokeColorWithColor(c, [UIColor redColor].CGColor); // 線色指定
    CGContextAddArc(c,100,100,10,0,2*M_PI,1);
    CGContextFillPath(c); // 塗りつぶし
    CGContextStrokePath(c); // 描画指定
}
これで実際に描画されるのは黒塗りつぶし円である。
理由は先に書いたとおり、Quartz2Dでは線の色と塗りつぶしの色を別に指定する必要があるためである。
線色指定の下の行に
CGContextSetFillColorWithColor(c, [UIColor redColor].CGColor);
を追加すると、目的通りの赤塗りつぶし円になる。

これでだいぶ悩まされた。
なので、覚え書き。








2011年11月12日土曜日

UIViewController;画面回転の認識

画面回転のwillAnimateRotation~は、そのコントロールが表示されている間に回転されたときのみ呼び出される。

回転されてから遷移してきたときは呼び出されないので、。別途回転処理を行う必要がある

そんだけ。

2011年11月10日木曜日

Xcodeにおけるファイル名の扱いいくつか


Xcodeにおけるファイル名の扱いいくつか。

 (1)Xcode上でプロジェクトに入れたファイルは、ローカライズ用を除いて、すべてのフォルダ内容がフラットにされるため、異なるフォルダに同じファイル名が存在する場合、重複と見なされる。

どちらが使われるかは未確認。


同様の理由でに、プロジェクト上で階層フォルダというか階層グループを作ってファイルを格納した場合も、フォルダ名を指定してアクセスする必要はない。

「例」
Alarm3D/imgというグループを作った場合、"img/ファイル名"では読めない



(2)#importはファイル名の大文字小文字が区別されない。MacOS上では区別されるので、
「どっちが読まれてる?」ってな事になることがある。基本的に、英大文字小文字だけで違うファイル名は使わない方が良い。Windows上では区別されないから、相互やりとりするときにも問題を起こす。

(3)リソースファイルはmainBundleのパス内にある。
フォルダはフラットになるが、iOSデバイス内ではちゃんとフォルダ構造を持っているからである。
なので、以下のようにアクセスする。
NSString *dir=[[NSBundle mainBundle]bundlePath];
NSString *path=[[NSString alloc]initWithFormat:@"%@/Icon.png",dir];

2011年11月9日水曜日

nib内にある要素のrelease

nib内にある要素はdeallocでreleaseが必須である。

nib内にあるのだから必要ないのかと思っていたが、実際にはnibの情報に従って読み込み時にメモリ上に領域を確保するようなので、解放が必要。

deallocが呼び出された後にメモリーリークが発生するときは真っ先にこれを疑うべし。

2011年11月8日火曜日

Windows7でのいろいろ

Windows7(32bit)でのいろいろテスト結果。
  • Falcomゲーム:そのままでは実行不可。ゲームエクスプローラーに登録すれば実行可能になる。
    「Ys6」「Ysフェルガナ」「YsOrigin」「Zwei2」はクリアして動作確認済み。
    ただし、Zwei!!はどうやっても実行できなかった。仮想XPモード上ではDirectXを使わないようにすれば一応実行可能だが、「画面が狭い」「マウスカーソルがずれる」「画面描画が遅い」という問題が出る。
  • Cygwin:フォルダを丸ごとコピーした上、mkpasswdとmkgroupさえやり直せばそのまま実行可能。
  • ATOKのパレットが表示されないとき。
    コントロールパネル>地域と言語>キーボードと言語>キーボードの変更>言語バーで設定を変更する。
  • ショートカットのアイコンが消えるとき。
    アイコンキャッシュが壊れている。
    1. c:\User\ユーザー名\AppData\Local\IconCache.dbを削除
    2. 同ディレクトリで右クリック~新規作成~テキスト(名前は適当)
    3. そのテキストをIconCache.dbにリネーム
    4. プロパティで読み取り専用にする
    しばらくするとアイコンが戻る(もしくは再起動)。
    しかし、これでもだめなものもある。
    XPではアイコンが出るのに7では出ないもの。

    というか7でもコピー直後は出てたのに、その後は「使えるアイコンがない」とかいって出てこないもの。
    「あふw」がそう。
    現在は解消。
  • とにかく画面描画が遅いので調整する。
    コントロールパネル>パフォーマンスの情報とツール>視覚効果の調整>視覚効果で
    「デスクトップのアイコン名に影を付ける」と「ドラッグ中にウインドウの内容を表示する」のチェックを外す。
    これでだいぶ速くなる。
    が、結局クラシック表示は止めてAero対応にしてしまった。
    でも後者の設定を外すだけでもだいぶ速い気はする。
  • Aero有効時のWindowキーを使った操作方法。
    TAB3次元表示
    拡大
    縮小
    スペースウインドウを透明化
    デスクトップ表示
    HOMEアクティブ以外を最小化
    1~タスクバーの左から順にウインドウを戻す
    他のAero時の操作方法は
    ここにも記事あり
  • Picasaの送るの変更は、
    Explorerで「プログラムから開く」>規定のプログラムの選択>参照で設定する。
    Picasa自体の中には設定がない。
というようなところ。仮想XPモードを使っても実行が難しいソフトがある様子。
やはりXPマシンは手放せない。

2011年11月7日月曜日

JavaScriptの変数の有効範囲

JavaScriptの変数の有効範囲。

どこにも情報がないので調べてみたが、1HTMLファイルの中だけらしい。
リンク先では参照できない。

どの順番で開いたかによって内容を変えようと思っているのだけど、出来ない。
JavScriptだけじゃ無理?

Google Chromeのcookie、デフォルトでは「ローカルへのデータ設定を許可する」になっているのに、なぜか設定できない(V12/V13で確認)。
正確には、Webサーバー上につないで閲覧したときは設定できるが、ローカルにあるHTML上では代入が無視されてしまう。

Firefox(Win/Mac)では問題ない。同じWebKitのSafari(Win/Mac)でも問題ない。
でもiOSのSafariはだめ。

IEはいちいちチェックをしてくるのがうっとうしいが、動作はする。

レンダリングエンジンとJavaScriptエンジンは別という証拠だけど、iOSだけ訳わからん。

2011年11月6日日曜日

Macでゴミ箱にファイルが入らなくなった時の解決法

Macで、ゴミ箱にファイルが入らなくなった。
「この項目はすぐに削除されます。この作業は取り消すことができません」と出て、即消えてしまう。
調べてみると、同様の現象を発見した。

http://tamuchi.net/2010/01/mac-osx-snow-leopard-106.html
http://masnoko.jugem.jp/?eid=293

うちの場合、「ls -ld ~./Trash」すると「そんなもんない」と言われる。
どうも状況が違う。
後者と合わせて考えるに、.Trashが消えているか、アクセス権がおかしくなっているかのいずれかである。
以下まとめ。
  1. ゴミ箱の位置は/Users/ユーザー名/.Trashである
    ルートにも.Tashesというのがあるが、これは関係ない。
  2. Mac上で隠しファイルを見る方法は上記にもいろいろ書かれているが、一番簡単なのは、ファイラーを使うこと。
    うちではmuCommanderを使っているが、これで一発だった。
  3. .Trashがある場合、「ユーザー名」フォルダのアクセス権が書き換わっている可能性が大

である。
本来、ユーザー名フォルダは、当然そのユーザーに読み書きのアクセス権があるはずだが、
なぜか、アクセスできるユーザーからそれが抜けていた。
なので、Finderでそこを開き、i=情報で共有アクセス権を表示し、鍵を開けて変更可能にして、
+でユーザーをアクセス権=読み書きで追加する。
その後、ギアマークから「内包している項目に適応」で、そのフォルダ内分全てを同じアクセス権にする。
それにより、.Trashのアクセス権も更新される。

これをすると、他PCからアクセスされる共有フォルダのアクセス権も変わってしまうので、そこは別途戻すこと。

2011年11月5日土曜日

Xcodeに.jsファイルを加える

XcodeのプロジェクトにJavaScriptのソースファイル.jsファイルを加えたら、
「no rule to process file」という警告が出た。

警告だけなのでコンパイルと実行できるが、出来れば消しておきたい。
この場合、

  1. projectを開く
  2. TARGETを選択
  3. Build Phasesのタブを選択
  4. Compile Sourceを開く
  5. ここに.jsが入っているので、Copy Bundle Resourcesに移動する

これでOK。日本では情報が見つからなかったが、JavaScriptを使う人が少ないのか?

2011年11月4日金曜日

iOS開発におけるProvisioningのいろいろ

今までの開発経験から、Provisioningのいろいろまとめ。
  • ProvisioningにはDeveloperとDistributionの2種類がある
  • ともにiTunes Connectで作成する
  • ProvisioningはDeveloper/Distributionそれぞれで1つずつ作成すれば良い

    ここで重要なのは、Developerは開発機の特定が必要でDeviceの設定があるが、
    Distributionは公開用なのでDeviceの設定は不要である。
    Deviceの設定がグレーアウトされているのはそういう意味なので、無理にSelectAllを押す必要はない。
  • 証明書にもDeveloperとDistributionの2種類がある
  • 先にProvisioningを作成、後で「それを含んだ」証明書を作る。
    これが非常に重要。この順番を間違えると無意味な証明書が出来てしまう

    無効な証明書でビルドすると、「Application failed codesign verification. The signature was invalid, or it was not signed with an Apple submission certificate. (-19011)」という警告が出る(この状態でもReleaseまでは実機で動作するが、Distributionはエラーが出て通らない)。
  • 出来上った証明書をキーチェーンユーティリティーでキーチェーンのルートとシステムに登録

    この際、キーチェーンユーティリティーにはバグがあり、同時に複数の操作を行えないので、
    「古い証明書の削除→一端終了→再起動→新しい証明書の登録→終了」の手順をDeveloperとDistributionで計4回(ルートとシステムの双方に登録が必要だから)も行う必要がある
  • XcodeのOrganaizerもしくはiPhone構成ユーティリティーでProvisioningを追加、さらに各デバイスを開いてそれをインストール
  • ここで非常に重要なのは、Developerは開発用デバイスの全てにインストールが必要であるが、
    Distributionはインストール不要だと言うことである。というかインストールできないのが正常。
  • Xcodeのコンパイル設定で、Debug/ReleaseはDeveloper、DistributionはDistributionをコード承認に設定する。
    Releaseでは相変わらず-19011の警告が出るが、無視すれば良い。
  • 追記;証明書をいじった後は、Xcodeのコード署名を再設定する(同じファイル名でも)
というややこしい手順が必要になる。

何回も訳がわからないまま証明書から作り直してしまったが、
通常はProvisioningの有効期限切れなら「renew」で更新さえすれば、こんなややこしい手間はしないで済む。

2011年11月3日木曜日

Objective-Cのメモリ管理指示子の違い

Objective-Cのメモリ管理指示子の違いまとめ。

assign アドレスコピー
メモリ領域のアドレスだけをコピーする
release不要
実体の値保証なし=実体の確保/管理の把握が必要(別途allocしてある領域とか)
内容の変更はしないか、したらオリジナルが改変される

retain 開放遅延
メモリ領域の開放を遅延する
release必要
ローカル領域にも有効
内容の変更は、基本的に不可(推奨されない。開放したら消えるから。)

copy
実体コピー
同じ大きさの領域を確保の上、内容もコピーする
release必要
内容の変更も自由。ただし、改変結果は大元には影響しない。

実際のところ、わからないのなら、メモリと速度に余裕があるならcopy~releaseにしておけば
安全。
UI要素はcopy宣言されている、と思う。

・・・

私は、解放タイミングが明確でないautoreleaseは一切使わない。
公開されているライブラリを使うときも、必ず使わないように書き換える。

2011年11月2日水曜日

Windows7のデスクトップからホームグループのアイコンを削除する方法

Windows7のデスクトップからホームグループのアイコンを削除する方法。

レジストリを変更する。

(1)検索にRegEdit.exe入力、実行
(2)以下のキーを変名する
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\Desktop\NameSpace\{B4FB3F98-C1EA-428d-A78A-D1F5659CBA93}
これを#{~}とかにする。削除しても同じ。
(3)regeditを終了
(4)デスクトップでF5を押す(画面の更新)

なお、Pro 64ビット版ではデフォルトで表示されてないような気がする。

2011年11月1日火曜日

「安心メール」発売開始

AIG-SoftのiOS用アプリ第5弾「安心メール」が今日から発売開始。

1ボタンを押すだけでメールの送信が出来ます。

電子機器の扱いに不慣れな方、特に高齢の親御さんと子どもさんの間の連絡に
便利なように設計しました。

iPhone/iPod touch4/iPad
iOS4/5
日英
対応です。

「安心メール」

よろしくお願いします。

近日、写真機能付きのVer2にアップデート予定です。

・・・正直な所・・・

アプリが売れないとここの維持もままならないので、
寄付と思ってお買い上げ頂くと非常にありがたいかと。m(_ _)m

MacのTimeMachine用HDDの交換仕方(MoutainLion対応版)

MacのTimeMachineの交換方法。MoutainLion対応版。

TimeMachine用HDDは特殊なファイル管理下にあるので、フォーマットしてFinderで内容をコピーしようとしても、権限がどうこうと表示されてコピーできない。

以下の方法で交換する。

1.Time Machineをオフにする
2.元ディスクと新ディスクを両方マウントする;TimeMachineのHDDはつながったままだと思うので、新しいHDDをつなげるだけ
3.ディスクユーティリティを立ち上げる
4.元ディスクを選択、その中の復元のタグを選択
5.ソースに元ディスク、復元先に新ディスクを設定。
4.復元を開始
5.旧ディスクをアンマウントする
6.システム設定のTime Machineから新ディスクをバックアップに指定、Time Machineをオンにする
7.新ディスクでの最初のバックアップ時に「前回から変更がある」と言ってくるが、OKする

手順自体は解ってしまえば簡単だが、とにかく時間がかかる。
320GBでも5時間ほど。
この間もMacの利用は出来るが、あまりやりすぎるとバックアップされてないファイルが増えることになるので要注意だ。

夜中にやるのが無難かもしれない。