IOS Swift - How can I use 2 table views in a collectionview with different data [closed] - ios

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 7 years ago.
Improve this question
I am developing an app where I have a collectionview with 2 different tableviews. But what I need to know is how I can recognize which tableview is filled with data at that moment.

1) Use a different delegate and data source for your 2 table views
or
2) Create outlets for your 2 tables and just compare. The delegate and data source methods pass a reference to the table
Example
#IBOutlet weak var table1: UITableView!
#IBOutlet weak var table2: UITableView!
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
if tableView == self.table1 {
// something
}
if tableView == self.table2 {
// something else
}
}

Each UIView Object has a tagproperty, which is used to identify a UIView at runtime.
You could set it like this:
myTableView1.tag = Int.min
myTableView2.tag = Int.max
and in the Delegate and DataSource methods:
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int
{
let rowCount: Int
if tableView.tag == Int.Min
{
rowCount = self.dataForTableView1.count
} else
{
rowCount = self.dataForTableView2.count
}
return rowCount
}
Use the tag value to identify the right TableView and that's it.

You need to give them different tags and then build your method around the use of these tags.

What is a CollectionView?
1.It's similar to a UITableView
2.Layout grid instead of columns.
3.Defined by the UICollectionViewFlowLayout.
4.Nees a custom UICollectionViewCell
5.Requires a data source and delegate
It can have sections just like TableViews have multiple sections. Items in each section are equivalent to the cells in a TableView.
The UICollectionViewCells have a stack of background properties. The first thing you drag into the cell will happen on top of the cell's content view. It' a property thats like an empty tabelViewCell. There's nothing in it, it's just a view so anything you drag on top of that view will be visible. such as an ImageView, LabelView etc.
If you turn the cell.contentView background colour on it will obscure whatever is underneath it. Underneath the cell.contentView is something called the cell.backgroundView / cell.selectedBackgroundView. Those are views that are initially nil but we can populate them with our own views.
Just drag a CollectionViewController to the storyboard and mark it as the Initial Controller. Take a look in the Document Outline panel (click square at bottom of Xcode window) and you'll see the CollectionViewController comes with a collectionView and in the CollectionView is a collectionViewCell and a UICollectionViewFlowLayout which controls where the cells are.
This is where you can have all of your fun. You can place any type of Views in there. Good luck.

Related

Better way to hide a cell which doesn't make a condition (UITableView)

I currently have a UITableView which hides cells which aren't within the radius (slider double). Im doing this by setting working out the distance then setting the height of the cells which match the if statement to return 0. However this throws up a bunch of constraint errors and I don't believe this is the best way to do it.
So my question is, is there a better cleaner and more elegant way to achieve the same, hiding a cell result?
Current Height Function
func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
if userCurrentLocation != nil {
let cellData = cacheData[indexPath.row]
//let radius: Double = radiusSliderValue
if cellData.distance > radiusData.radiusValue {
return 0
}
}
A better approach would be to do all the distance calculation before the tableview is loaded, and then put only the valid data into a different array that the tableview works off, so you're only ever presenting rows that are valid.
If the data could change once the tableview has loaded and you don't want to reload the whole table, you can use insertRowsAtIndexPaths:withRowAnimation: and deleteRowsAtIndexPaths:withRowAnimation: on the tableview to add new rows in.

