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-11-08
Windows 8 StoreアプリケーションでGoogleAnalyticsを使う
WinJS, Windows Metro, Windows 8
kishikawakatsumi/GoogleAnalytics-for-WinJS ? GitHub
Windows 8の Store アプリケーションで GoogleAnalytics を使う場合、まだ公式の SDK はありませんが、サードパーティからすでにいくつかライブラリがリリースされているのでそれを使うのがいいと思います。
ただ JavaScript(WinJS) で書いた Metro Style アプリケーション用のものはまだ無いみたいなので Windows Runtime Component を使って WinJS から C# のライブラリを扱う方法でやってみました。
Google Analytics for WinRT - Home
NuGet Gallery | Google Analytics for WinRT (Windows 8) apps 2.4
↑ GoogleAnalytics にリクエストを送る Windows 8 用のライブラリはいくつかありますが、今回はソースコードも公開されていて実装もシンプルな Google Analytics for WinRT - Home を使いました。
Windows Runtime Component のプロジェクトをソリューションに追加する
↓ 詳しい方法は下記のドキュメントを見てください。
Walkthrough: Creating a simple component in C# or Visual Basic and calling it from JavaScript
チュートリアル : C# または Visual Basic での単純なコンポーネントの作成および JavaScript による呼び出し
- Solution Explorer でソリューションを右クリックして、Add > New Project... と選択します。
- Visual C# > Windows Runtime Component と選択して、プロジェクト名を適当につけて [OK] を押します。
- Solution Explorer でWindows Store アプリケーションのプロジェクトを右クリックして、Add Reference... を選択します。
- Solution > Projects と選択して、先ほどの Windows Runtime Component として作ったプロジェクトにチェックをつけて [OK] を押します。
↑ ここまででこんな感じになります。
GoogleAnalytics のライブラリをプロジェクトに追加する
先ほどの Windows Runtime Component のプロジェクトから利用できるように GoogleAnalytics のライブラリを追加します。
- Solution Explorer でプロジェクトを右クリックして、Add > New Folder と選択します。
- そのフォルダに 'Nascent.GoogleAnalytics.dll' をコピーします。
- Solution Explorer で Windows Runtime Component のプロジェクトを右クリックして、Add Reference... を選択します。
- [Browse...] ボタンを押して 'Nascent.GoogleAnalytics.dll' を選択します。
- 'Nascent.GoogleAnalytics.dll' にチェックをつけて [OK] を押します。
ライブラリの呼び出しをブリッジするクラスを書く
↓ こんな感じで。
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using Nascent.GoogleAnalytics; namespace WindowsRuntimeGoogleAnalytics { public sealed class Tracker { public string webPropertyId { get; set; } public Tracker(string id) { webPropertyId = id; } public void SetCustomVariable(int index, string name, string value) { AnalyticsTracker tracker = AnalyticsTracker.GetInstance(webPropertyId); tracker.SetCustomVariable(index, name, value); } public void TrackPageView(string page) { AnalyticsTracker tracker = AnalyticsTracker.GetInstance(webPropertyId); tracker.TrackPageView(page); } public void TrackEvent(string category, string action) { AnalyticsTracker tracker = AnalyticsTracker.GetInstance(webPropertyId); tracker.TrackEvent(category, action, null, null); } public void TrackEvent(string category, string action, string label) { AnalyticsTracker tracker = AnalyticsTracker.GetInstance(webPropertyId); tracker.TrackEvent(category, action, label, null); } } }
JSのインターフェースを書く
↓ 直接呼んでもいいけどまとまってると何かと使いやすいのでこんな感じで。
(function () { "use strict"; var Tracker = WinJS.Class.define( function (webPropertyId) { this.webPropertyId = webPropertyId; this.tracker = new WindowsRuntimeGoogleAnalytics.Tracker(webPropertyId); }, { setCustomVariable: function (index, name, value) { var that = this; that.tracker.setCustomVariable(index, name, value); }, trackPageView: function (page) { var that = this; that.tracker.trackPageView(page); }, trackCurrentPageView: function () { var that = this; var page = Application.navigator.pageControl.uri.replace("ms-appx://" + Windows.ApplicationModel.Package.current.id.name.toLowerCase(), ""); that.trackPageView(page); }, trackEvent: function (category, action, label) { var that = this; that.tracker.trackEvent(category, action, label); } }); WinJS.Namespace.define("GoogleAnalytics", { Tracker: new Tracker("UA-4291014-7") }); })();
WinJS から呼び出してみる
↓ たとえば、画面が表示されるたびにアクセスを記録するならこんな感じで。
ready: function (element, options) { GoogleAnalytics.Tracker.trackCurrentPageView(); var listView = element.querySelector(".groupeditemslist").winControl; listView.groupHeaderTemplate = element.querySelector(".headertemplate"); 〜(略)〜
↓ 今回のサンプルコードはこちらです。
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
はてな touch 1.2.7 をリリースしました。

はてな touch 1.2.7 がアップルの審査を通過しました。
iOS 6, iPhone 5をサポートしました。
変更点
- iOS 6, iPhone 5をサポートしました。


































