2012年2月24日金曜日

Starting from now I will spend a few post talking about an app that I made shortly before starting at Brilliant Service, during my job search period. I think there are some implementations that might be interesting for other developers out there.

Take a look at iNippon in the iTunes Preview page here:  English  Japanese

In this post I'll share my experiences of implementing the UIPageViewController that is used in the new template Page-Based Application found in Xcode. For those of you who are not familiar with this, take a look at the iBooks app. The API for creating this beautiful and natural turning of pages is now made available using the UIPageViewController.

What the implementation in iNippon looks like can be seen in this screenshot.

iNippon, Today's view

Similar to UITableViewController, UIPageViewController takes a delegate and a datasource. Simply put, the datasource provide UIViewControllers for the UIPageViewController to display. The template in Xcode provides a fully functional implementation and it shouldn't be any problem to get ones head around how it works.

Problem
The template provided by Apple in Xcode creates new UIViewControllers on the fly when you start to turn the page. I started with this approach and it worked fine in the simulator and on the older generation iPod Touch and iPhone 3GS but on the iPhone 4 it was really slow and jerky. At first I thought this was weird but found the answer when removing the loading of the background image made it really fast and smooth. One might think that the iPhone 4 should be faster at loading images than the 3GS but in this case I used separate images sizes using the @2x suffix so the 3GS only loads an image that is 320x367 while the iPhone 4 uses an image that is 640x734 pixels, four times as much data as the lower resolution. Even though the iPhone 4 is faster it's not four times faster at this task, it seems.

Solution
So, have should we handle this? Some users might never turn the page while some users might use this functionality to flick through pages in a fast pace. Ten background images with different motives are used and loading them all into memory seems like a waste of valuable resources, especially considering most of them might not even be displayed. Remember memory is a valuable resource in mobile devices and by keeping our memory footprint low we keep other apps from being deallocated as well as improving our own loading time which will improve the overall user experience.

The solution came to be a compromise between fast page turning and memory usage. What I do is, in the datasource I keep an NSArray with 3 UIViewControllers, loaded and ready to be displayed. The one in the middle position is the one currently on screen, the others are the previous and the next page. If you turn a page the UIViewController at the next position is provided to the UIPageViewController and once the UIPageViewController has finished it's animations the next UIViewController is loaded and inserted into the array so that the array always contains three UIViewControllers. Of course, I have to keep the user from turning page again until the new UIViewController has loaded completely but this is easy done by deactivating the UIGestureRecognizers during this time. If the user takes the time to look through the content of the page, the new UIViewController will be loaded and ready well in time before the user turns page again. And as always, the edge case has to be handle separately when the user is on page zero and there are no more pages in back direction.

Utilize the UIPageViewController and create beautiful page-based applications you too. They provide a great user experience and make it fun to flick through pages.

iNippon Part 1

Starting from now I will spend a few post talking about an app that I made shortly before starting at Brilliant Service, during my job search period. I think there are some implementations that might be interesting for other developers out there.

Take a look at iNippon in the iTunes Preview page here:  English  Japanese

In this post I'll share my experiences of implementing the UIPageViewController that is used in the new template Page-Based Application found in Xcode. For those of you who are not familiar with this, take a look at the iBooks app. The API for creating this beautiful and natural turning of pages is now made available using the UIPageViewController.

What the implementation in iNippon looks like can be seen in this screenshot.

iNippon, Today's view

Similar to UITableViewController, UIPageViewController takes a delegate and a datasource. Simply put, the datasource provide UIViewControllers for the UIPageViewController to display. The template in Xcode provides a fully functional implementation and it shouldn't be any problem to get ones head around how it works.

Problem
The template provided by Apple in Xcode creates new UIViewControllers on the fly when you start to turn the page. I started with this approach and it worked fine in the simulator and on the older generation iPod Touch and iPhone 3GS but on the iPhone 4 it was really slow and jerky. At first I thought this was weird but found the answer when removing the loading of the background image made it really fast and smooth. One might think that the iPhone 4 should be faster at loading images than the 3GS but in this case I used separate images sizes using the @2x suffix so the 3GS only loads an image that is 320x367 while the iPhone 4 uses an image that is 640x734 pixels, four times as much data as the lower resolution. Even though the iPhone 4 is faster it's not four times faster at this task, it seems.

Solution
So, have should we handle this? Some users might never turn the page while some users might use this functionality to flick through pages in a fast pace. Ten background images with different motives are used and loading them all into memory seems like a waste of valuable resources, especially considering most of them might not even be displayed. Remember memory is a valuable resource in mobile devices and by keeping our memory footprint low we keep other apps from being deallocated as well as improving our own loading time which will improve the overall user experience.

The solution came to be a compromise between fast page turning and memory usage. What I do is, in the datasource I keep an NSArray with 3 UIViewControllers, loaded and ready to be displayed. The one in the middle position is the one currently on screen, the others are the previous and the next page. If you turn a page the UIViewController at the next position is provided to the UIPageViewController and once the UIPageViewController has finished it's animations the next UIViewController is loaded and inserted into the array so that the array always contains three UIViewControllers. Of course, I have to keep the user from turning page again until the new UIViewController has loaded completely but this is easy done by deactivating the UIGestureRecognizers during this time. If the user takes the time to look through the content of the page, the new UIViewController will be loaded and ready well in time before the user turns page again. And as always, the edge case has to be handle separately when the user is on page zero and there are no more pages in back direction.

Utilize the UIPageViewController and create beautiful page-based applications you too. They provide a great user experience and make it fun to flick through pages.

2012年2月14日火曜日

省電力評価
★★☆☆☆



アプリケーション概要
Google Chromeのモバイル版アプリです。
パソコン版Google Chrome と同期できる素敵なブラウザアプリです。




Android Market : https://market.android.com/details?id=com.android.chrome
Version : 0.16.4130.199



計測条件
・SIMカード:なし (3G通信なし)
・壁紙設定:壁紙
・Wi-Fi設定:ON
・Bluetooth設定:OFF
・GPS設定:OFF
・NFC設定:OFF
・バックグラウンドシンク設定:OFF
・現在地情報:無線ネットワークを使用 ON、GPS機能を使用 OFF



アプリケーション起動中の使用機能
機能使用
ネットワーク通信
GPS
WIFI制御×
バッテリー情報取得×
Bluetooth×
カメラ起動×
NFC
WakeLock使用



アプリケーション起動時の電力測定
ブラウザ起動後、通信を行っていない状態の波形です。



ブラウザ起動後、スクリーンOFF状態の波形です。



標準ブラウザと同じような波形でした。



Google検索の結果画面で上下に激しくスクロールを行いました。
標準ブラウザ(波形:白)とChrome Beta(波形:黄)の波形です。

  


