create tableview inside tableviewcell using swift - xcode

well i create tableview and inside of it tableview cell with xib file
now i want create tableview inside xib file , the main problem is that u can't create cell inside of it to define the identifier for this cell
i keep get this error
'unable to dequeue a cell with identifier AutoCompleteRowIdentifier -
must register a nib or a class for the identifier or connect a
prototype cell in a storyboard'
this is my code
import UIKit
class TableViewCell2: UITableViewCell, UITableViewDelegate, UITableViewDataSource, UITextFieldDelegate {
#IBOutlet weak var textField: UITextField!
#IBOutlet weak var autocompleteTableView: UITableView!
var pastUrls = ["Men", "Women", "Cats", "Dogs", "Children"]
var autocompleteUrls = [String]()
func textField(textField: UITextField, shouldChangeCharactersInRange range: NSRange, replacementString string: String) -> Bool
{
autocompleteTableView.hidden = false
let substring = (textField.text! as NSString).stringByReplacingCharactersInRange(range, withString: string)
searchAutocompleteEntriesWithSubstring(substring)
return true // not sure about this - could be false
}
func searchAutocompleteEntriesWithSubstring(substring: String)
{
autocompleteUrls.removeAll(keepCapacity: false)
for curString in pastUrls
{
var myString:NSString! = curString as NSString
var substringRange :NSRange! = myString.rangeOfString(substring)
if (substringRange.location == 0)
{
autocompleteUrls.append(curString)
}
}
autocompleteTableView.reloadData()
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return autocompleteUrls.count
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let autoCompleteRowIdentifier = "AutoCompleteRowIdentifier"
let cell : UITableViewCell = tableView.dequeueReusableCellWithIdentifier(autoCompleteRowIdentifier, forIndexPath: indexPath) as UITableViewCell
let index = indexPath.row as Int
cell.textLabel!.text = autocompleteUrls[index]
return cell
}
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
let selectedCell : UITableViewCell = tableView.cellForRowAtIndexPath(indexPath)!
textField.text = selectedCell.textLabel!.text
}
override func awakeFromNib() {
super.awakeFromNib()
textField.delegate = self
autocompleteTableView.delegate = self
autocompleteTableView.dataSource = self
autocompleteTableView.scrollEnabled = true
autocompleteTableView.hidden = true
}
override func setSelected(selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
// Configure the view for the selected state
}}
as you know you can't define identifier inside xib file
thanks

You need to register a cell with autocompleteTableView before you can dequeue it. Modify your code like this:
override func awakeFromNib() {
super.awakeFromNib()
textField.delegate = self
autocompleteTableView.delegate = self
autocompleteTableView.dataSource = self
autocompleteTableView.scrollEnabled = true
autocompleteTableView.hidden = true
// Register cell
autocompleteTableView.registerClass(UITableViewCell.self, forCellReuseIdentifier: "AutoCompleteRowIdentifier")
}

Related

Static cells from xib in UICollectionViews with segues (Swift 2)

I would like to create list of rows using UICollectionView with each row can click and go to another controller.
I create custom cell in xib and class for it.
This is my code:
class CollectionCellXIB: UICollectionViewCell {
#IBOutlet weak var label: UILabel!
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
}
override func awakeFromNib() {
super.awakeFromNib()
}
}
class Collection: UIViewController, UICollectionViewDelegate, UICollectionViewDataSource {
#IBOutlet weak var collectionView: UICollectionView!
func collectionView(collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return 2
}
func numberOfSectionsInCollectionView(collectionView: UICollectionView) -> Int {
return 1
}
func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
var cell: CollectionCellXIB
self.collectionView!.registerNib(UINib(nibName: "CollectionCellXIB", bundle: nil), forCellWithReuseIdentifier: "cell")
if indexPath.row == 0 {
cell = collectionView.dequeueReusableCellWithReuseIdentifier("cell", forIndexPath: indexPath) as! CollectionCellXIB
cell.label.text = "cell 1"
} else {
cell = collectionView.dequeueReusableCellWithReuseIdentifier("cell", forIndexPath: indexPath) as! CollectionCellXIB
cell.label.text = "cell 2"
}
return cell
}
}
Unfortunatelly, segues not working. When I clicked on a row, nothing happend. Method shouldPerformSegueWithIdentifier wasn't called.
So, question is, how to use custom cells with xib and using segues?

pass data between two UITableView with custom cell

