Custom swipeable Table View Cell, Close other once new one open - ios

I'm following tutorial from raywenderlich (How To Make A Swipeable Table View Cell With Actions) site, that shows you how to create custom cell with layers and delegate.
Now I got everything working correctly, buy I would like one of my cells to close if other cell open, how can I achieve this? or Like Messenger app, don't allow users to open another cell option unless they close the current one.
I can't wrap my head around this, I see few other people also ask the same question in comments, but no one reply.
Anyone with Objective-C knowledge, it's okay, I can translate it to swift myself.
The reason I'm using this tutorial, is because the Apple API doesn't allow custom button (using PaintCode) to be used as Action button.

I find a very simple solution for anyone else who trying to achieve the same method.
Create a Method - closeOtherCells:
Since we store all cells in NSMutableSet we can see which ones are available for closing.
func closeOtherCells(close close: Bool){
if close{
//Check For Available Cell
for cells in cellsCurrentEditing {
//Get Table Cells at indexPath
var cellToClose: CustomTableViewCell = self.tableView.cellForRowAtIndexPath(cells as! NSIndexPath) as! CustomTableViewCell
//Call Reset Method in our Custom Cell.
cellToClose.resetConstraintContstantsToZero(true, notifyDelegateDidClose: true)
}
}
}
Now Simply in your cellDidOpen: delegate method call closeOtherCells: with true parameter.
func cellDidOpen(cell: UITableViewCell) {
//Close Other Cells
closeOtherCells(close: true)
//Store Open Cell in NSMutableSet
let indexPath: NSIndexPath = self.tableView.indexPathForCell(cell)!
self.cellsCurrentEditing.addObject(indexPath)
}
I hope this help others. :)

Related

Add UIView at bottom of UITableViewCell programmatically

I'm working on a instant messaging app. The user can send text messages, for which I'm using a UITextView inside the custom tableview cells. The user should be able to send all kinds of multimedia data, such as images, documents and videos.
Inside my table view cell I have both a textView and a UIImageView in a stackView and I can send the respective kinds of data. If there is no text, I hide the TextView. If there is no Image, I hide the image.
The problem is: to scale the app, I'd have to add a new container for documents, another one for videos, another one for audio files and hide all the other containers that have no data added to it. It's a garbage solution, but it was the only one that I found.
Knowing from the backend what kind of data is sent, how could I programatically add a container view in which I make the setup on the spot? I was thinking of having a textView as default and an empty View and inside cellForRowAt just add the needed elements.
I would try to create several cells which you dequeue in cellForRowAt by checking for a criteria, e.g.:
if userPost.images != nil {
let cell = tableView.dequeueReusableCell(withReuseIdentifier: "Identifier1", for: indexPath) as! UITableViewCell
return cell
} else {
let cell = tableView.dequeueReusableCell(withReuseIdentifier: "Identifier2", for: indexPath) as! UITableViewCell
return cell
}
With this solution, you can create a cell that nicely fits the data a user sent another user. Just check for any criteria you want and return the according cell.
Hope it helped!

Save a UITextField into a UICollectionViewCell

I have an app that allows the user to create categories. A save screen appears with a UITextField. Although, I do not know how to save the user's entry, and allow a new UICollectionViewCell to be added into the current UICollectionView that contains the UITextField words that the user typed. Thanks!! This is also in Swift. This would be used in a UITableView: clothes.name = self.nameTextField.text ,but how would I convert this to a UICollectionView? **clothes is a variable
Your collection view has a data source where you initially have the model for your cells. In your case it's probably an array. The collection view looks at this data source and returns cells based on the entries contained in this data source.
What I am trying to get at is the following:
In order to show the newly created cell, you'll need to update your data source (I'll call it "the blueprint specification" the collection view adheres to) by adding the new cell's "specification" (I think I'm wording this in a more complex fashion than it actually is). Here is an example (If we assume that your data source is an array):
categoryArray.append(CategoryModel(title: yourTextField.text)) // update the data source
After you make changes to the data source you can tell the collection view to reload it's data:
collectionView.reloadData()
That will "parse" the data source to display the cells anew.
Let me know if anything is unclear.
EDIT
Regarding your comment -- given that you use a UINavigationController -- , you can achieve displaying the title like this:
You are probably using this method to go to your next view controller:
func collectionView(collectionView: UICollectionView, didSelectItemAtIndexPath indexPath: NSIndexPath) {
let category = categoriesArray[indexPath.row]
let detailVC = DetailViewController()
detailVC.title = category.title // your title
self.navigationController?.pushViewController(detailVC, animated: true, completion: nil)
}
Alternatively, in your DetailViewController you can do:
class DetailViewController : UIViewController{
var category : Category!
override func viewWillAppear(){
super.viewWillAppear()
self.title = self.category.title
}
}

How to set the topmost cell (first row) of detail view's table view with master view's selected cell content?

