try! Swift Tokyo 2017 hackasonに参加しました

try! Swift Tokyo 2017 hackasonに参加しました

name_holder

今年も福岡からtry! Swiftに参加しました。
去年に引き続き@niwatakoさんがセッションの聞き起こしをして下さっていますので
セッション内容についてはそちらを参照してください。


今年は3日目にハッカソンがあったので、どんなものなのか興味もあり参加しました。
ただ夕方に離脱する可能性があったのでソロ参加です。

アイデアソン

2日目にDerek Leeさんのチームの生産性を改善するために決断疲れを最小化するを聞いていたので
Xcodeユーザーの生産性を少しだけ改善するものをテーマにしました。

作ったもの

実装する必要があるProtocolのメソッドを補完するXcode Source Editor Extension。
継承関係を解析してカーソルがある位置に必要なメソッドを補完します。

GitHub: XcodeSourceEditorExtension-ProtocolImplementation

demo

2つコマンドを作りました。

  • from Completion: 補完リストを使って補完する
  • from Snippet: スニペットを使って補完する(要設定)

例えばUITableViewDataSourceを継承したコードで、

import UIKit

class ViewController: UIViewController {
}

extension ViewController: UITableViewDataSource {
// ここにカーソルがある状態でExtensionを実行
}

ワンアクションで必要なメソッドを展開できるようになります。

import UIKit

class ViewController: UIViewController {
}

extension ViewController: UITableViewDataSource {
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
<#code#>
}

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
<#code#>
}
}

キーバインド設定でショートカットキーを割り当てれば、
スニペットを選択して展開する場合と比べると1秒ぐらいは短縮できるんじゃないでしょうか。

from Completionコマンドについて、本当はRequiredなメソッドのみ展開したかったんですが、
今のところoptionalメソッド含めて全メソッドが展開されてしまいます😢

その他、正しく動かないケースもあると思うので改修したいですが、
とりあえず当日の状態のまま晒します。

どうやっているのか

SourceKittenFrameworkを使用して継承関係と補完データを取得して
カーソルがあるスコープに必要なメソッドを出力しているだけです。

これだけですが、SourceKittenを使ったことが無かったのでハマりました。

ハマったポイント

ExtensionでSourceKittenが使えない

そもそもExtensionはApp Sandboxが有効になってるいるため、
SourceKittenFrameworkが使えませんでした。
最初から詰んだかと思いましたが、最終的にXPC Serviceを経由することで回避できました。

ハッカソン中、下記4パターンを試行錯誤したのでメモしておきます。

  1. Processsourcekittenコマンドを叩く
    => ×:ダメでした。
  2. ホストアプリでSourceKittenを使用してApp GroupでExtensionと結果を共有する
    => △:ホストアプリを常時立ち上げておかないといけないのでつらい。
  3. そもそもExtensionをやめてプラグインにする(選択可能な補完リストも出せるし)
    => ×:プラグインを使えるようにしてみたらXcodeが死にましたXO 調べる時間が無かったので断念。
  4. デーモンを作ってプロセス間通信する
    => ○:XPC Serviceを経由させたらいけました。

翌日ググったらSourceKittenのIssueがあっさり見つかりました。XPC Serviceを使うのが正解のようです。

補完されたメソッドがoptionalなのか分からない

メソッド一覧はすぐ取れましたが、optionalなメソッドなのかを判別できる情報が含まれていないようでした。
これが判別できないと全てのメソッドが補完されてしまいます。

すぐにできる解決方法を思いつかなかったので、
スニペットを利用できるfrom Snippetコマンドを追加しました。
それに付随してプロトコルと対応するスニペットを設定できるようにする必要があったので、
今回は簡易的にホストアプリのウィンドウにテキストフィールドを置いて
スニペットの情報をJSON形式で入力できるようにしました。

