Adding Relational Data to a Class From User Class - Parse & Swift - ios

I have to classes in parse, one is showing the users and the other is showing tweets. Both of the classes has a username column. However, I need to add a relational data to the tweets class that will include the info of the user class object for each user. I tried lots of codes but I could not make it. The views of my two classes are attached. How would be the swift code that when someone enters a new tweet a relational input will also be created in the tweet class. My current tweet code is as below:
var tweetObj = PFObject(className: "tweets")
tweetObj["userName"] = PFUser.currentUser()!.username
tweetObj["profileName"] = PFUser.currentUser()!.valueForKey("profileName") as! String
tweetObj["photo"] = PFUser.currentUser()!.valueForKey("photo") as! PFFile
tweetObj["tweet"] = theTweet
tweetObj["tweetType"] = 1
if hasImage == true {
tweetObj["hasImage"] = "yes"
let imageData = UIImagePNGRepresentation(self.tweetImg.image)
let imageFile = PFFile(name: "tweetPhoto.png", data: imageData)
tweetObj["tweetImage"] = imageFile
} else {
tweetObj["hasImage"] = "no"
}
tweetObj.save()
println("tweet!")
self.dismissViewControllerAnimated(true, completion: nil)
}
http://i.imgur.com/blszoqn.png
http://i.imgur.com/fK4ghlq.png

Related

Coredata relationships how make ordered collection or added in particular index in iOS swift

I am working with core-data relationships add the student in profile entities.
Profile and Student entities are multiple relationship with each others.
Profile entities for create students, it successfully created.
I want to add or append some information that profile entities through student entities its also added.
(Its Like: Profile entities have a array of dictionary of student entities )
But when in display in UItableview added info of student it display in unordered.
I want to display the added student should be display in last or first.
Coredata is unordered collection of set. how to make it order.
Also selected ordered Arrangement. its shows error students not be ordered.
How can achieve this. Help me
Here my code:
func create(record: ProfileModel) {
let cdProfile = CDProfile(context: PersistentStorage.shared.context)
cdProfile.emailID = record.emailID
cdProfile.gender = record.gender
cdProfile.getDate = record.getDate
cdProfile.id = record.id
if(record.toStudent != nil && record.toStudent?.count != 0){
var studentSet = Set<CDStudent>()
record.toStudent?.forEach({ (student) in
let cdStudent = CDStudent(context: PersistentStorage.shared.context)
cdStudent.activity = student.activity
cdStudent.currentPage = Int16(student.currentPage ?? 0)
cdStudent.getPercentage = student.getPercentage
studentSet.insert(cdStudent)
})
cdProfile.toStudent = studentSet
}
PersistentStorage.shared.saveContext()
}
#IBAction func saveBtnClick(_ sender: Any) {
let studentArr = StudentModel(_activity: "S-\(self.sectionString)", _studentComments: self.infotextView.text, _getPercentage: "-", _result: String(self.audioValueKey.count), _sectionID: self.sectionString, _sessionDate: self.convertedDate, _timeSpend: self.timeSpendStr, _currentPage: self.allPageNumber, _selectedValue: self.audioValueKey)
if let getStudentData = userProfileArr![indexNumber].toStudent?.count{
self.personArrCount = getStudentData
let getArr = userProfileArr![indexNumber].toStudent!
if getArr.count == 0{
}else{
for j in 0..<getArr.count{
self.student.append(getArr[j])
// self.student.insert(getArr[j], at: 0)
}
self.student.append(studentArr)
}
}else{
self.personArrCount = 0
self.student.append(studentArr)
print("student-empty",student)
}
let getProfileData = userProfileArr![indexNumber]
let updatePerson = ProfileModel(_id: selectedUserIndex!.id, _profileComments: getProfileData.profileComments!, _emailID: getProfileData.emailID!, _gender: getProfileData.gender!, _profileImage: getProfileData.profileImage!, _getDate: "NO", _studentDOB: getProfileData.studentDOB!, _studentName: getProfileData.studentName!, _toStudent: student)
print("student",self.student)
if(dataManager.update(record: updatePerson))
{
print("Update added")
}else{
print("Not-- added")
}
}
How can i fix this issue help me... Thanks advance.
first of all Core data only provides sorting on parent table only
if you wanna sort data in a subtable you can do as below
First you need to add a field named student_id(int16) in student table
Then you need to assign value as count + 1
As core data does not provide autoincrement field need to manage manually.
Follow the below code to sort data as last to first
// assume you have fetched profile in stud_profile var
if let student_list = stud_profile.toStudent as? Set<CDStudent> {
let arrStudents = Array(student_list).sorted(by: {$0.student_id > $1.student_id})
}
4.You can use arrStudents as it will return sorted [CDStudent]

