How to reduce the quality of the text inside UITextView with Swift

I'm trying to reduce the quality of a message before its being sent, for example if the connect is poor I want to blur out the text in the UITextView and if connection improves or internet comes back, then remove the blur and show the normal text in the UITextView. I have tried using CATextLayer doesn't work. Is there a way I can achieve this?

cell.messageTextView.text = theText

let textLayer = CATextLayer()
textLayer.string = cell.messageTextView.text
textLayer.contentsScale = 0.2
cell.messageTextView.layer.addSublayer(textLayer)

enter image description here

3 answers

  • answered 2019-12-17 10:54 ChrisTheGreat

    You could try something like this:

    let blurEffect = UIBlurEffect(style: .systemUltraThinMaterial)
    let blurEffectView = UIVisualEffectView(effect: blurEffect)
    blurEffectView.frame = cell.view.bounds
    blurEffectView.autoresizingMask = [.flexibleWidth, .flexibleHeight]
    cell.view.addSubview(blurEffectView)
    

    Adding a UIVisualEffectView with blur effect on top of your table view cell.

  • answered 2019-12-17 11:24 Mojtaba Hosseini

    You can drop the quality of the layer by making it rasterized and reducing the scale of it:

    let badQualityRatio: CGFloat = 4
    textView.layer.shouldRasterize = true
    textView.layer.rasterizationScale = UIScreen.main.scale/badQualityRatio
    

    Result:

    Result

    you can set the rasterizationScale any number between 0 and UIScreen.main.scale

  • answered 2019-12-17 11:27 akashivskyy

    Mojtaba's answer is fine if your messages contain only text and no emoji or image attachments. Chris's answer provides a good hint to use UIVisualEffectView but you might run into problems if you try to "just" add it into your view hierarchy.

    If you want to add it on top of the whole bubble, you'll need to have the following hierarchy:

    ┌──────────────────┐    
    │     maskView     │    
    └┬─────────────────┘    
     │  ┌──────────────────┐
     ├─▶│     blurView     │
     │  ├──────────────────┤
     └─▶│     textView     │
        └──────────────────┘
    

    textView is your UITextView, blurView is UIVisualEffectView laid out directly on top the textView and maskView is a parent container for both of them where we will apply the masking.

    let maskView = UIView()
    maskView.mask = UIImageView(image: UIImage(named: "bubble"))
    
    let textView = UITextView()
    textView.backgroundColor = .orange
    textView.text = "Hello, world!"
    
    let blurView = UIVisualEffectView(frame: maskView.bounds)
    blurView.effect = UIBlurEffect(style: .systemUltraThinMaterial)
    
    maskView.addSubview(textView)
    maskView.addSubview(blurView)
    
    /* Layout left as an exercise for the reader. */
    

    Then just hide or unhide the blurView when needed. The result:

    Note that the bubble used as a mask must be a template image with only black and transparent pixels, preferably resizable for your use case. I used the following:

    Also note that there is unfortunately no way to "alter" the color of the blur effect. It will always appear desaturated. UIVisualEffectView has no public API to change this.