Working on a social iPhone app using Swift (with a Storyboard) and Parse where users can create posts and comment on posts similar to the Facebook iOS app and other social network apps.
The app has an initial, master Home Feed page (which displays user posts) and a detail Reply page (which displays user comments). Both use the PFTableViewController class and each of those table views have their own PFTableViewCell implemented in separate swift files as the prototype cells.
I am trying to send the content (username, post message, timestamp, etc) of a selected post cell from the master Home Feed page to the detail Reply page's topmost cell (the first cell at the top of the table view).
My goal is to have it work similar to the way the Facebook, Instagram, and Twitter iOS apps have it - whenever a user selects a post in the main feed/timeline, the detail view is shown where the main post is at the top (but not pinned to the top - meaning it will scroll up/down with the tableview) and its comments are in the cells beneath it.
I appreciate your help and time! Thank you!
On Selection on left panel, you can make tableview on right panel scroll to top animated false.
After further research, one way to "hack" it is by doing something similar to the following:
1) Create a custom tableview cell for the top row (topmost cell) by implementing it in a separate Swift file, just as you may have done for the prototype cell.
2) Now you have two custom cells. So implement two function where in each you customize them the way that serves your apps requirements, etc and the cell.
3) In the cellForRowAtIndexPath method, use an if/else statement to return the appropriate tableview cell for row 0 (topmost/header cell), otherwise return the other prototype cell for any other row (i.e.: the cells beneath the header cell):
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
if indexPath.row == 0 {
return headerCellAtIndexPath()
} else {
return commentCellAtIndexPath(indexPath)
}
}
func headerCellAtIndexPath() -> CommentsHeaderTableViewCell {
let headerCell = tableView.dequeueReusableCellWithIdentifier("topCell") as! CommentsHeaderTableViewCell
// Customize your headerCell...
return headerCell
}
func commentCellAtIndexPath(indexPath:NSIndexPath ) -> CommentTableViewCell {
let commentCell = tableView.dequeueReusableCellWithIdentifier("commentCell", forIndexPath: indexPath) as! CommentTableViewCell
// Customize your commentCell...
return commentCell
}

swift toggle between different table view cell layouts

I wonder what techniques there are when it comes to toggle between different layouts in a table view.
What I have right now is an embedded tableview/custom cell inside my VC.
It has a simple list design, an image / title.
What I would like to do is when the user press the "grid" button it will change the layout into a bigger cell, kinda like how instagram looks.
So is it possible to animate between different cell layouts in a tableview?
thanks!
I don't believe that it's possible to change the style once it has been initialised. You can however change between your own custom cells at runtime and is probably best achieved using a protocol for different cell types.
Yes it is possible. I have used it but I am not saying that this is the ultimate way.
Here are the steps you may like to follow :
Design two different cells with different identifiers(I did it from storyboard)
In cellForRowAtIndexPath method, check for the identifiers and display the layouts accordingly.
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cellIdentifier = (self.layoutSegmentControl.selectedSegmentIndex == 0) ? "gridLayoutCell" : "listLayoutCell" //I used segment control to toggle, change the condition as per your need
let cell = tableView.dequeueReusableCellWithIdentifier(cellIdentifier) as! MyCustomTableViewCell
if(cellIdentifier == "gridLayoutCell")
{
//Set the values
cell.bigImgView.image = [yourimage] //for ex
...
}
if(cellIdentifier == "listLayoutCell")
{
//Set the values
cell.thumbnailImgView.image = [yourimage] //for ex
...
}
}
reload your tableview when toggling(layout changes)
Try this and let me know. Hope it works for you!

Call UITableViewCell Method from Method in main VC?

I'm trying to do the opposite of what most people on this topic are asking to do. Most people want a button within a table view cell to call a method in their VC / VC table. I already have a protocol doing that.
Problem / Question
What I am trying to add now is the opposite: I need a button press on my main ViewController (which houses my table) to call a method within my CusomTableViewCell class (note: the button pressed on the main VC is not in the table). I have the protocol class created and the function written, but I don't know how to set the CustomCellViewClass as the delegate. When I did the opposite, I inserted "cell.delegate = self" into the cellForRowAtIndexPath method. I've also used prepareForSegue to assign a delegate. But with no segue and now cell-creation-method, I'm lost!
Example of Desired Function
My end goal is that pressing a button that is in the main VC will change the title of a button within the cells. A simple example would be that I have one view with a single table, on button press the table contents switch between two arrays, cars and motorcycles. When the table is showing cars, the cell button titles should all read "Look inside" but when showing the motorcycle button it should read "Look closer".
Code
I've already written the function that I want the cell to execute:
func cellButton_Title_Switch (currentList: String) {
if vcState == "cars" {
cellButton.setTitle("Look inside", forState: UIControlState.Normal)
}
else {
cellButton.setTitle("Look closer", forState: UIControlState.Normal)
}
}
I created the protocol:
protocol delegateToChangeCellBut {
func cellButton_Title_Switch (currentList: String)
}
I have the self.delegate.cellButton_Title_Switch(currentList) within my VC button and the protocol added to my custom cell class declaration. But how do I do that last missing piece in the custom cell class, where I assign the class to the delegate?
My original problem was that my UITableView's cell has buttons and labels, some of which change to match the state of things outside the table, things handled by the mainViewController.
The custom cell is defined by a customCellviewController. All the custom cell buttons and labels have their IBOutlets connected to the customCellviewController. I couldn't figure out how to make an action/change outside the table (in the mainViewController) immediately cause the cell labels and buttons to change.
Note: Protocols tend to work they other way around (a cell action triggers a function in the mainVC). I couldn't figure out how to use a protocol to solve this. Luckily, the solution was much simpler than a protocol.
The Solution!
I wrote the "updateCell" method that would change the labels and buttons and that code now sits in the customCellviewController. Then I called/triggered the "updateCell" function from the mainViewController simply by adding the call into my cellForRowAtIndexPath function. So it looks something like this:
var stateOfPage = "Green"
//Creates the individual cells. If the above function returns 3, this runs 3 times
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
//Setup variables
let cellIdentifier = "BasicCell"
let cell = tableView.dequeueReusableCellWithIdentifier(cellIdentifier, forIndexPath: indexPath) as! customCell
cell.updateCell(stateOfPage)
return cell
}
Now the above code/method runs when the table gets built. So to update the cells, have some button tap or other action reload the table data:
tableView.reloadData()
Good luck.

Resources