home > 投稿 > Objective-C as Flash : URLLoader
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

トラックバックURL

http://faces2.bascule.co.jp/mt/mt-tb.cgi/591

コメントを投稿

(コメントには承認が必要になることがあります。承認されるまではコメントは表示されません。)