iPhoneレシピ4:UIActionSheetにプログレスバーを表示する
ポイント
UIActionSheetの高さはタイトルの改行か、setNumberOfRowsメソッドで設定する。ただしsetNumberOfRowsはドキュメントには載っていないメソッド。
UIActionSheetはメインスレッドで表示しないと、ボタンが効かないっぽい。また、表示とその他の処理を同一スレッド内で行うと、処理終了までUIActionSheetが表示されない。
ソース
UIActionSheetの組み立て部分はこんな感じ。
- (void)viewDidLoad { [super viewDidLoad]; actionSheet = [[UIActionSheet alloc] initWithTitle:@"Please wait\n\n\n\n" delegate:self cancelButtonTitle:NSLocalizedString(@"Cancel",nil) destructiveButtonTitle:nil otherButtonTitles:nil]; progressBar = [[UIProgressView alloc] initWithFrame:CGRectMake(30.0f, 40.0f, 240.0f, 90.0f)]; progressBar.progressViewStyle = UIProgressViewStyleDefault; progressBar.progress = 0.0f; [actionSheet addSubview:progressBar]; progressLabel = [[UILabel alloc] initWithFrame:CGRectMake(30.0f, 50.0f, 240.0f, 20.0f)]; progressLabel.backgroundColor = [UIColor clearColor]; progressLabel.textColor = [UIColor whiteColor]; progressLabel.font = [UIFont systemFontOfSize:[UIFont systemFontSize]]; [actionSheet addSubview:progressLabel]; }
表示と処理のスレッド分けはこんな感じ。
- (IBAction)start { cancelFlag = NO; // UIActionSheetはメインスレッドで表示しないとボタンが効かないっぽい。 [self showSheet]; [self performSelectorInBackground:@selector(doProcess) withObject:nil]; } - (void)showSheet { progressBar.progress = 0; progressLabel.text = NSLocalizedString(@"Processing...", nil); [actionSheet showInView:self.view]; } // 何かしらの処理 - (void)doProcess { NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; @try { for (int i=0; i<100; i++) { if (cancelFlag) return; // Background threadで動いている時はUIProgressViewをMainThreadで動かすこともできる。 // どちらで動かすべきかはよく分からない。 // [self performSelectorOnMainThread:@selector(progress:) withObject:[NSNumber numberWithFloat:0.01f] waitUntilDone:NO]; [self performSelectorInBackground:@selector(progress:) withObject:[NSNumber numberWithFloat:0.01f]]; [NSThread sleepForTimeInterval:0.1f]; } [actionSheet dismissWithClickedButtonIndex:-1 animated:YES]; } @finally { [pool release]; } } - (void)progress:(NSNumber *)amount { progressBar.progress += [amount floatValue]; NSLog(@"%f", progressBar.progress); } /////////////////////////////////////////////////////////////////// // UIActionSheetDelegate implements // - (void)actionSheet:(UIActionSheet *)sheet didDismissWithButtonIndex:(NSInteger)buttonIndex { if (buttonIndex == sheet.cancelButtonIndex) { cancelFlag = YES; } }
iPhoneレシピ5:zipファイルを解凍する
ポイント
iPhoneにはzlibが入っているので、それを利用して解凍する。
zlibを使うためには、libz***.dylibへのリンクが必要。そのためには、xcodeで「グループとファイル」ビュー上で右クリック→「追加」→「既存のフレームワークを追加」でibz***.dylibを追加すればよい。
生のzlibをそのまま使うのはちょっと面倒だが、zlibと一緒に配布されているminizipをさらにObjective-Cでラップした「HetimaUnZip.framework」をHetimaさんが公開している。
HetimaUnZipはCocoaを使っているため、iPhoneで利用できるよう、Cocoaへの依存部分および不要なminizipファイルの削除と、メモリ上ではなく、直接ファイルに解凍するメソッドを追加したものを利用する。
オリジナルのFrameworkをiPhone上で使う方法が分からないため、とりあえず直接ソースのまま取り込んで使う。
改変したHetimaUnZipはここからダウンロードできる。
ソース
NSString *filePath = @"zipファイルへのパス"; HetimaUnZipContainer *unzipContainer = [[HetimaUnZipContainer alloc] initWithZipFile:filePath]; [unzipContainer setListOnlyRealFile:YES]; HetimaUnZipItem *item; NSEnumerator *contentsEnum = [[unzipContainer contents] objectEnumerator]; // プログレスバー表示用に全ファイルのサイズを取得 expectedUmcompressedContentSize = 0; for (item in contentsEnum) { expectedUmcompressedContentSize += [item uncompressedSize]; LOG(@"zip\tpath:%@\t%d", [item path], [item uncompressedSize]); } // 解凍 contentsEnum = [[unzipContainer contents] objectEnumerator]; for (item in contentsEnum) { NSString *path = [[NSFileManager defaultManager] suggestFilePath:[APPLICATION_DOC_DIR stringByAppendingPathComponent:[item path]]]; BOOL result = [item extractTo:path delegate:self]; if (!result) { NSString *err = [NSString stringWithFormat:NSLocalizedString(@"Failed to extract %@.", nil), [item path]]; UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"" message:err delegate:actionSheet cancelButtonTitle:nil otherButtonTitles:@"OK",nil]; [alert show]; [alert release]; } } // HetimaUnZipItemDelegate // HetimaUnZipItem#extractTo:delegate:の解凍状況はdelegateのメソッドで取得できる。 - (void)item:(HetimaUnZipItem *)item didExtractDataOfLength:(NSUInteger)length { progressBar.progress = progressBar.progress + ((long double)length / (long double)expectedUmcompressedContentSize) * 0.5f; LOG(@"Extracting %f", progressBar.progress); }
iPhoneレシピ6:zipファイルをダウンロードし、Documentsディレクトリに解凍する
下記4つのレシピを組み合わせて、zipファイルをダウンロードし、Documentsディレクトリに解凍する方法。
- iPhone SDKレシピ2:NSURLConnectionを使ってファイルをダウンロードする - Random Note
- iPhone SDKレシピ3:UIProgressViewの使い方 - Random Note
- iPhoneレシピ4:UIActionSheetにプログレスバーを表示する - Random Note
- iPhoneレシピ5:zipファイルを解凍する - Random Note
ポイント
基本的には上記のレシピの中にあるとおり。
ただしiPhone SDKレシピ3:UIProgressViewの使い方 - Random Noteにある、UIProgressViewのprogressプロパティを別スレッドで設定する、という部分の別スレッド呼び出しについては、NSURLConnectionとHetimaUnZipItemの中に隠蔽されている。
ソース
UIActionSheetを用意しておいて、
- (void)viewDidLoad { [super viewDidLoad]; actionSheet = [[UIActionSheet alloc] initWithTitle:@"Please wait...\n\n\n\n" delegate:self cancelButtonTitle:NSLocalizedString(@"Cancel",nil) destructiveButtonTitle:nil otherButtonTitles:nil]; progressBar = [[UIProgressView alloc] initWithFrame:CGRectMake(30.0f, 40.0f, 240.0f, 90.0f)]; progressBar.progressViewStyle = UIProgressViewStyleDefault; progressBar.progress = 0.0f; [actionSheet addSubview:progressBar]; progressLabel = [[UILabel alloc] initWithFrame:CGRectMake(30.0f, 50.0f, 240.0f, 20.0f)]; progressLabel.backgroundColor = [UIColor clearColor]; progressLabel.textColor = [UIColor whiteColor]; progressLabel.font = [UIFont systemFontOfSize:[UIFont systemFontSize]]; progressLabel.text = NSLocalizedString(@"Downloading...", nil); [actionSheet addSubview:progressLabel]; downloaderLock = [[NSLock alloc] init]; }
ダウンロードを開始し、
- (IBAction) download:(id)sender { [urlField resignFirstResponder]; downloadedContentLength = 0; progressBar.progress = 0; NSURLRequest *req = [NSURLRequest requestWithURL:[NSURL URLWithString:[urlField text]]]; [[NSFileManager defaultManager] clearTmpDirectory]; progressLabel.text = NSLocalizedString(@"Downloading...", nil); [actionSheet showInView:self.view]; downloader = [[URLDownload alloc] initWithRequest:req directory:APPLICATION_TMP_DIR delegate:self]; }
ダウンロードが終わったら解凍する。だけ。
- (void)downloadDidFinish:(URLDownload *)download { NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; LOG(download.filePath); progressLabel.text = NSLocalizedString(@"Extracting...", nil); HetimaUnZipContainer *unzipContainer = [[HetimaUnZipContainer alloc] initWithZipFile:download.filePath]; [unzipContainer setListOnlyRealFile:YES]; if ([[unzipContainer contents] count] == 0) { NSString *err = NSLocalizedString(@"No zip file is found.", nil); UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"" message:err delegate:actionSheet cancelButtonTitle:nil otherButtonTitles:@"OK",nil]; [alert show]; [alert release]; } else { HetimaUnZipItem *item; NSEnumerator *contentsEnum = [[unzipContainer contents] objectEnumerator]; expectedUmcompressedContentSize = 0; for (item in contentsEnum) { expectedUmcompressedContentSize += [item uncompressedSize]; LOG(@"zip\tpath:%@\t%d", [item path], [item uncompressedSize]); } contentsEnum = [[unzipContainer contents] objectEnumerator]; for (item in contentsEnum) { NSString *path = [[NSFileManager defaultManager] suggestFilePath:[APPLICATION_DOC_DIR stringByAppendingPathComponent:[item path]]]; BOOL result = [item extractTo:path delegate:self]; if (!result) { NSString *err = [NSString stringWithFormat:NSLocalizedString(@"Failed to extract %@.", nil), [item path]]; UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"" message:err delegate:actionSheet cancelButtonTitle:nil otherButtonTitles:@"OK",nil]; [alert show]; [alert release]; } } } [unzipContainer release]; [pool release]; [self dismissActionSheet]; }
ダウンロード中の進行状況はURLDownloadDelegateで取得。
- (void)download:(URLDownload *)download didReceiveResponse:(NSURLResponse *)response { expectedContentLength = [response expectedContentLength]; } - (void)download:(URLDownload *)download didReceiveDataOfLength:(NSUInteger)length { progressBar.progress = progressBar.progress + ((long double)length / (long double)expectedContentLength) * 0.5f; LOG(@"Download: %f", progressBar.progress); }
解凍中の進行状況はHetimaUnZipItemDeletegateで取得。
- (void)item:(HetimaUnZipItem *)item didExtractDataOfLength:(NSUInteger)length { progressBar.progress = progressBar.progress + ((long double)length / (long double)expectedUmcompressedContentSize) * 0.5f; LOG(@"Extracting %f", progressBar.progress); }
終わったらdismissActionSheetを呼びだし、後始末。
UIActionSheetが非表示になった時にダウンロードに使ったURLDownloadをリリースしている。
- (void)dismissActionSheet { if (actionSheet) { [actionSheet dismissWithClickedButtonIndex:-1 animated:YES]; } } - (void)actionSheet:(UIActionSheet *)actionSheet didDismissWithButtonIndex:(NSInteger)buttonIndex { [self releaseDownloader]; } - (void)releaseDownloader { [downloaderLock lock]; if (downloader != nil) { [downloader release]; downloader = nil; } [[NSFileManager defaultManager] clearTmpDirectory]; [downloaderLock unlock]; }
途中キャンセルもできる。
// なぜかactionSheetCancelが呼ばれないので、こちらで代用 - (void)actionSheet:(UIActionSheet *)sheet clickedButtonAtIndex:(NSInteger)buttonIndex { if (buttonIndex == sheet.cancelButtonIndex) { [downloader cancel]; } }
窓使いの憂鬱の設定 for Parallels Desktop on Mac
Parallelsのバージョンが4.0になってから、キーボードのリマップをParallelsがするようになった。
が、あまりに使いづらいので窓使いの憂鬱に戻した。
前のバージョンのParallelsで使っていたときの設定に、commandキー(Windowsキー)とcontrolの入れかえを追加してある。
include "109.mayu" # 109 キーボード設定 keymap Global #(こうやって key U-変換 = ひらがな ひらがな #ひらがな key IL-U-変換 = ひらがな ひらがな #ひらがな(IME オン時) key IC-U-変換 = Return ひらがな ひらがな #ひらがな(IME オン時-変換中) key S-U-変換 = 半角/全角 ひらがな 無変換 #カタカナ key IL-S-U-変換 = ひらがな 無変換 #カタカナ(IME オン時) key IC-S-U-変換 = Return ひらがな 無変換 #カタカナ(IME オン時-変換中) key U-無変換 = 半角/全角 半角/全角 #英数 key IL-U-無変換 = 半角/全角 #英数(IME オン時) key IC-U-無変換 = Return 半角/全角 #英数(IME オン時-変換中) mod Windows -= LeftWindows mod control += LeftWindows mod control -= LeftControl mod Windows += LeftControl key *LeftControl = *LeftWindows key *LeftWindows = *LeftControl
さくらインターネットでSubversion
svn+sshで接続できるSubversionをさくらインターネットのサーバ上に構築した時のインストールログ。
環境
FreeBSD 6.1-RELEASE-p23
subversion-1.5.4
ログ
基本的にさくらインターネットでSubversion » サイキョウラインを参考にした。
%mkdir -p $HOME/local/src %cd local/src %wget http://subversion.tigris.org/downloads/subversion-1.5.4.tar.bz2 %tar jxf subversion-1.5.4.tar.bz2 %wget http://subversion.tigris.org/downloads/subversion-deps-1.5.4.tar.gz %tar zxf subversion-deps-1.5.4.tar.gz %cd subversion-1.5.4 %./configure --prefix=$HOME/local --without-serf %make all install clean %cd $HOME %mkdir -p svn/repos %$HOME/local/bin/svnadmin craete svn/repos
最後に、.cshrcでpathに$HOME/local/binを追加。
以上でsvn+sshで利用できるSubversionのレポジトリが出来た。
備考
最初、subversion-1.5.4.tar.bz2だけをダウンロードした状態で
%./configure --prefix=$HOME/local
とconfigureしたら、
configure: WARNING: APR not found The Apache Portable Runtime (APR) library cannot be found. Please install APR on this system and supply the appropriate --with-apr option to 'configure' or get it with SVN and put it in a subdirectory of this source: svn co \ http://svn.apache.org/repos/asf/apr/apr/branches/0.9.x \ apr Run that right here in the top level of the Subversion tree. Afterwards, run apr/buildconf in that subdirectory and then run configure again here. Whichever of the above you do, you probably need to do something similar for apr-util, either providing both --with-apr and --with-apr-util to 'configure', or getting both from SVN with: svn co \ http://svn.apache.org/repos/asf/apr/apr-util/branches/0.9.x \ apr-util configure: error: no suitable apr found
と怒られた。上記のメッセージではapacheからaprを取ってこいと言っているが、Subversionのサイト上にsubversion-deps-1.5.4.tar.gzというファイルがあったので落として解凍してみたら、必要そうなものがいろいろsubversion-1.5.4ディレクトリに追加された。
この状態でもう一度configureすると、今度は
configure: WARNING: we have configured without BDB filesystem support You don't seem to have Berkeley DB version 4.0.14 or newer installed and linked to APR-UTIL. We have created Makefiles which will build without the Berkeley DB back-end; your repositories will use FSFS as the default back-end. You can find the latest version of Berkeley DB here: http://www.oracle.com/technology/software/products/berkeley-db/index.html
というWARNINGが出た。
調べてみると、FSFSというのはSubversionに新しく追加されたFile Systemで、どうもBerkley DBをback-endにするよりよさげな感じ。なのでこのままmakeすることにした。
%make all install clean
今度は
/usr/lib/crt1.o(.text+0x72): In function `_start': : undefined reference to `main' *** Error code 1 Stop in /home/***/local/src/subversion-1.5.4/serf. *** Error code 1 Stop in /home/***/local/src/subversion-1.5.4.
というわけわからんエラーで止まる。調べてみてもぴったり当てはまる件がなかったが、似たような事例の中に1つ--without-serfをつけてconfigureするという解決策があった。serfというのは「The serf library is a C-based HTTP client library built upon the Apache Portable Runtime 」とのことなので、svn+sshで使おうとしている今回の場合はなくても問題なさそう。
ということで、試しに--without-serfを付けてconfigureし、make installすると、見事成功。
ソースからインストールしたことがなかったので、どこかおかしいところはあるかもしれないが、今のところ問題なく動いている。
MacBook Proのインストールログ
Application
- TaskPaper
- AppFresh
- Plaxo
- CSSEdit
- AppCleaner
- Snapz Pro X
- Pixelmator
- Firefox
- Thousand
- Twitterific
- Lingon
- GreasKit
- SIMBL
- MacPorts
- sudo port -d selfupdate
- sudo port -d sync
- sudo port install subversion
- sudo port install zsh
- TextMate
- GetBundles
- ProjectPlus
- groovy
- 日本語対応
- QuickSilver
- Xcode
- iPhone SDK
- Bitmemo
- AquaSKK
- Growl
- Poladroid
- Versions
- Changes
- SafariTabmement
- SafariTabConfig
- http://colloquy.info/index.html:title=Colloquy]
- Cyberduck
- HandBrake
- Adium
- VLC Media Player
- Perian
- Flip4Mac
- CotEditor
- KeyRemap4MacBook
- 見つからない
- YadeX
- Mouse Locator
- http://mail.google.com/mail/help/notifier/notifier_mac.html:title=Google Notifier for Mac]
- Skype
環境設定
- キーボード
- キーのリピート速度を最速
- リピート入力認識までの時間を最短
- トラックパッド
- タップでクリックをON
- ドラッグをON
- 副ボタンのクリックをON
- Dock
- Dockを自動的に隠すをON
- Terminal
- Safari
- Fontsをインストール
.bashrc
export PATH=/opt/local/bin:/opt/local/sbin:$PATH export MANPATH=/opt/local/man:$MANPATH
.zshrc.mine
export PATH=/opt/local/bin:/opt/local/sbin:$PATH export MANPATH=/opt/local/man:$MANPATH
.zshrc
http://journal.mycom.co.jp/column/zsh/010/index.htmlより拝借。
# users generic .zshrc file for zsh(1) ## Environment variable configuration # # LANG # export LANG=ja_JP.UTF-8 ## Default shell configuration # # set prompt # autoload colors colors case ${UID} in 0) PROMPT="%B%{${fg[red]}%}%/#%{${reset_color}%}%b " PROMPT2="%B%{${fg[red]}%}%_#%{${reset_color}%}%b " SPROMPT="%B%{${fg[red]}%}%r is correct? [n,y,a,e]:%{${reset_color}%}%b " [ -n "${REMOTEHOST}${SSH_CONNECTION}" ] && PROMPT="%{${fg[white]}%}${HOST%%.*} ${PROMPT}" ;; *) PROMPT="%{${fg[red]}%}%/%%%{${reset_color}%} " PROMPT2="%{${fg[red]}%}%_%%%{${reset_color}%} " SPROMPT="%{${fg[red]}%}%r is correct? [n,y,a,e]:%{${reset_color}%} " [ -n "${REMOTEHOST}${SSH_CONNECTION}" ] && PROMPT="%{${fg[white]}%}${HOST%%.*} ${PROMPT}" ;; esac # auto change directory # setopt auto_cd # auto directory pushd that you can get dirs list by cd -[tab] # setopt auto_pushd # command correct edition before each completion attempt # setopt correct # compacked complete list display # setopt list_packed # no remove postfix slash of command line # setopt noautoremoveslash # no beep sound when complete list displayed # setopt nolistbeep ## Keybind configuration # # emacs like keybind (e.x. Ctrl-a goes to head of a line and Ctrl-e goes # to end of it) # bindkey -e # historical backward/forward search with linehead string binded to ^P/^N # autoload history-search-end zle -N history-beginning-search-backward-end history-search-end zle -N history-beginning-search-forward-end history-search-end bindkey "^p" history-beginning-search-backward-end bindkey "^n" history-beginning-search-forward-end bindkey "\\ep" history-beginning-search-backward-end bindkey "\\en" history-beginning-search-forward-end ## Command history configuration # HISTFILE=~/.zsh_history HISTSIZE=10000 SAVEHIST=10000 setopt hist_ignore_dups # ignore duplication command history list setopt share_history # share command history data ## Completion configuration # autoload -U compinit compinit ## Alias configuration # # expand aliases before completing # setopt complete_aliases # aliased ls needs if file/dir completions work alias where="command -v" alias j="jobs -l" case "${OSTYPE}" in freebsd*|darwin*) alias ls="ls -G -w" ;; linux*) alias ls="ls --color" ;; esac alias la="ls -a" alias lf="ls -F" alias ll="ls -l" alias du="du -h" alias df="df -h" alias su="su -l" ## terminal configuration # unset LSCOLORS case "${TERM}" in xterm) export TERM=xterm-color ;; kterm) export TERM=kterm-color # set BackSpace control character stty erase ;; cons25) unset LANG export LSCOLORS=ExFxCxdxBxegedabagacad export LS_COLORS='di=01;34:ln=01;35:so=01;32:ex=01;31:bd=46;34:cd=43;34:su=41;30:sg=46;30:tw=42;30:ow=43;30' zstyle ':completion:*' list-colors \ 'di=;34;1' 'ln=;35;1' 'so=;32;1' 'ex=31;1' 'bd=46;34' 'cd=43;34' ;; esac # set terminal title including current directory # case "${TERM}" in kterm*|xterm*) precmd() { echo -ne "\033]0;${USER}@${HOST%%.*}:${PWD}\007" } export LSCOLORS=exfxcxdxbxegedabagacad export LS_COLORS='di=34:ln=35:so=32:pi=33:ex=31:bd=46;34:cd=43;34:su=41;30:sg=46;30:tw=42;30:ow=43;30' zstyle ':completion:*' list-colors \ 'di=34' 'ln=35' 'so=32' 'ex=31' 'bd=46;34' 'cd=43;34' ;; esac ## load user .zshrc configuration file # [ -f ~/.zshrc.mine ] && source ~/.zshrc.mine
UITextFieldでリターンキーが押された時にキーボードを隠す
iPhoneでUITextFieldを使う際、リターンキー押下時にキーボードを隠したいことがある。
そのような時は、UITextFieldの「Did End On Exit」をIBActionにバインドし、そのIBActionの中で、UITextFieldインスタンスのresignFirstResponderメソッドを呼んでやればよい。
//View.h @interface View : UIView { IBOutlet UITextField *textField; } - (IBAction)download: (id)sender; //View.m @implementation View - (IBAction) download: (id)sender { [textField resignFirstResponder]; // あとは自由に。 } @end