第18回コベチケの会

コベリンの最近の取り組みとして、業務などで役立ちそうな知見を共有する会を開催することになりました。 そのついでに発表に使ったアジェンダもそのまま公開してしまおうという豪快な企画です。

※ アジェンダをそのままコピペして公開したものなので若干見にくい箇所もあるかもしれませんが、ご了承ください。

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 に書き直そうとした場合に

  1. HogeClass.swift を作って Swift 版を作成する
    1. クラス名がかぶらないように内部的には HogeClass2 とかにしておく
  2. HogeClass.{h,m} を削除して置き換える
  3. 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 をつけてやれば治ると言われていて実際コベリンでもみんなこれでうまく動いている

github.com

問題

なんか自分は arch -x86_64 をつけても上の問題が起きていた。しかしみんなは普通に開発している。 ( id:mironal は同じモデルのMacを使っている )

調査

色々調査していてRosettaを解除したのにarm64にならない原因 | 金沢音楽制作という記事を見つけた

hkmc.jp

要約するとターミナルの起動オプションのRosettaのオンオフでarm64とx86_64で動くようにできるのだが、チェックを外してもx86_64のままみたいだった

原因

image.png (152.3 kB)

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でビルドをしてしまっていた結果エラーが起きていたと思われる