Loading data from Parse server into a model file in an array. - swift

I want to load data from parse server into a model file in an array called posts but i don't know how.
Here is the code :
struct Post
{
var createdBy: User
var timeAgo: String?
var caption: String?
var image: UIImage?
var numberOfLikes: Int?
var numberOfComments: Int?
var numberOfShares: Int?
static func fetchPosts() -> [Post]
{
var posts = [Post]()
var usernameArray = [String]()
var avaArray = [PFFile]()
var dateArray = [Date?]()
var picArray = [PFFile]()
var titleArray = [String]()
var uuidArray = [String]()
let query = PFQuery(className: "posts")
query.findObjectsInBackground { (objects: [PFObject]?, error: Error?) in
if error == nil {
usernameArray.removeAll(keepingCapacity: false)
avaArray.removeAll(keepingCapacity: false)
dateArray.removeAll(keepingCapacity: false)
picArray.removeAll(keepingCapacity: false)
titleArray.removeAll(keepingCapacity: false)
uuidArray.removeAll(keepingCapacity: false)
// find related objects
for object in objects! {
usernameArray.append(object.object(forKey: "username") as! String)
avaArray.append(object.object(forKey: "ava") as! PFFile)
dateArray.append(object.createdAt)
picArray.append(object.object(forKey: "pic") as! PFFile)
titleArray.append(object.object(forKey: "title") as! String)
uuidArray.append(object.object(forKey: "uuid") as! String)
}
}
}
return posts
}
}
struct User
{
var username: String?
var profileImage: UIImage?
}

