Stefan
Stefan

Reputation: 35

Create attributed string based on cell type in Swift

I am currently developing a Notifications list screen that would display 4 types of notifications. Here is how it would look like in a very simple way: enter image description here

The main problem for me is to make the text attributed properly depending on the cell type. I have this kind of setup code for my notification cell:

enum NotificationType {
    case eventDue(UIImage)
    case eventCreated(UIImage)
    case eventChanged(UIImage)
    case inviteDeclined(UIImage)
    case adminMessage(UIImage)
    case invite(UIImage)
    
    var image: UIImage? {
        switch self {
        case .eventDue(let image), .eventChanged(let image), .inviteDeclined(let image), .eventCreated(let image):
            return image
        case .invite(let avatarImage), .adminMessage(let avatarImage):
            return avatarImage
        }
    }

In my viewModel I try to make the title of the notification attributed, but I am having issues with selecting the proper parts of the string and making them black color. My View Model code:

final class NotificationViewModel: ObservableObject {
   let type: NotificationType
   var isUnread: Bool
   let title: String
   let date: Date
   
   init(type: NotificationType,
        isUnread: Bool,
        title: String,
        date: Date) {
       self.type = type
       self.isUnread = isUnread
       self.title = title
       self.date = date
   }
}

extension NotificationViewModel {
   var formattedTitle: AttributedString {
       var result = AttributedString(title)
       result.font = Fonts.body
       result.foregroundColor = UIColor(displayP3Red: 0.68, green: 0.68, blue: 0.68, alpha: 1.0)
       
       let words = title.split(separator: " ")
       
       switch type {
       case .eventDue(_):
        // make time before event (either 60 or 30) and event name black
       case .eventCreated(_):
        // make name of person and event name black
       case .eventChanged(_):
       // make name of person and event name black
       case .inviteDeclined(_):
       // make name black
       case .message(_):
       // Make all text black
       case .invite(_):
           let nameSurname = words[0...1].joined(separator: " ") // here is what I was trying but realized it wouldn't work properly...
       }
   }
}

I decided to use AttributedString, I make my whole string gray by default and I think I could make the important parts for each notification type bold in each case. Basically, if it's a invitation notification - make the name (always as name and surname) of black color and leave the rest gray and so on... I don't think working with ranges would work properly, it does not seem to be very flexible. Also, it has to work with different languages, for example in German the order of the words might change because to their grammar... How can I accomplish this sort of task? Maybe I could make the title in the ViewModel a Struct that would have different properties depending on the NotificaitonType enum?

Thank you in advance.

Upvotes: 1

Views: 165

Answers (1)

Stefan
Stefan

Reputation: 35

I realized that this more a backend problem. If you want to have styled text for your notifications(which come from backend) you need to ask your colleagues to add markdown to those strings. Basically, you would receive a string with Markdown and just use AttributedString(markdown:) to display the styled text. The only advice I can give you is to skip HTML because web view is laggy... Stick to Markdown

Upvotes: 0

Related Questions