前提条件
Mac: macOS Catalina 10.15.6
Xcode: Version 12.4 (12D4e)
これで直る場合があります
Xcode を終了した後、以下のディレクトリを削除すると直る場合があります。
~/Library/Saved Application State/com.apple.dt.Xcode.savedState/
参考) Stack Overflow のこの回答
最後に
これで直れば幸いです!
Mac: macOS Catalina 10.15.6
Xcode: Version 12.4 (12D4e)
Xcode を終了した後、以下のディレクトリを削除すると直る場合があります。
~/Library/Saved Application State/com.apple.dt.Xcode.savedState/
参考) Stack Overflow のこの回答
これで直れば幸いです!
結論から言うと、Protocol での記述は weak
は特に気にしなくてよさそうです。
Protocol では実クラスのプロパティが weak
か strong
かには関心がありません。
Swift において、weak var
のプロパティを持つプロトコルを定義したくなった場合、
本ポストのタイトルのようなエラーが出ると思います。
例えば delegate を持つ Protocol を定義したい場合があると思います。
protocol BProtocol {
weak var delegate: AProtocol? { get set }
}
実クラスでは delegate は weak var
で宣言しないと循環参照となってしまいます。
ですが、Protocol での記述は weak
は気にしなくてよさそうです。
簡単なプログラムで検証します。
Mac: macOS Catalina 10.15.6
Xcode: Version 12.4 (12D4e)
先に言ったように、Protocol での記述は weak
は特に気にしなくてよさそうです。
以下のようなサンプルプログラムで検証します。
protocol AProtocol: AnyObject {
func doSometing()
}
final class A: NSObject, AProtocol {
var b: B?
func raiseB() -> B? {
b = B()
b?.delegate = self
return b
}
func doSometing() {}
}
protocol BProtocol {
var delegate: AProtocol? { get set }
}
final class B: BProtocol {
weak var delegate: AProtocol? // <- weak を外すと循環参照になります
func printDelegate() {
print("delegate: \(delegate)")
}
}
ここで注目したいのが class B
が持っている delegate です。
delegate プロパティはAProtocol に準拠したクラスの変数です。
BProtocol では delegate プロパティを weak 宣言していません(できません)。
が、実クラスのBでは weak 宣言しています。
最も単純なコードだと、A
のインスタンスがnil になった時点で、
Bが保持している delegate
プロパティも weak
であれば、 nil になるはるはずです。
以下のようなコードを書いたとします。
「コードX」とします。
// コードX
var a: A? = A()
let b = a?.raiseB()
print("最初のprint")
b?.printDelegate()
a = nil
print("二番目のprint")
b?.printDelegate()
a = nil を実行された時点で、b が保持している delegate プロパティも nil になるはずです。
実際にそのようになります。
最初のprint
delegate: Optional(<HogeApp.A: 0x6000010f4320>)
二番目のprint
delegate: nil
一方、実クラスのB の delegate から weak を外してみます。
BProtocol では delegate プロパティを weak 宣言していません(できません)。
final class B: BProtocol {
var delegate: AProtocol?
... 略 ...
}
これで「コードX」を実行します。
すると以下のようになります。
最初のprint
delegate: Optional(<HogeApp.A: 0x6000018b4530>)
二番目のprint
delegate: Optional(<HogeApp.A: 0x6000018b4530>)
つまり、Protocol では実クラスが weak
か strong
かには関心がない
ということになります。
Swift evolution に以下のプロポーザルがあります。
0186-remove-ownership-keyword-support-in-protocols.md
Protocol は weak だろうが strong だろうが宣言できるが、
実クラスではそれに従う必要はないため、混乱を招いてしまう。
そのため、そもそもProtocol ではそれらの宣言をできないようにするべきだ、と書かれています。
というわけで Protocol は所有権に関心がないということが分かりました。
以上です。
お疲れ様でした!
まずこれの違いについて確認します。
ざっくりと言えば、
ということかなと思います。
具体的に言うと、Helvetica や Times New Roman が書体です。
Helvetica Bold 50px や Times New Roman Regular 10px など、
大きさや線の太さなど表示・印字するときに必要な情報まで含めたのがフォントとなります。
他のブログを見ると
現在だとほぼ同義のように使われているため、(書体の専門家でなければ)それぞれ言い換えても全然伝わるでしょう、
と言う感じのようですね。
上記のように、現在だと「書体」との境界線が曖昧になりつつありますが、
昔ははっきりと使い分けがなされていたようです。
フォントとはその昔「活字印刷する際に利用する活字たちの一揃い」の事を指していたようです。
印刷するときには活字たちを一文字ずつ手作業で並べる必要があったと思いますが、
その際文字の大きさが違っていると、正しいものに入れ替えをする必要があり労力がかかりますね。
印刷する時にフォントを同じものにするには今よりはるかに注意が必要だったと思うので、
きちんと使い分けられていたのだと思います。
分類方法は特に定まったものがなさそうなため、以降の分類は一例として捉えてもらえれば。
欧文書体はまず大きく分けて以下の4つに分けることができそうです。
参考: Fonts.com: Type Classifications
セリフ(Serif)とは、文字の端にあるひげのような装飾です。
サンセリフ(Sans-Serif)のサン(Sans)はフランス語で「無い」という意味になります。
ですのでサンセリフはセリフがない書体という意味になります。
では以下、先述の4つの分類について更に細かく分類します。
上述の通り、文字の端にひげのような装飾のある書体です。
和文書体で言うと明朝体に近いです。
4つに分類する場合、例えば以下のような分類ができます。
1.ヴェネチアン・ローマン から3.モダン・ローマンに向かって年代が新しくなります。
セリフ体の詳細な解説は以下のサイトたちがとても参考になりそうです。
こちらは文字の端にひげがない書体となります。
和文書体で言うとゴシック体に近いです。
4つに分類する場合、例えば以下のような分類ができます。
サンセリフ体の詳細な解説は以下のサイトたちがとても参考になりそうです。
こちらは手書きに似せたフォントになります。
2つに分類する場合、例えば以下のような分類ができます。
読みづらくはあるので、地の文で使うことは少なそうで、
表彰状や招待状などエレガントで高級な世界観を表現するときによく使われるようです。
ちなみにとても荘厳な趣のあるブラックレターという書体も、スクリプト体の一部です。
スクリプト体の詳細な解説は以下のサイトたちがとても参考になりそうです。
看板や見出しなどに使用される、印象的なフォント。
インライン、グランジ、ステンシルなど様々な形態が内包されています。
などがあります。
多様なため一括りに語れませんが、
インパクトを与えたいキャッチコピーなどに使うのがよさそうです。
可読性はよくないと思うので、通常は本文に使うのは避けた方がいいかもしれません。
ざっくりとまとめてみました。
ロゴやWebのデザインに活かせればと思います!
Quick is a behavior-driven development framework for Swift and Objective-C. Inspired by RSpec, Specta, and Ginkgo.
https://github.com/Quick/Quick#readme
振る舞い駆動開発のためのSwift や Objective-C 用のテストフレームワークです。
振る舞い駆動開発とは何ぞや、ということについては上のリンクの他、 本ブログの以下ポストなどを参照していただければと思います。 Web-y.dev: 振る舞い駆動開発(Behavior-Driven Development)とは
公式ドキュメントがあります。
https://github.com/Quick/Quick/blob/main/Documentation/en-us/InstallingQuick.md
SwiftPM でもインストール可能でしたが、動作が不安定だった
(失敗したテストを再度回しても何のテストも実行されないなど)ので、
個人的には、SwiftPM以外の方法でインストールするのがいいかなと思います。
Web-y.dev: 一つ一つの振る舞いテストのお作法 に書いた通り、
一つ一つの振る舞いテストは以下の3ステップをひとまとまりとして記述していきます。
Quick はこの3ステップを、人が読みやすい形で記述することをサポートしてくれる
フレームワークとなっています。
Quick でテストを書くときのお作法として Arrange, Act, Assert の手順が挙げられていますが、
上記の Given, When, Then と同義かなと思います。
https://github.com/Quick/Quick/blob/main/Documentation/ja/ArrangeActAssert.md#effective-tests-using-xctest-arrange-act-and-assert
Git に公式ドキュメントがあります。
https://github.com/Quick/Quick/blob/main/Documentation/ja/QuickExamplesAndGroups.md
そちらを見てもらうのが早そうですが、イメージだけ書いておきます。
import Quick
import Nimble
@testable import HogeApp
class HogeAppSpec: QuickSpec {
override func spec() {
describe("メイン画面") {
var vc: MainVC!
beforeEach {
vc = MainVC()
vc.load()
}
it("メインコンテンツが表示される") {
expect(vc.collectionView.cellForItem(at: indexPath) as? ContentCell)
.toEventuallyNot(beNil()) // ここは Nimble で書ける
}
}
describe("アカウント画面") {
beforeEach {
// 下2つのcontext の事前準備の共通処理をここに書ける
}
context("ログインしている場合") {
it("アカウント情報が表示される") {
}
}
context("ログインしていない場合") {
it("ログイン画面が表示される") {
}
}
}
}
}
spec()
メソッドをオーバーライドし、その中でクロージャをネストさせてテストを書いていきます。
describe
もしくは context
内のクロージャで、
「Given: システムがこの状態の時(前提条件)」と「When: この動作をすると」まで記述します。
(describe
と context
に違いはなく、ただのエイリアスです)
it
内のクロージャで「Then: このような振る舞いをする」を記述します。
beforeEach
や afterEach
で共通の事前準備、後始末を書けます。
上記のテストコードを実行すると、以下の3つのテストケースが順番に実行されます。
テストファイルの上から実行されるのでは無く、テストケース名の辞書順に実行されます。
僕の思うメリットとデメリットは以下です。
describe
や context
で処理を共通化するため、ボイラーテンプレート的な事前準備などのコードを複数書かなくて済むdescribe
, context
, it
の組み合わせにより仕様書として読みやすい形になるdescribe
内のコードなんだっけ?と混乱しがちfunc
にテストを書かないため、ファイル内のテストケース一覧が参照できない注意しないとデメリットにあるようにけっこうスパゲッティコードになりがちかなと思います。
そのような場合、テストコードの設計見直しや、describe
や context
やテストファイルの分割などを検討するとよいのかなと思います。
銀の弾丸ではないので、本格導入する前に一度試してメリデメを把握するのがよいかと思います!
xdescribe
、xcontext
、xit
のように先頭に x
を付けると、
そのクロージャ内のテストを無効にできます。
fdescribe
、fcontext
、fit
のように先頭に f
を付けると、
そのクロージャ内のテストのみを有効にできます。
it
の内容がボイラーテンプレート的に同じような内容になる場合、
その部分も共通化することができます。
公式の説明はこちら。
https://github.com/Quick/Quick/blob/main/Documentation/en-us/SharedExamples.md
SharedExample という機構を使います。
以下のようなイメージで使います。
class HogeAppSpec: QuickSpec {
override func spec() {
describe("アカウント画面") {
context("ログインしている場合") {
itBehavesLike(HogeSharedExamplesConfiguration.accountViewExample) {[
HogeSharedExamplesConfiguration.faqKey: "ログインのFAQを表示"
]}
}
context("ログインしていない場合") {
itBehavesLike(HogeSharedExamplesConfiguration.accountViewExample) {[
HogeSharedExamplesConfiguration.faqKey: "ログインのFAQを表示"
]}
}
}
}
}
class HogeSharedExamplesConfiguration: QuickConfiguration {
static let accountViewExample = "アカウント画面"
static let faqKey = "faq"
override class func configure(_ configuration: Configuration) {
var faq: String!
sharedExamples(accountViewExample) { (sharedExampleContext: @escaping SharedExampleContext) in
it("情報が正しい") {
faq = sharedExampleContext()[faqKey] as? String
expect(faq).to(equal("ログインのFAQを表示"))
}
}
}
}
QuickConfiguration
を継承したクラスを作成し、共通する it
の処理を書いていきます。
で、テストする側は it
で呼び出すのでは無く、代わりに itBehavesLike
を使います。
テスト対象の値などを itBehavesLike
のクロージャ内に辞書形式で書き、SharedExample に渡します。
サンプルではString を渡していますが、それ以外の型ももちろん利用可能です。
SharedExample 側は sharedExampleContext()[キー名]
のような形で値を取り出し、
あとはそれを元にテストしていきます。
ちなみに、SharedExample 内には、以下のように it 以外も記述可能です。
class HogeSharedExamplesConfiguration: QuickConfiguration {
sharedExamples("hogeExample") { (sharedExampleContext: @escaping SharedExampleContext) in
beforeEach {
}
context("hogeContext") {
it("hogeIt") {
}
}
}
}
}
けっこうコストがかかる書き方のため、必要に応じて使うとよさそうですね!
Quick についてつらつらっと書いてみました。
本文に記した通り、銀の弾丸ではないと思うので、本格導入の前に一度試すのがよいのかなと思います。
他にもこんな便利な機能があるよ、というのがあればコメントに書いていただければと思います!
以上です。
お疲れ様でした!
テストコード。
開発期限が迫っているため書く余裕がない、ということはママあると思いますが、
個人的には書けるなら書いた方がいいかなと思っています。
テストを書ける状態のプロダクトコードになっていないなら、まずはリファクタから頑張る。。!
Baby-Steps で KAIZEN していくしか。。!
本ポストではテストコードを書くメリデメを含め、TDDの一流派のBDDについて書いていきます。
個人の見解ですが、以下のようなメリデメがあるのではと考えています。
短期的には成果が見えづらいため、焼畑的な開発を続けざるを得ない状況下においては、
取り入れるのが非常に難しいかなと思っています。
ですが長期的に見ると、低品質のコードや仕様の認識漏れやバグ修正などでの手戻りが減り、
スパゲッティコード化による属人化や開発速度の低下を防げるため、
プロダクト的にも、またもちろん精神衛生上にもとてもよいのではと思っています。
で、プロダクトコードを書いてからテストコードを書くのも速くていいですが、
可能であればテストコードを書いてからプロダクトコードを書いた方が品質が高くなるのでは
ないかと思っています。
プロダクトコードがある程度の品質で動いているなら
テストが書けない設計になっていても、多少サボってもいいと思ってしまうのが人間なのかなと🤔
もちろん、最初からテスタブルなコードを書けるなら順番はどちらでもいいと思います。
が、それなら最初からテストを書いた方が、リファクタによる手戻りの可能性は減りそうですね。
テストを書いてからプロダクトコードを書く開発手法をTest-Driven Development (TDD) と呼びます。
本ポストでは以下、TDDの一流派である Behavior-Driven Development (BDD) について
概要を書いていきます。
BDDはTDDの一流派ともいえますが、TDDに対し以下の実現のための原則や工夫が加えられています。
– テストを「振る舞い」(機能的な外部仕様)の記述に特化させる
– ユーザーの要求やアーキテクチャの設計仕様といった、より上位のインプットとTDDのテストにつながりを持たせる
https://www.atmarkit.co.jp/ait/articles/1403/05/news035_3.html
「コード自体の振る舞い」や「システム・アプリの振る舞い」に焦点を当てたテストを書いていくTDDの一流派です。
僕のイメージとしては、
ということを目指している開発手法、と捉えています。
目指しますが、個人的には、
ある程度以上複雑なアプリの場合、仕様を完璧に網羅するのは難しいと思うので、
コスパを鑑みた上である程度で妥協するのが現実的にはコスパがよいのではとも感じています。
特に動的なコンテンツ、インタラクティブなコンテンツは、
とかく考えうる仕様・条件・動きが膨大になりがちです。
妥協する場合、どの程度で妥協するかはチームやプロジェクト内で、
「価値のあるテストとは? 価値のないテストとは?」などについて話し合い、
最適な落とし所の認識を合わせる必要があるかと思います。
そもそも、振る舞い駆動開発(というより派生元のテスト駆動開発)は以下の3ステップの繰り返しで進めていきます。
Red では振る舞いテストを書きます。
システムがこの状態の時、この動作をすると、こう振る舞う、というテスト(つまり仕様)を書きます。
なので、ここではテストというよりは実質、仕様を書いていくという意識に近いかなと思います。
で、実装がまだないため、テスト実行すると必ずこけます。
テストがこけているのでIDEでは赤ポチがついているはずです。
なのでRed。
次にGreenです。
こけていたテスト(つまり仕様)を通すように実装をします。
実装が終わった後にテストを回すと、赤ポチが緑ポチになります。
なぜならテスト(つまり仕様)を満たすように実装したからです。
最後に、必要であれば実装をリファクタリングします。
これでおそらく、ある仕様を満たす最小限の実装ができたかと思います。
あとはこれの繰り返しです!
え、複数の出し分けの仕様があるのにこのままだと一つの条件しか考慮できておらず、マジックナンバーがある?
次のRed, Green, Refactor できれいに出し分け/リファクタすればいいでしょう!
こんな感じで、仕様を満たす最低限のロジックのみを書き、
それをテンポよく繰り返し改修していく。
仕様の解像度を徐々に上げていくような進め方。
それがBDD(TDD) かなと僕は捉えています。
一つ一つの振る舞いテストは以下の3つの手順で記述できると言われています。
Agile Allianceのメンバー Martin Fowler さんのブログより。
これらを1セットとして、一つ一つの振る舞いに対してのテストを記述できるはずです。
今ではテストを書かないとなんだか気持ち悪いと思えるようになりましたが、
当初はもちろん戸惑いました。
もちろんTDD/BDD が絶対正しいという訳ではなく、
コードの品質と、ある期間内での開発スピード感、どちらを重視するかによって
最適解は変わってくると思います。
以上、BDDについてでした.。
お疲れ様でした!
Xcode でビルドしようとした際にタイトルのエラーに遭遇したので対処法を書いていきます。
テストターゲットにCarthage で framework を追加しており、アプリをビルドしようとした際に遭遇しました。
Mac: macOS Catalina 10.15.6
Xcode: Version 12.4 (12D4e)
Carthage: 0.36.0 (後半で0.37.0 以降にアップデートします)
ビルド時に以下のようなエラーが出ました。
テキストに起こすと以下。
error: Building for iOS Simulator, but the linked framework 'Quick.framework' was built for iOS. (in target 'SampleApp02Tests' from project 'SampleApp02')
SampleApp02 というアプリなんですが、それのTestターゲットに
Quick.framework を追加した状態でのエラーです。
(このエラーメッセージはCarthage のバージョンで少し異なってくるかもしれません)
iOSシミュレータをビルドしているが、
リンクされているのはiOS用(=シミュレータ用ではない)のframeworkです、
と怒られています。
Stackoverflowに回答があります。
Build Settings
の Validate Workspace
の設定を一度 Yes
にし、その後 No
に変更すればOKです。
デフォルト表示は No
ですが、実際の挙動はどうやら Yes (Error)
となっているようです。
Yes
のままでもエラーは回避できますが、ビルド時にワーニングが出ます。
ただ、この対処法は少なくとも「フレームワークの検証をしない」という状態になるため、
将来的にはビルドできなくなる可能性も出てくるのかなと思います🤔
そもそも Validate Workspace が Yes (Error)
でエラーになるのは、
フレームワークの検証で引っかかっているからのようです。
どういうことかと言うと。
Carthage 0.36.0 で作成された framework は、
その中に実機用やシミュレータ用の複数のバイナリが含まれています。
それらが1つのframework として生成されます。
これはuniversal framework もしくは、より直感的に fat framework と呼ばれています。
fat framework のイメージは以下が非常に分かりやすいと思います。
Qiita: XCFrameworksに対応したCarthageを使ってみた CarthageがIntel Mac上でどのように動いていたか
そして、Xcode12.3 からはデフォルト(つまりValidate Workspaceが Yes(Error)
の状態)で
fat framework を弾くようになりました。
そのため、ビルドができなくなったようです。
ちなみにアプリのビルド時、Carthage の copy-frameworks スクリプトを実行していると思いますが、
そこでは fat framework を元に
という処理をしているようです。
fat framework が弾かれるようになった。
ではどうするか。
fat framework をやめ、XCFramework を使います。
XCFramework とは何か。
イメージを掴むには、中身を見るのが手っ取り早そうです。
このようにXCFramework の中には複数の framework が含まれています。
ios-arm64-armv7 がiOS用、ios-arm64_i386_x86_64-simulator がシミュレータ用のframework かな🤔
このXCFramework を、既存の framework の代わりにXcode に組み込むことで、
ビルド時にXcode が適切なアーキテクチャのframework を選択してリンクするようになります。
ということは先に述べた copy-frameworks スクリプトも不要になります🙌
主流になりそうだし使った方がよさそう、ということでCarthage でXCFramework を作ります!
そのためには Carthage 0.37.0 以降が必要なので準備しましょう。
準備できたらあとは --use-xcframeworks
オプションを付けて
carthage コマンドを打つだけです。
carthage update --use-xcframeworks --platform iOS
これ以降の導入手順は難しくないです。
DevelopersIO: [iOS] CarthageでもXCFrameworkが使いたい や
Qiita: XCFrameworksに対応したCarthageを使ってみた CarthageでXCFrameworksをビルドする
などが参考になりそうです。
以上です。
可能ならワークアラウンド的な方法ではなく根本的な対応をすると、
今後困る可能性が減りそうですね🙌
お疲れ様でした!
Carthage 0.38.0 をインストール しようとしたら、
既に0.37.0 が入っているしそれが最新だよと言われました。
$ brew upgrade carthage
Warning: carthage 0.37.0 already installed
Homebrew 自体のアップデートから Carthage をアップデートするまで
諸々対処したのでまとめます。
Mac: macOS Catalina 10.15.6
まずは Homebrew 本体をアップデート。brew update
コマンドを打ちます。
$ brew update
Error:
homebrew-core is a shallow clone.
homebrew-cask is a shallow clone.
To `brew update`, first run:
git -C /usr/local/Homebrew/Library/Taps/homebrew/homebrew-core fetch --unshallow
git -C /usr/local/Homebrew/Library/Taps/homebrew/homebrew-cask fetch --unshallow
These commands may take a few minutes to run due to the large size of the repositories.
This restriction has been made on GitHub's request because updating shallow
clones is an extremely expensive operation due to the tree layout and traffic of
Homebrew/homebrew-core and Homebrew/homebrew-cask. We don't do this for you
automatically to avoid repeatedly performing an expensive unshallow operation in
CI systems (which should instead be fixed to not use shallow clones). Sorry for
the inconvenience!
いきなり怒られました!🤯
brew update を実行するためにはまず以下のコマンドを打て、と言われています。
git -C /usr/local/Homebrew/Library/Taps/homebrew/homebrew-core fetch --unshallow
git -C /usr/local/Homebrew/Library/Taps/homebrew/homebrew-cask fetch --unshallow
その下に書かれているのは、意訳すると以下のような感じです。
GitHub の要請で shallow clone にしていました。 unshallow は時間などのコストがかかるため、CIで毎回自動実行されるとやばいことになるので、 手動で unshallow してもらってる状況です。 (というかそのような場合はshallow clone しないように修正すべきですね)
そもそも shallow clone とは🤔
古いコミットを切り捨ててgit clone する機能のようです。
公式ブログに説明がありました。
シャロークローンは、
https://github.blog/jp/2021-01-13-get-up-to-speed-with-partial-clone-and-shallow-clone/git clone
の--depth=<N>
パラメータを使って
コミット履歴を切り捨てます。
clone するのが早くなりそうなので一見良い機能に見えますが、そうでもなさそうです。
非常にピーキーな機能のようなので、日々の業務では積極的に採用しない方がよさそうですね。
これらの理由から、
https://github.blog/jp/2021-01-13-get-up-to-speed-with-partial-clone-and-shallow-clone/
その後すぐにリポジトリを削除するようなビルドのケースを除いて、
シャロークローンはお勧めしません。
シャロークローンからのフェッチは、
メリットよりもデメリットの方が大きくなることがあります。
Homebrew が指定した2つのコマンドを打ちます。
$ git -C /usr/local/Homebrew/Library/Taps/homebrew/homebrew-core fetch --unshallow
略
From https://github.com/Homebrew/homebrew-core
fe112d0e1b..259931b1d2 master -> origin/master
$ git -C /usr/local/Homebrew/Library/Taps/homebrew/homebrew-cask fetch --unshallow
略
From https://github.com/Homebrew/homebrew-cask
05081b9fd0..2e49b12876 master -> origin/master
数分待てば完了します。
$ brew update
略
You have 12 outdated formulae and 2 outdated casks installed.
You can upgrade them with brew upgrade
or list them with brew outdated.
正常に完了したようです。
続いて Carthage をアップデートします!
brew upgrade
と打ちます。
$ brew upgrade
略
==> Upgrading carthage 0.37.0 -> 0.38.0
略
==> Pouring carthage--0.38.0.catalina.bottle.tar.gz
==> Caveats
Bash completion has been installed to:
/usr/local/etc/bash_completion.d
==> Summary
🍺 /usr/local/Cellar/carthage/0.38.0: 8 files, 7.7MB
略
0.37.0 しか入れられなかったのが、0.38.0 を入れることに成功しました!
$ carthage version
0.38.0
以上です。
Carthage を 0.36.0 から 0.38.0 に上げるのにそこそこ苦労しました。
本ポストも本当の目的の途中経過です。
環境構築は難しいですね 😇
お疲れ様でした!
以下のコマンドを実行した際、エラーが出て完了できませんでした。
$ brew reinstall carthage
中略
==> `brew cleanup` has not been run in 30 days, running now...
Error: Permission denied @ apply2files - /usr/local/lib/node_modules/npm/node_modules/.bin/JSONStream
これの対処法をまとめます
Mac: macOS Catalina 10.15.6
ターミナルを見ると、brew cleanup
をしようとして失敗しているようです。
`brew cleanup` has not been run in 30 days, running now...
brew reinstall
, brew install
, brew upgrade
を実行すると自動で brew cleanup
が走るようです。
https://brew.sh/2019/02/02/homebrew-2.0.0/
brew cleanup
is run periodically (every 30 days) and triggers for individual formula cleanup on reinstall, install or upgrade.
で、そこでパーミッションの問題で弾かれているようですね。
Stack Overflow に対処法がありました。
以下のコマンドを実行します。
sudo chown -R ${LOGNAME}:staff /usr/local/lib/node_modules
/usr/local/lib/node_modules
とその配下のファイルやディレクトリの所有権を
再帰的に<アカウント名>:staff に変更するコマンドです。
「staff グループ」を初めて知ったんですが、
PCの管理者以外の触る人、という位置付けのグループのようです。
そもそもグループとはどういうものかあまりイメージできなかったので、
調べて本ブログの [Mac] UNIX のユーザとグループの世界観 にまとめました。
Stack Overflow の一つ下の回答 には少し別のコマンドが書かれていました。
sudo chown -R $(whoami):admin /usr/local/* \
&& sudo chmod -R g+rwx /usr/local/*
/usr/local/
配下の所有権や権限を全て変更するコマンドで、
個人的にちょっと怖かったのでこちらのコマンドは採用しませんでした。
が、こちらの回答の方が支持されているようですし、
Qiita などで様子を見る限りこちらでも問題はなさそうです。
むしろサーバなど共有PCで作業する場合は staff より admin の方がよいかもしれませんね🤔
試していませんが staff を admin に読み替えたコマンドを試してみるのもいいかもしれません。
$ sudo chown -R ${LOGNAME}:admin /usr/local/lib/node_modules
さて、前述のコマンドを打って改めて brew cleanup
すると、成功しました!🙌
$ brew cleanup
略
Pruned 19 symbolic links and 318 directories from /usr/local
更に carthage を reinstall してみます。
$ brew reinstall carthage
略
==> Summary
🍺 /usr/local/Cellar/carthage/0.37.0: 8 files, 7.7MB
成功しました🍺
以上です。
Carthage は本当は0.37.0 ではなく 0.38.0 を入れたかったんですが、Homebrew の何かが古いのかな?
次回はupdate, upgrade まわりについてまとめようと思います。
お疲れ様でした!
普段あまり意識しないMacのユーザやグループですが、
調べる機会があったのでコラム的な話も交えつつ概要を書いていきます!
世界観・外観を知ることで、
何が分からないか分からない状態から、何が分からないか分かる、
くらいになる助けになればと思います。
Mac: macOS Catalina 10.15.6
調べ物をしていたとき、admin
や staff
グループというものが出てきて、
admin とは何だ!となったところから始まります。
管理者なのでroot
的な権限を持てるグループか??などとも思いましたが、
後述しますが実際はけっこう違いました。
ユーザにはどんな種類があるでしょうか。
思いつくのは自分のアカウント、root、くらいかな……
サーバで開発していると他の人のアカウントもありますね。
グループは意識したことないのでよく分かりません。
というかなぜグループがあるのかもよく分かりません🤯
とっかかりとしてまず root ユーザについて調べます。
Linuxでは、あらゆる権限が与えられているユーザーを「root」あるいは「rootユーザー」「スーパーユーザー」と呼びます。rootというユーザー名でログインすると、あらゆるコマンドの実行やファイル操作ができるようになります。
https://www.atmarkit.co.jp/ait/articles/1706/02/news014_2.html
出典はLinux についての記事ですが、Mac と同じUnix系システムということでご容赦を。
root ユーザは何でもできます。sudo
コマンドを打つとパーミッションを突破して色々操作できるのは
その間だけroot ユーザになっているからなんですね。
ちなみに、sudo は super user do の略と思いきや substitute user do (代理人として実行)の略という説もあるようです。
少し調べると、初期状態では wheel
グループに所属するのは root
ユーザのみ、という情報がありました。
https://itectec.com/superuser/the-difference-between-the-default-groups-on-mac-os-x/
つまり、所謂 root 的な権限を持つ特権的なグループが wheel
ということになりそうです。
微妙に見覚えのある wheel グループですが、本当に root ユーザだけなのか調べます。
以下のコマンドを打ちます。
参考) https://superuser.com/a/444218
$ dscacheutil -q group -a name wheel
name: wheel
password: *
gid: 0
users: root
wheel グループについての情報が表示されました。
password はそのままですがパスワードで、 * でマスクされています。
gid はグループIDで0。0なのでいかにも特権的な感じですね。
users がグループに所属しているユーザ。
確かにroot のみ所属しているようです。
やはり強力なグループのようです。
同じようにコマンドをうちます。
$ dscacheutil -q group -a name admin
name: admin
password: *
gid: 80
users: root <自分のアカウント> ...
$ dscacheutil -q group -a name staff
name: staff
password: *
gid: 20
users: root <自分のアカウント> _serialnumberd ...
admin グループと staff グループには自分のアカウントが所属していました。
持っているMac が自分専用の場合 admin と staff の違いが実感しづらいかも知れません。
が、やはり admin グループの方が権限が強く、
例えばアプリのインストールなどは admin グループの方のユーザしかできないようです。
参考) https://superuser.com/a/20430
以下のコマンドで見てみます。
$ dscl . list /GROUPS
_amavisd
_analyticsd
略
utmp
wheel
思っていたよりめっちゃ多かったです。dscl . list /GROUPS | wc -l
でカウントすると131個もありました。
_
hogehoge のようなアンダースコアで始まるグループが多かったのですが、
触れるなよ的な圧を感じます。
mail や network や sys などもあり、用途によって色々グループ分けされているようです。
以下のコマンドで見てみます。
$ dscl . list /USERS
_amavisd
_analyticsd
略
<自分のアカウント>
root
やはりこちらも思ったより多く、dscl . list /USERS | wc -l
でカウントすると103個ありました。
こちらもアンダースコアで始まるユーザが多いです。
daemon や nobody といったユーザがいましたが、
軽く調べたところ古いお作法だったりと個人的にはあまり有効な用途がなさそうに見えます。
ですので僕の場合、ユーザに関しては
root と自分や他人のアカウントのみ意識していればよさそうかなと思いました。
ついでにこちらもコマンドで確認してみます。
$ groups root
wheel daemon kmem sys tty 略
root ユーザについて見てみると、所属グループは20個ほどでした。
131個の全グループに所属していると思ってましたが、そんなことはないんですね。
groups <自分のアカウント>
を実行してみるのも面白いかもしれません。
ユーザは root と自分や他人のアカウント。
あとは nobody とか daemon とか。
グループは権限の持ち方を束ねるもので、そこにユーザを振り分けることで
各ユーザに対する権限を、適切に効率的に管理することができる。
けっこう気になるポイントで、
ここが意味不明なので覚えづらいという面があると思います。
wheel はホイール、車輪です。
なぜ車輪が特権グループなのか。
実は英語にはBig Wheel というスラングがあり、
それは大きな車輪の馬車に乗る人、つまり大きな権力を持つ者・組織の重要人物のことを指していたそうです。
参考) https://unix.stackexchange.com/a/1271
Unix はこのスラングを取り入れたと。
なるほどね!
諸説あるようですが、確からしさはありそう。
ということで wheel の意図ができたので、だいぶ覚えやすくなりました。
以上です。
ユーザとグループについて雲を掴むようなふわふわしたイメージしか持てませんでしたが、
今回調べてみてなんとなく輪郭は分かったと思います。
お疲れ様でした!
Android Studio をアップデートしたらキーボードショートカットが全然効かなくなりました。
設定が勝手に変更されてそうなった場合があるので、復元手順を載せます。
秒で復元できます。
MacOS Catalina 10.15.6
Android Studio 4.2
まず「Android Studio」の「Preference」を開きます。
Preference で Keymap を選択します。
詳細のところにプルダウンがあるので、そこで「macOS」を選択し、「apply」を押します。
以上です!
ちなみに僕の場合はなぜか「IntelliJ IDEA Classic」が勝手に設定されていました。
以上です。
お疲れ様でした!