Fetch Parse Data based on Array - arrays

I have a PFQueryTableViewController.
I also have an array of numbers in a randomly generated order, from 1 to the Parse class count.
In Parse, each object in the class is assigned a number (1,2 ,3, etc.)
I want to fetch objects from this class in Parse to table view cells,and the order depends on the order of the array.
For example, my array would be [3, 2, 5, 1, 4]
I want to query where key "number" is equal to those numbers, in that order..
So far I have this:
// Define the query that will provide the data for the table view
override func queryForTable() -> PFQuery{
var query = PFQuery(className: "Stores")
for i in 1...10 {
query.whereKey("number", equalTo: numArray[i])
}
return query
}
and
//override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath, object: PFObject?) -> PFTableViewCell {
var cell = tableView.dequeueReusableCellWithIdentifier("cell") as! ExploreCell!
if cell == nil {
cell = ExploreCell(style: UITableViewCellStyle.Default, reuseIdentifier: "cell")
}
however, whenever i run, it only grabs information from 1 objects. My table view only has 1 cell that grabbed data.

I suppose that's Swift Code (I actually don't know Swift).
Anyway I don't see the need to (try to) query the objects in the order you want from array. Actually using query.whereKey more times you will just use the last one.
What you should do, is actually query the objects and then sort them (unless you want an ascending/descending order).
Also keep in mind that a Parse Query is asynchronous so probably structuring the function like you did won't work like you want.
EDIT: This is the kind of code you may want to use:
var query = PFQuery(className:"GameScore")
query.whereKey("playerName", equalTo:"Sean Plott")
query.findObjectsInBackgroundWithBlock {
(objects: [AnyObject]?, error: NSError?) -> Void in
if error == nil {
// The find succeeded.
println("Successfully retrieved \(objects!.count) scores.")
// Do something with the found objects
if let objects = objects as? [PFObject] {
for object in objects {
println(object.objectId)
}
}
} else {
// Log details of the failure
println("Error: \(error!) \(error!.userInfo!)")
}
}
The objects variable is the array you want to sort.
The Parse Documentation has been always useful to me to actually understand better Parse

Related

Passing a Model between View Controllers

I am struggling to pass a model of data from one controller to the next. I am sure I am just missing something very simple but hoping I can get some help.
Below I create the code to select all the data from the row that was selected:
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
tableView.deselectRow(at: indexPath, animated: true)
print(indexPath.row)
let passingData = arrivals[indexPath.row]
print(passingData)
let controller = storyboard?.instantiateViewController(withIdentifier: "FlightInfoVC") as! FlightInfoViewController
controller.flightDataPassedIn = passingData
//Code incomplete - Will add execution to show VC
}
That print statement is reflected below:
Now where I am struggling is to get that data to go to my next view controller. Setting the array of data in my new VC doesn't seem to work because it is expecting a type of 'FlightModel' but I cannot seem to figure out how to declare that. I have tried this but I cannot convert type [Any] to 'FlightModel'
var flightDataPassedIn: FlightModel = []
Appreciate any help you can give!
It sounds like the issue is that you're trying to initialize flightDataPassedIn with a value of [], which is of incompatible type [Any].
If you're okay with the flightDataPassedIn property on FlightInfoViewController being optional, that might be the most straightforward solution. It would automatically be initialized to nil, so would not require you to set an initial value - just declare it like this:
var flightDataPassedIn: FlightModel?
If you don't want it to be optional, initialize it to a default value of type FlightModel (add an initializer to FlightModel if necessary) and overwrite it with passingData from the parent ViewController.
Hope this helps!
The issue was that I was not passing the data via the main required function that everyone uses Prepare for segue
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "TrackingToInfo" {
if let destinationVC = segue.destination as? FlightInfoViewController {
destinationVC.flightDataPassedIn = readyToPass
}
}
}
Within the tableview I had to set the data to a var in my currentVC of type FlightModel? then the data passed

An array of user id's that you want to display information of; how do you filter for those elsewhere in the code?

