2014年6月24日火曜日

[iOS][Objective-C]NSMutableArrayの要素をイテレートしながら削除する


どうも。

ちょっと考えれば分かることなんですが、
あまりこういうシーンが今までなかったので…。

「NSMutableArrayから、
何かしらの条件に合致する要素を削除したい。」

となったときに、
・条件判定→ループ
・要素の削除→removeObject

で、

for (int i = 0; i < [aList count]; i++) {
    ・
    ・
    ・
}

と書き始めて、
「これじゃアカン!」
と…。

removeすると削除して詰めちゃうから、
インデックスがおかしくなる…。

と、
ちょっと考えてみて、
「index降順でループすればいいじゃん!」
という結論。

    int aListCnt = (int)[aList count];

    for (int i = aListCnt - 1; i >= 0; i--) {
 
   MyClass *myClass = [aList objectAtIndex:i];

   if ([myClass shouldBeRemovedFromList]) {
 
        [aList removeObjectAtIndex:i];
       }
    }

まぁ、
これまでこんなシーンがなかったんだなぁと、
なぜかしみじみw

んで、
int aListCnt = (int)[aList count];
というまどろっこしいのがあるんですが、
警告対策です。

countメソッドはNSUIntegerが返ってくるので、
for (int i = [aList count] - 1; …………
と書くと警告が出ます。

では、
for (NSUInteger i = [aList count] - 1; i >= 0; …………
と書いたらどうか?

これはこれで別な警告が出ます。
「unsignedなんだから、i>=0って常に真でしょ?」
みたいな。

まぁ、
for (int i = (int)[aList count] …………
と書けばいいんですが、
ループの条件が長いのも鬱陶しいので、
こんな整理にしてみました。


それでは。
ちゃお☆

まこぴー。

2014年6月11日水曜日

[iOS][Objective-C]バックグラウンド動作


どうも。

アプリがバックグラウンドに遷移しても、
処理を継続したい。
というのは、
要件としてありえる話です。

しかしながら、
iOS側の思想としては、
「アクティブでないのなら可能な限り速やかにサスペンドする」
というような感じです。
これは、バッテリー消費等の観点だと思われます。

通常、
バックグラウンド遷移後、
RunLoopやワーカスレッドの停止により、
サスペンド状態になり、
アプリ動作は停止する。

じゃあ、
本気で即時サスペンドかというとそうでもなく、
AppDelegateの
- (void)applicationDidEnterBackground:(UIApplication *)application;
の中で、
然るべきデータの保存等が可能なように、
5sec以内の処理が許可されている。

ある程度の間処理が継続出来ればいい、
というのであれば、
下記のような方法により、
サスペンドまでの時間を延長する事ができる。
注意が必要なのは、
その延長時間は、
iOS6では600sec、iOS7では180secとなっていること。

[AppDelegate.m]


UIBackgroundTaskIdentifier bgTask = 0;

- (void)applicationDidEnterBackground:(UIApplication *)application
{
    UIApplication *app = [UIApplication sharedApplication];

  bgTask = [app beginBackgroundTaskWithExpirationHandler:^{

  [app endBackgroundTask:bgTask];
        bgTask = UIBackgroundTaskInvalid;
    }];
}

上記はアプリ全般に言える事ですが、
特定の位置づけのアプリであれば、
上記の制約を飛び越える事ができます。

Audio再生や位置情報の利用など。
<AppName>-Info.plistに、
Required background modesとして定義する事が出来る。

だから、
iPodみたくAudioの再生をバックグラウンドでも止めたくない、
とか、
ナビゲーション機能はバックグラウンドだからといって止まってもらっては困る、
というのは、
Info.plistに定義の上、
無制限で処理の継続が許可される。

iOS7からは、
Background fetchとか、
Remote notificationsといった仕組みが追加になっているので、
SNSやWebサービス連携であれば、
そうした仕組みを積極利用すべきと考えられます。
これらは何かしらのトリガにより、
一時的にサスペンドから復帰して処理を実行後、
またサスペンド状態に戻る。
というような仕組みに見受けられる。
(使った事ないから詳しくは分からないw)

で、
裏技というか…。
バッテリー消費量だったり、
(iOS開発観点での)倫理的な問題から、
個人的にはやらない方がいいと思うんですが…。

やろうと思えば、
Info.plistに定義しといて、
空のAudioを再生し続けるとか、
必要なくても位置情報を更新し続けるとかすれば、
バックグラウンド動作が継続出来るワケですw

完全なバッドノウハウだと思います。
Rejectされない保証や、
後々取り下げられない保証はありません。
こういうのは危険と隣り合わせ、
と思っておくくらいがちょうどいいと思うし、
Storeに出したいのなら、
裏技は使わない方がいいかなと思います。

個人で無料で出すようなアプリならまだしも、
会社名義で出すようなアプリでは、
バッドノウハウは排除すべきだと思います。
しかしながら、
そうした警告をしても、
全く意に介さない人もいるので、
痛い目に遭わなきゃいいですがね…、
と見守るしかないですw


それでは。
ちゃお☆


まこぴー。

2014年6月3日火曜日

[iOS][Swift]新しいプログラミング言語「Swift」


どうも。

またまた、
ずいぶんとご無沙汰してしまいました…。

WWDC 2014があり、
iOS8の発表やら、
なんとまぁ、
新プログラミング言語の「Swift」の発表があったり…。

で、
そのSwift。
リファレンスを読むどころか、
早くもXcode6でSwiftをお試し実装している人たちもいる訳ですw
(まぁ、エンジニアたる者、自分もそうでなきゃいけないんですが…)

ちょいとすぐにはそんな時間が取れないので、
移動時間にリファレンスをチラ見して、
先取りしている人たちのコードなんかもチラ見して。
既にググれば、
サワリとしてはそこそこな情報があります。

で、
受けた印象としては、
コードの見た目的には、
JavascriptとかPythonとかに似ているかな。
まぁ、モダンな言語のいいとこ取りみたいな感じなんでしょうか?

Objective-Cに比べれば、
コード量や可読性は一気に上がりそうです。

iOS8以降のみをターゲットにして、
新たに書くならSwiftの方がいいかも知れない。
共存しながらのコンバートを経て、
最終的にはSwiftに完全に置き換わるのか、
果たして…。

ともかく、
実情のお仕事ベースで言うと、
これまで、そして、
いまいまはObjective-Cで書いているワケで、
当面はObjective-Cとのお付き合いは続きそうです。
また、ゆくゆくも、
レガシーなiOSアプリのコードとして付き合わざるを得ないシーンはあるかと。

忘れてはいけないことは、
iOS開発であることには変わりない。
ということです。
クセのあるUIとか画面遷移だとかマルチタスキングだとか、
気を使わなければならないポイントは同じ。

このブログも、
iOSアプリをObjective-Cで開発する、
という前提のトピックばかりでやってますが、
当面はその内容は変わらないと思います。
(まぁ、あまり更新もできていなかったりもしますが…w)

もともと自分が開発をする上で困らないように覚え書きしているので、
Objective-Cの開発が続くのであれば、
Objective-Cの覚え書きをするし、
違う言語になればその覚え書きをするまでです。


それでは。
ちゃお☆


まこぴー。