I'm going to pass data from a UITableViewController to another UITableViewController. These two UITableViewController have custom cell in it.
When I pass the data by segue, I can't get the data from sourceViewController as it says that there's no member of the label I built in the Custom UITableViewCell controller.
Main Problem that find no member in menuController. Do I need to inherit or delegate the custom cell to menuController or push it?
Here is the code of ordersController:
import UIKit
struct Order {
var tilte:String
var price:String
var quantity:String
}
class ordersController: UITableViewController {
var orders = Array<Order>()
override func viewDidLoad() {
super.viewDidLoad()
}
//handle exit from Cancel back of menuController
#IBAction func cancelBack(segue: UIStoryboardSegue){
}
//handle exit from Done back of menuController
#IBAction func doneBack(segue: UIStoryboardSegue){
print("Done and Back")
//let source = segue.sourceViewController as! newMenu
//let quantity = source.burgerQuan.text
}
override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return 1
}
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return self.orders.count
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("orderedItem", forIndexPath: indexPath) as! ordersCustomCell
let order:Order = self.orders[indexPath.row]
cell.ordersName.text = orders[indexPath.row].title
cell.ordersPrice.text = orders[indexPath.row].price
cell.ordersQuantity.text = orders[indexPath.row].quantity
return cell
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
}
Here is code of Custom Cell of ordersController:
class ordersCustomCell: UITableViewCell {
#IBOutlet weak var ordersName: UILabel!
#IBOutlet weak var ordersPrice: UILabel!
#IBOutlet weak var ordersQuantity: UILabel!
override func awakeFromNib() {
super.awakeFromNib()
}
override func setSelected(selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
}
Here is the code of menuController:
class menuController: UITableViewController {
var items:[String] = ["Hamburger","French Fries", "Coffee", "Lemon Tea"]
var price:[String] = ["$29", "$13", "$25", "$8"]
override func viewDidLoad() {
super.viewDidLoad()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return 1
}
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return self.items.count
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("menuItem", forIndexPath: indexPath) as! menuCustomCell
cell.menuName.text = self.items[indexPath.row]
cell.menuPrice.text = self.price[indexPath.row]
return cell
}
}
And here is code of custom cell of menuController:
class menuCustomCell: UITableViewCell {
#IBOutlet weak var menuName: UILabel!
#IBOutlet weak var menuPrice: UILabel!
#IBOutlet weak var menuQuantity: UILabel!
#IBOutlet weak var stepper: UIStepper!
#IBAction func stepperValueChanged(sender: UIStepper) {
menuQuantity.text = Int(sender.value).description
}
override func awakeFromNib() {
super.awakeFromNib()
}
override func setSelected(selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
}
}
How can I do this? --> When the Add button in Orders is clicked, it shows the Menu. User click the stepper to select the quantity. Then, data pass back to Orders when user click Done. The items which quantity is not 0 will be shown on the list on Orders.
Your menuController class does not that that variable menuName, thats why it cannot find it.
All you have is items and price in that view controller.
You have menuName within your custom cell. That is different from the viewController you are pushing too.

Trouble passing data from TableViewCell labels to a ViewController

