OS X Mountain Lion 10.8.5 上でウェブブラウザ Google Chrome に使われている JavaScript engine V8 を試す。

enchantMOON ; The Hypertext Authoring Tablet
http://enchantmoon.com/

賛否両論がある enchantMOON を 2013/07/13(Sat) にアスキーストアで予約しました。随分待たされましたが、2013/09/21(Sat) に到着しました。URL を入力して Web を開くシールを作ってみました。次回にでも公開したいと思います。

enchantMOON が到着するまでに時間があったので、以前から興味があった enchantMOON の JavaScript Based Virtual Machine (EAGLEVM) に利用されている V8 を試してみました。

Chrome V8 — Google Developers
https://developers.google.com/v8/

V8 は、ウェブブラウザ Google Chrome に使われている JavaScript engine です。プログラミング言語 C++ で書かれています。私の C++ の知識は、

C++ Primer(5th Edition)

C++ Primer (5th Edition)

C++ Primer (5th Edition)

を読んだ程度です。ほとんど C++ でプログラミングをしたことがない初心者です。

ソースのダウンロードは

How to Download and Build V8 - Chrome V8 — Google Developers
https://developers.google.com/v8/build
Source - v8 - How to get the V8 source code - V8 JavaScript Engine - Google Project Hosting
http://code.google.com/p/v8/wiki/Source

Git を使わず Subversion を利用しました。

ターミナル上で

~ $ svn checkout http://v8.googlecode.com/svn/trunk/ v8

上記コマンド svn を用いてソースコードを入手しました。

BuildingWithGYP - v8 - Instructions to build V8 using GYP - V8 JavaScript Engine - Google Project Hosting
http://code.google.com/p/v8/wiki/BuildingWithGYP

OS X Mountain Lion 上では GYP が正しく動作しないようなので、上記ページと v8/build/ReadMe.txt を参考に

~ $ cd v8
~/v8 $ make dependencies
~/v8 $ make x64.release
~/v8 $ make x64.release.check

上記コマンドを実行しました。

Getting Started - Chrome V8 — Google Developers
https://developers.google.com/v8/get_started
Getting Started
Audience
Hello World
Run the Hello World example

上記ページ、最初に紹介されている Hello World のソースは handle、scope、context が追加されていないので、ビルドできません。その下の Hello World サンプルソースを hello_world.cc として保存し、v8 フォルダにコピーします。ターミナル上で次のコマンド

~/v8 $ g++ -Iinclude hello_world.cc -o hello_world out/x64.release/libv8_base.x64.a out/x64.release/libv8_snapshot.a out/x64.release/libicu{data,i18n,uc}.a -lpthread

を実行するとビルドできました。実際に hello_world を実行すると次のように

~/v8 $ ./hello_world
Hello, World!
~/v8 $ 

表示されます。

ディレクトリ v8/out/x64.release には

~/v8 $ cd out/x64.release/
~/v8/out/x64.release $ ls
cctest			libv8_nosnapshot.x64.a	obj.target
d8			libv8_snapshot.a	preparser
libicudata.a		lineprocessor		process
libicui18n.a		mksnapshot.x64		shell
libicuuc.a		obj
libv8_base.x64.a	obj.host
~/v8/out/x64.release $ 

hello_world.cc のビルドに必要なライブラリ

libv8_base.x64.a
ibv8_snapshot.a
libicudata.a
libicui18n.a
libicuuc.a

と v8/samples のサンプルをビルドした実行ファイル

shell
process
lineprocessor

Javascript インタプリタ d8 が含まれています。以下が d8 の実行例です。

~ $ cd v8/out/x64.release/
~/v8/out/x64.release $ ./d8
V8 version 3.22.1 [console: dumb]
d8> var x=Math.sqrt(2);
undefined
d8> x
1.4142135623730951
d8> var r = function(x,y,x1,y1) { return Math.sqrt((x1-x)*(x1-x)+(y1-y)*(y1-y)); };
undefined
d8> r(0,0,1,1);
1.4142135623730951
d8> r(0,0,1,Math.sqrt(3));
1.9999999999999998
d8> quit()
~/v8/out/x64.release $ 

v8/samples ディレクトリのサンプルソースを理解するには、

~ $ cd v8/samples
~/v8/samples $ ls
count-hosts.js		process.cc		shell.cc
lineprocessor.cc	samples.gyp
~/v8/samples $ 
Getting Started - Chrome V8 — Google Developers
https://developers.google.com/v8/get_started
Getting Started
Embedder's Guide - Chrome V8 — Google Developers
https://developers.google.com/v8/embed
▼ Documentation
Embedder's Guide