Try this
static func fetchPosts() -> [Post]
{
var posts = [Post]()
var usernameArray = [String]()
var avaArray = [PFFile]()
var dateArray = [Date?]()
var picArray = [PFFile]()
var titleArray = [String]()
var uuidArray = [String]()
let query = PFQuery(className: "posts")
query.findObjectsInBackground { (objects: [PFObject]?, error: Error?) in
if error == nil {
// find related objects
if let returnedObjects = objects {
for object in returnedObjects {
usernameArray.append(object["username"] as! String)
avaArray.append(object["ava"] as! PFFile)
dateArray.append(object.createdAt)
picArray.append(object["pic" as! PFFile)
titleArray.append(object["title"] as! String)
uuidArray.append(object["uuid"] as! String)
}
}
}
}
return posts
}
In order to append data to your posts you need to
- Convert PFFile to UIImage
- Create a User object with the UIImage
- Add the User object to your posts
if let avaPicture = object["ava"]! as! PFFile {
avaPicture.getDataInBackground({ (imageData: Data?, error: Error?) -> Void in
if (error == nil) {
let image = UIImage(data: imageData!)
if image != nil {
// Create your User object with UIImage here
let user = User()...
// Add the new user and other data to your `posts`array
...
}
}
})
}

Related

Use of unresolved identifier 'self' (CoreData)

I am using this line below :
self.present(activityViewController, animated: true, completion: nil)
And I am getting an error of - Use of unresolved identifier 'self'. Any ideas about how to resolve this? To me it looks as it it is subordinate to the class, but clearly doing something wrong. Any help would be appreciated.
import UIKit
import CoreData
class CoreDataViewController: UIViewController {
#IBOutlet weak var CoreDataView: UITableView!
let context = (UIApplication.shared.delegate as! AppDelegate).persistentContainer.viewContext
var items:[Checkins]?
var btnnames = [""]
override func viewDidLoad() {
super.viewDidLoad()
// CoreDataView.dataSource = self
// CoreDataView.delegate = self
storeTranscription()
// Loads the current data
getTranscriptions()
// fetchCheckins()
let btn1name = btnnames[0]
let btn2name = btnnames[1]
let btn3name = btnnames[2]
let btn4name = btnnames[3]
let btn5name = btnnames[4]
let btn6name = btnnames[5]
// print(btnnames)
print(btn1name, btn2name, btn3name, btn4name, btn5name, btn6name)
}
#IBAction func export(_ sender: Any) {
exportDatabase()
}
#IBOutlet weak var Table_label: UILabel!
}
var CheckinDate: Date? = Date()
var fetchedStatsArray: [NSManagedObject] = []
let context = (UIApplication.shared.delegate as! AppDelegate).persistentContainer.viewContext
func storeTranscription() {
//retrieve the entity that we just created
let entity = NSEntityDescription.entity(forEntityName: "Checkins", in: context)
let transc = NSManagedObject(entity: entity!, insertInto: context) as! Checkins
//set the entity values
transc.who = "Who"
transc.reason = "Reason for visit"
transc.date = CheckinDate
//save the object
do {
try context.save()
print("saved!")
} catch let error as NSError {
print("Could not save \(error), \(error.userInfo)")
} catch {
}
}
func getTranscriptions () {
//create a fetch request, telling it about the entity
let fetchRequest: NSFetchRequest<Checkins> = Checkins.fetchRequest()
do {
//go get the results
let searchResults = try context.fetch(fetchRequest)
fetchedStatsArray = searchResults as [NSManagedObject]
//I like to check the size of the returned results!
print ("num of results = \(searchResults.count)")
//You need to convert to NSManagedObject to use 'for' loops
for trans in searchResults as [NSManagedObject] {
//get the Key Value pairs (although there may be a better way to do that...
print("\(trans.value(forKey: "who")!)")
let mdate = trans.value(forKey: "CheckinDate") as! Date
print(mdate)
}
} catch {
print("Error with request: \(error)")
}
}
func exportDatabase() {
let exportString = createExportString()
saveAndExport(exportString: exportString)
}
func saveAndExport(exportString: String) {
let exportFilePath = NSTemporaryDirectory() + "Checkins.csv"
let exportFileURL = NSURL(fileURLWithPath: exportFilePath)
FileManager.default.createFile(atPath: exportFilePath, contents: NSData() as Data, attributes: nil)
//var fileHandleError: NSError? = nil
var fileHandle: FileHandle? = nil
do {
fileHandle = try FileHandle(forWritingTo: exportFileURL as URL)
} catch {
print("Error with fileHandle")
}
if fileHandle != nil {
fileHandle!.seekToEndOfFile()
let csvData = exportString.data(using: String.Encoding.utf8, allowLossyConversion: false)
fileHandle!.write(csvData!)
fileHandle!.closeFile()
let firstActivityItem = NSURL(fileURLWithPath: exportFilePath)
let activityViewController : UIActivityViewController = UIActivityViewController(
activityItems: [firstActivityItem], applicationActivities: nil)
activityViewController.excludedActivityTypes = [
UIActivity.ActivityType.assignToContact,
UIActivity.ActivityType.saveToCameraRoll,
UIActivity.ActivityType.postToFlickr,
UIActivity.ActivityType.postToVimeo,
UIActivity.ActivityType.postToTencentWeibo
]
self.present(activityViewController, animated: true, completion: nil)
}
}
func createExportString() -> String {
var checkinwho: String?
var checkinreason: String?
var export: String = NSLocalizedString("who, reason, date \n", comment: "")
for (index, itemList) in fetchedStatsArray.enumerated() {
if index <= fetchedStatsArray.count - 1 {
checkinwho = Checkins.value(forKey: "who") as! String?
checkinreason = itemList.value(forKey: "reason") as! String?
let Datevar = Checkins.value(forKey: "date") as! Date
let whostring = checkinwho
let reasonstring = checkinreason
let DateSting = "\(Datevar)"
export += "\(whostring!),\(reasonstring!),\(DateSting) \n"
}
}
print("This is what the app will export: \(export)")
return export
}
Remove the } on this line
#IBOutlet weak var Table_label: UILabel!
}
and put another } at the end of this file.

Problem fetching data from firebase by using struct file

