くま's Tech系Blog

基本的には技術で学んだことを書き留めようと思います。雑談もやるかもね!

kotlinのフォルダ名について

小ネタです

val binding: ActivityTaskEditBinding = DataBindingUtil.setContentView(this, R.layout.activity_task_edit)
val editViewModel = ViewModelProviders.of(this).get(EditViewModel::class.java)
binding.editViewModel = editViewModel

上記ソースコードbinding.editViewModel = editViewModelで下記エラーが発生しました

Cannot access class 'ViewModel.EditViewModel'. Check your module classpath for missing or conflicting dependencies

なんだろうと思いながら、調べてみたら単純なミスでした・・

Java Naming Conventionsによるとフォルダ名はall-lowercase ASCII letters(全て小文字のASCII文字)にしないといけないようです

今回私はViewModelと言うフォルダ名にしていたので、エラーが発生していたようです

そこで、フォルダ名を'viewmodelに修正するとうまく動きました

Kotlinのコーディング規約には載ってなかったみたいでしたが、載せて欲しいですね(見落としている可能性はあるので、そのときはコメントください!!)

ドキュメントは普段からチェックするべきですね

参照

Java Naming Conventions

Kotlinコーディング規約

Flutterの環境構築【mac編】

今回はFlutterの環境構築について書いていきます

FlutterはiOSAndroid両方ファイルを分けずにアプリを作れるクロスプラットフォームの言語です

少し先に使うことになりそうなので早めに学ぼうと思い、とりあえず環境構築から始めようと思います

公式ドキュメントには英語ですが、手順が載っているので基本的にはその通りやればうまくいくはずです!!

Flutterのインストール

まずはFlutterのインストールを行います

公式からFlutterをダウンロードします

f:id:kumaskun:20200504193307p:plain

ファイル解凍してコマンドのPATHを通す

ダウンロードまで完了したら、ファイル解凍してコマンドのPATHを通します

まずは、プロジェクトのフォルダを作りましょう

$ mkdir ~/flutterTest
$ cd ~/flutterTest

プロジェクトフォルダを作成したら、ダウンロードファイルを解凍し、パスを通します

$ unzip ~/Downloads/flutter_macos_v1.12.13+hotfix.9-stable.zip

## コマンドのパスを永続的にPATHへ通す設定
$ echo 'export PATH="$PATH:`pwd`/flutter/bin"' >> ~/.bash_profile
$ source ~/.bash_profile

これでFlutter関連のコマンドが使えるようになったはずです

確認のためにFlutterコマンドを実行してみてください

$ flutter

ヘルプが表示されれば、うまく構築できいます

Flutterの依存関係の確認

パスを通すところまででコマンドが使えるようになったので、次はAndroidiOSで開発できる環境を整えます

開発できる環境が準備できているのかはflutter doctorコマンドで確認できます

$ flutter doctor

実行すると下記のような結果が表示されます

Doctor summary (to see all details, run flutter doctor -v):
[✓] Flutter (Channel stable, v1.12.13+hotfix.9, on Mac OS X 10.14.6 18G103, locale ja-JP)
 
[✓] Android toolchain - develop for Android devices (Android SDK version 29.0.3)
[!] Xcode - develop for iOS and macOS
    ✗ Xcode installation is incomplete; a full installation is necessary for iOS development.
      Download at: https://developer.apple.com/xcode/download/
      Or install Xcode via the App Store.
      Once installed, run:
        sudo xcode-select --switch /Applications/Xcode.app/Contents/Developer
        sudo xcodebuild -runFirstLaunch
[!] Android Studio (version 3.6)
    ✗ Flutter plugin not installed; this adds Flutter specific functionality.
    ✗ Dart plugin not installed; this adds Dart specific functionality.
[!] VS Code (version 1.44.2)
    ✗ Flutter extension not installed; install from
      https://marketplace.visualstudio.com/items?itemName=Dart-Code.flutter
[!] Connected device
    ! No devices available

チェックが入っている箇所は準備ができていて、✖️がついている箇所はこれから準備が必要な箇所です

Flutter (Channel stable, v1.12.13+hotfix.9, on Mac OS X 10.14.6 18G103, locale ja-JP)以外を見ていきましょう

Android toolchain

SDK Managerが入っているかを確認しています

Android Studioをインストールした上で、Android StudioSDK Manager→Android9をダウンロードしてください