上限値は同じぐらいですが、下限値がChrome Betaの方が高い値となりました。
安定化電源に表示された値は以下のようになりました。
標準ブラウザ … 約0.25A
Chrome Beta … 約0.30A

Chrome Betaの方が消費電流が高い!



次はGoogle画像検索の結果画面で上下に激しくスクロールを行いました。
標準ブラウザ(波形:白)とChrome Beta(波形:黄)の波形です。

  


Chrome Betaの波形(黄色)が被さって白い波形が見えずらくなってしまいました。
見えやすいように、色を逆転させました。


標準ブラウザ(波形:黄)とChrome Beta(波形:白)の波形です。



波形をみると、標準ブラウザの方が低いことがわかります。

安定化電源に表示された値は以下のようになりました。
標準ブラウザ … 約0.24A
Chrome Beta … 約0.30A

画像表示の画面でも、Chrome Betaの方が消費電流が高い結果となりました。



考察
Chrome Betaの方が消費電流が高い結果となりました。
Google社純正の2つのブラウザで、同じ端末上、同じwebkitを使用していても消費電流が異なることがわかりました。

アプリケーションの設計の違いが、消費電流の量に繋がってしまいます。
消費電流を意識した設計を心掛けるようにしたいものですね。

まだまだBeta版ということですので、消費電流の改善に期待します!

Chrome Beta

省電力評価
★★☆☆☆



アプリケーション概要
Google Chromeのモバイル版アプリです。
パソコン版Google Chrome と同期できる素敵なブラウザアプリです。




Android Market : https://market.android.com/details?id=com.android.chrome
Version : 0.16.4130.199



計測条件
・SIMカード:なし (3G通信なし)
・壁紙設定:壁紙
・Wi-Fi設定:ON
・Bluetooth設定:OFF
・GPS設定:OFF
・NFC設定:OFF
・バックグラウンドシンク設定:OFF
・現在地情報:無線ネットワークを使用 ON、GPS機能を使用 OFF



アプリケーション起動中の使用機能
機能使用
ネットワーク通信
GPS
WIFI制御×
バッテリー情報取得×
Bluetooth×
カメラ起動×
NFC
WakeLock使用



アプリケーション起動時の電力測定
ブラウザ起動後、通信を行っていない状態の波形です。



ブラウザ起動後、スクリーンOFF状態の波形です。



標準ブラウザと同じような波形でした。



Google検索の結果画面で上下に激しくスクロールを行いました。
標準ブラウザ(波形:白)とChrome Beta(波形:黄)の波形です。

  


上限値は同じぐらいですが、下限値がChrome Betaの方が高い値となりました。
安定化電源に表示された値は以下のようになりました。
標準ブラウザ … 約0.25A
Chrome Beta … 約0.30A

Chrome Betaの方が消費電流が高い!



次はGoogle画像検索の結果画面で上下に激しくスクロールを行いました。
標準ブラウザ(波形:白)とChrome Beta(波形:黄)の波形です。

  


Chrome Betaの波形(黄色)が被さって白い波形が見えずらくなってしまいました。
見えやすいように、色を逆転させました。


標準ブラウザ(波形:黄)とChrome Beta(波形:白)の波形です。



波形をみると、標準ブラウザの方が低いことがわかります。

安定化電源に表示された値は以下のようになりました。
標準ブラウザ … 約0.24A
Chrome Beta … 約0.30A

画像表示の画面でも、Chrome Betaの方が消費電流が高い結果となりました。



考察
Chrome Betaの方が消費電流が高い結果となりました。
Google社純正の2つのブラウザで、同じ端末上、同じwebkitを使用していても消費電流が異なることがわかりました。

アプリケーションの設計の違いが、消費電流の量に繋がってしまいます。
消費電流を意識した設計を心掛けるようにしたいものですね。

まだまだBeta版ということですので、消費電流の改善に期待します!

2012年2月13日月曜日

省電力評価
★★★☆☆



アプリケーション概要
Android4.0.3に標準に搭載されているブラウザアプリです。





Android Market : 登録なし
Version : 4.0.3-239410



計測条件
・SIMカード:なし (3G通信なし)
・壁紙設定:壁紙
・Wi-Fi設定:ON
・Bluetooth設定:OFF
・GPS設定:OFF
・NFC設定:OFF
・バックグラウンドシンク設定:OFF
・現在地情報:無線ネットワークを使用 ON、GPS機能を使用 OFF



アプリケーション起動中の使用機能
機能使用
ネットワーク通信
GPS
WIFI制御×
バッテリー情報取得×
Bluetooth×
カメラ起動×
NFC
WakeLock使用



アプリケーション起動時の電力測定
ブラウザ起動後、通信を行っていない状態の波形です。





ブラウザ起動後、スクリーンOFF状態の波形です。



ブラウザ起動後、無通信状態ではHome画面表示中とあまり変わりませんでした。



Google検索の結果画面で上下に激しくスクロールを行いました。
白い波形がGB版、黄色い波形がICS版です。
なんと、ICSの方が消費電流が低いことが解りました。







次はGoogle画像検索の結果画面で上下に激しくスクロールを行いました。
白い波形がGB版、黄色い波形がICS版です。
なんとなんと、さらにICSの方が消費電流が低いことが解りました。





波形をみると何となく画像検索結果画面(=画像が多い画面)の方が消費電流が低いように見えたので、波形を重ねてみました。
白い波形が文字列の多いGoogle検索の結果画面、黄色い波形が画像の多いGoogle検索画像の結果画面です。




Google検索結果画面よりGoogle画像検索結果画面の方が若干、消費電流が低いようです。




考察
GB版よりICS版の方が消費電流が低いことが解りました。
さらに画像表示の消費電流が大きく下がっています。
ドラッグ中の画像再描画に関する処理に改善対策が行われていると思います。
これは注目すべき改善点です。

標準ブラウザ Android4.0.3版

省電力評価
★★★☆☆



アプリケーション概要
Android4.0.3に標準に搭載されているブラウザアプリです。





Android Market : 登録なし
Version : 4.0.3-239410



計測条件
・SIMカード:なし (3G通信なし)
・壁紙設定:壁紙
・Wi-Fi設定:ON
・Bluetooth設定:OFF
・GPS設定:OFF
・NFC設定:OFF
・バックグラウンドシンク設定:OFF
・現在地情報:無線ネットワークを使用 ON、GPS機能を使用 OFF



アプリケーション起動中の使用機能
機能使用
ネットワーク通信
GPS
WIFI制御×
バッテリー情報取得×
Bluetooth×
カメラ起動×
NFC
WakeLock使用



アプリケーション起動時の電力測定
ブラウザ起動後、通信を行っていない状態の波形です。





ブラウザ起動後、スクリーンOFF状態の波形です。



