Friday, June 12, 2015

How to Custom Parse PFTableViewCell using Swift

Ok, let say you want to load some data from Parse into your custom made PFTableViewCell, below is the step by step

Step1: Drag a TableViewController into your main scene

Step2: Select your prototype cells, then change the style to "Custom", drag 4 label into your prototype cell and give them tag "10", "20", "30", "40"


Step3: Change the Class of your prototype cell to "PFTableViewCell", because you need to load data from Parse, so you need this


Step4: Create a new File -> Cocoa Touch Class
Class Name: MyTableViewController
SubClassName: PFQueryTableViewController

Then on the main scene, click your table view controller, set your class to "MyTableViewController"


Step5: Open your MyTableViewController.swift

put in the below code

////////////////////////////////////////////////////////////////////////////////////////////////////////

import UIKit
import Parse
import ParseUI

class MyTableViewController: PFQueryTableViewController {

override init!(style: UITableViewStyle, className: String!) {
        super.init(style: style, className: className)
            }

   required init(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
        
        // Configure the PFQueryTableView
        self.parseClassName = "Request"
        self.textKey = "item_wanted"
        self.pullToRefreshEnabled = true
        self.paginationEnabled = true 
       self.objectsPerPage = 25   
  
    }

 // Define the query that will provide the data for the table view
    override func queryForTable() -> PFQuery {
        var query = PFQuery(className: "Request")    
        query.includeKey("requester")

        return query
    }

override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath, object: PFObject?) -> PFTableViewCell {
        
        var cell = tableView.dequeueReusableCellWithIdentifier("Cell") as PFTableViewCell!
        if cell == nil {
            cell = PFTableViewCell(style: UITableViewCellStyle.Default, reuseIdentifier: "Cell")
        }


        if let mysubtitle = object?["email"] as? String {
                (cell.contentView.viewWithTag(10) as UILabel).text = mysubtitle
         }
        if let mysubtitle2 = object?["item_wanted"asString {
                (cell.contentView.viewWithTag(20as UILabel).text = mysubtitle2
         }
        if let mysubtitle3 = object?["city"asString {
                (cell.contentView.viewWithTag(30as UILabel).text = mysubtitle3
         }
        if let mysubtitle4 = object?["zipcode"asString {
                (cell.contentView.viewWithTag(40as UILabel).text = mysubtitle4
         }
        
        return cell
}

override func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
        return 50
    }
    

    override func viewDidLoad() {
        super.viewDidLoad()

        // Do any additional setup after loading the view.
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }

}

/////////////////////////////////////////////////////////////////////////////////
Code Explanation:
When you are using subclass of PFQueryTableViewController , you need to populate the below function

1.  required init(coder aDecoder: NSCoder)
- this is to initialize the Class, you need to tell which "Table" you want to request from Parse, my example I request to query the table "Request"

2. override func queryForTable() -> PFQuery {
- this is to write your query

3. override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath, object: PFObject?) -> PFTableViewCell {

- this is to specify what need to display on your cell 
- since we already tag our label with "10", "20", "30", "40" so we can populate data from Parse into the cell label by doing the coding below, my column "item_wanted" populate into the label with tag "10"

if let mysubtitle = object?["item_wanted"asString {
                (cell.contentView.viewWithTag(10as UILabel).text = mysubtitle
         }


here is my dummy data i loaded from Parse

hopefully it can hep you in some way

Swift Parse query multiple table and output into PFtableviewcell

Okay, let say I have 2 table in Parse, how do i query both of them and show it into PFtableviewcell?

Table 1: User
Column: username, email, address

Table 2: Request
Column: item_wanted, username

Note: username in Table2 is a "pointer" that point to Table 1 (you must use pointer)


import UIKit
import Parse
import ParseUI


class TableViewController2: PFQueryTableViewController {

override func queryForTable() -> PFQuery {
        var query = PFQuery(className: "Request")
        query.includeKey("username")
        return query

    }


override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath, object: PFObject?) -> PFTableViewCell {
        
        var cell = tableView.dequeueReusableCellWithIdentifier("Cell") as PFTableViewCell!
        if cell == nil {
            cell = PFTableViewCell(style: UITableViewCellStyle.Default, reuseIdentifier: "Cell")
        }


         if let myrequester = object?["username"] as? PFObject
        {
            if let myusername = myrequester["username"] as? String
            {
                   cell.textLabel?.text = myusername
            }
        }
        
     
        
        if let mysubtitle = object?["item_wanted"] as? String 
       {
            cell?.detailTextLabel?.text = mysubtitle
        }
        
        return cell
        
        
    }
}



///////////////////////////////////////////////////////////////

Key Note 1: You must use query.includeKey("username"), this mean you want Parse to include all the data from the table "User" using the key "username"

Key Note 2: Since it is double layer, you query table "Request" then into table "User" , so you need to access the data double layer
 if let myrequester = object?["username"asPFObject
        {
            if let myusername = myrequester["username"asString
            {
                   cell.textLabel?.text = myusername
            }
        }

you access the object["username") to get to the table "User" then you need to do it one more time myusername = myrequester["username"] 

hopefully I can help you in anyway, cheers



Thursday, June 11, 2015

Swift Convert CLLocation to Parse PFgeopoint

So let say you want to convert CLLocation to Parse PFGeopoint

let say your CLLocation = placemark.location

here is it





 user["geo"] = PFGeoPoint(location: placemark.location)

Monday, June 1, 2015

SWIFT HOW TO CONVERT ADDRESS TO COORDINATE IN MKMapview


Today I am trying to play around with MKMapview, I want to display location once the program is loaded,

a) Using coordinate (Step 1 to Step 7)
b) Using address I key in myself (Step 1 to Step 8)



Step1: Open Xcode

Step2: In Main Storyboard, drag MKMapview into your ViewController

Step3: Create a new file Cocoa Touch Class


Step4: Name it MapVC, Subclass of UIViewController


Step5: On the storyboard, click your MKMapView and on the right hand side -> "identity inspector" change the Class to "MapVC"



Step6: On the storyboard, click "Assistant Editor" on top to open the code side by side with your MKMapView, Control Drag your MKMapView to your "MapVC" code to create a variable connection,

see the diagram
@IBOutlet weak var mapView: MKMapView!




Step7: Put in the below code so once you open the app, it will load the location base on the coordinate i put

////////////////////////////////////////////////////////////////////////////

import UIKit
import MapKit
import CoreLocation

class MapVC: UIViewController
{
    @IBOutlet weak var mapView: MKMapView!
    var  initialLocation = CLLocation(latitude: 21.282778, longitude: -157.829444)

     

    override func viewDidLoad() {
        super.viewDidLoad()
        centerMapOnLocation(initialLocation)
    }


    func centerMapOnLocation(location: CLLocation)
    {
        
        let regionRadius: CLLocationDistance = 1000
        
        let coordinateRegion = MKCoordinateRegionMakeWithDistance(location.coordinate,
            regionRadius * 2.0, regionRadius * 2.0)
        mapView.setRegion(coordinateRegion, animated: true)
    }
}


/////////////////////////////////////////////////////////////////////

Code Explanation:
first you create a new variable "initialLocation" then you hardcode it with the coordinate you like

then you create a function "centerMapOnLocation" that set the mapView region to 1000 meter within the coordinate you give

finally on viewDidLoad() you call this function providing the parameter "initialLocation"



Step8: If you want to use the address instead, then you need to convert the address into coordinate, to do this, modify the MapVC.swift to below
////////////////////////////////////////////////////////////////////////////////////////

import UIKit
import MapKit
import CoreLocation

class MapVC: UIViewController
{
    @IBOutlet weak var mapView: MKMapView!
    var  initialLocation = CLLocation(latitude: 21.282778, longitude: -157.829444)

     

    override func viewDidLoad() {
        super.viewDidLoad()
       var address = "1 Infinite Loop, CA, USA"
        var geocoder = CLGeocoder()
        geocoder.geocodeAddressString(address, {(placemarks: [AnyObject]!, error: NSError!) -> Void in
            if let placemark = placemarks?[0] as? CLPlacemark
            {
               
                self.initialLocation = placemark.location
                self.centerMapOnLocation(self.initialLocation)
               
            }
        })
    }


    func centerMapOnLocation(location: CLLocation)
    {
        
        let regionRadius: CLLocationDistance = 1000
        
        let coordinateRegion = MKCoordinateRegionMakeWithDistance(location.coordinate,
            regionRadius * 2.0, regionRadius * 2.0)
        mapView.setRegion(coordinateRegion, animated: true)
    }
}


/////////////////////////////////////////////////////////////////////

Code Explanation, so here you create a new variable "address" and type in the address that you like, then you use the CLGeocoder to convert the address into coordinate, load the coordinate into "initialLocation" then finally call the function "centerMapOnLocation" to display it in the map


There you go, hopefully it can help you in some way