上記ページが参考になります。サンプル Hello World や Contexts、自作の関数を定義するのに利用する Templates など、基本的な仕組みを理解するのに便利です。

v8: v8::String Class Reference
http://izs.me/v8-docs/classv8_1_1String.html

また、上記ページで各クラスの説明を見ることができます。ディレクトリ v8/src、v8/include には、ソースやヘッダがあるので勉強になると思います。

私自身、初歩的なことがわかっていなかったので、

// hello_world.cc
Handle<String> source = String::New("'Hello' + ', World!'");

の String::New() は Local 返すのに Handle に代入していたので、疑問に思っていたのですが、Local は Handle を継承しているのですね!

また、process.cc 351行目

string ObjectToString(Local<Value> value) {
String::Utf8Value utf8_value(value);
return string(*utf8_value);
}

の *utf8_value が理解できなかったのですが、

~ $ cd v8/include
~/v8/include $ grep -e "class V8_EXPORT Utf8Value" *.h
v8.h:  class V8_EXPORT Utf8Value {
~/v8/include $ 
// ~/v8/include/v8.h 1838 行目
class V8_EXPORT Utf8Value {
public:
explicit Utf8Value(Handle<v8::Value> obj);
~Utf8Value();
char* operator*() { return str_; }
const char* operator*() const { return str_; }
int length() const { return length_; }

String::Utf8Value には、上の char* operator*() { return str_; } ように * 演算子が定義されているのですね!

Sample Code - Chrome V8 — Google Developers
https://developers.google.com/v8/samples
▼ Documentation
Sample Code

上記ページでサンプルコード、process.cc、shell.cc の簡単な説明があります。

~/v8/samples $ ls
count-hosts.js		process.cc		shell.cc
lineprocessor.cc	samples.gyp
~/v8/samples $ 

上記 v8/samples ディレクトリあるサンプルコード shell.cc、process.cc、lineprocessor.cc を説明したいと思います。

説明をしやすいように、下記のようにディレクトリ v8/samples 内のすべてのファイルをディレクトリ v8/out/x64.release/ に cp コマンドを使ってコピーしました。

~ $ cd v8/samples/
~/v8/samples $ cp *.* ../out/x64.release/
~/v8/samples $ 

■サンプルコード shell.cc

shell.cc は、コマンドライン引数として –help、–shell、ファイル名を指定できます。

~ $ cd v8/out/x64.release/
~/v8/out/x64.release $ ./shell
V8 version 3.22.1 [sample shell]
> 1+1
2
> var x=1;
> print(x);
1
> var text = read("shell.cc");
> print(text);
....
> load("count-hosts.js");
> version();
3.22.1
> quit();
~/v8/out/x64.release $ 

shell.cc
99行目より、自作関数として print()、read()、load()、quit()、version() が使えます。

print(x)		: 引数を表示する。
read(filename)	: 引数のファイルを読み込む
load(filename)	: 引数のファイルを読み込み、コンパイルして実行する。
quit()			: プログラム終了
version() 		: バージョン表示

shell のコマンドライン引数に javascript ファイルを指定すると javascript ファイルを実行します。

~/v8/out/x64.release $ ./shell count-hosts.js
~/v8/out/x64.release $ 

実行した後、shell モードに入りたい場合は、コマンドライン引数に –shell を指定します。

~/v8/out/x64.release $ ./shell count-hosts.js --shell
V8 version 3.22.1 [sample shell]
> Initialize();
> var request = {host:"localhost", path:"/", referrer:"apple.com", userAgent:"Safari"};
> var options = {verbose:0};
> var output = {};
> Process(request);
> print(output);
[object Object]
> print(request.host);
localhost
> print(output["localhost"]);
1
> quit();
~/v8/out/x64.release $ 

■サンプルコード process.cc

process.cc は v8/samples ディレクトリある Javascript ファイル count-hosts.js を利用します。

プログラム process.cc 内で log 関数、変数 options.verbose、output を作り、process.cc 599行目

const int kSampleSize = 6;
StringHttpRequest kSampleRequests[kSampleSize] = {
StringHttpRequest("/process.cc", "localhost", "google.com", "firefox"),
StringHttpRequest("/", "localhost", "google.net", "firefox"),
StringHttpRequest("/", "localhost", "google.org", "safari"),
StringHttpRequest("/", "localhost", "yahoo.com", "ie"),
StringHttpRequest("/", "localhost", "yahoo.com", "safari"),
StringHttpRequest("/", "localhost", "yahoo.com", "firefox")
};
StringHttpRequest("/process.cc", "localhost", "google.com", "firefox"),
を例にとると
var request = {path:"/proces.cc", host:"localhost",  referrer:"google.com", userAgent:"firefox"};
になります。

で宣言されているそれぞれの request を Javascript ファイル count-hosts.js 内の Process 関数で呼び出します。結果が、変数 output に格納されます。output の内容は、process,cc 652行目

PrintMap(&output);

で表示します。実行結果は

~/v8/out/x64.release $ ./process count-hosts.js
google.com: 1
google.net: 1
google.org: 1
yahoo.com: 3
~/v8/out/x64.release $ 

になります。 ./process のコマンドライン引数として verbose=true を宣言すると log 関数が呼び出されます。

~/v8/out/x64.release $  ./process count-hosts.js verbose=true
Logged: Processing google.com/process.cc from localhost@firefox
Logged: Processing google.net/ from localhost@firefox
Logged: Processing google.org/ from localhost@safari
Logged: Processing yahoo.com/ from localhost@ie
Logged: Processing yahoo.com/ from localhost@safari
Logged: Processing yahoo.com/ from localhost@firefox
google.com: 1
google.net: 1
google.org: 1
yahoo.com: 3
~/v8/out/x64.release $ 

■サンプルコード lineprocessor.cc

lineprocessor は、コマンドライン引数として –main-cycle-in-cpp、–main-cycle-in-js のどちらかを指定することで違った動作をします。ループ処理を C++側か、Javascript 側で行うかの違いがあります。

サンプルコード lineprocessor.cc の 56 行目にある

function ProcessLine(input_line) {
return ">>>" + input_line + "<<<";
}

の部分を main-cycle-in-cpp.js という名前で保存します。

コマンドライン引数を main-cycle-in-cpp.js、–main-cycle-in-cpp とし、実行すると

~/v8/out/x64.release $ ./lineprocessor main-cycle-in-cpp.js --main-cycle-in-cpp
hello
>>>hello<<<
bye
>>>bye<<<
^C
~/v8/out/x64.release $ 

lineprocessor.cc 内で入力処理を行い、Javascript ファイルの関数 ProcessLine(input_line) を呼び出します。関数 ProcessLine(input_line) の返り値を下記 RunCppCycle 関数内の

    printf("%s\n", cstr);

で表示します。

272行目

bool RunCppCycle(v8::Handle<v8::Script> script,
v8::Local<v8::Context> context,
bool report_exceptions) {

lineprocessor.cc 側の上記 RunCppCycle 関数内でループ処理を行います。

サンプルコード lineprocessor.cc の 66 行目にある

while (true) {
var line = read_line();
if (!line) {
break;
}
var res = line + " | " + line;
print(res);
}

の部分を main-cycle-in-js.js という名前で保存します。

コマンドライン引数を main-cycle-in-js.js 、–main-cycle-in-js としてし、実行すると

~/v8/out/x64.release $ ./lineprocessor main-cycle-in-js.js --main-cycle-in-js
hello
hello | hello
bye
bye | bye
^C
~/v8/out/x64.release $ 

lineprocessor.cc 内で read_line() を定義し、Javascript 側でループ処理をおこないます。

lineprocessor.cc の肝は、デバッガに対応していることです。

Google Chrome Developer Tools for Java

V8 でデバッガを利用するには、Google Chrome Developer Tools for JavaEclipse が必要です。

chromedevtools - Google Chrome Developer Tools for Java - Google Project Hosting
http://code.google.com/p/chromedevtools/

が、参考になります。

2013/09/29(Sun) 現在、OS X Mountain Lion バージョン 10.8.5 上では、

~ $ java -version
java version "1.6.0_51"
Java(TM) SE Runtime Environment (build 1.6.0_51-b11-457-11M4509)
Java HotSpot(TM) 64-Bit Server VM (build 20.51-b01-457, mixed mode)
~ $ 

Java のバージョンは、1.6.0_51で問題ありません。

Eclipse は、余計なものがインストールされないように

Eclipse Downloads
http://www.eclipse.org/downloads/
Eclipse Standard 4.3.1, 196 MB
Downloaded 381 Times  Other Downloads
Mac OS X 64 Bit

から、一番上の Eclipse Standard 4.3.1, 196 MB Mac OS X 64 Bit をダウンロードしました。ダウンロードした eclipse-standard-kepler-SR1-macosx-cocoa-x86_64.tar.gz ファイルを Finder 上でダブルクリックして展開し、作成された eclipse フォルダを /アプリケーション フォルダに移動します。

eclipse を再インストールルする時は、/アプリケーション フォルダ内の eclipse フォルダ と ~/書類/workspace フォルダを削除してください。workspace フォルダには、不可視ファイルが含まれているので必ず削除してください。

DebuggerTutorial - chromedevtools - First steps of using Debugger. - Google Chrome Developer Tools for Java - Google Project Hosting
http://code.google.com/p/chromedevtools/wiki/DebuggerTutorial

上記 URL を参考に、SDK をインストールする必要があります。

/アプリケーション/eclipse フォルダ 内の Eclipse を Finder 上でダブルクリックして起動します。

メニュー Help/Install New Software…. を選びます。

図 1

図 1の一番上のテキストフィールド Wok with: に

http://chromedevtools.googlecode.com/svn/update/dev/

を入力します。Add ボタンをクリックします。

図 2

図 2 のダイアログが開くので、Name: に

Google Chrome Developer Tools

と入力して OK ボタンをクリックします。

図 3

図 3 の中央に表示される大きなエリアの Google Chrome Developer Tools 横にある ▼ をクリックして開きます。

Chromium JavaScript Remote Debugger” にチェックを入れます。

後は Next > ボタンを 2 回クリックし、ライセンス同意ボタンを選択して終了します。途中、セキュリティ警告が表示されますが、OK ボタンをクリックしてください。

■サンプルコード lineprocessor.cc をデバッガで試す

AddDebuggerSupport - v8 - Adding debugger support to application HOW-TO. - V8 JavaScript Engine - Google Project Hosting
http://code.google.com/p/v8/wiki/AddDebuggerSupport

上記 URL が参考になります。

まず、最初にターミナルで、コマンドライン引数 -p 9222、–callback を追加して lineprocessor 実行します。

~/v8/out/x64.release $ ./lineprocessor -p 9222 main-cycle-in-cpp.js --main-cycle-in-cpp --callback

それから、

図 4

図 4のように Eclipse を起動、メニュー Run/Debug Configurations… を選択します。

図 5

図 5 のように、左エリア内の Standalone V8 VM を選択して、上部ノートに + が付いたアイコンをクリックします。図 6のように設定が新規に作成されます。

図 6

図 6 のように remote タブの Host: localhost、Port: 9222、show debugger network cominucation console にチェックを入れます。 Apply ボタンをクリックしてから Debug ボタンをクリックします。

図 7

上図のように表示されます。左上の一番上のアイコンをクリックすると下図のように表示されます。

図 8

Project Explorer の New_configuration の▼を開き、main-cycle-in-cpp.js をダブルクリックして開きます。
ソース main-cycle-in-cpp.js のブレークポイントを仕掛けたい行をクリックすると、図 9 のように青色反転させます。

図 9

図 10

図 10 のメニュー ‘Run’/’Add V8/Chrome Javascript Exception Breakpoint’/’Togle Line Breakpoint’ を選択して、ブレークポイントを仕掛けます。

図 11

ターミナル側で

./lineprocessor capitalizer.js -p 9222 --main-cycle-in-cpp --callback
hello

hello と文字を入力して Return キーを押します。

するとブレークポイントで実行が止まり、デバッガーを表示していいか尋ねてくるので、Yes ボタンをクリックします。

Variables タブで、変数 input_line に “Hello” という文字列が渡されているのが確認できると思います。

メニュー Window/Show Toolbar を選び、ツールバーを表示します。ツールバーの赤色正方形の横にステップイン、ステップオーバーなどのボタンがあります。

図 12

Resume ボタン(緑色の再生ボタン) 押すとターミナル側で

~ $ cd v8/out/x64.release/
~/v8/out/x64.release $ ./lineprocessor -p 9222 main-cycle-in-cpp.js --main-cycle-in-cpp --callback
hello
>>>hello<<<

図 13

>>>hello<<< という文字が表示されます。ターミナルで CTRL + C を押せば終了させることができます。

また、main-cycle-in-js.js、–main-cycle-in-js のコマンドライン引数を lineprocessor に渡しても、同じようにデバッガを使うことができます。

~/v8/out/x64.release $  ./lineprocessor main-cycle-in-js.js --main-cycle-in-js  -p 9222 --callback
hello

変数 line の内容を表示するには、ソースの line という文字にカーソルを合わせます。 図 14 のように “hello”というポップアップが現れます。

while (true) {
var line = read_line();
if (!line) {
break;
}
var res = line + " | " + line;
print(res);
}

図 14

プチコンmkII プログラム PBR (Petit Book Reader) 用 Mac 版補助ツール ConvertPTC 公開

プログラミングコンテスト 第二回 プチコン大喜利 審査結果発表」
http://smileboom.com/special/ptcm2/co_contest/

第二回 プチコン大喜利の審査結果が発表されました。早速、QR コードを読み取りました。特に Gust Notch? さん作

★プロ生ちゃん特別賞★
PBR (Petit Book Reader)
作/ Gust Notch? さん
GN_PBR
GN_MKBL
青空文庫リーダー

の deflate アルゴリズム実装には驚きました。

最近 Twiitter などで公開されている QR コードを追いかけていませんが、それでも自分の作りかけのプログラムも含めると約360本ほどあります。どんなプログラムがあるのか、ほとんど忘れてしまいました。それで、Mac のメモに Twitter などの発言をプログラムごとにまとめてあります。これを PBR (Petit Book Reader) で読めたら便利だと思い、早速試してみました。

(Twitter の発言を公開するわけにはいかないので、ここでは OOGIRI_B.txt を使用しています。テキストファイル OOGIRI_B.txt は、第二回 プチコン大喜利の結果をまとめたものです。QRコードのファイル名、プログラム名も書いてあります。どんなプログラムがあったか確認するのに便利です。後ほど紹介するアプリ ConvertPTC に含まれています。PTC ファイル化されているので、Windows ユーザーでも利用できます。 )

テキストファイル OOGIRI_B.txt を文字コード : ‘日本語 (Shift JIS)’、改行コード : ‘Windows CR LF’ で保存し、ターミナル上で gzip コマンドを使って

~ $ cd Desktop/ConvertPTC
~/Desktop/ConvertPTC $ gzip -c OOGIRI_B.txt > OOGIRI_B.gz
~/Desktop/ConvertPTC $ 

上記のように GZIP 圧縮ファイル OOGIRI_B.gz を作成しました。

はずかしいのですが、最初は圧縮書庫形式を TAR 形式 + GZIP 形式

 $ cd ~/Desktop/ConvertPTC/
~/Desktop/ConvertPTC $ tar czvf OOGIRI_B.tar.gz OOGIRI_B.txt
a OOGIRI_B.txt
~/Desktop/ConvertPTC $ 

のように tar.gz に圧縮していました。また、圧縮したアーカイブ・ファイルを展開するには

GZIP 圧縮ファイルの展開

~/Desktop/ConvertPTC $ gzip -dc OOGIRI_B.gz > OOGIRI_B.txt
~/Desktop/ConvertPTC $ 

TAR 形式 + GZIP 形式の展開

~/Desktop/ConvertPTC $ tar xzvf OOGIRI_B.tar.gz
x ./._OOGIRI_B.txt
x OOGIRI_B.txt
~/Desktop/ConvertPTC $ 

以上のコマンドでできます。

後は、PBR (Petit Book Reader) のマニュアルに説明されている通り、

プチコン MkII 開発支援ツール DSPCBMP
http://www.aogondo.net/PetitCom/DSPCBMP/

DSPCBMP を使って PTCファイルに変換しました。ところが Mac と Windows 間でファイルをやり取りしているせいか正しく変換されていないようです。(私の使用方法に問題があるのかもしれません。)

そこで、Ruby で PTC ファイルに変換するプログラムを作ってみたのですが、私の技術力不足でなかなか思った通りの動作をしてくれません。それで思いきって Mac 用の PTC 変換プログラムを作ってみました。折角なので、テキストファイルをドラッグ・ドロップするだけで GZIP 圧縮し、PTC ファイル化するようにしました。十分な動作確認をしていないので注意してください。

下記 URL で公開します。

Gust Notch? さん作 PBR (Petit Book Reader) で読むことができる
GRP 形式  PTC ファイルを Mac 上で作成する
プログラム ConvertPTC。
http://kyoshiaki.sakura.ne.jp/osx/Sample/ConvertPTC.zip

注意) GRP: OOGIRI_B を GN_PBR で読み込む時、エラーが出ます。GN_PBR を修正する必要があります。 上記 URL の ConvertPTC.zip に含まれる ReadMe を参照してください。Windows ユーザーにも ReadMe を読めるように PDF 形式で保存した ReadMe も同封しておきました。

詳しくは、

【使用方法】
5) プログラム GN_PBR を修正。

を参照してください。

文章ファイルリスト MEM: BOOKLIST を編集すると PBR (Petit Book Reader) GN_PBRの 起動画面で、文書タイトルをタッチするだけで読み込むことができます。その方法も、上記 URL の ConvertPTC.zip に含まれる ReadMe

【Tips】
4) 文書ファイルリスト
GN_MKBL 

