コベリンの最近の取り組みとして、業務などで役立ちそうな知見を共有する会を開催することになりました。 そのついでに発表に使ったアジェンダもそのまま公開してしまおうという豪快な企画です。
※ アジェンダをそのままコピペして公開したものなので若干見にくい箇所もあるかもしれませんが、ご了承ください。
Objective-C を Swift に置き換えていくときの気をつけるところ
(今更かよ)
Swift で書いたクラスのサブクラスを Objc で書けない
class OyaKurasu
が Swift に書かれているとき、 @interface SubKurasu: OyaKurasu
と Objc で書けない(コンパイルエラーになる)。
これは例えば Objc で以下のように親クラスとそれを継承している複数のサブクラスがある場合にこれらを Swift で書き直す場合には、最初に ParentClass を Swift で書き直してしまうとコンパイルができなくなってしまうので、 まずサブクラス群を Swift で書き直して、最後に親クラスを Swift で書き直すのが良い。
- ParentClass
- ChildClass1
- ChildClass2
https://forums.swift.org/t/cannot-subclass-a-class-with-objc-subclassing-restricted-attribute/5674
Objective-C と Swift で同じファイル名(拡張子除く)があるとコンパイルができなくなる
例えば HogeClass.{h,m}
という Objc のコードがあり、これを Swift に書き直そうとした場合に
- HogeClass.swift を作って Swift 版を作成する
- クラス名がかぶらないように内部的には
HogeClass2
とかにしておく
- クラス名がかぶらないように内部的には
- HogeClass.{h,m} を削除して置き換える
- Swift の方のクラス名を
HogeClass
に直す
という手順で修正していこうと考えたとする。
このとき、 HogeClass.swift
のせいなのかよくわからないがコンパイルエラーになる。
1 の手順で HogeClass2.swift
とかしておくとちゃんとコンパイルできるのでファイル名も気をつけよう.
UI_APPEARANCE_SELECTOR
Objc で作成した独自 View の property を apparance で操作したい場合には UI_APPEARANCE_SELECTOR
をつけるが、 Swift にはない。
@property (nonatomic) UIColor *linkTextColor UI_APPEARANCE_SELECTOR;
Swift ではこう書く。 @objc
を書き忘れると実行時エラーになるので分かりにくい。
@objc dynamic var linkTextColor: UIColor
相互参照の問題
Bridging-Header
に書いてある Objc のクラスが MyApp-Swift.h
にも依存しているとコンパイルできないから、芋づる式に Swift 化が必要になったりして非常に辛い.
その他色々
feather はもともと Objc で作られていて非常にでかいコードベースなので富豪が出資してくれないとなかなか全部を Swift に置き換えるのが大変.
俺のシェルがx86_64で動かないはずがない @takkumattsu
m1 Mac で pod install
をした人なら一度は見たことがあるこのエラー
Gem::Ext::BuildError: ERROR: Failed to build gem native extension. current directory: /Users/takkumattsu/workspace/feather/vendor/bundle/ruby/2.6.0/gems/ffi-1.15.5/ext/ffi_c
ググると arch -x86_64
をつけてやれば治ると言われていて実際コベリンでもみんなこれでうまく動いている
問題
なんか自分は arch -x86_64
をつけても上の問題が起きていた。しかしみんなは普通に開発している。 ( id:mironal は同じモデルのMacを使っている )
調査
色々調査していてRosettaを解除したのにarm64にならない原因 | 金沢音楽制作という記事を見つけた
要約するとターミナルの起動オプションのRosettaのオンオフでarm64とx86_64で動くようにできるのだが、チェックを外してもx86_64のままみたいだった
原因
x86_64でbashとかtmuxをインストールしてそこから起動すると全てx86_64で起動するとのこと
ちょっとピンときた
#!/bin/sh uname -m
こんなスクリプトを作って以下のコマンド二つを叩いてみた (ちなみにrosettaにはチェックを入れていないiTerm)
$ ./test.sh arm64 $ arch -x86_64 ./test.sh arm64
!?
arch -x86_64
を指定しているのに変わっていない!
さらに調べる
さっきtmuxとかが原因だったと聞いて、いったん.bash_profile
から.bashrc
の読み込みをやめてみた
$ ./test.sh arm64 $ arch -x86_64 ./test.sh x86_64
変わった!
bashrcを見てみる
#for bash_completion [[ -r "/opt/homebrew/etc/profile.d/bash_completion.sh" ]] && . "/opt/homebrew/etc/profile.d/bash_completion.sh" # import /usr/local/bin export PATH="/opt/homebrew/opt/coreutils/libexec/gnubin:$PATH" export PATH=/opt/homebrew/bin:$PATH # alias alias ls='ls --color' # color export CLICOLOR=1 export LSCOLORS=ExFxBxDxCxegedabagacad # vim alias vi='vim' # PS1 source /opt/homebrew/etc/bash_completion.d/git-prompt.sh source /opt/homebrew/etc/bash_completion.d/git-completion.bash GIT_PS1_SHOWDIRTYSTATE=true export PS1='\[\033[37m\][\[\033[36m\]\u\[\033[37m\]@\h \[\033[32m\]\w\[\033[37m\]]\[\033[31m\]$(__git_ps1)\[\033[00m\]\n\$ ' PS1="$PS1"'$([ -n "$TMUX" ] && tmux setenv TMUXPWD_$(tmux display -p "#D" | tr -d %) "$PWD")' # core utils PATH="/usr/local/opt/coreutils/libexec/gnubin:$PATH" #export PATH="$HOME/.rbenv/bin:$PATH" eval "$(rbenv init -)" # history function share_history { history -a history -c history -r } PROMPT_COMMAND='share_history' shopt -u histappend export HISTSIZE=9999 # nvm export NVM_DIR="$HOME/.nvm" [ -s "/opt/homebrew/opt/nvm/nvm.sh" ] && . "/opt/homebrew/opt/nvm/nvm.sh" # This loads nvm [ -s "/opt/homebrew/opt/nvm/etc/bash_completion.d/nvm" ] && . "/opt/homebrew/opt/nvm/etc/bash_completion.d/nvm" # This loads nvm bash_completion #if [ -e $(brew --prefix nvm)/nvm.sh ]; then # export NVM_DIR="${HOME}/.nvm" # source $(brew --prefix nvm)/nvm.sh #fi export NVM_DIR="$HOME/.nvm" [ -s "/opt/homebrew/opt/nvm/nvm.sh" ] && . "/opt/homebrew/opt/nvm/nvm.sh" # This loads nvm [ -s "/opt/homebrew/opt/nvm/etc/bash_completion.d/nvm" ] && . "/opt/homebrew/opt/nvm/etc/bash_completion.d/nvm" # This loads nvm bash_completion # ctrl + s, ctrl + q #if [[ -t 0 ]]; then # stty stop undef # stty start undef #fi #tmux # flutter export PATH="$PATH:$HOME/workspace/flutter/bin" # Android export ANDROID_SDK_ROOT="~/Library/Android/sdk" # Java HOME export JAVA_HOME='/Applications/Android Studio.app/Contents/jre/jdk/Contents/Home' export MINT_PATH="$HOME/.mint" export MINT_LINK_PATH="$MINT_PATH/bin" export PATH="$HOME/.rbenv/bin:$PATH"
色々returnを入れて調べた結果
--- .bashrc 2022-05-11 13:33:50.000000000 +0900 +++ .bashrc_fix 2022-05-11 13:33:33.000000000 +0900 @@ -2,7 +2,7 @@ [[ -r "/opt/homebrew/etc/profile.d/bash_completion.sh" ]] && . "/opt/homebrew/etc/profile.d/bash_completion.sh" # import /usr/local/bin -export PATH="/opt/homebrew/opt/coreutils/libexec/gnubin:$PATH" +#export PATH="/opt/homebrew/opt/coreutils/libexec/gnubin:$PATH" export PATH=/opt/homebrew/bin:$PATH # alias
coreutils君!!
上をコメントアウトしたら正しくx86_64で動くようになった!
結論
おそらくcoreutilsでパスが通っている何かをもとにpod install時のコマンドが叩かれてarm64
でビルドをしてしまっていた結果エラーが起きていたと思われる