しめ鯖日記

swift, iPhoneアプリ開発, ruby on rails等のTipsや入門記事書いてます

BitBarでMacメニューバーに好きな文字列を表示する

BitBarというアプリを使ってMacのメニューバーに文字を表示してみました。

f:id:llcc:20171007122252p:plain

まずは公式サイトからBitBarをインストールします。

getbitbar.com

起動するとプラグインのフォルダーを求められるので、好きな場所を指定します。

f:id:llcc:20171007122224p:plain

次にプラグインフォルダの中にスクリプトを追加します。
test.shというファイルを作って下のように記述します。

#!/bin/bash

echo "HelloWorld"

これでメニューバーのBitBarのRefresh Allを使えば先程の処理が反映されます。

f:id:llcc:20171007122824p:plain

プラグインはShellだけでなくRubyで書く事も可能です。

#! /usr/bin/env ruby

p 'HelloRuby'

f:id:llcc:20171007123040p:plain

複数行の出力は、下のような表示になります。

#! /usr/bin/env ruby

p 'Hello'
p 'Ruby'

f:id:llcc:20171007123134p:plain

プラグインが複数ある場合は、それぞれ表示されます。

f:id:llcc:20171007123207p:plain

【Swift】SimpleTabでおしゃれなUITabBarControllerを実現する

SimpleTabというUITabBarControllerがオシャレになったようなライブラリを試してみました。

f:id:llcc:20171003173111g:plain

github.com

CocoaPodsでインストールします。

target 'MyApp' do
  use_frameworks!

  pod 'SimpleTab'
end

2017/10/3時点ではSwift4に対応していないので、Swift3で動かします。

f:id:llcc:20171003173608p:plain

まずはStoryboardだけで動かしてみます。
最初にタブバー用の適当な画像を追加します。

f:id:llcc:20171003174035p:plain

続けてStoryboard上にUITabBarControllerを設置してタブバーの画像やタイトルを設定します。
そしてUITabBarControllerのクラスをSimpleTabBarControllerにします。

f:id:llcc:20171003174056p:plain

続けて、UITabBarControllerのUITabBarのクラスをSimpleTabBarに変更します。

f:id:llcc:20171003174148p:plain

最後にUITabBarControllerに設置するUITabItemのクラスをSimpleTabBarItemに変更します。

f:id:llcc:20171003174247p:plain

以上で設定完了です。
アプリを起動すると、アニメーション付きのタブバーが表示されている事が分かります。

f:id:llcc:20171003174448g:plain

冒頭の弾むようなアニメーションは、SimpleTabBarControllerのtabBarStyleをPopTabBarStyleにする事で実現できます。

import UIKit
import SimpleTab

@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
    var window: UIWindow?
    
    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
        
        if let c = window?.rootViewController as? SimpleTabBarController {
            c.tabBarStyle = PopTabBarStyle(tabBar: c.tabBar)
        }
        
        return true
    }
}

f:id:llcc:20171003175827p:plain

タブバーのアイコンの色やテキストのフォントサイズは、tabBarStyleで変更できます。

if let c = window?.rootViewController as? SimpleTabBarController {
    c.tabBarStyle = PopTabBarStyle(tabBar: c.tabBar)
    c.tabBarStyle?.setIconColor(color: UIColor.green, forState: .selected)
}

f:id:llcc:20171003180156p:plain

アプリのAHA体験を考える

先日読んだ本で、ユーザーの継続率を上げる為にはAHA体験が重要という事を学んだので、自分のアプリのAHA体験は何かを考えてみました。

今回考えたのはこちらのアプリについてです。

体重管理ダイエットのFitt

体重管理ダイエットのFitt

  • hiroki sugimoto
  • メディカル
  • 無料

アプリ内容

シンプルな体重管理アプリです。
「体重・体脂肪率の入力」「体重・体脂肪率の推移をグラフ化」「体重・体脂肪率をカレンダー形式で表示」などの機能を備えています。
細かいところで言うと、目標設定、グラフの前期比表示、グラフへの目標設定などがあります。

f:id:llcc:20171002141809p:plain

ユーザーがこのアプリをインストールするモチベーション

体重管理をして痩せたい、もしくは適切な体重を維持したい。
その為に続けやすいアプリがほしい。