そして下記コマンドを実行すれば解消されるはずです

$ flutter doctor --android-licenses

承認するかを聞かれるのでyを入力すれば大丈夫です

また、Java8でないとうまくいかないようなので、そこも考慮してください

Xcode - develop for iOS and macOS

Xcodeがインストールされているかの確認です

ただ、今回はインストールしていても✖️になっていました

そこで、メッセージに書かれていた下記コマンドを実行することで解決しました

$ sudo xcode-select --switch /Applications/Xcode.app/Contents/Developer
$  sudo xcodebuild -runFirstLaunch

Xcodeのインストールパスを指定して、セットアップツールを実行するコマンドです

Android Studio (version 3.6)

Android StudioでFlutterとDartプラグインをインストールすれば良さそうです

Android Studio > Preferences > Plugins -> DartFlutterをインストール

次にライセンスの解決を行います。

$ flutter doctor --android-licenses

VS Code (version 1.44.2)

Visual Studio Code拡張機能FlutterDartをインストールする必要があるので、インストールしてください

FlutterDartと検索すれば表示されるはずです

f:id:kumaskun:20200506211746p:plain

No devices availableに関しては実機につながない場合は無視して大丈夫です

または実機につないでテストをすれば解消されますので、プロジェクトを作成してから対応すればいいと思います

ここまででNo devices available以外の✖️が解消されれば環境構築は終了です

以外と簡単でかつ、開発者に親切だと感じました

参照

公式ドキュメント

[Flutter] Mac にインストールして開発環境を構築する

docker コマンド一覧

個人的によく使うやつをまとめます

docker-compose build

docker-compose.ymlの内容に基づいてイメージを作成するコマンド

$ docker-compose build

docker-compose up

docker-compose.ymlに書かれた依存関係をもとに、イメージを元にしてコンテナの作成と起動してくれるコマンド

イメージはdocker-compose buildで作成する必要があります。

$ docker-compose up

docker-compose down

docker-compose.ymlに書かれている内容をみてコンテナを停止するコマンド。また、そのコンテナとネットワークの削除もしてくれます。

--rmi allオプションをつけると、コンテナだけでなく、もとになったイメージも削除してくれます。

$ docker-compose down

docker ps

現在起動しているコンテナの一覧を見るコマンド

-aオプションをつけると、起動していなものも確認できます。

$ docker ps

docker images

Dockerfileを元に作成したイメージの一覧を表示してくれるコマンド

$ docker images

docker logs (コンテナのID)

docker psコマンドで確認したコンテナIDをもとに、ログを確認するコマンド

$ docker logs (コンテナID)

docker exec -it コンテナ名 bash

dockerコンテナに入って作業をするコマンド

コンテナ名はdocker psコマンドで確認できます

$ docker exec -it (コンテナ名) bash

docker rm

コンテナを削除するコマンド

$ docker rm (コンテナ名orコンテナID)

docker rmi

dockerイメージを削除するコマンド

イメージIDはdocker imagesコマンドで確認できます

$ docker rmi イメージID 

学んだものがあれば随時追加していきたいと思います!!

extensionとprotocolについて

今回はiOSでよく使うextensionとprotocolについて記載しようと思います

extensionについて

Swiftでは既存のStringやArrayなど提供されているクラス(既存のクラス)に自分専用のメソッドを追加できます。

Objective-Cにはカテゴリという、既存クラスにメソッドを追加できる機能がありますが、カテゴリで追加できるのはクラスのみに限定されています。

なので、これはかなり便利ですね。たまにこの機能欲しいってなったときにStringやArrayをいじることなく追加ができてしまいます。

例えを見ていきましょう!!

import Foundation
extension String {
 //メンバ変数のhogeを追加
    func helloWorld()->String{
        return "Hello World!!";
    }
}

上記のhelloWorld関数を追加するだけでString型の処理でhelloWorld関数を使えます

定義の仕方は、既存のファイルに追加や新しいファイルを作成するという手順です。

protocolについて

protocolは色んな言語でいうインターフェースです。

つまり、継承したクラスで実装すべきプロパティやメソッドを宣言する為に利用します。

Javaを使っていた自分としてはインターフェースと知ってから一気にイメージが湧きました。

使い方としては下記のようなプロトコルを用意します。

protocol TestProtocol
{
    var Test:String {get set}
    
    func  Test() -> Void
}