{
    "Directory": "/Users/tid/Library/Developer/Xcode/UserData/CodeSnippets",
    "Snippets": [
        { "key": "UIViewController", "path": "swift-uiviewcontrollerlifecycle"},
        { "key": "UITableViewDelegate", "path": "swift-uitableviewdelegate"},
        { "key": "UITableViewDataSource", "path":  "swift-uitableviewdatasource"},
        { "key": "UICollectionViewDataSource", "path":  "swift-uicollectionviewdatasource"}
    ]
}

Extensionから使える整形機能がない

Xcodeでスニペットを挿入した時に自動整形されるので
何か方法があるんじゃないかと予想していたんですが見つかりませんでした。
諦めてそれっぽくなるようにインデントを入れています。

まとめ

ハッカソン初参加で得た教訓はこんなところでしょうか。

  • 可能な限り事前準備(アイデア出しと調査)をやっておく
  • 使ったことがないものは使わない

体験しないと分からないこともあり参加してよかったです。
残念ながら途中で離脱することになったので審査を辞退するためDevPostの登録を取り下げた(つもりだった)んですが
今見たらプロジェクトだけ残っていました。すみません🙇🏻

記録としてプロジェクトのリンクを残しておきます。
Xcode Source Editor Extension

次はチームを組んで発表までしたいところですが、福岡だとオープンなハッカソンが少ないので来年になりそうです。

SwiftPM ライブラリとシステムモジュールを作る方法

SwiftPMでは2種類のパッケージを作れます。

  • ライブラリ
    一般的なライブラリを作成します。
    例えばAlamofireKingfisherなどのようなライブラリを作りたい場合はこちらになります。

  • システムモジュール
    外部ライブラリなどをモジュール化できます。
    libxml2やCommonCryptoなどをモジュール化する場合はこちらになります。

ライブラリを作る

作業ディレクトリ作成

$ mkdir SamplePackage
$ cd $_
$ swift package init --type library // swift package init でもOK
Creating library package: SamplePackage
Creating Package.swift
Creating .gitignore
Creating Sources/
Creating Sources/SamplePackage.swift
Creating Tests/
Creating Tests/LinuxMain.swift
Creating Tests/SamplePackageTests/
Creating Tests/SamplePackageTests/SamplePackageTests.swift

依存パッケージ設定

ライブラリは依存パッケージを持つことができます。
これにより例えばAlamofireを内部で利用するライブラリなどが作れます。

Package.swiftに依存関係を指定します。

import PackageDescription

let package = Package(
    name: "SamplePackage",
    dependencies: [
        .Package(url: "git@github.com:Alamofire/Alamofire.git", majorVersion: 4)
    ]
)

依存パッケージがなければ何も指定しません。

除外設定

ディレクトリに関係のないファイルやディレクトリ(ドキュメントなど)があるとビルドに失敗することがあります。
その場合、関係のないものをパッケージから除外するよう exclude で指定する必要があります。

import PackageDescription

let package = Package(
name: "SamplePackage",
exclude: ["Docs"]
)

コーディング

Sources/SamplePackage.swift にコードを記述します。
公開したいプロトコル・クラス・構造体・関数などはアクセス修飾子publicまたはopenを指定してください。

テストコードはTests/SamplePackageTests/SamplePackageTests.swiftに記述します。

ビルド

$ swift build

テスト

$ swift test

公開

SwiftPMのパッケージとして公開するにはGitHubにリポジトリを作成し、タグを作ります。

$ git init
$ git add .
$ git remote add origin [GitHub URL]
$ git commit -m "Initial commit"
$ git tag 1.0.0
$ git push origin master --tags

タグ名は下記フォーマットに従う必要があります。
このフォーマットに従っていないとSwiftPMでは利用できません。

"major.minor.patch[-prereleaseIdentifiers][+buildMetadata]"

補足

複数モジュールを含むライブラリを作る

Sourcesディレクトリ内にサブディレクトリを作ると別モジュールになります。

Sources/Foo/Widget.swift
Sources/Bar/Bazzer.swift

このディレクトリ構成ではモジュールFooBarが作成されるのでパッケージを使う側は、
Widget.swiftの内容にアクセスするにはimport Fooする必要があり、
Bazzer.swiftの内容にアクセスするにはimport Barする必要があります。