Downcast from Any to Specific type

I have firestore DB "sales", which has one column called saleapproveddate. There are 2 levels of people, one who logs sale and other approves the sale logs. While logging sale, I save the saleapproveddate as NSNull() (which saves as nil in firestore DB field). Approver can update the saleapproveddate as TimeStamp, but if the approver never approves the sale log, it remains as nil in firestore DB field. So it can have either nil or TimeStamp type.
I have model Sales
class Sale {
var saleapprovedate : Any?
}
When I load the data from firestore, I tried to downcast the saleapprovedate as Any
let approvedDate = document[SaleProperties.paidDate.rawValue] as Any
But the real challenge is, saleapprovedate can have either nil or Timestamp. How do I check for type condition, convert to specific type and display in label?
Below is what I tried:
While loading data:
sale.saleapprovedate = document[SaleProperties.saleapprovedate.rawValue] as Any
while displaying data:
let saleItem = sales[indexPath.row]
let paidDate = saleItem.saleapprovedate
if paidDate == nil {
cell.paidDateLabelContainer.text = "Yet to pay"
cell.paidStatusImageView.isHidden = true
}
else {
let paidDateTimeStamp = saleItem.saleapprovedate as! Timestamp
let convertedPaidDate = self.convertTimestampToDate(timeStamp: paidDateTimeStamp)
cell.paidDateLabelContainer.text = convertDateToString(date: convertedPaidDate)
cell.paidStatusImageView.isHidden = false
}
But the above code is not updating the cell label properly. I have two data, one has saleapprovedate as Timestamp and other as nil. Both the cell label is displaying as "Yet to pay". What is wrong?
Modal :
var incentivepaiddate : Any?
Array :
var sales : [Sale] = [Sale]()
Loading data from firestore :
for document in querySnapshot!.documents {
let sale = Sale()
sale.incentivepaiddate = document[SaleProperties.incentivepaiddate.rawValue]
self.sales.append(sale)
}
Checking for nil, downcasting to a specific type and display data in cell
let saleItem = sales[indexPath.row]
let paidDate = saleItem.incentivepaiddate
if let paid = paidDate {
let paidDateTimeStamp = paid as? Timestamp
let convertedPaidDate = self.convertTimestampToDate(timeStamp: paidDateTimeStamp!)
cell.paidDateLabelContainer.text = convertDateToString(date: convertedPaidDate)
}
else {
cell.paidDateLabelContainer.text = "Yet to pay"
cell.paidStatusImageView.isHidden = true
}
Hope this helps someone!

Save json dictionary to core data Swift 3

