Swiftで正規表現を使って文字列を置き換える

カテゴリー:  Tech  タグ:  osx programming swift xcode

Stringを使うと簡単に正規表現での文字列置換が可能になります。

String.stringByReplacingOccurrencesOfString(target, withString, options, range)を使用します。ここで、optionsにNSStringCompareOptions.RegularExpressionSearchを指定することで正規表現が有効となります。

以下の例は、sourceに入った文字列の前後の空白と削除し文字列の空白を1つにまとめるための処理が書かれています。

var destination : String = source.stringByReplacingOccurrencesOfString("^ +| +$", withString:"", options:NSStringCompareOptions.RegularExpressionSearch, range: nil)

destination = destination.stringByReplacingOccurrencesOfString(" +", withString: " ", options: NSStringCompareOptions.RegularExpressionSearch, range: nil)
println("[\(destination)]")

その他、NSStringCompareOptionsはその他に以下のようなオプションがあります。

  1. NSLiteralSearch(正確な一致)

  2. NSCaseInsensitiveSearch(大文字小文字を無視)

面倒になったので詳しくはAPI Documentを

UIの更新をマルチスレッドで行う

カテゴリー:  Tech  タグ:  osx programming swift xcode

dispatch処理する関数

GDCを使うとそもそもマルチスレッドの処理も簡単に記述できるのですが、読みやすいプログラムにするために以下のようなメソッドを用意しておきます。UIの更新を非同期にしたいとかなら十分。

func dispatch_async_main(block: () -> ()) {
    dispatch_async(dispatch_get_main_queue(), block)
}

func dispatch_async_global(block: () -> ()) {
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), block)

マルチスレッド処理の記述

上記の関数を利用してバックグランドとメインのUIの更新処理をそれぞれのブロックに記述します。