に解説してあります。

プログラミングコンテスト 第二回 プチコン大喜利 審査結果発表」
http://smileboom.com/special/ptcm2/co_contest/
技術賞
一分間戦争
作/ Ackieee さん
OMWAR
PDF 書類 manual-omwar.pdf
http://smileboom.com/special/ptcm2/co_contest/media/manual-omwar.pdf

に熱中しています。なかなか手強いですね。

プチコン 3号(仮称)
http://smileboom.com/special/ptcm2/html_third.php

ニンテンドー3DSプチコンが発表されました。近日発売だそうです。楽しみですね。

拙作 iPhone 用 RSS リーダー iYKRSS、iPad 用 RSS リーダー iYKRSSHD 無料公開、 iOS 用 Twitter アプリ作成方法

ちょっと宣伝です。拙作 RSS リーダー iYKRSS を iPhone 5 スクリーンで表示できるようにしました。また、iPadRSS リーダー iYKRSSHD を Retina ディスプレイに対応しました。

あらかじめ登録された芸能人ブログリストから RSS フィードを簡単に選ぶことができるので、RSS リーダーを使ったことがない初心者にもお勧めです。

iYKRSS、iYKRSSHD 共に無料です。ただし、iYKRSSHD は、9月になると 85 円に戻ります。iPhoneiPod touchiPad を持ってる人は、良かったら試しにダウンロードしてみてください。

