Learn Swift / viva Cocoa / viva Cocoa


Learn Swift / 第18章  ドキュメント・ベースド・アプリケーション


このコーナーでは、Swift による、Mac OS X アプリケーションの作成方法を、説明しています。

2016年1月22日

home  目次  前へ  次へ  mail


ドキュメント・ベースド・アプリケーション

 ドキュメント・ベースド・アプリケーションは、複数のドキュメントウィンドウを、開くことのできるアプリケーションです。

 ドキュメントウィンドウとは、そのアプリケーションのメインウィンドウのことです。現在では、アプリケーションのウィンドウは、一つにまとめられるようになりました。昔は、メインウィンドウ以外に、メインウィンドウを補助するための、パネルと呼ばれまるウィンドウを、いくつか表示していました。ドキュメントウィンドウという呼び方は、その時の名残です。

 Safari や、テキストエディットは、いくつものウィンドウを開くことができます。この仕組みを作るのが、ドキュメント・ベースド・アプリケーションです。


Webs プロジェクト

 Xcode を起動して、Cocoa アプリケーションのプロジェクトを作ります。Product Name を、「Webs」にしてください。チェックボックスは、次の図のように、「Use Storyboards」と「Create Document-Based Application」にチェックを入れます。その他のチェックは、すべて外してください。

 プロジェクトが開きましたら、実行ボタンをクリックしてください。Webs アプリケーションが起動して、次のようなウィンドウが表示されます。「File」メニューの「New」を選択すると、いくつでもウィンドウが開きます。


コンテンツの作成

 今回は、ウィンドウに表示される、コンテンツを、第17章で作成した、「Web ブラウザ」にします。

 Main.stroryboard を開いて、「Your document contents here」という、Text Field を削除してください。そして、 第17章  Web ブラウザ を参考にして、Web ブラウザを作り込んでください。

   WebKit フレームワークの追加とインポート、App Transport Security の設定も忘れずに!


新規ウィンドウをずらして表示させる

 新規ウィンドウを開いても、前のウィンドウと同じ位置に表示されます。これを、ずらして表示させるようにします。

 次のリストのように、ViewControler.swift に、新しいプロパティを追加してください。

・・・
class ViewController: NSViewController {
    var url = "https://www.apple.com/jp/"
    static var offset = -1
    @IBOutlet weak var web: WebView!
・・・
static var offset = -1

 プロパティに static キーワードをつけることによって、そのプロパティは、クラスのプロパティになります。

 通常のプロパティは、インスタンスプロパティと呼ばれ、インスタンスが、作成されるたびに、新しいプロパティが作られます。つまり、ウィンドウ一つ一つに、インスタンスプロパティが作られることになります。

 一方、クラスプロパティは、クラスに一つしか存在しません。クラスのインスタンス、つまりウィンドウが、いくつ作られても、クラスプロパティは、一つだけです。

 次に、viewDidLoad メソッドに、コードを追加します。次のリストの太字部分が追加するコードです。

    override func viewDidLoad() {
        super.viewDidLoad()
        
        ViewController.offset += 1
        loadWeb()
    }
ViewController.offset += 1

 先ほど定義した、クラスプロパティ offset を呼び出すには、クラス名.プロパティ名と記述します。ここでは、クラスプロパティ offset の値を一つ増やしています。つまり、ビュー (ウィンドウ) が、作られるたびに、値が、一つ増えることになります。

 続けて、ViewWillAppear というメソッドを定義します。

    override func viewDidLoad() {
        super.viewDidLoad()
        
        ViewController.offset += 1
        loadWeb()
    }
    
