iOS 9 のコンテンツブロックで始まる HTTP 2.0 時代の Web 広告

iOS 9 から Safari の Extension 機能としてコンテントブロックの実装が可能になった。 developer.apple.com Web ページ内の特定の HTML 要素を見えなくしたり、特定のURLのロードをブロックする仕組みを Apple は ブラウザ Safari に提供した、それだけである。しかしこれにより Web ページの広告やトラッカーといったJavaScriptの読み込みを遮断する Safari 拡張アプリの実装が可能になることから、実質 Apple が Web 広告を潰しにきたと iOS 9 発表当時から話題になった。 実際 iOS 9 リリースとともに広告・トラッカーをブロックするアプリがストアに並び、ランキングの上位に躍り出ることになった。以前から Apple が Web 広告を蔑ろにしていることは、iOS 5 で Safari に追加したリーダー(Web ページの記事の文章だけにフォーカスする)機能などから伺えた。ただこれは読み込んだページに対して機能することと、ブログなど Safari が記事ページと判断したときだけ有効になるので、広告潰しとして話題になることはなかった。 少し話が逸れるがニュースアプリの SmartNews がリリースされた当初、ネットワークがオフラインでも先読みしてニュース記事の文章だけを表示するという機能が物議を醸したことがあった。その後 SmartNews はメディアと協業していく形で成功している。 ブラウザに広告ブロック機能が追加できることは目新しいことではない。PC ブラウザではアドオン・拡張機能として古くからある。昔から言われているのはこういったアドオンをインストールする人は、そもそも広告を踏むことはないので収入には影響がないという話だ。概ね正しいと思うが、厳密には広告インプレッションは減ってしまう。 これまでと状況が異なるのはブラウザのアドオンマーケットと違い、普通に iPhone を使う人がその存在を認知できる形で提供されることだ。無料アプリであればソムリエな学生の口コミで瞬く間に普及するシナリオは大いにあり得る。ユーザーからすれば広告を消すことにデメリットはない。通信量も減りブラウジングが軽くなるのは事実で、特にバッテリーで動作するスマホには恩恵が大きい。過去に Android もブロックアプリがストアに並んでいたが、広告収入がメインの Google は一斉に排除している。 もし無視できないほど広告ブロックアプリが普及したらどうなるのか。iOS の Safari は今のネットにおいてトップシェアを誇るため、確実に収益減少に繋がる。その一方で、ブロック機能をオフにしないとサイトの閲覧をさせないようにする方法はある。サイトに広告が表示できたかどうか検証するスクリプトを直接ページに埋め込み、ブロックされた場合にコンテンツを隠すようにできるからだ。コンテンツに自信のあるサイトは、ブロックアプリを排除するか会員制に移行するか選択するだろう。 ちなみにトラッカーまでブロックされるとステルスアクセスになり、Google Analytics でページビューを把握してると単に訪問者が減ったように見える。Web サーバの HTTP アクセスログと照らし合わせないとわからない。 ここで立ち戻って、なぜ広告をブロックしたい状況なのか考える。以下の2点が大きい。 鬱陶しく広告の載せているサイトがある。スマホでは成人向けの広告が一般サイトで表示されることも多い。 広告・トラッカーのスクリプトをクライアントサイドでロード・処理しているため、ユーザー負担が大きい。 一方でサイト運営者はなぜ広告を掲載するのか大きく分けると以下の2つだ。 ...

2015年9月25日 · Toshimitsu Takahashi

iOSアプリエンジニア養成読本を共著させていただきました

