Showing images from remote server inside message bubble MessageKit swift

494 views Asked by At

I'm trying to show image inside message bubble of Message Kit. As I got to know Message Kit has a lot of types of its bubbles. For my approach .photo(ImageMediaItem) , I think, is the best message kind. I would like to see loaded imaged inside freshly created messages collection view, or it is bad idea? I don't know surely how to solve this task so this is my own single idea. Tutorial for image loading I found here. For this purpose I created struct for storing image:

private struct ImageMediaItem: MediaItem {
    
    var url: URL?
    var image: UIImage?
    var placeholderImage: UIImage
    var size: CGSize
    
    init(image: UIImage) {
        self.image = image
        self.size = CGSize(width: 240, height: 240)
        self.placeholderImage = UIImage()
    }
    
}

Due to the fact that I received messages data from remote server, I decided to loop over received messages data and send request to the remote when the image is in data. Here is handling of server response:

chatMd.chat?.unread?.forEach({ (message) in
var mKind:MessageKind = .text(message.body!)
DispatchQueue.main.async {
      if  message.body!.extractURLs().count > 0{
           let link = message.body!.extractURLs()[0]
           if link.absoluteString.contains("jpg") || link.absoluteString.contains("png") || link.absoluteString.contains("jpeg"){            
               mKind = .photo(ImageMediaItem(image: imageFromServerURL(urlString: link)))
            }else{
               mKind = .linkPreview(MockLinkItem(text: "nil", attributedText: nil, url: URL.init(string:  link.absoluteString)!, title: link.lastPathComponent, teaser: "", thumbnailImage: #imageLiteral(resourceName: "attachment")))
             }
         }
      }
                                        


})
}

for link fetching I used such extension, maybe it will be useful :

extension String {
    func extractURLs() -> [URL] {
        var urls : [URL] = []
        do {
            let detector = try NSDataDetector(types: NSTextCheckingResult.CheckingType.link.rawValue)
            detector.enumerateMatches(in: self, options: [], range: NSMakeRange(0, self.count), using: { (result, _, _) in
                if let match = result, let url = match.url {
                    urls.append(url)
                }
            })
        } catch let error as NSError {
            print(error.localizedDescription)
        }
        return urls
    }
}

So, as you can see image fetching starts here:

mKind = .photo(ImageMediaItem(image: imageFromServerURL(urlString: link)))

for image fetching I created function:

func imageFromServerURL(urlString: URL) -> UIImage {
        var finalImg = UIImage()
        var request = URLRequest(url: urlString)
        
        request.setValue("application/json; charset=UTF-8", forHTTPHeaderField: "Content-Type")
        request.setValue("Bearer " + UserDefaults.standard.string(forKey: "access_token")!, forHTTPHeaderField: "Authorization")
        
        
        URLSession.shared.dataTask(with: request, completionHandler: { (data, response, error) -> Void in
           
            if error != nil {
                print(error as Any)
                return
            }
            DispatchQueue.main.async(execute: { () -> Void in
                print(data?.count)
                finalImg = UIImage(data: data ?? Data()) ?? UIImage(systemName: "AppIcon")!
            })
            
        }).resume()
        
        
        return finalImg
    }

but I have the problem in this line:

finalImg = UIImage(data: data ?? Data()) ?? UIImage(systemName: "AppIcon")!

I usually receive such an error:

Fatal error: Unexpectedly found nil while unwrapping an Optional value

Firstly I thought that I have nil data but after checking its .count I saw that data isn't empty. So I think that the problem is somewhere in UIImage, for solving it I tried to add such handling ?? UIImage(systemName: "AppIcon")! but it didn't solve my crash problem. Maybe someone will see where the problem is.

P.S. If I didn't post some important information , please let me know in comments, and I will edit my question. Thank you :)

0

There are 0 answers