Calling delegate method UICollectionViewCell - ios

I'm having trouble calling a delegate method that resides in my UICollectionViewCell...
In my FOFPhotoCell.m i have the following code:
-(void)fadeOutLabels
{
NSLog(#"fadeOutLabels was called");
[UIView animateWithDuration:1.0
delay:0.0 /* do not add a delay because we will use performSelector. */
options:UIViewAnimationOptionCurveEaseIn
animations:^ {
self.titleLabel.alpha = 0.0;
}
completion:^(BOOL finished) {
[self.titleLabel removeFromSuperview];
}];
}
in the FOFPhotoCell.h there is the following defined:
#protocol FOFPhotoCellDelegate <NSObject>
#required
-(void)fadeOutLabels;
#end
#interface FOFPhotoCell : UICollectionViewCell {
id delegate;
}
#property (nonatomic, weak) id<FOFPhotoCellDelegate> delegate;
in my FOFPhotosViewController.h:
#interface FOFPhotosViewController : UICollectionViewController <FOFPhotoCellDelegate>
#end
and lastly, my FOFPhotosViewController.m:
-(UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {
FOFPhotoCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:#"photo" forIndexPath:indexPath];
NSArray *photosArray = [self.dishes valueForKeyPath:#"avatar_url"];
NSArray *nameArray = [self.dishes valueForKeyPath:#"name"];
// NSLog(#"photoURL %#", _responseDictionary);
cell.backgroundColor = [UIColor lightGrayColor];
[cell.imageView setImageWithURL:[NSURL URLWithString:[NSString stringWithFormat:#"****",[photosArray objectAtIndex: indexPath.row]]]];
cell.titleLabel.text = [NSString stringWithFormat:#"%#", [nameArray objectAtIndex:indexPath.row]];
UILongPressGestureRecognizer *tapAndHold = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:#selector(fadeOutLabels)];
tapAndHold.minimumPressDuration = 0.5;
[self.collectionView addGestureRecognizer:tapAndHold];
[self.collectionView reloadItemsAtIndexPaths:[NSArray arrayWithObject:indexPath]];
return cell;
}
But this makes the app crash: -[FOFPhotosViewController fadeOutLabels]: unrecognized selector sent to instance
I can't seem to figure this one out, so I would really appreciate some help! Let me know if any more code is needed.
Thanks in advance
Chris

fadeOutLables is a method of your cell, not of your view controller.
The error message is just right.
Assuming that everything else is right, change this line as follows:
UILongPressGestureRecognizer *tapAndHold = [[UILongPressGestureRecognizer alloc] initWithTarget:cell action:#selector(fadeOutLabels)];

Related

TableviewCells are not inserted as expected

I have a reusableTablViewCell that will be simply echoed to the tableview whenever a user gives an input in the textbook and clicks send button, my problem is that the cells are not behaving as expected few times the cells are inserted correctly and few times they won't.
Expected Behaviour: when the user clicks send button after he has finished typing some text in the text box the same value should be printed twice (like sending and receiving the same text).
//view somewhat looks like this on expected behaviour
'''''''''
' hi '
'''''''''
'''''''''
' hi '
'''''''''
Current Behaviour: Sometimes it does give me the expected behaviour, but some times both the cells are on the same side
EX:
//view when it doesn't work as expected
'''''''
' hi '
'''''''
'''''''
' hi '
'''''''
or something like
''''''''
' hi '
''''''''
''''''''
' hi '
''''''''
And sometimes when we scroll, the cells change their position(being odd Cell and Even-cell which u can see in the code) from sender to receiver and vice-versa.
My code
//FirstTableViewController.h
#import <UIKit/UIKit.h>
#class SecondViewController;
#interface FirstTableViewController : UITableViewController
#property (strong, nonatomic) IBOutlet UITableView *messageView;
#property (nonatomic,readwrite) NSInteger counter;
#property (nonatomic,readwrite) NSMutableArray *userInput;
#property (nonatomic,readwrite) NSMutableDictionary *heightAtIndexPath;
#property (nonatomic, assign) BOOL shouldScrollToLastRow;
+ (id)sharedInstance;
#end
#interface ChatMessageCellTableViewCell : UITableViewCell
#property (nonatomic, retain) UILabel *formLabel;
#property (nonatomic, retain) UIView *bubbleBackView;
#end
//FirstTableViewController.m
#import "FirstTableViewController.h"
BOOL isReceived;
#interface ChatMessageCellTableViewCell (){
NSLayoutConstraint *leadingConstraint;
NSLayoutConstraint *trailingConstraint;
}
#end
#implementation ChatMessageCellTableViewCell
-(void) loaded{
if(isReceived){
[self.bubbleBackView setBackgroundColor:[UIColor whiteColor]];
[self.formLabel setTextColor:[UIColor blackColor]];
}
else{
[[self bubbleBackView] setBackgroundColor:[UIColor colorWithRed:(66/255) green:(137/255.0) blue:1 alpha:1.0]];
[self.formLabel setTextColor:[UIColor whiteColor]];
}
}
-(id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier{
[self setBackgroundColor:[UIColor clearColor]];
self.formLabel = [UILabel new];
self.bubbleBackView = [UIView new];
//[self.bubbleBackView setBackgroundColor:[UIColor yellowColor]];
[self.bubbleBackView.layer setCornerRadius:12];
self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
if(self){
[[self contentView] addSubview:self.bubbleBackView
];
[self loaded];
[self.bubbleBackView setTranslatesAutoresizingMaskIntoConstraints:NO];
[[self contentView] addSubview:self.formLabel];
[self.formLabel setTranslatesAutoresizingMaskIntoConstraints:NO];
if (#available(iOS 9.0, *)) {
[self.formLabel.topAnchor constraintEqualToAnchor:self.topAnchor constant:32].active=YES;
[self.formLabel.bottomAnchor constraintEqualToAnchor:self.bottomAnchor constant:-32].active=YES;
[self.formLabel.widthAnchor constraintLessThanOrEqualToConstant:250].active=YES;
[self.bubbleBackView.topAnchor constraintEqualToAnchor:_formLabel.topAnchor constant:-16].active=YES;
[self.bubbleBackView.bottomAnchor constraintEqualToAnchor:_formLabel.bottomAnchor constant:16].active=YES;
[self.bubbleBackView.trailingAnchor constraintEqualToAnchor:_formLabel.trailingAnchor constant:16].active=YES;
[self.bubbleBackView.leadingAnchor constraintEqualToAnchor:_formLabel.leadingAnchor constant:-16].active=YES;
leadingConstraint= [self.formLabel.leadingAnchor constraintEqualToAnchor:self.leadingAnchor constant:32];
trailingConstraint = [self.formLabel.trailingAnchor constraintEqualToAnchor:self.trailingAnchor constant:-32];
if(isReceived){
[leadingConstraint setActive:YES];
[trailingConstraint setActive:NO];
}
else{
[leadingConstraint setActive:NO];
[trailingConstraint setActive:YES];
}
} else {
// Fallback on earlier versions
}
[self.formLabel setLineBreakMode:NSLineBreakByWordWrapping];
[self.formLabel setNumberOfLines:0];
[self.formLabel sizeToFit];
[self.contentView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:#"V:|-40-[bodyLabel]-40-|" options:0
metrics:nil
views:#{ #"bodyLabel":self.formLabel}]];
}
return self;
}
#end
#interface FirstTableViewController ()
{
NSArray *messages;
FirstTableViewController *classA;
}
#end
#implementation FirstTableViewController
+(id)sharedInstance
{
static FirstTableViewController *sharedClassA = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
sharedClassA = [[self alloc] init];
});
return sharedClassA;
}
- (void)viewDidLoad {
[super viewDidLoad];
self.heightAtIndexPath = [NSMutableDictionary new];
self.userInput = [[NSMutableArray alloc] init];
[self.tableView registerClass:[ChatMessageCellTableViewCell class] forCellReuseIdentifier:#"id"];
[[self tableView] setSeparatorStyle:UITableViewCellSeparatorStyleNone];
[self.tableView setBackgroundColor:[UIColor colorWithWhite:0.95 alpha:1]];
[[self navigationController] setTitle:#"Meetings"];
classA = [FirstTableViewController sharedInstance];
[classA setCounter:(classA.userInput.count)];
[classA setMessageView:(self.messageView)];
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
classA.counter=classA.userInput.count;
return classA.counter;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
NSString *cellIdentifier = (indexPath.row % 2 == 0 ? #"EvenCell" : #"OddCell"); //just to differentiate the sending and receiving cell.
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];
ChatMessageCellTableViewCell *messageCell = (ChatMessageCellTableViewCell*) cell;
if (messageCell == nil) {
messageCell = [[ChatMessageCellTableViewCell alloc] initWithStyle: UITableViewCellStyleDefault
reuseIdentifier:cellIdentifier];
}
if(indexPath.row % 2 == 0) // simple logic to differentiate and apply my constraints to the sending and receiving cells.
{
isReceived =TRUE;
}
else{
isReceived = FALSE;
}
[[messageCell formLabel]setText:classA.userInput[indexPath.row]];
[messageCell setSelectionStyle:UITableViewCellSelectionStyleNone];
[[self tableView] setEstimatedRowHeight:50.0];
[self.tableView setRowHeight:UITableViewAutomaticDimension];
return messageCell;
}
-(void)viewWillLayoutSubviews{
if(classA.shouldScrollToLastRow){
[classA setShouldScrollToLastRow:NO];
dispatch_async(dispatch_get_main_queue(),^{
NSIndexPath *path = [NSIndexPath indexPathForRow:(self->classA.counter)-1 inSection:0];
//Basically maintain your logic to get the indexpath
[self->classA.messageView scrollToRowAtIndexPath:path atScrollPosition:UITableViewScrollPositionBottom animated:NO];
});
}
}
-(void)viewDidAppear:(BOOL)animated{
[super viewDidAppear:animated];
}
-(void)dealloc{
NSLog(#"Dealloc!!!");
}
#end
//SecondViewController.m
//sendButtonClicked is the function from where the data is passed to the FirstViewController's tableview cell.
-(IBAction)sendButtonClicked{
NSString *input = self.ChatTextInput.text;
if([input isEqualToString:#""]){
NSLog(#"this is a nil ");
}
else{
[inputValues addObject:input];
[inputValues addObject:input];
[classA setUserInput:inputValues];
[classA setCounter:inputValues.count];
[self.ChatTextInput setText:nil];
[classA setShouldScrollToLastRow:YES];
[classA.messageView reloadData];
}
}
This is basically a chat view which I'm actually trying to achieve everything is good except this abnormal behaviour.
I hope anyone can take some time and correct me where am I wrong.
UPDATE: Any one who is looking for basic chatView in objective-C can use the code above as an reference, use the code above and correct the mentioned things in the accepted answer.
This is a typical cell reuse issue. In iOS all collections (UITableView/UICollectionView) reuses the cell and cells initWithStyle gets called only once the cell is initialised. Once tableView has enough cells with it, it will reuse the cell so initWithStyle will not get called all the time. Hence few of your cells (preferably initial ones) seems all right. As you set its constraints properly in init and for other cells which are not shown properly init was never called so your constraints were never updated. Hence shows wrong bubble.
Whats the solution?:
1. Use PrepareforReuse
every cell when it gets reused, iOS calls prepareForReuse on the cell to give developer a last chance to do all clean up
-(void) prepareForReuse {
[super prepareForReuse];
[self.formLabel setText: nil];
//set default background color or change bubble view
// do whatever clean up you wanna do here
}
2. Modify your cells method and ensure you update your constraints every time cell is shown and not just in init
lets say you add a method called:
-(void)configureView:(BOOL) isRecieved {
isReceived = isRecieved;
if(isReceived){
[leadingConstraint setActive:YES];
[trailingConstraint setActive:NO];
}
else{
[leadingConstraint setActive:NO];
[trailingConstraint setActive:YES];
}
//[self layoutIfNeeded]; might be needed here
[self loaded];
}
In your init remove code to set constraint based on isRecieved Value
-(id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier{
[self setBackgroundColor:[UIColor clearColor]];
self.formLabel = [UILabel new];
self.bubbleBackView = [UIView new];
//[self.bubbleBackView setBackgroundColor:[UIColor yellowColor]];
[self.bubbleBackView.layer setCornerRadius:12];
self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
if(self){
[[self contentView] addSubview:self.bubbleBackView
];
[self loaded];
[self.bubbleBackView setTranslatesAutoresizingMaskIntoConstraints:NO];
[[self contentView] addSubview:self.formLabel];
[self.formLabel setTranslatesAutoresizingMaskIntoConstraints:NO];
if (#available(iOS 9.0, *)) {
[self.formLabel.topAnchor constraintEqualToAnchor:self.topAnchor constant:32].active=YES;
[self.formLabel.bottomAnchor constraintEqualToAnchor:self.bottomAnchor constant:-32].active=YES;
[self.formLabel.widthAnchor constraintLessThanOrEqualToConstant:250].active=YES;
[self.bubbleBackView.topAnchor constraintEqualToAnchor:_formLabel.topAnchor constant:-16].active=YES;
[self.bubbleBackView.bottomAnchor constraintEqualToAnchor:_formLabel.bottomAnchor constant:16].active=YES;
[self.bubbleBackView.trailingAnchor constraintEqualToAnchor:_formLabel.trailingAnchor constant:16].active=YES;
[self.bubbleBackView.leadingAnchor constraintEqualToAnchor:_formLabel.leadingAnchor constant:-16].active=YES;
leadingConstraint= [self.formLabel.leadingAnchor constraintEqualToAnchor:self.leadingAnchor constant:32];
trailingConstraint = [self.formLabel.trailingAnchor constraintEqualToAnchor:self.trailingAnchor constant:-32];
} else {
// Fallback on earlier versions
}
[self.formLabel setLineBreakMode:NSLineBreakByWordWrapping];
[self.formLabel setNumberOfLines:0];
[self.formLabel sizeToFit];
[self.contentView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:#"V:|-40-[bodyLabel]-40-|" options:0
metrics:nil
views:#{ #"bodyLabel":self.formLabel}]];
}
return self;
}
Finally in cellForRowAtIndexPath call configureView with isReceived value
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
NSString *cellIdentifier = (indexPath.row % 2 == 0 ? #"EvenCell" : #"OddCell"); //just to differentiate the sending and receiving cell.
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];
ChatMessageCellTableViewCell *messageCell = (ChatMessageCellTableViewCell*) cell;
if (messageCell == nil) {
messageCell = [[ChatMessageCellTableViewCell alloc] initWithStyle: UITableViewCellStyleDefault
reuseIdentifier:cellIdentifier];
}
if(indexPath.row % 2 == 0) // simple logic to differentiate and apply my constraints to the sending and receiving cells.
{
isReceived =TRUE;
}
else{
isReceived = FALSE;
}
[messageCell configureView: isReceived];
[[messageCell formLabel]setText:classA.userInput[indexPath.row]];
[messageCell setSelectionStyle:UITableViewCellSelectionStyleNone];
[[self tableView] setEstimatedRowHeight:50.0];
[self.tableView setRowHeight:UITableViewAutomaticDimension];
return messageCell;
}
Hope it helps

Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'UICollectionView must be initialized with a non-nil layout parameter

I have the same code in three pages, but in two of them, this error occurs:
Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'UICollectionView must be initialised with a non-nil layout parameter
I don't understand why, if the code is the same in three pages and in the first page i don't have any problem.
My Code in header file
#import <UIKit/UIKit.h>
#interface CollectionViewController : UICollectionViewController<UICollectionViewDataSource>
#property (nonatomic,strong) NSMutableArray *marrImages;
#property (nonatomic,strong) NSMutableDictionary *mdictImageData;
#end
and in .m file
#interface CollectionViewController ()
#end
#implementation CollectionViewController
#synthesize marrImages,mdictImageData;
static NSString * const reuseIdentifier = #"cell";
- (void)viewDidLoad {
[super viewDidLoad];
//navigation bar
UIImage *image = [UIImage imageNamed:#"home.png"];
UIButton *backButton = [UIButton buttonWithType:UIButtonTypeCustom];
backButton.frame = CGRectMake(0, 0, 50, 50);
[backButton setImage:image forState:UIControlStateNormal];
// [backButton addTarget:self action:#selector(leftButtonAcion:) forControlEvents:UIControlEventTouchUpInside];
UIBarButtonItem *button2 = [[UIBarButtonItem alloc] initWithCustomView:backButton];
self.navigationItem.leftBarButtonItem = button2;
self.title = #"Welcome";
marrImages=[[NSMutableArray alloc]init];
mdictImageData=[[NSMutableDictionary alloc]initWithObjectsAndKeys:#"circlshadow_parking.png",#"imageFile",#"Estacionamentos",#"Info",nil];
[marrImages addObject:mdictImageData];
mdictImageData=[[NSMutableDictionary alloc]initWithObjectsAndKeys:#"circlshadow_charging.png",#"imageFile",#"Carregar Saldo",#"Info", nil];
[marrImages addObject:mdictImageData];
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
}
#pragma mark <UICollectionViewDataSource>
- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section {
return [marrImages count];
}
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
CustomCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:reuseIdentifier forIndexPath:indexPath];
cell.lblIndex.text=[[marrImages objectAtIndex:[indexPath row]]valueForKey:#"Info"];
UIImage *image=[UIImage imageNamed:[[marrImages objectAtIndex:[indexPath row]]valueForKey:#"imageFile"]];
[cell.ivCartoon setImage:image];
return cell;
}
- (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath
{
NSUInteger lastIndex = [indexPath indexAtPosition:[indexPath length] - 1];
if(lastIndex == 0)
{
ParkingMenu *parkingMenu = [[ParkingMenu alloc] init];
parkingMenu.modalPresentationStyle = UIModalPresentationPageSheet;
parkingMenu.modalTransitionStyle = UIModalTransitionStyleCrossDissolve;
[self.navigationController pushViewController:parkingMenu animated:YES];
[parkingMenu release];
}
else if(lastIndex == 1)
{
BalanceMenu *balanceMenu = [[BalanceMenu alloc] init];
balanceMenu.modalPresentationStyle = UIModalPresentationPageSheet;
balanceMenu.modalTransitionStyle = UIModalTransitionStyleCrossDissolve;
[self.navigationController pushViewController:balanceMenu animated:YES];
[balanceMenu release];
}
else if(lastIndex == 2)
{
}
else if(lastIndex == 3)
{
}
}
#end
This code:
ParkingMenu *parkingMenu = [[ParkingMenu alloc] init];
parkingMenu.modalPresentationStyle = UIModalPresentationPageSheet;
parkingMenu.modalTransitionStyle = UIModalTransitionStyleCrossDissolve;
[self.navigationController pushViewController:parkingMenu animated:YES];
[parkingMenu release];
shows that you're creating an instance of ParkingMenu without referencing the storyboard. Presumably this is a subclass of UICollectionViewController and is resulting in you not using the designated initialiser initWithCollectionViewLayout: or unarchiving from the storyboard (which would also set the layout).
You're also not using ARC, so you have to call release, which you shouldn't do really...
You need to update your code so it triggers a segue between the view controllers or so it loads the ParkingMenu from the storyboard by identifier.

-didSelectRowAtIndexPath: not being called in UITableView

When I click the UITableViewCell , It have selection effect (grey background in clicked cell),But didSelectRowAtIndexPath is not calling ,what happen?
EDIT
this is my code
tableView.h file
#interface PopCardView : MMPopupView <UITableViewDataSource, UITableViewDelegate>
#end
tableView.m file
#property (nonatomic, strong) NSMutableArray *tagsArray;
#property (nonatomic, strong) UIView *backView;
#property (nonatomic, strong) UITableView *tableView;
#property (nonatomic, assign) NSUInteger lastIndex;
#end
-(id)initWithTags:(NSMutableArray *)tags{
self = [super init];
if (self) {
self.backView = [[UIView alloc] init];
self.backView.backgroundColor = [UIColor whiteColor];
self.backView.layer.cornerRadius = 5;
self.backView.layer.masksToBounds = YES;
[self addSubview:self.backView];
[self.backView mas_makeConstraints:^(MASConstraintMaker *make) {
make.left.top.bottom.right.equalTo(self);
}];
_tableView = [[UITableView alloc]initWithFrame:CGRectMake(0, 0, 324, 300) style:UITableViewStylePlain];
_tableView.tableFooterView =[[UIView alloc] init];
[self.backView addSubview:_tableView];
[_tableView mas_makeConstraints:^(MASConstraintMaker *make) {
make.left.top.right.bottom.equalTo(self.backView).insets(UIEdgeInsetsMake(45,0, 45, 15));
make.size.mas_equalTo(CGSizeMake(324, 200));
}];
[_tableView registerClass:[PopCardTagViewCell class] forCellReuseIdentifier:#"cell"];
_tableView.allowsSelection = YES;
_tableView.allowsSelectionDuringEditing = YES;
[_tableView setUserInteractionEnabled:YES];
_tableView.dataSource = self;
_tableView.delegate = self;
}
return self;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
[_tagsArray enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
PopCardData *data = (PopCardData *)obj;
data.selected = #"0";
if (idx == indexPath.row) {
data.selected = #"1";
}
}];
dispatch_async(dispatch_get_main_queue(), ^{
[self.tableView reloadData];
});
}
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *identifer = #"cell";
PopCardTagViewCell *cell = [self.tableView dequeueReusableCellWithIdentifier:identifer];
if (!cell) {
cell = [[PopCardTagViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:identifer];
}
[self configureCell:cell forIndexPath:indexPath];
return cell;
}
-(void)configureCell:(PopCardTagViewCell *)cell forIndexPath:(NSIndexPath *)indexPath {
PopCardData *data = (PopCardData *)[_tagsArray objectAtIndex:indexPath.row];
//configure cell
[cell setUserInteractionEnabled:YES];
}
-(NSInteger)numberOfSectionsInTableView:(UITableView *)tableView{
return 1;
}
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
return _tagsArray.count;
}
EDIT2
this is my initialize code of PopCardView,it use swift
let pop = PopCardView(tags: self.m_model.getItmes())
pop.show()
The code you show does not set any delegate to the table view. Either this is the reason or you posted an incomplete code snippet.
self.tableView.delegate = self;
and add UITableViewDelegate to your interface like
#interface ClassName ()<UITableViewDelegate>
Make sure you don't have anything in the cell that can swallow the touch event. Things like buttons and textfields can cause this. Strip everything from your cell, test to see if it works, then add things back in slowly to find the culprit.

Delegate method is being called but doesn't execute properly

I'm having a problem with one of my delegate methods. I have a collectionViewController to which I have added a UILongPressGestureRecognizer, which is calling a delegate method fadeOutLabels in my UICollectionViewCell. I can confirm the delegate method being called by a NSLog statement NSLog(#"fadeOutLabels was called");. But the other code inside that function isn't being executed. I'm quite sure I'm missing something completely obvious, but I can't seem to figure it out myself. Code as follows:
FOFPhotoCell.h
#protocol FOFPhotoCellDelegate <NSObject>
#required
-(void)fadeOutLabels;
#end
#interface FOFPhotoCell : UICollectionViewCell {
id delegate;
}
#property (nonatomic, weak) id<FOFPhotoCellDelegate> delegate;
#property (nonatomic) UIImageView *imageView;
#property (nonatomic) NSDictionary *photo;
#property (nonatomic) NSArray *fetchPhotos;
#property (nonatomic) UILabel *titleLabel;
#end
FOFPhotoCell.m
#implementation FOFPhotoCell
#synthesize delegate = _delegate;
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
CGFloat widthFromBounds = self.contentView.bounds.size.width;
self.imageView = [[UIImageView alloc] init];
[self.contentView insertSubview:self.imageView atIndex:0];
UILabel *titleLabel = [[UILabel alloc] initWithFrame:CGRectMake(0, 30, widthFromBounds, 60)];
self.titleLabel = titleLabel;
self.titleLabel.backgroundColor = [UIColor colorWithRed:0.0 green:0.0 blue:0.0 alpha:0.3];
self.titleLabel.font = [UIFont preferredFontForTextStyle:UIFontTextStyleHeadline];
self.titleLabel.textColor = [UIColor whiteColor];
self.titleLabel.textAlignment = NSTextAlignmentCenter;
[self.contentView insertSubview:self.titleLabel atIndex:1];
}
return self;
}
-(void)fadeOutLabels
{
NSLog(#"fadeOutLabels was called");
[UIView animateWithDuration:1.0
delay:0.0 /* do not add a delay because we will use performSelector. */
options:UIViewAnimationOptionCurveEaseIn
animations:^ {
self.titleLabel.alpha = 0.0;
}
completion:^(BOOL finished) {
[self.titleLabel removeFromSuperview];
}];
}
FOFPhotosViewController.h
#import <UIKit/UIKit.h>
#import "FOFPhotoCell.h"
#interface FOFPhotosViewController : UICollectionViewController <FOFPhotoCellDelegate>
#end
FOFPhotosViewController.m
-(UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {
FOFPhotoCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:#"photo" forIndexPath:indexPath];
NSArray *photosArray = [self.dishes valueForKeyPath:#"avatar_url"];
NSArray *nameArray = [self.dishes valueForKeyPath:#"name"];
// NSLog(#"photoURL %#", _responseDictionary);
cell.backgroundColor = [UIColor lightGrayColor];
[cell.imageView setImageWithURL:[NSURL URLWithString:[NSString stringWithFormat:#"http://xx.yy.zz.qq:4000%#",[photosArray objectAtIndex: indexPath.row]]]];
cell.titleLabel.text = [NSString stringWithFormat:#"%#", [nameArray objectAtIndex:indexPath.row]];
UILongPressGestureRecognizer *tapAndHold = [[UILongPressGestureRecognizer alloc] initWithTarget:cell action:#selector(fadeOutLabels)];
tapAndHold.minimumPressDuration = 0.5;
[self.collectionView addGestureRecognizer:tapAndHold];
[self.collectionView reloadItemsAtIndexPaths:[NSArray arrayWithObject:indexPath]];
return cell;
}
I would really appreciate if some one could help me with this issue.
Thanks in advance
Chris
I believe your problem comes from the LongPressGestureRecognizer that should be instantiated in your custom cell and not in your view controller.
Basically, if you have a hundred cell how the long press gesture recognizer is supposed to know which cell you have pressed and which label to fade out.
You can try this instead, in your custom cell :
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
UILongPressGestureRecognizer *tapAndHold = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:#selector(fadeOutLabels)];
tapAndHold.minimumPressDuration = 0.5;
[self addGestureRecognizer:tapAndHold];
....
}
}
And of course remove those lines in the view controller.

UITableView content not displayed the very first time even after reloadData

I am trying to create an account page where user will be able to select his preferable language and voice. For this part of my app I was thinking to create 2 different UIButtons and once user has press one of them, a UITableView will appear on appropriate location tableFrame (something like drop down menu). Things were working great, initially, when I had just one array. Now, I have a general array that used from Table View delegate methods to load data and 2 other arrays that contain languages and voices.
My problem is that the very first time when I am tapping on any of the buttons, the table displays no content but numberOfRowsInSection returns correct value. Next, if tap on the same or the other button again .. everything is fine.
I believe the problem appears where I am, initially, initialise the general array with no object in viewDidLoad.
I have tried reloadData with now success.
Any ideas? Below my code:
Account.h
#import <Foundation/Foundation.h>
#interface AccountViewController : UIViewController <UITableViewDelegate, UITableViewDataSource>{
NSMutableArray *content;
NSMutableArray *languages;
NSMutableArray *voices;
CGRect tableFrame;
}
#property (strong, nonatomic) IBOutlet UIButton *languageBtn;
#property (strong, nonatomic) IBOutlet UIButton *narratorBtn;
#property (strong, nonatomic) IBOutlet UITableView *contentTbl;
- (IBAction)selectLanguage:(id)sender;
- (IBAction)selectVoice:(id)sender;
#end
Account.m
- (void) viewDidLoad{
[super viewDidLoad];
content = [[NSMutableArray alloc] init];
languages = [[NSMutableArray alloc] initWithObjects:#"English", #"Ελληνικά", #"French", #"Spanish", #"Deutch", nil];
voices = [[NSMutableArray alloc] initWithObjects:#"English", #"US English", #"Ελληνικά", #"Spanish", nil];
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return [content count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
cell.textLabel.text = [content objectAtIndex:indexPath.row];
return cell;
}
- (IBAction)selectLanguage:(id)sender{
if ([(UIButton *)sender tag] == 0) {
content = [languages copy];
tableFrame = CGRectMake(50, 173, 220, 203);
[self startAnimationAndDisplayTable:YES];
[(UIButton *)sender setTag:1];
} else{
[self startAnimationAndDisplayTable:NO];
[(UIButton *)sender setTag:0];
}
}
- (IBAction)selectVoice:(id)sender{
if ([(UIButton *)sender tag] == 0) {
content = [voices copy];
tableFrame = CGRectMake(50, 243, 220, 203);
[self startAnimationAndDisplayTable:YES];
[(UIButton *)sender setTag:1];
} else{
[self startAnimationAndDisplayTable:NO];
[(UIButton *)sender setTag:0];
}
}
- (void)startAnimationAndDisplayTable:(BOOL)show{
if (show) {
[self.contentTbl setHidden:NO];
[self.contentTbl setFrame:tableFrame];
[UIView beginAnimations:#"Fade In" context:nil];
[UIView setAnimationDuration:0.7];
[self.contentTbl setAlpha:1.0];
[UIView commitAnimations];
[self.contentTbl reloadData];
} else{
[UIView beginAnimations:#"Fade Out" context:nil];
[UIView setAnimationDuration:0.5];
[self.contentTbl setAlpha:0.0];
[UIView commitAnimations];
}
}
#end
"content" is an empty mutable array until you touch whatever (button?) action that calls the "selectLanguage" and "selectVoice" methods (and then you reassign the "content" variable).
I don't see any other manipulations of the "content" mutable array, so it's no wonder to me that nothing appears until you actually touch something.
You also do not show where you are calling "reloadData". "content" needs to have array entries in there for "reloadData" to work.

Resources