I am able to get the last guest dictionary value in the json array saved into core data as a dictionary using the transformable key value however the other guest dictionary values are not saving. Guest is also it's on entity for now but I was hoping to save the guest as a dictionary since this task doesn't require complex relationships. I'm sure I'm looking through the json, the value type for reservation.guest = [AnyHashable: Any]?Any suggestions would be helpful here is my json response https://pastebin.com/J28myW66, thanks
Note: using Alamofire for the HTTP Request. Also haven't included my entire class here as this is the main part of it. Reservation and Guest are both NSManagedObject classes
let managedObjectContext = CoreDataManager.shared.persistentContainer.viewContext
let reservationEntityDescription = NSEntityDescription.entity(forEntityName: "Reservation", in: managedObjectContext)
let guestEntityDescription = NSEntityDescription.entity(forEntityName: "Guest", in: managedObjectContext)
let reservation = Reservation(entity: reservationEntityDescription!, insertInto: managedObjectContext)
let guest = Guest(entity: guestEntityDescription!, insertInto: managedObjectContext)
let url = "\(serverEndpoint)\(path)"
manager?.request(
url
).responseJSON { responseData in
if(responseData.result.error != nil) {
print(responseData.response)
}
else if responseData.result.value != nil{
let json = JSON(responseData.result.value!)
let content = json["data"]
var reservationArray: [String] = []
if let dates = content.array {
for item in dates {
if let str = item["date_time"].string {
reservationArray.append(str)
print(reservationArray)
}
}
}
for (key,obj) in content {
let guestData = obj["guest"]
let guestDict = guestData.dictionaryObject!
reservation.guest = guestDict
reservation.id = obj["id"].stringValue
reservation.dateTime = obj["date_time"].date
reservation.startTime = obj["start_time"].time
reservation.numOfPeople = obj["number_of_people"].intValue as NSNumber?
reservation.status = obj["status"].stringValue
reservation.tables = obj["tables"].arrayObject as! [NSString]?
reservation.reservationCollections = reservationArray as [NSString]?
guest.id = guestData["id"].stringValue
guest.email = guestData["email"].stringValue
guest.name = guestData["full_name"].stringValue
guest.phone = guestData["phone"].stringValue
guest.notes = guestData["notes"].stringValue
}
print("Reservation to be saved\(reservation)")
print("Guest to be saved: \(guest)")
}
}
do {
try reservation.managedObjectContext?.save()
} catch let error as NSError {
fatalError(error.localizedDescription)
}
do {
try guest.managedObjectContext?.save()
} catch let error as NSError {
fatalError(error.localizedDescription)
}
When your code starts, you create one instance of Guest and one instance of Reservation:
let reservation = Reservation(entity: reservationEntityDescription!, insertInto: managedObjectContext)
let guest = Guest(entity: guestEntityDescription!, insertInto: managedObjectContext)
After that you never create any other instances. In your loop you assign values to this instance:
reservation.guest = guestDict
reservation.id = obj["id"].stringValue
...
guest.id = guestData["id"].stringValue
guest.email = guestData["email"].stringValue
...
But since there's only one instance, only the last pass through the loop gets saved. The first time through the loop you assign values to guest and reservation. Every other time, you overwrite the previous values with new ones.
If you want to save a new instance for every pass through the loop, you need to create new instances every time. Move the let guest = ... and let reservation = ... lines inside the loop.
Firstly you need to make design flow bit generic i.e The HTTP request/response, DataBase Part, Model Part and UI part.
Now create a generic model class for your response,
so that the values will bind in single object.
In you core data sub class your table i.e custom NSManagedObject Class.
First convert the dictionary objects [objects in content.array] into respective model class objects.
In that SBPlayer is a model class
Favourite+CoreDataProperties.swift & Favourite+CoreDataClass.swift are custom NSManagedObject class (auto-generated).
Now with every object, you have mapping respective properties in database table and in custom NSManagedObject class.
Map the values and Save it DataBase.
For example: https://github.com/Abhishek9634/ScoreBoard/blob/master/ScoreBoard/ScoreBoard/SBDBManager.swift
Reference : https://github.com/Abhishek9634/ScoreBoard

How to handle Empty PFFile objects (Parse backend, Swift)