struct UserClass {
var babyName: String!
var babyHeight: String!
var babyWeight: String!
var babyURL: String!
var uid: String!
var reference:DatabaseReference!
var key: String!
init?(snapshot: DataSnapshot?) {
guard let value = snapshot?.value as? [String:AnyObject],
let uid = value["uid"] as? String,
let babyName = value["BabyName"] as? String,
let babyURL = value["BabyURL"] as? String,
let babyHeight = value["BabyHeight"] as? String,
let babyWeight = value["BabyWeight"] as? String else {
return nil
}
self.key = snapshot?.key
self.reference = snapshot?.ref
self.uid = uid
self.babyURL = babyURL
self.babyName = babyName
self.babyHeight = babyHeight
self.babyWeight = babyWeight
}
func getuserData() -> String {
return ("BabyName = \(babyName)")
}
}
func fetchCurrentUserInfo() {
var currentUserRef = Database.database().reference().child("Users").child("\(userID)")
handler = currentUserRef.queryOrderedByKey().observe(DataEventType.value, with: { (snapshot) in
print("User data = \(snapshot.value)")
let user = UserClass(snapshot: snapshot)
print(user?.babyName)
self.babyName.text = user?.babyName
})
}
I am getting user data but not user.babyName. How can I fix this?
May be this will help you, as the db structure is not mentioned in question. but you have to iterate children one by one and then use for loop to fetch the exact data from firebase.
reference = FIRDatabase.database().reference()
reference.child("Users").queryOrderedByKey().observe(DataEventType.value, with: { (snapshot) in
if let snapshots = snapshot.children.allObjects as? [FIRDataSnapshot] {
for snap in snapshots
{
let userId = child.childSnapshot(forPath: "userID").value! as! String
print(userId)
}
}
})

How to data pass array to dictionary in Alamofire

