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 :)