Adding UIView to UIViewController dynamically - ios

I have an Array of 5 items. This array is dynamic therefore the number of items may vary.
I have aUIVIewController as shown in the following image. In my UIView, there are few components (Like buttons, etc). Based on the number of items in the above array i want to add the UIVIew to my UIViewContorlleras shown in the image.
For example: There're 5 items in the Array, then i need to add 5 UIView's to my UIViewController.
1.) I don't want to use a XIBfile for the UIView but want to use only StoryBoard. How can i design the UIView in StoryBoard ?
2.) How can i add UIView to the UIViewController dynamically as the number of items in the array increased ?

Loop through your array (I have assumed your array contains UIViews, if not you may update accordingly) like:
for(UIView *subView in arrayOfItems){
subView.position = specify the position
[self.view addSubview:subView];
}

1) You need to create a class, where the properties have IBOutlets, like this:
#interface MyView ()
#property (weak, nonatomic) IBOutlet UIView *viewContent;
#end
Than you can design your UIView inside the UIStoryboard and connect them from the class to the ui element. In previous xCode versions there was always a problem if you want to drag from UIStoryboard to the class, have to do it the different way.
2) To add a UIView to your UIViewController you just have to add it as subView inside your UIViewController like this:
[self.view addSubView:anyView]

set the frame of the sub views as per your design
for (int i=0;i<YourViewArrayCount; i++) {
[self.view addSubview:[YourViewArrayCount objectAtIndex:i]];
}