そして、下記のように継承・プロトコル実装します。

class Test : TestProtocol
{
    var test:String!
    
    // 実装しないとエラーになる
    var Test1: String
    {
        get
        {
            return self.test
        }
        set
        {
            self.test = newValue
        }
    }
    
    // 実装しないとエラーになる
    func  Test() -> Void{
        print(self.Test1)
    }
}

こうすることで、プロトコルで宣言されたメソッドを継承クラスで利用できます。

var test1:TestProtocol= Test()

test1.Test1 = "テスト"
test1.Test() // テスト

その他に、viewControllerでも使うパターンがあります。

class TestViewController: UIViewController { 
    self.tableView.delegate = self 
    self.tableView.dataSource = self 
    self.webView.delegate = self 
} 

extension TestViewController: UITableViewDataSource {
    ... 
} 

extension TestViewController: UIWebViewDelegate { 
    ... 
}

このようにすると、どのパターンでどんな処理を行うのか一気に見やすくなります。

getter/setterとプロトコルで定義したメソッドは継承先で記述しないとエラーになります。(どの言語でも同じだとは思いますが)

依存性を減らすことができるので、柔軟性が高くて抽象化できるのがメリットだと思います。

extensionとprotocolの組み合わせ

最後に、extensionとprotocolを組み合わせるパターンを紹介します。

ここでは動物プロトコルを定義しています。

protocol Animal {
    var name: String { get }
    func bark() -> String
}

動物インターフェースを下記のように作成します。

struct Cat: Animal {
    let name = "ぽち"
    func bark() -> String {
        return "ワン"
    }
}

let cat = Cat()
cat.name          // "ぽち"
cat.bark()        // "ワン"

動物インターフェースではProtocol で宣言した変数・関数を実装すれば犬がの名前と鳴き声を設定できます。

ただ毎回鳴き声を実装するのが大変な場合があります。基本的に動物が鳴かないのであればデフォルトで空白を入れればいいですね。

extension Animal {
    func bark() -> String {
        return ""
    }
}

このようにextensionとprotocolを組み合わせることで冗長な処理を書かなくて済むことが多いです。

基本的な内容になりましたが、よく使うと思うので参考にしてみてください

参照

SwiftのProtocol(プロトコル)とextension(エクステンション)

【Swift】Extensionしてますか?

Swiftのif letについて

少し間が空いてしまいました・・・・orz

これからは小まめに記事投稿していきますので、よろしくお願いします!!

今回はSwiftのif let という書き方についてです

最近、本格的にSwiftを使い始めたのですが、違和感のある書き方でしたので調べてみました

if letについて

if letは変数の中身がnilかどうかを判定し、nilでなければ処理を行います

var age: Int?
age = 24

if let ageTest = age {
    print(ageTest)
}

上記サンプルではageが24のためageTestnilではないので、24が表示されます(ageTestはif文の中で使う変数だと思っていてください)

var age: Int?

if let ageTest = age {
    print(ageTest)
}

この場合は、agenilのため処理は行われません。

こうするとnilでアプリが落ちるのを防ぐことができます

guard letについて

if letとは別にguard letというものがあります。どんな違いがあるのでしょう

guard letの場合は、条件を満たさない場合にreturnbreakthrowなど、スコープを抜けるコードがないとエラーになるという違いがあります

var age: Int?

guard let ageTest = age else {
    // nilの場合の処理
    return
}

nilの時にこれ以上処理を進めたくない場合はguard letを使用します

こうすることで、想定外の値で処理を続行してしまうというミスがなくなります。

一般的にはnilの場合に、別の処理を行うというのはあまりよくない処理だと思うので、guard letの方が使う気がします。

場合によって、if letguard letをうまく使い分けることでExceptionを発生させないようにできると思います

参照

Swiftでif let文を使って出来ることとguard letの使い分けに関して

git pushを取り消そう

久しぶりの投稿になります!

技術書典の執筆やら、LTの資料作成やらでなかなか更新できずにいました。(技術書典中止らしい・・・・)

今回はそんな中、焦ってやってしまったpushを取り消す方法です。

①Revert

変更を打ち消すコミットを作成するという一番安心なやり方です。

# 直前のコミットの内容を打ち消すためのコミットを行う。コミットIDでも可
$ git revert HEAD
or
 $ git revert [ コミットID ]

# 打ち消したコミットをプッシュする
$ git push origin master

