Changing singleton content - ios

I have two view controllers, one is of table view and another one is to display the content of selected cell from table view. Now both view controller and tableview cell has textfields, if change the text of textfield in content displaying view controller I want same change in respected tableview cell when I came back to tableview. Note that, the data is accessing from singleton object. I tried to change the value in singleton, changes are done inside the view controller it does not effecting tableview cell.
func textFieldShouldReturn(_ textField: UITextField) -> Bool {
resignFirstResponder()
if(textField == carRating){
let rating = Float(textField.text!)
secondInstanceForMyData.masterCarData[index].carRating = rating
}
return true
}
Here carRating is an element of singleton instance "secondInstanceForMyData". This code is in viewController for selected row in table view. Now after changing the value if go back to table view there is no change in respected cell. How can I achieve change in respected table cell, I have index value for selected cell.

You might just need to call reloadData or reloadRowsAtIndexPaths:withRowAnimation: on the UITableView when you go back to it.
This assumes you definitely have a singleton you are working with -- secondInstanceForMyData is suspiciously named.

Related

Preview a view in a table view cell from selecting a row on touch

In my table view cell I have a UIView that shows 5 stars rating. Users can tap it to change the rating. The problem is, when users change the rating the didSelectRow on the table view row is triggered. What is the best way of preventing this? Is there a way to block the UIView from passing the touch events to the table view? I still want the table view cell to be tappable outside the rating view.
1.If you are using buttons in ratting view for ratting?
if yes then increase button size
2.Otherwise you have to increase cell height for ratting view clickable.
I request you to provide screenshot of your tableview
and Answer if you are using any library for ratting.
You could override UIResponder's next property to break the responder chain:
extension CosmosView {
open override var next: UIResponder? {
return nil
}
}
See https://developer.apple.com/documentation/uikit/uiresponder/1621099-next.

How to hide a view from a stack view in table view cellForRow delegate method

I'd like to know what's the cleanest way to remove a view from a stack view if a certain property in my data model is nil. I have a table view which is populated by prototype cells. They look like this:
The second label text contains an optional value which may be nil; I want to hide the label if it's nil. Should I call removeArrangedSubview inside the cellForRow table view cell method or inside the CustomTableViewCell class with a function?
I want to hide the label if [optional value] is nil
You should set label's hidden property to true rather than removing it from arranged subview list of stack layout in order to avoid adding it back when the cell gets reused for a different row.
It is mostly a matter of preference where you do it. If most of your cell setup code is in the cellForRow function, you should hide and unhide the label from that function as well:
if let labelText = model.getTextForMyLabel(indexPath.row) {
cell.label.text = labelText
cell.label.hidden = false
} else {
cell.label.hidden = true
}
If you have a setter for label text in the code for your CustomTableViewCell, you can use the same approach to set the label's hidden property along with its text.

bringSubviewToFront() doesn't do the same thing it does in the storyboard when I set it programmatically

So I have a subview called emptifier in a TableViewController that is just an empty UIView and an empty sub-subview. I use emptifier to hide the separator for the last cell in my tableview. But when I have an empty table, I want to push this subview to the back of the tableview hierarchy (behind all the other cells) so that I can actually see the separators and see that the tableview is empty.
So here is what I have in code:
func clearTable() {
/*
Clearing table code
*/
//To show the last cell's separator:
self.emptifier.superview!.sendSubviewToBack(self.emptifier)
}
And:
func loadTableResults() {
/*
Load Results code
*/
//To hide the last cell's separator:
self.emptifier.superview!.bringSubviewToFront(self.emptifier)
}
Now this should work perfectly, and I checked using print(tablview.subviews) that emptifier is a subview of the table AND that it moves to the front/back of the table correctly. But for some reason, whatever order I set in the storyboard beforehand reins supreme, it's as if I don't have anything written in code.
My guess is that there is something having to do with tableviewcontrollers that I just don't understand and I just can't manipulate a tableview's subviews that way. But I tried to look it up and I couldn't find anything.

Locate a specific content view in a UITableViewController using viewWithTag function