create a UICollectionView in the storyboard , and add a UICollectionViewCell prototype with a UIButton in it , and in the UICollectionViewDataSource method numberOfItemsInSection return your array count:
-(NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section
{
return yourArray.count;
}
and in order to handle the button touch event ,you'll have to set the UIButton tag to 999 for example in the UICollectionViewCell prototype in storyboard,and in the UICollectionViewDataSource method cellForItemAtIndexPath get a reference to the button using its tag then add the touch event handler to it programmatically :
-(UICollectionViewCell*)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
UICollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:#"yourCellIdentifier" forIndexPath:indexPath];
UIButton *button = [cell viewWithTag:999];
[button addTarget:self action:#selector(buttonTouchHandler:) forControlEvents:UIControlEventTouchUpInside];
return cell;
}
finally to find out which button was actually touched (at which indexPath) , i suggest subclassing the UIButton class and add a property of type NSIndexPath (don't forget to change the button class in storyboard to your new UIButton subclass) and in the UICollectionViewDataSource method cellForItemAtIndexPath do the following
-(UICollectionViewCell*)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
UICollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:#"yourCellIdentifier" forIndexPath:indexPath];
MySepcialButton *button = [cell viewWithTag:999];
button.indexPath = indexPath;
[button addTarget:self action:#selector(buttonTouchHandler:) forControlEvents:UIControlEventTouchUpInside];
return cell;
}
this way in the buttonTouchHandler: method you can check the button property indexPath.

Related

How to access UIButton (or any UIElement) inside UITableViewHeaderFooterView subclass?

I'm learning UITableView in Objective-C. Could you hint me how to access UIButton inside UITableviewHeaderFooterView subclass from my UIViewController class? Programatically, as I don't use IB.
Full code: https://gist.github.com/tomnaz/3d790b308d305af8b98c
[[??? btnEdit] addTarget:self
action:#selector(addNewItem:)
forControlEvents:UIControlEventTouchUpInside];
Don't do this in viewDidLoad, do it in viewForHeaderInSection: where you have a pointer to your header view.
- (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section
{
static NSString *headerReuseIdentifier = #"TableViewSectionHeaderViewIdentifier";
ItemsHeaderView *sectionHeaderView = [tableView dequeueReusableHeaderFooterViewWithIdentifier:headerReuseIdentifier];
[sectionHeaderView.btnEdit addTarget:self action:#selector(addNewItem:) forControlEvents:UIControlEventTouchUpInside];
return sectionHeaderView;
}
When you initially create the buttons, you can store them in a property or array so you can easily find them later.
Alternatively, you could set a tag on the button, and then call viewWithTag: on your UITableviewHeaderFooterView subclass to find the button.

If a UITableViewCell has multiple buttons, where is the best place to handle touch events

I'm presenting a lot of data in format of a table with multiple columns. Almost each column has a button (up to 4 in total) and each row is a UITableViewCell.
How could I detect that the buttons were touched and where should I handle touch events of the buttons? I'm certain, it shouldn't be a didSelectRowAtIndexPath method though.
As soon as, I could detect which button was pressed, I would fetch the data in that particular row and manipulate it. So, I need to know the indexPath of the row, as well as what button was pressed on it.
You can subclass UIButton with two properties row and column and implement the logic below:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"Cell"
forIndexPath:indexPath];
MyButton *button1 = (MyButton *)[cell viewWithTag:1];
button1.row = indexPath.row;
button1.column = 1; // view tag
[button1 addTarget:self
action:#selector(clickAction:)
forControlEvents:UIControlEventTouchUpInside];
// button2,button3...
return cell;
}
-(void)clickAction:(MyButton *)sender {
// now you can known which button
NSLog(#"%ld %ld", (long)sender.row, (long)sender.column);
}
Generalized undetailed answer:
Create UITableviewcell subclass, link cell ui elements to this class.
Add method configureWithModel:(Model*)model; //Model being the information you want the cell to represent
Manipulate that information or
If you need to manipulate the screen or other objects. You need to give the table view cell subclass a reference to the other objects when the cell is created. (in code or in storyboard or in nib).
how to handle button presses in ios 7: Button in UITableViewCell not responding under ios 7 (set table cell selection to none)
how to link a button: http://oleb.net/blog/2011/06/creating-outlets-and-actions-via-drag-and-drop-in-xcode-4/
If those four views are UIButton then you will receive the tap events on each button or if they are not UIButton then you should add UITapGestureReconiser on each of this views
Several options here. But I would do the following:
Adopt a Delegate Protocol in your custom cell class (see here: How to declare events and delegates in Objective-C?) . This will handle the target selector for the buttons. Pass this message back to your view controller with the sender. To detect which cell it was in do the following:
CGPoint buttonPosition = [sender convertPoint:CGPointZero toView:self.tableView];
CGRect senderFrame = CGRectMake(buttonPosition.x, buttonPosition.y, sender.frame.size.width, sender.frame.size.height);
From here you can decide what the do. Use the buttons .x coordinate to determine which button it was or specify a different tag for each button in cellForRowAtIndexPath:. Or if you want to grab the index path of the cell you can do:
NSArray *indexPaths = [YOUR_TABLE_VIEW indexPathsForRowsInRect:senderFrame];
NSIndexPath *currentIndexPath = [indexPaths lastObject];
Because each button has a different action, the only thing you need to get at runtime is the indexPath of the button. That can be done by looking at the button's superviews until a cell is found.
- (IBAction)action1:(UIButton *)button
{
UITableViewCell *cell = [self cellContainingView:button];
NSIndexPath *indexPath = [self.tableView indexPathForCell:cell];
MyDataModel *object = self.objects[indexPath.row];
// perform action1 on the data model object
// Now that the data model behind indexPath.row was done, reload the cell
[self.tableView reloadRowsAtIndexPaths:#[indexPath]
withRowAnimation: UITableViewRowAnimationAutomatic];
}
- (id)cellContainingView:(UIView *)view
{
if (view == nil)
return nil;
if ([view isKindOfClass:[UITableViewCell class]])
return view;
return [self cellContainingView:view.superview];
}
There: no delegates, no tags, and the action doesn't care about the internals of the cell.
You will still want to subclass UITableViewCell with the four buttons (call them button1, button2, button3, and button4 if you don't have better names). You can make all the connection is Interface Builder. This will only be needed for populating object data into the cell during -tableView:cellForRowAtIndexPath:.
Ideally, you should create a custom cell by subclassing UITableViewCell and implement the actions for each of these buttons in that cell. If your view controller needs to know about these actions, you can define a protocol, MyCustomCellDelegate or similar, and have your view controller conformed to that protocol. Then MyCustomCell will be able to send messages to the view controller when user interacts with its buttons or other controls.
As in the example code below, you can create a cell in storyboard or nib and hook one of the button's action to firstButtonAction method of CustomTableCell class.
Also, you need to set your view controller as delegate property of CustomTableCell object created and implement the method buttonActionAtIndex: of CustomTableCellDelegate in your view controller class. Use controlIndexInCell param passed to this method to determine which button might have generated the action.
#protocol CustomTableCellDelegate <NSObject>
- (void) buttonActionAtIndex:(NSInteger)controlIndexInCell
#end
In CustomTableCell.h class
#interface CustomTableCell: UITableViewCell
#property (nonatomic, weak) id <CustomTableCellDelegate> delegate
- (IBAction) firstButtonAction:(id)sender
#end
In CustomTableCell.m class
#implementation CustomTableCell
#synthesize delegate
- (IBAction) firstButtonAction:(id)sender{
if ([delegate respondToSelector:#selector(buttonActionAtIndex:)])
[delegate buttonActionAtIndex:0];
}
#end
This is a personal preference on how I like to handle situations like these, but I would first subclass UITableViewCell because your table cells do not look like a default iOS UITableViewCell. Basically you have a custom set up, so you need a custom class.
From there you should set up your 4 IBActions in your header file
- (IBAction)touchFirstButton;
- (IBAction)touchSecondButton;
- (IBAction)touchThirdButton;
- (IBAction)touchFourthButton;
You do not need to pass a sender in these actions, because you will not be using that object in these methods. They are being created to forward the call.
After that set up a protocol for your UITableViewSubClass
#protocol UITableViewSubClassDelegate;
Remember to put that outside and before the #interface declaration
Give your sell a delegate property
#property (nonatomic, strong) id<UITableViewSubClassDelegate> delegate;
and finally define your actual protocol, you will need to set up 4 methods, 1 for each button and take your subclass as a parameter
#protocol UITableViewSubClassDelegate <NSObject>
- (void)forwardedFirstButtonWithCell:(UITableViewSubClass*)cell;
- (void)forwardedSecondButtonWithCell:(UITableViewSubClass*)cell;
- (void)forwardedThirdButtonWithCell:(UITableViewSubClass*)cell;
- (void)forwardedFourthButtonWithCell:(UITableViewSubClass*)cell;
#end
This will be placed outside of the #interface #end section at the bottom
After that create a configureWithModel: method in your #interface and #implementation as well as a property for your model
#interface:
#property (nonatomic, strong) Model *model;
- (void)configureWithModal:(Model*)model;
#implementation:
- (void)configureWithModal:(Model*)model {
self.model = model;
// custom UI set up
}
From here you should configure your action methods in your #implementation file to call the delegate methods, i'm only showing the first one, but you would do this with all of the IBActions
- (void)configureWithModal:(Model*)model {
[self.delegate forwardFirstButtonWithCell:self];
}
From here your custom cell set up is done and we need to go back to the UIViewController that is displaying the UITableView. First go into the header file of the view controller, and import your custom UITableViewCellSubClass and then setup the class to implement this protocol.
It should look something like this
#interface MYViewController : UIViewController <UITableViewSubClassDelegate>
from there you should go into your cellForRowAtIndexPath: method and configure your custom UITableViewCell
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCellSubClass *cell = [tableView dequeueReusableCellWithIdentifier:#"CellIdentifier"];
cell.delegate = self;
Model *cellModel = self.tableData[indexPath.row];
[cell configureWithModel:cellModel];
return cell;
}
Now go into your cell class and copy paste all of the protocol methods into your viewController class. I will display one as an example.
In your UIViewController:
- (void)forwardedFirstButtonWithCell:(UITableViewSubClass*)cell {
Model *cellModel = cell.model;
// do stuff with model from outside of the cell
}
do that for all methods and you should be good.
Remember to have all your #imports in so there's no forward declarations and remember to link up the IBActions to your storyboard or xib files. If you want a custom xib for your table cell you will have to check if the cell is nil and then allocate a new one, but if you are using prototype cells then this should be sufficient.
For simplicity sakes i put forwardFirstButtonWithCell: but i would encourage making the name something that describes what it's doing such as, displayPopOverToEnterData or something similar. From there you could even change the parameters of the delegate protocol methods to take models instead so instead of
- (void) displayPopOverToEnterDataWithCell:(UITableViewSubClass*)cell;
make it
- (void) displayPopOverToEnterDataWithModel:(Model*)model;
but, i don't know what type of information you need to access from the cell. So update these methods as you see fit.

iOS: Storyboard CollectionView segue not being triggered

I have a UICollectionView controller embedded inside a navigation controller. The collectionView lists projects and each cell is supposed to segue to a ProjectDetail screen.
I simply cannot get the segue to trigger. If I simply drop a button on the nav bar and hook up a segue to the detail, it works. But triggering from my CollectionView cell doesn't.
Here is what the storyboard looks like: http://cl.ly/RfcM I do have a segue hooked up from the CollectionViewCell to the ProjectDetailViewController
Here's the relevant code inside my ProjectDetailViewController:
#interface ProjectCollectionViewController () {
NSArray *feedPhotos;
Projects *projects;
}
#end
#implementation ProjectCollectionViewController
- (void)viewDidLoad {
[super viewDidLoad];
[self.collectionView registerClass:[FeedViewCell class] forCellWithReuseIdentifier:#"cell"];
[self loadData];
}
- (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath {
NSLog(#"selected %d", indexPath.row);
Project *project = [projects getProject:indexPath.row];
NSLog(#"project = %#", project);
}
- (void)loadData {
[self.projectLoader loadFeed:self.username
onSuccess:^(Projects *loadedProjects) {
NSLog(#"view did load on success : projects %#", loadedProjects);
projects = loadedProjects;
[self.collectionView reloadData];
}
onFailure:^(NSError *error) {
[self handleConnectionError:error];
}];
}
- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section {
return projects.count;
}
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {
static NSString *identifier = #"cell";
FeedViewCell *cell = (FeedViewCell *) [collectionView dequeueReusableCellWithReuseIdentifier:identifier forIndexPath:indexPath];
cell.backgroundColor = [UIColor colorWithRed:0.0 green:0.0 blue:1.0 alpha:1.0];
UIImageView *cellImageView = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, 100, 100)];
Project *project = [projects getProject:indexPath.row];
NSString *imageUrl = [project coverPhotoUrl:200 forHeight:200];
NSLog(#"imageurl =>%#", imageUrl);
if (imageUrl) {
[cellImageView setImageWithURL:[NSURL URLWithString:imageUrl]];
}
[cell addSubview:cellImageView];
cell.imageView = cellImageView;
return cell;
}
I'm guessing the problem is somewhere in how I'm hooking up the Cells to the CollectionView.
Any help would be greatly appreciated!
You cannot create segues directly from cells in a storyboard because the collectionview is populated dynamically through the data source. You should use the collectionView:didSelectItemAtIndexPath: and perform the segue programatically using performSegueWithIdentifier:sender:. Something like this:
- (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath {
[self performSegueWithIdentifier:#"MySegueIdentifier" sender:self];
}
where MySegueIdentifier is the identifier of the segue defined in storyboard.
TLDR: FOR A STORYBOARD, do not call registerClass:forCellWithReuseIdentifier:. It overrides what the storyboard sets up for the cell (including how segues are handled):
How to set a UILabel in UICollectionViewCell
Brief setup
Used a storyboard
Created a new collection view controller using the Xcode template,
setting it as a subclass of UICollectionViewController.
Initially used the default UICollectionViewCell, adding a UILabel
programmatically.
The generated UICollectionViewController code registered the cell in viewDidLoad:
[self.collectionView registerClass:[UICollectionViewCell class] forCellWithReuseIdentifier:reuseIdentifier];
First Issue:
The prepareForSegue:sender: event was not firing, which brought me to this answer .
I implemented the UICollectionViewDelegate and collectionView:didSelectItemAtIndexPath: event, then called the segue programmatically.
This fixed my first issue.
Second Issue: I switched to a custom cell containing one label. After hooking everything up, the cell label was not displaying.
After some digging, I found a solution contained in the link at the top of my answer.
Third Issue and Solution: I removed the registerClass:forCellWithReuseIdentifier: line. When I ran my app, the label appeared correctly, but when I tapped a cell, it called the prepareForSegue:sender event twice. By removing the registerClass:forCellWithReuseIdentifier line, the cell was processing cell touches directly, without the need of the delegate method. This is how I expected the storyboard to work. I deleted the collectionView:didSelectItemAtIndexPath: event, which resolved the double-firing of prepareForSegue:sender:. If you are using a storyboard, do not register the cell class. It overwrites what storyboard sets up.
Have you made your CollectionView Cell's connection in Triggered Segues on selection?
You can also trigger a segue programatically using
[self performSegueWithIdentifier:#"segueIdentifier" sender:nil]
in
- (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath
Equivalent Swift code for similar question.
override func collectionView(collectionView: UICollectionView, didSelectItemAtIndexPath indexPath: NSIndexPath) {
self.performSegueWithIdentifier(#"TargetSegway", sender: self)
}
Make sure, in case if your cell has other overlapping views, "User Interaction Enabled" is unchecked (you can find this option, under attribute inspector View/Interaction). Otherwise, your Tap Gesture is consumed by the overlapping view, didSelectItemAtIndexPath may not be called.

How to get a UITableViewCell from one of its subviews

I have a UITableView with a UITextField in each of the UITableViewCells. I have a method in my ViewController which handles the "Did End On Exit" event for the text field of each cell and what I want to be able to do is update my model data with the new text.
What I currently have is:
- (IBAction)itemFinishedEditing:(id)sender {
[sender resignFirstResponder];
UITextField *field = sender;
UITableViewCell *cell = (UITableViewCell *) field.superview.superview.superview;
NSIndexPath *indexPath = [_tableView indexPathForCell:cell];
_list.items[indexPath.row] = field.text;
}
Of course doing field.superview.superview.superview works but it just seems so hacky. Is there a more elegant way? If I set the tag of the UITextField to the indexPath.row of the cell its in in cellForRowAtIndexPath will that tag always be correct even after inserting and deleting rows?
For those paying close attention you might think that I have one .superview too many in there, and for iOS6, you'd be right. However, in iOS7 there's an extra view (NDA prevents me form elaborating) in the hierarchy between the cell's content view and the cell itself. This precisely illustrates why doing the superview thing is a bit hacky, as it depends on knowing how UITableViewCell is implemented, and can break with updates to the OS.
Since your goal is really to get the index path for the text field, you could do this:
- (IBAction)itemFinishedEditing:(UITextField *)field {
[field resignFirstResponder];
CGPoint pointInTable = [field convertPoint:field.bounds.origin toView:_tableView];
NSIndexPath *indexPath = [_tableView indexPathForRowAtPoint:pointInTable];
_list.items[indexPath.row] = field.text;
}
One slightly better way of doing it is to iterate up through the view hierarchy, checking for each superview if it's an UITableViewCell using the class method. That way you are not constrained by the number of superviews between your UITextField and the cell.
Something along the lines of:
UIView *view = field;
while (view && ![view isKindOfClass:[UITableViewCell class]]){
view = view.superview;
}
You can attach the UITableViewCell itself as a weak association to the UITextField, then pluck it out in the UITextFieldDelegate method.
const char kTableViewCellAssociatedObjectKey;
In your UITableViewCell subclass:
- (void)awakeFromNib {
[super awakeFromNib];
objc_setAssociatedObject(textField, &kTableViewCellAssociatedObjectKey, OBJC_ASSOCIATION_ASSIGN);
}
In your UITextFieldDelegate method:
UITableViewCell *cell = objc_getAssociatedObject(textField, &kTableViewCellAssociatedObjectKey);
NSIndexPath *indexPath = [self.tableView indexPathForCell:cell];
//...
I'd also recommend re-associating every time a cell is dequeued from the UITableView to ensure that the text field is associated with the correct cell.
Basically in this case, I would prefer you to put the IBAction method into cell instead of view controller. And then when an action is triggered, a cell send a delegate to a view controller instance.
Here is an example:
#protocol MyCellDelegate;
#interface MyCell : UITableViewCell
#property (nonatomic, weak) id<MyCellDelegate> delegate;
#end
#protocol MyCellDelegate <NSObject>
- (void)tableViewCell:(MyCell *)cell textFieldDidFinishEditingWithText:(NSString *)text;
#end
In a implementation of a cell:
- (IBAction)itemFinishedEditing:(UITextField *)sender
{
// You may check respondToSelector first
[self.delegate tableViewCell:self textFieldDidFinishEditingWithText:sender.text];
}
So now a cell will pass itself and the text via the delegate method.
Suppose a view controller has set the delegate of a cell to self. Now a view controller will implement a delegate method.
In the implementation of your view controller:
- (void)tableViewCell:(MyCell *)cell textFieldDidFinishEditingWithText:(NSString *)text
{
NSIndexPath *indexPath = [_tableView indexPathForCell:cell];
_list.items[indexPath.row] = text;
}
This approach will also work no matter how Apple will change a view hierarchy of a table view cell.

Use a button on a UICollectionViewCell to display data from an array

I have an array of NSStrings, one UILabel & a UICollectionView.
My Question:
I want the array's count to determine how many UICollectionViewCell's there are.
Each UICollectionViewCell contains a button. Upon click, I want this button to cause the data in the array that corresponds to the UICollectionViewCell's number to be displayed in the label.
For example, if the user clicks on the 13th UICollectionViewCell's button, then the 13th NSString in the array would become the UILabel's text.
What I have done:
I have made my own subclass of UICollectionViewCell for the nib file that I use for all of the UICollectionViewCells, & connected the button to the .h file as a IBAction. I have also imported the MainViewController.h, which is the one that contains the array property that stores the NSStrings.
When I edit the code in the UICollectionViewCell's action, I cannot access the array property. The button does work - I placed an NSLog in the IBAction's method, which does work.
I have searched through tens of other answers on SO, but none answer my specific question. I can update this with samples of my code if requested.
I have made my own subclass of UICollectionViewCell for the nib file
that I use for all of the UICollectionViewCells, and connected the
button to the .h file as a IBAction.
If you connect the IBAction to the subclass of collectionViewCell you would need to create a delegate to make the touch event available in the viewController where you are displaying the data.
One easy tweak is to add the button the collectionViewCell, connect it's IBOutlet to the cell. But not IBAction. In the cellForRowAtIndexPath: add an eventHandler for button in that viewController containing collectionView.
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
//Dequeue your cell
[cell.button addTarget:self
action:#selector(collectionViewCellButtonPressed:)
forControlEvents:UIControlEventTouchUpInside];
return cell;
}
- (IBAction)collectionViewCellButtonPressed:(UIButton *)button{
//Acccess the cell
UICollectionViewCell *cell = button.superView.superView;
NSIndexPath *indexPath = [self.collectionView indexPathForCell:cell];
NSString *title = self.strings[indexPath.row];
self.someLabel.text = title;
}
Please try like this..
In YourCollectionViewCell.h
Create an IBOutlet not IBAction called button for the UIButton that you added to the xib. Remember you should connect the outlet to the cell object not to the file owner in the xib.
MainViewController.m
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
cell.button.tag = indexPath.row;
[cell.button addTarget:self action:#selector(buttonPressed:) forControlEvents:UIControlEventTouchUpInside];
return cell;
}
-(void)buttonPressed:(UIButton*)sender
{
NSLog(#"%d : %#",sender.tag,[array objectAtIndex:sender.tag]);
self.textLabel.text = [array objectAtIndex:sender.tag];
}
Edit- Handle multiple sections
-(void)buttonPressed:(UIButton*)sender
{
NSIndexPath *indexPath = [self.collectionView indexPathForCell: (UICollectionViewCell *)sender.superview.superview];
NSLog(#"Section : %d Row: %d",indexPath.section,indexPath.row);
if (0 == indexPath.section) {
self.textLabel.text = [firstArray objectAtIndex:indexPath.row];
}
else if(1 == indexPath.section)
{
self.textLabel.text = [secondArray objectAtIndex:indexPath.row];
}
}
When I edit the code in the UICollectionViewCell's action, I cannot access the array property.
That's because you connected the button action to the "wrong" object. It needs to be connected to the MainViewController (or whoever it is that does have access to the array property).
You are going to have several tasks to perform:
Receive the button action message.
Access the array (the model for the data).
Throw a switch saying which cell should now have its label showing.
Tell the collection view to reloadData, thus refreshing the cells.
All those tasks should most conveniently belong to one object. I am presuming that this is MainViewController (and thus I am presuming that MainViewController is the delegate/datasource of the collection view).

Resources