I have added a uibutton in my uitableviewcell and trying to change its background image when it is taped here is the code
-(void)downloadImage:(UIButton *)link
{
UITableViewCell *cell = (UITableViewCell*)[link superview];
UIButton *view = [[UIButton alloc]init];
NSArray *subviews = [cell subviews];
for (view in subviews)
{
if([view isKindOfClass:[UIButton class]])
{
view = (UIButton*)subviews;
[view setBackgroundImage:[UIImage imageNamed:#"yellow"] forState:UIControlStateNormal];
}
}
...
but its not working
if i add this line
view = (UIButton*)subviews;
i am getting this error
Thread 1:signal SIGTRAP
and without this line nothing is happening, any idea what is going wrong?
It depends on how you're adding your subview to your UITableViewCell in your:
-(UITableViewCell)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
NSString *cellID = #"cellID";
UITableViewCell *cell = [tableView dequeReusableCellForID:cellID];
if(cell == nil)
{
...
myButton = [[UIButton alloc] initWithFrame....];
[myButton addTarget:self selector:#selector(downloadImage:) forControlEvent:UIControlEventTouchUpInside];
// -------------------------------------------------------
// This is the important part here.
// Usually, we add "myButton" to the cell's contentView
// You will need to match this subview hierarchy
// in your "downloadImage:" method later
// -------------------------------------------------------
[cell.contentView addSubview:myButton];
}
return cell;
}
-(void)downloadImage:(id)sender
{
// -------------------------------------------------------
// Here, "sender" is your original "myButton" being tapped
//
// Then "[sender superview]" would be the parent view of your
// "myButton" subview, in this case the "contentView" of
// your UITableViewCell above.
//
// Finally, "[[sender superview] superview]" would be the
// parent view of the "contentView", i.e. your "cell"
// -------------------------------------------------------
UIButton *button = (UIButton *)sender;
// button now references your "myButton" instance variable in the .h file
[button setBackgroundImage:[UIImage imagenamed:#"filename.png"] forControlState:UIControlStateNormal];
}
Hope that helps.
As for why your app crashes when you do:
view = (UIButton*)subviews;
That is because "subviews" is an NSArray of all the subviews. You're telling iOS to typecast an NSArray * to a UIButton *, which it doesn't know how to do. So you end up causing the app to crash.
In your for loop, you probably want to do something like this instead (although you shouldn't need to if you use my above "downloadImage" method):
for (view in subviews)
{
if([view isKindOfClass:[UIButton class]])
{
// ------------------------------------------------
// When you go for(view in subviews), you're saying
// view = [subviews objectAtIndex:i]
//
// Hence view = (UIButton *)subviews become
// redundant, and not appropriate.
// ------------------------------------------------
//view = (UIButton*)subviews; // <--- comment out/delete this line here
[view setBackgroundImage:[UIImage imageNamed:#"yellow"] forState:UIControlStateNormal];
}
}
Related
I have a UIViewController with a UICollectionView image gallery created inside it programmatically. I want to add a button to the on each uiimage of UICollectionView cell: The code in CMFViewController.h.m file for adding button to imageview is:
-(UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {
CMFGalleryCell *cell = (CMFGalleryCell *)[collectionView dequeueReusableCellWithReuseIdentifier:#"cellIdentifier" forIndexPath:indexPath];
NSString *imageName = [self.dataArray objectAtIndex:indexPath.row];
[cell setImageName:imageName];
// [[cell myButton] addTarget:self action:#selector(myClickEvent:event) forControlEvents:UIControlEventTouchUpInside];
UIButton *button = [UIButton buttonWithType:UIButtonTypeRoundedRect];
button.frame = CGRectMake(80.0, 210.0, 100.0, 20.0);
[button addTarget:self action:#selector(show) forControlEvents:UIControlEventTouchUpInside];
[button setTitle:#"ShowView" forState:UIControlStateNormal];
// NSMutableArray *buttonArray = [NSMutableArray arrayWithCapacity:100];
// for (int i = 0; i < 4; i++) {
// NSUInteger index = arc4random() % 4;
// newButton.frame = CGRectMake( 5, 5, 10, 10); // Whatever position and size you need...
// UIImage *buttonImage = [UIImage imageNamed:[self.dataArray objectAtIndex:indexPath.row]];
//[newButton setBackgroundImage:buttonImage forState:UIControlStateNormal];
// [buttonArray addObject:newButton];
// }
// newButton = buttonArray; // Where myButtons is a NSArray property of your class, to store references to the buttons.
// [newButton addTarget:self action:#selector(loadImages:) forControlEvents:UIControlEventTouchUpInside];
//[newButton addTarget:self action:#selector(updateCell) forControlEvents:UIControlEventTouchUpInside];
[cell updateCell];
return cell;
}
I have tied to get help from codes at following links
adding-a-uibutton-to-a-uicollectionview
UIButton in cell in collection view not receiving touch up inside event
Please give my your suggestion and help me on this issue.
from this link u can download source code in Creating a Paged Photo Gallery With a UICollectionView: their i want to place next and previous buttons on middle lines of each image of the screen
For implementing next and previous buttons, don't added it on each image, better u add it on collection view, what chinttu-maddy-ramani told in his answer is correct, but he is doing in xib file, but programatically u can do it like below,
just add this code
Edit for requirement updating the buttons
in CMFViewController.h file make two button properties
replace by below code
#import <UIKit/UIKit.h>
#interface CMFViewController : UIViewController <UICollectionViewDataSource, UICollectionViewDelegate, UICollectionViewDelegateFlowLayout>
#property (nonatomic, strong) UIButton *nextButton;
#property (nonatomic, strong) UIButton *prevButton;
#end
in CMFViewController.m file
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
[self loadImages];
[self setupCollectionView];
[self addNextAndPreviousButtons];//add a method to add previous and next buttons
}
//hear u are adding previous and next images, but i didn't added the constraints u add it if u want t work in both orientation
- (void)addNextAndPreviousButtons
{
_nextButton = [UIButton buttonWithType:UIButtonTypeSystem];
_nextButton.frame =CGRectMake(self.view.bounds.size.width - 40, self.view.bounds.size.height/2, 50, 30);
[_nextButton setTitle:#"Next" forState:UIControlStateNormal];
[_nextButton addTarget:self action:#selector(nextButtonAction:) forControlEvents:UIControlEventTouchUpInside];
_prevButton = [UIButton buttonWithType:UIButtonTypeSystem];
_prevButton.frame = CGRectMake(self.view.bounds.origin.x, self.view.bounds.size.height/2, 50, 30);
[_prevButton setTitle:#"Prev" forState:UIControlStateNormal];
[_prevButton addTarget:self action:#selector(previousButtonAction:) forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:_nextButton];
[self.view addSubview:_prevButton];
}
//previous button action
- (void)previousButtonAction:(id)sender
{
NSArray *visibleCell = [_collectionView visibleCells];
if(visibleCell)
{
NSIndexPath *path = [_collectionView indexPathForCell:[visibleCell lastObject]];
if(!path.row == 0)
{
NSIndexPath *nextPath = [NSIndexPath indexPathForItem:(path.row - 1) inSection:0];
[_collectionView scrollToItemAtIndexPath:nextPath atScrollPosition:UICollectionViewScrollPositionCenteredHorizontally animated:YES];
}
}
}
//next button action
- (void)nextButtonAction:(id)sender
{
NSArray *visibleCell = [_collectionView visibleCells];
if(visibleCell)
{
NSIndexPath *path = [_collectionView indexPathForCell:[visibleCell lastObject]];
if(path.row < [_dataArray count] - 1)
{
NSIndexPath *nextPath = [NSIndexPath indexPathForItem:(path.row + 1) inSection:0];
[_collectionView scrollToItemAtIndexPath:nextPath atScrollPosition:UICollectionViewScrollPositionCenteredHorizontally animated:YES];
}
}
}
//edited the method addNextAndPreviousButtons please replace it by this edited answer
//for all cases even when u are swiping
//this is to handle buttons either by tapping or navigation through swiping the collection view
- (void)updateButtons:(NSInteger)row
{
//at the beginning
if(row == 0)
{
_prevButton.hidden = YES;
_nextButton.hidden = NO;
return;
}
else if(row == ([_dataArray count] -1))
{
_nextButton.hidden = YES;
_prevButton.hidden = NO;
}
else
{
_nextButton.hidden = NO;
_prevButton.hidden = NO;
}
}
//finally u have to call updateButtons method this method
-(UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
CMFGalleryCell *cell = (CMFGalleryCell *)[collectionView dequeueReusableCellWithReuseIdentifier:#"cellIdentifier" forIndexPath:indexPath];
NSString *imageName = [self.dataArray objectAtIndex:indexPath.row];
[cell setImageName:imageName];
[cell updateCell];
[self updateButtons:indexPath.row]; //update the buttons
return cell;
}
you can add button in you cell to direct drag & drop button in CMFGalleryCell.xib please check attach screenshot. and add button constraint to center horizontally and center vertically with your cell.
for suggestion only if you want next-previous functionality then you can also add button in main xib in CMFViewController.xib as per below screenshot.
I have programmatically created a UITableView and I have also programmatically created UIButtons to be included with every cell / row. I have set these buttons so that if they are tapped, their button image changes. So when the user first sees the table view, the buttons are the color grey, but if the user taps one of the buttons, then that button will turn red. If they tap it again, it will turn back to grey.
I need to make it so that if a button has been pressed, and is currently using the red image, then it will pass it's cell's detailTextLabel property value into an NSMutableArray object.
Here is my code that controls the majority of the UITableView. This is where the cell's textLabels and detalTextLabels are set:
userName = [self.potentiaFriendsInParseFirstNamesArray objectAtIndex:indexPath.row];
NSString *firstNameForTableView = [self.potentiaFriendsInParseFirstNamesArray objectAtIndex:indexPath.row];
NSString *userNameForTableView = [self.potentiaFriendsUsernameArray objectAtIndex:indexPath.row];
UIImage *addUserButtonImage = [UIImage imageNamed:#"SliderThumb-Normal-G"];
UIImage *addUserButtonImageHighlighted = [UIImage imageNamed:#"SliderThumb-Normal"];
UIButton *addUserButton = [[UIButton alloc]init];
addUserButton.frame = CGRectMake(237, -10, 64, 64);
[addUserButton setImage:addUserButtonImage forState:UIControlStateNormal];
[addUserButton setImage:addUserButtonImageHighlighted forState:UIControlStateHighlighted];
[addUserButton setImage:addUserButtonImageHighlighted forState:UIControlStateSelected];
[addUserButton addTarget:self action:#selector(handleTouchUpInside:) forControlEvents:UIControlEventTouchUpInside];
[cell.textLabel setText:firstNameForTableView];
[cell.detailTextLabel setText:userNameForTableView];
[cell.contentView addSubview:addUserButton];
The most important parts of the above code are these statements:
[addUserButton setImage:addUserButtonImage forState:UIControlStateNormal];
[addUserButton setImage:addUserButtonImageHighlighted forState:UIControlStateHighlighted];
[addUserButton setImage:addUserButtonImageHighlighted forState:UIControlStateSelected];
The above control the settings for the different states of the button, and this helps make the button turn to the grey image or the red image when it is pressed.
The below statement is a method call that handles the "touch" events and makes the button change from the grey image to the red image when it is pressed:
[addUserButton addTarget:self action:#selector(handleTouchUpInside:) forControlEvents:UIControlEventTouchUpInside];
And here is the above method's method implementation in my View Controller:
- (void)handleTouchUpInside:(UIButton *)sender {
sender.selected = !sender.selected;
NSLog(#"Has sender state changed?: %u", sender.state);
}
You will notice that I am using NSLog to print out the button's state. The "state" property changes it's value every time one of the button's is pressed. Now I need to figure out a way to make it so that if a specific button's state is changed, we will grab it's cell's "detailTextLabel" property and place it inside an NSMutableArray.
You can use the addUserButton.tag property to keep tableview index row (1), so inside the handleTouchUpInside (2) you can find button row:
1- Set indexPath row inside the cellForRowAtIndexPath function
//Keep indexPath.row on Button.tag
addUserButton.tag = indexPath.row
2- Find button on TableView Rows
- (void)handleTouchUpInside:(UIButton *)sender {
UIButton *cellButton = (UIButton *)sender;
NSIndexPath *indexPath = [NSIndexPath indexPathForRow:cellButton.tag inSection:0];
UITableViewCell *cell = [self.tableView cellForRowAtIndexPath:indexPath];
cell.detailTextLabel.text = #"teste";
}
I hope it works.
Here's the essence of how you'd subclass UITableViewCell to accomplish this (condensed a bit to save space...) First the .h
#import <UIKit/UIKit.h>
#interface SampleCell : UITableViewCell
#property (nonatomic, assign) id delegate;
#end
#protocol FancyProtocolNameGoesHere
- (void)doSomethingWithThisText:(NSString*)text fromThisCell:(UITableViewCell*)cell;
#end
And the .m
#import "SampleCell.h"
#interface SampleCell ()
#property (strong, nonatomic) UIButton *button;
- (void)handleTouchUpInside;
#end
#implementation SampleCell
- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
{
self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
if (self) {
[self configureCell];
}
return self;
}
- (void)configureCell
{
_button = [[UIButton alloc] init];
//Configure all the images etc, for the button
[_button addTarget:self action:#selector(handleTouchUpInside) forControlEvents:UIControlEventTouchUpInside];
[self addSubview:_button]; //you'd probably want to set the frame first...
}
- (void)handleTouchUpInside
{
if (_button.selected) {
[self.delegate doSomethingWithThisText:self.textLabel.text fromThisCell:self];
}
_button.selected = !_button.selected;
}
#end
Register this subclass with the TableView (remember to declare conformity to the protocol), and assign the delegate to self within -(UITableViewCell*)cellForRowAtIndexPath:(NSIndexPath*)indexPath
The final magic comes as you implement - (void)doSomethingWithThisText:(NSString*)text fromThisCell:(UITableViewCell*)cell; because you can call [self indexPathForCell:cell] on the cell parameter you passed in to get the index path you probably need so you know where to insert the text in your NSMutableArray data object.
A subclassed UITableViewCell with a delegate protocol pattern is not the only way to do this, but I think it makes some sense for what you described.
This solutions is safe to table sections.
- (void)onButtonPressed:(UIButton *)sender event:(id)event
{
CGPoint point = [[[event allTouches] anyObject] locationInView:self.tableView];
NSIndexPath *indexPath = [self.tableView indexPathForItemAtPoint:point];
UITableViewCell *cell = [self.tableView cellForRowAtIndexPath:indexPath];
/* use cell here */
}
I have a collection view where each cell contains 7 buttons, (created via code not storyboard).
They are sharp initially, however if I scroll up / down a few times the quality decreases.
The sharpness is restored when I change views and return.
Any ideas ?
Addit:
I am making the buttons like this, within a loop (can be 1 to 7 buttons)
- (UICollectionViewCell*) collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"patientCell";
UICollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:CellIdentifier forIndexPath:indexPath];
Patient *aPt = [self.fetchedResultsController objectAtIndexPath:indexPath];
PatientCVCell *ptCell = (PatientCVCell *) cell;
ptCell.ptName.text = aPt.name;
ptCell.ptRoom.text = aPt.room;
ptCell.ptRx.text = aPt.diagnosis;
int xPos = 20;
NSArray *daysForRx = aPt.ofList.listDays;
// loop through to add button for each day of Rx
for (int i = 0; i < [daysForRx count]; i++) {
// get the treatment day that == postition in array
for (Treatment *t in aPt.patientRx) {
if (t.day == daysForRx[i]) {
//NSLog(#"%i", xPos);
StatusButton *testButton = [StatusButton buttonWithType:UIButtonTypeCustom];
testButton.frame = CGRectMake(xPos, 110, 28, 28);
testButton.btnTreatment = t;
// match status of the RX to the correct button
if ([t.status intValue] == NotSeen) {
[testButton setImage:[UIImage imageNamed:#"toSee"] forState:UIControlStateNormal];
testButton.linkNumber = NotSeen;
}
else if ([t.status intValue] == SeenNotCharted) {
[testButton setImage:[UIImage imageNamed:#"seenNotCharted"] forState:UIControlStateNormal];
testButton.linkNumber = SeenNotCharted;
}
else if ([t.status intValue] == SeenCharted) {
[testButton setImage:[UIImage imageNamed:#"seenCharted"] forState:UIControlStateNormal];
testButton.linkNumber = SeenCharted;
}
else if ([t.status intValue] == NotSeeing) {
[testButton setImage:[UIImage imageNamed:#"notSeeing"] forState:UIControlStateNormal];
testButton.linkNumber = NotSeeing;
}
else if ([t.status intValue] == NotSeeingDC) {
[testButton setImage:[UIImage imageNamed:#"notSeeingDischarged"] forState:UIControlStateNormal];
testButton.linkNumber = NotSeeingDC;
}
[testButton addTarget:self action:#selector(buttonClicked:) forControlEvents:UIControlEventTouchUpInside];
[cell addSubview:testButton];
xPos = xPos + 36;
}
}
}
return cell;
}
The image is correct size so no need to scale the image.
Occurs in simulator and on device.
After looking more closely, the inside of the images are sharp! So this issue has to do with the transparency for my circle shape of a button within a square button!
You are dequeuing a cell, then you add your buttons to the dequeued cell.
Those buttons never get removed. When you scroll up and down cells that go off screen are put on the dequeue queue. At this time they still have the buttons, then they are dequeued and you add more buttons. You have many buttons above each other, and that's why it looks blurry and your memory footprint gets bigger.
I would add the buttons from inside the cell. Save them in a array so you can remove them later. Then I would add a method to set the number of buttons you'll need. Like this:
// header
#property (strong, nonatomic) NSMutableArray *buttons;
// implementation
- (void)setNumberOfButtons:(NSInteger)numberOfButtons withTarget:(id)target selector:(SEL)selector {
// remove existing buttons from view
[self.buttons makeObjectsPerformSelector:#selector(removeFromSuperview)];
// "save" existing buttons in a reuse queue so you don't have to alloc init them again
NSMutableArray *reuseQueue = self.buttons;
self.buttons = [NSMutableArray arrayWithCapacity:numberOfButtons];
for (NSInteger i = 0; i < numberOfButtons; i++) {
UIButton *button = [reuseQueue lastObject];
if (button) {
[reuseQueue removeLastObject];
}
else {
button = [UIButton buttonWithType:UIButtonTypeCustom];
// you should always use the same target and selector for all your cells. otherwise this won't work.
[button addTarget:target action:selector forControlEvents:UIControlEventTouchUpInside];
}
[self.buttons addObject:button];
button.frame = ....
// don't set up images or titles. you'll do this from the collectionView dataSource method
}
}
you would then set the number of buttons in collectionView:cellForItemAtIndexPath: and configure each button according to your needs. something along those lines:
- (UICollectionViewCell*) collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {
Cell *cell = ... dequeue ...
Object *object = ... get from your backend ...
/* configure your cell */
if ([cell.buttons count] != object.numberOfItems) {
// no need to remove and add buttons if the item count stays the same
[cell setNumberOfButtons:object.numberOfItems withTarget:self selector:#selector(buttonPressed:)];
}
for (NSInteger i = 0; i < [object.numberOfItems count]; i++) {
UIButton *button = cell.buttons[i];
[button setImage:... forState:UIControlStateNormal];
}
}
And the action would look like this:
- (IBAction)buttonPressed:(UIButton *)sender {
UICollectionView *collectionView;
CGPoint buttonOriginInCollectionView = [sender convertPoint:CGPointZero toView:collectionView];
NSIndexPath *indexPath = [collectionView indexPathForItemAtPoint:buttonOriginInCollectionView];
NSAssert(indexPath, #"can't calculate indexPath");
Cell *cell = [collectionView cellForItemAtIndexPath:indexPath];
if (cell) {
NSInteger pressedButtonIndex = [cell.buttons indexOfObject:sender];
if (pressedButtonIndex != NSNotFound) {
// do something
}
}
else {
// cell is offscreen?! why?
}
}
pretty straight forward. Get the indexPath, get the collectionViewCell, check which index the pressed button has
I'm trying to to something like apple's alarm clock, when tap the edit button, a custom view cover the custom UITableViewCell.
The code above:
// CGRect frame = [tableView rectForRowAtIndexPath:indexPath];
// CGPoint yOffset = self.tableViewBlock.contentOffset;
// CGRect newFrame = CGRectMake(frame.origin.x, (frame.origin.y - yOffset.y + 45), frame.size.width, frame.size.height);
CallBlock_Date_EditMode *viewController = [[CallBlock_Date_EditMode alloc] initWithNibName:#"CallBlock_Date_EditMode" bundle:nil];
// self.view.frame = newFrame;
// [self.view addSubview:viewController.view];
// [self addChildViewController:viewController];
UITableViewCell *cell = (UITableViewCell*)[self.tableViewBlock cellForRowAtIndexPath:indexPath];
[cell.contentView addSubview:viewController.view];
Cover the specific cell when I put in under:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
Just to make sure the size is ok (although when I tap a button in that xib the app crash without even a single error).
But I want to do like apple's alarm clock (actually, mimic it), tap my edit button and my custom UITableViewCell will get cover with this xib as a view.
Maybe there is a better approach to do it?
EDIT:
My updated code is:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
CallBlock_TableCell *cell = (CallBlock_TableCell*)[tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
if (cell == nil)
{
cell = [[CallBlock_TableCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
// Configure the cell...
[self configureCell:cell atIndexPath:indexPath];
return cell;
}
- (void)configureCell:(CallBlock_TableCell *)cell atIndexPath:(NSIndexPath *)indexPath
{
cell.accessoryType = self.isEditing ? UITableViewCellAccessoryDisclosureIndicator : UITableViewCellAccessoryNone;
CallBlock_ByDate *callBlock = (CallBlock_ByDate*)[fetchedObjects objectAtIndex:indexPath.row];
cell.labelTime.text = callBlock.startDate;
cell.labelRepeat.text = callBlock.repeat;
cell.labelTextLabel.text = callBlock.label;
cell.switchCallBlock.on = YES;
cell.switchCallBlock.tag = (NSInteger)indexPath.row +1;
[cell.switchCallBlock addTarget:self action:#selector(handleSwitch:) forControlEvents:UIControlEventValueChanged];
cell.switchCallBlock.hidden = self.isEditing ? YES : NO;
if (self.isEditing)
{
cell.switchCallBlock.hidden = YES;
UIButton *btnArrow = [[UIButton alloc] init];
btnArrow.frame = CGRectMake(282.0, 31.0, 18.0, 21.0);
[btnArrow setBackgroundImage:[UIImage imageNamed:#"arrow_FWR_off"] forState:UIControlStateNormal];
[btnArrow setBackgroundImage:[UIImage imageNamed:#"arrow_FWR_on"] forState:UIControlStateHighlighted];
btnArrow = [UIButton buttonWithType:UIButtonTypeCustom];
[btnArrow addTarget:self action:#selector(handleTapToEdit:) forControlEvents:UIControlEventTouchUpInside];
btnArrow.tag = indexPath.row + 1;
[cell.contentView addSubview:btnArrow];
[cell.contentView bringSubviewToFront:btnArrow];
}
}
But I cannot get the btnArrow appear on the UTableView.
The reason you are getting a crash is because nothing is retaining your CallBlock_Date_EditMode view controller. You add its view to your cell as a subview, but nothing maintains a reference to the view controller, so it is deallocated and then, when pressing a button that is supposed to pass a message to your view controller, it is sent to a deallocated object and you get a crash.
There are two possible solutions to this. First, you could store that view controller in one of your properties to maintain a reference to it so that it does not deallocated. This is, for the most part, probably not what you want.
Instead, what I would suggest doing is do not make your CallBlock_Date_EditMode a UIViewController, but instead make it a UIView. You may be wondering "But how can I use a xib without a UIViewController?". I would do something like the following:
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self)
{
UIView *view = [[[NSBundle mainBundle] loadNibNamed:#"CallBlock_Date_EditMode" owner:self options:nil] objectAtIndex:0];
self.myEditButton = (UIButton *)[view viewWithTag:2];
[self addSubview:view];
}
return self;
}
This would be code inside your custom UIView that would load in a xib file and add it as a subview. In order to get access to your subviews, you have to use tags inside interface builder, so you do lose the convenience of drawing/connecting IBOutlets... But in the end, it is much better than allocating/storing a bunch of unnecessary UIViewControllers.
If I understand you right and you want to mimic the functionality of the alarm clock that comes pre-installed from Apple, your solution is much simpler than creating a custom view. It looks like all they do is set the On-Off switches to hidden and add a disclosure indicator to the cell. This is what I would do...
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
bool hide = (tableView.editingStyle == UITableViewCellEditingStyleDelete); // set to true or false depending on if the table is in editing mode
for (UIView *sv in [cell subviews] ) {
if([sv isKindOfClass:[UISwitch class]]) { // find the on-off switch
[sv setHidden:hide]; // hide the switch depending on the t/f value of hide
break;
}
}
if(hide) { // adds the arrow like in apple's alarm clock table if the cell is in edit mode
[cell setAccessoryType:UITableViewCellAccessoryDisclosureIndicator];
}
else {
[cell setAccessoryType:UITableViewCellAccessoryNone];
}
return cell;
}
I am showing a image in CellImage when any cell is clicked it works fine but problem is that when a new cell is selected then previous cell image is also visible i want that when user selects on new cell previous cellImage should be hidden.
here is the code
-(IBAction)imageButtonAction:(id)sender{
CustomCell *cell = (CustomCell *) [[sender superview] superview];
UIButton *btn = (UIButton *)sender;
UIView *backimage = [[UIView alloc] initWithFrame:CGRectMake(300,0,312,105)];
backimage.backgroundColor=[UIColor colorWithPatternImage:[UIImage imageNamed:#"popupj.png"]];
[backimage setUserInteractionEnabled:YES];
[cell addSubview:backimage];
}
I am calling this method on the button which is in cell i have used custom cell
You might try this, it may help you.
-(IBAction)imageButtonAction:(id)sender{
CustomCell *cell = (CustomCell *) [[sender superview] superview];
UIButton *btn = (UIButton *)sender;
for (UIView *subView in cell.contentView.subviews) {
if([subView isKindOfClass:[UIView class]]){
subView.hidden=YES;
}
}
UIView *backimage = [[UIView alloc] initWithFrame:CGRectMake(300,0,312,105)];
backimage.backgroundColor=[UIColor colorWithPatternImage:[UIImage imageNamed:#"popupj.png"]];
[backimage setUserInteractionEnabled:YES];
[cell addSubview:backimage];
}
Or you can even use the block, to loop through subviews and hide them
Cheers
There is a value on a table view xib called selection, check that its value is set to single selection in your xib. Or programmatically set this property to NO:
#property(nonatomic) BOOL allowsMultipleSelection
Change the hidden value property of your previous selected cell in tableView:didSelectRowAtIndexPath:
Access the cell by using:
UITableViewCell *cell = (UITableViewCell *)[tableView cellForRowAtIndexPath:previousIndex];
cell.yourImage.hidden = YES;
In your button action you could set maintain the previousIndexPath which should be declared in the .h file . By using this previousIndexPath you can easily hide the previously loaded image:
CustomCell *cell=(CustomCell *)[yourTable cellForRowAtIndexPath:previousIndexPath];
cell.yourImage.hidden=TRUE;