Load a UIViewController with data from .plist [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 7 years ago.
Improve this question
I have a UITableView set up in storyboard with static rows populated with different content, and all going to a single UIViewController. I've also got a separate plist for each view I intend to load (containing the different content), that I would like loaded depending on which row was selected.
As a bonus, I would rather have a single plist that the UITableViewController will populate the rows with (instead of having 120+ static rows in storyboard), but am unsure of how to do that as well.
I've searched quite a bit, but only found things for Objective-C. I'm a bit new to Swift, and never really got far into Objective-C, but I think I've got the basics down.
Right, my question. My question is, how can I load each individual plist (one for each row) and display its contents when the UIViewController is shown? My bonus question is: how can I consolidate my 120+ static rows into a single plist that basically accomplishes the same thing, except instead of editing the SB to add new rows, I just need to add to the plist?
First of all, it's rare to use plist to store such contents. Not easy to maintain. Use XML or json to store it are better choices.
Regards your question #1,
put below code to a loop to load your plist into a dict like this:
let path = NSBundle.mainBundle().pathForResource("Your_path", ofType: "plist")
let dict = NSDictionary(contentsOfFile: path!)
You may want to store all the dicts into an array, so you know how many plists you have. Let's say we have dictArray property in your view controller to hold all your dicts.
You don't add static cell on SB for UITableView, it's not efficient. You just let the dataSource delegate to load the data and create as many cells as it needs.
I will leave some code for you to write, this will warm you up. I just give the essential part of code.
Don't forget to set your dataSource and delegate to proper object, like self!
then,
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return dictArray.count
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier(textCellIdentifier, forIndexPath: indexPath) as UITableViewCell
let row = indexPath.row
let dictOfPlist = self.dictArray[row]
// now you get your plist while configuring your cells,
// do your customization for your cells from now on
return cell
}
// MARK: UITableViewDelegate Methods
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
let row = indexPath.row
let dictOfPlist = self.dictArray[row]
// if you tap one cell, now you get its corresponding plist
// time to pass the data to your view controller
// either use segue or other ways to do it
}
}
Some ways to pass data to your new UIViewController:
If you segue exist in the storyboard with a segue identifier between your 2 views, you can just call it programmatically using:
performSegueWithIdentifier("mySegueID", sender: yourDataDict)
later you can access yourDataDict in your nextViewController to load it
You could also do :
nextViewController.dataDict = yourDataDict // set a public property so you can access it later on
presentViewController(nextViewController, animated: true, completion: nil)
Or if you are in a Navigation controller :
self.navigationController?.pushViewController(nextViewController, animated: true)
To consolidate your plists into one plist, you might need to write some small programs or scripts to merge them; or copy them. There's a quite a lot of ways to do it. But as I suggested, I don't recommend you to continue using plist to do such things. You better change to another form at beginning. Otherwise when you realize you really need to change, it's too late and you have many code to rewrite.

Custom header of table view with IB

I would like to create a custom header for a table view section with interface builder. I cannot use the method titleForHeaderInSection because i need to display two labels. I used this instructions: Customizing Header and Footer of TableView in iOS8 but it does not work.
What I have done so far:
Create a custom class CustomTableCell which inherits from UITableViewCell
class CustomTableCell: UITableViewCell {
#IBOutlet weak var dateLabel: UILabel!
#IBOutlet weak var dateDescriptionLabel: UILabel!
}
Create a dynamic prototype cell in storyboard
Add an identifier
Connect the labels to the custom UITableViewCell
Implement viewForHeaderInSection
func tableView(tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
let headerCell = tableView.dequeueReusableCellWithIdentifier("CustomTableCell") as CustomTableCell
headerCell.backgroundColor = UIColor.cyanColor()
headerCell.dateLabel.text = "Test date"
headerCell.dateDescriptionLabel.text = "Test date description"
return headerCell
}
When i run the app the section appears one second and then moves under the table cells and I get an error: no index path for table cell being reused.
What is wrong with this solution? I downloaded the project from the tutorial I have linked and it works there.
Your problem has its roots in how UIKit handles UITableViews.
To make sure table views are fast and responsive, even with a large amount of cells, the cells are re-used.
By calling tableView.dequeueReusableCellWithIdentifier("CustomTableCell") you are asking the tableView to give you a cell to reuse.
A lot of people have been using the reusable cells to design their headers/footers in Storyboards. Ever since iOS 7 Beta 5 this may lead to errors. This answer explains the situation well: What is the meaning of the “no index path for table cell being reused” message in iOS 6/7?
To design your own custom header/footer views I don't recommend using UITableViewCells. Instead you should create and design a custom UIView directly in your code. If you want to use Interface Builder you could create a .xib or create a view in your Storyboard that is not a subview of the actual controller's view.

Swift MVC Design With Multiple Table Views