AHA体験候補

上記のモチベーションを考えると、AHA体験は下の物が候補になりそうだと思いました。

  • グラフに目標や前期比を表示できるからモチベーションを維持しやすい
  • 入力が簡単で使いやすい

AHA体験を促す施策

上で挙げたAHA体験を促す施策をそれぞれ考えてみました。

グラフに目標や前期比を表示できるからモチベーションを維持しやすい

  • 初回起動時、グラフのビジュアルを表示する
  • データが1件もない時、グラフ画面にはサンプルデータを表示する
  • 目標は初期設定で入力できるようにする

入力が簡単で使いやすい

  • 体重・体脂肪率を入力している動画をAppStoreに載せる
  • 初回起動時、入力しているアニメーションを表示する
  • 入力画面で、「早速入力してみよう」的なチュートリアルを付ける

TabPageViewControllerでおしゃれなタブメニューを実現する

TabPageViewControllerというタブメニューを実現するライブラリを使ってみました。
このライブラリは有名なiQONで使われているということで、かなり期待できそうです。

github.com

UIPageViewControllerをつかって無限スクロールできるタブUIを実装してOSSとして公開しました - Start Today Technologies TECH BLOG

まずはCocoaPodsでインストールします。

target 'MyApp' do
  use_frameworks!

  pod 'TabPageViewController'
end

使い方は下のとおりです。
TabPageViewControllerのcreateメソッドで基本となるViewControllerを生成して、そこに色々加えていきます。

import UIKit
import TabPageViewController

class ViewController: UIViewController {
    override func viewDidAppear(_ animated: Bool) {
        
        let tabPageViewController = TabPageViewController.create()
        let vc1 = UIViewController()
        let vc2 = UIViewController()
        tabPageViewController.tabItems = [(vc1, "First"), (vc2, "Second")]
        
        present(tabPageViewController, animated: true, completion: nil)
    }
}

起動すると下のようにタブメニューが表示されます。

f:id:llcc:20171003183005p:plain

isInfinityを付けると無限にスクロールする事ができます。

import UIKit
import TabPageViewController

class ViewController: UIViewController {
    override func viewDidAppear(_ animated: Bool) {
        
        let tabPageViewController = TabPageViewController.create()
        let vc1 = UIViewController()
        let vc2 = UIViewController()
        tabPageViewController.tabItems = [(vc1, "First"), (vc2, "Second")]
        tabPageViewController.isInfinity = true
        
        present(tabPageViewController, animated: true, completion: nil)
    }
}

起動時の画面は下の通りです。

f:id:llcc:20171003183220p:plain

色やフォントサイズの情報は、TabPageViewControllerのoptionというプロパティーにセットします。
かなり細かくデザイン調整できそうです。

import UIKit
import TabPageViewController

class ViewController: UIViewController {
    override func viewDidAppear(_ animated: Bool) {
        
        let tabPageViewController = TabPageViewController.create()
        let vc1 = UIViewController()
        let vc2 = UIViewController()
        tabPageViewController.tabItems = [(vc1, "First"), (vc2, "Second")]
        tabPageViewController.option.fontSize = 14
        tabPageViewController.option.currentColor = .cyan
        tabPageViewController.option.currentColor = .darkGray
        tabPageViewController.option.tabHeight = 60.0
        tabPageViewController.option.tabMargin = 40.0
        tabPageViewController.option.tabWidth = 100
        tabPageViewController.option.currentBarHeight = 80
        tabPageViewController.option.tabBackgroundColor = .lightGray
        tabPageViewController.option.pageBackgoundColor = .gray
        tabPageViewController.option.isTranslucent = true
        tabPageViewController.option.hidesTabBarOnSwipe = true
        
        present(tabPageViewController, animated: true, completion: nil)
    }
}

それとTabPageViewControllerがUINavigationControllerにセットされている場合、updateNavigationBarHiddenメソッドを使う事ができます。
このメソッドを呼び出すと、ナビゲーションバーがアニメーション付きで隠れます。

import UIKit
import TabPageViewController