Say you have a subset of users in an array via their uid. You want to display the information of these users in your application. So how do you use this array elsewhere in the code to only display for those uids.
There are 2 pages where I have to do this, and on one I managed to fix it with if self.array1.contains(people.key) However on the second page (I assume because it is structured differently), that does not work.
//Part 1: The array and current attempt
var array1 = [String]() ///this is at top of code before viewDidLoad
///In view did load
if let unwrappedName = name {
self.array1.append(unwrappedName)
}
}
print(self.array1, "ahah")
///Also in view did load, in a dataSnapshot, above the array definition
refArtists = Database.database().reference().child("people");
refArtists.observe(DataEventType.value, with: {snapshot in
for people in snapshot.children.allObjects as! [DataSnapshot] {
if people.key != thisUsersUid {
**if Calendar.current.isDateInToday(date) && countb >= 1 && self.array1.contains(people.key) {**
}
...
self.people.append(peopl)
...
self.people.sort(by: { $0.TodayLikeCount ?? 0 > $1.TodayLikeCount ?? 0 })
print("aaaaaaaa", self.people.map {$0.TodayLikeCount})
self.table.reloadData()
///How is this page structured:
1)class ranking: UITableViewController, CLLocationManagerDelegate{
2) All the definitions like var = this, let this = that etc
3)public override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int
4)public override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell ///Return cell is made here
5)override func viewDidLoad(), super.viewDidLoad(), table.dataSource = self, table.delegate = self
6) **The refArtist.obeseve snapshot posted above**
7)**The defining of the array**
8)Other code
For filtering an array and show it, you have to create another array and store the sorted results in that array, and use that array to reload the tableView. Also initially keep that array same as peopleArray by default. Then you can pass around this array to other pages as well.
var filteredArray = [String]() // declare at the top
Inside the viewDidLoad
filteredArray = self.people.sort(by: { $0.TodayLikeCount ?? 0 > $1.TodayLikeCount ?? 0 })
self.table.reloadData()
Hope you are clear.

Optional array is empty after appending elements inside it in Swift

