I have existing Model where I am adding Chatto for UI so I am able to create a message with placeholder but unable to figure out the best way to change the same after download.
Library Link
https://github.com/badoo/Chatto
i am using chatto test app with DemoPhotoMessageModel.
then i use the follwing to add
var imgMess = DemoPhotoMessageModel(messageModel: messageModel, imageSize: placeholder.size, image: placeholder)
self.slidingWindow.insertItem(imgMess, position: .bottom)
self.delegate?.chatDataSourceDidUpdate(self)
ImageDownloader.default.downloadImage(with: downloadURL, options: [], progressBlock: nil) {[unowned self]
(image, error, url, data) in
print("Downloaded Image: \(image)")
if let img = image, let imgData = UIImagePNGRepresentation(img){
imgMess.setImage(img: img) //I updated the default implementation changing the image from var to let constant
}
}
Wha I have also tried is updating the object in slidingWindow itself. That also doesn't work. What will be the possible solution to create a new object with new uid or anything else.
You can download image in willBeShown() method of view model. As you need to pass url to view model, you need to subclass couple of classes. Please see the full solution in the gist. Please feel free to ask any questions.
Related
I did try with Cocapods "Kingfisher" but cannot figure out how to set an animating placeholder image while the image is being downloaded.
here is the Below code I tried with kingfisher Pod
func configureCell(category:Category){
if let url = URL(string: category.imgUrl){
let placeholder = UIImage(named: "placeholder")
let options : KingfisherOptionsInfo = [KingfisherOptionsInfoItem.transition(.fade(0.1))]
categoryImg.kf.indicatorType = .activity
categoryImg.kf.setImage(with: url, placeholder: placeholder, options: options)
}
}
This is actually not an image but a UIView. The best option would be to use SkeletonView.
SkeletonView has been conceived to address this need, an elegant way to show users that something is happening and also prepare them to which contents he is waiting.
This animation is called Shimmer effect . You can use this link for your help
facebook/Shimmer.
I am creating a chatting application. User can share the images from other application to my application. I have added Share Extension to show my app in the native share app list. I'm also getting the selected data in didSelectPost Method. From here I want to show the list of the users to whom the image can be forwarded. For this, I'm using an already created view controller in the main app target.
override func didSelectPost() {
// This is called after the user selects Post. Do the upload of contentText and/or NSExtensionContext attachments.
if let content = self.extensionContext!.inputItems[0] as? NSExtensionItem {
let contentType = kUTTypeImage as String
// Verify the provider is valid
if let contents = content.attachments as? [NSItemProvider] {
for attachment in contents {
if attachment.hasItemConformingToTypeIdentifier(contentType) {
attachment.loadItem(forTypeIdentifier: contentType, options: nil) { (data, error) in
let url = data as! URL
let imageData = try! Data(contentsOf: url)
// Here I'm navigating to my viewcontroller, let's say: ForwardVC
}
}
}
}
}
I don't want to recreate the same screen in Share Extension. Apart from this view controllers, I have many more classes and wrappers that I want to use within the share extension. Like, SocketManager, Webservices, etc. Please suggest me your approach to achieve the same.
P.S.: I've tried setting multiple targets to required viewControllers and using same pods for Share Extention. In this approach, I'm facing a lot of issues as many of the methods and pods are not extention compliant. Also, is it the right way to do this.
I'm using SwiftGif framework to animate a GIF I made, problem is I need to know which image is currently displaying.
The extension is using UIImage.animatedImage(with images: [UIImage], duration: TimeInterval) -> UIImage? to display the animated image.
Here is how I load my gif :
spikes.loadGif(name: "Trap")
and here is how I get the image I'd like to compare it to :
spikes.image.images[2]
I know those are weak explanations but I can't find any more relevant informations, however I can give you more informations if it can help you.
If you know any other solution that could involve me using another framework I would take it too.
If someone ever needs an answer as I did, I found a way to do it.
Load GIF with the extension's loadGif() method
Since the images that are composing the GIF are now stored in spikes.image.images, I store those images in another var
Set spikes.image = nil to cancel animations generated from loadGif() method
Make a timer that keeps changing the actual image of the view
Here's how it looks like :
spikes.loadGif(name: "Trap", completion: { _ in
self.spikesImages = self.spikes.image?.images
self.spikes.image = nil
self.spikes.image = self.spikesImages.first?.img
self.animateSpikes()
})
func animateSpikes() {
Timer.scheduledTimer(withTimeInterval: 0.5, repeats: true, block: { _ in
if let currentImage = self.spikesImages.first {
self.spikes.image = currentImage
self.spikesImages.append(currentImage)
self.spikesImages.remove(at: 0)
}
})
}
I'm pretty sure this is not the best way to do it but it works
Alright, I am not familiar with structs or the ordeal I am dealing with in Swift, but what I need to do is create an iMessage in my iMessage app extension with a sticker in it, meaning the image part of the iMessage is set to the sticker.
I have pored over Apple's docs and https://www.captechconsulting.com/blogs/ios-10-imessages-sdk-creating-an-imessages-extension but I do not understand how to do this or really how structs work. I read up on structs but that has not helped me accomplishing what Apple does in their sample code (downloadable at Apple)
What Apple does is they first compose a message, which I understood, taking their struct as a property, but I take sticker instead
guard let conversation = activeConversation else { fatalError("Expected a conversation") }
//Create a new message with the same session as any currently selected message.
let message = composeMessage(with: MSSticker, caption: "sup", session: conversation.selectedMessage?.session)
// Add the message to the conversation.
conversation.insert(message) { error in
if let error = error {
print(error)
}
}
They then do this (this is directly from sample code) to compose the message:
fileprivate func composeMessage(with iceCream: IceCream, caption: String, session: MSSession? = nil) -> MSMessage {
var components = URLComponents()
components.queryItems = iceCream.queryItems
let layout = MSMessageTemplateLayout()
layout.image = iceCream.renderSticker(opaque: true)
layout.caption = caption
let message = MSMessage(session: session ?? MSSession())
message.url = components.url!
message.layout = layout
return message
}
}
Basically this line is what Im having the problem with as I need to set my sticker as the image:
layout.image = iceCream.renderSticker(opaque: true)
Apple does a whole complicated function thing that I don't understand in renderSticker to pull the image part out of their stickers, and I have tried their way but I think this is better:
let img = UIImage(contentsOfURL: square.imageFileURL)
layout.image = ing
layout.image needs a UIImage, and I can get the imageFileURL from the sticker, I just cant get this into a UIImage. I get an error it does not match available overloads.
What can I do here? How can I insert the image from my sticker into a message? How can I get an image from its imageFileURL?
I'm not sure what exactly the question is, but I'll try to address as much as I can --
As rmaddy mentioned, if you want to create an image given a file location, simply use the UIImage constructor he specified.
As far as sending just a sticker (which you asked about in the comments on rmaddy's answer), you can insert just a sticker into an iMessage conversation. This functionality is available as part of an MSConversation. Here is a link to the documentation:
https://developer.apple.com/reference/messages/msconversation/1648187-insert
The active conversation can be accessed from your MSMessagesAppViewController.
There is no init(contentsOfURL:) initializer for UIImage. The closest one is init(contentsOfFile:).
To use that one with your file URL you can do:
let img = UIImage(contentsOfFile: square.imageFileURL.path)
This might be an amateur question, but although I have searched Stack Overflow extensibly, I haven't been able to get an answer for my specific problem.
I was successful in creating a GIF file from an array of images by following a Github example:
func createGIF(with images: [NSImage], name: NSURL, loopCount: Int = 0, frameDelay: Double) {
let destinationURL = name
let destinationGIF = CGImageDestinationCreateWithURL(destinationURL, kUTTypeGIF, images.count, nil)!
// This dictionary controls the delay between frames
// If you don't specify this, CGImage will apply a default delay
let properties = [
(kCGImagePropertyGIFDictionary as String): [(kCGImagePropertyGIFDelayTime as String): frameDelay]
]
for img in images {
// Convert an NSImage to CGImage, fitting within the specified rect
let cgImage = img.CGImageForProposedRect(nil, context: nil, hints: nil)!
// Add the frame to the GIF image
CGImageDestinationAddImage(destinationGIF, cgImage, properties)
}
// Write the GIF file to disk
CGImageDestinationFinalize(destinationGIF)
}
Now, I would like to turn the actual GIF into NSData so I can upload it to Firebase, and be able to retrieve it on another device.
To achieve my goal, I have two options: Either to find how to use the code above to extract the GIF created (which seems to directly be created when creating the file), or to use the images on the function's parameters to create a new GIF but keep it on NSData format.
Does anybody have any ideas on how to do this?
Since nobody went ahead for over six months I will just put the answer from #Sachin Vas' comment here:
You can get the data using NSData(contentsOf: URL)