class ViewController: UIViewController {
    override func viewDidAppear(_ animated: Bool) {
        
        let tabPageViewController = TabPageViewController.create()
        let vc1 = UIViewController()
        let vc2 = UIViewController()
        tabPageViewController.tabItems = [(vc1, "First"), (vc2, "Second")]
        
        present(UINavigationController(rootViewController: tabPageViewController), animated: true, completion: {
            tabPageViewController.updateNavigationBarHidden(true, animated: true)
        })
    }
}

それから、displayControllerWithIndexを使うと任意のメニューを選ぶ事ができます。

import UIKit
import TabPageViewController

class ViewController: UIViewController {
    override func viewDidAppear(_ animated: Bool) {
        
        let tabPageViewController = TabPageViewController.create()
        let vc1 = UIViewController()
        let vc2 = UIViewController()
        tabPageViewController.tabItems = [(vc1, "First"), (vc2, "Second")]
        
        present(UINavigationController(rootViewController: tabPageViewController), animated: true, completion: {
            tabPageViewController.displayControllerWithIndex(1, direction: .reverse, animated: true)
        })
    }
}

【Swift】didSetの呼ばれるタイミング(初期化/Struct/Classなどで検証)

SwiftのdidSetの呼ばれるタイミングを調べてみました。

didSetとは

プロパティーの値セットを検知する仕組みです。
下のように書くことで、プロパティーに値がセットされたタイミングを検知する事ができます。

class MainClass {
    var value: Int? {
        didSet {
            print("didSet")
        }
    }
}

didSetの呼ばれるタイミング

下のようにプロパティーを変更するとdidSetが呼ばれます。

class MainClass {
    var value: Int? {
        didSet {
            print("didSet")
        }
    }
}

let c = MainClass()
c.value = 0 // → didSetが呼ばれる

初期値をセットする時は呼ばれません。

class MainClass {
    var value: Int? = 0 { // 初期値を入れても呼ばれない
        didSet {
            print("didSet")
        }
    }
}

同じ値を連続で入れた場合、2回didSetが呼ばれます。

class MainClass {
    var value: Int? {
        didSet {
            print("didSet")
        }
    }
}

let c = MainClass()
c.value = 0
c.value = 0 // didSetが2回呼ばれる

少し複雑ややこしいのですが、Structのプロパティーを変更した時も呼ばれます。

struct MyStruct {
    var value = 0
}

class MainClass {
    var myStruct = MyStruct() {
        didSet {
            print("didSet")
        }
    }
}

let c = MainClass()
c.myStruct.value = 0 // didSetが呼ばれる

classの場合はdidSetが呼ばれません。

class MyClass {
    var value = 0
}

class MainClass {
    var myClass = MyClass() {
        didSet {
            print("didSet")
        }
    }
}

let c = MainClass()
c.myClass.value = 0 // didSetは呼ばれない

【囲碁AI】MacでGNU Goを動かしてみる

MacGNU Goという囲碁ソフトを動かしてみました。

brewに対応しているので、インストールはコマンド1行でできます。

brew install gnu-go

実行はgnugoコマンドを打つだけです。
そのあとはQ16のような形で位置を指定すれば遊ぶ事ができます。

f:id:llcc:20170929144337p:plain

白番を取りたい場合は下オプションを使います。

gnugo --color white

f:id:llcc:20170929145817p:plain

UIStackViewでUIViewを均等配置

iOS9から登場したUIStackViewを試してみました。

UIStackViewでUIViewを均等配置

まずはUIStackViewを配置します。
縦方向と横方向があるのですが、今回は横方向に配置しました。

f:id:llcc:20171015201838p:plain

UIStackViewは下のように画面に配置しました。

f:id:llcc:20171015202013p:plain

続けてUIViewを2つ配置します。
今回はこの3つを等幅・等間隔に並べてみます。

f:id:llcc:20171015202223p:plain

等間隔に並べるために、DistributionをFill Equallyにします。

f:id:llcc:20171015202247p:plain

間隔の調整はSpacingで行います。
今回は間隔を30にしました。

f:id:llcc:20171015202355p:plain

UIViewの縦の位置調整はAlignmentで行います。
下はTopを選択したので、上揃えになります。

f:id:llcc:20171015202535p:plain

LastBaseLineを選ぶと下のような配置になります。

f:id:llcc:20171015202625p:plain