JSQMessages send media - swift

Im building a small chat app using JSQMessages, and trying to send images from photo library or camera.
I got to the point where I saved the image to parse backend but I cannot display it on screen. I found few solutions but they were in obj-C, I tried to swift-fy but it failed.
I have extra column in parse "images" next to "message".
Here is what I tried:
var message = messages[indexPath.row]
if message != "" {
return messages[indexPath.row]
} else if message?.isMediaMessage == true {
let mediaItem:JSQMessageMediaData = message!.media
if (mediaItem.isKindOfClass(JSQPhotoMediaItem)) {
var photoItem: JSQPhotoMediaItem = mediaItem as! JSQPhotoMediaItem
var image: UIImage = photoItem.image
print("yay")
}
}
return messages[indexPath.row]

You are not actually setting the message content to the photo that you have saved on the backend. You have a var image: UIImage = photoItem.image that just saves it to a variable not to the message content that is being displayed. Also this does evaluate if (mediaItem.isKindOfClass(JSQPhotoMediaItem)) {
var photoItem: JSQPhotoMediaItem = mediaItem as! JSQPhotoMediaItem
so if set your message.media = (data from parse) it should show up.

Related

Can't fill my collection views with API data by using Alamofire

There is an api (https://docs.api.jikan.moe/#section/Information). I get data from it, but I can’t display them in my collection views in any way. The data should come, I checked. I implement filling the collection view cells through the view model ViewController <-> ViewModel and with Network Manager API Manager
The result is just white collectionView - Screen
For the first time I decided to work with Alamofire and apparently I don’t understand something. Please tell me what is the problem. Link to github in case someone needs it.
Updated
The problem might be with asynchronous coding. And i still have no ideas to fix it, cause don't understand the GCD as well. Screen
func fetchRequest(typeRequest: TypeRequest) -> [AnimeModel] {
var animeModels: [AnimeModel] = []
switch typeRequest {
case .name(let name):
let urlString = "https://api.jikan.moe/v4/anime?q=\(name)"
AF.request(urlString).response { response in
guard let data = response.data else { return print("NO DATA FOR - \(name)") }
do {
let json = try JSON(data: data)
let title = json["data"][0]["title_english"].string ?? "Anime"
let imageURL = json["data"][0]["images"]["jpg"]["image_url"].string ?? ""
let image = AnimeModel.downloadImage(stringURL: imageURL)
animeModels.append(AnimeModel(image: image, title: title))
print(".NAME ANIME MODELS - \(animeModels)")
} catch let error {
print(error.localizedDescription)
}
}
}
print("BEFORE RETURN ANIME MODELS - \(animeModels)")
return animeModels // returns empty array and then "animeModel.append()" is applied
}

How can I use firebase storage to download images in a file and show them in a table view?

Good afternoon,
I have been stuck on this problem for months. I am trying to use firebase storage to save image files that a user uploaded. The program should then be able to update the queue and show the image in a horizontal table view. Kinda like netflix where its titles of movies/shows but mine would just be pictures. After trying to figure this out, this is what I came up with. Here is to receive the images
class ImageRecieve : ObservableObject {
#Published var songImageArrayURL = [URL]()
#Published var data : Data?
#Published var songImage : NSImage?
#Published var AlbumCoverArray = [NSImage]()
func GetURLS(){
//we want to get the download urls
bfRef.listAll { (result, error) in
if let error = error{ //if theres an error, print it
print(error.localizedDescription)
}
let prefixes = result.prefixes
//loop to search each song prefix
for i in prefixes.indices{
//get the song of each prefix
prefixes[i].listAll { (result, error) in
if let error = error {
print(error.localizedDescription)
}
else {
let items = result.items
//if anything contains ".mp3" dont add it to array.
for j in items.indices{
if(!items[j].name.contains("mp3")){
SongImage.append(items[j])
self.download(SongImage: items[j])
}
}
}
}
}
}
}
func download(SongImage:StorageReference){
//get download url
DispatchQueue.main.async {
SongImage.downloadURL { (url, error) in
if let error = error { //if there is an error print it
print(error.localizedDescription)
}
else {
if(url != nil){
self.songImage = NSImage(byReferencing: url!)
self.AlbumCoverArray.append(self.songImage!)
}
}
}
}
}
func load(){
if(self.songImageArrayURL.isEmpty){
GetURLS()
}
print(self.songImageArrayURL)
for i in self.songImageArrayURL.indices{
print(self.songImageArrayURL[i])
DispatchQueue.global().async{
if let data = try? Data(contentsOf: self.songImageArrayURL[i]){
if let image = NSImage(data:data){
DispatchQueue.main.async {
self.songImage = image
}
}
}
}
}
}
func cancel(){
}
}
here is to load the images :
struct LoadImages<Placeholder: View>: View {
#ObservedObject var loader : ImageRecieve
private var placeholder : Placeholder?
init(placeholder: Placeholder? = nil) {
loader = ImageRecieve()
self.placeholder = placeholder
}
var body: some View {
image
.onAppear(perform: loader.GetURLS)
.onDisappear(perform: loader.cancel)
}
private var image: some View{
ForEach(loader.AlbumCoverArray.indices,id:\.self){
i in
Group{
if(self.loader.songImage != nil){
Image(nsImage:self.loader.AlbumCoverArray[i]).resizable().frame(width:50, height:50)
}
else{
self.placeholder
}
}
}
}
}
the problem I've been stuck on is that the photos are only downloading one at a time and not listing one by one. For example, they show one image and then switch to the next. I would like an array of images. So that the images get added to the list. I've tried using an image array but it doesnt work.
photos are only downloading one at a time and not listing one by one.
in all languages an array/list is processed sequentially, you might want to use multi-Threading for parallelism. use a queue and assign few threads which download image, after each download pop the element from queue.
all the child threads append/push the data to the main thread. in that manner you will be able to display images as they load.
PS:i am != swiftie but seeing your programming i sense turmoil. try improving your code grammar and avoid too many functions and spaces.

Load data before views in Swift

I'm trying to load some data via JSON from the web and save it globally to my app.
I have a separate swift file
struct MyAppData {
static var vendorCol = "15"
static var vendorDel = "45"
static var VendorID = "1"
}
Using alomofire i populate it.
Alamofire.request("https://domainname/data.json").responseJSON { (responseData) -> Void in
if((responseData.result.value) != nil) {
let json = JSON(responseData.result.value!)
guard let times = json["content"]["clients"].array else {
print("No Data")
return
}
for time in times {
MyAppData.vendorCol = time["col"].string!
MyAppData.vendorDel = time["del"].string!
MyAppData.VendorID = time["id"].string!
}
}
}
This works as expected if I place it on a view controller and use MyAppData.VendorID
My issue is I need a place load the data at a place where it's immediately available to all views and only want to load it once.
I tried in app delegate with no success, the function was called but the data was never updated all over the app. Some labels I set only had the default values from MyAppData.
Any help would be appreciated.

Swift and Firebase 3.x saving and retrieving data

I'm saving data in one view with the following code:
let item1:String = textfield.text!
if TextField1.text != "" {
self.ref.child("userProfile").child((user!.uid)/value1Total").setValue(Double(item1)!)
}
What would be my code in a different view to set that saved value to a label?
You can try like below example:
let name = nameTextField.text
let user: NSDictionary = ["name":name!,"dob":dateOfBirthTimeInterval]
//add firebase child node
let profile = firebase.ref.childByAppendingPath(name!)
// Write data to Firebase
profile.setValue(user)
Have a look on it this link for more info

Show Image from URL in detailView after selection in tableView

I have a tableView which display a list of traffic-cameras parsed from a XML file. When I select a cell, it sends the ImageURL, Roadname, Coordinates etc. via the prepareForSegue method.
In my detailviewcontroller I declare the incoming values as the following:
var selectedFeedURL = String()
var selectedFeedRoadname = String()
var selectedFeedLongitude = String()
var selectedFeedLatitude = String()
I have no problem printing all the values into the log or set it as labels. The problem occurs when I try to load the selectedFeedURL (which is the URL to the image, i.e: http://webkamera.vegvesen.no/kamera?id=559847) and set it to my imageView..
In my viewDidLoad, I have the following code, which should download the image and set it to my imageView named cameraImageView.
if let url = NSURL(string:"\(selectedFeedURL)") {
if let data = NSData(contentsOfURL: url){
print("Suksess")
cameraImageView.image = UIImage(data: data)
}
}
My imageView stays empty and I doesn't get any errors or complains in the debug area. If I print out the selectedFeedURL, the link is there.
The weird part is that if I change
NSURL(string:"\(selectedFeedURL)")
to
NSURL(string:"http://webkamera.vegvesen.no/kamera?id=559847")
Basically changing the variable to a camera URL, it works perfectly.
Soo... any suggestions on what the problem might be?
Much appreciated :)
If there are white spaces and newline characters at the start and end of your URL string, it won't work.
Try:
selectedFeedURL = selectedFeedURL.stringByTrimmingCharactersInSet(.whitespaceAndNewlineCharacterSet())
if let url = NSURL(string: selectedFeedURL) {
if let data = NSData(contentsOfURL: url){
print("Suksess")
cameraImageView.image = UIImage(data: data)
}
}