技術評論社さんから刊行されますiOSアプリエンジニア養成読本[クリエイティブな開発のための技術力/デザイン力/マインドを養う!]を執筆させていただきました。 日頃お世話になっているクラスメソッド株式会社のエンジニアの諏訪さん、平屋さん、平井さんとフリーランスのyumulab 湯村さんとの共著になります。 自分が書いたのは三章立ての巻頭特集**「iOSエンジニアとして食べていくために知っておくべき14の重要スキルと知識 ~Appleの世界で生きるための処世術」**になります。 iOSアプリの開発からリリースまでに必要となるスキルや持っていた方がいい知識を、自分のこれまでの経験を基に網羅的に書いたものになります。 副題にあるとおり、iOSアプリを取り巻く世界はAppleによってコントロールされているため、良くも悪くもその中で巧くやる必要があります。 それらを特に、これからiOSエンジニアを目指す方・1年未満の方、既にやっているけどアプリのリリースをしたことは無い方、iOSの受託開発をしようとしている会社のプロジェクトリーダー・マネージャーの方を念頭に、幅広くそして嵌りやすい点は掘り下げて書かせていただきました。 特集1, 3, 4 についてはクラスメソッドさんのエンジニアの御三方のコメントをご覧下さい。 iOSアプリエンジニア養成読本執筆のお知らせ | Developers.IO 養成読本というサフィックスですが、他の方の特集記事も含めてエキスパートで無い限りは何かしら得るものがある本になっています。 書店でお見かけの際はぜひに手に取っていただけると幸いです。 iOSアプリエンジニア養成読本[クリエイティブな開発のための技術力/デザイン力/マインドを養う! ] (Software Design plus) 作者: ?橋俊光,諏訪悠紀,湯村翼,平屋真吾,平井祐樹 出版社/メーカー: 技術評論社 発売日: 2014/03/20 メディア: 大型本 ※ 自分の苗字を本来のはしごだかで書誌登録してもらったところ、UTF-8の全盛の現代でも文字化けや欠けになる場合があるみたいです。

2014年3月12日 · Toshimitsu Takahashi

iOS 7 設定画面の色定義まとめ

グループテーブルビューなどで使うことがあるので、iOS 7 設定画面の各種パーツの色定義をまとめた。 セル 背景 #FFFFFF 1 [UIColor colorWithRed:1.0 green:1.0 blue:1.0 alpha:1.0] テキスト #000000 1 [UIColor colorWithRed:0.0 green:0.0 blue:0.0 alpha:1.0] 詳細テキスト #8E8E93 1 [UIColor colorWithRed:0.556 green:0.556 blue:0.576 alpha:1.0] ディスクロージャ #C7C7CC 1 [UIColor colorWithRed:0.78 green:0.78 blue:0.8 alpha:1.0] ボタン #007AFF 1 [UIColor colorWithRed:0.0 green:0.478 blue:1.0 alpha:1.0] 強調ボタン #FF3B30 1 [UIColor colorWithRed:1.0 green:0.231 blue:0.188 alpha:1.0] セクションヘッダ・フッタ テキスト #6D6D72 1 [UIColor colorWithRed:0.427 green:0.427 blue:0.447 alpha:1.0] 背景 #EFEFF4 1 [UIColor colorWithRed:0.937 green:0.937 blue:0.956 alpha:1.0]

2013年11月22日 · Toshimitsu Takahashi

iOS 6 の新しいアクションシート機能を UIActivityViewController で実装する (2)

iOS 6 の新しいアクションシート機能を UIActivityViewController で実装する - Tosshi Note で iPhone アプリへのアクティビティ連携の実装方法を書きました。 そのiPad版です。例によって、UIPopoverController を使います。UIActivityViewController をコンテントビューコントローラとしてラップします。 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 - (IBAction)actionButtonPressed:(id)sender { NSString *ttl = @"Tosshi Note"; NSURL *url = [NSURL URLWithString:@"http://d.hatena.ne.jp/tilfin/"]; NSArray *activityItems = [NSArray arrayWithObjects:ttl, url, nil]; UIActivityViewController *activityView = [[UIActivityViewController alloc] initWithActivityItems:activityItems applicationActivities:nil]; _actionPopover = [[UIPopoverController alloc] initWithContentViewController:actionViewController]; [_actionPopover presentPopoverFromBarButtonItem:_actionButtonItem permittedArrowDirections:UIPopoverArrowDirectionAny animated:YES]; [activityView release]; } 上記の _actionPopover はそのまま present して autorelease するとメモリアクセス不正で落ちるので、dismiss以降にリリースをかけましょう。

2012年10月23日 · Toshimitsu Takahashi

iOS 6 の新しいアクションシート機能を UIActivityViewController で実装する