Objective-Cでコードを書く

ディレクトリ構成に制限がありますが、SwiftだけでなくC言語やObjective-Cなども使えます。
(対応言語:C / C++ / Objective-C / Objective-C++)
基本的な構成の例は下記の通りです。

Sources/Baz/m.c
Sources/Baz/include/m.h

この例ではモジュールBazが作成され、import BazすることでC言語で書いた関数などにアクセスできるようになります。

詳細はドキュメント“C language targets”で確認してください。

システムモジュールを作る

libxml2をモジュール化する方法を紹介します。

作業ディレクトリ作成

$ mkdir SwiftClibxml2
$ cd $_
$ swift package init --type system-module
Creating system-module package: CommonCrypto
Creating Package.swift
Creating .gitignore
Creating module.modulemap

コーディング

import PackageDescription

let package = Package(
    name: "SwiftClibxml2",
    pkgConfig: "libxml-2.0",
    providers: [
        .Brew("libxml2"),
        .Apt("libxml2-dev")
    ]
)
module SwiftClibxml2 [system] {
    header "libxml2.h"
    link "xml2"
    export *
}
#import <libxml2/libxml/tree.h>
#import <libxml2/libxml/parser.h>
#import <libxml2/libxml/HTMLtree.h>
#import <libxml2/libxml/HTMLparser.h>
#import <libxml2/libxml/xpath.h>
#import <libxml2/libxml/xpathInternals.h>

Providers

libxml2を使うにはシステムにlibxml2がインストールされている必要があります。
これはPackageの引数providersに指定することでユーザーに教えることができます。

providers: [
.Brew("libxml2"), // homebrew
.Apt("libxml2-dev") // apt-get
]

インストールされていないときは下記のようなメッセージが表示されます。

note: you may be able to install libxml-2.0 using your system-packager:

brew install libxml2

公開する

ライブラリと同じ方法で公開します。

参考

Swift Package Manager Documentation

Swift Package Managerの使い方

Swift Packager Manager(SwiftPM)とは?

ライブラリの依存関係を管理してくれるツールで、
CocoaPodsCarthage と同じようなものです。
マルチプラットフォームで使えるのでサーバーサイドSwift^1で採用されています。

GitHub: apple/swift-package-manager

略称は SPMSwiftPM の2つが見られますが、
ドキュメントでは後者が使われているので SwiftPM を使います。

ここでは使い方を紹介します。なおライブラリの作り方は別にまとめました。
SwiftPM ライブラリとシステムモジュールを作る方法

SwiftPMの使い方

セットアップ

まずは作業ディレクトリを作成します。

$ makedir Sample
$ cd $_
$ swift package init --type=executable
Creating executable package: Sample
Creating Package.swift
Creating .gitignore
Creating Sources/
Creating Sources/main.swift
Creating Tests/

依存パッケージ(ライブラリ)を指定する

Package.swift に依存パッケージを指定します。

import PackageDescription

let package = Package(
name: "Sample",
dependencies: [
.Package(url: "git@github.com:tid-kijyun/SamplePackage.git", majorVersion: 1)
]
)

バージョンの指定

依存パッケージの指定部分は複数のイニシャライザが用意されています。
これらを使うことで、より細かいバージョン指定が可能です。

.Package(url: String, versions: Range<Version>)

.Package(url: String, versions: ClosedRange<Version>)

.Package(url: String, majorVersion: Int)

.Package(url: String, majorVersion: Int, minor: Int)

.Package(url: String, _ version: Version)
// バージョン1.0.0以上1.2.0以下
.Package(url: "git@github.com:tid-kijyun/SamplePackage.git", versions: "1.0.0"..."1.2.0")

// バージョン1.0.0以上2.0.0未満
.Package(url: "git@github.com:tid-kijyun/SamplePackage.git", versions: "1.0.0"..<"2.0.0")

// メジャーバージョン1の最新版(上と同じ)
.Package(url: "git@github.com:tid-kijyun/SamplePackage.git", majorVersion: 1)