So I have the main view of my controller that has a table view. This table view will be displaying many different custom classes that subclass UITableViewCell. Some of these cells will ALSO have table views inside of them.
My problem is that I do not know what class I should assign to to be the UITableViewDelegate in this sort of situation for the table view in the table view cell. My intial thought was to make it the cell view class:
class MyTableViewCell: TableViewCell {
#IBOutlet var tableView: UITableView!;
var messages: Array<String>?;
//called by parent tableview when cellForRowAtIndexPath is called in main controller
//to initialize view with dynamic properties at run time
override func render(obj: MyObject) {
messages = obj.getMessages();
}
}
extension MyTableViewCell: UITableViewDataSource {
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return messages == nil ? 0 : messages!.count;
}
}
This is problematic because I have no where to register my nib files to the table view:
nib = UINib(nibName: "MyTableViewCell", bundle: nil);
self.tableView.registerNib(nib!, forCellReuseIdentifier: "custom");
Also, I feel like making a view a table view data source is violating MVC principles. What is the best way to go about with my table views within table view cells?
The UITableView within a UITableCell was indeed implemented in Pulse as described by genalipsis. In Obj-C,there is a full tutorial plus posted code located here for UITableView within a UITableCell:
http://iosstuff.wordpress.com/2011/06/29/adding-a-uitableview-inside-a-uitableviewcell/
http://iosstuff.wordpress.com/2011/06/29/creating-pulse-style-scrolling-horizontally-scrolling-uitableview-as-a-subview-of-uitableviewcell/
The was done in Xcode 4. I am not sure if this will work in Xcode 6.1 but it does describe a methodology.
I think an even more descriptive and easier to follow tutorial was posted at Ray Wenderlich's site here:
http://www.raywenderlich.com/4680/how-to-make-an-interface-with-horizontal-tables-like-the-pulse-news-app-part-1
http://www.raywenderlich.com/4723/how-to-make-an-interface-with-horizontal-tables-like-the-pulse-news-app-part-2
Create a regular UITableView
Create a custom UITableViewCell
Add a rotated UITableView as a subview of our UITableViewCell
Create another custom UITableViewCell for our articles
Rotate our custom cell and use it for our horizontal table view
While the tuorial was from 2011, some of the comments are very recent, so the approach must still work.
There is also a github project that references a stack overflow discussion from earlier this year:
https://github.com/hefgi/TableViewInTableViewCell
If you open the project, the storyboard file for the iPhone is instructive (Main_iPhone.storyboard):
A table view inside of a table view has been done before. One of the first iPad Apps, Pulse, used this strategy to allow uses to scroll vertically between RSS feeds and horizontally, within each cell, between RSS entries. That is, the embedded table view was rotated and the cells inside it where also rotated so that their orientation allowed reading.
For usability reasons, you will probably want to follow a similar pattern, else it might be difficult to scroll.
Tentative architecture: MainTableViewController is the controller for the table view that contains sub table views. SubTableViewController is the controller for the table views contained within the cells of the MainTableViewController. This approach lets you use TableViewControllers in the "standard" fashion
class MainTableViewController: TableViewController {
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
//dequeue a cell or create an instance of a cell
//create instances of SubTableViewController or change the data source for indexPath
//add the view of SubTableViewController to the cell's view hierarchy
//make necessary view adjustments depending on orientation, etc.
}
Not a standard setup, so I would expect that a few further hacks will be necessary.

How to create a couple uitableview in swift using interface builder?

how we can create a couple of uitableview in view controller.let we have two categories of pizza like veg and non veg. how we can show veg pizza in left uitableview and non veg pizza in right uitableview. .
Take a UIViewController (not a UITableViewController) and drag two UITableViews onto it. Size them to your needs and set the constraints accordingly.
After that, you have to create a custom class for the UIViewController that handles the required TableViewDatasource protocols. Set the Datasource and Delegate properties of the UITableViews to that class.
I would create 2 UITableViews into your ViewController.
Create a TableViewController and set the Delegate and Datasource to them.
Then create 2 Tags (for each Table) and then use in every tableView method your tag identifier.
For Example:
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
if(tableView.tag == 0) {
// return count of normal pizza
} else {
// return count of veg pizza
}
}

Resources