10/30/2013
MacOS X MavericksのVirtualBoxでWIndows 7が起動しない時の対処法
Kernel driver not installed (rc=1908)
Make sure the kernel module has been loaded successfully.
というエラーポップアップでVirtualBoxにインストールしているWindows 7が起動しない。しかもMacOS本体を立ち上げ直すたびに再現するようで困っている。。
この画面が立ち上がってしまうと普通に終了できなくなるのでアクティビティモニタからVirtualBoxを選んで強制終了するしかない。
この問題の対処法はVirtualBoxの再インストール、VirtualBoxをきちんと終了させてから行おう。
VirtualBoxのインストールはたまに失敗してファイルが破損したりして、バックアップがないと悲惨なことになる可能性があるので、注意してオペレーションして下さい。
インストールが正常に完了すればMacを再起動しなくても立ち上がると思う。
Label:
Mac,
Mavericks,
OS,
VirtualBox
10/24/2013
MacOS X MavericksにしたらVirtualBoxがおかしくなった時の対処法
Mac OS X MavericksにしたらVirtualBoxがおかしくなったので対処した方法を書いておきます。
事象
ホストオンリーアダプタが無効になり、ホストからゲストOSへSSHが出来なくなった。
対処
VirtualBox 4.3をインストールする。
https://www.virtualbox.org/wiki/Downloads
2013/10/23時点、初回のtryで開発元が認証できないエラーが出てインストールできなかったが、2013/10/24にretryしたら正常にインストールできた。
インストールに失敗すると、アプリケーションとしてのVirtualBoxファイルが破損して起動できなくなったりするので厳重注意!
既存のアプリケーションフォルダとVirtualBox VMディレクトリをrenameしてからインストールを行うと失敗した場合手軽に復元できるのでよい。
VirtualBox VMディレクトリはサイズが大きいと思うのでコピペはお勧めできない。
通常ユーザーディレクトリ直下に作成されるVirtualBox VMディレクトリは当然引き継げるので、挙動が変になった時に設定をいじったり、消したりしないように。
VirtualBox 4.3 Oracle VM VirtualBox Extension Pack
https://www.virtualbox.org/wiki/Downloads
事象
ホストオンリーアダプタが無効になり、ホストからゲストOSへSSHが出来なくなった。
対処
VirtualBox 4.3をインストールする。
https://www.virtualbox.org/wiki/Downloads
2013/10/23時点、初回のtryで開発元が認証できないエラーが出てインストールできなかったが、2013/10/24にretryしたら正常にインストールできた。
インストールに失敗すると、アプリケーションとしてのVirtualBoxファイルが破損して起動できなくなったりするので厳重注意!
既存のアプリケーションフォルダとVirtualBox VMディレクトリをrenameしてからインストールを行うと失敗した場合手軽に復元できるのでよい。
VirtualBox VMディレクトリはサイズが大きいと思うのでコピペはお勧めできない。
通常ユーザーディレクトリ直下に作成されるVirtualBox VMディレクトリは当然引き継げるので、挙動が変になった時に設定をいじったり、消したりしないように。
VirtualBox 4.3 Oracle VM VirtualBox Extension Pack
https://www.virtualbox.org/wiki/Downloads
こちらも併せてダウンロードしておくと良い。
ダウンロードしたらVirtualBox VM直下などに保存して、
VirtualBox > 環境設定 > 機能拡張にある拡張パッケージとして追加する。
4.3では、ゲストOSの画面リサイズが自動で出来るようになっている反面、マルチディスプレイ対応で画面上部にメニューバーがある都合上、ゲストOSの画面をフルスクリーンで表示すると画面下部が見切れたりする。
スケールモードでなんとかなる。
Label:
Mac,
Mavericks,
OS,
VirtualBox
10/14/2012
KeyRemap4MacBookの設定方法
MacBookProを使っているのだが、コードを書く際に
矢印キーが押しにくいのでKeyRemap4MacBookを使って
以下のようにRemapした。
↑はControl-L + I
↓はControl-L + K
←はControl-L + J
→はControl-L + L
ついでにHOMEとENDもそれぞれRemapした。
HOMEはControl-L + A
ENDはControl-L + E
まずはKeyRemap4MacBookをインストールする。
つぎにリファレンスを一読する。
最後に私が設定しているprivate.xmlを貼ります。
<?xml version="1.0"?>
<root>
<item>
<name>CUSTOM_CURSOR_UP</name>
<identifier>CUSTOM_CURSOR_UP</identifier>
<autogen>
--KeyToKey--
KeyCode::I, ModifierFlag::CONTROL_L,
KeyCode::CURSOR_UP
</autogen>
</item>
<item>
<name>CUSTOM_CURSOR_DOWN</name>
<identifier>CUSTOM_CURSOR_DOWN</identifier>
<autogen>
--KeyToKey--
KeyCode::K, ModifierFlag::CONTROL_L,
KeyCode::CURSOR_DOWN
</autogen>
</item>
<item>
<name>CUSTOM_CURSOR_LEFT</name>
<identifier>CUSTOM_CURSOR_LEFT</identifier>
<autogen>
--KeyToKey--
KeyCode::J, ModifierFlag::CONTROL_L,
KeyCode::CURSOR_LEFT
</autogen>
</item>
<item>
<name>CUSTOM_CURSOR_RIGHT</name>
<identifier>CUSTOM_CURSOR_RIGHT</identifier>
<autogen>
--KeyToKey--
KeyCode::L, ModifierFlag::CONTROL_L,
KeyCode::CURSOR_RIGHT
</autogen>
</item>
<item>
<name>CUSTOM_HOME</name>
<identifier>CUSTOM_HOME</identifier>
<autogen>
--KeyToKey--
KeyCode::A, ModifierFlag::CONTROL_L,
KeyCode::HOME
</autogen>
</item>
<item>
<name>CUSTOM_END</name>
<identifier>CUSTOM_END</identifier>
<autogen>
--KeyToKey--
KeyCode::E, ModifierFlag::CONTROL_L,
KeyCode::END
</autogen>
</item>
</root>
矢印キーが押しにくいのでKeyRemap4MacBookを使って
以下のようにRemapした。
↑はControl-L + I
↓はControl-L + K
←はControl-L + J
→はControl-L + L
ついでにHOMEとENDもそれぞれRemapした。
HOMEはControl-L + A
ENDはControl-L + E
まずはKeyRemap4MacBookをインストールする。
つぎにリファレンスを一読する。
最後に私が設定しているprivate.xmlを貼ります。
<?xml version="1.0"?>
<root>
<item>
<name>CUSTOM_CURSOR_UP</name>
<identifier>CUSTOM_CURSOR_UP</identifier>
<autogen>
--KeyToKey--
KeyCode::I, ModifierFlag::CONTROL_L,
KeyCode::CURSOR_UP
</autogen>
</item>
<item>
<name>CUSTOM_CURSOR_DOWN</name>
<identifier>CUSTOM_CURSOR_DOWN</identifier>
<autogen>
--KeyToKey--
KeyCode::K, ModifierFlag::CONTROL_L,
KeyCode::CURSOR_DOWN
</autogen>
</item>
<item>
<name>CUSTOM_CURSOR_LEFT</name>
<identifier>CUSTOM_CURSOR_LEFT</identifier>
<autogen>
--KeyToKey--
KeyCode::J, ModifierFlag::CONTROL_L,
KeyCode::CURSOR_LEFT
</autogen>
</item>
<item>
<name>CUSTOM_CURSOR_RIGHT</name>
<identifier>CUSTOM_CURSOR_RIGHT</identifier>
<autogen>
--KeyToKey--
KeyCode::L, ModifierFlag::CONTROL_L,
KeyCode::CURSOR_RIGHT
</autogen>
</item>
<item>
<name>CUSTOM_HOME</name>
<identifier>CUSTOM_HOME</identifier>
<autogen>
--KeyToKey--
KeyCode::A, ModifierFlag::CONTROL_L,
KeyCode::HOME
</autogen>
</item>
<item>
<name>CUSTOM_END</name>
<identifier>CUSTOM_END</identifier>
<autogen>
--KeyToKey--
KeyCode::E, ModifierFlag::CONTROL_L,
KeyCode::END
</autogen>
</item>
</root>
Label:
KeyRemap4MacBook
4/17/2012
JavaScriptで数値の配列をソートする
Array.prototype.sortNumbers = function (op) {if (op || 0) {
//降順ソート return this.sort(function(a,b){ return b - a; }); } else { //昇順ソート return this.sort(function(a,b){ return a - b; }); }}/*var arr = [1,15,3,8,24];alert(arr.sortNumbers());*/
Label:
JavaScript
1/23/2012
Mac OS Xでパスワード付きzipファイルを作る方法
ターミナルで対象ファイルのzipファイルを作成して、パスワードを付けるという流れで作成する。
1.ターミナルで対象ファイルがある場所まで移動(例:tarouのDesktopにあるhoge.pdf)
$ cd /Users/tarou/Desktop/
2.zipファイルの作成(例:hoge.zipという名前のzipファイルを作成)
$ zip hoge.zip hoge.pdf
3.作成したzipファイルにパスワードを付与(例:パスワードをpassとした場合)
$ zipcloak hoge.zip
Enter password: pass
Verify password: pass
以上、3ステップです。
1.ターミナルで対象ファイルがある場所まで移動(例:tarouのDesktopにあるhoge.pdf)
$ cd /Users/tarou/Desktop/
2.zipファイルの作成(例:hoge.zipという名前のzipファイルを作成)
$ zip hoge.zip hoge.pdf
3.作成したzipファイルにパスワードを付与(例:パスワードをpassとした場合)
$ zipcloak hoge.zip
Enter password: pass
Verify password: pass
以上、3ステップです。
1/10/2012
iOSシミュレータの画面をスクリーンショットする方法
iOSアプリ画面のスクリーンショットは起動画像やスタートガイドなので
よく使われる。実機の画面をコピーしてもよいが、iOSシミュレータの画面を
使うほうが勝手が良い。
なぜなら、iOSシミュレータのデバイスを切り替えることで、Retinaのそれも
コピー出来るからだ。
- Ctrl+Cmd+Cで画面コピー(メニューからも可能)
- プレビュー.appを起動
- Cmd+Nでコピー画像を貼り付ける。
以上の手順で作成する。
iPhoneのLaunch名:Default.png
iPhone(Retina)のLaunch名:Default@2x.png
iPad(Portrait)のLaunch名:Default-Portrait~ipad.png
iPad(Landscape)のLaunch名:Default-Landscape~ipad.png
Launch画像を作る上で注意すべきはiPadの画面サイズ
コピーされた画像は768×1024なので、これを
748×1024と1004×768にしなければならない。
Photoshopなどで加工しよう。
Label:
Screenshot
9/26/2011
iOSデバイスを判定するSnippet
主にiPadなのかそれ以外なのかを判定するのに使っている。
BOOL isPad = [[UIDevice currentDevice]userInterfaceIdiom] == UIUserInterfaceIdiomPad;
if (isPad) {
} else {
}
読み込むnibファイルを切り替えたり
NSString *nibName = [[UIDevice currentDevice]userInterfaceIdiom] == UIUserInterfaceIdiomPad ? @"viewController_iPad" : @"viewController_iPhone";
UIViewController *viewController = [[UIViewController alloc]initWithNibName:nibName bundle:nil];
短縮URLを作るNSString (shortURL) カテゴリ
昨日の短縮URLを展開するNSString (expandURL) カテゴリと対となるカテゴリ。
Bitly APIを使用しているので、事前にBitlyのアカウントとAPIキーを取得しておく必要がある。また、JSON形式の返り値をNSDictionaryに変換するためにSBJSONを使用している。
NSString+shortURL.h
Bitly APIを使用しているので、事前にBitlyのアカウントとAPIキーを取得しておく必要がある。また、JSON形式の返り値をNSDictionaryに変換するためにSBJSONを使用している。
NSString+shortURL.h
#import <Foundation/NSString.h>
@interface NSString (shortURL)
+ (NSString *)shortURL:(NSString *)longUrl;
@end
NSString+shortURL.m
#import "NSString+shortURL.h"
#import "SBJson.h"
static NSString *kBitlyWrapperString = @"http://api.bit.ly/shorten?version=2.0.1&format=json&longUrl=";
static NSString *kBitlyFootterString = @"&login=ログイン名&apiKey=APIキー";
@implementation NSString (shortURL)
+ (NSString *)shortURL:(NSString *)longUrl{
NSString *aaa = nil;
NSString *escapeStr = (NSString *)CFURLCreateStringByAddingPercentEscapes(kCFAllocatorDefault, (CFStringRef)longUrl, NULL, CFSTR(":/?#[]@!$&’()*+,;="), kCFStringEncodingUTF8);
NSString *str = [NSString stringWithFormat:@"%@%@%@",kBitlyWrapperString,escapeStr,kBitlyFootterString];
NSURL *url = [NSURL URLWithString:str];
NSData *data = [NSData dataWithContentsOfURL:url];
if (data) {
NSString *tempStr = [[[NSString alloc]initWithData:data encoding:NSUTF8StringEncoding]autorelease];
NSDictionary *aDic = [tempStr JSONValue];
NSLog(@"%@",[aDic description]);
NSNumber *errorCode = [aDic objectForKey:@"errorCode"];
NSString *statusCode = [aDic objectForKey:@"statusCode"];
if ([errorCode intValue] == 0 && [statusCode isEqualToString:@"OK"]) {
NSDictionary *results = [[aDic objectForKey:@"results"]objectForKey:longUrl];
NSString *shortUrl = [results objectForKey:@"shortUrl"];
aaa = shortUrl;
} else {
aaa = longUrl;
}
} else {
aaa = longUrl;
}
return aaa;
}
@end
Label:
Bitly,
Category,
JSON,
NSDictionary,
NSString
9/25/2011
短縮URLを展開するNSString (expandURL) カテゴリ
短縮URLを見ない日はなくなった。
APIが返す値はJSON形式で返ってくるものを選び、SBJSONを利用してNSDictionary形式に変換、後続の処理を行なっている。失敗した場合は展開前の短縮URLが返るようにしてある。展開できる短縮URLの種類はAPIに依存しているので注意されたし。またAPIサービスそのものの業務継続性にも注意が必要。
Twitterなどは自前でt.coなる短縮URLを用意して悪意のある短縮URLからユーザーを守ろうという試みも行われている。また、アクセスの解析も行われているようだ。
iOSアプリケーションを開発する上では、短縮URLを展開して元URLのURLスキームを解析することにより、UIApplicationの-(BOOL)OpenURL:(NSURL *)メソッドを使用するか否かの判断が可能になる。
これを使用するとSafariやその他の外部アプリケーションが起動されるため、ユーザーが自前のアプリケーションから離れてしまうからだ。
この短縮URLを展開してくれるAPIが幾つか存在するので、その中の2つを使ってNSStringのカテゴリとしてまとめてみた。
APIが返す値はJSON形式で返ってくるものを選び、SBJSONを利用してNSDictionary形式に変換、後続の処理を行なっている。失敗した場合は展開前の短縮URLが返るようにしてある。展開できる短縮URLの種類はAPIに依存しているので注意されたし。またAPIサービスそのものの業務継続性にも注意が必要。
NSString+expandURL.h
#import <Foundation/NSString.h>
@interface NSString (expandURL)
+ (NSString *)expandURL:(NSString *)urlStr;
@end
NSString+expandURL.m
#import "NSString+expandURL.h"
#import "SBJson.h"
@implementation NSString (expandURL)
+ (NSString *)expandURL:(NSString *)urlStr{
NSString *str = nil;
NSURL *url = nil;
NSData *data = nil;
NSString *aaa = nil;
str = [NSString stringWithFormat:@"http://api.unshort.me/?r=%@&t=json",urlStr];
url = [NSURL URLWithString:str];
data = [NSData dataWithContentsOfURL:url];
if (data) {
NSString *result = [[[NSString alloc]initWithData:data encoding:NSUTF8StringEncoding]autorelease];
NSDictionary *aDic = [result JSONValue];
NSString *status = [aDic objectForKey:@"success"];
if ([status isEqualToString:@"true"]){
aaa = [aDic objectForKey:@"resolvedURL"];
} else {
aaa = urlStr;
}
} else {
str = [NSString stringWithFormat:@"http://expandurl.appspot.com/expand?url=%@",urlStr];
url = [NSURL URLWithString:str];
data = [NSData dataWithContentsOfURL:url];
if (data) {
NSString *result = [[[NSString alloc]initWithData:data encoding:NSUTF8StringEncoding]autorelease];
NSDictionary *aDic = [result JSONValue];
NSString *status = [aDic objectForKey:@"status"];
if ([status isEqualToString:@"OK"]){
aaa = [aDic objectForKey:@"end_url"];
} else {
aaa = urlStr;
}
} else {
aaa = urlStr;
}
}
return aaa;
}
@end
Label:
Category,
JSON,
NSDictionary,
NSString
9/14/2011
UITableViewのtableFooterViewにUIButtonを追加する
参考画像
上の実装例は設定したボタンを押すとアラートがポップアップする。
実際にはデータを読み込む処理や、読み込んだ後に追加されたデータの直前まで
テーブルをスクロールさせるような処理を追加する。
このように追加でデータを読み込むような使い方をするケースが多い。
テーブルを引っ張って更新するのが流行りだが、Footerの場合はCellの数によって
トリガーとなる基準の位置座標が変わるので、UIButtonで実装する方が簡単。
- (void)viewDidLoad{}内でUIButtonを作成してtableViewFooterに設定する。
- (void)viewDidLoad
{
[super viewDidLoad];
readMoreButton = [UIButton buttonWithType:UIButtonTypeCustom];
[readMoreButton addTarget:self action:@selector(readMoreButtonPushed) forControlEvents:UIControlEventTouchUpInside];
[readMoreButton setTitle:@"Read more" forState:UIControlStateNormal];
[readMoreButton setTitle:@"Load" forState:UIControlStateHighlighted];
[readMoreButton setTitle:@"Loading" forState:UIControlStateDisabled];
readMoreButton.backgroundColor = LIGHT_BACKGROUND;
readMoreButton.frame = CGRectMake(0, 0, self.tableView.frame.size.width, 44);
self.tableView.tableFooterView = readMoreButton;
}
- (void)readMoreButtonPushed{
readMoreButton.enabled = NO;
UIAlertView *alert = [[UIAlertView alloc]initWithTitle:@"message" message:@"Read more button pushed." delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil];
[alert show];
[alert release];
readMoreButton.enabled = YES;
}
上の実装例は設定したボタンを押すとアラートがポップアップする。
実際にはデータを読み込む処理や、読み込んだ後に追加されたデータの直前まで
テーブルをスクロールさせるような処理を追加する。
Label:
UIButton,
UITableView
9/12/2011
UITableViewCell内部にあるUIImageViewをタップした時の処理
UIImageViewを含むカスタマイズされたUITableViewCellがあったとする。
このUIImageViewをタップした時に何らかの処理を実行したい時の実装例。
上の実装例ではMyTableViewCellに画像URLを持たせて、UIImageViewをタップしたらsample.pngをダウンロードしてtapme.pngと差し替えるといった処理を行っている。
このUIImageViewをタップした時に何らかの処理を実行したい時の実装例。
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = CELLIDENTIFIER;
MyTableViewCell *cell = (MyTableViewCell *)[tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
UIViewController* viewController = [[UIViewController alloc] initWithNibName:CellIdentifier bundle:nil];
cell = (MyTableViewCell *)viewController.view;
[viewController release];
}
// Configure the cell...
cell.imageURL = @"http://sample.com/sample.png";
cell.iconImageView.userInteractionEnabled = YES;
cell.iconImageView.image = [UIImage imageNamed:@"tapme.png"];
UITapGestureRecognizer *tapGesture = [[UITapGestureRecognizer alloc]initWithTarget:self action:@selector(tapImage:)];
tapGesture.numberOfTapsRequired = 1;
[cell.iconImageView addGestureRecognizer:tapGesture];
[tapGesture release],tapGesture = nil;
return cell;
}
- (void)tapImage:(id)sender{
UIImageView *imgView = (UIImageView *)[sender view];
if ([imgView.image isEqual:noImage]) {
BooksTableViewCell *cell = (BooksTableViewCell *)[[imgView superview]superview];
NSLog(@"%@",[[imgView superview]class]);
NSLog(@"%@",[[[imgView superview]superview]class]);
NSURL *imgURL = [NSURL URLWithString:cell.imageURL];
NSLog(@"%@",cell.imageURL);
UIImage *img = nil;
NSData *data = [NSData dataWithContentsOfURL:imgURL];
if (data) {
img = [UIImage imageWithData:data];
[cell.iconImageView setImage:img];
} else {
return;
}
}
}
UITableViewは画像を持つセルを多数表示するとメモリ不足で落ちたりするので、このような処理もメモリ使用量を節減する選択肢となり得る。
実際の実装では画像URLは配列から取り出すことになるだろうし、tapme.pngも1つのインスタンスを使い回すことになるだろう。
- (void)tapImage:(id)senderメソッドについては、[sender view]は確かにここでいうタップしたiconImageViewなのだが、iconImageViewとMyTableViewCellの間にUITableViewCellContentViewが挟まっているので、それをNSLogで明示している。
UIImageを指定サイズにリサイズするSnippet
- (UIImage *)resizeImage:(UIImage *)image width:(CGFloat)width height:(CGFloat)height{
UIImage *returnImage = nil; //リサイズ後のUIImage
UIGraphicsBeginImageContext(CGSizeMake(width, height));
[image drawInRect:CGRectMake(0, 0, width, height)];
returnImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return returnImage;
}
PropertyListからNSDictionaryを作り、Keyをアルファベット順に並べ替えてNSArrayに格納する
まずはPropertyListを作る。
仮にDictionary.plistとする。
次にDictionary.plistからNSDictionaryを作る。
このmyDictionaryとkeyArrayをUITableViewControllerクラスのメンバとしておけば、keyArrayをUITableViewのテーブルの表示やセルタイトルに使い、テーブルセル選択時にセルのタイトルをkeyとしてmyDictionaryのvalueが取り出せる。
仮にDictionary.plistとする。
![]() |
| Dictionary.plist |
次にDictionary.plistからNSDictionaryを作る。
NSString *path = [[NSBundle mainBundle]pathForResource:@"Dictionary" ofType:@"plist"];
NSDictionary *myDictionary = [[NSDictionary alloc]initWithContentsOfFile:path];
最後にKeyをアルファベット順に並べ替えてNSArrayに格納する。
NSCountedSet *cset = [[NSCountedSet alloc] initWithArray:[myDictionary allKeys]];
NSArray *keyArray = [[NSArray alloc]initWithArray:[[cset allObjects]sortedArrayUsingSelector:@selector(compare:)]];
[cset release];
NSDictionaryのKeyを配列として持ちたい、かつそれがアルファベット順であってほしい時にこれを使う。あるいはテーブルの構成要素をプロパティリストで表現したい時にも使える。
Label:
NSArray,
NSCountedSet,
NSDictionary,
PropertyList
NSXMLParserとBitlyAPIを使って短縮URLを作る
BitlyShortURLというNSObjectのサブクラスを作る。
まずはBitlyShortURL.h
まずはBitlyShortURL.h
#import <Foundation/Foundation.h>
@interface BitlyShortURL : NSObject <NSXMLParserDelegate>
{
NSString *_baseURL; //短縮される元URL
NSString *_resultURL; //APIによって短縮されたURL
}
- (id)initWithLongURL:(NSString *)longURL; //元URLを使って初期化
- (NSString *)parse; //パースして短縮URLを返す
@end
次にBitlyShortURL.m
パースされた要素の通り、他にも色々な情報があるがとりあえず短縮URLを手に入れたい!って時にこれから始める。
#import "BitlyShortURL.h"
static NSString *kBitlyWrapperString = @"http://api.bit.ly/shorten?version=2.0.1&format=xml&longUrl=";
static NSString *kBitlyFootterString = @"&login=ログイン名&apiKey=APIキー";
@implementation BitlyShortURL
- (NSString *)returnLink:(NSString *)str{
return (NSString *)CFURLCreateStringByAddingPercentEscapes(kCFAllocatorDefault, (CFStringRef)str, NULL, CFSTR(":/?#[]@!$&’()*+,;="), kCFStringEncodingUTF8);
}
- (id)initWithLongURL:(NSString *)longURL{
self = [super init];
if (self) {
NSString *str = [NSString stringWithFormat:@"%@%@%@",kBitlyWrapperString,[self returnLink:longURL],kBitlyFootterString];
_baseURL = [[NSString alloc]initWithString:str];
NSLog(@"%@",_baseURL);
_resultURL = @"error";
}
return self;
}
- (NSString *)parse{
NSURL *url = [NSURL URLWithString:_baseURL];
NSXMLParser *parser = [[NSXMLParser alloc]initWithContentsOfURL:url];
[parser setDelegate:self];
[parser parse];
if (_resultURL == nil) {
_resultURL = @"error";
}
return _resultURL;
}
- (void)dealloc{
[_baseURL release],_baseURL = nil;
[_resultURL release],_resultURL = nil;
[super dealloc];
}
#pragma mark -
#pragma mark NSXMLParserDelegate Protocol
- (void)parserDidStartDocument:(NSXMLParser *)parser{
}
- (void)parserDidEndDocument:(NSXMLParser *)parser{
}
- (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName
namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qualifiedName
attributes:(NSDictionary *)attributeDict {
NSLog(@"<%@>",elementName);
if ([elementName isEqualToString:@"shortUrl"]) {
[_resultURL release],_resultURL = nil;
}
}
- (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string {
NSLog(@"%@",string);
if (_resultURL == nil) {
_resultURL = [[NSString alloc]initWithString:string];
}
}
- (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName
namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName {
NSLog(@"</%@>",elementName);
}
@end
Label:
Bitly,
NSXMLParser
iOSのバージョン判定のSnippet
iOSのバージョンによって処理を変えたい時などに使うSnippet
NSString *versions = [[UIDevice currentDevice]systemVersion];
if ([versions compare:@"5.0"] != NSOrderedAscending) {
} else {
}
上の例はiOS5.0以上なら正とする場合の実装例。
NSXMLParserの基本形
NSXMLParserのサブクラスを作成する。
ここでは
XMLParser.h
XMLParser.m
とする。
まずはXMLParser.h
#import <Foundation/Foundation.h>
@interface XMLParser : NSXMLParser <NSXMLParserDelegate> {
ここでは
XMLParser.h
XMLParser.m
とする。
まずはXMLParser.h
#import <Foundation/Foundation.h>
@interface XMLParser : NSXMLParser <NSXMLParserDelegate> {
}
@end
次にXMLParser.m
#import "XMLParser.h"
@implementation XMLParser
#pragma mark -
#pragma mark Object lifecycle
- (id)initWithContentsOfURL:(NSURL *)url {
self = [super initWithContentsOfURL:url];
if (self) {
[self setDelegate:self];
}
return self;
}
- (id)initWithData:(NSData *)data {
self = [super initWithData:data];
if (self) {
[self setDelegate:self];
}
return self;
}
- (void) dealloc {
[super dealloc];
}
#pragma mark -
#pragma mark NSXMLParserDelegate Protocol
- (void)parserDidStartDocument:(NSXMLParser *)parser{
}
- (void)parserDidEndDocument:(NSXMLParser *)parser{
}
- (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName
namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qualifiedName
attributes:(NSDictionary *)attributeDict {
NSLog(@"<%@>",elementName);
}
- (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string {
NSLog(@"%@",string);
}
- (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName
namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName {
NSLog(@"</%@>",elementName);
}
@end
まずは対象となるXMLの要素をNSLogで出力して、どの要素が必要なのかを確認してから中身を実装していくとよい。
必要な要素に対応したクラスを作成して、それをNSMutableArrayに格納するとUITableViewなどで使い勝手が良い。
Label:
NSXMLParser
NSLog()文を除去するSnippet
${PRODUCT_NAME}-Prefix.pch内に次のコードを挿入する。
不要時には/* */で囲んでコメントアウトしてやる。
デバッグ時にも使うときと使わない時があるのでこの方法を採用している。
不要時には/* */で囲んでコメントアウトしてやる。
デバッグ時にも使うときと使わない時があるのでこの方法を採用している。
//NSLog()文を除去
#ifndef NSLog
#define NSLog(m, args...)
#endif
Label:
Snippet
NSNotificationCenterのサンプルSnippet
登録、通知、監視、登録解除の流れをごく簡単に列挙。
登録
登録
NSNotificationCenter *nc = [NSNotificationCenter defaultCenter];
[nc addObserver:self selector:@selector(valueChanged:) name:@"ValueChanged" object:nil];
通知
NSString *value = @"Value";
NSNotification *n = [NSNotification notificationWithName:@"ValueChanged" object:value];
[[NSNotificationCenter defaultCenter]postNotification:n];
監視
※事前に登録をしておいた上でselectorのメソッドを実装する。
- (void)valueChanged:(NSNotification *)n{
NSString *str = n.object;
NSLog(@"%@",str);
}登録削除
- (void)viewDidUnload
{
[[NSNotificationCenter defaultCenter]removeObserver:self];
[super viewDidUnload];
}
Label:
NSNotificationCenter,
Snippet
9/09/2011
7bunnies.comのブログ運用を始めました。
ここではiOSアプリ開発の近況を中心に活動内容を不定期に書いていきたいなと思います。
筆不精なので更新が途切れることもあるかと思いますが温かい目で見守ってくださることを期待しております。
筆不精なので更新が途切れることもあるかと思いますが温かい目で見守ってくださることを期待しております。
登録:
投稿 (Atom)