使い方がわからない人は、気軽にコメントに書き込んでください。返事は、遅れるかもしれないのでご了承ください。

iYKRSS version 1.0.4
http://appstore.com/yoshiakikoyama/iykrss

iYKRSSHD version 1.0.2
http://appstore.com/yoshiakikoyama/iykrsshd

随分遅れましたが、前回、予告した iOS 用 Twitter アプリ作成方法を説明したいと思います。私自身、良く理解していない部分もあるので、間違いもあるかもしれません。

基本的に、下記 URL の REST API v1.1 を

REST API v1.1 Resources | Twitter Developers
https://dev.twitter.com/docs/api/1.1

使って Twitter のタイムライン情報などを取得します。REST API v1.1 を前回説明した GET、POST で送信するのですが、

Authorizing a request | Twitter Developers
https://dev.twitter.com/docs/auth/authorizing-request

上記、URL の

POST /1/statuses/update.json?include_entities=true HTTP/1.1
Accept: */*
Connection: close
User-Agent: OAuth gem v0.4.4
Content-Type: application/x-www-form-urlencoded
Authorization:
OAuth oauth_consumer_key="xvz1evFS4wEEPTGEFPHBog",
oauth_nonce="kYjzVBB8Y0ZFabxSWbWovY3uYSQ2pTgmZeNu2VS4cg",
oauth_signature="tnnArxj06cWHq44gCs1OSKk%2FjLY%3D",
oauth_signature_method="HMAC-SHA1",
oauth_timestamp="1318622958",
oauth_token="370773112-GmHxMAgYyLbNEtIKZeRNFsMKPR9EyMZeS9weJAEb",
oauth_version="1.0"
Content-Length: 76
Host: api.twitter.com
status=Hello%20Ladies%20%2b%20Gentlemen%2c%20a%20signed%20OAuth%20request%21

のように、認証情報 (上の Authorization: OAuth の部分) が必要です。OAuth を使って取得する必要があります。

しかし、iOS の場合、

 Using Reverse Auth | Twitter Developers
https://dev.twitter.com/docs/ios/using-reverse-auth

Reverse Auth を使って OAuth の情報を取得できます。取得の仕方は、

 seancook/TWReverseAuthExample · GitHub
https://github.com/seancook/TWReverseAuthExample

を参考にした拙作サンプル

自作 iOS 用 Twitter アプリ サンプル TSTwitter
http://kyoshiaki.sakura.ne.jp/osx/Sample/Twitter.zip

に含まれています。 KeyDefines.h の

#define TWITTER_CONSUMER_KEY    @""
#define TWITTER_CONSUMER_SECRET @""

を設定してください。Consumer key、Consumer secret を使うには、

Twitter Developers
https://dev.twitter.com/

にログインして、自分のアイコンをクリックして表示されるメニューから ‘My applications’ を選び、’Create a new application’ ボタンをクリックして My application を作成する必要があります。

Sign in with your Twitter account | Twitter Developers
https://dev.twitter.com/apps

作成した application を選べば、Consumer key、Consumer secret は表示されます。

自作 iOS 用 Twitter アプリ サンプル TSTwitter
http://kyoshiaki.sakura.ne.jp/osx/Sample/Twitter.zip

の TSViewController.m の Reverse Auth を呼び出している部分は、

TSViewController.m

- (void)awakeFromNib {
__unsafe_unretained TSViewController *me = self;
_accountStore = [[ACAccountStore alloc] init];
_apiManager = [[TWAPIManager alloc] init];
ACAccountType *twitterType = [_accountStore accountTypeWithAccountTypeIdentifier:ACAccountTypeIdentifierTwitter];
_accounts = [_accountStore accountsWithAccountType:twitterType];
_account = [_accounts objectAtIndex:0];
NSLog(@"%@", _account);
NSLog(@"identifier: %@", _account.identifier);
NSLog(@"username: %@", _account.username);
if ([TWITTER_CONSUMER_KEY isEqualToString:@""]) {
NSLog(@"TWITTER_CONSUMER_KEY=\"\"");
[self requestApiTimeline:self];
//        [self requestApi:me];
} else {
[_apiManager performReverseAuthForAccount:_account withHandler:^(NSData *responseData, NSError *error) {
if (responseData) {
NSString *responseStr = [[NSString alloc] initWithData:responseData encoding:NSUTF8StringEncoding];
NSArray *parts = [responseStr componentsSeparatedByString:@"&"];
me.reverseAuth = [NSMutableDictionary dictionary];
//            NSLog(@"%@", responseStr);
for (NSString *line in parts) {
NSArray *array = [line componentsSeparatedByString:@"="];
[me.reverseAuth setObject:array[1] forKey:array[0]];
}
//            NSLog(@"%@", me.reverseAuth);
//
[me requestApi:me];
//                [me requestRawApi:me];
}
}];
}
}

[_apiManager performReverseAuthForAccount:_account withHandler:^(NSData *responseData, NSError *error) { です。

_apiManager に引数、ACAccount *account と最終的に呼ばれるブロックを渡し、performReverseAuthForAccount: withHandler: メソッドを呼ぶと

Using Reverse Auth | Twitter Developers
https://dev.twitter.com/docs/ios/using-reverse-auth

の最後にある下部

oauth_token=2311112785-EXKeLV5ezo3HHIaIf1T3ffeww0mR5dfYXKZjjRy0&oauth_token_secret=KYxxxxx3U4Fxrxva3BGD92--12ehEzFwQ&user_id=38895958&screen_name=theseancook

のような、oauth_token、oauth_token_secret、user_id、screen_name を NSData *responseData で返してくれます。ここで重要なのは、user_id を返してくれることです。実は、Reverse Auth を使わなくても、タイムラインを表示することができます。

    if ([TWITTER_CONSUMER_KEY isEqualToString:@""]) {
NSLog(@"TWITTER_CONSUMER_KEY=\"\"");
[self requestApiTimeline:self];
//        [self requestApi:me];

上の部分が TWITTER_CONSUMER_KEY が設定されていない場合、Reverse Auth を使わないでタイムラインを表示しています。

ただし、他の REST API v1.1 を使用するためには user_id が必要になってきます。

後は、簡単です。アップルが用意したフレームワークの SLReuest を使って Twitter API v1.1 を呼び出す汎用 API

- (void)performTwitterRequestAccount:(ACAccount *)account Method:(SLRequestMethod)method URL:(NSURL *)url parameters:(NSDictionary *)dict completion:(TwitterRequestHandler)completion

です。

- (void)requestApi:(id)sender {
//    url = [NSURL URLWithString:@"http://192.168.1.6:9090/1.1/lists/list.json"];
url = [NSURL URLWithString:@"https://api.twitter.com/1.1/lists/list.json"];
//    dict = @{@"user_id" : @"00000000"}; // user_id を設定してください
dict = @{@"user_id" : [self.reverseAuth objectForKey:@"user_id"]}; // TWITTER_CONSUMER_KEY を設定していないと使えません。
[self performTwitterRequestAccount:_account Method:SLRequestMethodGET URL:url parameters:dict completion:^(NSArray *json, NSURLResponse *response, NSError *error) {
NSLog(@"===< List >===");
//      NSLog(@"%@", json);
for (NSDictionary *list in json) {
NSString *text = [NSString stringWithFormat:@"<%@>\n  list_id:%@\n  slug:%@",[list  objectForKey:@"uri"],[list  objectForKey:@"id"],[list  objectForKey:@"slug"]];
NSLog(@"%@", text);
}
}];

で、- (void)performTwitterRequestAccount:(ACAccount *)account Method:(SLRequestMethod)method URL:(NSURL *)url parameters:(NSDictionary *)dict completion:(TwitterRequestHandler)completion を呼び出しているのがわかると思います。この場合、自分のリストを表示しています。

 url = [NSURL URLWithString:@"http://192.168.1.6:9090/1.1/lists/list.json"];

を有効にして、前回の GET、POST のように SLRequest がどんなデータをサーバーに送信しているのか確認することができます。

まず、ターミナルで

自作 iOS 用 Twitter アプリ サンプル TSTwitter
http://kyoshiaki.sakura.ne.jp/osx/Sample/Twitter.zip

に含まれる server.rb を実行します。その後、TSTwitter.xcodeproj を開き、ツールバー上 Run ボタンをクリックします。画面が現れプログラムが起動し終えたら、Stop ボタンを押します。ターミナル上に実際の SLRequst がサーバーに送るデータが下図のように表示されます。

上図より、

Authorizing a request | Twitter Developers
https://dev.twitter.com/docs/auth/authorizing-request

上記 URL の

POST /1/statuses/update.json?include_entities=true HTTP/1.1
Accept: */*
Connection: close
User-Agent: OAuth gem v0.4.4
Content-Type: application/x-www-form-urlencoded
Authorization:
OAuth oauth_consumer_key="xvz1evFS4wEEPTGEFPHBog",
oauth_nonce="kYjzVBB8Y0ZFabxSWbWovY3uYSQ2pTgmZeNu2VS4cg",
oauth_signature="tnnArxj06cWHq44gCs1OSKk%2FjLY%3D",
oauth_signature_method="HMAC-SHA1",
oauth_timestamp="1318622958",
oauth_token="370773112-GmHxMAgYyLbNEtIKZeRNFsMKPR9EyMZeS9weJAEb",
oauth_version="1.0"
Content-Length: 76
Host: api.twitter.com
status=Hello%20Ladies%20%2b%20Gentlemen%2c%20a%20signed%20OAuth%20request%21