dispatch_async_global {
          // Background operations
          // 通信など時間がかかる処理

          // Mainと同期する
          self.dispatch_async_main {
              // UIの更新などメインスレッドで同期させたい処理
          }

Swiftでの文字列の長さの数え方

カテゴリー:  Tech  タグ:  osx programming swift xcode

Swiftになって NSString と Stringが混在する状況になり自分でも混乱したので整理します。

  1. ~~countElementsというグローバルメソッドが用意されているので、これを使うのがてっとり早いでしょう~~。

  2. ~~UTF-16 表現での16ビットコード単位に基づいた utf16Countもある~~

Swift 1.2では上記の2つの方法はサポートされなくなり、グローバルメソッドのcount()に集約されました。

Swiftでは、絵文字をサポートもあり、文字によって異なるメモリ容量を持っています。よって文字列の長さを得るには、単にメモリ上のサイズを返すだけではダメで文字列の各文字を全てチェックする必要があります。あまり効率がよろしくないかもしれません。

var string1 : String = "abcdefg"
var lengh1OfString1 = countElements(string1) //Swift 1.2 ではサポートされない
var length2OfString1 = string1.utf16Count //Swift 1.2 ではサポートされない
var length3OfString1 = count(string1)
var length4OfString1 = count(string1.utf16)

SwiftでのSingletonパターン

カテゴリー:  Tech  タグ:  osx programming swift xcode

ちょっと必要そうだったので、SwiftでのSingletonパターンの実装方法を調べてみました。

いくつか実装パターンがあるようですが、一番安心そうなのが以下のパターンです。クラスにStatic変数を持てないので、structをネストして利用しています。

//Singleton.swift
class Singleton : NSObject {
    class var sharedInstance : Singleton {
        struct Static {
            static let instance : Singleton = Singleton()
        }
        return Static.instance
    }
    var message : NSString?
    private override init() {
        message = "Hello World"
    }
}

StoryBoardからTableViewを使う

カテゴリー:  Tech  タグ:  osx programming swift xcode

StoryBoardを使った場合のTableViewの設定がわからなかったので、作ってみました。

いくつか方法があるようですが、XCodeが作ってくれるテンプレートベースで一番うまくいったやり方です。

データ用にクラスを用意する

必須ではありませんが、今回は曲のデータとして曲名と曲の長さを持つようなクラスをTableViewに表示したいと思います。

// Song.swift
class Song: NSObject {
    var title : String = "A Song"
    var duration : NSTimeInterval = 0.0

}

extension Song {

    func durationString() -> String {
        return NSString(format:"%i:%02i",Int(self.duration) / 60, Int(self.duration) % 60)
    }
}

TableViewを作る

StoryBoard上にTableViewをおきます。

StoryBoard

StoryBoard

以下の手順で設定します。

  1. 1列目の名前をTitle、2列目のタイトルをDurationにします。

  2. Identity Inspectorで、1列目のIdentifierをTitle、2列目のIdentifierをDurationに設定します。いくつかのコンポーネントから構成されていますから、Outlineで間違えないように選んでください。

  3. OutlineでTable Viewを選択して、Attribute Inspectorを開いて、Content ModeをCell Basedにします。

  4. TableViewを選択したまま、Connections Inspectorを開いて dataSourceとdelegateとViewControllerを接続します。

  5. StoryBoard上のTable Viewをコードエディタ上のViewControllerにドラッグして、NSTableViewのOutletを作成します。

TableView用の実装コード

NSTableViewのために2つのメソッドをViewController上に実装する必要があります。

//ViewController.swift
var songs : [Song] = []
func numberOfRowsInTableView(aTableView: NSTableView) -> Int
{
    return songs.count
}

numberOfRowsInTableView()では、songsにSongクラスの配列が格納されている前提でその数を返しています。

// ViewController.swift
func tableView(aTableView: NSTableView,
    objectValueForTableColumn aTableColumn: NSTableColumn?,
    row rowIndex: Int) -> AnyObject?
{
    let titleOfSong = songs[rowIndex].title as NSString
    let durationOfSong = songs[rowIndex].durationString()
    let columnName = aTableColumn?.identifier

    if columnName == "Title" {
        return titleOfSong
    }
    else if columnName == "Duration" {
        return durationOfSong
    }
    return ""
}

まず、各行と対応する配列内のSongオブジェクトを取り出しています。 次に渡ってきたTableColumn.identifierを元にどの列をデータが求められているか判断し、曲名と曲の時間を返すようにしています。

//ViewController.swift
func tableViewSelectionDidChange(aNotification: NSNotification)
{
    let row = tableView.selectedRow
    if row >= 0
    {
        let selected = songs[row].title as String
        NSLog("Selected: \(selected)")
    }
}

どうせならTableView上のカーソルの位置に従って曲を選択したアクションをしたいので、tablViewSelectionDidChange()を実装しました。コード例ではログに書き出しているだけですが。

GitHub : yostos/TableView

(2014-12-20追記) データを追加した後、表示を反映させるためには NSTableView.reloadData() を投げてやる必要があります。

2つのウィンドウを持つOS Xアプリ

カテゴリー:  Tech  タグ:  osx programming swift xcode

2つのウィンドウを持つ場合のStoryboardの使い方がわからなかったのでまとめてみました。

2つ目のViewControllerを用意する。

メインウィンドウにあるボタンを押すと、2つ目のウィンドウが現れるようなアプリケーションを作ってみます。

StoryBoardを開いて、2つ目のViewControllerを作ります。WindowControllerでないとところが注意店です。

StoryBoard

StoryBoard

ここでは「Push Me」ボタンのアクションを受けるので、ボタンのactionから2つ目のViewControllerをつなぎ、Modalを選択します。ここでSheetやPopoverを選択すると現れ方が変わります。

2つ目のViewにはラベルと閉じるためのボタンを配置しておきます。

View間を受け渡すオブジェクトを作る。

View間でデータを受け渡したいのですが、お互いに参照を持っていないので困りました。

「Push Me」ボタンを押して、Modalで2つ目のViewを開く時 prepareForSegue()が動き、ここで参照が渡ってくるのでこの参照を利用します。以下のようにprepareForSegueをオーバーライドし、segueのdestinationControllerをキャストしてSecondViewControllerの参照を取得します。

今回はMessageというクラスを作ったので、このオブジェクトのrepresentaedObjectとしてセットします。

//ViewController.swift

override func prepareForSegue(segue: NSStoryboardSegue, sender: AnyObject?) {
    let secondViewController = segue.destinationController as SecondViewController
    secondViewController.representedObject = aMessage
}

ViewControllerクラスを作る。

次に2つ目のViewControllerに対応するNSViewControllerから派生したクラスを作ります。 init()のオーバーライドは必要そうなんで追加しました。StoryBoardのIdentify Inspectorで

まず、2つ目のViewを閉じた時のアクションを追加します。 StoryBoardのCloseボタンから SecondViewControllerのコードエディタにドラッグして@IBAction を作ります。ここではdismiss()としています。

// SecondViewController

required init?(coder: (NSCoder!)) {
    super.init(coder: coder)
}

@IBAction func dismiss(sender: AnyObject) {
    self.dismissController(self)
}

次にラベル用のOutletを作ります。StoryboardからコードエディタにLabelをドラッグします。 そして、representedObjectで渡ってきたMessageオブジェクトからテキストをセットします。セットするのはViewが開かれる際に呼び出されるviewWillAppear()をオーバーライドします。

// SecondViewController.swift

@IBOutlet weak var aLabel: NSTextField!

override func viewWillAppear() {
    let aMessage = self.representedObject as Message
    aLabel.stringValue = aMessage.message
}

GitHub: yostos/TwoWindows

Totes Automatic Open & Close Titanium

カテゴリー:  Gadget  タグ:  umbrella

以前使用していた折りたたみ傘 Knirps Fiber T3 Duomatic 折りたたみ傘 Pinstripe (Black) 【日本正規品】 KNF886-410 をどこかに忘れてきてしまったので、 totes AUTOMATIC OPEN & CLOSE TITANIUM W80 0A254Jを購入しました。以前、Reinforce と呼んでいた製品の後継ですね。

作り的には Knirpsとほぼ同じで開閉ボタンで一発で開いて閉じることができます(閉じるときは中棒は縮まない)。完全に閉じるときは少し力を入れて中棒を縮める必要がありますが、この力加減がKnirpsより軽く片手でも大丈夫です。ただ、Knirps T3のほうは途中で手を離してしまった時に開いてしまわないよう安全装置がありましたが、この点は心配です。

Knirps T3と比べると50gほどしか違いませんが、持ってみると圧倒的に軽いです。T3のほうが大きいこともありますが、受け骨がチタニウムでできてることもあるかもしれません。開いたときのサイズはほぼ同じで直径90cm強です。折りたたみ傘としては十分です。

その他の美点として、Knirps は防水加工が今ひとつでしたが、Totesのほうは内側と外側にシリコンとアクリルで防水加工がしてあります。これによって閉じた時の水のキレが非常によいです。しっかりとした防水ケースもついているので安心です。

また、傘のベルトが幅7cmもあり、巻き取りも楽だし巻いた時の形もしっかりしています。

Knirpsはドイツ製で作りもしっかりしていて所持している満足感は高かったのですが、Totesのほうは実用性という点で満足出来る製品でした。しかも価格的にはKnirpsの半額です。

今度は無くさないように大事にしたいと思います。

PRO GUARD CRYSTAL GLASS

カテゴリー:  Gadget  タグ:  iphone

ずっと パワーサポート アンチグレアフィルム for iPhone5S/5C/5 PJK-02を使ってきましたが、所持の時に何か油をこぼしてしまったらしく中央部が溶けたようになってしまったので買い替えました。

指紋が付くのがいやでずっとアンチグレアを使ってきましたが、今回はクリスタルな強化ガラスにしてみました。

日本製で製品の品質はとても高いです。思っていた以上に指紋に対する耐性があり、ほとんど指紋が目立ちません。撥油性も高いので、少し汚れてもサッと一拭きすれば綺麗になります。耐傷性は試してないのでわかりませんが、0.3mmと厚くはないけれど薄すぎない厚さは安心感があります。ラウンド加工されているので、厚さ自体は操作の上では全く気になりません。

しかも、 パワーサポート アンチグレアフィルム for iPhone5S/5C/5 PJK-02より安価です。さすがにamazonでの評価が高いだけあります。耐久性が弱いようなコメントもあるようですが、この値段であれば数ヶ月持つのであれば十分かなとおもいます。

高まるぅ

カテゴリー:  Automotive  タグ:  subaru wrx

車買っちゃう?

カテゴリー:  Automotive  タグ:  subaru

保険で所有権譲渡の手続きもあり、ディーラーへ行ってきました。

ついで買い替えの話。 なんと今日からキャンペーン。

買っちゃう?

キャンペーンのチラシ