// メジャーバージョン1、マイナーバージョン2の最新版
.Package(url: "git@github.com:tid-kijyun/SamplePackage.git", majorVersion: 1, minor: 2)

// バージョンを固定する
未実装、ピン機能というのが実装されるようです。(SE-0145)

バージョンを文字列で指定する場合は下記フォーマットに従う必要があります。
このフォーマットに従っていないパッケージは利用できません。

"major.minor.patch[-prereleaseIdentifiers][+buildMetadata]"

@swift-3

GitHubを見ているとフォーマットに一致していない 3.0.1@swift-3 のようなタグを見かけるかもしれません。
この @swift-3 はSwiftPMが自動判別して利用するオプションなので使う側は気にする必要はありません。

詳細はVersion-specific tag selectionを参照してください。

依存パッケージのビルド

$ swift build
Cloning git@github.com:Alamofire/Alamofire.git
HEAD is now at 7a17b1d Added release notes to the CHANGELOG and bumped the version to 4.2.0.
Resolved version: 4.2.0
Compile Swift Module 'Alamofire' (17 sources)
Compile Swift Module 'Sample' (1 sources)
Linking ./.build/debug/Sample

コーディング

Sources/main.swift にコードを記述します。

import SamplePackage

sayHello()

ビルド

$ swift build
Compile Swift Module 'Sample' (1 sources)
Linking ./.build/debug/Sample

実行

$ .build/debug/Sample

その他

Xcodeを使う

コマンドでXcodeのプロジェクトを生成できます。
ただし依存パッケージを追加・削除するたびに実行する必要があります。

$ swift package generate-xcodeproj
generated: ./Sample.xcodeproj

参考

Swift Package Manager Documentation

TensorFlow iOSのサンプルを動かす

6月8日にTensorFlowがiOSをサポートしました。
ここではTensorFlowのインストールからiOSのサンプルを動かすまでを記します。

⚠️TensorFlow 0.9.0 RC0 時点の記事です。

インストール

  1. 事前準備
    protobuf 3 が必要になるのでインストールしていなければ、インストールしておきます。
    homebrew以外をお使いの方は各々の方法でインストールしてください。

    > brew install --devel protobuf
  2. ダウンロード

    > curl -L -O https://github.com/tensorflow/tensorflow/archive/v0.9.0rc0.tar.gz`
    > tar -xvzf tensorflow-0.9.0rc0.tar.gz
  1. ビルド
    完了するまでに時間が掛かるので && で繋いで寝る前に実行することをお勧めします。

    > cd tensorflow-0.9.0rc0

    > ./tensorflow/contrib/makefile/download_dependencies.sh

    > make -f tensorflow/contrib/makefile/Makefile TARGET=IOS IOS_ARCH=ARM64

    > ./tensorflow/contrib/makefile/compile_ios_protobuf.sh

    > ./tensorflow/contrib/makefile/compile_ios_tensorflow.sh

サンプルを実行

simpleサンプルを実行してみます。