ブラウザ起動後、無通信状態ではHome画面表示中とあまり変わりませんでした。



Google検索の結果画面で上下に激しくスクロールを行いました。
白い波形がGB版、黄色い波形がICS版です。
なんと、ICSの方が消費電流が低いことが解りました。







次はGoogle画像検索の結果画面で上下に激しくスクロールを行いました。
白い波形がGB版、黄色い波形がICS版です。
なんとなんと、さらにICSの方が消費電流が低いことが解りました。





波形をみると何となく画像検索結果画面(=画像が多い画面)の方が消費電流が低いように見えたので、波形を重ねてみました。
白い波形が文字列の多いGoogle検索の結果画面、黄色い波形が画像の多いGoogle検索画像の結果画面です。




Google検索結果画面よりGoogle画像検索結果画面の方が若干、消費電流が低いようです。




考察
GB版よりICS版の方が消費電流が低いことが解りました。
さらに画像表示の消費電流が大きく下がっています。
ドラッグ中の画像再描画に関する処理に改善対策が行われていると思います。
これは注目すべき改善点です。
Nexus Sにて再度、明るさ設定の確認を行いました。
GingerBreadとIce Cream Sandwichで消費電流の違いがあるか確認します。

条件:
・壁紙設定:壁紙
・Wifi設定:OFF
・bluetooth設定:OFF
・GPS設定:OFF
・バックグラウンドシンク設定:OFF

「画面の明るさ」の変更方法:
・電源管理ウィジェットによる変更


1.「画面の明るさ」設定:レベル1

電源管理ウィジェットにて一番暗い設定にしました。




2.「画面の明るさ」設定:レベル2

電源管理ウィジェットにて1段階目の明るさ。




3.「画面の明るさ」設定:レベル3

電源管理ウィジェットにて2段階目の明るさ。






まとめ

各レベルと電流値を表にしました。

画面の明るさ電流値
レベル10.12A
レベル20.15A
レベル30.25A


以前、GingerBread版で計測した結果と比べると、ほぼ同じ値となりました。
画面設定「画面の明るさ」の違いを確認する - オシロスコープの波形
http://bs-power-save-project.blogspot.com/2011/10/blog-post.html


「画面の明るさ」に関しては、OSによる違いはありませんでした。

画面設定「画面の明るさ」の違いを確認する - Android4.0.3版

Nexus Sにて再度、明るさ設定の確認を行いました。
GingerBreadとIce Cream Sandwichで消費電流の違いがあるか確認します。

条件:
・壁紙設定:壁紙
・Wifi設定:OFF
・bluetooth設定:OFF
・GPS設定:OFF
・バックグラウンドシンク設定:OFF

「画面の明るさ」の変更方法:
・電源管理ウィジェットによる変更


1.「画面の明るさ」設定:レベル1

電源管理ウィジェットにて一番暗い設定にしました。




2.「画面の明るさ」設定:レベル2

電源管理ウィジェットにて1段階目の明るさ。




3.「画面の明るさ」設定:レベル3

電源管理ウィジェットにて2段階目の明るさ。






まとめ

各レベルと電流値を表にしました。

画面の明るさ電流値
レベル10.12A
レベル20.15A
レベル30.25A


以前、GingerBread版で計測した結果と比べると、ほぼ同じ値となりました。
画面設定「画面の明るさ」の違いを確認する - オシロスコープの波形
http://bs-power-save-project.blogspot.com/2011/10/blog-post.html


「画面の明るさ」に関しては、OSによる違いはありませんでした。

http://upload.wikimedia.org/wikipedia/en/0/0c/Xcode_icon.pngXcode has great code-completion (or auto-completion) and by utilizing this wisely we can save ourselves lots of trouble. A good thing to do at the beginning of every app development is to create an global.h file to hold all constants, strings, etc, and include this in all the classes where needed. Even though it might not feel necessary at the start of a small project, as new functionality is added the amount of constants, strings, etc, needed quickly grows and it becomes difficult to remember them all. By collecting them all in one place, we make configuration, updates and changes very easy to do.


My Global.h can look something like this:

// NSUserDefaults
#define kUDMusicState           @"MusicState"           // BOOL
#define kUDSoundState           @"SoundState"           // BOOL
#define kUDNrOfPlayers          @"NrOfPlayers"          // int
#define ...

// Notification Center
#define kNCFacebookLogin        @"FacebookDidLogin"
#define kNCFacebookLogout       @"FacebookDidLogout"
#define ...

// Images
#define kImageHelpGamePhone     @"helppageGame"        
#define kImageHelpGamePad       @"helppageGame~pad"
#define ...

Now, when somewhere in my code I need to access NSUserDefaults. I know that all my NSUserDefault keys start with kUD... so when I type kUD all the keys are presented to me and I can easily choose from the menu the one I need.
