I need to locate a specific content view in a table view.
This table view is driven by a UITableViewController that is used to show my user with some parameters he can change in my app.
For one of those cell, I need to programatically add a UITextView that I had subclass (NSTextStorage) to change text attribute, have rich text editing and so.
So I need to find that specific cell (content view) to by able to call my .addSubview. I thought this you be as simple as adding a specific tag to this view and call the .viewWithTag later in my viewDidLoad. The problem is a got a nil!?!
Here's the little code snippet and a capture of my table hierarchy
override func viewDidLoad() {
super.viewDidLoad()
let specific = self.view.viewWithTag(99) //--> Return nil
let specific2 = self.tableView.viewWithTag(99) //--> Also nil
What I'm doing wrong or did I miss something? This's my first shot at this method (viewWithTag) and maybe there's something else I need to do?
Thx!
You can't call this on viewDidLoad, since you are using an UITableView, all those Cells will be only loaded AFTER viewDidLoad on the method tableView:cellForRowAtIndexPath:.
So if you want to insert anything on a Cell, you must use tableView:cellForRowAtIndexPath: to do that.
I'm not sure if viewWithTag works with TableView, but you shouldn't do that. To get a View for a specific Cell (after it being loaded on the method I said above) you can call the method below:
UITableViewCell *cell = [self.tableView cellForRowAtIndexPath:[[NSIndexPath indexPathForRow:0 inSection:0]];
After a lot of search, I decided to go with a Container View.
So I place UIContainerView control inside my cell. This create a embed segue to a custom view.
In this view a can override the viewDidLoad and load my custom UITextView Control...
class CustomView: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
// ... code of my super class UITextView with my custom NSTextStorage
self.view.addSubview(specialTextBox)
}
So now it works! :-)

Update DataSource from UITextView in UITableView

I have a UITableView and each UITableViewCell contains an editable UITextView.
My data source is a NSMutableArray containing NSMutableDictionary that holds the text value and some styling keys for the text.
How can I (efficiently) make it so that any changes a user makes to the UITextView are updated in the corresponding datasource NSMutableDictionary?
A rather simple way is to utilize the index path of the table, it is NOT the cleanest so it depends on the complexity of your datasource, and if you have multiple tables etc.
What you can do is when the user ends editing the textView or selects another row in tableView, you read the indexPath of the selected row (That requires that the row keeps actually being in the selected state while editing the textView which it should by default). From there you call your update method.
To catch the end of editing you implement
-(void)textViewDidEndEditing:(UITextView *)textView
{
NSIndexPath *selectedpath = [myTable indexPathForSelectedRow];
[self myUpdateMethodForIndexPath:selectedpath];
}
To catch deselect of the table row and the above doesnt get called, you implement
-(void)tableView:(UITableView *)tableView didDeselectRowAtIndexPath:(NSIndexPath *)indexPath
{
[self myUpdateMethodForIndexPath:indexPath];
}
Your update method must then read the value of the textView at the corresponding cell at the indexPath and handle this in the datasource. To care for sections of course you need to correctly handle the indexPath, in the example just the row is used (1 section).
-(void)myUpdateMethodForIndexPath:(NSIndexPath *)editPath
{
UITableViewCell *editCell = [myTable cellForRowAtIndexPath:editPath];
NSString *newText = editCell.theTextView.text;
....
NSMutableDictionary *dict = [myDictArray objectAtIndex:editPath.row];
....
}
First of all, you must assign a tag to each UITextView, to know exactly which UITextView are you refering.
Then you must implement UITextViewDelegate in your view controller which holds the tableview. Then, make this view controller the delegate of each UITextView. Read here how to implement it: UITextViewDelegate reference.
Look for the protocol method that better fits your needs (probably – textView:shouldChangeTextInRange:replacementText:, wich is called each time the text changes in any range.
In the delegate method, you can read the text with UITextView.text property, and assign this value to your data model (the dictionary).
Another possible approach is to use KVO pattern, but it requires more coding and a better understanding both, the pattern and the implementation. Hope it helps!
Make your view controller the delegate of each text view. Listen for appropriate events to get the updated text. Then have the view controller update the data model with the updated text.
If you have custom cells then have the cell be the text view delegate. Then the cell should notify its delegate (the view controller) about the updated text. Of course this requires that your custom cell class define its own delegate protocol and the view controller should make itself the delegate of each cell.
That's as specific as an answer can be for such a vague question.

Resources