FC2ブログ

【swift】テキストファイルの配列への読み込み【cocoa】


未だに swift1.1 を使っている人がいるとも思えまないので、ブログで公開したところで誰かの役に立つとは思えませんが、備忘録ってことで。

やろうとしたことは、

1. 改行区切りのテキストファイルを読み込み
2. 1行づつ配列に格納する
3. 格納された配列を整数型に変換

これだけ。
あとは例のごとく整数型に変換したデータを使ってゴチョゴチョやるって感じ。

ファイル・オープンについては 過去記事を参照

オープンパネルからファイル・パスを引っ張ってきたら、

 let file = String(contentsOfFile: path, encoding: NSUTF8StringEncoding, error: nil)



こんな感じでファイルを読み込み。
ここで、NSString で読んでないことに注意してください。

で、次に改行区切りでのファイルの分割なんですが、String.componetsSeparatedByString("\n") を使って大ハマり。
ここは素直に String.enumerateLines を使って、

 var strArray = [String]()
 file?.enumerateLines { (line, stop) -> () in
  strArray.append(line )
 }


こんな感じに。
このために file の読み込みに NSString ではなく、String を使っています。

最後に String を Int に変換。

 var intVal0 = strArray[1].toInt()
 var intVal1 = strArray[2].toInt()
 var intVal2 = strArray[3].toInt()



まぁ、分かっている人にはなんてことないことでしょうが、ワタクシのような素人があっちゃこっちゃのサイトを参考にしてフランケン・コードを書いていると、整合性が取れずにエラーが頻発するのですよ。

スポンサーサイト



【swift】 NSTableView で文字色変更 【cocoa】


こちらの記事 でテーブル・ビューにテキストを表示できたのですが、書式(というか文字色を)変えたくなって調べたところ、ネット検索して引っ掛かる内容がワタシの環境では使えないものが多かったので備忘録。

検索結果の中で、簡単に実装できそうだったのが、

 func tableView(tableView: NSTableView, willDisplayCell cell: (id)cell, forTableColumn tableColumn: NSTableColumn?, row: Int)

を使って、cell.setTextColor(NSColor.blackColor()) とかやる方法。

しかし、これ、wilDisplayCell が AnyObject になってて使えない。

しょうがないので、面倒臭そうだけど、NSAttributedString を使うことに。
というわけで、前回のコードを改造。

 func tableView(tableView: NSTableView!, objectValueForTableColumn tableColumn: NSTableColumn!, row: Int) -> AnyObject!
 {
 // var string:String = "row " + String(row) + ", Col" + String(tableColumn.identifier) 
 // return string
  var newString = getDataArray().objectAtIndex(row).objectForKey(tableColumn.identifier) as? NSAttributedString //String から変更して、NSAttributedString を表示させるようにする
  println(newString)
  return newString;
 }



で、こちらも NSAttributedString を使えるように変更。

func getDataArray () -> NSArray {

  // 設定したいアトリビュート 文字色を赤に
  let attr = [ NSForegroundColorAttributeName: NSColor.redColoe() ]

  //NSAttribtedString(string: String, attributed: attributed) を使ってアトリビュートを指定
  var dataArray: [Dictionary] = [["FirstName": NSAttributedString(string: "Debasis", attributes: attr),
    "LastName": NSAttributedString(string: "Das", attributes: attr)],
    ["FirstName": NSAttributedString("Nishant", attributes: attr),
    "LastName": NSAttributedString(string: "Singh", attributes: attr)],
    ["FirstName": NSAttributedString(string: "John", attributes: attr),
    "LastName": NSAttributedString(string: "Doe", attributes: attr)],
    ["FirstName": NSAttributedString(string: "Jane", attributes: attr),
    "LastName": NSAttributedString(string: "Doe", attributes: attr)],
    ["FirstName": NSAttributedString(string: "Mary", attributes: attr),
    "LastName": NSAttributedString(string: "Jane", attributes: attr)]];

  println(dataArray);
  return dataArray as NSArray;  // as NSArray を追加
 }



これを使うと、アラインやフォントもデフォルト設定(IBなどで設定した値ではない)になってしまうみたいなので、デフォルト以外の設定を使いたい場合は一緒に設定してやると良いかと。

こんな感じでできました。

とはいえ、ワタシの環境も古いので、最新版の開発環境では、もっとシンプルに実装できるのかもしれない。

【swift】TableView 【cocoa】


MacOS で TableView を使った小物のアプリを作ったのですが、思いのほか手間取ったので備忘録。

こちらのサイトのサンプル を参考にしたのですが、このままでは動かなかったので、手直ししたところだけ。

 func applicationDidFinishLaunching(aNotification: NSNotification) {
  // Insert code here to initialize your application
  myTableView.setDelegate(self)
  myTableView.setDataSource(self)
  myTableView.reloadData()  //一応
 }