Same when I need an images, simply typing kImage... and code-completion gives my a list of all my defined image names. No more going back to check what the filename was or looking for bugs that are caused by wrong spelling in the key string (maybe I'm the only one who get this kind of bug *_* )

If Xcode doesn't show the auto-completion list, try hitting ESC. If still no suggestion comes up, the needed file is not included or you're trying write something that doesn't belong there. On rare occasions the auto-completion systems fails to work properly but building the project should solve that.

If you have any good tip on how to make the most of Xcode, please let me know!

Utilize Auto-Completion in Xcode


http://upload.wikimedia.org/wikipedia/en/0/0c/Xcode_icon.pngXcode has great code-completion (or auto-completion) and by utilizing this wisely we can save ourselves lots of trouble. A good thing to do at the beginning of every app development is to create an global.h file to hold all constants, strings, etc, and include this in all the classes where needed. Even though it might not feel necessary at the start of a small project, as new functionality is added the amount of constants, strings, etc, needed quickly grows and it becomes difficult to remember them all. By collecting them all in one place, we make configuration, updates and changes very easy to do.


My Global.h can look something like this:

// NSUserDefaults
#define kUDMusicState           @"MusicState"           // BOOL
#define kUDSoundState           @"SoundState"           // BOOL
#define kUDNrOfPlayers          @"NrOfPlayers"          // int
#define ...

// Notification Center
#define kNCFacebookLogin        @"FacebookDidLogin"
#define kNCFacebookLogout       @"FacebookDidLogout"
#define ...

// Images
#define kImageHelpGamePhone     @"helppageGame"        
#define kImageHelpGamePad       @"helppageGame~pad"
#define ...

Now, when somewhere in my code I need to access NSUserDefaults. I know that all my NSUserDefault keys start with kUD... so when I type kUD all the keys are presented to me and I can easily choose from the menu the one I need.
















Same when I need an images, simply typing kImage... and code-completion gives my a list of all my defined image names. No more going back to check what the filename was or looking for bugs that are caused by wrong spelling in the key string (maybe I'm the only one who get this kind of bug *_* )

If Xcode doesn't show the auto-completion list, try hitting ESC. If still no suggestion comes up, the needed file is not included or you're trying write something that doesn't belong there. On rare occasions the auto-completion systems fails to work properly but building the project should solve that.

If you have any good tip on how to make the most of Xcode, please let me know!

2012年2月7日火曜日



f:id:bs-android:20120204105131j:image


Androidアプリケーション、デザイナーとプログラマーのハッカソン vol2 が開催されました。


前回に引き続き第二弾です。


従来のハッカソンではプログラマーがメインとなるイベントですが、デザイナーさんも交えてAndroidアプリを作りました。


チーム分け


事前に用意したネタごとにチームを作りました。


時計やライブウォールペーパーなど、デザイナーさんの力が光りそうなアプリがあります。


f:id:bs-android:20120204103615j:image:w400


ハッカソンの様子


f:id:bs-android:20120204104610j:image:w400


各チーム席をくっつけ、ハッカソンスタートです


f:id:bs-android:20120204104832j:image:w400


ライブウォールペーパーを作るチームは、すでにあるライブウォールペーパーを参考にしているようです


f:id:bs-android:20120204142305j:image:w400


ノートにはラフ画が書かれています


f:id:bs-android:20120204134546j:image:w400


ガシガシ画像作ってます


こういうソフト使える人に憧れます!


f:id:bs-android:20120204142601j:image:w400


デザイナーと意思を疎通させるためには、手書きも便利ですね


f:id:bs-android:20120204162932j:image:w400


発表資料を作っているようです


発表


チーム DQN 「DQN Clock」

f:id:bs-android:20120204170608j:image:w400


メンバー




f:id:bs-android:20120204171510j:image:h400


カラフルでユニークな時計を作られていました。


マスコットキャラクターのDQNちゃん(ドキュンちゃん)がかわいく手を振ります




チーム 小学3年生 「電卓アプリ」

f:id:bs-android:20120204171106j:image:w400


メンバー




f:id:bs-android:20120204171204j:image:w400


見た目は普通だけど、なんと占いまでできてしまう電卓を作られていました。


占い機能と見た目はできたけど、ハプニングにつき完成には至りませんでした。


発表者曰く、「電卓は鬼門だから次からは辞めとけ」だそうですw




チーム MemoPad「MemoPad」

f:id:bs-android:20120204171613j:image:w400


メンバー




  • @zaki50(プログラマー)

  • @b0ner_jp(プログラマー)

  • @mstssk(プログラマー)

  • 匿名希望(デザイナー)


このチームは@zaki50 さんがAndroidMarketで公開されている


MemoPadのデザインを、より良くしようと集結しました。


f:id:bs-android:20120204171823j:image:w400


色を選ぶUIが、より分かりやすくなりました。


f:id:bs-android:20120204172422j:image:w400


さらに描いた絵をNFCを利用してSmartTagに書きこむ機能まで追加!


すごい!




チーム La battle 「La 合戦」

f:id:bs-android:20120204172822j:image:w400


メンバー




チーム内に歴史が好きな人がいた事と、フランス人と仲良くなりたいという人がいたので


フランス人と仲良くなるための合戦ゲームを作っていました。


f:id:bs-android:20120204172908j:image:w400


こんな感じで手裏剣を投げ合って


敵の大将を倒すと…


f:id:bs-android:20120204172746j:image:w400


うちとったりーと表示されます


私もフランス人と仲良くなれるよう、遊んでみたいです。




チーム 左官「ライブウォールペーパー -天気-」

f:id:bs-android:20120204173606j:image:w400


メンバー




チーム左官は天気を表示するライブウォールペーパーを作りました。


和風テイストでとても綺麗です。


f:id:bs-android:20120204174839j:image:w400


さらに画面をタッチすると、なぜか手裏剣が空を舞います


某合戦チームの影響だそうですw




チーム オレオレ詐欺 「oreoreゲーム」

f:id:bs-android:20120204174023j:image:w400


メンバー




f:id:bs-android:20120204174356j:image:w400


チームオレオレ詐欺は、さめがめというゲームを作っていました。


この短時間で基本的なゲームの部分が完成していました。素晴らしい!


石を消すと気持ちいい音が鳴るのも特徴でした。音はなかなか気づかないですが重要ですよね。


投票


全員に一人5票で投票してもらいました。


結果は…




  • 1位 オレオレ詐欺 oreoreゲーム 41票

  • 2位 La battle La合戦 30票

  • 3位 MemoPad 27票


おめでとうございます!


その他


Androidアプリ デザイナーとプログラマーのハッカソン vol.2 - Togetter


http://togetter.com/li/253227


参加者リスト


https://twitter.com/#!/bs_android/dpthon2




文責:技術部 山下 智樹





Androidアプリケーション、デザイナーとプログラマーのハッカソン vol2が開催されました。



f:id:bs-android:20120204105131j:image


Androidアプリケーション、デザイナーとプログラマーのハッカソン vol2 が開催されました。


前回に引き続き第二弾です。


従来のハッカソンではプログラマーがメインとなるイベントですが、デザイナーさんも交えてAndroidアプリを作りました。


チーム分け


事前に用意したネタごとにチームを作りました。


時計やライブウォールペーパーなど、デザイナーさんの力が光りそうなアプリがあります。


f:id:bs-android:20120204103615j:image:w400


ハッカソンの様子


f:id:bs-android:20120204104610j:image:w400


各チーム席をくっつけ、ハッカソンスタートです


f:id:bs-android:20120204104832j:image:w400


ライブウォールペーパーを作るチームは、すでにあるライブウォールペーパーを参考にしているようです


f:id:bs-android:20120204142305j:image:w400


ノートにはラフ画が書かれています


f:id:bs-android:20120204134546j:image:w400


ガシガシ画像作ってます


こういうソフト使える人に憧れます!


f:id:bs-android:20120204142601j:image:w400


デザイナーと意思を疎通させるためには、手書きも便利ですね


f:id:bs-android:20120204162932j:image:w400


発表資料を作っているようです


発表


チーム DQN 「DQN Clock」

f:id:bs-android:20120204170608j:image:w400


メンバー




f:id:bs-android:20120204171510j:image:h400


カラフルでユニークな時計を作られていました。


マスコットキャラクターのDQNちゃん(ドキュンちゃん)がかわいく手を振ります




チーム 小学3年生 「電卓アプリ」

f:id:bs-android:20120204171106j:image:w400


メンバー




f:id:bs-android:20120204171204j:image:w400


見た目は普通だけど、なんと占いまでできてしまう電卓を作られていました。


占い機能と見た目はできたけど、ハプニングにつき完成には至りませんでした。


発表者曰く、「電卓は鬼門だから次からは辞めとけ」だそうですw




チーム MemoPad「MemoPad」

f:id:bs-android:20120204171613j:image:w400


メンバー




  • @zaki50(プログラマー)

  • @b0ner_jp(プログラマー)

  • @mstssk(プログラマー)

  • 匿名希望(デザイナー)


このチームは@zaki50 さんがAndroidMarketで公開されている


MemoPadのデザインを、より良くしようと集結しました。


f:id:bs-android:20120204171823j:image:w400


色を選ぶUIが、より分かりやすくなりました。


f:id:bs-android:20120204172422j:image:w400


さらに描いた絵をNFCを利用してSmartTagに書きこむ機能まで追加!


すごい!




チーム La battle 「La 合戦」

f:id:bs-android:20120204172822j:image:w400


メンバー




チーム内に歴史が好きな人がいた事と、フランス人と仲良くなりたいという人がいたので


フランス人と仲良くなるための合戦ゲームを作っていました。


f:id:bs-android:20120204172908j:image:w400


こんな感じで手裏剣を投げ合って


敵の大将を倒すと…


f:id:bs-android:20120204172746j:image:w400


うちとったりーと表示されます


私もフランス人と仲良くなれるよう、遊んでみたいです。




チーム 左官「ライブウォールペーパー -天気-」

f:id:bs-android:20120204173606j:image:w400


メンバー




チーム左官は天気を表示するライブウォールペーパーを作りました。


和風テイストでとても綺麗です。


f:id:bs-android:20120204174839j:image:w400


さらに画面をタッチすると、なぜか手裏剣が空を舞います


某合戦チームの影響だそうですw




チーム オレオレ詐欺 「oreoreゲーム」

f:id:bs-android:20120204174023j:image:w400


メンバー




f:id:bs-android:20120204174356j:image:w400


チームオレオレ詐欺は、さめがめというゲームを作っていました。


この短時間で基本的なゲームの部分が完成していました。素晴らしい!


石を消すと気持ちいい音が鳴るのも特徴でした。音はなかなか気づかないですが重要ですよね。


投票


全員に一人5票で投票してもらいました。


結果は…




  • 1位 オレオレ詐欺 oreoreゲーム 41票

  • 2位 La battle La合戦 30票

  • 3位 MemoPad 27票


おめでとうございます!


その他


Androidアプリ デザイナーとプログラマーのハッカソン vol.2 - Togetter


http://togetter.com/li/253227


参加者リスト


https://twitter.com/#!/bs_android/dpthon2




文責:技術部 山下 智樹





2012年2月6日月曜日

Are you looking for a way to learn how your users use you app, retention rate, error logging, etc?

This website introduce 7 different solutions. Personally, I only have experience with Flurry and Google Analytics. I'm very pleased with Flurry and even though some of the other services also look good, I feel no need to try them. (This is not a review, only a recommendation...)

http://support.flurry.com/images/logo.gif
Flurry Analytics
Flurry can be used in iOS, Android, Blackberry, Windows Phone, JavaME and HTML5.

The API is super easy to install and use and compared to Google Analytics which is originally made for webpages and not really adapted to mobile apps, Flurry is designed for mobile apps. For example, if you use a UITabBarController or UINavigationController, you can with one line of code in your app delegate track all "page" views controlled by that controller.

The free analytics package is all you need to get all plenty of feedback on how your app is doing out there.

Check the webpage by clicking the logo above for more information.

App Analytics

Are you looking for a way to learn how your users use you app, retention rate, error logging, etc?

This website introduce 7 different solutions. Personally, I only have experience with Flurry and Google Analytics. I'm very pleased with Flurry and even though some of the other services also look good, I feel no need to try them. (This is not a review, only a recommendation...)

http://support.flurry.com/images/logo.gif
Flurry Analytics
Flurry can be used in iOS, Android, Blackberry, Windows Phone, JavaME and HTML5.

The API is super easy to install and use and compared to Google Analytics which is originally made for webpages and not really adapted to mobile apps, Flurry is designed for mobile apps. For example, if you use a UITabBarController or UINavigationController, you can with one line of code in your app delegate track all "page" views controlled by that controller.

The free analytics package is all you need to get all plenty of feedback on how your app is doing out there.

Check the webpage by clicking the logo above for more information.

2012年2月1日水曜日

If you have some experience with objective oriented languages and want to learn Objective-C, or if you already started learning Objective-C but want to learn more from a great instructor, I have a tip for you.

Stanford University publishes their iOS App Development lectures on iTunes U, for anyone to download. Both HD videos and lecture notes are available.

There is material available from older quarters if you want to go for Xcode 3 and iOS 4. New material from 2011 is also available, which includes iOS 5, Xcode 4, Storyboard, iCloud and other new features of iOS 5.

The instructor is Paul Hegarty. He explains very well and makes the videos enjoyable to watch. You will learn not only the technical part of iOS and Objective-C but also how to create user friendly apps, what to avoid and best practices. One of the best instructors you can get.

I've watched all videos from both quarters below and even if you've seen Fall 2010 I highly recommend Fall 2011 because there is plenty of new information about the new features of iOS 5.

For iOS 4, please look at: Fall 2010

Developing Apps for iOS (HD)



For iOS 5, please look at: Fall 2011

iPad and iPhone Application Development (HD)


If you're looking for a good book, I can recommend this one. It explains in detail how Objective-C works and will give you a good insight into the language. -Link to Amazon-


Objective-C and iOS - Online learning resources

If you have some experience with objective oriented languages and want to learn Objective-C, or if you already started learning Objective-C but want to learn more from a great instructor, I have a tip for you.

Stanford University publishes their iOS App Development lectures on iTunes U, for anyone to download. Both HD videos and lecture notes are available.

There is material available from older quarters if you want to go for Xcode 3 and iOS 4. New material from 2011 is also available, which includes iOS 5, Xcode 4, Storyboard, iCloud and other new features of iOS 5.

The instructor is Paul Hegarty. He explains very well and makes the videos enjoyable to watch. You will learn not only the technical part of iOS and Objective-C but also how to create user friendly apps, what to avoid and best practices. One of the best instructors you can get.

I've watched all videos from both quarters below and even if you've seen Fall 2010 I highly recommend Fall 2011 because there is plenty of new information about the new features of iOS 5.

For iOS 4, please look at: Fall 2010

Developing Apps for iOS (HD)



For iOS 5, please look at: Fall 2011

iPad and iPhone Application Development (HD)


If you're looking for a good book, I can recommend this one. It explains in detail how Objective-C works and will give you a good insight into the language. -Link to Amazon-


2012年1月31日火曜日

Nexus SをAndroid 4.0.3にUpdateしました。
波形をとりながら動作確認中を行ったところ、面白い発見をしたので記事にしました。


キーガードロック画面のNFC動作
まずはAndroid2.3.6 GingerBread版Nexus Sの波形です。


電源キーによりスクリーンOFF → ONを行いキーガードロック画面を表示しました。
スクリーンON中はNFC電源ONになり、その波形が現れています。
約5秒後、再びスクリーンOFFになりました。


次はAndroid4.0.3 Ice Cream Sandwich版Nexus Sの波形です。


同じ操作でキーガードロック画面を表示しました。
しかし、スクリーンONになってもNFC電源ONの波形が現れません!

どうやら、ICSの変更でキーガードロック中はNFC電源が入らないように修正されているようです。


プログラムを確認してみましょう。
まずは、Android2.3.6 GingerBreadのプログラムです。
スクリーンON/OFFの動作処理を行っているのは以下のファイルです。
\packages\apps\Nfc\src\com\android\nfc
- NfcService.java

private class EnableDisableDiscoveryTask extends AsyncTask {
@Override
protected Void doInBackground(Boolean... enable) {
if (enable != null && enable.length > 0 && enable[0]) {
synchronized (NfcService.this) {
mScreenOn = true;
applyRouting();
}
} else {
:
}
return null;
}
}

private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
:
} else if (intent.getAction().equals(Intent.ACTION_SCREEN_ON)) {
:
new EnableDisableDiscoveryTask().execute(new Boolean(true));
} else if (intent.getAction().equals(Intent.ACTION_SCREEN_OFF)) {
:
}
}


