iOS通知文本在部分设备显示为数字的问题排查求助
问题排查请求
我为通知类型创建了NotificationType枚举,用来告知用户有人关注、评论或点赞了帖子,每个枚举值对应对应的notificationMessage。大部分设备显示正常,但有iOS 16+的iPhone用户反馈,所有通知旁都显示“1”和“3”,和通知类型无关。我原本以为是枚举绑定的Int值问题,但不同类型通知显示相同数字,显然不是这个原因。已经检查过该用户的Firestore数据,和其他用户一致。现在因为只有部分设备出问题,完全没头绪,求排查思路。
异常显示效果

预期显示效果

Notification代码
struct Notification: Identifiable, Decodable { @DocumentID var id: String? var postId: String? let timestamp: Timestamp let type: NotificationType let uid: String var isFollowed: Bool? = false var post: Post? var user: User? } enum NotificationType: Int, Decodable { case like case comment case follow var notificationMessage: String { switch self { case .like: return " liked your post." case .comment: return " commented on your post." case .follow: return " followed you." } } }
NotificationCell代码
struct NotificationsCell: View { @StateObject var viewModel: NotificationCellViewModel var isFollowed: Bool { return viewModel.notification.isFollowed ?? false} var body: some View { HStack (alignment: .top) { if let user = viewModel.notification.user { NavigationLink { LazyView(ProfileView(user: user)) } label: { KFImage(URL(string: user.profileImageUrl)) .resizable() .scaledToFill() .frame(width: 48, height: 48) .cornerRadius(6) } } if viewModel.notification.type != .follow { if let post = viewModel.notification.post { NavigationLink { ScrollView { LazyView(FeedCell(viewModel: FeedCellViewModel(post: post))) } } label: { Text("\(Text(viewModel.notification.user?.fullname ?? "").font (Font.body2))\(Text(viewModel.notification.type.notificationMessage))\(Text(" "))\(Text((viewModel.timestampString)).foregroundColor(.gray).font(Font.footnote))") .foregroundColor(Color(.label)) .font(Font.body) .multilineTextAlignment(.leading) } } } else { VStack (alignment: .leading, spacing: 8) { if let user = viewModel.notification.user { NavigationLink { LazyView(ProfileView(user: user)) } label: { Text("\(Text(user.fullname).font(Font.body2))\(Text(viewModel.notification.type.notificationMessage))\(Text(" "))\(Text((viewModel.timestampString)).foregroundColor(.gray).font(Font.footnote))") .foregroundColor(Color(.label)) .font(Font.body) .multilineTextAlignment(.leading) } } HStack { Button(action: { isFollowed ? viewModel.unfollow() : viewModel.follow() }, label: { Text(isFollowed ? "Following" : "Follow Back") .font(Font.button) .padding(4) .foregroundColor(isFollowed ? Color.accentColor: .white) .background(isFollowed ? .white : Color.accentColor) }) .cornerRadius(10) .overlay( RoundedRectangle(cornerRadius: 10) .stroke(Color.accentColor, lineWidth: isFollowed ? 1 : 0) ) } } } Spacer() if viewModel.notification.type != .follow { if let post = viewModel.notification.post { NavigationLink { ScrollView { LazyView(FeedCell(viewModel: FeedCellViewModel(post: post))) } } label: { KFImage(URL(string: viewModel.notification.post?.imageUrl ?? "")) .resizable() .scaledToFill() .frame(width: 40, height: 48) .cornerRadius(6) } } } } .padding(.vertical, 8) .padding(.horizontal) } }
NotificationCellViewModel代码
class NotificationCellViewModel: ObservableObject { @Published var notification: Notification var timestampString: String { let formatter = DateComponentsFormatter() formatter.allowedUnits = [.second, .minute, .hour, .day, .weekOfMonth] formatter.maximumUnitCount = 1 formatter.unitsStyle = .abbreviated return formatter.string(from: notification.timestamp.dateValue(), to: Date()) ?? "" } init(notification: Notification) { self.notification = notification checkIfUserIsFollowed() fetchNotificationPost() fetchNotificationUser() } func follow() { UserService.follow(uid: notification.uid) { _ in NotificationsViewModel.uploadNotification(toUid: self.notification.uid, type: .follow) self.notification.isFollowed = true } } func unfollow() { UserService.unfollow(uid: notification.uid) { _ in self.notification.isFollowed = false } } func checkIfUserIsFollowed() { guard notification.type == .follow else { return } UserService.checkIfUserIsFollowed(uid: notification.uid) { isFollowed in self.notification.isFollowed = isFollowed } } func fetchNotificationPost() { guard let postId = notification.postId else { return } COLLECTION_POSTS.document(postId).getDocument { snapshot, _ in self.notification.post = try? snapshot?.data(as: Post.self) } } func fetchNotificationUser() { COLLECTION_USERS.document(notification.uid).getDocument { snapshot, _ in self.notification.user = try? snapshot?.data(as: User.self) } } }
排查思路
- iOS 16+的Text拼接兼容性问题:当前代码用了多层
Text嵌套拼接的写法,iOS 16可能对这种组合逻辑有解析bug。建议改成直接用字符串拼接,再通过AttributedString或自定义Modifier设置不同部分的样式,避免嵌套Text组件。 - DateComponentsFormatter行为差异:用户看到的“1”“3”可能是时间格式化的异常输出。试试移除
.weekOfMonth单位,或者换成DateFormatter测试,看是否还会出现奇怪的数字。 - 枚举解码兼容性:给
NotificationType的rawValue显式赋值,避免iOS 16的Codable对隐式Int值解码出现异常:enum NotificationType: Int, Decodable { case like = 0 case comment = 1 case follow = 2 // ... } - KFImage加载异常:检查KFImage的配置,是否在iOS 16下加载失败时显示了默认数字占位符,尝试替换为本地占位图测试。
- 设备系统设置影响:让用户检查设备的语言、区域格式,特殊的日期/数字格式可能导致时间字符串显示异常。
- SwiftUI布局逻辑变更:iOS 16的SwiftUI对
NavigationLink、Text布局有API变更,简化NotificationCell的嵌套结构,逐步排查是否是布局嵌套导致的渲染bug。
内容的提问来源于stack exchange,提问作者amelia
相关产品推荐
相关产品推荐