I have a list of users stored on Parse (backend), with a column called "profile_picture" that stores the user's profile picture. However, there are certain users without a profile picture, thus their profile_picture column is "undefined" (has no value).
I am using a searchbar to query through all the users and update the tableview with the user's profile pic and username. I do this by appending the username to var searchResults = String , and the profile pic to var searchImages = PFFile after the query like so:
let query = PFQuery.orQuery(withSubqueries: [usernameQuery!,fbUsername!, firstnameQuery!, lastnameQuery!]);
searchActive = true;
query.findObjectsInBackground { (objects, error) in
if error != nil {
print("There was an error getting userlist");
}
else {
if let users = objects {
self.searchResults.removeAll(keepingCapacity: false);
for object in users {
if let user = object.object(forKey: "username") as? String {
self.searchResults.append(user);
}
if let picture = object.object(forKey: "profile_picture") as? PFFile {
self.searchImages.append(picture);
}
self.searchTableView.reloadData();
}
The problem is that when the "profile_picture" column is empty, it does not append anything, which then means that the searchResults array (containing usernames) and the searchImages array (containing the PFFiles) have different sizes, which results in uncoordinated assignments of values. They are supposed to parallel arrays. And I'm using values in these arrays to assign values in a table cell.
Hope you guys understand my problem! Thanks in advance
So your username field is definitely not empty. I think you can add an else after you check whether profile_picture is nil or not. Like:
if let picture = object.object(forKey: "profile_picture") as? PFFile {
self.searchImages.append(picture);
} else {
self.searchImages.append(UIImage(named:"placeholder"))
}

One to many relations Parse

I've looked all over but I can't find an answer to this question.
I am saving a Podcasts and its related episodes to Parse but the following code only saves 1 episode and the podcast (I suppose every entry found in the for loop resets currentP and only the last value found gets saved).
let currentP = PFObject(className: self.podcastClass)
currentP["user"] = PFUser.currentUser()
currentP["name"] = name
currentP["artist"] = artist
currentP["summary"] = summary
currentP["feedURL"] = feedURL
currentP["artworkURL"] = artworkURL
currentP["artwork"] = artwork
currentP["date"] = date
let episodesToParse = PFObject(className: self.episodesClass)
for episode in episodes {
episodesToParse["showDate"] = episode.date
episodesToParse["title"] = episode.title
episodesToParse["downloadURL"] = episode.enclosures[0].valueForKey("url") as? String
episodesToParse["showNotes"] = episode.summary
episodesToParse["localPath"] = ""
episodesToParse["isDownloaded"] = "no"
episodesToParse["parent"] = currentP
}
episodesToParse.saveInBackground()
If I use something like episodesToParse.addObject(episode.date, forKey: "showDate") then the following error is returned:
[Error]: invalid type for key showDate, expected date, but got array (Code: 111, Version: 1.8.1)
I'm not sure how to proceed. What I want is currentP to be saved as it is and all its episodes to be saved in a different class with a relationship to its parent (Podcast). I found tons of ways to do this if you're adding one episode at a time but not a whole bunch of them (I would like to be able to save 500 instance of episodesToParseat once.
Thanks for your help.
Your problem is, that you save the episodesToParse after the loop. You have to move the episodesToParse.saveInBackground() inside the loop so that everytime the loop sets the properties of the episode the episode gets updated:
for episode in episodes {
episodesToParse["showDate"] = episode.date
episodesToParse["title"] = episode.title
episodesToParse["downloadURL"] = episode.enclosures[0].valueForKey("url") as? String
episodesToParse["showNotes"] = episode.summary
episodesToParse["localPath"] = ""
episodesToParse["isDownloaded"] = "no"
episodesToParse["parent"] = currentP
//Inside
episodesToParse.saveInBackground()
}
Or you could use PFObject.saveAllInBackground to save all objects:
var episodesToSave[PFObject] = []
for episode in episodes {
var episodeToParse
episodeToParse["showDate"] = episode.date
episodeToParse["title"] = episode.title
episodeToParse["downloadURL"] = episode.enclosures[0].valueForKey("url") as? String
episodeToParse["showNotes"] = episode.summary
episodeToParse["localPath"] = ""
episodeToParse["isDownloaded"] = "no"
episodeToParse["parent"] = currentP
//Add to episode-array
episodesToSave.append(episodesToParse)
}
//Save all objects in the array
PFObject.saveAllInBackground(episodesToSave)

Resources