iOS 6 から Safari やカメラロールなどのアクションボタンをタップすると、タイル状に並んだアイコンから [Twitter や Facebook への共有機能などが呼び出せるようになりました。 下記のように、OS標準以外のアプリにもこの機能を簡単に追加できます。 このアクションシートの機能は UIActivityViewController に集約されているので、これを呼び出すだけです。ただ単純にコピペ実装できるエントリが見つからなかったので紹介しておきます。 上記のように、よくある Twitter, Facebook などにテキストとURLを投稿するときの方法です。 1 2 3 4 5 6 7 8 9 10 11 12 13 14 - (IBAction)actionButtonPressed:(id)sender { NSString *ttl = @"Tosshi Note"; NSURL *url = [NSURL URLWithString:@"http://d.hatena.ne.jp/tilfin/"]; NSArray *activityItems = [NSArray arrayWithObjects:ttl, url, nil]; UIActivityViewController *activityView = [[UIActivityViewController alloc] initWithActivityItems:activityItems applicationActivities:nil]; [self presentViewController:activityView animated:YES completion:^{ }]; [activityView release]; } UIActivityViewController の initWithActivityItems:applicationActivities: メソッドを使って、activityItems には NSString と NSURL を NSArray にまとめて渡します。 applicationActivities には、独自のアクティビティ(機能)を渡すことでさらに追加できます。今回は、システムの標準に従って表示させるため、nil にしています。 表示させたくないアクティビティは、excludedActivityTypes プロパティに、以下の Built-in Activity Types 定数を使って NSArray でセットします。 http://developer.apple.com/library/ios/#documentation/UIKit/Reference/UIActivity_Class/Reference/Reference.html Built-in Activity Types の項には、それぞれアクティビティの説明に activityItems に指定できるリソースが書かれています。

2012年10月12日 · Toshimitsu Takahashi

iOS バージョンとデバイス対応のまとめ

未明に iPhone 5, iPod touch (5th generation) の発表がありました。 開発用に今後の端末のバージョンバリエーションをどうするか考えるため、まとめておく。 最新 iOS 6.0 まで対応するデバイス iPhone 5 *, iPhone 4S, iPhone 4, iPhone 3GS iPod touch (5th generation) *, iPod touch (4th generation) iPad (3rd generation), iPad 2 * ディスプレイ 1136×640 ピクセル 既にバージョン対応が止まっているデバイス iOS 5.1.1 iPad (1st generation) iPod touch (3rd generation) iOS 4.2.1 (マルチタスク非対応) iPhone 3G iPod touch (2nd generation) iOS 3.1.3 iPod touch (1st generation) iOS 5 以上であれば端末のみでアップグレードできるため、既存端末への普及は普通に進むと思われる。零細開発者としては「iOS 5 未満は切り捨て」が現実的なところだろうか。

2012年9月13日 · Toshimitsu Takahashi

iOS デバイスで現在 iPod で再生中の曲情報を取得するには

iPhone, iPad, iPod touch で音楽などを再生したりするには、MediaPlayer.framework を使います。 MPMusicPlayerController が音楽を再生を制御するコントローラクラスでこのクラスメソッドの iPodMusicPlayer を使うと iPod のコントローラが取得できます。 さらに nowPlayingItem プロパティからその名の通り再生中(一時停止している場合も含む)のデータを MPMediaItem インスタンスで取得できます。 MPMediaItem からメタデータを各フィールドを表す定数を指定して取り出せます。アイテムの種別は MPMediaItemPropertyMediaType で NSInteger をカプセル化した NSNumber で取得できます。 以下は、曲を再生中の場合に曲名、アルバム名、アーティストそしてアートワークの80x80画像をそれぞれ取得しています。 #import <MediaPlayer/MediaPlayer.h> MPMusicPlayerController *pc = \[MPMusicPlayerController iPodMusicPlayer\]; MPMediaItem *playingItem = \[pc nowPlayingItem\]; if (playingItem) { NSInteger mediaType = \[\[playingItem valueForProperty:MPMediaItemPropertyMediaType\] integerValue\]; if (mediaType == MPMediaTypeMusic) { NSString *songTitle = \[playingItem valueForProperty:MPMediaItemPropertyTitle\]; NSString *albumTitle = \[playingItem valueForProperty:MPMediaItemPropertyAlbumTitle\]; NSString *artist = \[playingItem valueForProperty:MPMediaItemPropertyArtist\]; textView.text = \[NSString stringWithFormat:@"%@ \- %@ / %@", artist, songTitle, albumTitle\]; MPMediaItemArtwork *artwork = \[playingItem valueForProperty:MPMediaItemPropertyArtwork\]; UIImage *artworkImage = \[artwork imageWithSize:CGSizeMake(80.0, 80.0)\]; UIImageView *artworkImageView = \[\[UIImageView alloc\] initWithImage:artworkImage\]; } }

2011年10月27日 · Toshimitsu Takahashi

Xcode 4 のユニバーサルプロジェクト構成を考える

Xcode 3 から Xcode 4 になってウィザードから生成されるプロジェクトの構成も変わっている。 iPhone, iPadで共通化するユニバーサルで、ユニットテストありにした Windows Base プロジェクトを生成すると下記のようになる。 ファイルシステム上は、プロジェクト名のフォルダにxcodeprojectフォルダさらに同名のプロジェクトフォルダとTestsがサフックスに付いたテストフォルダが並ぶ。 プロジェクトフォルダにはiPhone, iPadが並ぶ。 WindowExample - WindowExample.xcodeproj - WindowExample - iPhone - iPad - WindowExampleTests Xcode 3 のようにClasses, Resourcesがない。自分も経験的に、XIBファイルと対になるViewControllerクラスは並んでいた方が扱いやすい。テンプレートでクラスを追加したときに同時に生成されるのでまとまっていた方が良いだろう。 ユニーバサルであればビューのベース部分やそもそも共通クラスがある(Common)。さらにイメージファイルもグループ化すると良いだろう(Images)。ほかにもユーティリティ群などが並ぶだろう(Utilities)。 ファイルシステム上もiPhone, iPad, Common, Images, Utilitiesはフォルダにする。クラス数が多ければ各グループ内もさらにグループ化した方がいいだろう。 ただこれらのグループは、画面数の増加などアプリの修正・機能追加に伴って柔軟に変えられる方が良いと考える。よって、ファイルシステム上はフラットに管理することにする。 WindowExample - WindowExample.xcodeproj - WindowExample - iPhone - iPad - Common - Utilities - Images - WindowExampleTests Xcode は Visual Studio, Eclipse のようにプロジェクトのファイル構成がファイルシステムと同一ではない。Java をやってきた人には気持ち悪いかもしれない。パッケージや名前空間という概念は Objective-C にはない。グループはあくまでも人間から見た管理のしやすさだ。 Xcode はファイル追加後にファイルシステム上の移動をするのが非常に面倒である。このため、ファイルの上の場所は追加するときに確定させた方が良い。ただグループもフラットだと管理上破綻するだろう。これが前述のような構成にした理由だ。 まとめると、 プロジェクトフォルダ、テストフォルダを分ける。 プロジェクトフォルダの直下は、iPhone, iPad, iPhone・iPad共通でグループをわける。 これらのグループはそのままファイルシステム上フォルダ化にする。 第2階層以降のグループは Xcode プロジェクトのみで管理し、ファイルシステムには適用しない。 となる。

2011年8月29日 · Toshimitsu Takahashi

iPhoneとiPadで処理を替えるには

直ぐ忘れるのでメモ。iOS 3.2以降で使用可能。 float fs; if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPhone) { fs = 11.0; } else { // if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) fs = 13.0; } return [UIFont fontWithName:@“Helvetica” size:fs];

2011年8月22日 · Toshimitsu Takahashi

UITableViewでセクションヘッダをタップするとそのセクションの先頭にスクロールさせるには

iPhone, iPad で長いリストを扱うときにセクションの固まり項目をきれいに表示させたくなります。 Newstrush というニュースリーダーアプリでは、記事のカテゴリ毎にセクション化しています。 ↓ このアプリではセクションのヘッダ部分をタップすると、そこが先頭にくるように細工をしてあります。 実装方法は下記の通り。 セクションヘッダビューの定義 セクションヘッダ用のカスタムViewを作成します。 カスタム init メソッドでセクションインデックスとテーブルビューのポインタを渡して、touchesEnded イベントでUITableViewの scrollRectToVisible メソッドにセクションから始まる画面領域の矩形を渡して呼び出します。 TableSectionHeaderView.h #import <UIKit/UIKit.h> @interface TableSectionHeaderView : UIView { @private id _tableView; int _sectionIndex; } \- (id)initWithSectionIndex:(NSUInteger)index forTable:(id)tableView; @end TableSectionHeaderView.m #import "TableSectionHeaderView.h" @implementation TableSectionHeaderView \- (id)initWithSectionIndex:(NSUInteger)index forTable:(id)tableView { self = \[super init\]; if (self) { _sectionIndex = index; _tableView = tableView; } return self; } \- (void)dealloc { _tableView = nil; \[super dealloc\]; } \- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event { CGRect rect_ = \[\_tableView rectForSection:\_sectionIndex\]; rect_.size.height = \[_tableView frame\].size.height; \[\_tableView scrollRectToVisible:rect\_ animated:YES\]; } @end ※ UITableView の参照は相互で retain しないように id にしてあります。 ...

2011年7月9日 · Toshimitsu Takahashi