以下の処理により、電源ONになりNFCタグ受信待ち状態となります。
  1. スクリーンONのIntentであるIntent.ACTION_SCREEN_ONを受信する
  2. EnableDisableDiscoveryTask().execute()をコール
  3. applyRouting()をコール
  4. mManager.enableDiscovery(DISCOVERY_MODE_READER)をコール



つぎは、Android4.0.3 Ice Cream Sandwichのプログラム確認。
\packages\apps\Nfc\src\com\android\nfc
- NfcService.java

/**
* Read mScreenState and apply NFC-C polling and NFC-EE routing
*/
void applyRouting(boolean force) {
synchronized (this) {
:
// configure NFC-C polling
if (mScreenState >= POLLING_MODE) {
if (force || !mNfcPollingEnabled) {
Log.d(TAG, "NFC-C ON");
mNfcPollingEnabled = true;
mDeviceHost.enableDiscovery();
}
} else {
if (force || mNfcPollingEnabled) {
Log.d(TAG, "NFC-C OFF");
mNfcPollingEnabled = false;
mDeviceHost.disableDiscovery();
}
}
}
}



class ApplyRoutingTask extends AsyncTask {
@Override
protected Void doInBackground(Integer... params) {
synchronized (NfcService.this) {
if (params == null || params.length != 1) {
// force apply current routing
applyRouting(true);
return null;
}
mScreenState = params[0].intValue();

boolean needWakelock = mScreenState == SCREEN_STATE_OFF;
if (needWakelock) {
mWakeLock.acquire();
}
applyRouting(false);
if (needWakelock) {
mWakeLock.release();
}
return null;
}
}
}

