Cocoa練習帳 -5ページ目

[macOS]OS X の起動可能なインストーラを作成する

備忘録。
Macintosh復旧のため、USBメモリーにインストーラを書き込んだので、そのコマンドを記載する。
$ sudo /Applications/Install\ OS\ X\ El\ Capitan.app/Contents/Resources/createinstallmedia --volume /Volumes/ボリューム名 --applicationpath /Applications/Install\ OS\ X\ El\ Capitan.app
関連情報
OS X の起動可能なインストーラを作成する

【Cocoa練習帳】
http://www.bitz.co.jp/weblog/
http://ameblo.jp/bitz/(ミラー・サイト)

[Cocoa]Cocoa Study at Ikebukuro #1

場所を池袋に移しての最初の勉強会。
今回の発表は、nibから文書を生成するツールとATS、Bluemix、サーバサイドSwiftでした。

【Cocoa練習帳】
http://www.bitz.co.jp/weblog/
http://ameblo.jp/bitz/(ミラー・サイト)

Bluemix

iOSアプリケーションの開発をしていると、どうしてもサーバ側の話が出てくる。でも、自分で立ち上げて維持管理するのは大変だ。実運用でなく、開発時としても、もっと楽をしたい。

そんな自分の要求を満たしてくれるのか?明日のセミナーが楽しみだ。

関連情報 【夜間】IBM Bluemix入門セミナー
IBM Blumix入門セミナー
【Cocoa練習帳】 http://www.bitz.co.jp/weblog/
http://ameblo.jp/bitz/(ミラー・サイト)

[OSX]Mandelbrot Set Playground

Swiftは進化が早い。Playgroundでフラクタル!と喜んでいたが、最新の環境で実行するとエラー。残念。

New Playgrounds Part 2 - Sources

このまま諦めるのは悔しいので、動作するように修正してみた。

このブログで公開されているプロジェクトは、Palygroundプロジェクトにソースファイルをリソースとして追加する例だ。プロジェクトを開くといきなりエラー。そして、問題のコードがない!と戸惑ってしまうが、Viewメニューの Navigators / Show Project Navigator を選択して、プロジェクト・ウィンドウの左側にソースファイルを表示させると問題のコードが見えるようになる。

修正内容を列挙すると以下のとおり。