cd ./tensorflow/contrib/ios_examples/simple

  1. 事前準備
    必要なデータをダウンロードします。

    > cd data

    > curl -L -O https://storage.googleapis.com/download.tensorflow.org/models/inception5h.zip

    > unzip inception5h.zip
  2. プロジェクト設定の修正
    Header Search Paths の設定が実際のディレクトリパスと合致していなかったので修正しました。
    環境によって異なるかもしれないので、実際のパスを確認して修正してください。

    旧:$(SRCROOT)/../../makefile/downloads/eigen-eigen-f3a13643ac1f
    新:$(SRCROOT)/../../makefile/downloads/eigen-eigen-d02e6a705c30

  3. コードの修正
    graph.pb.h L127-139PROTOBUF_DEPRECATED_ATTR にエラーが出るので削除します。
    これはワークアラウンドですが、Issue(#183) が上がっているのでそのうち解決すると思います。

    /*PROTOBUF_DEPRECATED_ATTR*/ void clear_version();
    /*PROTOBUF_DEPRECATED_ATTR*/ static const int kVersionFieldNumber = 3;
    /*PROTOBUF_DEPRECATED_ATTR*/ ::google::protobuf::int32 version() const;
    /*PROTOBUF_DEPRECATED_ATTR*/ void set_version(::google::protobuf::int32 value);
  4. ビルド&実行
    ここまででビルドが通って実行できるようになっているはずです。

    simpleサンプルの起動画面

参考

TensorFlow Makefile - GitHub

TensorFlow iOS Examples - GitHub

protobuf v3.0.0-alpha-2 is in Homebrew now - GitHub

Xcode Source Editor Extensionを試す

Qiitaに投稿した記事を手直ししたものです。

本記事は Xcode8 beta1 を対象に作成しています。

what's_new_dev_.png
WWDC2016にてXcode Source Editor Extension、Xcode Editor Extensionが発表されました。
Xcode用のApp Extensionが作れる、というものです。
Mac App Storeで配布もできるとのことでAlcatrazが不要になるかもしれませんね。

ここではXcode Source Editor Extensionを試してみます。

Xcode Source Editor Extensionとは?

名前の通りSource Editor部分を拡張するもので、現在できることは3つだけです。

・Add commands to the source editor = Source Editorへコマンドを追加
・Edit text = テキストの編集
・Change selections = 選択範囲の変更
Using and Extending the Xcode Source Editor 13:17頃より引用

残念ながら独自UIの表示・Xcodeメニューのカスタマイズなどはできないようになっています。
もっと広範を拡張したい場合はXcode Editor Extensionを作ることになるのかなと思います。

XcodeとExtensionの関係性を図にするとこんな感じです。

Xcodeとの関係

作ってみる

事前準備

macOS 10.11では事前に下記手順が必要です。

  • Xcode-betaを起動してadditional system componentをインストール
  • sudo /usr/libexec/xpccachectl を実行
  • macOSを再起動

プロジェクトの作成

まずはプロジェクトをCocoa Applicationテンプレートで作ります。

その後にFile > New > Target... または +ボタン(Add a target) から作成します。

以上でExtensionのSchemaを選択して実行(Choose an app to run:)でXcode8を選択すれば
Editorメニューに項目が追加されます。

Running状態になる前に操作するとうまく動きません。実行した後、一呼吸置きましょう。

生成されたファイルを見てみる

ターゲットを作成すると、下記のSwiftファイルが生成されます。

  • SourceEditorExtension.swift
  • SourceEditorCommand.swift
import Foundation
import XcodeKit

class SourceEditorExtension: NSObject, SourceEditorExtension {
	/*
    func extensionDidFinishLaunching() {
        // If your extension needs to do any work at launch, implement this optional method.
    }
	*/
    
    /*
    var commandDefinitions: [[XCSourceEditorCommandDefinitionKey: AnyObject]] {
        // If your extension needs to return a collection of command definitions that differs from those in its Info.plist, implement this optional property getter.
        return []
    }
    */
}
import Foundation
import XcodeKit

class SourceEditorCommand: NSObject, XCSourceEditorCommand {
    
    func perform(with invocation: XCSourceEditorCommandInvocation, completionHandler: (NSError?) -> Void ) -> Void {
        // Implement your command here, invoking the completion handler when done. Pass it nil on success, and an NSError on failure.
        
        completionHandler(nil)
    }
    
}

さしあたり見るべきなのは4つだけで良さそうです。

  • extensionDidFinishLaunching

    起動時に呼ばれる。

  • commandDefinitions

    実行するコマンドの情報を定義する。
    info.plistに書いてある情報が使われるので定義しなくてもよい。

  • perform

    コマンドが実行されると呼ばれる。
    ここに処理を書く。

  • XCSourceEditorCommandInvocation

    これを操作する形でXcode Source Editorに干渉できるようです。
    詳細は定義にジャンプして覗くしかありません。

サンプル

XcodeSourceEditorExtension-Alignment - GitHub

選択範囲の代入文を整列する拡張です。
XcodeのEditorメニューにAlignmentが追加されます。

使い方

Xcodeでコードを選択状態にしてから Alignment を選択してください。

// before:
var hoge = "hoge"
var foo = "foo"
var awesome = ""
// after:
var hoge = "hoge"
var foo = "foo"
var awesome = ""

ショートカットキーの登録方法

開発者側によるデフォルト設定はできず、
Preference > KeyBindings からユーザーが設定するしかないようです。

メモ

Xcode-beta.app内に2つXcode Source Editor Extensionがありました。

名前 キー 説明
XCDocumenterExtension.appex ⌥⌘/ ドキュメントコメントを生成。中身はVVDocumenter† のようです。
IDECacheDeleteAppExtension.appex Derived Dataを消せる? Xcode Editor Extension のようです。

† VVDocumenterの作者@onevcatさんのツイートより。

参考

Xcode

公式の紹介ページ、Editor Extensionsの項目にてMac App Storeで配信できると書いてあります。

Release Note

New in Xcode 8.0 beta - IDE > Source Editor Extensions
Known Issues in Xcode 8.0 beta - IDE > Source Editor Extensions

Using and Extending the Xcode Source Editor

WWDC2016の関連セッション。
24:37からDemo、実際に作って試すところが見れます。

try!Swift 2日目のQ&Aセッションの振り返り

本セッションに関しては@niwatakoさんを始めとして素晴らしい記事があるのでそちらをどうそ!

20160303 try! Swift Day2 聞き起こしまとめ #tryswiftconf - niwatakoのはてなブログ

Q&Aセッションで私が聞いたことをまとめます。

Core Animationで作る高度なグラフィックス

スピーカー:Tim Oliverさん

Q “CoreAnimator(ツール)とXcodeの連携はコピペのみ?”

A “Yes”

何度もコピペとビルドが発生して大変ではともお聞きしてみましたが
あまり問題になっていないようでした。
微調整したいときは実機の前にPlaygroundで確認すればいいようです。

ただデザイナーと分業する場合を想像すると、
デザイナーがツールでアニメーションを変更して、
プログラマーがコピペで組み込みするのは辛い気がするので分業の事例があれば知りたいなと思っていたら
質問を聞かれていた@ka2nさんがAfterEffectのデータをJSONとして出力し、
JSONをappで読んでCore Animationで再生している、という事例を教えてくださいました。

コードとアニメーション(データ)が分離できてて素晴らしかったです!

ライブラリの開発

スピーカー:Jeff Huiさん

ライブラリのリリース作業の自動化についてお聞きして
Nimbleのリリース用スクリプトを教えていただきました。
https://github.com/Quick/Nimble/blob/master/script/release

恥ずかしい話ですが以前、公開しているライブラリでpodspecのバージョン変更を忘れたままバージョンをリリース†してCocoapodsへのpuhsも忘れしまったことがありました。
その後に同種のスクリプトを書いたわけですが、
これを知ってたら書かなくて済んだのに…と思いました。

これからライブラリを作る方は参考になると思います!

† セッション中のスライドにもあったと思いますが、CocoaPodsに対応している場合は下記の定型処理が必要になります。

  1. podsecというファイルにバージョン番号を記載する
  2. githubにリリースを作る
  3. > pod trunk push

Protocol-Oriented Programming in Networking

スピーカー:Yosuke Ishikawaさん

Himotokiとの連携は狙っていたのかお聞きしました。
偶然とのことです。

先月初めてAPIKit(とHimotoki)を触って、すごく綺麗に書けたので
元々Himotokiに繋ぐことも視野に入れて開発されたのかなぁと
思ってましたが違いました😅

他の方の質問ですが、Swiftの勉強はNatashさんの記事や
Ikeshoさんを始めとしたOSSコードなどを読んだりしているそうです。

Natasha The Robot

ちなみにこれも偶然ですが先月、今日のセッションで紹介されていた
APIKit + Himotoki + RxSwiftの組み合わせを使って
Qiitaクライアントアプリを作ってストアに申請しました。

Ishikawaさんがライブコーディングされていたように流れるように素早く書けましたので
RxSwift(もちろんAPIKit + Himotokiも!)を使ったことがない方は是非試してみてください!

Android開発入門 with Kotlin

環境のセットアップ

Android Studioにプラグインを入れて開発します。

  1. Android Studioのインストール
    公式サイトに従って入れます。
    迷うのはどのJDKのバージョンを入れるかぐらいです。
    推奨されているバージョンを選択するのがいいと思います。

  2. プラグインのインストール
    Android Studio > Preferences > Plugins > Install Jetbrains Plugin > Kotlin
    Android Studio > Preferences > Plugins > Install Jetbrains Plugin > Kotlin Extensions for Android
    インストール後にAndroid Stdioを再起動すると有効になります。

Extensionはオプションですが、入れると記述量が減って楽になります。
具体的にはfindViewByIdを書く必要がなくなります。

// Extension導入前
var view = findViewById(R.id.hoge)
view.title = "sample"

// Extension導入後
hoge.title = "sample"

プロジェクトのセットアップ

  1. プロジェクトを作成

  2. JavaからKotlinへ変換
    Code > Convert Java File to Kotlin File

  3. プロジェクトの変換
    Tool > Kotlin > Configure Kotlin in Project

ActivityとFragment

UIの名称

iOSのあのUIはAndroidでいうと何?

iOS Android 1 2 説明
UINavigationBar ToolBar(App Bar) 上部のバー。ActionBarは古いみたいです。
Slide Menu NavigationDrawer スライドして出てくるメニュー
UITableView ListView RecyclerView カスタマイズするならRecyclerViewがおすすめ。
UIImageView ImageView
WKWebView WebView

Adding the App Bar

ライブラリ

Picasso

画像の取得からキャッシュまで。
Glideというのもあるみたいです。

OkHttp

通信ライブラリ。Volleyもあるけど個人的にはOkHttpの方が使いやすいです。

マテリアルデザイン

Android Design Support Libraryを使うと楽ができます。
build.gradleに下記を追加することで導入できます。

compile 'com.android.support:design:23.1.1'

プロジェクト作成時に選ぶテンプレートによっては最初から追加されていることもあります。

素材

  1. Material icons
    Googleが公開しているアイコンセット。
    SVG/PNG/ICON FONTの3種類が用意されています。

zsh設定

Mac OS Xのクリーンインストールをしたついでにzsh環境を1から整理しているのでメモ。

作業メモです。固まったら整理します。

zshの基本設定

Preztoにお任せ。

$ zsh
$ git clone --recursive https://github.com/sorin-ionescu/prezto.git "${ZDOTDIR:-$HOME}/.zprezto"

$ setopt EXTENDED_GLOB
for rcfile in "${ZDOTDIR:-$HOME}"/.zprezto/runcoms/^README.md(.N); do
ln -s "$rcfile" "${ZDOTDIR:-$HOME}/.${rcfile:t}"
done
$ chsh -s /bin/zsh

Gitブランチ表示

.zpreztorcを編集

zstyle ':prezto:load' pmodule \  
'environment' \
'terminal' \
'editor' \
'history' \
'directory' \
'spectrum' \
'utility' \
'completion' \
'git' \ #追加
'prompt'

percol

pecoにしようとも思ったけど変更せず。

sudo pip install percol

Emacsライクなキーバインドが使えるように設定

$HOME/.percol.d/rc.pyに追記。

percol.import_keymap({
"C-h" : lambda percol: percol.command.delete_backward_char(),
"C-d" : lambda percol: percol.command.delete_forward_char(),
"C-k" : lambda percol: percol.command.kill_end_of_line(),
"C-y" : lambda percol: percol.command.yank(),
"C-a" : lambda percol: percol.command.beginning_of_line(),
"C-e" : lambda percol: percol.command.end_of_line(),
"C-b" : lambda percol: percol.command.backward_char(),
"C-f" : lambda percol: percol.command.forward_char(),
"C-n" : lambda percol: percol.command.select_next(),
"C-p" : lambda percol: percol.command.select_previous(),
"C-v" : lambda percol: percol.command.select_next_page(),
"M-v" : lambda percol: percol.command.select_previous_page(),
"M-<" : lambda percol: percol.command.select_top(),
"M->" : lambda percol: percol.command.select_bottom(),
"C-m" : lambda percol: percol.finish(),
"C-j" : lambda percol: percol.finish(),
"C-g" : lambda percol: percol.cancel(),
})

zshのコマンド履歴をpercolで絞り込む

.zshrcに追記。
Ctrl+Rでコマンド履歴が検索できて便利。

function exists { which $1 &> /dev/null }

if exists percol; then
function percol_select_history() {
local tac
exists gtac && tac="gtac" || { exists tac && tac="tac" || { tac="tail -r" } }
BUFFER=$(history -n 1 | eval $tac | percol --query "$LBUFFER")
CURSOR=$#BUFFER # move cursor
zle -R -c # refresh
}

zle -N percol_select_history
bindkey '^R' percol_select_history
fi

参考:404 Engineer Logs -ライフチェンジングなpercolとautojumpの紹介

ディレクトリチェンジ

これまでautojumpを使っていたけどpercolにお任せすることにしました。

# cd 履歴を記録
typeset -U chpwd_functions
CD_HISTORY_FILE=${HOME}/.cd_history_file # cd 履歴の記録先ファイル
function chpwd_record_history() {
echo $PWD >> ${CD_HISTORY_FILE}
}
chpwd_functions=($chpwd_functions chpwd_record_history)

# percol を使って cd 履歴の中からディレクトリを選択
# 過去の訪問回数が多いほど選択候補の上に来る
function percol_get_destination_from_history() {
sort ${CD_HISTORY_FILE} | uniq -c | sort -r | \
sed -e 's/^[ ]*[0-9]*[ ]*//' | \
sed -e s"/^${HOME//\//\\/}/~/" | \
percol | xargs echo
}

# percol を使って cd 履歴の中からディレクトリを選択し cd するウィジェット
function percol_cd_history() {
local destination=$(percol_get_destination_from_history)
[ -n $destination ] && cd ${destination/#\~/${HOME}}
zle reset-prompt
}
zle -N percol_cd_history

# percol を使って cd 履歴の中からディレクトリを選択し,現在のカーソル位置に挿入するウィジェット
function percol_insert_history() {
local destination=$(percol_get_destination_from_history)
if [ $? -eq 0 ]; then
local new_left="${LBUFFER} ${destination} "
BUFFER=${new_left}${RBUFFER}
CURSOR=${#new_left}
fi
zle reset-prompt
}
zle -N percol_insert_history

# C-j C-j でディレクトリに cd
# C-j C-i でディレクトリを挿入
bindkey '^j^j' percol_cd_history
bindkey '^j^i' percol_insert_history

参考:Slip Ahead Logging - percol で z / autojump のようにディレクトリ高速ジャンプ

ショートカット追加

tvOS Simulator メモ

Appleの9/10のイベントでtvOSが発表され、AppleTV向けアプリの開発ができるようになりました。

試しに触ってみて気になったことをメモしていきます。

  1. Simulatorの操作方法
    メニュー Hardware > Show Apple TV Remote でリモコンが表示されます。
    optionキーを押しながらマウス操作をすることで
    リモコンのタッチ操作をシミュレートしてくれるようです。

githubで2段階認証を設定したときにコンソールからHTTPSでアクセスする方法

githubで2段階認証を設定したときにコンソールからHTTPSでアクセスする方法。

  1. Personal access tokenを作成する
    アカウント設定ページ からPersonal access tokenを作成する。

  2. .netrc に記入する

machine github.com
login YOUR_ID
password YOUR_PERSONAL_ACCESS_TOKEN

これでID/PASSを聞かれなくなります。
SSHもいいですけどこっちの方が手軽です。