private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
:
} else if (action.equals(Intent.ACTION_SCREEN_ON)
|| action.equals(Intent.ACTION_SCREEN_OFF)
|| action.equals(Intent.ACTION_USER_PRESENT)) {
// Perform applyRouting() in AsyncTask to serialize blocking calls
int screenState = SCREEN_STATE_OFF;
if (action.equals(Intent.ACTION_SCREEN_OFF)) {
screenState = SCREEN_STATE_OFF;
} else if (action.equals(Intent.ACTION_SCREEN_ON)) {
screenState = mKeyguard.isKeyguardLocked() ?
SCREEN_STATE_ON_LOCKED : SCREEN_STATE_ON_UNLOCKED;
} else if (action.equals(Intent.ACTION_USER_PRESENT)) {
screenState = SCREEN_STATE_ON_UNLOCKED;
}
new ApplyRoutingTask().execute(Integer.valueOf(screenState));
} else if (action.equals(ACTION_MASTER_CLEAR_NOTIFICATION)) {
:
}
}


以下のように処理が変更され、スクリーンONでは電源ONとなりません。
  1. スクリーンONのIntentであるIntent.ACTION_SCREEN_ONを受信する
  2. mKeyguard.isKeyguardLocked()でキーガード状態かどうか確認する
  3. キーガード状態の場合、SCREEN_STATE_ON_LOCKEDを引数としてApplyRoutingTask().execute()をコール
  4. applyRouting(false)をコール
  5. mScreenStateがSCREEN_STATE_ON_LOCKEDなので、mDeviceHost.enableDiscovery()はコールしない

電源ONとなるタイミングはIntent.ACTION_USER_PRESENTを受信した時、
つまり、キーガードが解除された時に電源ONとなります。

キーガード中のNFC動作 GingerBread と Ice Cream Sandwichの違い

Nexus SをAndroid 4.0.3にUpdateしました。
波形をとりながら動作確認中を行ったところ、面白い発見をしたので記事にしました。


キーガードロック画面のNFC動作
まずはAndroid2.3.6 GingerBread版Nexus Sの波形です。


電源キーによりスクリーンOFF → ONを行いキーガードロック画面を表示しました。
スクリーンON中はNFC電源ONになり、その波形が現れています。
約5秒後、再びスクリーンOFFになりました。


次はAndroid4.0.3 Ice Cream Sandwich版Nexus Sの波形です。


同じ操作でキーガードロック画面を表示しました。
しかし、スクリーンONになってもNFC電源ONの波形が現れません!

どうやら、ICSの変更でキーガードロック中はNFC電源が入らないように修正されているようです。


プログラムを確認してみましょう。
まずは、Android2.3.6 GingerBreadのプログラムです。
スクリーンON/OFFの動作処理を行っているのは以下のファイルです。
\packages\apps\Nfc\src\com\android\nfc
- NfcService.java

private class EnableDisableDiscoveryTask extends AsyncTask {
@Override
protected Void doInBackground(Boolean... enable) {
if (enable != null && enable.length > 0 && enable[0]) {
synchronized (NfcService.this) {
mScreenOn = true;
applyRouting();
}
} else {
:
}
return null;
}
}

private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
:
} else if (intent.getAction().equals(Intent.ACTION_SCREEN_ON)) {
:
new EnableDisableDiscoveryTask().execute(new Boolean(true));
} else if (intent.getAction().equals(Intent.ACTION_SCREEN_OFF)) {
:
}
}


