
昨日の勉強会でさっそく買ったばかりのiPad 3GをXcodeにつないでみたら、ご覧のように対応していないOSであるとエラーが出てしまいました。
再度iPhone Developer CenterからSDKをダウンロードしてインストールし直したら問題なく動作するようになりました。おそらく単にSDKが古かっただけなのだとは思いますが、一応。
A
および B
と名付けます。A
を表示してから、 B
を表示する際に Core Data モデルを delete - insert すると、 A
を再度表示した際にアプリケーションがクラッシュします。原因はおそらく、 A
で既に読み込まれているモデルを B
が削除してしまっているため、 A
で既に削除されているモデルをテーブルが表示しようとしてクラッシュしているものだと思われます。 A
の viewWillAppear などのタイミングで、再度 Core Data からオブジェクトを取得し直せばこの問題は解決します。NSFetchedResultsController
を使えばたぶんこの問題は発生しないと思うのですが、いずれにせよ変更があったデータをフェッチしなおさなければならなくなってしまいます。ということで可能な限りプライマリキー項目を設定して update で対応することをお勧めします。ただし update は update で sqlite3 の実行がやたら遅いということが分かっているのでこちらはこちらで別途チューニングが必要です。詳細はまた別エントリーにて。
使用したバージョン | アイテム件数 | 同期にかかった時間 | アイテム/秒 |
---|---|---|---|
Byline 2.5.6 | 511件 | 340.43秒 | 1.50 |
Byline 3.0f1 | 275件 | 135.99秒 | 2.02 |
[NSString lengthOfBytesUsingEncoding:NSUTF8StringEncoding]
を表します。ほかの言語の場合もそれぞれ相当するメソッドまたは関数が用意されていると思います。// NFDこれらのメソッドは、 Unicode 文字列をそれぞれ NFD, NFC, NFKD, NFKC と呼ばれるフォーマットの文字列に変換してくれます。それぞれの文字列がどのような表現を表しているかは、以下のページを参考にしてみてください。英語ですが図説がついてるので非常にわかりやすいです。
– (NSString *)decomposedStringWithCanonicalMapping
// NFKD
– (NSString *)decomposedStringWithCompatibilityMapping
// NFC
– (NSString *)precomposedStringWithCanonicalMapping
// NFKC
– (NSString *)precomposedStringWithCompatibilityMapping
TTPhotoViewController
に読み込ませようとして一部はまってしまったので共有します。TTPhotoViewController
の中に一部 NSHTTPURLResponse
でないと動かないところがあるため、ファイル読み込みでは動作しない@"bundle://filename.jpg"
や @"documents://filename.jpg"
といった記法を用いることで回避可能photos = [[NSMutableArray alloc] init];
PhotoBookPhoto *photo;
NSString *imagesDirectoryPath = [[[NSBundle mainBundle] bundlePath] stringByAppendingPathComponent:@"Images"];
NSArray *imagePathes = [[NSFileManager defaultManager] directoryContentsAtPath:imagesDirectoryPath];
for (int i=0; i<imagePathes.count; i++) {
NSString *imagePath = (NSString *)[imagePathes objectAtIndex:i];
imagePath = [imagesDirectoryPath stringByAppendingPathComponent:imagePath];
LOG(@"%d - %@ %@", i, imagePath, [[NSURL fileURLWithPath:imagePath] absoluteString]);
photo = [[[PhotoBookPhoto alloc] initWithURL:[[NSURL fileURLWithPath:imagePath] absoluteString]
smallURL:[[NSURL fileURLWithPath:imagePath] absoluteString]
size:CGSizeMake(960, 640)] autorelease];
photo.photoSource = self;
photo.index = i;
[photos addObject:photo];
}
TTRequestLoader
中の以下のコードが直接的な原因です。///////////////////////////////////////////////////////////////////////////////////////////////////本来
///////////////////////////////////////////////////////////////////////////////////////////////////
#pragma mark -
#pragma mark NSURLConnectionDelegate
///////////////////////////////////////////////////////////////////////////////////////////////////
- (void)connection:(NSHTTPURLConnection*)connection didReceiveResponse:(NSHTTPURLResponce*)response {
_response = [response retain];
NSDictionary* headers = [_response allHeaderFields];
NSURLConnectionDelegate
のデリゲートメソッドである、 connection:didReceiveResponse:
は NSURLResponce
を引数にとるのですが、何故か NSHTTPURLResponce
が直接指定されています。通常はこれでも問題ありませんが、fileスキームのURLは当然HTTPではありませんから、 NSHTTPURLResponse
を返しません。従って allHeaderFields
の呼び出しでエラーになってしまいます。NSURLResponce
がきても動作する様にしてしまいました。///////////////////////////////////////////////////////////////////////////////////////////////////また、あとから知ったのですが、Three20においては以下のようなURLが使用できるみたいです。
///////////////////////////////////////////////////////////////////////////////////////////////////
#pragma mark -
#pragma mark NSURLConnectionDelegate
///////////////////////////////////////////////////////////////////////////////////////////////////
- (void)connection:(NSURLConnection*)connection didReceiveResponse:(NSURLResponse*)response {
_response = [response retain];
if ([_response isMemberOfClass:NSHTTPURLResponse.class]) {
NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse *)_response;
NSDictionary* headers = [httpResponse allHeaderFields];
int contentLength = [[headers objectForKey:@"Content-Length"] intValue];
// If you hit this assertion it's because a massive file is about to be downloaded.
// If you're sure you want to do this, add the following line to your app delegate startup
// method. Setting the max content length to zero allows anything to go through. If you just
// want to raise the limit, set it to any positive byte size.
// [[TTURLRequestQueue mainQueue] setMaxContentLength:0]
TTDASSERT(0 == _queue.maxContentLength || contentLength <=_queue.maxContentLength);
if (contentLength > _queue.maxContentLength && _queue.maxContentLength) {
TTDCONDITIONLOG(TTDFLAG_URLREQUEST, @"MAX CONTENT LENGTH EXCEEDED (%d) %@",
contentLength, _urlPath);
[self cancel];
}
_responseData = [[NSMutableData alloc] initWithCapacity:contentLength];
} else {
_responseData = [[NSMutableData alloc] initWithCapacity:response.expectedContentLength];
}
}
Three20/TTGlobalCorePaths.h
にて定義されています。photo = [[[PhotoBookPhoto alloc] initWithURL:@"bundle://image.png"たぶん Three20以外では使用できない記法 なので注意が必要ですが、この方法で読み込むと
smallURL:@"documents://thumbnails/smallImage.png"
size:CGSizeMake(960, 640)] autorelease];
NSHTTPURLResponce
が返却されるためコードを書き換えなくても正常に動作します。 こちらのほうが簡単でThree20の開発チームの人もそうしているのでお勧めです。