I have a UILabel and need to reference its initial indexPath.row in another view controller? I have already used the tag of the UILabel for a different purpose, but is there a way I can set an associated value of some sort with the UILabel in swift.
Your UILabel should not be acting as a store for data, that's what data structures are for. One simple possibility to start out with is to have the tag be the index of that label's data in an array or use the tag value as the key of a dictionary and store the data you need in those data structures.
If you are using custom view for your TableViewCell (which I assume you are ), I would just create new custom view (inherited from UILabel) and add another property to it for indexPath and assign this property with the original indexPath, I would use this custom label view instead of UILabel. Please let me know if you have questions about this approach.
Related
I am making an iPhone app.
In this application I have to make a look like below.
I am not allowed to use collection view.
I am using tableview, and custom cells. Which I am easily able to incorporate. Means taking 3 subviews in Custom cells. And making a look.
Here the problem is In a cell, how do I distinguish each object. so that I can call each object, to set an image on image view.
Is there any Object oriented mechanism to distinguish all 3 objects in a cell ?
Try to get the data as NSArray of NSDictionary containing an array of 3 objects that you want to display on cell.
Assign tag to UImageView in the custom cell.
In cellForRowAtIndexPath, get the 3 objects and apply image using switch case.
Well everything depends on how you get the data from the server
You can use outlet collections which will give you an array of UIImageView and you can assign different tags to the imageview so you can assign to them.
You can use these guides to understand how outlet collections works:
http://nshipster.com/ibaction-iboutlet-iboutletcollection/
http://useyourloaf.com/blog/interface-builder-outlet-collections/
All the standard procedures should work to achieve this but then it only depends on how nice you want to do this.
The straight forward procedure is to expose the outlets of the image views and labels in the cell and assign the correct values to those when dequeuing/creating table view cell.
The first upgrade would be to rather expose 3 setters on the cell to simply set your model to each of them which will then internally set the images and texts inside the cell.
The next thing you may do is to rather insert an array of objects (always sending up to 3 in your case) instead of having 3 setters.
At this point you may actually rather use a collection view INSIDE the cell and make the cell a data source for the collection view. But this is totally optional.
Now since you may still dislike the table view data source you may create another model which contains an array of objects (again up to 3 in your case) and make a system that will distribute your original array of objects into the array of these containers.
If then you need to handle buttons or other touch events they may be handled with collection view delegate or 3 buttons and in both cases I advise you to handle those in the cell and create a custom delegate for the cell which will report the event with the appropriate model.
This together generates the following:
When you receive the data call a container class to distribute your array of objects (into groups of 3) and assign it to your table view data source (view controller usually)
Number of rows is the same as number of containers in the array
Cell for row assigns the container with row index to the cell. It assigns self as a delegate
Cell internally handles the object distribution either via collection view, separated outlets or outlet collections.
Cell handles actions and reports them back to the delegate (- (void)myCell:(MyCell *)cell selectedItem:(MyObject *)item;)
The cell delegate can again handle what to do upon reported actions
Also if you want to avoid a collection view inside the cell you can create a custom view using xib so you do not copy the labels, image views and such. Then simply create 3 of these custom views inside the cell. Also by using inspectable and designable these views will be visible inside the storyboard.
First I'll say that a restriction against using UICollectionView is silly. Are you still targeting ios5?
I'd look at it like this.
make your own view class for the 'subcell' let's use this term for any single instance of the 3 views per cell. I'd subclass UIImageView, adding the label for the name down the bottom and a 'setSelected:' kind of method to highlight when selected via user interaction by drawing differently.
make a UITableViewCell subclass to host and layout up to three of these subcells. I say up to 3 because the last cell may contain 1 or 2 subcells and not 3 if the total people to represent is not divisible by three.
Selection Logic: You'll need to override 'setSelected:' because you want to deselect and select only subcells, you don't want the whole cell to highlight on selection, only a third of it.
You'll also want to implement touchesEnded: in this cell so that you can figure out which of the three subcells was last touched, and you'll need to be able to query or communicate this back to the controller, probably using delegation. If the cell can communicate back whether selection was in subcell 0,1 or 2 then this together with the UITableViewDelegate didSelectAtIndexPath should map to your model nicely - selectedPerson = myArrayOfPeople[ (indexPath.row * 3) + subcellIndex ]
You'll be able to decorate your cells in cellForRowAtIndexPath: in similar fashion..
personOne = model.arrayOfPeople[indexPath.row*3]
personTwo = model.arrayOfPeople[indexPath.row*3 +1 ]
personThree = model.arrayOfPeople[indexPath.row*3 + 2 ]
I have a problem with getting data from cells in UITableView.
I have a lots of cells (other class with xib) with some people info in table view. Every cell has own switch.
Under table is button that will send message to every person with switch pressed on.
I set property in people class that will remember if switch for person is on. Every switch in cellForRow method has set selector with method for switch action.
Problem is that I have no idea, where to set person property value about switch state. In selector method I don't have access to person info. I have sender, but no info about person.
I'd do this in one of 2 ways depending on what exactly you're trying to do:
Pass a pointer of the person object to the cell when you're configuring it and let the cell handle updating the property that holds the value of the switch.
Make a protocol with a function
-(void)switchInCell:(UITableViewCell*) cell valueModifiedTo:(NSInteget) newValue
Adopt the new protocol in your view controller, add a delegate property of type new protocol to the cell, call that delegate method from within the cell if the switch value changes.
In that method implementation in your view controller, you can do
NSIndexPath* indexPath = [theTable indexPathForCell:cell];
PersonClass* person = Your_DataSource_Array [indexPath.row];
//modify person properties
You can set the UIView tag property to a number, for each of the subviews of the table View Cell's "content" property, at the cell's creation time (e.g. when you add all the UIViews, e.g. labels, buttons, etc...), giving each subview a unique value.
Later, if just given the UITableViewCell, you can iterate through the subviews of is content view and locate your switch (and any other UIViews) by checking their tag value.
If you are using custom cells, you can have method for your switch inside the cell's implementation. From the method, you can get back to the data source using delegation, or notifications and you can pass indexPath of the cell for further identification of the object in the data. You can have a property to store the indexPath of the cell in implementation of the cell's class and you can set the value to that property in cellForItemAtIndexPath: method. Good Luck!
you said you have sender. then you need to just make custom subclass of the control you are using and create a custom property like this.
#property (nonatomic, strong)NSIndexPath *indexPath;
and set it in cellforrowatindexpath. when your selecter calls the you can parse the sender to the custom created class and get the value form the property. try this once.
I am working on a UITableView inside a UIViewControlller and I would like to add a new cell to a row, but in a way that the only thing showing on the table would be the user defined name, but hidden data (such as a hyperlink) would be retained too. The purpose is to open such hyperlink when pressing the relative button.
I'm using
[dataSource addObject:UserDefineddName];
and this adds the name to the row, but how can I add the data too, without displaying it?
I have labels and a button set up in IB and I was thinking that perhaps the link could be assigned to a hidden label, but it's not clear to me how to do it.
Please advise!
Many thanks
Create a class for your data with two properties, name and url. Then simply fill your data source with instances of this class instead of simply strings. In your cellForRowAtIndexPath do something like this:
titleLabel.text = [dataSource objectAtIndex:indexPath.row].name;
I'm building a blog reader app with a list of post objects in an NSArray.
cell.postTitle.text=post.Title;
I'm trying to find out which post has been selected and then set the corresponding cell.postTitle.text to a lighter font.
Somehow I have to remember this state when the navigationcontroller segue back to the top level (and destroyed?).
Can anyone tell me the best way to do this? Each post object has a postID. Maybe I can store this in NSUserDefault, but the list of read postID might grow too big over time.
Also there is didSelectRowAtIndexPath but in this method, I can't access the cell properties directly right?
If you are using a UITableView to display your information you should use the delgate didSelectRowAtIndexPath.
In order to make this work with a custom interface (I assume you have), you should create your own custom cell, subclass UITableViewCell and create a controller and xib. You can then register your xib to the table and use that. Then you can call the needed attributes.
Somehow I have to remember this state when the navigationcontroller segue back to the top level (and destroyed?).
This is best handled by using a delegate method by creating a custom protocol:
https://developer.apple.com/library/ios/documentation/cocoa/conceptual/ProgrammingWithObjectiveC/WorkingwithProtocols/WorkingwithProtocols.html
When your user clicks the cell, you would call a delegate method which could set the postID value back in the top controller.
Also there is didSelectRowAtIndexPath but in this method, I can't access the cell properties directly right?
Yes, you can get at the cell. Check out this question and answer:
How to reach the current selected cell in didSelectRowAtIndexPath?
Alternatively, if you want to get at the data you used to create the table cells in the first place, in your didSelectRowAtIndexPath method you can used the indexPath.row value to get the value from your array that is at that index position and pass that via a delegate method.
Found a solution.
Just add the postId of the selected post to an NSMutableArray in didSelectRowAtIndexPath. Then in cellForRowAtIndexPath, I check to make sure that the postID doesn't exist in my self.readPostID array.
If it does I set the font to Helvetica Light, else set it to Helvetica Bold.
First I had to make sure to [self.tableview reloadData] every time viewdidappear.
Second, I just save my NSMutableArray of readPostId to NSUserDefault everytime viewDidDisappear and reload the array in viewDidLoad.
Also I had to make sure that cell reuse doesn't affect the font. The else condition fixed that.
I have a TableView with a prototype cell, in this prototype cell I have a text field.
Well, what I need is to get a information from this text field when it changes. I need to do that to feed a object.
How can I do that ?
Short answer - you don't.
Slightly more in depth answer...
The UITableViewCell is a "view". It is used only to display information to the screen. It is not for storing data in.
In a UITableViewController (i.e. UITableViewDatasource and UITableViewDelegate) you should have an NSArray (or an NSFetchedResultsController) that you use to store information in.
Then using the delegate methods you populate the table with that data.
If the data changes then you reload the table to update the cells.
What should never happen is the following...
Load the table by passing in data to the cell.
The cell then changes its own data and changes what is on the screen.
The controller then reads that data out of the cell.
No, no, no, don't do this.
What should happen is this...
Load the table and configure the cell display to represent the correct part of the data.
When the button is pressed (or text field is changed, etc...) in the cell then call a method back in the controller to update the data accordingly.
Now the data has changed, reload the cell.
It will now show the correct information based on the new data.
You need a custom cell with a public property (IBOutlet) UITextfield. Then you can set your ViewController as the textField's delegate in cellForRowAtIndexPath,
cell.textField.delegate = self;
in this case your ViewController has to implement UITextFieldDelegate protocol.