0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

【SwiftUI】Button系のlabelをTextにするとメモリリークする問題

Last updated at Posted at 2021-12-05

追記

  • 日本語か、もしくはアルファベットでも10文字以上だと発生

環境

  • MacOS Big Sur
  • Xcode 13.1
  • Swift5

GitHub

現象

struct LoginView: View {
    @ObservedObject private var viewModel: LoginViewModel

    init(viewModel: LoginViewModel) {
        self.viewModel = viewModel
    }

    var body: some View {
        VStack {
            Text(viewModel.invalidMessage)
                .foregroundColor(.red)
                .accessibility(identifier: "loginInvalidMessage")
            TextField("Eメール", text: $viewModel.email)
                .textFieldStyle(.roundedBorder)
                .autocapitalization(.none)
                .padding()
                .accessibility(identifier: "loginEmailTextField")
            SecureField("パスワード", text: $viewModel.password)
                .textFieldStyle(.roundedBorder)
                .autocapitalization(.none)
                .padding()
                .accessibility(identifier: "loginPasswordSecureField")

            // これがメモリリークする
            Button(action: {}) {
                Text("ログイン")
                    .frame(maxWidth: .infinity)
                    .padding()
                    .foregroundColor(.white)
                    .background(Color(.orange))
                    .cornerRadius(24)
                    .padding()
                    .accessibility(identifier: "loginButton")
            }

            // 追記: これもメモリリークする
            NavigationLink(destination: signUpView) {
                Text("新規登録")
                    .frame(maxWidth: .infinity)
                    .padding()
                    .foregroundColor(.white)
                    .background(Color(.orange))
                    .cornerRadius(24)
                    .padding()
                    .accessibility(identifier: "toSignUpButton")
            }
        }
    }
}

文字を入れるとメモリリークする

Button(action: {}) {
    Text("ログイン")
        .frame(maxWidth: .infinity)
        .padding()
        .foregroundColor(.white)
        .background(Color(.orange))
        .cornerRadius(24)
        .padding()
        .accessibility(identifier: "loginButton")
}

image.png

空文字だとメモリリークしない

Button(action: {}) {
    Text("")
        .frame(maxWidth: .infinity)
        .padding()
        .foregroundColor(.white)
        .background(Color(.orange))
        .cornerRadius(24)
        .padding()
        .accessibility(identifier: "loginButton")
}

image.png

やったこと

TextではなくImageを使うとメモリリークしなくなった。
さすがにおかしいので何か知っている方いらっしゃれば教えてください。

追記: 10文字未満のアルファベットを指定するとメモリリークしなくなったのでひとまず日本語を使わなければ大丈夫そう

Button(action: {}) {
    Image(systemName: "hand.thumbsup.fill")
}

image.png

Button(action: { viewModel.didTapLoginButton.send() }) {
    Text("Login")
        .padding()
        .foregroundColor(.white)
        .background(Color(.orange))
        .cornerRadius(24)
        .padding()
        .opacity(viewModel.isLoginEnabled ? 1 : 0.5)
        .accessibility(identifier: "loginButton")
}.disabled(!viewModel.isLoginEnabled)
0
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?