ラベル iOS8 の投稿を表示しています。 すべての投稿を表示
ラベル iOS8 の投稿を表示しています。 すべての投稿を表示

2014年10月5日日曜日

Xcode6ではStoryboardで指定するSegue名が変更されている

Storyboardで指定するSegue(セグエ)名

Xcode6ではSegue名が変更され、以前まで使用していたpush, modal等のSegueはDeprecated Segueとなり非推奨となってしまいました。互換性のために残されていると考えられるので、今後は新しいSegueを使用した方が良いでしょう。

新しいSegue(セグエ)名について
Segue(セグエ)名の対応表
Xcode5 Xcode6 機能概要
Push Show NavigationControllerのNavigationスタックにViewControllerを追加します。画面はアニメーションしながら次の画面(ViewController)を表示します。Navigation用の戻るボタンやエッジスワイプで元の画面に簡単に戻れます。
Model Present Modally 現在の画面(ViewController)の上に新しい画面(ViewController)を表示します。新しい画面はNaivationControllerでは管理されません。
Popover Present As Popover 主にiPadで吹き出しスタイルの表示を行います。
Replace Show Detail 主にiPadで現在表示している画面(ViewController)の差し替えを行います。iPadの設定アプリで項目の選択で右側ペインの画面さ差し替わっていくイメージです。
Accessory ActionのSegue(セグエ)について

今まであまり使ったことがなかったので、調べてみました。このAccessory Actionセグエはアクセサリアイコンが選択された時用のセグエになるようです。例えば、TableViewではセルのAccessoryを指定することが可能で、そのアクセサリが選択された場合とテーブルセル自体が選択された時を区別するためにセグエが別に定義されているようです。


AD.

2014年9月16日火曜日

UITableViewのセルの高さを動的に計算するSelf-Sizing Cellsを試してみた(iOS8, Swift)

はじめに
UITableviewCellの高さを動的に変更する実装はiOS7の頃(?)から可能で、iOS8では実装が簡略されてさらにパフォーマンスが高いよといったお話です。
どういう点が簡略化されたの?
iOS7では主に以下の実装が必要でした。
  1. AutoLayoutを有効にしてConstraintsを設定
  2. tableView:heightForRowAtIndexPath: メソッド実装によるセルの高さ計算
  3. tableView:cellForRowAtIndexPath: メソッド実装
iOS8の場合、 2番目の高さを計算する処理がまるっと省略可能で、おまじない程度の設定で済みます。
Constraintsの追加と設定(AutoLayout)
本例ではUITableViewControllerとして実装されたUITableVivew及びUITableViewCellのContentViewにLabelを一つ配置しています。 まずはLabelのConstraintsを追加していきます。

まずはUITableviewControllerの配置。
Cell上へラベルの配置。
Cell上のContentViewにLabelを一つ配置しています。
Constraintsを追加していきます。Labelの上下左右のマージンを設定します。
ラベルは複数行を許可するためLinesの値を0に設定しておく必要があります。
全体的な構成はこんな感じ。
UITableViewCellは独自のカスタムクラスを設定しておき、ラベルのアウトレットの作成をしておきます。
rowHeightの設定
tableViewのプロパティであるrowHeight及びestimatedRowHeightの設定を行います。 以下、UITableViewControllerの実装クラスです。
class TableViewController : UITableViewController {
    
    override func viewDidLoad() {
        //
        super.viewDidLoad()
        
        //initialize
        tableView.estimatedRowHeight = 60
        tableView.rowHeight = UITableViewAutomaticDimension
        
    }
    
    //MARK: implementation of uitableviewcontroller datasources
    override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
        return 1
    }
    
    override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return 5
    }
    
    override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
        //
        let cell = tableView.dequeueReusableCellWithIdentifier("cell", forIndexPath: indexPath) as CustomCell
        
        //dummy text
        var dummyString = "01234567890"
        for i in 0...indexPath.row {
            dummyString += dummyString
        }
        //set text
        cell.customLabel.text = "index : \(indexPath.row), dummyString : \(dummyString)"

        return cell
    }
}
おまじないはviewDidLoadメソッド内で実装している以下の箇所
tableView.estimatedRowHeight = 60
tableView.rowHeight = UITableViewAutomaticDimension
tableView.rowHeight = UITableViewAutomaticDimension
の設定が自動設定を表しています。estimateRowHeightは設定することでスクロール中のパフォーマンス向上につながるらしいです。
tableView:cellForRowAtIndexPath: メソッド実装
rowが増すごとに表示文字列を増やしているダミー処理がありますが、特に通常と変わった実装はありません。
    override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
        //
        let cell = tableView.dequeueReusableCellWithIdentifier("cell", forIndexPath: indexPath) as CustomCell
        
        //dummy text
        var dummyString = "01234567890"
        for i in 0...indexPath.row {
            dummyString += dummyString
        }
        //set text
        cell.customLabel.text = "index : \(indexPath.row), dummyString : \(dummyString)"

        return cell
    }