My context is as follows: I have a view controller that draws different room shapes. Each wall is a subclass of UIView. The model for the walls is as follows:
struct Wall {
let name: String
let number: Int
var length: CGFloat?
var attachedObjects: [WallObject]?
var isSelected: Bool
}
So each wall has a property that gets assigned one of the above ones.
When a tap happens on one wall the sender gets stored into an optional variable:
#objc fileprivate func changeWallProperties(sender: UITapGestureRecognizer) {
guard let tappedWall = sender.view as? RoomShapeDrawingV else {print("could not get wall"); return}
tappedWall.wallModel?.isSelected = true
selectedWallModel = tappedWall.wallModel
I have a collection view that displays objects that can go on the wall. When a cell is selected I get a WallObject type that is another struct for the contents of the collection view, the selection needs to be placed into the model for the selected wall:
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
guard let aWallHasBeenSelected = isWallSelected else {print("could not get the selected wall"); return}
if aWallHasBeenSelected {
print("a wall has been selected")
let wallObject = wallObjects[indexPath.item]
selectedWallModel?.attachedObjects?.append(wallObject)
The last line does nothing, [attachedObjects] is nil inside the model for that selected wall. I have found a solution on this post: Adding elements to optional arrays in Swift
But I want to know why this happens, if there is a logical error on my behalf or what. Is it because I use structs and I make copies of them, or there is something else happening?

Getting array objects into NSTableView

I want to catch information from an array and display it into my NSTableView. I'm unsure what I need to do for that (I am very new to Swift and programming in general).
My table view looks like this:
I want to get value name from my array and display it in the name table with the NSTableView. I've found this tutorial on Ray Wenderlich but the code is very outdated and I don't want to use old things within my project which might not work anymore in newer OS versions.
It seems that I need an [NSTableViewDataSource numberOfRows][3] and viewFor.
Any examples on how to do this - maybe someone made this a few weeks ago with Swift 3? :D
The information within the array will be generated by the following:
var devices = [Device]()
let quantityDevices = quantityData.intValue
for i in 0...quantityDevices-1 {
let newDevice = Device()
print("created new device")
newDevice.name = titleData.stringValue + "-\(i)"
devices.append(newDevice)
}
print("now we have \(devices.count) devices in our array")
}
The important part of the code you need is the DataSource delegate functions:
extension ViewController : NSTableViewDataSource {
func numberOfRows(in tableView: NSTableView) -> Int {
return devices.count
}
func tableView(_ tableView: NSTableView, viewFor tableColumn: NSTableColumn?, row: Int) -> NSView? {
// 1 - get the device for this row
guard let device = devices[row] else {
return nil
}
// 2 - configure the cell with the device data
return nil
}
There is an example here on StackOverflow that should give a better example

NSIndexPath in Swift

I know, hopefully, that class NSIndexPath deals with arrays which has arrays.
I have this code:
import UIKit
class ViewController: UIViewController, UITableViewDataSource {
let devCourses = [
("iOS App Dev with Swift Essential Training","Simon Allardice"),
("iOS 8 SDK New Features","Lee Brimelow"),
("Data Visualization with D3.js","Ray Villalobos"),
("Swift Essential Training","Simon Allardice"),
("Up and Running with AngularJS","Ray Villalobos"),
("MySQL Essential Training","Bill Weinman"),
("Building Adaptive Android Apps with Fragments","David Gassner"),
("Advanced Unity 3D Game Programming","Michael House"),
("Up and Running with Ubuntu Desktop Linux","Scott Simpson"),
("Up and Running with C","Dan Gookin") ]
func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return 1
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return devCourses.count
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
var cell = UITableViewCell()
let (courseTitle, courseAuthor) = devCourses[indexPath.row]
cell.textLabel?.text = courseTitle
return cell
}
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
What I don't understand how NSIndexPath works. I have read documentation but is it still too hard for me to understand at this point of my learning how this works. How can I know NSIndexPath has property of row? Cans somebody explain every part of this line please:
let (courseTitle, courseAuthor) = devCourses[indexPath.row]
How does NSIndexPath know that courseTitle in this constant refers to index number 0 whitin array index 0 ("iOS App Dev with Swift Essential Training","Simon Allardice")
What I don't understand how NSIndexPath works.
For iOS, you can think of NSIndexPath as a read-only structure that contains two Int properties section and row if you're working with UITableViews or section and item if you're working with UICollectionViews.
You create them with the NSIndexPath:forRow:inSection: factory method:
let indexPath = NSIndexPath(forRow: 1, inSection: 0)
and read them by accessing their properties:
print("row is \(indexPath.row)")
How can I know NSIndexPath has property of row?
Xcode has some nice features to help you understand the code you are looking at. In Xcode, Option-click on row in the above statement line, and it will tell you what it is. In the pop-up, if you click on NSIndexPath UIKit Additions next to Reference, it will bring up the documentation.
Can somebody explain every part of this line please:
let (courseTitle, courseAuthor) = devCourses[indexPath.row]
devCourses is an array of tuples containing two values of type String. You can see this by option-clicking on devCourses and it shows [(String, String)]. Had it been an array of array of String it would have said [[String]] or [Array<String>] (which is two ways of saying the same thing).
indexPath.row is just an Int indicating the selected row of the tableView.
devCourses[indexPath.row] then is the tuple at that index. For example, if the row were 0, then the tuple would be ("iOS App Dev with Swift Essential Training","Simon Allardice").
Finally, you can initialize two variables simultaneously by declaring them as a tuple and initializing them with a tuple. For example:
let (a, b) = (3, 4)
creates two Int constants a and b and assigns 3 to a and 4 to b.
So this statement is retrieving the tuple from the array indicated by the integer indexPath.row and creating two variables, assigning the first variable courseTitle the value of the first value in the tuple and assigning the second variable courseAuthor the value of the second value in the tuple.
Update for Swift 3
NSIndexPath still exists in Foundation, but when working with indexPaths in Swift 3, a new type IndexPath is now used. This type is a structure.
You can still create an NSIndexPath in Swift 3, with the following updated syntax, but you can't change the properties:
var ip = NSIndexPath(row: 0, section: 0)
ip.row = 5 // Cannot assign to property: 'row' is a get-only property
but you should use the new IndexPath structure instead.
IndexPath is created with a similar syntax:
var ip2 = IndexPath(row: 0, section: 0)
ip2.row = 5 // this works
You can convert between IndexPath and NSIndexPath by casting with as:
let ip = NSIndexPath(row: 0, section: 0)
let ip2 = ip as IndexPath // convert to IndexPath
let ip3 = ip2 as NSIndexPath // convert back to NSIndexPath
All of the Cocoa and Cocoa Touch API's that use indexPaths have been converted to use IndexPath in Swift.
Slightly off topic, but I'd like to encourage everybody to use custom classes for the model rather than "primitive" types. There's a little effort but big benefit.
Simple class with two properties and a description (the description variable is helpful while debugging)
class DevCourse : Printable {
var author : String
var title : String
init(author : String, title : String) {
self.author = author
self.title = title
}
var description : String { return "DevCourse \(title) by \(author)"}
}
The devCourses array can be easily mapped to create the DevCourse instances with one line
let rawDevCourses = [
("iOS App Dev with Swift Essential Training","Simon Allardice"),
("iOS 8 SDK New Features","Lee Brimelow"),
("Data Visualization with D3.js","Ray Villalobos"),
("Swift Essential Training","Simon Allardice"),
("Up and Running with AngularJS","Ray Villalobos"),
("MySQL Essential Training","Bill Weinman"),
("Building Adaptive Android Apps with Fragments","David Gassner"),
("Advanced Unity 3D Game Programming","Michael House"),
("Up and Running with Ubuntu Desktop Linux","Scott Simpson"),
("Up and Running with C","Dan Gookin") ]
let devCourses = rawDevCourses.map { DevCourse(author: $0.1, title: $0.0) }
the lines to apply the properties look much clearer
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("MyIdentifier", forIndexPath: indexPath) as! UITableViewCell
let course = devCourses[indexPath.row]
cell.textLabel?.text = course.title
return cell
}

Resources