## ComplexNumbers.swift
3c3
< public struct Complex: Equatable, Printable {
---
> public struct Complex: Equatable, CustomStringConvertible {
18c18
<             let p = -2
---
>             // let p = -2
68c68
< public struct ComplexRect: Equatable, Printable {
---
> public struct ComplexRect: Equatable, CustomStringConvertible {

PrintableプロトコルはCustomStringConvertibleと名前が変わったので変更する。18行めのコードは無意味なのでコメントアウトする。

## MandelbrotView.swift
16c16
<         println("Elapsed time: \(elapsedTime) seconds")
---
>         Swift.print("Elapsed time: \(elapsedTime) seconds")
55c55
<                 var c_f : CGFloat = CGFloat(c)
---
>                 let c_f : CGFloat = CGFloat(c)
76c76
<     func viewCoordinatesToComplexCoordinates(#x: Double, y: Double, rect: CGRect) -> Complex {
---
>     func viewCoordinatesToComplexCoordinates(x: Double, y: Double, rect: CGRect) -> Complex {
93,94c93,94
<         var width:Double = Double(rect.size.width)
<         var height:Double = Double(rect.size.height)
---
>         let width:Double = Double(rect.size.width)
>         let height:Double = Double(rect.size.height)
97,99c97,99
<         for x in stride(from: 0, through: width, by: blockiness) {
<             for y in stride(from: 0, through: height, by: blockiness) {
<                 let cc = viewCoordinatesToComplexCoordinates(x: x, y: y, rect: rect)
---
>         for x in 0.stride(through: width, by: blockiness) {
>             for y in 0.stride(through: height, by: blockiness) {
>                 let cc = viewCoordinatesToComplexCoordinates(x, y: y, rect: rect)
105c105
<         println("Calculation time: \(elapsedTime)")
---
>         Swift.print("Calculation time: \(elapsedTime)")


printlnをprintに変更する。この名前だと衝突するようなので名前空間Swiftをつける。値の変更がないという警告が出ている変数への代入をvarからletに変更する。stride関数の仕様が変わったようなので変更する。

## Contents.swift
19c19
<     println("Exploring: \(triple.0)")
---
>     print("Exploring: \(triple.0)")

printlnをprintに変更する。

エラーが取れて、図が表示された。

関連情報 New Playgrounds Part 2 - Sources
【Cocoa練習帳】 http://www.bitz.co.jp/weblog/
http://ameblo.jp/bitz/(ミラー・サイト)
Qiita

[iOS]GitHub + Travis CI + Slack

GitHubにリポジトリがあるプロジェクトのTOPディレクトリ(.gitディレクトリがあるディレクトリ)に.travis.ymlファイルを作成する。

language: objective-c
osx_image: xcode7.2
script:
  - xcodebuild test -project Xxxx.xcodeproj -scheme XxxxTests -destination 'platform=iOS Simulator,name=iPhone 6s' ONLY_ACTIVE_ARCH=NO
  - xcodebuild test -project Xxxx.xcodeproj -scheme XxxxUITests -destination 'platform=iOS Simulator,name=iPhone 6s' ONLY_ACTIVE_ARCH=NO
notifications:
  email:
    - XXXX@XXXX.XXX
  slack: XXXXXXXXXX

上記の例は、単体テストとUIテストを実行する内容となっている。

現時点で、osx_imageを指定しないとXcode 6.1 (10.9.x)となるので、最新のXcode 7.2 (10.11.x)を設定している。

xctoolを使ったビルドの方が楽だと思うが、著者の環境ではビルドエラーとなったため、xcodebuildを使っている。

notificationsのemailには結果を通知してほしいメールアドレスを記述する。slackには結果を通知してほしいslackno slackの場所を設定するのだが、何を設定するかは、後ろで説明する。

Xcodeプロジェクトを外部サービスでビルドする場合は、スキーム毎に許可を与える必要がある。

slackのIntegration SettingsでTravis CIの設定を行い、Tokenを得る。

これを.travis.ymlに設定すると、このリポジトリにpushする度に、テストが走る。

関連情報 GitHub
Travis CI
slack
【Cocoa練習帳】 http://www.bitz.co.jp/weblog/
http://ameblo.jp/bitz/(ミラー・サイト)
Qiita

[tvOS]Apple TV Tech Talk videos

Apple TV Tech Talkの動画が視聴可能となった。

Apple TV Tech Talks Videos

関連情報 ADC
【Cocoa練習帳】 http://www.bitz.co.jp/weblog/
http://ameblo.jp/bitz/(ミラー・サイト)
Qiita

[C++]Singleton

前回、Swiftでシングルトンの実装が楽になった件を発表したが、C++だとどうなるのか試してみた。

class Singleton {
    Singleton* sharedInstance;
    static mutex mtx;
    static atomic flag_init;
    Singleton* getInstance();
};
mutex Singleton::mtx;
atomic Singleton::flag_init {false};
Singleton* Singleton::getInstance()
{
    if (! flag_init) {
        mtx.lock();
        if (! flag_init) {
            sharedInstance = new Singleton();
            flag_init = true;
        }
        mtx.unlock();
    }
    return sharedInstance;
}

もっと簡易に書ける機能があるようだが、基本はこうなるようだ。

関連情報 Adopting Cocoa Design Patterns
【Cocoa練習帳】 http://www.bitz.co.jp/weblog/
http://ameblo.jp/bitz/(ミラー・サイト)
Qiita

[Cocoa]Singleton

大晦日になって、自分が知らなかったことに気がついてしまった。

マルチスレッドの環境でシングルトンを実装する場合、ロックが思っていたが、Swiftでは状況が異なるようだ。

Objective-Cで実装する場合、以下の通り。

+ (instancetype)sharedInstance {
    static id _sharedInstance = nil;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        _sharedInstance = [[self alloc] init];
    });
 
    return _sharedInstance;
}

Swiftだとstatic変数はクラスアクセス時に生成されるので、以下のように記述できる。

class Singleton {
    static let sharedInstance = Singleton()
}

シングルトンなインスタンス生成時に設定が必要な場合は以下となる。

class Singleton {
    static let sharedInstance: Singleton = {
        let instance = Singleton()
        // setup code
        return instance
    }()
}

もし、シングルトン以外のインスタンス生成を許したくない場合は、C++でコンストラクタをpriateにするのと同様に、privateなinit()関数を用意すればいい。

    private init() {
        // setup code
    }
関連情報 Using Swift with Cocoa and Objective-C (Swift 2.1)
【Cocoa練習帳】 http://www.bitz.co.jp/weblog/
http://ameblo.jp/bitz/(ミラー・サイト)
Qiita

[Cocoa]Cocoaの概念

クラスクラスタ

複数の非公開具象クラスをまとめた公開抽象クラス。例を挙げるとNSNumberクラス。内部には、整数や浮動小数毎に実装されたクラスを用意しているが、インタフェーストして公開しているのは数値に対応したNSNumberクラス。

クラスクラスタの欠点を挙げるとすれば、公開抽象クラスのサブクラスを定義することが困難。

クラスファクトリメソッド

クラスファクトリメソッドの名前は、「+ (type)className...」となる。例を挙げると、例えば、NSDateクラスの場合は以下の通り。

+ (id)dateWithTimeIntervalSinceNow:(NSTimeInterval)secs;
+ (id)dateWithTimeIntervalSinceReferenceDate:(NSTimeInterval)secs;
+ (id)dateWithTimeIntervalSince1970:(NSTimeInterval)secs;

ARCが広く使われるようになった現状では、allocとinitの二つのメソッドを呼ばないといけないので楽という利点しか感じられなくなったが、このメソッドの呼び出し側はオブジェクトを所有しない。つまり、autoreleaseされたインスタンスを返すという意味のメソッドだ。

デリゲートとデータソース

デリゲート(委譲)は、サブクラスを作成しないで、あるオブジェクトの処理を外に出す実装方法。

データソースは、デリゲートと似ていて、デリゲートがインタフェースの制御を委譲するものだが、データソースはデータの制御を委譲するものだ。

イントロスペクション

イントロスペクションは、オブジェクトの内容を調べる機能のことで、例えば、あるクラスのサブクラスなのかだとか、あるメソッドを実装しているか、あるプロトコルに純処しているか等だ。

ちょっと、純粋なオブジェクト指向言語に反する部分があると思うのだが、実用主義らしい、これによって柔軟な実装ができる便利な機能だと思う。

オブジェクトの割り当て

他の純粋なオブジェクト指向言語と異なり、インスタンスの生成などが言語でなくフレームワークで定義されているというのが、Cocoaの面白いところだ。

オブジェクトの初期化

「オブジェクトの割り当て」と重複するが、C++でコンストラクタ(構築子)と呼ばれるものは、NSObjectの実装ルールとなっている。

Model-View-Controllerパターン

Lisa Toolkitから受け継がれているAppleのクラスライブラリで重要視しているデザインパターン。著者がCocoaを始めた時は、具体的にどうするのかがピンとこなかったが、現在では、対応するクラスがフレームワークで用意されているなどで、このデザインパターンに沿いやすくなったと思う。

オブジェクトモデリング

初期のCocoaではモデルに対応するクラスがなかったが、CocoaバインディングやCoreDataが出た頃から、モデルの実装をサポートする機能が充実してきた。

オブジェクトの可変性

MutableとMutableでないクラスが用意されていることだ。

アウトレット

Interface Builderで接続される、他のオブジェクトの参照。インスタンス変数のことだ。

Receptionistパターン

キー値監視(KVO)などを使った、あるイベントに対応した処理を呼び出すようなもののこと。

ターゲット-アクション機構

対象となるオブジェクトのメソッドを呼び出す仕組み。例を挙げるとInterface Builderでコントローラでイベントが発生すると、接続したインスタンスのメソッドを呼び出すことだ。

フレームワークの相互乗り入れについて

Core FoundationとFoundationで、相互にデータを利用出来る仕組みで、Toll-Free Bridgingと呼ばれている。

関連情報 Cocoa Advent Calendar 2015
Cocoa向け コーディングガイドライン
Objective-Cプログラミングの概念
【Cocoa練習帳】 http://www.bitz.co.jp/weblog/
http://ameblo.jp/bitz/(ミラー・サイト)

[tvOS]Gameコントローラ

tvOSのサンプルDemoBotsとGameplayKitのサンプルMazeを参考にして、SpriteKitとGameplayKitを使ったtvOSのゲーム・アプリケーションの実装を試す。

Xcodeの新規プロジェクトで生成されるSpriteKitを使ってプロジェクトをGameコントローラを使用したものに変更してみる。

Gameコントローラの内容は以下のとおり。

import Foundation
import SpriteKit
import GameplayKit
 
class Game {
    var gameScene: GameScene?
    let random: GKRandomSource?
    
    init() {
        random = GKRandomSource()
    }
    
    deinit {
    }
    
    var scene: GameScene? {
        get {
            if gameScene == nil {
                gameScene = GameScene(fileNamed: "GameScene")
            }
            return gameScene
        }
    }
}

以下がViewControllerの変更前。

class GameViewController: UIViewController {
    :
    override func viewDidLoad() {
        print(NSStringFromClass(self.dynamicType), __FUNCTION__)
        super.viewDidLoad()
        
        if let scene = GameScene(fileNamed: "GameScene") {
            // Configure the view.
            let skView = self.view as! SKView
            skView.showsFPS = true
            skView.showsNodeCount = true
            
            /* Sprite Kit applies additional optimizations to improve rendering performance */
            skView.ignoresSiblingOrder = true
            
            /* Set the scale mode to scale to fit the window */
            scene.scaleMode = .AspectFill
            
            skView.presentScene(scene)
        }
    }
    :
}

以下がViewControllerの変更後。

class GameViewController: UIViewController {
    :
    override func viewDidLoad() {
        print(NSStringFromClass(self.dynamicType), __FUNCTION__)
        super.viewDidLoad()
        
        game = Game()
        if let aGame = game {
            let scene = aGame.scene
            scene!.scaleMode = .AspectFill
            
            let skView = view as! SKView
            skView.presentScene(scene)
            skView.ignoresSiblingOrder = true
            skView.showsFPS = true
            skView.showsNodeCount = true
        }
    }
    :
}
ソースコード GitHubからどうぞ。
https://github.com/murakami/workbook/tree/master/tvos/Pokopen - GitHub
関連情報 Cocoa Advent Calendar 2015
App Programming Guide for tvOS
GameplayKit Programming Guide
実践!iOSで作るゲームアプリ
【Cocoa練習帳】 http://www.bitz.co.jp/weblog/
http://ameblo.jp/bitz/(ミラー・サイト)