以下の処理により、電源ONになりNFCタグ受信待ち状態となります。
  1. スクリーンONのIntentであるIntent.ACTION_SCREEN_ONを受信する
  2. EnableDisableDiscoveryTask().execute()をコール
  3. applyRouting()をコール
  4. mManager.enableDiscovery(DISCOVERY_MODE_READER)をコール



つぎは、Android4.0.3 Ice Cream Sandwichのプログラム確認。
\packages\apps\Nfc\src\com\android\nfc
- NfcService.java

/**
* Read mScreenState and apply NFC-C polling and NFC-EE routing
*/
void applyRouting(boolean force) {
synchronized (this) {
:
// configure NFC-C polling
if (mScreenState >= POLLING_MODE) {
if (force || !mNfcPollingEnabled) {
Log.d(TAG, "NFC-C ON");
mNfcPollingEnabled = true;
mDeviceHost.enableDiscovery();
}
} else {
if (force || mNfcPollingEnabled) {
Log.d(TAG, "NFC-C OFF");
mNfcPollingEnabled = false;
mDeviceHost.disableDiscovery();
}
}
}
}



class ApplyRoutingTask extends AsyncTask {
@Override
protected Void doInBackground(Integer... params) {
synchronized (NfcService.this) {
if (params == null || params.length != 1) {
// force apply current routing
applyRouting(true);
return null;
}
mScreenState = params[0].intValue();

boolean needWakelock = mScreenState == SCREEN_STATE_OFF;
if (needWakelock) {
mWakeLock.acquire();
}
applyRouting(false);
if (needWakelock) {
mWakeLock.release();
}
return null;
}
}
}

private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
:
} else if (action.equals(Intent.ACTION_SCREEN_ON)
|| action.equals(Intent.ACTION_SCREEN_OFF)
|| action.equals(Intent.ACTION_USER_PRESENT)) {
// Perform applyRouting() in AsyncTask to serialize blocking calls
int screenState = SCREEN_STATE_OFF;
if (action.equals(Intent.ACTION_SCREEN_OFF)) {
screenState = SCREEN_STATE_OFF;
} else if (action.equals(Intent.ACTION_SCREEN_ON)) {
screenState = mKeyguard.isKeyguardLocked() ?
SCREEN_STATE_ON_LOCKED : SCREEN_STATE_ON_UNLOCKED;
} else if (action.equals(Intent.ACTION_USER_PRESENT)) {
screenState = SCREEN_STATE_ON_UNLOCKED;
}
new ApplyRoutingTask().execute(Integer.valueOf(screenState));
} else if (action.equals(ACTION_MASTER_CLEAR_NOTIFICATION)) {
:
}
}


以下のように処理が変更され、スクリーンONでは電源ONとなりません。
  1. スクリーンONのIntentであるIntent.ACTION_SCREEN_ONを受信する
  2. mKeyguard.isKeyguardLocked()でキーガード状態かどうか確認する
  3. キーガード状態の場合、SCREEN_STATE_ON_LOCKEDを引数としてApplyRoutingTask().execute()をコール
  4. applyRouting(false)をコール
  5. mScreenStateがSCREEN_STATE_ON_LOCKEDなので、mDeviceHost.enableDiscovery()はコールしない

電源ONとなるタイミングはIntent.ACTION_USER_PRESENTを受信した時、
つまり、キーガードが解除された時に電源ONとなります。
Kaspersky Endpoint Security, which claims to be compatible with Lion, apparently is not.