I am trying to pass data from the selected cell of an "Events" table view, to a "Details" View Controller. I have looked at various questions similar to mine, but I can't seem to properly apply it to my code. I also used labels, instead of a Subtitle style. There is also an image that needs to be passed.
my view controller looks like this:
import UIKit
class ViewController: UIViewController, UITableViewDataSource, UITableViewDelegate {
#IBOutlet var tableView: UITableView!
var names = ["BTown Diner", "Dunnkirk", "Chocolate Mousse", "Lil Wayne", "Annie", "Campus Squad Social"]
var details = ["Free drink with meal after 12 AM", "LADIES drink free", "10% off all ice cream!", "Lil 500 concert", "an IU Theater Production", "Bring your Squad to the Campus Squad Social"]
var images = [UIImage(named: "btown"), UIImage(named: "dunn"), UIImage(named: "choco"), UIImage(named: "lilwayne"), UIImage(named: "default"), UIImage(named: "default")]
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.
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return names.count
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = self.tableView.dequeueReusableCellWithIdentifier("cell", forIndexPath: indexPath) as! CustomCell
cell.name.text = names[indexPath.row]
cell.detail.text = details[indexPath.row]
cell.photo.image = images[indexPath.row]
return cell
}
var valueToPass:String!
func tableView(tableView: UITableView!, didSelectRowAtIndexPath indexPath: NSIndexPath!) {
println("You selected cell #\(indexPath.row)!")
// Get Cell Label
let indexPath = tableView.indexPathForSelectedRow();
let currentCell = tableView.cellForRowAtIndexPath(indexPath!) as UITableViewCell!;
valueToPass = currentCell.textLabel.text
performSegueWithIdentifier("detailsSegue", sender: self)
}
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if (segue.identifier == "detailsSegue") {
// initialize new view controller and cast it as your view controller
var viewController = segue.destinationViewController as detailsViewController
// your new view controller should have property that will store passed value
viewController.passedValue = valueToPass
}
}
}
and here is my customCell.swift file:
import UIKit
class CustomCell: UITableViewCell {
#IBOutlet var photo: UIImageView!
#IBOutlet var name: UILabel!
#IBOutlet var detail: 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
}
}
I am very new to Swift, and it has proven to be very challenging for me. I'm really not a coder, however a project demands that I complete some of the coding for an application that I am the UI/UIX designer of. Thank you for your help in advance!
Try to register your "CustomCell" with the name "cell"
override func viewDidLoad() {
super.viewDidLoad()
tableView.registerNib(UINib(nibName: "CustomCell", bundle: nil), forCellReuseIdentifier: "cell")
}
Here is a slight variation on your code starting with the main view controller...
import UIKit
class EventTableViewController: UITableViewController, UITableViewDataSource, UITableViewDelegate {
var names = ["BTown Diner", "Dunnkirk", "Chocolate Mousse", "Lil Wayne", "Annie", "Campus Squad Social"]
var details = ["Free drink with meal after 12 AM", "LADIES drink free", "10% off all ice cream!", "Lil 500 concert", "an IU Theater Production", "Bring your Squad to the Campus Squad Social"]
var images = [UIImage(named: "btown"), UIImage(named: "dunn"), UIImage(named: "choco"), UIImage(named: "lilwayne"), UIImage(named: "default"), UIImage(named: "default")]
override func viewDidLoad() {
super.viewDidLoad()
}
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return names.count
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = self.tableView.dequeueReusableCellWithIdentifier("cell", forIndexPath: indexPath) as! CustomCell
cell.name.text = names[indexPath.row]
cell.detail.text = details[indexPath.row]
cell.photo.image = images[indexPath.row]
return cell
}
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if segue.identifier == "detailsSegue" {
guard let eventVC = segue.destinationViewController as? DetailsViewController,
let eventIndex = tableView.indexPathForSelectedRow?.row else {
return
}
eventVC.eventName = names[eventIndex]
eventVC.eventDetail = details[eventIndex]
eventVC.eventPhoto = images[eventIndex]
}
}
}
and then a sample detailsViewController...
import UIKit
class DetailsViewController: UIViewController {
var eventName: String = ""
var eventDetail: String = ""
var eventPhoto: UIImage!
override func viewDidLoad() {
super.viewDidLoad()
print(eventName)
print(eventDetail)
}
}
You were off to a good start. Hope this helps get you the rest of the way.

How to transfer data from table cell to a new view controller using prepare for segue method?

