Combined TableViews & CollectionViews in Swift - ios

I am stuck...
I have a collectionView (let's call it masterCollectionView). Each cell of the collectionView holds a list of data.
In each of these collectionView cells in the masterCollectionView, I have a tableView which holds all the records themselves in each row, grouped into tableView sections based on certain criteria within the dataset.
The data is stored in a multi-dimensional array which I download from the cloud, and this provides the list title to the masterCollectionView cell, as well as the # of sections, # of records (i.e. rows) in each list for the respective tableView.
My problem is that I can't tell which masterCollectionView cell I'm in when I'm populating the tableView. For example:
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
}
The above function doesn't allow me to identify the masterCollectionView cell I'm currently building the tableView in and therefore I don't know which records in the data array to load.
At the moment I have all of the above built as one storyboard in interface builder along with one corresponding viewController but can easily change based on recommendations.
Please help. I'm pulling my hair out.

You probably want to have a separate instance of your table view data source for each collection view cell.
You could create a new NSObject subclass implementing UITableViewDataSource whose purpose is only to act as the data source for one cell. This object can be configured with the data for that cell only.
You would then have an array of these instances, one for each collection view cell. When the cell is loaded in cellForItemAtIndexPath, set that cell's table view delegate to the correct data source from the array.

Ok I will first give you the quickest solution to your problem, although its easy to implement it is not the 'right' way to do it I will explain later.
So the quickest way to do it is using view tags. Each UIView has a tag member which is an Integer. So where ever you are setting your tables, you can do this
I dont have your code so I am assuming you setting your table in
func collectionView(_ collectionView: UICollectionView,
cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell
function of your UICollectionView, so in there you do something like this
myTableView.tag = indexPath.row
This should set tag to the TableView, when you are creating them which would be index in the array. and in your UITableView datasource you can do this
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return yourDataArray[tableView.tag].count;
}
This is the short and quick way the correct way would be to break up your data properly, may your UICollectionView cells as datasources for the included UITableView and then load the data when needed.

Related

How to capture cell data from UITableView with multiple cell prototypes?

I designed a UITableView containing 3 different cell prototypes. I'm trying to figure out how I can capture their user inputs. One of them has a checklist in the form of a nested table view, so I need the ones they selected. Another has a UIPickerView so I need the selected option from a PickerView. Last one is a text area so I need the string inputting in that.
So I not only need a mechanism to capture the data to repopulate it back with their inputs when the user scrolls up or down to make it visible again. Would the best option be to use the following delegate function to capture non-visible cells:
func tableView(_ tableView: UITableView, didEndDisplaying cell: UITableViewCell, forRowAt indexPath: IndexPath) {
// do something with the cell before it gets deallocated
}
and then capture data on the visible cells on form submission? I'm not sure if this approach would work, so I'm wondering if there are better options.
The form input data would be 1 to many sections of self-repeating cells for sections 2 and up, so I need a way to capture all the input data with the TableView dequeuing these cells.
Your approach is wrong.
You have to implement a logic to update the data model at the moment the user changes something in the view.
This can be accomplished with protocol / delegate or with callback closures.

Swift Button That Outputs UICollectionView Cells One by One?

I made a UICollectionView, and everything is working. It makes 100 cells that I can scroll through in simulator with no problem.
However, rather than seeing all the cells at once, I want the cells to be released one by one whenever that red button is pressed.
I am confused because I noticed in the storyboard, it hard codes the number of cells it has on the screen at once. Is there any way to get around this?
Thank you!
This is what the UI looks like in storyboard.
This is the code I used to make it. It's basic, and just says to fill the text box of the cell with a string from the array.
Your question is garbled.
A collection view has a delegate and a data source. The data source responds to messages in the UICollectionViewDataSource protocol. That protocol lets the collection view ask how many sections it has, and how many rows in each section, as well as asking for the cells from those sections and rows.
There are also methods that let you tell the table view that you want to add more cells. Take a look at the method insertItems(at:). That lets you provide an array of indexPaths, which tells the table view that you have added new entries.
You could certainly write a button action method that added one or more entries to your data model and then used the insertItems(at:) method to notify the collection view that it had new entries. If there was room in the content view of the collection view to display additional cells it would then call the data source and ask for new cells at those index paths.
Sounds like you just need to keep track of how many items you want displayed (which will increase the more that button is pressed) and use that in your UICollectionViewDataSource method. Something like:
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return min(myRunningItemCount, maximumNumberOfItems) //assuming there's a maximum
}
Then you just need to call reloadData on the collection view whenever that number changes.

Rows With Different UI Swift and also reusing any of cell in different viewcontroller to avoid repeated coding

