3
2

「Message from debugger: Terminated due to signal 9」エラーの原因と対応~CPU利用率・メモリ使用量改善~

Last updated at Posted at 2024-09-21

エラーの原因

個人開発アプリのアップデートのための実装中に「Message from debugger: Terminated due to signal 9」というエラーが起きたので調べてみました。
CPU利用率が大きい・メモリ使用量が大きいことが原因と考えられるエラーが発生し、クラッシュしました。

CPU利用率 メモリ使用量

改善・考察

アプリの状態によって改善方法は変わってくると思いますが、自分の個人開発のアプリでエラーの原因を考察しながら改善してみました。

HomeView画面 ProfileView画面

①改善

LazyViewを作成

struct LazyView<Content: View>: View {
    var content: () -> Content
    var body: some View {
        self.content()
    }
}

HomeViewの一つひとつの投稿のCellがPostViewです。
PostViewの画面遷移の一部

NavigationLink(destination: {
                    if let myUserID = currentUserID, let profileBio = currentBio {
                        if post.userID == myUserID {
                            // LazyView作成
                            LazyView {
                                ProfileView(isMyProfile: true, posts: posts, profileBio: profileBio, profileDisplayName: post.username, profileUserID: post.userID)
                            }
                        } else {
                            // LazyView作成
                            LazyView {
                                ProfileView(isMyProfile: false, posts: posts, profileBio: "", profileDisplayName: post.username, profileUserID: post.userID)
                            }
                        }
                    }
                }, label: {
                    Image(uiImage: profileImage)
                        .resizable()
                        .scaledToFill()
                        .frame(width: 50, height: 50, alignment: .center)
                        .clipShape(RoundedRectangle(cornerRadius: 60))
                        .overlay {
                            RoundedRectangle(cornerRadius: 60)
                                .stroke(Color.black, lineWidth: 1.0)
                        }
                        .padding(.leading, 10)
                    Text(post.username)
                        .font(.title2)
                        .fontWeight(.medium)
                        .foregroundStyle(.black)
                        .padding(.leading, 10)
                })

ProfileViewが実際に必要になる前に作成されてしまっていたが、作成したLazyViewを間に挟むことによって実際にボタンをクリックしたときにのみ作成されるように改善しました。

②改善

PostModelをstructからclassに変更。

struct PostModel: Hashable {
    var postID: String
    var userID: String
    var username: String 
    var caption: String 
    var dateCreated: Date
    var likeCount: Int
    var likedByUser: Bool
    var comentsCount: Int 
}

extension PostModel: Identifiable {
    var id: String {
        postID
    }
}
class PostModel: Hashable {
    var postID: String 
    var userID: String
    var username: String
    var caption: String 
    var dateCreated: Date
    var likeCount: Int
    var likedByUser: Bool 
    var comentsCount: Int

    init(postID: String, userID: String, username: String, caption: String, dateCreated: Date, likeCount: Int, likedByUser: Bool, comentsCount: Int) {
        self.postID = postID
        self.userID = userID
        self.username = username
        self.caption = caption
        self.dateCreated = dateCreated
        self.likeCount = likeCount
        self.likedByUser = likedByUser
        self.comentsCount = comentsCount
    }

    func hash(into hasher: inout Hasher) {
        hasher.combine(postID)
        hasher.combine(userID)
        hasher.combine(username)
        hasher.combine(caption)
        hasher.combine(dateCreated)
        hasher.combine(likeCount)
        hasher.combine(likedByUser)
        hasher.combine(comentsCount)
    }

    static func == (lhs: PostModel, rhs: PostModel) -> Bool {
        return lhs.postID == rhs.postID &&
               lhs.userID == rhs.userID &&
               lhs.username == rhs.username &&
               lhs.caption == rhs.caption &&
               lhs.dateCreated == rhs.dateCreated &&
               lhs.likeCount == rhs.likeCount &&
               lhs.likedByUser == rhs.likedByUser &&
               lhs.comentsCount == rhs.comentsCount
    }
}

extension PostModel: Identifiable {
    var id: String {
        postID
    }
}

structでは値が渡されるたびにコピーが作成されてしまって、大量のデータを扱う場合や頻繁なデータの更新で、コピーによるオーバーヘッドがCPUに負荷をかけてたのが原因だと考察した。一方、classは参照型で、コピーされるのはポインタだけで、データのコピー回数が減り、メモリ使用量やCPU負荷が大幅に軽減できると考えた。

結果

CPU利用率・メモリ使用量ともに改善し、クラッシュしないように実装できました。
c786ec6ea28d008f4cf401702048b24c.png

1e4657f5be8e10885c609a77ca601558.png

おわり

まだまだCPU使用量やメモリへの影響について勉強中ですが、CPU利用率・メモリ使用量が過剰でアプリがクラッシュするエラーが起きたので、自分のアプリでの改善方法を記事にしてみました。

参考文献

3
2
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
3
2