2009/05/17
Objective-C as Flash : URLLoader
FLASH の URLLoader が使いたかったので暫定実装。
URLLoader.delegate ・・・Dispatch先のクラス
URLLoader.open ・・・開始時メソッドを指定(SEL)
URLLoader.ioError ・・・エラーメソッドを指定(SEL)※5/25追記
URLLoader.progress ・・・now loading メソッドを指定(SEL)
URLLoader.complete ・・・完了時メソッドを指定(SEL)
[URLLoader load:string_url] ・・・ロード
[URLLoader close] ・・・ロードをキャンセル※5/25追記
complete後に以下のプロパティが読めます。
URLLoader.data ・・・生データ(NSData)
URLLoader.text ・・・ふつうにテキストを読んでくる(UTF-8)
URLLoader.variables ・・・loadVariablesみたいにパース(NSDictionary)
※↑携帯コンテンツのアプリ移植に便利なようにSJISで読む仕様
URLLoader.image ・・・画像で渡す(UIImage:ASでいうbitmapData)
URLLoader.tsv ・・・独自仕様の Tab Separated Values(NSDictionary:連想配列)
import するとこんな風に書けます。
iPhone ではネットが切れることが日常なのでエラー処理があると便利です。
- (void)onComplete:(URLLoader*)aLoader{
NSLog(@"%@",aLoader.text);
}
- (void)onError:(URLLoader*)aLoader{
NSLog(@"%@",[aLoader.error localizedDescription]);//5/25追記
}
- (void)applicationDidFinishLaunching:(UIApplication *)application {
URLLoader *l = [[URLLoader alloc] initWithDelegate:self];
l.complete = @selector(onComplete:);
l.ioError = @selector(onError:);//5/25追記
[l load:@"http://faces.jp/"];
[window makeKeyAndVisible];
}
URLLoader.h
//
// URLLoader.h
// fooLoader
//
// Created by ao on 09/05/25.
// Copyright 2009 Bascule. All rights reserved.
//
#import <Foundation/Foundation.h>
@interface URLLoader : NSObject {
int bytesLoaded;
int bytesTotal;
NSMutableData *data;
NSString *dataFormat;
SEL complete;
//SEL httpStatus;
SEL ioError;
SEL open;
SEL progress;
//SEL securityError;
NSError *error;
NSString *text;
NSDictionary *variables;
NSDictionary *tsv;
UIImage *image;
NSURLConnection *urlConection;
id delegate;
}
@property (assign) id delegate;
@property int bytesLoaded;
@property int bytesTotal;
@property (nonatomic, retain) NSMutableData *data;
@property (nonatomic, retain) NSString *dataFormat;
- initWithDelegate:(id)aDelegate;
- (void)close;
- (void)load:(NSString *)aUrl;
@property SEL complete;
@property SEL ioError;
@property SEL open;
@property SEL progress;
@property (nonatomic, retain) NSError *error;
- (NSString*)text;
- (NSDictionary*)variables;
- (NSDictionary*)tsv;
- (UIImage*)image;
@end
URLLoader.m
//
// URLLoader.m
// fooLoader
//
// Created by ao on 09/05/25.
// Copyright 2009 Bascule. All rights reserved.
//
#import "URLLoader.h"
@implementation URLLoader
//パブリックプロパティ
@synthesize bytesLoaded;
@synthesize bytesTotal;
@synthesize data;
@synthesize dataFormat;
//イベントメソッド
@synthesize complete;
@synthesize open;
@synthesize progress;
@synthesize ioError;
@synthesize delegate;
@synthesize error;
NSArray* explode(NSString *$delimiter, NSString *$string){
return [$string componentsSeparatedByString:$delimiter];
}
int count(NSArray *$array){
return [$array count];
}
NSMutableDictionary* parse_str(NSString *$str){
id $item = [[NSMutableDictionary alloc] init];
id $queries = explode(@"&",$str);
for(id $q in $queries){
id $array = explode(@"=",$q);
if(count($array)==1){
$array = [NSArray arrayWithObjects:[$array objectAtIndex:0], @"", nil];
}
if(count($array)>=2){
[$item setValue:[$array objectAtIndex:1] forKey:[$array objectAtIndex:0] ];
}
}
return $item;
}
- initWithDelegate:(id)aDelegate{
[self init];
self.delegate = aDelegate;
return self;
}
- (NSString*)text{
text = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
return text;
}
- (NSDictionary*)variables{
id s = [[NSString alloc] initWithData:data encoding:NSShiftJISStringEncoding];
variables = parse_str(s);
return variables;
}
- (UIImage*)image{
return [UIImage imageWithData:data];
}
- (NSDictionary*)tsv{
id rows = explode(@"\n",self.text);
id keys = explode(@"\t",[rows objectAtIndex:0]);
id items = [[NSMutableDictionary alloc] init];
for(int i=1;i<count(rows);i++){
id cells = explode(@"\t",[rows objectAtIndex:i]);
id item = [[NSMutableDictionary alloc] init];
[item setValue:[[NSNumber alloc] initWithInteger:i] forKey:@"id"];
for(int j=0;j<count(cells);j++){
if(![[cells objectAtIndex:j] isEqualToString:@""]){
[item setObject:[cells objectAtIndex:j] forKey:[keys objectAtIndex:j]];
}
}
[items setValue:item forKey:[[NSNumber alloc] initWithInteger:i]];
}
return items;
}
- (void)dispatch:(SEL)aSelector{
if( [delegate respondsToSelector:aSelector] ) {
[delegate performSelector:aSelector withObject:self];
}
}
- (void)load:(NSString *)aUrl{
NSURLRequest* request = [NSURLRequest requestWithURL:[NSURL URLWithString:aUrl]];
urlConection = [[NSURLConnection alloc] initWithRequest:request delegate:self];
bytesLoaded = 0;
}
- (void)close{
[urlConection cancel];//未テスト。動かなかったらごめん
}
- (void)connection:(NSURLConnection *)aConnection didFailWithError:(NSError *)anError{
error = anError;
[self dispatch:ioError];
//ダイアログは不要ならカットして
UIAlertView *alert = [[[UIAlertView alloc] initWithTitle:@"Error" message:[[anError localizedDescription] capitalizedString] delegate:self cancelButtonTitle:nil otherButtonTitles:@"OK",nil] autorelease];
[alert show];
}
//- (void)connection:(NSURLConnection *)aConnection didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge *)aChallenge{}
- (void)connection:(NSURLConnection *)aConnection didReceiveData:(NSData *)aData{
[data appendData:aData];
bytesLoaded = data.length;
[self dispatch:progress];
}
- (void)connection:(NSURLConnection *)aConnection didReceiveResponse:(NSURLResponse *)aResponse{
bytesTotal = [aResponse expectedContentLength];
dataFormat = [aResponse MIMEType];
data = [[NSMutableData alloc] init];
[self dispatch:open];
}
//- (NSCachedURLResponse *)connection:(NSURLConnection *)connection willCacheResponse:(NSCachedURLResponse *)cachedResponse{}
//- (NSURLRequest *)connection:(NSURLConnection *)connection willSendRequest:(NSURLRequest *)request redirectResponse:(NSURLResponse *)redirectResponse{}
- (void)connectionDidFinishLoading:(NSURLConnection *)aConnection{
[self dispatch:complete];
}
@end