I am making a layout similar to this
Here all cells are different UI (approx 9 cells). So I tried using XIB files for each one and added in
func tableView(tableView: UITableView, viewForHeaderInSection section: Int) -> UIView?
{
}
But using xib i have achieved UI but i am finding it complicated.
Please guide me how can i achieve this layout, if there is any better solution than XIB.
And if any of this cell has to be reused in Other ViewController, how to design and code it to avoid repeating.
What you could do is make different cells and then when you call the cellForRowAtIndexPath you can load in a different cell depending on the index you are at. For example, at index 3 you may want to load in cell A while at index 5-7 you may want cell C.
Just go to the tableview drop in the cells you need, design each one, link it with a class, and then set its reuse identifier. Don't add them as section headers but as prototype cells.

How can I parse image from table cell inside table view to detail view in iOS?

I have an image inside my tableview cell.
What I want to do is when I click on that cell I want to parse both text & image to detail view.
I can do for text but I can't get the point about image.
So, simply my question is how can I parse image inside tableview cell to detail view in iOS.
Thanks
You can use it as the same way you're using it. Use indexPath to specify the row you wanna manipulate.
Here's how you do it. implement UITableViewDelegate in your ViewController, and implement the following method.
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
}
The short answer, you access the image the same way that you set it. In the case of the standard UITableViewCell, it is the imageView property that you used.
For these API type questions though, there is no better place to start, than the documentation

Swift coding multiple tableviews- how to connect them up?

Hi I'm new to coding so basically i've created a tableview app on github
the first one shows what i want to do without code https://github.com/edlen/guideline.git
and the second one is an attempt to recreate it with code
https://github.com/edlen/guidelines-via-code.git
but I'm really stuck about how to create code for going between screens so say for example on the main menu I select helpful info, how do i make the tableview with those options appear? and then if i select PO switch how do I segue to it?
Technically I can do what I want grand without code but I would really like to be able to understand coding of tableviews better and how to go between multiple tableviews and then select a final individualised view controller full of text.
Any advice that you could offer would be great- but please be prepared to speak very slowly and clearly as I'm still learning as i go along!!
At first, designing the app with Interface Builder inside Xcode is both the same for Swift and Objective C.
A UITableViewController should be embedded inside a UINavigationController, if you want to switch between views. Just drag'n'drop a UINavigationController and a UITableViewController into your storyboard - make sure the UITableViewController is the root viewcontroller of the navigation controller (right-click drag the tableview controller on the navigation controller).
After that, create a new Cocoa Touch Class - file (or press CMD-N). Look at this:
Make sure you choose UITableViewController at "Subclass of".
After that, go back to your interface builder and select your UITableViewController. There go to the identity inspector to change the class of your tableview controller. Look here:
After that, you just need to choose a reuse identifier for you tableview cells. You need the reuse identifier, so that your iPhone (or iPad) can reuse a cell and doesn't have to create a new one everytime. I just chose "myCell" as reuse identifier. To do that, click on the cell and go to the attributes inspector:
OK, the part with interface builder is done. Now go to your previously created MyTableViewController.swift.
There you have some methods. You need at least these to methods:
func numberOfSectionsInTableView(tableView: UITableView) -> Int
and
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int
You need these methods, because the data source of your tableview is set to self. That means, this class is used to fill your tableview with information.
Let's start simple. To test everything, just use 1 section. So in your numberOfSectionsInTableView return 1.
If you have some data to be displayed, I think you'll store this data inside an array? However, in numberOfRowsInSection you have to return the number of rows that have to be displayed inside that section. So if you want to display 3 rows, just return 3 here. That makes 1 section with 3 rows inside that section.
Now you have to customize your tableview cell with labels and maybe an image view. So you need the function
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("myCell", forIndexPath: indexPath) as UITableViewCell
// Configure the cell...
// add some UILabels or UIImageViews here.
return cell
}
to create your own cells. Here you'll need the reuse identifier you've set in interface builder.
A UITableView also has a delegate, which is responsible for events like (de)selecting a cell. So if you want to show a UIViewController when the user taps on a cell, you have to implement the method
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath)
Here you can switch between views. Here you need to have the tableview controller embedded inside a navigation controller (except you are presenting your views as modal view controllers, but that's not the point here).
So the user taps on a cell, you have the index of the cell inside indexPath.row - you'll need that to show the user the information inside the new view. After that, create your UIViewController or whatever, and present the viewcontroller with
self.navigationController?.presentViewController(myViewControllerToPresent, animated: true, completion: { () -> Void in
// some code to do after the presentatioin is ready
})
That's it!

Resources