明示的にデリゲートとデータソースを設定してやんなきゃダメみたい。
myTableView.Delegate = self 的な書き方を良く見かけたけど、ワタシの環境が古いからかエラーに。

 func tableView(tableView: NSTableView!, objectValueForTableColumn tableColumn: NSTableColumn!, row: Int) -> AnyObject!
 {
 // var string:String = "row " + String(row) + ", Col" + String(tableColumn.identifier) 
 // return string
  var newString = getDataArray().objectAtIndex(row).objectForKey(tableColumn.identifier) as? String //as? String を追加
  println(newString)
  return newString;
 }

こちらも as? String と明示的に指定してやらないとダメでした。

 func getDataArray () -> NSArray {
  var dataArray: [Dictionary] = [["FirstName": "Debasis", "LastName": "Das"],
    ["FirstName": "Nishant", "LastName": "Singh"],
    ["FirstName": "John", "LastName": "Doe"],
    ["FirstName": "Jane", "LastName": "Doe"],
    ["FirstName": "Mary", "LastName": "Jane"]];

  println(dataArray);
  return dataArray as NSArray;  // as NSArray を追加
 }

こちらも戻り値を NSArray に明示的にキャストしないとエラーに。

他に注意点としては、IB で TableView を cell based にしてやることと、column の ID を dataArray の key と同じ にしてやることですかね。

一画面しか使わない小物アプリだと、わざわざ viewController を追加するのも面倒なので、まぁ、こんな感じで良いかと。

しかし、なんで自分で拡張しなくちゃならんのか。
柔軟性重視なのかな。
指定のフォーマットで Dictionary なり Array を作って、引数として渡せば、表示してくれる物かと思ったなり。

【swift】アプリアイコンにドラッグ&ドロップしてアプリを起動【cocoa】


Xcode で Mac(cocoa) アプリの作り方を勉強しているのですが、表題についての解説が少なかったので備忘録。
つーか、基本過ぎて解説するまでもなかったのだろうか?

まず、アプリのプロジェクトを選択して、Info を編集します。
Document Types を開いて「+」を押すと、受け付けるファイルタイプを追加できます。

Name : 適当に分かりやすい名前をつけます。
Class : 使わなければ空欄でOK。
Extensions : 受け付けるファイルの拡張子を指定。複数ある場合は、カンマ「,」で列記できるようです。
Icon : 空欄でOK。
Identifier : 空欄でOK。
Role : 良く分かってないのですが、None にすると無処理になってしまうみたいなので、Editor か Viewer で。
Mime Types : 空欄でOK。
Bundle : これも良く分からないのですが、デフォルトにしておけば良いような気がしますが、複数ファイルを受け付けなければチェックを外しておいたほうが良いかも知れないです。


以上で設定は終了。
で、AppDelegate.swift に以下のコードを追加。


  func application(sender: NSApplication, openFile filename: String) -> Bool {
    //ドラッグ&ドロップでファイルを受け付けたときに行いたい処理
  }



以上で、アプリアイコンにドラッグ&ドロップしてアプリが起動するハズ。
ちなみに、ドラッグ&ドロップでアプリを起動しても、当然ながら func applicationDidFinishLaunchong~ を処理します。


この動作をデバッガで検証する方法が分からなかったので、.app 化(リリース・ビルド?)してみたので、その手順もついでに。

Product メニューから Archive を選択。
新しいウィンドウが開くので、そこの右上の Export... ボタンを押して、エクスポートしたいファイル形式を選択。
保存先を選択して OK ボタンを押す。


以上で .app 書き出されます。

【Swift】 Thread1:EXC_BAD_INSTRUCTION【エラー】


さっきまで動いていたのに急に「Thread 1: EXC_BAD_INSTRUCTION (code = EXC_I386_INVOP, subcode = 0x0)」とか言われてビルドできなくなる・・・。

検索してみると、ありえない計算してたりすると出るらしい。
UInt でオーバーフローおこしてマイナス値になったり、0で割ったり。

Xcodeさんが指し示す行を見てみると

var i: Int = nn
 ・
 ・
 ・
i--    <- ココ

特に計算できないようなことも無さそうだけど。

で、ワケが分からないので、コメントアウトしてみたら、その上の行でエラー。
で、そこもコメントアウトしたら、その上でエラー・・・。

ムキー! と、ガシガシ、コメントアウトしてはビルド、コメントアウトしてはビルドしていったら、確かにありました、不定値で割り算しているところ。
で、そこを直したら、エラーが取れました。
いや、なんでその行を指してくれないの?

1日半くらい潰れたような気がする・・・。

Xcode が古いからかなぁ。

その後も同じエラーが出たんだけど、どうも一回はビルドが通るような気がするんだよなぁ。
で、1回は実行できるんだけど、次にエラーが出るような気がする・・・。
気のせいだろうか。