78
Help us understand the problem. What are the problem?

More than 5 years have passed since last update.

posted at

updated at

Organization

Mac OSXスクリーンセーバーをSwiftで作成する

この記事はCocoa Advent Calendar 2015の2日目の記事です。

はじめに

スクリーンセーバーのアプリを作った人なんてほとんどいないと思いますが、その手始めにSwiftでの起動方法まで紹介します。

また、今回のプロジェクトは github.com/kaneshin/TextSaver に置いておきます。

環境

  • OS X El Capitan 10.11.1 (15B42)
  • Xcode 7.1.1 (7B1005)

準備

ScreenSaverEngine.appの用意

実装しているScreen Saverを実行するためにScreenSaver.frameworkにあるScreenSaverEngine.appをApplicationsディレクトリへシンボリックリンクを作成します。

$ ln -sf /System/Library/Frameworks/ScreenSaver.framework/Versions/A/Resources/ScreenSaverEngine.app /Applications/ScreenSaverEngine.app

実装

Screen Saverテンプレート

テンプレートを作成するとObjective-Cのテンプレートしかないため、Swiftファイルを用意する。この時、なるべく同じファイル名にすること。

Screen Shot 2015-11-29 at 4.03.00 PM.png

作成したら、Objective-C用のテンプレファイルは削除してください。

Swift用のコードテンプレート

作成したSwiftファイルにそのまま下記をペーストしてください。

import Foundation
import ScreenSaver

class TextSaverView: ScreenSaverView {

    required init?(coder: NSCoder) {
        super.init(coder: coder)
        self.animationTimeInterval = 1.0 / 30.0
    }

    override init?(frame: NSRect, isPreview: Bool) {
        super.init(frame: frame, isPreview: isPreview)
        self.animationTimeInterval = 1.0 / 30.0
    }

    override func startAnimation() {
        super.startAnimation()
    }

    override func stopAnimation() {
        super.stopAnimation()
    }

    override func drawRect(rect: NSRect) {
        super.drawRect(rect)
    }

    override func animateOneFrame() {
        return
    }

    override func hasConfigureSheet() -> Bool {
        return false
    }

    override func configureSheet() -> NSWindow? {
        return nil
    }

}

Target Settings

Principal class の設定

テンプレ作成時のObjective-Cとは違う命名でSwiftファイルを作成した場合、Principal class の値を変更する必要があります。

Screen Shot 2015-11-29 at 4.09.54 PM.png

Embedded Content Contains Swift Code の設定

Swiftファイルを実行するため、下記の通りに値を Yes に変更してください

Screen Shot 2015-11-29 at 4.10.37 PM.png

起動

Runで実装しているスクリーンセーバーをScreenSaverEngine.appでバックグラウンド起動できるようにします。

Schemeの設定

InfoにあるExecuteへScreenSaverEngine.appを設定する

Screen Shot 2015-11-29 at 4.14.07 PM.png

Argumentsの設定

ArgumentsにあるArguments Passed on Launchに下記の値を設定する

  • -background
  • -module "$(EXECUTABLE_NAME)"

Screen Shot 2015-11-29 at 4.15.09 PM.png

Run Scriptの設定

実装しているスクリーンセーバーをスクリーンセーバー用のディレクトリにコピーするために下記のコマンドを設定する

  • open -W "${CODESIGNING_FOLDER_PATH}"

New Run Script Phase
Screen Shot 2015-11-29 at 4.16.13 PM.png

Run Script
Screen Shot 2015-11-29 at 4.16.33 PM.png

Run - 実行

Command+Rで実行すると、下記の画像のようにScreenSaverのインストールを求められるのでそのまま Install してください

Screen Shot 2015-11-29 at 4.18.50 PM.png

インストールするとDesktop & Screen Saverの画面が開きますが、そのまま閉じてください。

Screen_Shot_2015-11-29_at_4_19_01_PM.png

すると、デスクトップでスクリーンセーバーが動いていることが確認できると思います。

起動しない場合

起動時のデバッグメッセージに

Message from debugger: cannot attach to process due to System Integrity Protection

というメッセージが出る場合はプロテクションが有効になっているため、それを無効にします。

How to Disable System Integrity Protection (rootless) in OS X El Capitan

  • Recoveryモードで起動し、ターミナルを開く
  • csrutil disable; reboot をタイプ

おわりに

iOS開発しかしたことが無い方が多数だと思うのですが、OSX開発はiOS開発のようにフレームワークが手厚くないのと、ググっても記事が出てこないですが結構楽しいです。

スクリーンセーバー作成の初歩中の初歩を紹介したので、仮に、好評そうであれば追加の実装方法を別記事で紹介したいと思います。

今回はひとまずここまでです。

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
78
Help us understand the problem. What are the problem?