- 投稿日:2021-01-06T23:43:38+09:00
Mac Catalystでのキーボードイベントについて 【Xcode & Swift】
はじめに
今回の記事は、例えば電卓アプリを作成する場合、表示ラベル、数字キーと演算(+/-/×/÷/=)キーボタンを配置して、ボタンタップやマウスクリックで操作するシーンは普通であるが、ここに物理キーボードのキー押下でも、操作したい場合の話である。(テキスト入力フィールドを持つアプリであれば、特に何も困らないので。)
また、同一ソースコードでiOS(含むiPadOS)とMacOS(Mac Catalyst)の全部に対応したい場合の話である。記事執筆時点の環境は以下の通り。
開発環境version
- MacOS : 11.1 (20C69)
- Xcode : 12.3 (12C33)
- Swift : 5.3.2 (swiftlang-1200.0.45 clang-1200.0.32.28)ターゲット環境version
- iOS/iPadOS : 14.0
- MacOS : 11.01. キーボードイベントの拾い方
APPKitによるMacOSアプリの場合は、
NSView
クラスのkeyDown(with:)
とkeyUp(with:)
メソッドを実装すれば良いが、このメソッドはUIView
クラスには存在しない。
UIKitだとUIView
クラスのpressesBegan(:with:)
とpressesEnded(:with:)
メソッドを実装することになるが、UIKitネイティブのiOS/iPadOSなら問題なく動作するが、Mac(Catalyst)だと一部のキーは動作するがほとんどのキーはコンソールに「Warning: insertText reached」が出力され上記メソッドは呼ばれない。こちらの記事 1 と似たような現象だが解決されてない。他の方法としては、iOS14からサポートされた
Game Controller
によるGCKeyboard
クラスを使用する方法がある。 使い方の概要は以下の通り。if let keyboard = GCKeyboard.coalesced?.keyboardInput { // bind to any key-down/up keyboard.keyChangedHandler = { (keyboard, key, keyCode, pressed) in // compare button to GCKeyCode ・・・ } // bind to specific key-down/up keyboard.button(forKeyCode: .spacebar)?.valueChangedHandler = { (key, value, pressed) in // SpaceBar was pressed or released ・・・ } }試した限り、
GCKeyboard
クラスを使用すれば、iOS/iPadOSとMac(Catalyst)の全部で動作した。
ただし、Macについては、一部のキー押下でBeep音が出る現象に遭遇した。これは、APPKitによるMacOSアプリでNSView
クラスのkeyDown(with:)
とkeyUp(with:)
メソッドを実装した時に発生した現象と同じであるが、MacAppでの回避策 2 3 4 はNSView
を使わないMac(Catalyst)では適用できない。2. Beep音回避
Mac(Catalyst)でGCKeyboard使った時のBeep音の回避策はズバリ、ここ 5 に載っていた。
pressesBegan
pressesEnded
をダミー実装してアプリケーションレベルにメッセージを伝達させないことである。心配なのでpressesCancelled
もダミー実装した。override func pressesBegan(_ presses: Set<UIPress>, with event: UIPressesEvent?) { } override func pressesEnded(_ presses: Set<UIPress>, with event: UIPressesEvent?) { } override func pressesCancelled(_ presses: Set<UIPress>, with event: UIPressesEvent?) { }3. GCKeyCodeのハンドリング
GCKeyboard
クラスによるキーボードイベントのハンドリングは、非常にローレベルなハンドリングとなる。どのキーが押されたのか/離されたのかがGCKeyCode型で通知されるが、この型はキーボードのキートップの刻印とは必ずしも一致しないので、注意が必要である。いくつか例を示す。
・ イコール記号(=)
JISキーボードだと shiftキーと-(ハイフン)キー であるため、
leftShift
(rightShift
)とhyphen
の2回のイベントに別れて通知される。
USキーボードだと =(イコール)キー であるため、equalSign
の1回のイベントで通知される。つまり、同じ文字でもJIS/USキーボードで通知されるコードが違うことがある。左右の2つのシフトキーは区別され独立して通知される。
・ 数字のゼロ(0)
普通はキーボード上部に数字キーは並ぶが、フルキーボードだと右側にテンキーとしても数字キーが配置され、同じ0(数字のゼロ)でもコードが違う。
キーボード上部の数字0はzero
。テンキーの数字0はkeypad0
。 余談であるが、個人的にはzero
ではなく、アルファベットと同じようにkey0
として欲しかった。つまり、同じキートップ文字でも、キーの場所が違うと通知されるコードが違う。
・ aとA(小文字/大文字)の扱い
CapsLockされていない限り、英文字は小文字で入力されるのが普通である。大文字で入力する場合はシフトキーと同時に押す。一方、CapsLockされている場合は、大文字で入力され、シフトキーと同時に押すと小文字になる。
シフトキー+Aの場合に、大文字と解釈するのか小文字と解釈するのか、CapsLockの状態に依存するが、これを知ることができるのか不明である。英小文字と大文字を区別したいアプリの場合はこのハンドリングが難しいだろう。
(アプリ起動後のCapsLockキー押下はイベント通されるが、アプリ起動前にすでにCapsLock状態の場合だと、逆の意味となる)UIKey型であれば
modifierFlags
によってCapsLock状態を知ることができるので、pressesBegan
イベントを併用すれば判断が可能か?(試してないので併用できるか不明)(2021.1.7追記)
pressesBegan
イベントを併用できることを検証したが、それでも工夫が必要である。・
pressesBegan
イベントの併用における注意点iOSとMac(Catalyst)で挙動が異なる。OSのバグの可能性もあるので検証時のバージョンを明示しておく。
- MacOS 11.1(20C69)
- iOS 14.2 (18B92)メソッドの呼び出し(順)
- Mac Catalyst
# メソッド Aキーのみ シフトキーのみ シフトキー+Aキー 備考 1 keyChangedHandler pressed=true 1 1 1 (s), 3 (a) (s)シフトキー 2 keyChangedHandler pressed=false 2 3 4 (a), 5 (s) (a)Aキー 3 pressesBegan - 2 2 (s) 4 pressesEnded - 4 6 (s) Aキーにおいて
pressesBegan
/pressesEnded
が呼ばれないのは、1項で説明した通り。
- iOS
# メソッド Aキーのみ シフトキーのみ シフトキー+Aキー 備考 1 keyChangedHandler pressed=true 2 2 2 (s), 4 (a) (s)シフトキー 2 keyChangedHandler pressed=false 4 4 6 (a), 8 (s) (a)Aキー 3 pressesBegan 1 1 1 (s), 3(a) 4 pressesEnded 3 3 5 (a), 7(s)
keyChangedHandler
とpressesBegan(/Ended)
が呼ばれる順がMac(Catalys)と逆になる。CapsLockキーの扱い
# キーの押下順 Mac iOS CapsLock状態を示すLED 0 - - - 消灯 1 CapsLockキーを押す pressed=true, PressesBeganが呼ばれる PressesBegan, pressed=trueが呼ばれる 点灯 2 CapsLockキーを離す 何も呼ばれない PressesEended, pressed=falseが呼ばれる 点灯 3 Aキーを押す pressed=trueが呼ばれる PressesBegan, pressed=trueが呼ばれる 点灯 4 Aキーを離す pressed=falseが呼ばれる PressesBegan, pressed=trueが呼ばれる 点灯 5 CapsLockキーを押す pressed=false, PressesEendedが呼ばれる PressesBegan, pressed=trueが呼ばれる 消灯 6 CapsLockキーを離す 何も呼ばれない PressesEended, pressed=false 消灯
PressesBegan
に渡されるUIPress.key.modifierFlags
のalphaShift
がCapsLock状態を示す為、アプリ起動後のCapsLock状態はMac/iOSとも、正しく認識可能である。
しかし、アプリ起動前にCapsLock状態にしておいた場合は、Mac/iOSとも、正しくCapsLock状態を認識できない。理由は、Macの場合、AキーでPressesBegan
が呼ばれない為。iOSの場合、UIPress.key.modifierFlags
のalphaShift
が真逆にセットされている為である。iOSはバグの可能性がある。・ キーボード自体の識別
JISとUSキーボードではキー配列に大きな違いがあるが、JISキーボードのキーが押されたのか、USキーボードのキーが押されたのか、
これを区別する方法は未調査である。これを区別できない。(2021.1.8追記)
GCPhysicalInputProfile
でキー数等は判別できるが、明確にキーボードの種類を識別できる情報は無い。そもそもJISキーボードでハイフンの右隣のキー^(ハット)を押すと、なんとequalSign
を返してくる。これはUSキーボード配列のコードである。電卓アプリ程度であれば使用するキーが限定的なため上記の点だけを注意すれば実現可能であるが、viの様なスクリーンエディタを開発するとなると、キーボードイベントのハンドリングに相当な労力が必要と思われる。
4. Macキーボードの例
Apple純正キーボードのキー配列は以下の通り。
最後に
『Mac(Catalyst)でキーボードイベントが拾えない。キーを叩くとBeep音が出る。』この調査にほぼ一日を要したので、ここにまとめておいた。
未調査/未検証事項は後日必要時に追記することとする。(2021.1.8追記)
そもそもGame Controller
はゲームアプリのためのフレームワークであるから、これでviの様なスクリーンエディタを開発しようとすること自体に無理があるのだろう。
以上おまけ
UIKeyModifierFlags
とGCKeyCode
を可視化(文字化)するエクステンションを載せておく。
ここに表示
extension UIKeyModifierFlags { var toString: String { var result = "[" let keys: [UIKeyModifierFlags] = [.alphaShift, .shift, .control, .alternate, .command, .numericPad] let strs = ["alphaShift", "shift", "control", "alternate", "command", "numericPad"] for n in keys.indices { if self.contains(keys[n]) { if result.count == 1 { result += strs[n] } else { result += " ," + strs[n] } } } result += "]" return result } } extension GCKeyCode { var toString: String { let str: String switch self { case .F1: str = "F1" case .F10: str = "F10" case .F11: str = "F11" case .F12: str = "F12" case .F2: str = "F2" case .F3: str = "F3" case .F4: str = "F4" case .F5: str = "F5" case .F6: str = "F6" case .F7: str = "F7" case .F8: str = "F8" case .F9: str = "F9" case .LANG1: str = "LANG1" case .LANG2: str = "LANG2" case .LANG3: str = "LANG3" case .LANG4: str = "LANG4" case .LANG5: str = "LANG5" case .LANG6: str = "LANG6" case .LANG7: str = "LANG7" case .LANG8: str = "LANG8" case .LANG9: str = "LANG9" case .application: str = "application" case .backslash: str = "backslash" case .capsLock: str = "capsLock" case .closeBracket: str = "closeBracket" case .comma: str = "comma" case .deleteForward: str = "deleteForward" case .deleteOrBackspace: str = "deleteOrBackspace" case .downArrow: str = "downArrow" case .eight: str = "eight" case .end: str = "end" case .equalSign: str = "equalSign" case .escape: str = "escape" case .five: str = "five" case .four: str = "four" case .graveAccentAndTilde: str = "graveAccentAndTilde" case .home: str = "home" case .hyphen: str = "hyphen" case .insert: str = "insert" case .international1: str = "international1" case .international2: str = "international2" case .international3: str = "international3" case .international4: str = "international4" case .international5: str = "international5" case .international6: str = "international6" case .international7: str = "international7" case .international8: str = "international8" case .international9: str = "international9" case .keyA: str = "keyA" case .keyB: str = "keyB" case .keyC: str = "keyC" case .keyD: str = "keyD" case .keyE: str = "keyE" case .keyF: str = "keyF" case .keyG: str = "keyG" case .keyH: str = "keyH" case .keyI: str = "keyI" case .keyJ: str = "keyJ" case .keyK: str = "keyK" case .keyL: str = "keyL" case .keyM: str = "keyM" case .keyN: str = "keyN" case .keyO: str = "keyO" case .keyP: str = "keyP" case .keyQ: str = "keyQ" case .keyR: str = "keyR" case .keyS: str = "keyS" case .keyT: str = "keyT" case .keyU: str = "keyU" case .keyV: str = "keyV" case .keyW: str = "keyW" case .keyX: str = "keyX" case .keyY: str = "keyY" case .keyZ: str = "keyZ" case .keypad0: str = "keypad0" case .keypad1: str = "keypad1" case .keypad2: str = "keypad2" case .keypad3: str = "keypad3" case .keypad4: str = "keypad4" case .keypad5: str = "keypad5" case .keypad6: str = "keypad6" case .keypad7: str = "keypad7" case .keypad8: str = "keypad8" case .keypad9: str = "keypad9" case .keypadAsterisk: str = "keypadAsterisk" case .keypadEnter: str = "keypadEnter" case .keypadEqualSign: str = "keypadEqualSign" case .keypadHyphen: str = "keypadHyphen" case .keypadNumLock: str = "keypadNumLock" case .keypadPeriod: str = "keypadPeriod" case .keypadPlus: str = "keypadPlus" case .keypadSlash: str = "keypadSlash" case .leftAlt: str = "leftAlt" case .leftArrow: str = "leftArrow" case .leftControl: str = "leftControl" case .leftGUI: str = "leftGUI" case .leftShift: str = "leftShift" case .nine: str = "nine" case .nonUSBackslash: str = "nonUSBackslash" case .nonUSPound: str = "nonUSPound" case .one: str = "one" case .openBracket: str = "openBracket" case .pageDown: str = "pageDown" case .pageUp: str = "pageUp" case .pause: str = "pause" case .period: str = "period" case .power: str = "power" case .printScreen: str = "printScreen" case .quote: str = "quote" case .returnOrEnter: str = "returnOrEnter" case .rightAlt: str = "rightAlt" case .rightArrow: str = "rightArrow" case .rightControl: str = "rightControl" case .rightGUI: str = "rightGUI" case .rightShift: str = "rightShift" case .scrollLock: str = "scrollLock" case .semicolon: str = "semicolon" case .seven: str = "seven" case .six: str = "six" case .slash: str = "slash" case .spacebar: str = "spacebar" case .tab: str = "tab" case .three: str = "three" case .two: str = "two" case .upArrow: str = "upArrow" case .zero: str = "zero" default: str = "???" } return str } }
- 投稿日:2021-01-06T23:36:46+09:00
M1搭載Macのpip installに苦戦した
参考記事
https://freeheroblog.com/pipenv-install/M1搭載のMacBookProを買ったがpip install すら出来ず。
それを乗り越えたので。
難しいことはしてないし書かないし分からない。環境
MacBookPro M1
つまづいた原因
Homebrew がARMプロセッサでは対応してないということで
インストールを諦めた事。そもそも、普通にはインストール出来なかった
Homebrewインストール方法
特に気にせず、
ターミナルで/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"を実行すると、
「ARMプロセッサに対応してない」的なエラーが出る
と同時に下の文には、
「Rosetta2でHomebrewインストールを再実行します」
と書いてあるそのため、Rosettaからインストールしますがその方法を下記に。
①Finderからターミナルを検索します
②ターミナルを2本指クリック(右クリック)
③「情報をみる」をクリック
④「Rosetta」を使用して開く にチェックを入れるここまでしたら再度、ターミナルを開いて、
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"実行します
何かしら上手くいかなければPCを再起動してください
それで自分もインストールできましたここまでできたら
仮想環境内であろうと、pip install が正常に動作するようになりました
- 投稿日:2021-01-06T19:51:25+09:00
.DS_Storeをコマンド一発で再帰的に消す
ファイル納品の時とか邪魔でしょうがないのでaliasを切ってカレント配下全部消すようにする。
.bashrcに以下追記
alias rmds='find . -name ".DS_Store" -print -exec rm {} ";"'remove ds の略
.DS_Storeを消したいディレクトリに移動してrmdsするだけ。
新年一発目の記事、おわり。
- 投稿日:2021-01-06T17:38:52+09:00
C#でProtocolBuffersを使って見た!!
?新年明けましておめでとうございます?
業務の中でProtocolBuffersを使用することになり、
"なんなんそれ..."と思い、習うより慣れろということで動かしてみました。
詳しい説明を知りたい方は先人の方々がわかりやすく解説してくださっているものが
ありますのでそちらを参考にしていただきたいと思います。
ちなみに、私はこちらのページを参考にしました。手順の流れ
- Protocを入手
- Protoファイル作成
- ProtoファイルからC#のクラスを自動生成する
- サンプルプログラムを書く
1. Protocを入手
Homebrewを使用して入手
# terminal $ brew update # formula を更新 $ brew upgrade # 更新があるパッケージを再ビルドする $ brew install protobuf # protobufをインストール $ brew upgrade protobuf # protobufをアップグレード $ protoc --version libprotoc 3.14.02. Protoファイル作成
Human.protosyntax = "proto3"; package MyPackage; message Human { string name = 1; uint32 age = 2; }3. ProtoファイルからC#のクラスを自動生成する
・Protoファイルが存在する場所まで移動する。
# terminal protoc --csharp_out=. -I. Human.proto4. サンプルプログラムを書く
下準備
・NuGetから Google.Protobuf をインストールする。
・先程の自動生成したcsファイルをRiderのProgram.csと同じ階層に置く。Program.csusing System; using Google.Protobuf; using MyPackage; namespace protocol_test { class Program { static void Main(string[] args) { var human = new Human { Name = "name001", Age = 20 }; byte[] bytes = human.ToByteArray(); Console.WriteLine(BitConverter.ToString(bytes)); // // デシリアライズ var human2 = new Human(); human2 = Human.Parser.ParseFrom(bytes); Console.WriteLine(human2.Age); } } }#実行結果 0A-07-6E-61-6D-65-30-30-31-10-14 20参考文献
・C#でProtocolBuffersを使う方法
・Protocol Buffers 導入メモ Mac/Win
・XML、JSON、Protocol Buffersを比較してみました
- 投稿日:2021-01-06T17:21:53+09:00
デベロッパーツールへの行き方2通り
alt + command + i
特定の要素を右クリック+検証を押下
→デベロッパーモードが開き、特定の要素のHTMLがデベロッパーモードに現れる
- 投稿日:2021-01-06T15:14:25+09:00
【mac】gethのデータを外付けSSDへ移行【ストレージ不足解消】
はじめに
macのストレージがカツカツになりました。
ストレージ不足のせいでXcodeのアップデートができない困った状況です…。
でも、私の環境における諸悪の根源はわかっています。
EthereumのDApps作業用に使っているgethのデータディレクトリです。
rinkebyディレクトリだけで78GBも喰っています…。
こいつをなんとかしてストレージ不足を解消することにしました。で、試行錯誤の結果、gethのデータを外付けSSDへ移行できたので、その際の手順をメモしておきます。
環境
私の環境は下記となります。
PC:MacBook Air(13-inch, Early 2014)
OS:Catalina(10.15.6)
HD:256GB(フラッシュストレージ)gethのバージョン:1.9.9
外付けSSD:SanDisk Extreme ポータブル SSD(250GB)
(※ヨドバシで8800円でした)では、手順を見ていきましょう。
外付けSDDの形式確認/フォーマット
外付けSSDをWindowsパソコンと共有できたら便利なので互換性のあるexFATにしたい所ですが、私の環境ではgethの起動時に下記のエラーがでて同期できませんでした。
exFATで発生したエラーFatal: Error starting protocol stack: listen unix /Volumes/ssd_drive/geth/rinkeby/geth.ipc: bind: invalid argumentですので、外付けSSDのフォーマットはAPFSにしました。
(※すでに外付けSSDがAPFSでフォーマットされている場合は、下記の手順.2(フォーマット)はスキップしてください)
(※途中まで試した感じだと[Mac OS拡張(ジャーナル)]でも動きそうな感じはしましたが、最後までは試していません)手順.1:ディスクユーティリティの起動
外付けSSDをmacに接続して[Launcpad]→[その他]→[ディスクユーティリティ]を起動します。
手順.2:外付けSSDのフォーマット
*ご注意*
以下の手順を試す際は、間違ってmacのHDをフォーマットしないように、対象のドライブが外付けのSSDになっているかをよく確認した上で行ってください対象の外付けSSDを右クリックして[消去...]を選択します。
開いたダイアログにて、フォーマットを[APFS]に設定して、[消去]を実行します。
(※APFSが表示されない場合/エラーがでる場合は後述の[補足:APFSの設定がうまくいかない場合]を参照ください)
(※セキュリティオプションで[最も安全]を選ぶと時間がかかるのでご注意ください=試しにやったら日が暮れました…)
補足:APFSの設定がうまくいかない場合
case.1
APFSが選択できない場合は、一旦[Mac OS拡張(ジャーナル)]形式で消去した後、対象のSSDを右クリックしたメニューから[APFSに変換...]を選択します。
case.2
APFS変換時に「A GUID Partition Table (GPT) partitioning scheme is required.」エラーがでる場合は[diskutil]にて初期化します。まず、[ターミナル]を起動します。
続いて、下記のコマンドにて外付けSSDのディスク番号を確認します。
ディスク番号を確認する$ diskutil list*実行例*
[MacBook-Air:~ hakumai$ diskutil list
/dev/disk0 (internal, physical):
#: TYPE NAME > SIZE IDENTIFIER
0: GUID_partition_scheme *251.0 GB disk0
1: EFI EFI > 209.7 MB disk0s1
2: Apple_APFS Container disk1 250.8 GB disk0s2/dev/disk1 (synthesized):
#: TYPE NAME > SIZE IDENTIFIER
0: APFS Container Scheme - +250.8 GB disk1
Physical Store disk0s2
1: APFS Volume Macintosh HD - Data 221.2 GB disk1s1
2: APFS Volume Preboot 82.3 MB disk1s2
3: APFS Volume Recovery 528.8 MB disk1s3
4: APFS Volume VM 1.1 GB disk1s4
5: APFS Volume Macintosh HD 11.1 GB disk1s5/dev/disk2 (external, physical):
#: TYPE NAME > SIZE IDENTIFIER
0: GUID_partition_scheme *250.1 GB disk2
1: EFI EFI 209.7 MB disk2s1
2: Microsoft Basic Data 名称未設定 249.8 GB disk2s2↑ 私の環境では、外付けSSDが[disk2]として認識されていました。
ディスク番号がわかったら、下記のコマンドにて外付けSSDをフォーマットします。
対象のディスクをAPFSでフォーマットする$ diskutil eraseDisk APFS [設定するドライブ名] [対象のディスク番号]*実行例*
[MacBook-Air:~ hakumai$ diskutil eraseDisk APFS ssd_drive disk2
Started erase on disk2
Unmounting disk
Creating the partition map
Waiting for partitions to activate
Formatting disk2s2 as APFS with name ssd_drive
Mounting disk
Finished erase on disk2↑ドライブ名を[ssd_drive]、ディスク番号を[disk2]でフォーマットした例です。
case.3
[diskutil]の[APFS]指定で失敗する場合は、オプション[JHFS+](Mac OS拡張)で初期化し、その後[case.1]の手順をお試しください。対象のディスクをJHFS+でフォーマットする$ diskutil eraseDisk JHFS+ [設定するドライブ名] [対象のディスク番号]手順.3:ドライブ名の設定
ドライブ名をクリックしてお好きな名前をつけましょう。
ここでは[ssd_drive]としました。
gethの同期時に、このドライブ名でパスを指定することになります。
例えば上記例であれば、パスは[/Volumes/ssd_drive]となります。gethで同期
外付けSSDに適当なディレクトリを作成してgethの同期を開始します。
(※ここでは接続先をRinkebyテストネットとしています)
(※外付けSSDに作成した[geth/rinkeby]ディレクトリを保存先にしたいので、パスとして[/Volumes/ssd_drive/geth/rinkeby]を指定しています)gethで同期$ geth --rinkeby --datadir /Volumes/ssd_drive/geth/rinkeby↓同期中、retryが出まくったのでかなりドキドキしました(※外付けSSDへの書き込みが遅いせいかもしれません…)。
count=1920 elapsed=10.325ms processed=163021371 pending=6704 retry=0 duplicate=18423 unexpected=60488
INFO [01-06|08:37:07.173] Imported new state entries count=1920 elapsed=12.420ms processed=163023291 pending=5893 retry=0 duplicate=18423 unexpected=60488
INFO [01-06|08:37:07.927] Imported new state entries count=1536 elapsed=8.910ms processed=163024827 pending=5925 retry=0 duplicate=18423 unexpected=60488
INFO [01-06|08:37:08.735] Imported new state entries count=1536 elapsed=8.045ms processed=163026363 pending=6121 retry=0 duplicate=18423 unexpected=60488
INFO [01-06|08:37:09.517] Imported new state entries count=1536 elapsed=9.212ms processed=163027899 pending=5965 retry=0 duplicate=18423 unexpected=60488
INFO [01-06|08:37:10.249] Imported new state entries count=1920 elapsed=11.310ms processed=163029819 pending=5222 retry=0 duplicate=18423 unexpected=60488
INFO [01-06|08:37:10.916] Imported new state entries count=1536 elapsed=9.066ms processed=163031355 pending=4988 retry=0 duplicate=18423 unexpected=60488ですが、ひたすら放置しておいたら、同期が完了してくれました。
↓下記のログが出力されたら同期の完了です(※gethを終了するには[Ctrl+C]を入力します)。INFO [01-06|08:59:34.821] Fast sync complete, auto disabling
同期にかかった時間は24時間弱、ほぼ丸一日でした。
感覚的にはmacのHD(フラッシュストレージ)を対象にした時に比べて、2〜3倍遅い印象です。
mac側のコネクタがType-Aなので、Type-Cの利用できるmacならもっと速いのではないかと思います。truffleとの連携確認:読み込み
同期したデータディレクトリを対象にgethをRPCモードで起動します。
gethをPRCモードで起動$ geth --allow-insecure-unlock --rpc --rpcapi personal,web3,eth,net --verbosity 0 console --rinkeby --datadir /Volumes/ssd_drive/geth/rinkeby次に、ターミナルの別タブからTruffleを起動します
(※rinkebyのネットワーク設定がされているプロジェクトフォルダへ移動してから起動してください)Truffleの起動$ truffle console --network rinkebyテストアカウントの残高を確認します(※残高表示が0だったり実際の値と違う場合は同期が完了していないので再同期してください)。
残高確認truffle(rinkeby)> web3.eth.getBalance( accounts[0] ) '474167714324901098982'MetaMask等で残高を増減した後、再度残高を確認します(※ここでは[0.16ETH]減らしてみました)。
再度残高確認truffle(rinkeby)> web3.eth.getBalance( accounts[0] ) '474005299324901098982'ちゃんと同期がとれています。
[truffle]との連携確認:デプロイ
スマートコントラクトをデプロイしてみます。
(※プロジェクトのビルドが通り、migrateの設定に問題がない状況でデプロイしてください)コントラクトのデプロイ[truffle(rinkeby)> migrate --f 2 Compiling your contracts... =========================== > Everything is up to date, there is nothing to compile. Migrations dry-run (simulation) =============================== > Network name: 'rinkeby-fork' > Network id: 4 > Block gas limit: 10000000 (0x989680) 2_deploy_contracts.js ===================== Replacing 'HelloWorld' ---------------------- > block number: 7844413 > block timestamp: 1609893660 > account: 0xebfCB28c530a9aAD2e5819d873EB5Cc7b215d1E1 > balance: 474.003238390901098982 > gas used: 1030467 (0xfb943) > gas price: 2 gwei > value sent: 0 ETH > total cost: 0.002060934 ETH ------------------------------------- > Total cost: 0.002060934 ETH Summary ======= > Total deployments: 1 > Final cost: 0.002060934 ETH Starting migrations... ====================== > Network name: 'rinkeby' > Network id: 4 > Block gas limit: 10000000 (0x989680) 2_deploy_contracts.js ===================== Replacing 'HelloWorld' ---------------------- > transaction hash: 0xdf4bb76e2ca3913cd637cd7ceaeec0aafc409743493cf3fbb10c85249c7f2ec7 > Blocks: 1 Seconds: 4 > contract address: 0xaD1c3A4E6E19955C4a3cdB993843d7aC78F7294c > block number: 7844412 > block timestamp: 1609893664 > account: 0xebfCB28c530a9aAD2e5819d873EB5Cc7b215d1E1 > balance: 473.984389984901098982 > gas used: 1045467 (0xff3db) > gas price: 20 gwei > value sent: 0 ETH > total cost: 0.02090934 ETH > Saving artifacts ------------------------------------- > Total cost: 0.02090934 ETH Summary ======= > Total deployments: 1 > Final cost: 0.02090934 ETHデプロイも問題なく完了しました。
外部クライアントから適当にアクセスし、その結果もEthescanから確認できました。https://rinkeby.etherscan.io/address/0xaD1c3A4E6E19955C4a3cdB993843d7aC78F7294c
どうやら問題なく動いているようです。
結果として、mac側のストレージから[geth]のデータディレクトリを削除することができました。
空き容量も100GBを回復して、Xcodeのアップデートも無事完了しました。めでたしめでたし。
まとめ
gethの同期先を外付けSSDを対象にした場合、macのHDと比べて同期に時間がかかるので、ストレージをとるか速さをとるかで検討しましょう。
たまにsolidityをいじってデプロイする程度のgeth利用であれば、データを外付けSSDへ移行するのは十分ありだと思います。
- 投稿日:2021-01-06T01:07:28+09:00
【Unity for Mac】VSCodeでC# Extensionの設定
UnityのScript EditorでVSCode
- C# Extensionが機能しない
- F12やCommand+クリックで関数の定義へジャンプしない
- C#のエクステンションをインストールする(エクステンションショートカット:Command+Shift+X)
- 設定を開く(設定ショートカット:Command+,)
- Search settingsに「mono」とタイプすると、Extensionsの項目に「C# configuration」がヒットするので開く
- 「Use Global Mono」の設定を「always」にする
- 「Mono Path」の設定(Edit in settings.json)を開き、「omnisharp.monoPath」を入力する
- VSCodeを再起動する
omnisharp.monoPath の確認方法
ターミナルを開き以下のコマンドで確認する
which monomono バージョンの確認方法
mono -V