Before upgrading to Lion I had no problems with Xcode or other application freezing and becoming "not responding". After upgrading, Xcode, which I use all day in my work, often freezes, sometimes other applications too. Usually it returns to normal state if I wait 1-5 minutes, but sometimes not and unsaved data is lost when I have to force quit Xcode (before I discovered how to quit Kaspersky's process). The really bad thing is that it's when saving that Kaspersky locks up the saving application so the chances of loosing valuable work is high.

If you are required to run Kaspersky on your Mac, I recommend that you do not upgrade to Lion until Kaspersky has fixed to support Lion's Autosave and Versions.

If Xcode or any other application locks up, open "Activity Monitor" and quit the process "kav". This will release the lock on the frozen application but (it looks like) Kaspersky will automatically restart so you have to repeat this every time an application freezes when saving data.

I'm not alone:
Cocoabuilder.com: Xcode4 and Lion causes freezes when saving
Stackoverflow.com: Xcode is very slow to save a file frequently beach balls

Waiting for a fix...

Lion + Kaspersky + Xcode = Trouble...

Kaspersky Endpoint Security, which claims to be compatible with Lion, apparently is not.

Before upgrading to Lion I had no problems with Xcode or other application freezing and becoming "not responding". After upgrading, Xcode, which I use all day in my work, often freezes, sometimes other applications too. Usually it returns to normal state if I wait 1-5 minutes, but sometimes not and unsaved data is lost when I have to force quit Xcode (before I discovered how to quit Kaspersky's process). The really bad thing is that it's when saving that Kaspersky locks up the saving application so the chances of loosing valuable work is high.

If you are required to run Kaspersky on your Mac, I recommend that you do not upgrade to Lion until Kaspersky has fixed to support Lion's Autosave and Versions.

If Xcode or any other application locks up, open "Activity Monitor" and quit the process "kav". This will release the lock on the frozen application but (it looks like) Kaspersky will automatically restart so you have to repeat this every time an application freezes when saving data.

I'm not alone:
Cocoabuilder.com: Xcode4 and Lion causes freezes when saving
Stackoverflow.com: Xcode is very slow to save a file frequently beach balls

Waiting for a fix...

2012年1月25日水曜日

In one of my apps I have data as csv files in the bundle and at when the app is run for the first time I parse these files and create a database using Core Data. During development I often added more data to the csv files, adjusted the Core Data classes and so on, so I needed a smooth way of telling whether the app was run for the first time or not since the last build so I can reconstruct the database.

I first tried another solution that didn't require the target name "MYTARGET" in the script which means you don't have to customize the script for every project but I couldn't get that to work in Xcode 4.2 but here is a script that works great for me. I will link to the source if I remember it later.

In the project navigator, select your project and then your target to the right.
In the "Info"-tab, create a new "Custom iOS Target Property" called "BuildNumber" and let it be a string.
Select the tab "Build Phases" and "Add Build Phase" down to the right.
Select "Add Run Script" and set the shell to "/bin/bash"
Paste in this script: (replace MYTARGET with the name of your target (usually same as name of project)

#!/bin/bash
buildNumber=$(/usr/libexec/PlistBuddy -c "Print BuildNumber" MYTARGET/MYTARGET-Info.plist)
buildNumber=$(($buildNumber + 1))
/usr/libexec/PlistBuddy -c "Set :BuildNumber $buildNumber" MYTARGET/MYTARGET-Info.plist

bundleShortVersion=$(/usr/libexec/PlistBuddy -c "Print CFBundleShortVersionString" MYTARGET/MYTARGET-Info.plist)
bundleVersion=$bundleShortVersion"."$buildNumber
/usr/libexec/PlistBuddy -c "Set :CFBundleVersion $bundleVersion" MYTARGET/MYTARGET-Info.plist

Now, each time you build your app the variable "BuildNumber" will be increased by 1 and your bundle version will be set to Version.BuildNumber. That is, if your app version is 1.0 and your on build number 8, the bundle version will be 1.0.8.

If you, in your app delegate or elsewhere, want to check if the "BuildNumber" has changed since the last run by comparing it with the last value, stored in NSUserDefaults, do something like:

int thisVersion = [[[[NSBundle mainBundle] infoDictionary] objectForKey:@"BuildNumber"] intValue];
int lastVersion = [[NSUserDefaults standardUserDefaults] integerForKey:@"lastVersion"];
[[NSUserDefaults standardUserDefaults] setInteger:thisVersion forKey:@"lastVersion"];
BOOL appIsNewVersion = lastVersion != thisVersion;

And there, you have a smooth, automated way of telling if you're on a new build and do the proper initializing, etc.

Auto incrementing build number in Xcode

In one of my apps I have data as csv files in the bundle and at when the app is run for the first time I parse these files and create a database using Core Data. During development I often added more data to the csv files, adjusted the Core Data classes and so on, so I needed a smooth way of telling whether the app was run for the first time or not since the last build so I can reconstruct the database.

I first tried another solution that didn't require the target name "MYTARGET" in the script which means you don't have to customize the script for every project but I couldn't get that to work in Xcode 4.2 but here is a script that works great for me. I will link to the source if I remember it later.

In the project navigator, select your project and then your target to the right.
In the "Info"-tab, create a new "Custom iOS Target Property" called "BuildNumber" and let it be a string.
Select the tab "Build Phases" and "Add Build Phase" down to the right.
Select "Add Run Script" and set the shell to "/bin/bash"
Paste in this script: (replace MYTARGET with the name of your target (usually same as name of project)

#!/bin/bash
buildNumber=$(/usr/libexec/PlistBuddy -c "Print BuildNumber" MYTARGET/MYTARGET-Info.plist)
buildNumber=$(($buildNumber + 1))
/usr/libexec/PlistBuddy -c "Set :BuildNumber $buildNumber" MYTARGET/MYTARGET-Info.plist

bundleShortVersion=$(/usr/libexec/PlistBuddy -c "Print CFBundleShortVersionString" MYTARGET/MYTARGET-Info.plist)
bundleVersion=$bundleShortVersion"."$buildNumber
/usr/libexec/PlistBuddy -c "Set :CFBundleVersion $bundleVersion" MYTARGET/MYTARGET-Info.plist

Now, each time you build your app the variable "BuildNumber" will be increased by 1 and your bundle version will be set to Version.BuildNumber. That is, if your app version is 1.0 and your on build number 8, the bundle version will be 1.0.8.

If you, in your app delegate or elsewhere, want to check if the "BuildNumber" has changed since the last run by comparing it with the last value, stored in NSUserDefaults, do something like:

int thisVersion = [[[[NSBundle mainBundle] infoDictionary] objectForKey:@"BuildNumber"] intValue];
int lastVersion = [[NSUserDefaults standardUserDefaults] integerForKey:@"lastVersion"];
[[NSUserDefaults standardUserDefaults] setInteger:thisVersion forKey:@"lastVersion"];
BOOL appIsNewVersion = lastVersion != thisVersion;

And there, you have a smooth, automated way of telling if you're on a new build and do the proper initializing, etc.

2012年1月23日月曜日

My first post. I guess it would be a good a idea to share what I do whenever I start a new project in Xcode.

It has kind of become a habit of mine to log to console at almost every method for easy bug tracking. However, using NSLog doesn't show you what method unless you do something like:

NSLog(@"MyViewController:viewDidLoad");

Which is rather cumbersome when you add logging to many methods. This is where my savior comes into the picture.

By adding the following to your "MyApp-Prefix.pch" file in the "Supporting Files"-group

// DLog is almost a drop-in replacement for NSLog
// DLog();
// DLog(@"here");
// DLog(@"value: %d", x);
// Unfortunately this doesn't work DLog(aStringVariable); you have to do this instead DLog(@"%@", aStringVariable);
#ifdef DEBUG
# define DLog(fmt, ...) NSLog((@"%s [Line %d] " fmt), __PRETTY_FUNCTION__, __LINE__, ##__VA_ARGS__);
#else
# define DLog(...)
#endif

// ALog always displays output regardless of the DEBUG setting
#define ALog(fmt, ...) NSLog((@"%s [Line %d] " fmt), __PRETTY_FUNCTION__, __LINE__, ##__VA_ARGS__);

you can use ALog (always log) and DLog (debug log) for a rich debug logging.
Simply putting DLog(); in your viewDidAppear method will output something like:

[MainViewController viewDidAppear:] [Line 169]

Even showing the line number where in your source code the line was executed. And don't worry about performance or similar, when compiling for release DLog(); is defined to nothing so there will be no logging going on.

The blog post where I found this information is >>here

First post, logging.

My first post. I guess it would be a good a idea to share what I do whenever I start a new project in Xcode.

It has kind of become a habit of mine to log to console at almost every method for easy bug tracking. However, using NSLog doesn't show you what method unless you do something like:

NSLog(@"MyViewController:viewDidLoad");

Which is rather cumbersome when you add logging to many methods. This is where my savior comes into the picture.

By adding the following to your "MyApp-Prefix.pch" file in the "Supporting Files"-group

// DLog is almost a drop-in replacement for NSLog
// DLog();
// DLog(@"here");
// DLog(@"value: %d", x);
// Unfortunately this doesn't work DLog(aStringVariable); you have to do this instead DLog(@"%@", aStringVariable);
#ifdef DEBUG
# define DLog(fmt, ...) NSLog((@"%s [Line %d] " fmt), __PRETTY_FUNCTION__, __LINE__, ##__VA_ARGS__);
#else
# define DLog(...)
#endif

// ALog always displays output regardless of the DEBUG setting
#define ALog(fmt, ...) NSLog((@"%s [Line %d] " fmt), __PRETTY_FUNCTION__, __LINE__, ##__VA_ARGS__);

you can use ALog (always log) and DLog (debug log) for a rich debug logging.
Simply putting DLog(); in your viewDidAppear method will output something like:

[MainViewController viewDidAppear:] [Line 169]

Even showing the line number where in your source code the line was executed. And don't worry about performance or similar, when compiling for release DLog(); is defined to nothing so there will be no logging going on.

The blog post where I found this information is >>here

Related Posts Plugin for WordPress, Blogger...