Variable not being saved outside closure - swift

I am using Parse for a database.
Problem: I am querying the database and saving an object, but it does not seem to be saving outside the query function. I think it is because I need to refresh a variable or something but I have no idea how to do that.
Relevant code:
class AddClassViewController: UIViewController {
var classroom = Classroom()
var checkClassList: [Classroom] = []
#IBAction func enrollClassButton(sender: AnyObject) {
self.classroom.classCode = classCodeText.text.uppercaseString
self.classroom.year = yearText.text
self.classroom.professor = professorNameText.text
ClassListParseQueryHelper.checkClass({ (result: [AnyObject]?,error: NSError?) -> Void in
self.checkClassList = result as? [Classroom] ?? []
//count is 1 inside here
println(self.checkClassList.count)
}, classCode: self.classroom.classCode!)
//count is 0 out here
println(self.checkClassList.count)
}
//this gets class with matching classcode
static func checkClass(completionBlock: PFArrayResultBlock, classCode: String){
let query = PFQuery(className: "Classroom")
query.whereKey("ClassCode", equalTo: classCode)
query.findObjectsInBackgroundWithBlock(completionBlock)
}

This is how I solved this:
class ClassListParseQueryHelper{
//this gets class with matching classcode
static func checkClass(classCode: String) -> [PFObject]{
let query = PFQuery(className: "Classroom")
query.whereKey("ClassCode", equalTo: classCode)
var test = query.findObjects() as! [PFObject]
return test
}
self.checkClassList = ClassListParseQueryHelper.checkClass(self.classroom.classCode!) as! [Classroom]

Related

fetched json data Dictionary or array is empty in viewdidload or tableview datasource?

I want to add strings from an array of dictionary from backend.
but it's always empty outside the fetch function
//fetch data
func fetchFaqs(){
let manager = APIManager()
manager.parsingGet(url: BaseURL.faqs) { (JSON, Status) in
if Status {
let dict = JSON.dictionaryObject
let data = dict!["data"] as! [[String:Any]]
self.faqs = data as! [[String : String]]
}
}
}
//Viewdidload
class FaqViewController: UIViewController,UITableViewDelegate,UITableViewDataSource {
var faqs = [[String:String]]()
var questions = NSMutableArray()
var answers = NSMutableArray()
#IBOutlet var faqsTableView: UITableView!
override func viewDidLoad() {
super.viewDidLoad()
fetchFaqs()
self.faqsTableView.reloadData()
print(faqs)
// faqsTableView.rowHeight = UITableView.automaticDimension
// faqsTableView.estimatedRowHeight = 600
}
}
Reload the tableview inside the api call closure in Main thread
func fetchFaqs(){
let manager = APIManager()
manager.parsingGet(url: BaseURL.faqs) { (JSON, Status) in
if Status {
let dict = JSON.dictionaryObject
let data = dict!["data"] as! [[String:Any]]
self.faqs = data as! [[String : String]]
DispatchQueue.main.async {
self.faqsTableView.reloadData()
}
}
}
}

query Object from Realm List

enter image description herei'm trying to query object from realm
class MessageRealm: Object {
dynamic var fromId = String()
dynamic var messageID = String()
dynamic var textDownloadded = String()
override class func primaryKey() -> String? {
return "messageID"
}
}
class UsersRealm: Object {
dynamic var sender = String()
let msgs = List<MessageRealm>()
override class func primaryKey() -> String? {
return "sender"
}
}
i have two class one for messages and the other for users, every users have a list of messages and i need to query thats message based on (UserRealm.sender)
This is the realm DB
I solve the issue by this way if anyone face the same
var messageIndex: Results<MessageRealm>!
let realm = try! Realm()
let mssagesRealm = realm.objects(UsersRealm.self).filter("sender = %#", userTitleName)
for sub in mssagesRealm {
messageIndex = sub.msgs.sorted(byKeyPath: "timeStamp")
}

Using Realm with MPMediaQuery

I want to build an Audiobookplayer which can set Bookmarks. Loading the Audiobooks from my Library with MPMediaQuery works fine, but when I take an audiobook off through iTunes, it stays in my realmfile.
I would like realm to delete the entry automatically when the playlist is updated through iTunes, but I can't seem to figure out how.
Here is my code.
class Books: Object {
dynamic var artistName: String?
dynamic var albumTitle: String?
dynamic var artwork: NSData?
dynamic var albumUrl: String?
dynamic var persistentID: String?
let parts = List<BookParts>()
override static func primaryKey() -> String? {
return "persistentID"
}
override class func indexedProperties() -> [String] {
return ["albumTitle"]
}
convenience init(artistName: String, albumTitle: String, albumUrl: String) {
self.init()
self.artistName = artistName
self.albumTitle = albumTitle
self.albumUrl = albumUrl
}
class BookQuery {
let realm = try! Realm()
var bookItems = Array<Books>()
var partItems = Array<BookParts>()
func getBooks() {
let query: MPMediaQuery = MPMediaQuery.audiobooks()
query.groupingType = .album
let collection: [MPMediaItemCollection] = query.collections!
try! realm.write {
for allbooks in collection {
let item = allbooks.representativeItem
let book = Books()
let id = item?.value(forProperty: MPMediaItemPropertyAlbumPersistentID) as! Int
book.artistName = item?.artist
book.albumTitle = item?.albumTitle
book.albumUrl = item?.assetURL?.absoluteString
book.artwork = Helper.getArtwork(item?.artwork) as NSData?
book.persistentID = id.stringValue
realm.add(book, update: true)
guard realm.object(ofType: Books.self, forPrimaryKey: "persistentID") != nil else {
continue
}
bookItems.append(book)
}
}
}
}
I calling the MediaQuery in "viewDidLoad" in my LibraryViewController.
I am pretty new to coding and are trying to solve this for a while.
Thanks for any help.
The high level thing you'll need to do is to have a way to detect when the iTunes playlist is updated and then delete the removed items' corresponding objects from the Realm.
A general approach to this is to get all the "persistent ID"s currently in the Realm at the start of the for loop, put those in an array, remove each ID it sees from the array, then delete objects with the persistent ID in the array that's left, since those weren't in the collection.

How to get all data for current user using Parse in Swift?

İ have a Parse app. İ want to get data from Parse class or database but for current user.
This is a poorly asked question, you provide no code nor do you show any effort on your own part to solve the problem. However, I myself remember struggling with this quite a but so here is how I accomplish this...
var arrayForData = Array()
var arrayForMoreData = Array()
var arrayForEvenMoreData = Array()
func fetchUserData() {
let userQuery: PFQuery = PFUser.query()!
userQuery.whereKey("username", equalTo: (currentUser?.username)!)
userQuery.findObjectsInBackgroundWithBlock({
(users, error) -> Void in
var someData = users!
var someMoreData = users!
var thirdSetOfData = users!
if error == nil {
if someData.count >= 1 {
for i in 0...users!.count-1 {
self.arrayForData.append(someData[i].valueForKey("columnNameParse1") as! Int)
self.arrayForMoreData.append(someMoreData[i].valueForKey("columnNameParse2") as! Double)
self.arrayForEvenMoreData.append(thirdSetOfData[i].valueForKey("columnNameParse3") as! String)
}
}
self.usersArray = users as! [PFUser]
self.tableView.reloadData()
} else {
print(error)
}
})
}

swift/parse: error when setting Parse data to labels

What I am trying to do is to have data from Parse be retrieved from columns by object order. All labels are connected to their respective outlets and all of the outputs retrieve their correct data.
When I run it and open a cell in the tableview it crashes and gives me Thread 1: EXC_BAD_INSTRUCTION (code=EXC>I386_INVOP, subcode=0x0) on this line: self.navBar.topItem?.title = output1 if I select the first cell, and then on this line: self.navBar.topItem?.title = output1b if I select the second cell.
Here is the full function:
firstObject is grabbing the first object in the "eventsdetail" column
secondObject is grabbing the second object in the "eventsdetail" column
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
var query = PFQuery(className: "eventsdetail")
let runkey = query.orderByAscending("ID")
runkey.findObjectsInBackgroundWithBlock {
(objects: [PFObject]?, error : NSError?) -> Void in
if error == nil {
if let objects = objects as [PFObject]! {
for object in objects {
var firstObject = objects[0]
var secondObject = objects[1]
let output1 = firstObject.objectForKey("navTitle") as! String!
let output2 = firstObject.objectForKey("articleTitle") as! String!
let output3 = firstObject.objectForKey("written") as! String!
let output4 = firstObject.objectForKey("date") as! String!
let output5 = firstObject.objectForKey("article") as! String!
let output1b = secondObject.objectForKey("navTitle") as! String!
let output2b = secondObject.objectForKey("articleTitle") as! String!
let output3b = secondObject.objectForKey("written") as! String!
let output4b = secondObject.objectForKey("date") as! String!
let output5b = secondObject.objectForKey("article") as! String!
if indexPath.row == 0 {
self.performSegueWithIdentifier("0a", sender: nil)
self.tableview.deselectRowAtIndexPath(indexPath, animated: true)
self.navBar.topItem?.title = output1
self.articleTitle.text = output2
self.writtenBy.text = output3
self.date.text = output4
self.article.text = output5
} else if indexPath.row == 1 {
self.performSegueWithIdentifier("0a", sender: nil)
self.tableview.deselectRowAtIndexPath(indexPath, animated: true)
self.navBar.topItem?.title = output1b
self.articleTitle.text = output2b
self.writtenBy.text = output3b
self.date.text = output4b
self.article.text = output5b
}
}
}
}
}
}
If there is an easier way of doing this, please mention it, if not try to just solve this method's problem. I know it isn't the cleanest way of doing things.
I am not sure of how you Parse your data but if it can help you, here's how I would do:
//
// Test.swift
// Test
//
// Created by Charles-Olivier Demers on 16-01-04.
//
import UIKit
//import Parse
class EventViewController: UIViewController, UITableViewDelegate {
private var _info = [EventDetails]()
override func viewDidLoad() {
fetchData()
}
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
self.performSegueWithIdentifier("0a", sender: nil)
self.tableview.deselectRowAtIndexPath(indexPath, animated: true)
self.navBar.topItem?.title.text = _info[indexPath.row].navTitle()
self.articleTitle.text = _info[indexPath.row].articleTitle()
self.writtenBy.text = _info[indexPath.row].writtenBy()
self.date.text = _info[indexPath.row].date()
self.article.text = _info[indexPath.row].article()
}
func fetchData() {
let query = PFQuery(className: "eventsDetails")
query.orderByAscending("ID")
query.findObjectsInBackgroundWithBlock { (objects: [PFObject]?, error: NSError?) -> Void in
if error == nil {
if let objects = objects {
for object in objects {
let navTitleObject = object["navTitle"] as! String
let articleTitleObject = object["articleTitle"] as! String
let writtenByObject = object["writtenByObject"] as! String
let dateObject = object["dateObject"] as! String
let articleObject = object["articleObject"] as! String
_info.append(EventDetails(navTitle: navTitleObject, articleTitle: articleTitleObject, writtenBy: writtenByObject, date: dateObject, article: articleObject))
}
}
}
else {
print("Error #\(error!.code)")
}
}
}
}
class EventDetails {
private var _navTitle: String!
private var _articleTitle: String!
private var _writtenBy: String!
private var _date: String!
private var _article: String!
init(navTitle: String, articleTitle: String, writtenBy: String, date: String, article: String) {
self._navTitle = navTitle
self._article = articleTitle
self._writtenBy = writtenBy
self._date = date
self._article = article
}
func navTitle() -> String {
return _navTitle
}
func articleTitle() -> String {
return _articleTitle
}
func writtenBy() -> String {
return _writtenBy
}
func date() -> String {
return _date
}
func article() -> String {
return _article
}
}
First of all, I would create a class named EventDetails. This class will take all the property of EventsDetails class on Parse. So when you fetch your data, you append the data you fetch in an array of EventDetails class in Swift.
After that in your
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath)
you take the value in your EventDetails array with the indexPath.row and you fill your Table View.
That is how I would do.