How to use prepare for segue to transfer the images (tweetImg) and date (dateLbl) from tablecell (mainCell) to the Newviewcontroller when I select the cell? in my case I am using parse.com as my backend to retrieve the images and dates data. I am new to programming would appreciate some help, thank you.
mainVC
import UIKit
class mainVC: UIViewController, UITableViewDataSource, UITableViewDelegate, {
#IBOutlet weak var resultsTable: UITableView!
var resultsStartdateArray = [String]()
var resultsTweetImageFiles = [PFFile?]()
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return resultsTweetImageFiles.count
}
func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
return 350
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell:mainCell = tableView.dequeueReusableCellWithIdentifier("Cell") as! mainCell
cell.dateLbl.text = self.resultsStartdateArray[indexPath.row]
resultsTweetImageFiles[indexPath.row]?.getDataInBackgroundWithBlock({
(imageData:NSData?, error:NSError?) -> Void in
if error == nil {
let image = UIImage(data: imageData!)
cell.tweetImg.image = image
}
})
return cell
}
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
self.performSegueWithIdentifier("SendDataSegue", sender: self)
}
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?)
{
if (segue.identifier == "SendDataSegue")
{
let destination: NewViewController = segue.destinationViewController as! NewViewController
// I believe the missing code should be here
}
}
}
mainCell
import UIKit
class mainCell: UITableViewCell {
#IBOutlet weak var tweetImg: UIImageView!
#IBOutlet weak var dateLbl: UILabel!
override func awakeFromNib() {
super.awakeFromNib()
}
}
NewViewController
import UIKit
class NewViewController: UIViewController {
#IBOutlet weak var dateLbl: UILabel!
#IBOutlet weak var tweetImg: UIImageView!
var titleString: String!
override func viewDidLoad()
{
super.viewDidLoad()
self.dateLbl.text = self.titleString
}
Bellow i have mentioned a sample template code. organize your code according to bellow mentioned code. important part is select a cell in the prepareForSegue instead of in didSelectRowAtIndexPath. Which is let IndexPath = self.tableView.indexPathForSelectedRow()!
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
//Index path is the selected cell
let IndexPath = self.tableView.indexPathForSelectedRow()!
//Here you can assign your tweetImg and dateLbl
let newViewController = segue.destinationViewController as! NewViewController
newViewController.dateLbl.text = //your date label value
//here assign your image to destination view controller property
}
Delete the method didSelectRowAtIndexPath and connect the segue to the table view cell rather than the view controller.
When a cell is selected it's passed as the sender parameter in the prepareForSegue method.
A side note : Don't perform background tasks in the view – the cellForRowAtIndexPath method – , do it in the model – the items in the data source array – and then call reloadData()

TableViewController and CustomCell using Swift

I'm trying to populate a TableViewController with data and display it using a CustomCell so I can have two labels and a button on each row.
I have placed the two labels and the button in the PrototypeCell within the Main Storyboard.
I have created a CustomCellTableViewCell class:
import UIKit
class CustomCellTableViewCell: UITableViewCell {
#IBOutlet var customCellLabel1: [UILabel]!
#IBOutlet var customCellLabel2: [UILabel]!
#IBOutlet var CustomCellButton: [UIButton]!
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
}
}
and within my UITableViewController I have:
var DevicesList: Array<AnyObject>=[]
var ii: Int = 1
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let CellID : NSString = "DeviceCell"
var cell : CustomCellTableViewCell = tableView.dequeueReusableCellWithIdentifier(CellID) as CustomCellTableViewCell
if DevicesList.count > 0 {
var data: NSManagedObject = DevicesList[indexPath.row] as NSManagedObject
cell.customCellLabel1[indexPath.row].text = data.valueForKeyPath("name") as? String
println("loading row \(ii) loaded!")
ii++
} else {
println("nothing loaded...?")
}
println("cell loaded")
return cell
}
when I run it though the first row is loaded but then I get a:
loading row 1 loaded!
cell loaded
fatal error: Array index out of range
The guilty line is shown as this one:
cell.customCellLabel1[indexPath.row].text = data.valueForKeyPath("name") as? String
I have 7 rows to load so somewhere I need to append the labels/button array and if so where/how do I do it?
Thanks!
Kostas
Just for future searches here is how it was solved:
Created new class:
import UIKit
class DeviceCustomCell: UITableViewCell {
#IBOutlet var myLabel1: UILabel!
#IBOutlet var myLabel2: UILabel!
#IBOutlet var myButton: UIButton!
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
}
#IBAction func PressButton(sender: AnyObject) {
myButton.setTitle("OFF", forState: UIControlState.Normal)
}
}
Linked the labels and button from the Main storyboard to the two variables (New Reference Outlet).
Important to have the Identifier as "DeviceCustomCell" for the Prototype Cell and then modify the function:
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let CellID : NSString = "DeviceCustomCell"
var cell = tableView.dequeueReusableCellWithIdentifier("DeviceCustomCell") as DeviceCustomCell
if DevicesList.count > 0 {
var data: NSManagedObject = DevicesList[indexPath.row] as NSManagedObject
var devicename : String = data.valueForKeyPath("name") as String
var lastchanged: String = data.valueForKeyPath("lastChangedRFC822") as String
cell.myLabel1.text = devicename
cell.myLabel2.text = lastchanged
println("loading row \(ii) loading...")
ii++
return cell
} else {
println("nothing loaded...?")
}
return cell
}
This now works nicely!
Important is to understand this line:
var cell = tableView.dequeueReusableCellWithIdentifier("DeviceCustomCell") as DeviceCustomCell
as it holds the key to success! :)
Kostas

Resources