I have the following code, and now I am trying to implement accessory to the UITableView.
All the data is from Parse, even though there are tutorials out there helping out on how to do normal accessory, I am unable to find one that actually teaches on how to do that if I am getting data from online db like Parse.
//
// Listdoctors.swift
// ihealthtwo
//
// Created by David on 10/1/16.
// Copyright © 2016 ƒ. All rights reserved.
//
import UIKit
import Parse
class Listdoctors: UITableViewController {
#IBOutlet var listdoctors: UITableView!
var doctorName = [String]()
var doctorRate = [NSInteger]()
var doctorDetail = [String]()
var refresher: UIRefreshControl!
func refresh()
{
let query = PFQuery(className: "doctors")
query.orderByDescending("createdAt")
query.findObjectsInBackgroundWithBlock(
{
(listll: [PFObject]?, error: NSError?) -> Void in
if error == nil {
// The find succeeded.
print("Successfully retrieved \(listll!.count) names of the lawyers.")
// Do something with the found objects
if let objects = listll {
for object in objects {
print(object)
self.doctorName.append(object["doctorName"] as! String)
self.doctorRate.append(object["Rate"] as! NSInteger)
self.doctorDetail.append(object["doctorContent"] as! String)
// print(object["Lawyer_Name"] as! String )
// self.lawyersname.append(object["Lawyer_Name"] as! String)
//self.lblName.text = object["Lawyer_Name"] as? String
}
self.listdoctors.reloadData()
}
print(self.doctorName.count)
} else {
// Log details of the failure
print("Error: \(error!) \(error!.userInfo)")
}
self.tableView.reloadData()
self.refresher.endRefreshing()
})
}
override func viewDidLoad() {
super.viewDidLoad()
refresher = UIRefreshControl()
refresher.attributedTitle = NSAttributedString(string: "Pull to refrehsh")
refresher.addTarget(self, action: "refresh", forControlEvents: UIControlEvents.ValueChanged)
self.tableView.addSubview(refresher)
refresh()
// Uncomment the following line to preserve selection between presentations
// self.clearsSelectionOnViewWillAppear = false
// Uncomment the following line to display an Edit button in the navigation bar for this view controller.
// self.navigationItem.rightBarButtonItem = self.editButtonItem()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
// MARK: - Table view data source
override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
// #warning Incomplete implementation, return the number of sections
return 1
}
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
// #warning Incomplete implementation, return the number of rows
return doctorName.count
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let doctorcell: doctorsCell = tableView.dequeueReusableCellWithIdentifier("doctorsproto") as! doctorsCell
// Configure the cell...
doctorcell.doctorname.text = doctorName[indexPath.row]
doctorcell.doctorcontent.text = doctorDetail[indexPath.row]
doctorcell.doctorrate.text = "\(doctorRate [indexPath.row])"
//lawyercell.lblExpll.text = lawyerExp[indexPath.row]
//lawyercell.lblPracareall.text = lawyerPracArea[indexPath.row]
//profImages[indexPath.row].getDataInBackgroundWithBlock{(imageData: NSData?, error: NSError?) -> Void in
// if imageData != nil {
// let image = UIImage(data: imageData!)
// lawyercell.imageLawyer.image = image
// }
// else
// {
// print(error)
// } }
return doctorcell
}
override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath)
{
print(indexPath.row)
}
// MARK: - Navigation to doctor detail
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if let identifier = segue.identifier
{
switch identifier
{
doctor "TodoctorDetail":
let productDetailVC = segue.destinationViewController as! doctorDetail
if let indexPath = self.tableView.indexPathForCell(sender as! UITableViewCell)
{
}
default: break
}
}ˍ
}
//MARK: - Helper Method
//func productAtIndexPath(indexPath: NSIndexPath) ->?? (waht should i Put here)
}
My last line of code is not what I am sure what I exactly need to return, this is a example I am following from
https://www.youtube.com/watch?v=c-E_EbMR9wA
From the looks of it, you're trying to pass your data to a detail view which in this case you should be doing something like this assuming you have the proper indexPath and variables defined in the detailView already.
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if let identifier = segue.identifier
{
switch identifier
{
doctor "TodoctorDetail":
let productDetailVC = segue.destinationViewController as! doctorDetail
if let indexPath = self.tableView.indexPathForCell(sender as! UITableViewCell)
{
// Assuming you have the proper indexPath defined here for the selected cell and that you have these three values already defined in your productDetailVC
productDetailVC.doctorName = doctorName[indexPath.row]
productDetailVC.doctorContent = doctorContent[indexPath.row]
productDetailVC.doctorRate = doctorRating[indexPath.row]
}
default: break
}
}ˍ
}
Related
When I use NSUserDefaults, it is not working and reloading the data on the tableView. I have a page to add an item, but it shows the item added, and when I open it again, it is not saving. here is my full code.
import UIKit
var noteTitles = [String]()
var text = [String]()
class TableViewController: UITableViewController {
override func viewDidAppear(animated: Bool) {
tableView.reloadData()
}
override func viewDidLoad() {
super.viewDidLoad()
if NSUserDefaults.standardUserDefaults().objectForKey("note") != nil {
noteTitles = NSUserDefaults.standardUserDefaults().objectForKey("note") as! [String]
}
// Uncomment the following line to preserve selection between presentations
// self.clearsSelectionOnViewWillAppear = false
// Uncomment the following line to display an Edit button in the navigation bar for this view controller.
// self.navigationItem.rightBarButtonItem = self.editButtonItem()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
// MARK: - Table view data source
override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
// #warning Incomplete implementation, return the number of sections
return 1
}
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
// #warning Incomplete implementation, return the number of rows
return noteTitles.count
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("Cell", forIndexPath: indexPath) as! UITableViewCell
cell.textLabel?.text = noteTitles[indexPath.row]
// Configure the cell...
return cell
}
I don't know what is going wrong, and Xcode does not show any errors or warnings. What did I do wrong, and how would I fix it?
I don't see where you saved your value.
You have to save it first, then call synchronize method so that value can be saved.
NSUserDefaults.standUserDefaults().setObject(noteTitles, forKey: "note")
NSUserDefaults.standardUserDefaults().synchronize()
If you are working with NSUserDefaults at many places.
You could use below structure.
In AppDelegate
func saveToDefaults(ObjectToSave : AnyObject? , KeyToSave : String)
{
let defaults = NSUserDefaults.standardUserDefaults()
if (ObjectToSave != nil)
{
defaults.setObject(ObjectToSave, forKey: KeyToSave)
}
else
{
defaults.removeObjectForKey(KeyToSave)
}
NSUserDefaults.standardUserDefaults().synchronize()
}
func getFromDefaults(KeyToReturnValye : String) -> AnyObject?
{
let defaults = NSUserDefaults.standardUserDefaults()
if let name = defaults.valueForKey(KeyToReturnValye)
{
return name
}
return nil
}
struct defaultKeys
{
static let key_note = “notes”
. . .
. . .
}
Throughout application development whenever you want to access defaults. you could use code like below.
let appDelegate = UIApplication.sharedApplication().delegate as! AppDelegate
appDelegate.saveToDefaults(“Value”, KeyToSave: appDelegate.defaultKeys.key_note)
appDelegate.getFromDefaults(appDelegate.defaultKeys.key_note)
I have a really specific problem. I want to access and present to a table view the user's contact list. The problem is that when I run the code I access only one contact from the contact list. I'm trying to think what I should change but nothing so far. Given the code below what I need to change the achieve the result that I want? Here is the code:
import UIKit
import Contacts
import AddressBook
class MasterViewController: UITableViewController {
var detailViewController: DetailViewController? = nil
var objects = [CNContact]()
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
let addExisting = UIBarButtonItem(title: "Add Existing", style: .Plain, target: self, action: #selector(MasterViewController.addExistingContact))
self.navigationItem.leftBarButtonItem = addExisting
if let split = self.splitViewController {
let controllers = split.viewControllers
self.detailViewController = (controllers[controllers.count-1] as! UINavigationController).topViewController as? DetailViewController
}
NSNotificationCenter.defaultCenter().addObserver(self, selector: #selector(MasterViewController.insertNewObject(_:)), name: "addNewContact", object: nil)
self.getContacts()
}
func getContacts() {
let store = CNContactStore()
if CNContactStore.authorizationStatusForEntityType(.Contacts) == .NotDetermined {
store.requestAccessForEntityType(.Contacts, completionHandler: { (authorized: Bool, error: NSError?) -> Void in
if authorized {
self.retrieveContactsWithStore(store)
}
})
} else if CNContactStore.authorizationStatusForEntityType(.Contacts) == .Authorized {
self.retrieveContactsWithStore(store)
}
}
func retrieveContactsWithStore(store: CNContactStore) {
do {
let groups = try store.groupsMatchingPredicate(nil)
let predicate = CNContact.predicateForContactsInGroupWithIdentifier(groups[0].identifier)
//let predicate = CNContact.predicateForContactsMatchingName("John")
let keysToFetch = [CNContactFormatter.descriptorForRequiredKeysForStyle(.FullName), CNContactEmailAddressesKey]
let contacts = try store.unifiedContactsMatchingPredicate(predicate, keysToFetch: keysToFetch)
self.objects = contacts
dispatch_async(dispatch_get_main_queue(), { () -> Void in
self.tableView.reloadData()
})
} catch {
print(error)
}
}
func addExistingContact() {
}
override func viewWillAppear(animated: Bool) {
self.clearsSelectionOnViewWillAppear = self.splitViewController!.collapsed
super.viewWillAppear(animated)
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func insertNewObject(sender: NSNotification) {
if let contact = sender.userInfo?["contactToAdd"] as? CNContact {
objects.insert(contact, atIndex: 0)
let indexPath = NSIndexPath(forRow: 0, inSection: 0)
self.tableView.insertRowsAtIndexPaths([indexPath], withRowAnimation: .Automatic)
}
}
// MARK: - Segues
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if segue.identifier == "showDetail" {
if let indexPath = self.tableView.indexPathForSelectedRow {
let object = objects[indexPath.row]
let controller = (segue.destinationViewController as! UINavigationController).topViewController as! DetailViewController
controller.contactItem = object
controller.navigationItem.leftBarButtonItem = self.splitViewController?.displayModeButtonItem()
controller.navigationItem.leftItemsSupplementBackButton = true
}
}
}
// MARK: - Table View
override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return 1
}
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return objects.count
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("Cell", forIndexPath: indexPath)
let contact = self.objects[indexPath.row]
let formatter = CNContactFormatter()
cell.textLabel?.text = formatter.stringFromContact(contact)
cell.detailTextLabel?.text = contact.emailAddresses.first?.value as? String
return cell
}
override func tableView(tableView: UITableView, canEditRowAtIndexPath indexPath: NSIndexPath) -> Bool {
// Return false if you do not want the specified item to be editable.
return false
}
}
This is how I currently get a list of the user's contacts and store them in a CNContact array.
let request = CNContactFetchRequest(keysToFetch: [CNContactEmailAddressesKey, CNContactFormatter.descriptorForRequiredKeysForStyle(.FullName)])
var contacts = [CNContact]()
do {
try store.enumerateContactsWithFetchRequest(request) { contact, stop in
contacts.append(contact)
}
self.objects = contacts
NSOperationQueue.mainQueue().addOperationWithBlock({
self.tableView.reloadData()
})
} catch {
print(error)
}
I'm assuming your problem is with the line groupsMatchingPredicate(nil), where you don't pass in a predicate so it can't find any matches. Just a thought.
I am attempting to display data from Parse onto the following tableView controller. For some reason, the data is not displaying on the tableView (i.e. the rows are blank). I do not think that the data queried from Parse is being appended to the arrays. I am wondering what I'm doing wrong here.
Here's the current output:
I am using a custom prototype cell with identifier "CellTrack" class "TrackTableViewCell" and as shown below:
Here is my code in the TableViewController file:
import UIKit
import Parse
class MusicPlaylistTableViewController: UITableViewController {
var usernames = [String]()
var songs = [String]()
var dates = [String]()
override func viewDidLoad() {
super.viewDidLoad()
}
override func viewWillAppear(animated: Bool) {
var query = PFQuery(className:"PlaylistData")
query.findObjectsInBackgroundWithBlock { (objects: [PFObject]?, error: NSError?) -> Void in
if error == nil {
if let objects = objects! as? [PFObject] {
self.usernames.removeAll()
self.songs.removeAll()
self.dates.removeAll()
for object in objects {
let username = object["username"] as? String
self.usernames.append(username!)
print("added username")
let track = object["song"] as? String
self.songs.append(track!)
let date = object["createdAt"] as? String
self.dates.append(date!)
self.tableView.reloadData()
}
}
} else {
print(error)
}
}
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
// MARK: - Table view data source
override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
// #warning Incomplete implementation, return the number of sections
return 1
}
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
// #warning Incomplete implementation, return the number of rows
return usernames.count
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("CellTrack", forIndexPath: indexPath) as! TrackTableViewCell
cell.username.text = usernames[indexPath.row]
cell.songTitle.text = songs[indexPath.row]
cell.CreatedOn.text = dates[indexPath.row]
return cell
}
}
And here is my code in the "TrackTableViewCell.swift" class:
import UIKit
class TrackTableViewCell: UITableViewCell {
#IBOutlet weak var songTitle: UILabel!
#IBOutlet weak var username: UILabel!
#IBOutlet weak var CreatedOn: UILabel!
override func awakeFromNib() {
super.awakeFromNib()
// Initialization code
}
override func setSelected(selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
// Configure the view for the selected state
}
}
Execute your tableView.reloadData() in main thread.
dispatch_async(dispatch_get_main_queue(), {
self.tableViewCell.reloadData()
})
Try doing a guard let to see if those values are actually coming back as string or not. My guess would be that the value for created at never came back. Try it out and let me know.
guard let username = object["username"] as? String else {
print ("could not get username")
}
self.usernames.append(username)
print("added username")
guard let track = object["song"] as? String else {
print ("could not get song")
return
}
self.songs.append(track)
guard let date = object["createdAt"] as? String else {
print ("could not get createdAt")
return}
self.dates.append(date!)
func dequeueReusableCellWithIdentifier(_ identifier: String) -> UITableViewCell?
Return Value
A UITableViewCell object with the associated identifier or nil if no such object exists in the reusable-cell queue.
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
var cell = tableView.dequeueReusableCellWithIdentifier("CellTrack", forIndexPath: indexPath) as! TrackTableViewCell
if cell == nil {
// create a new cell here
cell = TrackTableViewCell(...)
}
cell.username.text = usernames[indexPath.row]
cell.songTitle.text = songs[indexPath.row]
cell.CreatedOn.text = dates[indexPath.row]
return cell
}
I have an error that idk how to fix it. The error is: "Definition conflicts with previous value." I have copied the code below and starred the portion which is flagged.
Thanks in advance.
import UIKit
import Parse
class ScienceTableViewController: UITableViewController, UITableViewDataSource {
var dataRecords = [Data]()
override func viewDidLoad() {
super.viewDidLoad()
override func viewWillAppear(animated: Bool) {
super.viewWillAppear(animated)
dataRecords = [Data]()
let query = PFQuery(className: "data")
query.findObjectsInBackgroundWithBlock { (objects: [AnyObject]?, error: NSError?) -> Void in
if error == nil {
for object in objects! {
let data = Data(objectID: object.valueForKey("objectId")! as! String, title: object.valueForKey("title")! as! String, date: object.valueForKey("date")! as! String, information: object.valueForKey("information")! as! String)
self.dataRecords.append(data)
self.tableView.reloadData()
}
} else {
print(error)
}
}
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
// MARK: - Table view data source
override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return dataRecords.count > 0 ? 1 : 0
}
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return dataRecords.count
}
**override func tableView(tableView: UITableView**, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("Cell", forIndexPath: indexPath)
// Configure the cell...
let title = dataRecords[indexPath.row].title
let date = dataRecords[indexPath.row].date
let information = dataRecords[indexPath.row].information
cell.textLabel?.text = title
cell.detailTextLabel?.text = date
return cell
}
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
let controller: ViewController = segue.destinationViewController as! ViewController
if segue.identifier == "newData" {
controller.objectID = ""
} else if segue.identifier == "showData" {
let indexPath: NSIndexPath = self.tableView.indexPathForSelectedRow!
controller.objectID = dataRecords[indexPath.row].objectID
}
}
}}
I am also getting problems with xCode where it claims "Xcode encountered a problem. Source editor functionality is limited. Attempting to restore" and the editor does not recognize the code for brief moments.
I believe your issue is with the class declaration line that has UITableViewDataSource as a protocol. A UiTableViewController already is a data source so that is redundant and should be removed.
Below is my code. After testing the app for a bit I realized that the didSelectRowAtIndex is run AFTER prepareForSegue. How can I get didSelectRowAtIndex to run first.
If the answer involves threading, I have no idea how that works so please explain. Thank-you.
import UIKit
class AvailableShifts: UITableViewController {
var shiftData: NSMutableArray = NSMutableArray()
var shiftID: String!
override func viewDidAppear(animated: Bool) {
super.viewDidAppear(true)
// self.refreshControl = UIRefreshControl()
//
// self.refreshControl?.addTarget(self, action: "refreshList", forControlEvents: .ValueChanged)
loadData()
// Uncomment the following line to preserve selection between presentations
// self.clearsSelectionOnViewWillAppear = false
// Uncomment the following line to display an Edit button in the navigation bar for this view controller.
// self.navigationItem.rightBarButtonItem = self.editButtonItem()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
// MARK: - Table view data source
override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
// #warning Potentially incomplete method implementation.
// Return the number of sections.
return 1
}
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
// #warning Incomplete method implementation.
// Return the number of rows in the section.
return shiftData.count
}
override func tableView(tableView: UITableView?, cellForRowAtIndexPath indexPath: NSIndexPath?) -> UITableViewCell {
let cell:AvailableShiftsCell = tableView!.dequeueReusableCellWithIdentifier("Cell", forIndexPath: indexPath!) as AvailableShiftsCell
let shift: PFObject = shiftData.objectAtIndex(indexPath!.row) as PFObject
cell.locationLabel.text = shift.objectForKey("Location") as String?
cell.shiftLabel.text = shift.objectForKey("Shift") as String?
cell.dateLabel.text = shift.objectForKey("Date") as String?
cell.id.text = shift.objectId
return cell
}
override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
let shift: PFObject = shiftData.objectAtIndex(indexPath.row) as PFObject
shiftID = shift.objectId
println(shiftID)
}
func loadData () {
var getShifts = PFQuery(className: "Shifts")
getShifts.findObjectsInBackgroundWithBlock {
(objects:[AnyObject]!, error:NSError!) -> Void in
if (error == nil) {
self.shiftData.removeAllObjects()
for object in objects {
self.shiftData.addObject(object)
}
let array: NSArray = self.shiftData.reverseObjectEnumerator().allObjects
self.shiftData = array.mutableCopy() as NSMutableArray
self.tableView.reloadData()
}
}
}
#IBAction func refreshButtonPressed(sender: AnyObject) {
loadData()
}
// func refreshList() {
//
// loadData()
//
// self.refreshControl?.endRefreshing()
//
// }
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject!) {
if (segue.identifier == "details") {
var svc = segue.destinationViewController as ShiftOverview;
svc.shiftID = shiftID
println(shiftID)
}
}
}
There's no need to implement didSelectRowAtIndexPath at all for your application. If the segue is made from the cell, then the sender argument in prepareForSegue:sender: will be the cell. You can use the table view method indexPathForCell: to get the indexPath, and thus the PFObject you need.