my json response array to dictioary but i am tring to get my data in show tableview.but my response in one key "member" and i want get data for a member key but getting some error.
I am trying to pass an array as a parameter to a Alamofier request .but i have not get data from my json i am getting some error my code i can not what i do....
My URL:
https://myfoodtalk.com:3001/api/restaurants?filter={"counts":"restaurant-comments","order":"created DESC","include":[{"relation":"follow-restaurants","scope":{"where":{"m_id":""}}},{"relation":"members"},{"relation":"favorite-restaurants","scope":{"where":{"m_id":""}}}]}
My model class:
class RestaurantsData: NSObject {
var title = String()
var descriptions = String()
var image1 = String()
var postcommentsCount = String()
var viewscount = String()
var created = String()
var members = [String:Any]()
var mbersdata = membersData()
func getRestaurentData(dataArray: [[String:Any]]) -> [RestaurantsData] {
var array = [RestaurantsData]()
let mObj = membersData()
for item in dataArray {
let obj = RestaurantsData()
obj.title = item.validatedValue("title", expected: String() as AnyObject) as! String
obj.descriptions = item.validatedValue("description", expected: String() as AnyObject) as! String
obj.image1 = item.validatedValue("image1", expected: String() as AnyObject) as! String
obj.postcommentsCount = item.validatedValue("post-commentsCount", expected: String() as AnyObject) as! String
obj.viewscount = item.validatedValue("views_count", expected: String() as AnyObject) as! String
obj.created = item.validatedValue("created", expected: String() as AnyObject) as! String
obj.members = item.validatedValue("members", expected: [String:Any]() as AnyObject) as! [String:Any]
obj.mbersdata = mObj.getMemberData(dataDic:obj.members)
array.append(obj)
}
return array
}
//Mark:- Class created for member data
class membersData: NSObject {
var photo = String()
var created = String()
var username = String()
func getMemberData(dataDic: [String:Any]) -> membersData {
let obj = membersData()
obj.username = dataDic.validatedValue("username", expected: String() as AnyObject) as! String
obj.created = dataDic.validatedValue("created", expected: String() as AnyObject) as! String
obj.photo = dataDic.validatedValue("photo", expected: String() as AnyObject) as! String
return obj
}
}
}
My code:- I'm using Alamofire
var dataArray = [RestaurantsData]()
//MARK: Web API calling
func ShowRestaurantsData(){
var params = [String:Any]
params = [
"counts":"restaurant-comments",
"order":"created DESC",
"include":[["relation":"follow-restaurants","scope":["where":["m_id":""]]],["relation":"members"],["relation":"favorite-restaurants","scope":["where":["m_id":""]]]
Alamofire.request( "https://myfoodtalk.com:3001/api/restaurants", method:.get, parameters: nil, headers: nil).responseJSON { (responseObject) -> Void in
switch responseObject.result
{
case .success(let value):
let dataArray = value as! [[String:Any]]
print("JSON Response:::::: \(dataArray)")
let obj = RestaurantsData()
self.dataArray = obj.getRestaurentData(dataArray: dataArray)
self.tableView.reloadData()
case .failure(let error):
print(error)
}
}
}
In your request,
Alamofire.request( "https://myfoodtalk.com:3001/api/restaurants", method:.get, parameters: nil, headers: nil).responseJSON { (responseObject) -> Void in
You are passing "
parameters as nil
which is wrong, pass "params"...

Posts Being Uploaded Randomly in Collection View - Swift & Firebase

I have been refactoring my code and now I'm having trouble with the posts.
Whenever I add a new post to the collection view, it is being added in a random cell and out of order, instead of in the first post.
I know the reason is the fetchuser function and from what I'm being told due to the asynchronous loading, but don't know what to do in order to correct this.
Could someone help me figure out what to do so that my posts are added in the first cell?
#objc func observePostsAdoption() {
let postsRef = Database.database().reference().child("posts")
postsRef.queryOrdered(byChild: "postType").queryEqual(toValue: "adopt").observe(.value) { (snapshot) in
var tempPost = [Posts]()
for child in snapshot.children {
if let childSnapshot = child as? DataSnapshot {
let dict = childSnapshot.value as? [String: Any]
let newAdoptiondPost = Posts.transformPost(dict: dict!)
//This will look up all users at once
self.fetchUser(userid: newAdoptiondPost.userid!, completed: {
tempPost.insert(newAdoptiondPost, at: 0)
DispatchQueue.main.async {
self.postsadoption = tempPost
self.adoptionCollectionView.reloadData()
self.refresherAdoption.endRefreshing()
}
})
}
}
}
}
func fetchUser(userid: String, completed: #escaping ()-> Void ) {
Database.database().reference().child("users").child(userid).observeSingleEvent(of: .value) { (snapshot) in
if let dict = snapshot.value as? [String: Any] {
let user = UserProfile.transformUser(dict: dict)
self.users.insert(user, at: 0)
completed()
}
}
}
Here's my Post Struct
class Posts {
//UserView
var uid: String?
var author: UserProfile?
var timestamp: Date?
var userid: String?
func getDateFormattedString() -> String {
let formatter = DateFormatter()
formatter.dateFormat = "MMM d, HH:mm"
return formatter.string(from: self.timestamp!)
}
//Image
var photoUrl: URL?
//PostInformation View
var city: String?
var municipality: String?
var name: String?
var breed : String?
var phone : String?
var address : String?
var petType: String?
var genderType: String?
var comments: String?
}
extension Posts {
static func transformPost(dict: [String: Any]) -> Posts {
let post = Posts()
//Post Picture
let photoUrl = dict["photoUrl"] as? String
post.photoUrl = URL(string: photoUrl!)
//INFO POSTS
post.userid = dict["userid"] as? String
post.city = dict["city"] as? String
post.municipality = dict["municipality"] as? String
post.name = dict["name"] as? String
post.breed = dict["breed"] as? String
post.phone = dict["phone"] as? String
post.address = dict["address"] as? String
post.comments = dict["comments"] as? String
post.petType = dict["petType"] as? String
post.genderType = dict["gender"] as? String
let timestamp = dict["timestamp"] as? Double
post.timestamp = Date(timeIntervalSince1970: timestamp!/1000)
return post
}
}
If you already have the posts ordered by post type you can just do sorting depending on the timestamp. For example
#objc func observePostsAdoption() {
let postsRef = Database.database().reference().child("posts")
postsRef.queryOrdered(byChild: "postType").queryEqual(toValue: "adopt").observe(.value) { (snapshot) in
var tempPost = [Posts]()
for child in snapshot.children {
if let childSnapshot = child as? DataSnapshot {
let dict = childSnapshot.value as? [String: Any]
let newAdoptiondPost = Posts.transformPost(dict: dict!)
//This will look up all users at once
self.fetchUser(userid: newAdoptiondPost.userid!, completed: {
tempPost.insert(newAdoptiondPost, at: 0)
DispatchQueue.main.async {
self.postsadoption = tempPost
self.postsadoption.sort { (p1, p2) -> Bool in
return p1.timeStamp?.compare(p2.timeStamp!) == .orderdDescending
}
self.adoptionCollectionView.reloadData()
self.refresherAdoption.endRefreshing()
}
})
}
}
}
}
With that the posts adoption array will be sorted depending on the timestamp that you have.

How do I filter data from my Firebase Database?

How do I change the fetchAllPosts function in my networking file and in the homeviewController so that I only get posts from the database that match the UID of the user I’m following with the post.UID, so my feed is filled with posts of users I follow?
Here is the reference showing how I make a new follower in the database:
let followingRef = "following/" + (self.loggedInUserData?["uid"] as! String) + "/" + (self.otherUser?["uid"] as! String)
Here is the post structure in the Firebase database
posts
-Ke4gQKIbow10WdLYMTL (generated key)
postDate:
postId:
postPicUrl:
postText:
postTit:
type:
uid: looking to match this
Here is the current fetchAllPosts function in the networking file
func fetchAllPosts(completion: #escaping ([Post])->()) {
let postRef = self.dataBaseRef.child("posts")
postRef.observe(.value, with: { (posts) in
var resultsArray = [Post]()
for post in posts.children {
let post = Post(snapshot: post as! FIRDataSnapshot)
resultsArray.append(post)
}
completion(resultsArray)
}) { (error) in
print(error.localizedDescription)
}
}
here is the fetchAllPosts function in the homeViewController
private func fetchAllPosts(){
authService.fetchAllPosts {(posts) in
self.postsArray = posts
self.postsArray.sort(by: { (post1, post2) -> Bool in
Int(post1.postDate) > Int(post2.postDate)
})
self.tableView.reloadData()
}
}
Here is my post structure in my swift file:
struct Post {
var username: String!
var uid: String!
var postId: String!
var type: String
var postText: String
var postTit: String
var postPicUrl: String!
var postDate: NSNumber!
var ref: FIRDatabaseReference!
var key: String = ""
init(postId: String,postText: String, postTit:String, postDate:NSNumber, postPicUrl: String?, type:String, uid: String, key: String = ""){
self.postText = postText
self.postTit = postTit
self.postPicUrl = postPicUrl
self.type = type
self.uid = uid
self.postDate = postDate
self.postId = postId
}
init(snapshot: FIRDataSnapshot){
self.ref = snapshot.ref
self.key = snapshot.key
self.postId = (snapshot.value! as! NSDictionary)["postId"] as! String
self.type = (snapshot.value! as! NSDictionary)["type"] as! String
self.postPicUrl = (snapshot.value! as! NSDictionary)["postPicUrl"] as! String
self.postDate = (snapshot.value! as! NSDictionary)["postDate"] as! NSNumber
self.postTit = (snapshot.value! as! NSDictionary)["postTit"] as! String
self.uid = (snapshot.value! as! NSDictionary)["uid"] as! String
self.postText = (snapshot.value! as! NSDictionary)["postText"] as! String
}
func toAnyObject() -> [String: Any] {
return ["postId":self.postId,"type":self.type, "postPicUrl":self.postPicUrl,"postDate":self.postDate, "postTit":self.postTit,"uid": self.uid, "postText":self.postText,]
}
}
Did you use this;
postRef.queryOrdered(byChild: "uid").queryEqual(toValue: yourUid).observe(.value, with: {
snapshot in
if let shot = snapshot {
let post = Post(snapshot: post as! FIRDataSnapshot)
}
}
This returns data you are looking for.