iPhone アプリケーション
-
はてな touch/Hatena touch
-
LDR touch
-
テレビ番組表/TV Listings
-
LCD Clock by forYou Inc.
-
MyWebClip by forYou Inc.
-
MyWebClip LITE by forYou Inc.
-
Japan Subway Route Map by Studio Heat
-
こころくろっく by AppBank
-
英辞郎 on the WEB for iPhone by アルク
-
i-Radio by i-Radio
-
くるりんぱ性格診断 by 小学館
-
英辞郎検索ランキング(アルク) by アルク
-
kotobank - コトバンク by genesix
-
miil by frogapps
iPad アプリケーション
Windows 8 Store アプリケーション
共著
2013-04-22
iOS/Macの両方で使えて、文字の選択やリンクのクリックに対応したテキストビューをテスト公開しました。
iPhone, Mac, Objective-C, Cocoa
kishikawakatsumi/SECoreTextView ? GitHub


SECoreTextView はリッチテキストの表示と文字の選択(現在はOS Xのみ)やリンクがクリック可能だったりするテキストビューです。
別のアプリでテーブルビューのセルにリンクを含むテキストを表示するのに、既存のものでMacで使えるいい感じのものが今ひとつ見つからなかったので書きました。
OS X で使うだけだとなんなので、せっかくだから iOS にも対応してみました。
UITableVIewやNSTableVIewのセルで使うと便利だと思います。
iOS のほうは半日くらいでちょちょっと書いただけなのでおかしなところが結構あると思うので見つけたら教えてください。
2012-12-29
iPhone の画面操作を録画するライブラリを公開しました。
iPhone, Objective-C, Cocoa, iPad
kishikawakatsumi/ScreenRecorder ? GitHub
ScreenRecorder は iOS デバイスの画面を連続的にキャプチャして、動画に変換することで画面の操作を録画することができる機能をアプリケーションに追加します。
開発中のソフトウェアのユーザーテストなどに利用すると効果的です。
使い方
1. 以下のファイルをプロジェクトに追加します
- Lib/SRScreenRecorder.h
- Lib/SRScreenRecorder.m
- Vendor/KTouchPointerWindow.h
- Vendor/KTouchPointerWindow.m
2. 以下のフレームワークをリンクします
- QuartzCore.framework
- CoreVideo.framework
- CoreMedia.framework
- AVFoundation.framework
startRecording で録画を開始します。
デフォルトの設定は
- バックグラウンドに入ったときに自動保存
- 10 分ごとに自動保存、ファイルのローテート
- 30FPSで録画
- タッチ箇所の表示
となっています。
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { [[SRScreenRecorder sharedInstance] startRecording]; return YES; }
いくつかの挙動は、設定で変更することができます。
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { SRScreenRecorder *recorder = [SRScreenRecorder sharedInstance]; recorder.frameInterval = 1; // 60 FPS recorder.autosaveDuration = 1800; // 30 minutes recorder.showsTouchPointer = NO; // hidden touch pointer recorder.filenameBlock = ^(void) { return @"screencast.mov"; }; // change filename [recorder startRecording]; return YES; }
タッチ・ポインターの表示には @itok_twit さんの KTouchPointerWindow を利用しています。
iPhone/iPadの画面にタッチ位置を表示するためのソースコード KTouchPointerWindow を公開しました
2012-10-24
リンクするだけで iOS 6 で Google Map が使えるようになる YAMapKit を公開しました。
iPhone, Objective-C, Cocoa, iPad
kishikawakatsumi/YAMapKit ? GitHub
YAMapKit は MapKit.framework と(ほぼ)互換性のある代替ライブラリです。
Google Maps Javascript API と UIWebView を利用して iOS 6 で Apple の標準地図の代わりに Google Map を使った表示ができます。
MapKit.framework と(ほぼ)互換性があるのでリンク先を差し替えるだけで動作します(たいていの場合は)。
あまりヘビーな利用には向きませんが、アプリケーションの中でちょっと MapKit を使って地図を表示したりピンを挿したりしているという場合に効果的です。
まだ未サポートの機能がたくさんあるので、手伝ってくれる方や、バグレポート、要望を歓迎します。
使い方
- MapKit.framework のリンクを外します。
- libMapKit.a をリンクします。
- CoreLocation.framework をリンクします。
できないこと
- ジオコーディング(代わりに 'CLGeocoder' を使ってください)
- カスタムビューのオーバーレイ表示(組み込みのオーバーレイ (MKPolylineView, MKCircleView など) しか使えません)
- アノテーションのドラッグ&ドロップ
- アノテーションのコールアウトを表示したあとで更新する
(たぶん他にもいっぱいあります)
利用例
2012-10-23
Objective-C でサブクラスのインスタンスから任意のスーパークラスのメソッドを呼ぶ
iPhone, Cocoa, Objective-C, iPad
サブクラスのインスタンスからポリモーフィズムを無視して任意のスーパークラスのメソッドを呼びます。
↓ 下のように Shape クラスと Shape クラスを継承した Path クラス、および Path クラス を継承した Circle があります。
それぞれのクラスで draw メソッドをオーバーライドしています。
//////////////////////////////////////////////////////////////////////// #pragma mark - Shape //////////////////////////////////////////////////////////////////////// @interface Shape : NSObject @end @implementation Shape - (void)draw { NSLog(@"%@", @"Shape."); } @end //////////////////////////////////////////////////////////////////////// #pragma mark - Path //////////////////////////////////////////////////////////////////////// @interface Path : Shape @end @implementation Path - (void)draw { NSLog(@"%@", @"Path."); } @end //////////////////////////////////////////////////////////////////////// #pragma mark - Circle //////////////////////////////////////////////////////////////////////// @interface Circle : Path @end @implementation Circle - (void)draw { NSLog(@"%@", @"Circle."); } @end
↓ Circle クラスのインスタンスから draw メソッドを呼び出すと Circle クラスの draw メソッドが実行されて "Circle." と出力されます。
たまに多態性を無視してスーパークラスや、スーパークラスのさらにスーパークラスのメソッドを実行したいということってありますよね。
そういうときは 対象メソッドの IMP (メソッドを参照する関数へのポインタ) を使います。
#import <UIKit/UIKit.h> @interface ViewController : UIViewController @end @implementation ViewController - (void)viewDidLoad { [super viewDidLoad]; Shape *shape = [[Circle alloc] init]; [shape draw]; // => Circle. SEL selector = @selector(draw); void(*pathFunction)(id, SEL, ...) = (void(*)(id, SEL, ...))[Path instanceMethodForSelector:selector]; pathFunction(shape, selector); // => Path. void(*shapeFunction)(id, SEL, ...) = (void(*)(id, SEL, ...))[Shape instanceMethodForSelector:selector]; shapeFunction(shape, selector); // => Shape. } @end
↑ IMP の定義のままだと ARC が戻り値を retain しようとするので、戻り値が void の関数ポインタにキャストしています。
↓ 上記のコードの出力は下記になります。
2012-10-23 13:15:20.632 Monomorphism[50033:c07] Circle. 2012-10-23 13:15:20.633 Monomorphism[50033:c07] Path. 2012-10-23 13:15:20.633 Monomorphism[50033:c07] Shape.
サブクラスのインスタンスからポリモーフィズムを無視して任意のスーパークラスのメソッドが呼べました。
↓ 試したコードの全体を載せておきます。
#import <UIKit/UIKit.h> @interface ViewController : UIViewController @end //////////////////////////////////////////////////////////////////////// #pragma mark - Shape //////////////////////////////////////////////////////////////////////// @interface Shape : NSObject @end @implementation Shape - (void)draw { NSLog(@"%@", @"Shape."); } @end //////////////////////////////////////////////////////////////////////// #pragma mark - Path //////////////////////////////////////////////////////////////////////// @interface Path : Shape @end @implementation Path - (void)draw { NSLog(@"%@", @"Path."); } @end //////////////////////////////////////////////////////////////////////// #pragma mark - Circle //////////////////////////////////////////////////////////////////////// @interface Circle : Path @end @implementation Circle - (void)draw { NSLog(@"%@", @"Circle."); } @end @implementation ViewController - (void)viewDidLoad { [super viewDidLoad]; Shape *shape = [[Circle alloc] init]; [shape draw]; // => Circle. SEL selector = @selector(draw); void(*pathFunction)(id, SEL, ...) = (void(*)(id, SEL, ...))[Path instanceMethodForSelector:selector]; pathFunction(shape, selector); // => Path. void(*shapeFunction)(id, SEL, ...) = (void(*)(id, SEL, ...))[Shape instanceMethodForSelector:selector]; shapeFunction(shape, selector); // => Shape. } @end
2012-10-20
iOS 6.0 と iOS 5.x の両方で動作するアプリケーションをビルドする設定
iPad, Xcode, Objective-C, Cocoa, iPhone
iOS 4.0 と iPhone OS 3.x の両方で動作するアプリケーションをビルドする設定 - 24/7 twenty-four seven
↑ こちらも参考に
iOS 4.0 が登場したくらいのときに上の記事を書いて、仕組みは変わってないのですけど Xcode 4.x 系だと UI が変わってるので現在のやり方をまとめます。
ベース SDK と Deployment Target を設定する
プロジェクトの "Build Settings" で "Base SDK" を "Latest iOS" にします。
前にも書きましたが、ベース SDK は最新を指定したほうがいいです。
プロジェクトの "Info" で "Deployment Target" をサポートする OS の最も低いバージョンにします。
(下の場合は iOS 5.0 以降で動作する。)
今なら、Base SDK 6.0 でビルドして、Deployment Target を 5.0 または 5.1 にするのが効果的でしょうか。2世代サポートということで。
新しい Framework を Weak Link (Optional) に設定する
古い環境には含まれていない Framework をリンクしていると、Dynamic Linker がシンボルのロードに失敗してアプリケーションが起動しません。
その場合は、新しい OS にのみ存在する Framework を Weak Link に設定します(今回は Social.framework)。
↑ リンクの設定はプロジェクトではなくターゲットに対してしか行えないので、ターゲットを選択して "Build Phases" > "Link Binary With Libraries" から設定します。
リンクするフレームワークを設定して、 Required > Optional に変更します。
OS のバージョンごとに処理を分岐する
古い API には存在しないセレクタを呼び出したり、クラスを参照したりするとクラッシュしますので必要に応じて処理を分岐します。
- (void)tweet:(id)sender { Class clazz = NSClassFromString(@"SLComposeViewController"); if (clazz) { SLComposeViewController *controller = [SLComposeViewController composeViewControllerForServiceType:SLServiceTypeTwitter]; [self presentViewController:controller animated:YES completion:nil]; } else { TWTweetComposeViewController *controller = [[TWLandscapeTweetComposeViewController alloc] init]; [self presentViewController:controller animated:YES completion:nil]; } }
Auto Layout に注意
Auto Layout は iOS 6 以降しか使えません。Auto Layout を使用していると iOS 5.x などで起動時に関連のクラスが無くてクラッシュします。StoryBoard を新しく追加したときなどにうっかり Auto Layout のチェックをつけたままにしてしまったりするので注意しましょう。
2012-10-05
iOS 6 では Supported interface orientations の順番に注意!
iPhone, Xcode, iPad, Objective-C, Cocoa
最近の Xcode ではアプリケーションが対応しているデバイスの向きをターゲットの Summary 画面から GUI を用いて設定できるようになりましたが、ここから設定する場合はボタンを押す順番に注意する必要があります。
というのも、この画面で設定した内容は、Info.plist の Supported interface orientations (UISupportedInterfaceOrientations) に反映されるのですが、この項目は Array の値で順番が起動時の状態に影響するからなのです。
上記の画面の状態になるように、ボタンを左から順に押していった場合、Info.plist の UISupportedInterfaceOrientations は下記のようになります。これは新規プロジェクトを作成した場合のデフォルト値です。
今度は同じ状態になるように、ボタンを「右から」順に押していきます。すると Info.plist は下記のようになります。
値の順番が変わっています。
実はこの順番は起動時の画面の向きに関係していて、iOS 6 では一番先頭に指定されている画面の向きで起動することになります。
つまり、前の例では縦画面で起動するのですが、後の例では横向きで起動することになります。
別のキーに Initial interface orientation (UIInterfaceOrientation) というものがあって、こちらを指定すると初期状態を指定できそうですが、試したところ iOS 6 ではどうもこの値は無視されるようです。
2012-10-04
iOS 6 ではグループスタイルのテーブルビューの背景色がこっそり非推奨になっている。
iOS 6 では上記のカラーを生成するメソッドがヘッダのコメントでひそかに deprecated になっています。
UIInterface.h
// Group style table view backgrounds can no longer be represented by a simple color. // If you want to have a background in your own view that looks like the table view background, // then you should create an empty table view and place it behind your content. + (UIColor *)groupTableViewBackgroundColor; // This method will be deprecated during the 6.0 seed program
ドキュメントの記載は変わってないのですが、実際に使ってみると今までは下記のコードでピンストライプのカラーが設定されていましたが、iOS 6 だと真っ黒になってしまいます。
self.view.backgroundColor = [UIColor groupTableViewBackgroundColor];
この背景色を使いたい場合は空のテーブルビューを設定しろということなので、iOS 6 から代替のコードは下記のようになります。
UITableView *tableView = [[UITableView alloc] initWithFrame:self.view.bounds style:UITableViewStyleGrouped]; [self.view addSubview:tableView];
2012-10-01
はやりのシンボルフォントを iOS で画像として扱える SymbolFontKit を公開しました。
iPhone, Objective-C, Cocoa, iPad
kishikawakatsumi/SymbolFontKit ? GitHub

↑ シミュレータに表示されている画像やツールバーのボタン、タブバーのアイコンは全てフォントです。
シンボルフォントとは要するにアイコン画像などをフォント形式にしたものです。
Webだと最近のブラウザだとWebフォントが使えるので、利用者の環境にフォントがインストールされていなくても使えるので、最近は解像度非依存ということもあっていろいろな Github や Twitter などいろいろなサイトで利用されています。
シンボルフォントについて詳しくは下記のリンク先などを見てください。
Ligature Symbols 〜ほんとにべんりなフォントのはなし〜
【完全版】Ligature Symbols フォントセットの自作方法 - くらげだらけ
で、フォントなのでベクターデータのためどんな解像度でもキレイに表示されることや、1つのアイコンで色違いや別のサイズを表示することが簡単だったり、はやっているので様々なデザインのシンボルフォントが使いやすいライセンスで入手できるなど、iOS でも利用できたら便利だと思って作りました。
使い方
- SFKImage.h/m をプロジェクトにコピーします。
- 利用したいフォントファイルをプロジェクトにコピーします。
- 上記でコピーしたフォントファイルのファイル名を UIAppFonts をキーにして Info.plist に追加します。
API は UIImage 互換なので UIImage と同様の使い方ができます。(実は現在は imageNamed: 以外のインスタンス化はできません)
SFKImage *image = [SFKImage imageNamed:@"print"];
インスタンス化した SFKImage オブジェクトは UIImage のインスタンスと同様に UIButton や UIImageView、UITabBarItem などに直接設定することができます。
self.imageView1.image = [SFKImage imageNamed:@"share"]; UITabBarItem *calendarTabBarItem = [[UITabBarItem alloc] initWithTitle:@"calendar" image:[SFKImage imageNamed:@"calender"] tag:1]; UITabBarItem *globeTabBarItem = [[UITabBarItem alloc] initWithTitle:@"globe" image:[SFKImage imageNamed:@"globe"] tag:2]; _tabBar.items = @[calendarTabBarItem, globeTabBarItem];
フォントのレンダリングは実際に画面に描画されるときまで遅延されるので、UIImage と違って、1つのインスタンスを途中で色や大きさを変えたりできます。
SFKImage *image = [SFKImage imageNamed:@"compass"]; image.size = CGSizeMake(20, 20); image.color = [UIColor redColor]; self.imageView6.image = image; image.size = CGSizeMake(40, 40); image.color = [UIColor yellowColor]; self.imageView7.image = image; image.size = CGSizeMake(80, 80); image.color = [UIColor blueColor]; self.imageView8.image = image;
UIImage として振る舞うためにちょっと無茶をしているのでそのまま AppStore の審査に通るかどうかは「?」ですが近いうちに適当なアプリを提出して調査したいと思います。
SymbolFontKit は第1回iphone_dev_jp東京 iPhone/Mac Hackathon 〜みんなが幸せになるハッカソン〜の成果物です。
2012-09-25
2012-09-18
はてなブックマークの ShareKit 拡張を書きました
ShareKit/Classes/ShareKit/Sharers/Services/Hatena at hatena ? kishikawakatsumi/ShareKit ? GitHub
ShareKit といういろいろな外部サービスとの連携機能を提供するライブラリがあるのですが、それのプラグイン (ShareKit では Sharer と呼びます) として「はてなブックマーク」とリンクを共有するものを書きました。
オリジナルを fork して hatena ブランチにコミットしています。利用するには clone して hatena ブランチに切り替えます。
本家にPull Request を送ったので、もしかしたらマージされるかもしれません。
(既存の Sharer に日本のサービスはなかったのでイマイチ勝手がわかりませんでした。)
↓ 発端は fladdict さんとの下記のやりとりです。
アプリではてぶをサポートしようとしたら、APIがキモイしメンドクサイので断念した。ライブラリないかな。なければあきらめよう。
2012-08-26 23:12:48 via web
@fladdict はてブするほう?なんやったら書きますよ。はてな応援。
2012-08-26 23:29:18 via Echofon to @fladdict
@k_katsumi おお、ありがとうございます! とりあえず、昨日おみせしたやつTestFlightしますね
2012-08-27 00:01:18 via web to @k_katsumi
@fladdict どうもっす。仕様とあと適当に締切を設定してくれたら間に合うように書きます。
2012-08-27 00:06:16 via Echofon to @fladdict
@k_katsumi うぃ、仕様書というか、ShareKitがわりとイイ感じなのでこれにはてなを追加しようかなぁと思ってたところなんです。URL
2012-08-27 00:08:27 via web to @k_katsumi
@fladdict なるほど。じゃあShareKitを見て合わせてみます。なんやったらPullReqしよ。
2012-08-27 00:10:24 via Echofon to @fladdict
@akisutesama @k_katsumi sharekitはステキライブラリですよ。もっと流行るべき
2012-08-27 01:13:56 via web to @akisutesama
はてなブックマークへの投稿は昔書いたことがあったので、認証を OAuth にしたらあとはカンタンそうだなと思って安請け合いしました。いやまあ、特に難しいことはなかったんですけど。
@fladdict ShareKitってこのリポジトリで合ってます?最後の更新が2年以上前っぽいですけど。 URL
2012-08-31 16:45:26 via Echofon to @fladdict
@fladdict はてなブックマークのShareKit拡張書いたよー URL hatenaブランチをチェックアウトしてください。
2012-09-04 04:26:28 via YoruFukurou to @fladdict
@k_katsumi ありがとうございまっす!!! さっそく組み込むです!
2012-09-04 11:52:08 via web to @k_katsumi
@fladdict OAuthだけでいいっすよね。ただiOS6でサンブルプロジェクトで動かすとたまにクラッシュすることがあった気がします。まだ直せてない。あとOAMutableURLRequestを拡張してるのは付属のに2重エンコードのバグがあったからです。
2012-09-04 11:53:28 via Echofon to @fladdict
@k_katsumi おお、2重エンコードなんてしてたのですねぇ。そのfix本家におつたえしたら喜ばれそう。
2012-09-04 11:55:36 via web to @k_katsumi
ShareKitのOAuthConsumerの2重エンコードこれね。 URL これだとKeyとValueをURLエンコードしたあとさらにエンコードするから「extraOAuthParametersがある場合に」シグネチャがおかしくなる。
@k_katsumi おぉ。なるほです!
2012-09-04 12:06:08 via web to @k_katsumi
↑ ちょっとだけハマったのは、付属している OAuth ライブラリ (OAuthConsumer) が不具合のあるリビジョンのもので、シグネチャを組み立てるときに追加の OAuth パラメータの部分を2重に URL エンコードしていました。
そのため、はてなの OAuth は必ずコールバック URL を oauth_callback パラメータで指定する必要があるのですが、シグネチャが invalid になって OAuth が成功しないということがありました。
↓ こちらの不具合は別の Pull Request でパッチを送ったので現在は修正されています。
@k_katsumi うーん、「認証要求に問題が発生しました」って怒られる。Consumer = APIキー Secret = 秘密鍵ですよね。Callbackはアプリ登録時のものにしてます。plistじゃなくてクラス内にキー直書きでいいんですよね。
2012-09-04 12:37:28 via web to @k_katsumi
@fladdict 僕の環境だとSHKHatena.mの82行目をwrite_publicだけにしたら通りました。scopeパラメータは完全にはてなの仕様なので詳しい人に聞かないとわからないっすねえ。
2012-09-04 13:34:33 via Echofon to @fladdict
@k_katsumi はてなAPI、不正トークンエラーとかもバリバリでて、なんかAPIがすごい不安定ですよねぇ。社内的にAPI全然興味ないのかしらとか思う。
2012-09-04 14:45:40 via web to @k_katsumi
@fladdict 何回かの割合でトークンが不正って言われちゃいますよね。。。あんまり安定しないようだとID, PASSWORDでWSSE認証するほうも用意しますわ。
2012-09-04 14:47:22 via Echofon to @fladdict
@k_katsumi ありがとうございますー。とりあえず埋め込んだものをもうちょっとブラッシュしてTestFlightを発射できるようにしますね!
2012-09-04 14:50:45 via web to @k_katsumi
↑ そんなこんなでとりあえず書いてみた割りにはちゃんと使えてるようでよかったです。
OAuth で許可するスコープに write_private を書いたら失敗する点とか気になるところはあるけど。。。
はてなブックマークのShareKit拡張もこのままPullRequest送ろうかしら。さっきのが取り込まれたらファイルが1組減るんだけど。 URL
@k_katsumi いいね!
2012-09-16 14:21:06 via web to @k_katsumi
@fladdict 一点サービス名をローカライズ(Hatena Bookmark => はてなブックマーク)しようかどうか考えていて、他にサービス名をローカライズしてるところがない(必要がない)からstringsファイルに追記していいものかどうか悩んでいます。
2012-09-16 14:26:57 via Echofon to @fladdict
@k_katsumi なくていいんじゃないでしょうか。日本語サービスは日本人以外みんなが困るのでw
2012-09-16 14:27:55 via web to @k_katsumi
@fladdict そですね。僕もそんな気がします。
2012-09-16 14:28:55 via Echofon to @fladdict
↑ Pull Request しました。↓
Add Hatena Bookmark Sharer. by kishikawakatsumi ? Pull Request #521 ? ShareKit/ShareKit ? GitHub


