実装結果
実行イメージ。
もし、tableView.rowHeight = UITableViewAutomaticDimension の設定を行わないと以下のようになります。
コードの詳細はGitHubを参照して下さい。
https://github.com/takuran/SelfSizingCellExample
参考:What's New in Table and Collection Views(https://developer.apple.com/videos/wwdc/2014/)
※上記参考先リンクはiOS Developer 登録していないと参照出来ないかも。スミマセン。

2014年9月8日月曜日

Swift環境からObjective-Cで書かれたCocoaPodsを使用する
(SwiftでFMDBを使う)

Swift環境からObjective-Cで書かれたCocoaPodsのライブラリを利用してみる
ライブラリはFMDBを取り込んで、FMDBを使用した簡単なプログラムをSwiftを用いて作成します。
空プロジェクトの作成
まずは、空プロジェクトを作成し、そしてすぐに閉じます。CocoaPodsでFMDBを取り込むプロジェクトファイルだけを前もって作成します。

※因みに本サンプルはXcode6 beta7にて作成しています。
podfileの作成とインストール
podfileの内容を以下のようにして作成したプロジェクトの直下に作成し、
pod 'FMDB'
以下コマンドを実行してインストールを実行。
% pod install
インストールしたら、作成されたワークスペース(プロジェクトファイルじゃないです)を開きます。 下記の様にコマンドラインから起動しても良いですし、FinderからXXX.xcworkspaceファイルをダブルクリックしても良いです。
% open XXX.xcworkspace
ワークスペースを起動したら、以下のようにPodsプロジェクトが作成されていることを確認して下さい。
※CocoaPodsは既にインストール済みを前提とします。CocoaPodsのインストールやそのた詳細についてはCOCOAPODSを参照。

Bridging Headerの作成
Objective-CをSwift環境から利用するにはBridging Headerを作成する必要があります。
このヘッダにSwift環境で使用するObjective-Cのヘッダファイルを記載することになります。
Bridging-Headerは、
1)仮のObjective-Cのファイルを作成することで自動作成、自動設定する方法(自動生成)
2)個別に作成し設定する方法(独自作成)
があります。
Bridging Headerを自動生成する場合は
Objective-Cのファイルを生成します。 Xcode menu > File > New > File... を選択しファイル新規作成します。 以下の様に、Objective-C Fileを選択しNextを押下。
ファイル名は後ほど削除するので、何でも良いです。
すると、以下の様に bridging header を作成するか問われるのでYESを押下します。
以下の様に bridging headerが作成されます。
以上で完了です。後はObjective-Cのヘッダファイルをbridging headerに記載するのみです。 FMDBの場合は以下のようにすれば良いでしょう。
//
//  Use this file to import your target's public headers that you would like to expose to Swift.
//
#import "FMDatabase.h"
作成したdummy.mファイルは削除して構いません。
Bridging Headerを独自に作成、設定する場合は
まずはbridging headerを作成します。 ファイル名はなんでも良いですが、bridging headerと分かるようにしましょう。
作成したら、BuildSettingを変更します。作成したプロジェクトを選択して、Swift Conpiler - Code Generation の設定項目値の Objective-C Bridging Header の項目を編集します。
ヘッダの内容は自動設定の時と同じです。自前でヘッダを作成すると#ifdef/#endifが自動挿入されますが、特に削除して問題無いでしょう。(自動作成時に存在しなかったので)
//  Bridging-Header.h
//  UsingCocoaPodsInSwift
//
#import "FMDatabase.h"

以上で、準備は終わりです。
SwiftからFMDBのメソッド呼び出し
あとはSwiftでコードが書いていくだけです。FMDBが提供しているメソッドの呼び出しはSwift言語仕様に変換されて呼び出すことになりますが、Xcodeのコード補完の機能があるので、メソッド名さえ分かっていればそれほど難しくはないでしょう。
抜粋しますが、FMDBに関するメソッドとして、初期化と更新クエリの呼び出し箇所を載せておきます。詳細は後述するGitHub上のソースコードを参照下さい。

FMDBインスタンス生成
        m_db = FMDatabase(path:m_dbPath)
トランザクションを開始してインサート処理
    func createNewContent(content:String) -> Bool {
        if m_db.goodConnection() {
            m_db.beginTransaction()
            m_db.executeUpdate("insert into memo (contents, 'update') values (?, ?)", withArgumentsInArray: [content, NSDate()])
            m_db.commit()
            //OK
            return true
        }
        //FAIL, database not opend.
        return false;
    }
詳細はGitHubに上げていますので、適宜参照して下さい。
https://github.com/takuran/UsingCocoaPodsInSwift
以下画面サンプル。