と似ているのが理解できると思います。SLRequest を使わずに NSMutableURLRequest で実現したのが

自作 iOS 用 Twitter アプリ サンプル TSTwitter
http://kyoshiaki.sakura.ne.jp/osx/Sample/Twitter.zip

に含まれているソース

TSSignedRequest.h
TSSignedRequest.m

の TSSignedRequest

- (void)performTSTwitterRequestMethod:(TSSignedRequestMethod)method URL:(NSURL *)url parameters:(NSDictionary *)dict completion:(TSTwitterRequestHandler)completion {
- (void)requestRawApi:(id)sender {
- (void)performTSTwitterRequestMethod:(TSSignedRequestMethod)method URL:(NSURL *)url parameters:(NSDictionary *)dict completion:(TSTwitterRequestHandler)completion {

です。SLRequest と似ているので注意してください。TSSignedRequest を通常使う必要はありません。Twitter API の動作を確認するために、実験的に作ってみただけです。SLRequest を使ってください。

SLRequest を使うだけなら、Reverse Auth が必要ないと思うかもしれません。以前は ACAccount *account から user_id を取り出すことができたのですが、現在、Reverse Auth を使って user_id を取り出すしか方法がありません。

Twitter API v1.1 を試すには、Mac App StoreTwitter、ターミナル上で curl を使う方法があります。

Mac 上で動作する本家 Twitter アプリは、Mac App Store にあります。

Twitter
http://appstore.com/mac/twitterinc/twitter

上記 URL をクリックすれば表示されます。

Twitter をクリックして実行し、メニュー/Twitter/環境設定… を選び、ツールバーから ‘開発者’ を選択します。コンシュマーキー、アクセストークンを入力し、認証ボタンをクリックすると開発者メニューが有効になります。

試しに、メニュー/開発/コンソール を選び、ホームタイムラインを表示してみたのが下図です。

curl を使って試す方法は、まず、

Twitter Developers
https://dev.twitter.com/

にログインします。

REST API v1.1 Resources | Twitter Developers
https://dev.twitter.com/docs/api/1.1

を開き、呼びたい REST Api をクリックします。ここでは、GET statuses/home_timeline にします。
右側、OAuth tool で ‘Select one of your Apps’ から自分のアプリケーションを選びます。その後、Generate OAuth signature ボタンをクリックします。

表示されたページの Request URI: が正しく設定されているか確かめます。 Request query: に設定したいパラメーターを入力します。ここでは、count=2 と入力します。

この後、ページの一番下の See Oauth signature for this request ボタンをクリックします。

表示されたページの OAuth Signing Results に cURL command と名前の項目があります。右横にパラメーターがセットされた curl コマンドが表示されています。それをコピーして、ターミナルにペーストし実行すれば、生の JSON データを取得することができます。