ただ、コミット履歴が残ってしまうので、そこが難点かと。

あと、こっそり消してしまいたいときってありますよね笑

そんな時は次のやり方がオススメです!

②git reset

resetを使うとコミット履歴を残さず、元に戻すことができます。

これを使うときは他の人がみていない場所でしれっと行いましょう笑

# 直前のコミットを取り消す。コミットIDでも可
$ git reset --soft HEAD^
or
$ git reset --hard [ コミットID ]

# 強制的プッシュ
$ git push -f origin master

強制プッシュしないと自分が修正しているリポジトリの歴史を書き換えようとするためエラーが発生するので注意が必要です。

今回はresetを使ってことなきをえました。

ここで補足です

$ git reset –soft→commitのみ取り消す

$ git reset –hard→commit・add・ソースの変更を取り消す

$ reset –mixed→commitとaddのみを取り消す

また、HEADだと直前のコミットになりますが、HEAD^2などで2つ前のコミットというように数字指定もできます。

皆さんも快適なGitライフを!

参照

git pushを取り消す2つの方法

SDKのライセンスについて

久々にAndroidネタです!

PCをMacに変えて、プロジェクトをGithubからクローンしていよいよ開発かと思ったら、ビルドでエラーが。。。。

内容を見てみると下記のようなエラーが出ていました。

Failed to install the following Android SDK packages as some licences have not been accepted.
     platforms;android-27 Android SDK Platform 27
     build-tools;27.0.3 Android SDK Build-Tools 27.0.3
  To build this project, accept the SDK license agreements and install the missing components using the Android Studio SDK Manager.

あれれー、どういうことなんだと思っているとさらに悲劇が。。。

appフォルダ配下が開かないのです。

開けるのはbuild.gradleくらいで謎が深まりました。

調べてみると、ライセンスがないからエラーが発生し、ライセンスを許可すると解決しそうです。

Macの場合は下記コマンドで解決するみたいなので実行すると解決しました。

export JAVA_HOME=/Applications/Android\ Studio.app/Contents/jre/jdk/Contents/Home
yes | ~/Library/Android/sdk/tools/bin/sdkmanager --licenses

こんなことになった原因は想定では下記のどちらかと考えています。

①最新のAndroidStudioを使っているので、SDKのバージョンが古すぎる?→プロジェクト見れないもんなのか

Windowsで作成したプロジェクトなので、SDKのパスが正しくない?→コマンドで直るもんなのか

というようにまだ曖昧なので、他の原因だよともし知っている方がいれば教えていただきたいです。

もう少し気になるので、調べてみたいと思います。

とりあえず直りはしたので、快適なAndroidライフを楽しみたいと思います。

参照

stackoverflow

sdkmanager(公式ドキュメント)

<p>と<span>の違い

pタグだと空白が多いなあと思い、spanタグに変えると空白がないので、気になって調べました。

pタグ

pタグは簡単にいうと段落を表すタグです。

改行された後に1行空白が入るのが特徴です。

HTMLリファレンスの例が参考になると思います。

f:id:kumaskun:20200113233529p:plain

今思えば、だから変な空白(空行)が入っていたんですね!

spanタグ

一方、spanタグは特に何かを表すタグではなく、どこか一部のデザインを変えたいときに使います。

一般的にspanタグでは文章の一部を変更したいときに使います。(文章の一部の色を変えたいなど)

さらに、pタグと違い、空白はありません。

私が開発していたときにはspanを使えばよかったのです。

これが大まかな違いですが、なんか味気ないなあと思っちゃったので、少し関連するdivタグも絡めて書きたいと思います。

ついでにdivタグ

divタグは段落を表すタグです。

特徴としては、空白は入らないが、前後に改行が入るということです。(下記が例です)

<div>aaa</div><div>bbb</div><div>ccc</div>

// このように表示される
aaa
bbb
ccc

divタグとspanタグには大きな違いがあります。

それは、divタグはdisplay: blockに対して、spanタグはdisplay: inlineなんです。

divタグは高さや幅が決められて、spanタグは設定できません。

これで、どこでどのタグを使うか少しはわかったと思います。

今まで、感覚でやってきた部分もあるので、調べてみて使いどころが少しは理解できた気がします。

参照

divとspanの違いは?使い分け方を初心者向けに解説

pタグ: 段落要素(HTMLリファレンス)