T-Code入力環境tc2で句読点をカンマピリオドにする設定

T-Code入力環境tc2では,ストローク [3 → 2] で句読点をカンマピリオドに変更できます.
これを毎回やるのが面倒で,デフォルトの句読点をカンマピリオドにしようと思い,ストローク表をいじる方法を調べました.

こちらのページの資料 tcode-ws.pdf にやりかたが載っていました.

ストローク表の読み込み後にその表をいじるので元の表に影響を与えません.

以下を .tc に追加しました(句読点を変えるついでに括弧も全角にしてみました).

(add-hook 'tcode-after-load-table-hook
  (lambda ()
    (cond ((eq tcode-input-method 'tcode)
      (tcode-set-action-to-table '(27 12) "(")
      (tcode-set-action-to-table '(17 22) ")")
      (tcode-set-action-to-table '(26 22) ",")
      (tcode-set-action-to-table '(25 23) ".")))))

第4回スタートHaskellの演習問題#6 でのバックトラックのしくみを調べてみた

先日の第4回スタートHaskellでは,演習として四則演算のパーサを実装しました.演習問題

Haskellではバックトラック付きのパーサをメモリ消費を抑えつつ簡単に実装できるとのこと.
しかし、なぜバックトラックできるのかをうまく理解しきれませんでした.例えば「"2 - 1" をパースして計算する時に,まず"+"かどうかを調べるのだから,そこでトークンを一文字消費するのではないだろうか...?」と思ったのです.
帰り際に講師のTravisさんに聞いてみたところ、「do構文を使わずに書くと分かり易いですよ」と教えてもらったので,やってみました.
今回は、演習問題 #6 で実装したexpr関数をdo構文を使わないように書き直してみました.
expr関数は、足し算や引き算をするための関数です.
(この関数中の+++演算子は,Parsecの<|>に相当するそうです)

      • -

元のexpr関数

> expr :: Parser Int
> expr = do t <- term -- トークンtを取得する
>           do symbol "+"   -- 次のトークンが"+"かどうかを調べる
>              e <- expr    -- さらにその次のトークンは数字である
>              return (t+e) -- Parserコンテナで(t+e)の計算結果を包んで、それをexpr関数の返り値とする
>             +++ do symbol "-"   -- 次のトークンが"+"でないなら、それが"-"かどうかを調べる
>                    e <- expr    -- さらにその次のトークンは数字である
>                    return (t-e) -- Parserコンテナで(t-e)の計算結果を包んで、それをexpr関数の返り値とする
>                   +++ do return t  -- 次のトークンが"+"でも"-"でもないならtをParserコンテナで包んで返す


最初のdoを消す。

> expr :: Parser Int
> expr = term >>= (\t ->             -- doを消す
>           do symbol "+"
>              e <- expr
>              return (t+e)
>             +++ do symbol "-"
>                    e <- expr
>                    return (t-e)
>                   +++ do return t) -- 閉じ括弧

3行目からdoを追い出す。doは4行目に。

> expr :: Parser Int
> expr = term >>= (\t ->
>             ((symbol "+") >>
>              (do e <- expr
>                  return (t+e)))
>             +++ do symbol "-"
>                    e <- expr
>                    return (t-e)
>                   +++ do return t)


4行目からdoを追い出す。doは5行目に。

> expr :: Parser Int
> expr = term >>= (\t ->
>             ((symbol "+") >>
>              (expr >>= (\e ->
>                  do return (t+e))))
>             +++ do symbol "-"
>                    e <- expr
>                    return (t-e)
>                   +++ do return t)


5行目からdoを追い出す。(doを消すだけ)

> expr :: Parser Int
> expr = term >>= (\t ->
>             ((symbol "+") >>
>              (expr >>= (\e ->
>                  return (t+e))))
>             +++ do symbol "-"
>                    e <- expr
>                    return (t-e)
>                   +++ do return t)


以降同様に…

> expr :: Parser Int
> expr = term >>= (\t ->
>             ((symbol "+") >>
>              (expr >>= (\e ->
>                  return (t+e))))
>             +++ ((symbol "-") >>
>                  (expr >>= (\e ->
>                      return (t-e))))
>                   +++ return t)


これを整形すると、

> expr :: Parser Int
> expr = term >>= (\t -> ((symbol "+") >> (expr >>= (\e -> return (t+e))))
>                    +++ ((symbol "-") >> (expr >>= (\e -> return (t-e))))
>                    +++ return t)

ここまで書いて気付いたのは,実はこういうことだった,ということ.

> expr = term >>= (\t -> A
>                    +++ B
>                    +++ C

整形すると,

> expr = term >>= (\t -> A +++ B +++ C)


つまり,こういうこと.

> expr = term >>= (\t -> A)

上が失敗したら
> expr = term >>= (\t -> B)

上が失敗したら
> expr = term >>= (\t -> C)

そこで,試しにわざとAを失敗させてみる。("+"文字が2個連続することを要求してみる)

> expr :: Parser Int
> expr = term >>= (\t ->     ((symbol "+") >> (symbol "+") >> (expr >>= (\e -> return (t+e)))) -- A
>                        +++ ((symbol "-") >> (expr >>= (\e -> return (t-e))))                 -- B
>                        +++ return t                                                          -- C
>                 )

Aの式の中では, >> でいくつも計算が繋がっている.
>> で繋がっている小さな計算のうちどれかが失敗すると全体の計算が失敗するので,

> expr :: Parser Int
> expr = term >>= (\t -> 失敗
>                        +++ ((symbol "-") >> (expr >>= (\e -> return (t-e)))) -- B
>                        +++ return t                                          -- C
>                 )

となる.これは以下と等価となる.

> expr :: Parser Int
> expr = term >>= (\t -> ((symbol "-") >> (expr >>= (\e -> return (t-e)))) -- B
>                        +++ return t                                      -- C
>                 )


テストの実行結果(スタートHaskellでの演習は,与えられたテストケースをパスする関数を実装するという形式で行われる)
足し算を行うコードが,さも実装されていなかったかのようなテスト結果になった.

*Main> runTests evalTests 
### Error in:   3                          
unused input + 2
### Error in:   5                          
invalid input
### Error in:   6                          
unused input + 4
### Error in:   7                          
unused input * (3 + 4)
Cases: 12  Tried: 12  Errors: 4  Failures: 0
Counts {cases = 12, tried = 12, errors = 4, failures = 0}


今度は,失敗する足し算の下に,成功する足し算を書いてみた.

> expr :: Parser Int
> expr = term >>= (\t ->     ((symbol "+") >> (symbol "+") >> (expr >>= (\e -> return (t+e)))) -- 失敗する足し算
>                        +++ ((symbol "+") >> (expr >>= (\e -> return (t+e)))) -- 成功する足し算
>                        +++ ((symbol "-") >> (expr >>= (\e -> return (t-e))))
>                        +++ return t
>                 )
*Main> runTests evalTests 
Cases: 12  Tried: 12  Errors: 0  Failures: 0
Counts {cases = 12, tried = 12, errors = 0, failures = 0}


しっかりテストをパスした.

      • -

長くなりましたが,考察です.
以上のように,+++演算子の左の計算が失敗すると,それがさも無かったかのようにプログラムが動作します.
そのため,>>で繋った計算のうちどれかが失敗すると,"+"や"-"を読み取るために1文字消費したのは無かったことになります.

これが遅延評価のすばらしいところ,ということでしょうかね...?
まだまだ理解が進んでいないので,ツッコミが欲しいところです.

UIImageやUIImagePickerControllerの使い方について.(StackOverflowの記事の和訳)

UIImageやUIImagePickerの使い方について分かり易くまとめている記事を見つけたので,和訳してみました.もし誤訳を発見されましたら,ご指摘いただけると幸いです.

元記事: iphone - UIImagePickerController, UIImage, Memory and More? - Stack Overflow

#### 以降,記事の和訳 ####
私はUIImageオブジェクトの扱い方についての質問が多いことに気付きました。
特に多いのは、UIImagePickerControllerとの連携や、ビュー上(大抵はUIImageView)への表示についての質問です。
それらに関してよくある質問とそれに対する回答を集めてみました。
編集や追加はお気軽にどうぞ。

私はこれらすべての情報をいろいろなところで学びました。
フォーラムでの様々な投稿、StackOverflowでの回答、そして私自身の実験がこれらの解決法をもたらしてくました。
私が修正したものもありますが、以降のサンプルコードの著作権はそのコードの投稿者にあります。
投稿者の全員を思い出せませんが、あなたたちには脱帽です!

Q: ローカルに保存済みの画像や、カメラで撮影した画像を取得するにはどうすればいいの?

A: UIImagePickerControllerを使おう。このクラスのドキュメントは、これの使い方の概要を親切に説明してくれているよ。ここで見ることができる。

基本的には、モーダルのビューコントローラとしてこのクラスのインスタンスを作って、それを表示する。この時、このインスタンスのデリゲートも指定しておく。そうすれば、ユーザが動画や画像を選択した時に、その通知をデリゲートメソッドで受け取れる(訳注: そのときに画像のデータも受け取れる)。あとは煮るなり焼くなりご自由に。

Q: デリゲートメソッドは呼ばれたけれど、ここからどうやって画像を取得するの?

A: デリゲートメソッドの引数や返り値は以下の通り。

- (void)imagePickerController:(UIImagePickerController *)picker
didFinishPickingMediaWithInfo:(NSDictionary *)info;

(この記事ではやらないけれど)デバッガでこのメソッドにブレークポイントを置いてdictionary(訳注:引数の info を指している)の中身を見ておいたほうがいい。

さて、このdictionaryの中から、例えば以下のようにして画像データを取り出す。

UIImage* image = [info objectForKey:UIImagePickerControllerOriginalImage];

ほかにもやり方はいくつかある。全部ドキュメントに載っているよ。

Q: OK。画像は取れた。でもこの画像には、位置データが含まれていないね。どうやってそれを付加したらいいの?

A: 残念なことに、Appleはその情報を使わせてくれないんだ。UIImageに画像のデータを読み込んだ時に、その画像のEXIFデータや位置情報データなどは取り払われてしまう。でも、次の質問の回答では画像の元データを扱う方法について言及しているよ(iOS 4以上)。

Q: ディスク上にある画像の元データは扱える?

A: iOS 4以上ならできるよ。でも、かなり煩わしい。以下のコード例では、画像のAssetsLibraryのURLを取得して、そのURLを assetForURL:resultBlock:failureBlock: に渡している。

NSURL *referenceURL = [info objectForKey:UIImagePickerControllerReferenceURL];
ALAssetsLibrary *library = [[ALAssetsLibrary alloc] init];
[library assetForURL:referenceURL resultBlock:^(ALAsset *asset) {
    // code to handle the asset here
} failureBlock:^(NSError *error) {
    // error handling
}];
[library release];

これは煩わしい。なぜなら、やろうとしていることはフォトライブラリへのアクセスなのに、アプリはユーザに現在地情報へのアクセス許可を求めるからだ。ユーザが意図してEXIF位置データを取得しようとしていない限り、ユーザを少し混乱させてしまうだろう。

ちなみに、この作業をするときにはAssetsLibraryフレームワークが含まれているか確認しよう。

Q: UIImageのピクセルを取得するにはどうしたらいい?

A: UIImageのデータは変更できないので、ピクセルデータを直接変更することはできない。ただし、そのデータを複製することはできる。そのためのコードはこんな感じ。

UIImage* image = ...; // An image
NSData* pixelData = (NSData*) CGDataProviderCopyData(CGImageGetDataProvider(image.CGImage));
unsigned char* pixelBytes = (unsigned char *)[pixelData bytes];

// Take away the red pixel, assuming 32-bit RGBA
for(int i = 0; i < [pixelData length]; i += 4) {
        pixelBytes[i] = 0; // red
        pixelBytes[i+1] = pixelBytes[i+1]; // green
        pixelBytes[i+2] = pixelBytes[i+2]; // blue
        pixelBytes[i+3] = pixelBytes[i+3]; // alpha
}

でも、気を付けないといけないのは、CGDataProviderCopyData が"データを変更できない"参照を返すということ。もし変更しようとするならBAD_ACCESSエラーが起きるだろう。もしピクセルデータを変更する方法が知りたいなら、次の質問を見るといいよ。

Q: どうやってUIImageのピクセルデータを変更するの?

A: UIImage自体は変更できない。でも、ピクセルデータのコピーをとり、それを変更する方法について、Appleがすばらしい記事を書いてくれている。それを私がここにコピペするより、あなたが直接それを読んだほうが良いだろう。

上記の記事に書かれているように、ビットマップのコンテクストを取得したら、以下のようにしてピクセルを変更したUIImageを得ることができる。

CGImageRef ref = CGBitmapContextCreateImage(bitmap);
UIImage* newImage = [UIImage imageWithCGImage:ref];

参照(訳注: CGImageRef refを指している)を開放するのを忘れずに。さもないと、僅かだがメモリリークが発生する。

Q: カメラから3つ画像を取得したらメモリを使い切ってしまった。助けて!

A: ディスクから読み込んだ画像はPNGまたはJPGで圧縮されているのでそれらは数キロバイトしかない。一方、カメラで撮影した画像が直接UIImageに読み込まれた時、それらは無圧縮の状態にある。そのような画像データのサイズの計算式は、およそ以下のようになる。

width x height x 4 = bytes in memory

8メガバイトは巨大だ。開発しているアプリケーションに24メガバイトのメモリ使用量の制約があるときは特にそういえる。これがメモリを使い切ってしまう理由だ。

Q: OK。なぜメモリが足りなくなるのか分かったよ。じゃあ、どうすればいいの?

A: そもそも画像を最大の解像度で画面に表示する必要はない。iPhoneの画面は 480 x 320 ピクセルしかないのだから、メモリスペースを無駄にするだけだ。このような時には、自問するといい。この画像を最大の解像度で必要としているのか、と。

もしその答えがNOなら、次のパートを読もう。

もしその答えがYESなら、後で使うためにその画像を保存しよう。
最大の解像度で画像を扱うと決めたら、それとは別に画面表示用の小さな画像を作る。サムネイル、フルスクリーン用の画像、最大解像度の画像…いろんなサイズの画像が何度も必要になるだろう。

Q: OK。分かった。それで、どうやって画像をリサイズするの?

A: 残念なことに、画像のリサイズする方法は定義されていない。そこで、画像をリサイズしたい時には、元の画像を変更するのではなく、新しい画像を得る。

リサイズするための方法はふたつある。ここではその両方を紹介し、それぞれの長所と短所を挙げる。

方法1: UIKitを使う

+ (UIImage*)imageWithImage:(UIImage*)image scaledToSize:(CGSize)newSize;
{
    // Create a graphics image context
    UIGraphicsBeginImageContext(newSize);

    // Tell the old image to draw in this new context, with the desired
    // new size
    [image drawInRect:CGRectMake(0,0,newSize.width,newSize.height)];

    // Get the new image from the context
    UIImage* newImage = UIGraphicsGetImageFromCurrentImageContext();

    // End the context
    UIGraphicsEndImageContext();

    // Return the new image.
    return newImage;
}

この方法はとてもシンプルで、素晴らしい働きをする。これは UIImageOrientation を扱う。これのお蔭で、端末を横向きにした撮影でも特に何も気をつける必要はない。でも、このメソッドはスレッド安全ではない。また、サムネイルを作成するのに大きな処理を必要とする(1600 x 1200 の画像を処理するのに iPhone 3G で大体 ~2.5秒かかる)ので、バックグラウンドで動作している別スレッドに非常に大きな処理をやらせることになる。

方法2: CoreGraphicsを使う

+ (UIImage*)imageWithImage:(UIImage*)sourceImage scaledToSize:(CGSize)newSize;
{
    CGFloat targetWidth = targetSize.width;
    CGFloat targetHeight = targetSize.height;

    CGImageRef imageRef = [sourceImage CGImage];
    CGBitmapInfo bitmapInfo = CGImageGetBitmapInfo(imageRef);
    CGColorSpaceRef colorSpaceInfo = CGImageGetColorSpace(imageRef);

    if (bitmapInfo == kCGImageAlphaNone) {
        bitmapInfo = kCGImageAlphaNoneSkipLast;
    }

    CGContextRef bitmap;

    if (sourceImage.imageOrientation == UIImageOrientationUp || sourceImage.imageOrientation == UIImageOrientationDown) {
        bitmap = CGBitmapContextCreate(NULL, targetWidth, targetHeight, CGImageGetBitsPerComponent(imageRef), CGImageGetBytesPerRow(imageRef), colorSpaceInfo, bitmapInfo);

    } else {
        bitmap = CGBitmapContextCreate(NULL, targetHeight, targetWidth, CGImageGetBitsPerComponent(imageRef), CGImageGetBytesPerRow(imageRef), colorSpaceInfo, bitmapInfo);

    }   

    if (sourceImage.imageOrientation == UIImageOrientationLeft) {
        CGContextRotateCTM (bitmap, radians(90));
        CGContextTranslateCTM (bitmap, 0, -targetHeight);

    } else if (sourceImage.imageOrientation == UIImageOrientationRight) {
        CGContextRotateCTM (bitmap, radians(-90));
        CGContextTranslateCTM (bitmap, -targetWidth, 0);

    } else if (sourceImage.imageOrientation == UIImageOrientationUp) {
        // NOTHING
    } else if (sourceImage.imageOrientation == UIImageOrientationDown) {
        CGContextTranslateCTM (bitmap, targetWidth, targetHeight);
        CGContextRotateCTM (bitmap, radians(-180.));
    }

    CGContextDrawImage(bitmap, CGRectMake(0, 0, targetWidth, targetHeight), imageRef);
    CGImageRef ref = CGBitmapContextCreateImage(bitmap);
    UIImage* newImage = [UIImage imageWithCGImage:ref];

    CGContextRelease(bitmap);
    CGImageRelease(ref);

    return newImage; 
}

この方法のいいところは、スレッドセーフであること、そして、細かいこと(正しいカラースペースやビットマップ情報を使うこと、画像の向きを扱うこと)の面倒を看てくれる。

Q: 縦横比率を保ったままリサイズするには?(AspectFillオプションみたいなのがあるの?)

A: それは上記の方法とよく似た方法が使える。こんな感じ。

+ (UIImage*)imageWithImage:(UIImage*)sourceImage scaledToSizeWithSameAspectRatio:(CGSize)targetSize;
{  
    CGSize imageSize = sourceImage.size;
    CGFloat width = imageSize.width;
    CGFloat height = imageSize.height;
    CGFloat targetWidth = targetSize.width;
    CGFloat targetHeight = targetSize.height;
    CGFloat scaleFactor = 0.0;
    CGFloat scaledWidth = targetWidth;
    CGFloat scaledHeight = targetHeight;
    CGPoint thumbnailPoint = CGPointMake(0.0,0.0);

    if (CGSizeEqualToSize(imageSize, targetSize) == NO) {
        CGFloat widthFactor = targetWidth / width;
        CGFloat heightFactor = targetHeight / height;

        if (widthFactor > heightFactor) {
            scaleFactor = widthFactor; // scale to fit height
        }
        else {
            scaleFactor = heightFactor; // scale to fit width
        }

        scaledWidth  = width * scaleFactor;
        scaledHeight = height * scaleFactor;

        // center the image
        if (widthFactor > heightFactor) {
            thumbnailPoint.y = (targetHeight - scaledHeight) * 0.5; 
        }
        else if (widthFactor < heightFactor) {
            thumbnailPoint.x = (targetWidth - scaledWidth) * 0.5;
        }
    }     

    CGImageRef imageRef = [sourceImage CGImage];
    CGBitmapInfo bitmapInfo = CGImageGetBitmapInfo(imageRef);
    CGColorSpaceRef colorSpaceInfo = CGImageGetColorSpace(imageRef);

    if (bitmapInfo == kCGImageAlphaNone) {
        bitmapInfo = kCGImageAlphaNoneSkipLast;
    }

    CGContextRef bitmap;

    if (sourceImage.imageOrientation == UIImageOrientationUp || sourceImage.imageOrientation == UIImageOrientationDown) {
        bitmap = CGBitmapContextCreate(NULL, targetWidth, targetHeight, CGImageGetBitsPerComponent(imageRef), CGImageGetBytesPerRow(imageRef), colorSpaceInfo, bitmapInfo);

    } else {
        bitmap = CGBitmapContextCreate(NULL, targetHeight, targetWidth, CGImageGetBitsPerComponent(imageRef), CGImageGetBytesPerRow(imageRef), colorSpaceInfo, bitmapInfo);

    }   

    // In the right or left cases, we need to switch scaledWidth and scaledHeight,
    // and also the thumbnail point
    if (sourceImage.imageOrientation == UIImageOrientationLeft) {
        thumbnailPoint = CGPointMake(thumbnailPoint.y, thumbnailPoint.x);
        CGFloat oldScaledWidth = scaledWidth;
        scaledWidth = scaledHeight;
        scaledHeight = oldScaledWidth;

        CGContextRotateCTM (bitmap, radians(90));
        CGContextTranslateCTM (bitmap, 0, -targetHeight);

    } else if (sourceImage.imageOrientation == UIImageOrientationRight) {
        thumbnailPoint = CGPointMake(thumbnailPoint.y, thumbnailPoint.x);
        CGFloat oldScaledWidth = scaledWidth;
        scaledWidth = scaledHeight;
        scaledHeight = oldScaledWidth;

        CGContextRotateCTM (bitmap, radians(-90));
        CGContextTranslateCTM (bitmap, -targetWidth, 0);

    } else if (sourceImage.imageOrientation == UIImageOrientationUp) {
        // NOTHING
    } else if (sourceImage.imageOrientation == UIImageOrientationDown) {
        CGContextTranslateCTM (bitmap, targetWidth, targetHeight);
        CGContextRotateCTM (bitmap, radians(-180.));
    }

    CGContextDrawImage(bitmap, CGRectMake(thumbnailPoint.x, thumbnailPoint.y, scaledWidth, scaledHeight), imageRef);
    CGImageRef ref = CGBitmapContextCreateImage(bitmap);
    UIImage* newImage = [UIImage imageWithCGImage:ref];

    CGContextRelease(bitmap);
    CGImageRelease(ref);

    return newImage; 
}

このメソッドでは、好みのサイズのビットマップを作れる。しかし、比率を保つために指定したサイズよりも大きく描画される。

Q: さて、縮小したイメージを得られた。これをどうやって保存するの?

A: その方法はとてもシンプルだよ。未圧縮のピクセルデータではなく、圧縮したものをディスクに保存したいことを思い出そう。
Appleは、これをやるためのふたつの関数を提供している(ドキュメントはここ)。

NSData* UIImagePNGRepresentation(UIImage *image);
NSData* UIImageJPEGRepresentation (UIImage *image, CGFloat compressionQuality);

これらを使いたければ、こんな感じで書く。

UIImage* myThumbnail = ...; // Get some image
NSData* imageData = UIImagePNGRepresentation(myThumbnail);

さて、ディスクに保存する準備ができた。これが最後のステップだ。

// Give a name to the file
NSString* imageName = @"MyImage.png";

// Now, we have to find the documents directory so we can save it
// Note that you might want to save it elsewhere, like the cache directory,
// or something similar.
NSArray* paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString* documentsDirectory = [paths objectAtIndex:0];

// Now we get the full path to the file
NSString* fullPathToFile = [documentsDirectory stringByAppendingPathComponent:imageName];

// and then we write it out
[imageData writeToFile:fullPathToFile atomically:NO];

Q: 保存した画像をメモリに読み込むには?

A: +imageWithContentsOfFile: のような UIImage の初期化メソッドがAppleのドキュメントに載っているのでそれを見ればいい。

さくらのVPSでmonitを使おうとしたときのエラー

さくらのVPSCentOS 5.5)でmonitを使おうとしたとき,以下のエラーが発生しました。

$ sudo /usr/bin/monit
monit: Error opening the idfile '/var/monit/id' -- No such file or directory

/var/monit が存在しないために起こるエラーのようで,

sudo mkdir /var/monit

としてやると,

$ sudo /usr/bin/monit
monit: generated unique Monit id <自動生成されたユニークID> and stored to '/var/monit/id'

と,エラーを回避できました.

FacebookのAPIでアルバムに画像をアップロードするときにハマったこと(その2)

先日この記事でFacebookAPIでの写真のアップロードについて書きました.
FacebookのAPIでアルバムに画像をアップロードするときにハマったこと. - じょにーさんのにっき

今度は別の問題でハマってしまったので,忘れないうちに書きとめておきます.
どうもこのAPIでは,投稿画像のファイルサイズの大きさによってサーバに接続を切られてしまうようです(少なくとも私のアカウントでは).

先日の記事で使用していた画像は,2,3KBの小さなものでした.
今回,大きなサイズ(といっても150KB程度)の画像をアップロードしようとしたのですが,APIサーバに接続を切られてしまいました.
それでもなお,2,3KBの画像はアップロードできました.原因が全く分かりません.

というわけで代替手法を考えていたのですが,こちらのサイト様に良い方法が載っていました.
urlというパラメータとして画像のURLを書けるそうです.
http://facebook.astrea.jp/?p=106

これを試したところ,数百KBの画像データをアルバムにアップロードできました.

この url というパラメータは公式サイトのドキュメントには載っていませんでした(古いのかな?).
以下のドキュメントに載っているパラメータは message と source のみです.
グラフAPI - ドキュメンテーション - 開発者向けFacebook

実機に転送しようとすると,No provisioned iOS devices are available

Xcode4にしたら,開発しているiPhoneアプリを実機(iOS 4.3)に転送できなくなってしまいました.

転送しようとすると,No provisioned iOS devices are available xcode4 と怒られました.

原因は,iOS Deployment Target が iOS 5 となっていたことでした.
これを iOS 4.3 に変更することで,実機に転送できました.

Xcode4からインターフェイスがガラリと変わったため,いつもどこに何があるか戸惑います…