2011年1月15日土曜日

XcodeでMacRuby・5日目 Document Base

というわけで5日目は木下誠氏のcocoa中級セミナーに挑戦。(リンクは直接ダウンロードに行っちゃうのでご注意を)

わ、いきなりRSSリーダーですか。大丈夫かなあ。と不安を抱えつつ作業をしてみる。今回は「Document Base」のアプリケーション。うむ、勉強のいい機会だ。

まずはプロジェクトを作る。

この段階で自動生成される「MyDocument.rb」の中身はこうなっている。
class MyDocument < NSDocument
 
 # Name of nib containing document window
 def windowNibName
  'MyDocument'
 end
 
 # Document data representation for saving (return NSData)
 def dataOfType(type, error:outError)
  outError.assign(NSError.errorWithDomain(NSOSStatusErrorDomain, code:-4, userInfo:nil))
  nil
 end

 # Read document from data (return non-nil on success)
 def readFromData(data, ofType:type, error:outError)
  outError.assign(NSError.errorWithDomain(NSOSStatusErrorDomain, code:-4, userInfo:nil))
  nil
 end

 # Return lowercase 'untitled', to comply with HIG
 def displayName
  fileURL ? super : super.sub(/^[[:upper:]]/) {|s| s.downcase}
 end

end

昨日はこのファイルを見ただけでorzってなったんですが、これに書き加えながら勉強、と。 まず読み込めるファイルの種類を設定する、と。「ターゲット」からやればいいんですね。知らなかった。昨日はinfo.plistを直接いじってみたのでした。(^^;)
この規模のIDEとなると、やっぱり闇雲な猿いぢりだけではダメですね。ちゃんと1冊本を買うほうがいいか・・・。 それから「attr_accessor :textView」だけMyDocument.rbに記述しておいてOutletをつなぐ。
MyDocument.rbをセーブしないでこの作業をしようとしたら、どうしてもTextViewに行き着かず悩みました。 さてここから、いよいよコーディング。本日は実質、次の関数を書き換えて終わりました。
- (void)windowControllerDidLoadNib:(NSWindowController *) aController 
    [super windowControllerDidLoadNib:aController];
 // 書類のURLを取得します
 NSURL* fileURL; fileURL = [self fileURL]; if (!fileURL) {
  return;
 }
 // テキストファイルを読み込みます
 NSData* data; NSString* string; 
    data = [NSData dataWithContentsOfURL:fileURL]; 
        string = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
        if (!string) {
  return;
 }
 // テキストビューにテキストを設定します 
 [textView setString:string];
dataOfType、readFromData、windowControllerDidLoadNibといった関数がどんな働きをするのか調べるところから始まるので、時間がかかりますねー。Document Baseのアプリがどのようにデータをもらって起動するか、といった辺りの説明はちょいとググれば山ほどの記述に行き当たります。みなさん同じことを苦労して調べてるのね。それをちゃんと書き残してくれるから、私のような「遅れてきた」人間もなんとか頑張れるんだなあ。 とりあえず
def readFromData(data, ofType:type, error:outError)
    outError.assign(NSError.errorWithDomain(NSOSStatusErrorDomain, code:-4, userInfo:nil))
    true
end
この関数のnilがあるとどんなドキュメントも読み込んでくれないので適当に「true」としておいたけど大丈夫だろうか。いや大丈夫みたいなんですけどね。 一番困ったのが
string = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
この部分。ググったりXcode付属のドキュメントを探したりいろいろしましたが、どうやって書くのかわからない。もうやめようか、と思うくらい。 NSStringで「string」を初期化して、initWithDataで「data」を文字列化したものを渡す、という処理だというのはわかるんだけどMacRubyでどう書いたらいいか、そんなのどこにも書いてませんわねえ。 ところが
MacRuby: The Definitive Guide
にはちゃんと書いてありましたよ。(MacRubyの作者の一人が書きかけの本を公開してるものです)第5章「Foundation」の「Data」にちゃんとこう書いてある。
NSString.alloc.initWithData(data, encoding:NSUTF8StringEncoding) # => "Some classes gets initiated using data, (i.e NSXMLDocument)"
そうか、NSString.alloc.って書いていくのか。 というわけで現在のところのMyDocument.rbはこんな感じです。
class MyDocument < NSDocument
attr_accessor :textView
 # Name of nib containing document window
 def windowNibName
  'MyDocument'
 end
 
 # Document data representation for saving (return NSData)
 def dataOfType(type, error:outError)
  #outError.assign(NSError.errorWithDomain(NSOSStatusErrorDomain, code:-4, userInfo:nil))
  #nil
  str=textView.string
  data=str.dataUsingEncoding(NSUTF8StringEncoding)
  data
 end

 # Read document from data (return non-nil on success)
 def readFromData(data, ofType:type, error:outError)
  outError.assign(NSError.errorWithDomain(NSOSStatusErrorDomain, code:-4, userInfo:nil))
  true
 end

 # Return lowercase 'untitled', to comply with HIG
 def displayName
  fileURL ? super : super.sub(/^[[:upper:]]/) {|s| s.downcase}
 end
 def windowControllerDidLoadNib(aController)
  super
  fileURL ? super : return
  
  data=NSData.dataWithContentsOfURL(fileURL)
  str=NSString.alloc.initWithData(data, encoding:NSUTF8StringEncoding)
  return unless str 
  textView.setString(str)
 end

end

中級セミナーの資料は40ページほどなんですが、ここまで10ページ。さすがに先が長いなあ。

ど下手なコードでも、一応人目にさらすことを考えると一生懸命勉強して、少しでも「ruby」っぽくなるよう努力できるものですね。そんなわけで、これを書きながら、私は「ruby」と「cocoa」、両方の学習をできていて幸せ。

0 件のコメント:

コメントを投稿