    override func viewWillAppear() {
        var originX = view.window?.frame.origin.x
        let originY = view.window?.frame.origin.y
        originX! += CGFloat(ViewController.offset) * 30
        view.window?.setFrameOrigin(CGPointMake(originX!, originY!))
    }
override func viewWillAppear() {

 viewWillAppar は、ビュー (ウィンドウ) が、表示される直前に、呼び出されるメソッドです。

var originX = view.window?.frame.origin.x

 view プロパティは、ViewController クラスのスーパークラスである、NSViewController クラスに、定義されているプロパティです。view プロパティは、このビューを表しています。そして、ウィンドウを表す、window プロパティを持っています。そして、そのウィンドウ window の、外枠 frame の、基点 origin の、横方向 x の値を取得しています。横方向の値は、お使いのモニターの左辺から (デスクトップの左辺から)、ウィンドウの左辺までの値になります。取得した値は、変数 originX に設定しています。この値は後ほど変更されますので、変数に、設定しています。なお、window プロパティの後に、? が付いているのは、このプロパティが nil かもしれない可能性を表しています。

let originY = view.window?.frame.origin.y

 定数 originY に、このビュー view の、ウィンドウ window の、外枠 frame の、基点 origin の、縦方向 y の値を設定しています。縦方向の値は、お使いのモニターの下辺から (デクストップの下辺から)、ウィンドウの下辺までの値です。つまり、ウィンドウの基点 origin は、ウィンドウの左下になります。

originX! += CGFloat(ViewController.offset) * 30

 変数 originX に、offset の30倍の値を足しています。offset の値は、最初のウィンドウの時に0、2番目のウィンドウの時に1になります。originX はオプショナル型なので、+= で演算する前に、非オプショナル型に戻しています。オプショナル型のままでは、演算することができません。また、offset は、整数型 Int なので、演算する前に、CGFloat 型に変換しています。型の違う、Int 型と CGFloat 型のままでは、演算することができません。

view.window?.setFrameOrigin(CGPointMake(originX!, originY!))

 setFrameOrigin メソッドは、ウィンドウの基点を設定するメソッドです。CGPointMake は、基点を作成するメソッドです。

 コーディングが終わりましたら、Webs アプリケーションを実行してみてください。新規ウィンドウが、前のウィンドウの、30 ポイント右に表示されます。


ウェブサイトのタイトルの取得

 次に、WebView に表示されている、ウェブサイトのタイトルを取得して、ウィンドウのタイトルに、設定します。  

 ViewController の定義に、次のリストのコードを追加してください。

class ViewController: NSViewController, WebFrameLoadDelegate {
WebFrameLoadDelegate

 WebFrameLoadDelegate は、WebView に、ウェブサイトが、読み込まれた時に、実行される、様々なメソッドが、定義されているプロトコルです。プロトコロル (protocol、議定書) については、 第14章  プロトコル で説明しています。

 続けて、viewDidLoad メソッドにも、コードを追加します。次のリストの太字部分が、追加するコードです。

    override func viewDidLoad() {
        super.viewDidLoad()
        
        web.frameLoadDelegate = self
        ViewController.offset += 1
        loadWeb()
    }
web.frameLoadDelegate = self

 WebView の frameLoadDelegate として、self、つまりこの ViewController クラスを設定しています。Delegate (デリゲート、委譲・委任) についても、第14章  プロトコル で、説明しています。

 続けて、WebFrameLoadDelegate で定義されているメソッドを、実装します。次のリストのように、メソッドを追加してください。

    override func viewWillAppear() {
        var originX = view.window?.frame.origin.x
        let originY = view.window?.frame.origin.y
        originX! += CGFloat(ViewController.offset) * 30
        view.window?.setFrameOrigin(CGPointMake(originX!, originY!))
    }
    
    func webView(sender: WebView!, didReceiveTitle title: String!, forFrame frame: WebFrame!) {
        sender.window?.title = title
    }
func webView(sender: WebView!, didReceiveTitle title: String!, forFrame frame: WebFrame!)

 このメソッドは、WebView に表示されているウェブサイトの、タイトルが読み込まれた時に、呼び出されます。

sender.window?.title = title

 メソッドによって取得した、ウェブサイトのタイトルを、ウィンドウのタイトルに、設定しています。


ウェブサイトの URLの取得

 ウエブサイトの URL を取得して、その取得した URL を、Text Field に表示します。

 Text Field と ViewController.swift を、アウトレットで接続します。Name は、「textField」にしてください。

 この結果、次のリストのようなコードが、自動的に挿入されます。太字部分が、アウトレットの接続によって、自動的に挿入された、コードです。

・・・
class ViewController: NSViewController, WebFrameLoadDelegate {
    var url = "https://www.apple.com/jp/"
    static var offset = -1
    @IBOutlet weak var textField: NSTextField!
    @IBOutlet weak var web: WebView!
・・・

 続けて、次のリストのとおりに、新しくメソッドを追加します。

・・・
    func webView(sender: WebView!, didReceiveTitle title: String!, forFrame frame: WebFrame!) {
        sender.window?.title = title
    }
    
    func webView(sender: WebView!, didStartProvisionalLoadForFrame frame: WebFrame!) {
        textField.stringValue = (frame.provisionalDataSource.request.URL?.absoluteString)!
    }
・・・
webView(sender: WebView!, didStartProvisionalLoadForFrame frame: WebFrame!)

 WebView フレームの、暫定的な読み込みが始まった時に、呼び出されるメソッドです。「フレームの暫定的な読み込みが始まった時」とは、いつのことなのか、私にも分かりません。しかし、Apple Developer に、WebView に表示されたサイトから、情報を入手するには、このメソッドを使うように指定されています。

textField.stringValue = (frame.provisionalDataSource.request.URL?.absoluteString)!

 Text Field に、読み込んだサイトの、URL を設定しています。


お疲れ様でした。

 次章では、昔、Apple から提供されていた、Currency Converter サンプルプログラムを作ります。このチュートリアルは、Objective-C と、nib ファイルによって作られていましたが、それを、Swift と、ストーリーボードに書き換えてみます。


home  目次  前へ  次へ  mail


無断転載禁止
Copyright 2016. vivacocoa.jp All right reserved.