I am using Parse as my back end and have a home view where all user's photos will go, kind of like a stream, each cell has a header with the user's username where you can click it and go to their profile. However I can't figure out how to access the user's information and bring it to the next view.. This is my code so far.
-(UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section {
static NSString *headerIdentifier = #"headerIdentifier";
UITableViewHeaderFooterView *headerView = [tableView dequeueReusableHeaderFooterViewWithIdentifier:headerIdentifier];
if (headerView == nil) {
headerView = [[UITableViewHeaderFooterView alloc] initWithFrame:CGRectMake( 0.0f, 0.0f, self.view.bounds.size.width, 44.0f)];
//Container to hold everything.
self.containerView = [[UIView alloc] initWithFrame:CGRectMake( 0.0f, 0.0f, self.view.bounds.size.width, 44)];
self.containerView.backgroundColor = [UIColor clearColor];
[headerView.contentView addSubview:containerView];
UIButton *button = [UIButton buttonWithType:UIButtonTypeSystem];
[button addTarget:self
action:#selector(viewProfile: user:)
forControlEvents:UIControlEventTouchUpInside];
[button setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];
button.frame = CGRectMake(8, 6, 100, 30);
//Setting the username to button.
PFObject *owner = [self.userPhotos objectAtIndex:section];
PFUser *user = [owner objectForKey:#"user"];
[user fetch];
self.usernameHolder = user.username;
[button setTitle:self.usernameHolder forState:UIControlStateNormal];
[containerView addSubview:button];
}
return headerView;
}
- (void)viewProfile:(UIButton *)button user:(PFUser *)user {
AccountView *accountView = [[AccountView alloc] init];
[accountView setUser:user];
[self.navigationController pushViewController:accountView animated:YES];
}
When I do an NSLog on the accountView it comes back as null and am very confused!
I think one issue is that the button isn't passing anything in the user parameter to the -viewProfile:user method.
As much as I hate using "magic numbers" for this sort of thing, what you probably need to do is use the .tag property on the button as an index to then lookup the user via the userPhotos. So...
Add in -tableView:viewForHeaderInSection:
button.tag = section
Change
[button addTarget:self action:#selector(viewProfile: user:) forControlEvents:UIControlEventTouchUpInside];
to
[button addTarget:self action:#selector(viewProfile:) forControlEvents:UIControlEventTouchUpInside];
And replace your -viewProfile:user: method with
- (void)viewProfile:(UIButton *)button {
AccountView *accountView = [[AccountView alloc] init];
PFObject *owner = [self.userPhotos objectAtIndex:button.tag];
PFUser *user = [owner objectForKey:#"user"];
[accountView setUser:user];
[self.navigationController pushViewController:accountView animated:YES];
}
You may or may not need to fetch the user again - I'm not sure if the Parse SDK will update the user in userPhotos when you fetch it. You could also avoid the fetch altogether if you .includeKey("user") on your query to get the userPhotos.
Related
I write one category method in UIView+Extensions.m:
#interface UIView (Extensions)
+ (UIView*)configureMoreViewWithBtns:(NSArray*)btnsConf;
#end
+ (UIView*)configureMoreViewWithBtns:(NSArray*)btnsConf
{
UIView* moreView = [[self alloc] initWithFrame:CGRectMake(195, 180, 120, 100)];
[moreView setBackgroundColor:[UIColor lightGrayColor]];
for (int i = 0; i < btns.count; i++) {
NSDictionary* confDict = btnsConf[i];
UIButton* btn = [[UIButton alloc] initWithFrame:CGRectMake(0, i*30 + 10, 120, 20)];
btn.contentHorizontalAlignment = UIControlContentHorizontalAlignmentLeft;
[btn setTitle:confDict[#"title"] forState:UIControlStateNormal];
[btn addTarget:self
action:NSSelectorFromString(confDict[#"selector"]
forControlEvents:UIControlEventTouchUpInside];
[moreView addSubView:btn];
}
return moreView;
}
But this implement is wrong, because i don't know how pass target parameter from my ViewController?
In my viewController, i called this method like this:
- (void)handleMoreImageTapped:(UITapGestureRecognizer*)gestureRecognizer
{
NSLog(#"%s", __FUNCTION__);
UITableViewCell* tappedCell = [UIView tableViewCellFromTapGestture:gestureRecognizer];
NSArray* btnsConf = #[
#{#"title": #"分享", #"selector": NSStringFromSelector(#selector(handleShare:))},
#{#"title": #"私信", #"selector": NSStringFromSelector(#selector(handleSiXin:))},
#{#"title": #"举报或屏蔽", #"selector": NSStringFromSelector(#selector(handleJuBao:))}
];
UIView* moreView = [UIView configureMoreViewWithBtns:btnsConf];
}
You need to also pass the target (the object the selector would be called on, in this case the viewcontroller from which you call the configuremoreviewwithbtns method) in the dictionairies.
So a dictionairy you add to the array would become
#{#"title": #"thetitle", #"selector": NSStringFromSelector(#selector(theselector:)), #"target": self},
and you'd have to change the UIView extension to this:
[btn addTarget:confDict[#"target"]
action:NSSelectorFromString(confDict[#"selector"]
forControlEvents:UIControlEventTouchUpInside];
I have a button that I want to change the background image if its selected. The code I have here works but if I scroll up and down again it becomes unselected.
- (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section {
UIView *sectionHeader = [[UIView alloc] initWithFrame:CGRectMake(0, 0, self.tableView.frame.size.width, 33)];
UILabel *sectionHeaderLabel = [[UILabel alloc] initWithFrame:CGRectMake(10, 0, 100, 30)];
sectionHeaderLabel.text = [NSString stringWithFormat:#"Section %i",section+1];
UIButton *button = [[UIButton alloc] initWithFrame:CGRectMake(200, 5, 42, 20)];
[button setBackgroundImage:[UIImage imageNamed:#"unselected_image"] forState:UIControlStateNormal];
[button setBackgroundImage:[UIImage imageNamed:#"selected_image"] forState:UIControlStateSelected];
[button addTarget:self action:#selector(buttonPressed:) forControlEvents:UIControlEventTouchUpInside];
[sectionHeader addSubview:button];
return sectionHeader;
}
- (void)buttonPressed:(id)sender {
UIButton *allButton = (UIButton*)sender;
allButton.selected = !allButton.selected;
}
1) Create an image name array in you ViewDidLoad. This array tracks the name of you photos whether if its been clicked or not.
- (void)viewDidLoad
{
//this array is just an example, loop and add items to the array for the number of sections you want
//in this example there are 5 sections with 5 images
imageNameArray = [[NSMutableArray alloc] initWithObjects:#"unselected_image", #"unselected_image", #"unselected_image", #"unselected_image", #"unselected_image", nil];
}
2) Your viewForHeaderInSection
- (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section
{
UIView *sectionHeader = [[UIView alloc] initWithFrame:CGRectMake(0, 0, self.tableView.frame.size.width, 33)];
UILabel *sectionHeaderLabel = [[UILabel alloc] initWithFrame:CGRectMake(10, 0, 100, 30)];
sectionHeaderLabel.text = [NSString stringWithFormat:#"Section %i",section+1];
button = [[UIButton alloc] initWithFrame:CGRectMake(200, 5, 42, 20)];
[button setBackgroundImage:[UIImage imageNamed:[imageNameArray objectAtIndex:section]] forState:UIControlStateNormal];
[button setTag:section];
[button addTarget:self action:#selector(buttonPressed:) forControlEvents:UIControlEventTouchUpInside];
[sectionHeader addSubview:button];
return sectionHeader;
}
3) If button is pressed change the name of you image in the Array
- (void)buttonPressed:(id)sender
{
UIButton *allButton = (UIButton*)sender;
[imageNameArray insertObject:#"selected_image" atIndex:[allButton tag]];
[allButton setBackgroundImage:[UIImage imageNamed:[imageNameArray objectAtIndex:[allButton tag]]] forState:UIControlStateNormal];
}
What happens here is that every time the view becomes visible, you actually create a completely new view with everything reset. Instead of doing that you could simply save the view and re-use the same view every time. Create the view in viewDidLoad instead:
- (void)viewDidLoad
{
sectionHeader = [[UIView alloc] initWithFrame:CGRectMake(0, 0, self.tableView.frame.size.width, 33)];
UILabel *sectionHeaderLabel = [[UILabel alloc] initWithFrame:CGRectMake(10, 0, 100, 30)];
sectionHeaderLabel.text = [NSString stringWithFormat:#"Section %i",section+1];
UIButton *button = [[UIButton alloc] initWithFrame:CGRectMake(200, 5, 42, 20)];
[button setBackgroundImage:[UIImage imageNamed:#"unselected_image"] forState:UIControlStateNormal];
[button setBackgroundImage:[UIImage imageNamed:#"selected_image"] forState:UIControlStateSelected];
[button addTarget:self action:#selector(buttonPressed:) forControlEvents:UIControlEventTouchUpInside];
[sectionHeader addSubview:button];
}
viewForHeaderInSection simply becomes:
- (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section {
return sectionHeader;
}
Please note that if you have more than one section you would need to create an array of section header views and return the correct one for each section, based on the value of the section in viewForHeaderInSection
That happen because when table scroll up and down it will again create cell so you have to manage it in some way which button is selected or not and again set selected state to those button which are previously selected in viewForHeaderInSection you can do that as bellow
//Define in header file
NSMutableArray *mutArrSelected;
//Initlise in viewdidload
mutArrSelected = [[NSMutableArray alloc] init];
- (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section
{
if(mutArrSelected.count < section)
{
[mutArrSelected addObject:[NSNumber numberWithBool:NO]];
}
UIView *sectionHeader = [[UIView alloc] initWithFrame:CGRectMake(0, 0, self.tableView.frame.size.width, 33)];
UILabel *sectionHeaderLabel = [[UILabel alloc] initWithFrame:CGRectMake(10, 0, 100, 30)];
sectionHeaderLabel.text = [NSString stringWithFormat:#"Section %i",section+1];
UIButton *button = [[UIButton alloc] initWithFrame:CGRectMake(200, 5, 42, 20)];
if([[mutArrSelected objectAtIndex:section] boolValue])
{
button.selected = YES;
}
button.tag = section;
[button setBackgroundImage:[UIImage imageNamed:#"unselected_image"] forState:UIControlStateNormal];
[button setBackgroundImage:[UIImage imageNamed:#"selected_image"] forState:UIControlStateSelected];
[button addTarget:self action:#selector(buttonPressed:) forControlEvents:UIControlEventTouchUpInside];
[sectionHeader addSubview:button];
return sectionHeader;
}
- (void)buttonPressed:(id)sender
{
UIButton *allButton = (UIButton*)sender;
allButton.selected = !allButton.selected;
[mutArrSelected removeObjectAtIndex:allButton.tag];
[mutArrSelected insertObject:[NSNumber numberWithBool:allButton.selected] atIndex:allButton.tag];
}
I am fetching the data from UITableViewCell and am storing into string is countryString. I want to change the button title with country string but its not working, i thought it is a simple issue, but am struggling from last 2 hours. still I cant find the solution why is not working
countryButton=[[UIButton alloc]initWithFrame:CGRectMake(145, 145, 100, 30)];
countryButton.backgroundColor=[UIColor whiteColor];
[countryButton setTitle:CountryString forState:UIControlStateNormal];
countryButton.titleLabel.textColor=[UIColor blackColor];
[countryButton addTarget:self action:#selector(countryTable) forControlEvents:UIControlEventTouchUpInside];
[notesView addSubview:countryButton];
-(void)tableView:(UITableView*)tableView didSelectRowAtIndexPath:(NSIndexPath*)indexPath
{
jsonDict = [newarray objectAtIndex:indexPath.row];
CountryString=[jsonDict objectForKey:#"countryName"];
NSLog(#"country is %#", CountryString);
CountryTableview.hidden=YES;
}
try this
-(void)tableView:(UITableView*)tableView didSelectRowAtIndexPath:(NSIndexPath*)indexPath
{
jsonDict = [newarray objectAtIndex:indexPath.row];
CountryString=[jsonDict objectForKey:#"countryName"];
NSLog(#"country is %#", CountryString);
[countryButton setTitle:CountryString forState:UIControlStateNormal];
countryButton.titleLabel.textColor=[UIColor blackColor];
CountryTableview.hidden=YES;
}
assume that its your str
CountryString =#"XXXX";
UIButton *countryButton = [UIButton buttonWithType:UIButtonTypeRoundedRect]; //or button type custom
[countryButton addTarget:self action:#selector(buttonClicked:) forControlEvents:UIControlEventTouchUpInside];
[countryButton setFrame:CGRectMake(145, 145, 100, 30)];
[countryButton setTitle: CountryString forState:UIControlStateNormal];
[countryButton setExclusiveTouch:YES];
countryButton.backgroundColor=[UIColor whiteColor];
countryButton.titleLabel.textColor=[UIColor blackColor];
[self.view addSubview: countryButton]; //whatever u need self.view or notesView
-(void) buttonClicked:(UIButton*)sender
{
NSLog(#"you clicked on button %#", sender.tag);
}
I know that this kind of issue discussed several times here but, I have already searched and tried without success. I am trying to create a simple login view on the top of general menu. This login page contains 2 textfields(username & password) and 1 button(login). My problem is that while everything appears perfectly when I click on Login button, is not responding.
*The login view animated from start to end point using moveTo method. Comment that part but still not responding.
Main.m
- (void)viewDidLoad
{
prefs = [NSUserDefaults standardUserDefaults];
if (![prefs objectForKey:#"userName"]) {
LoginScreen *login = [[LoginScreen alloc] initWithFrame:CGRectMake(35, 400, 250, 350)];
[self.view addSubview:login];
[login moveTo:CGPointMake(35.0, 65.0) duration:0.6 option:UIViewAnimationOptionCurveEaseOut];
}
[super viewDidLoad];
}
LoginScreen.m
#synthesize login;
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
self.layer.masksToBounds = YES;
self.userInteractionEnabled = YES;
[self addButton:login withTitle:#"Login" andSize:CGRectMake(85, 200, 90, 35)];
[login addTarget:self action:#selector(attemptLogin)
forControlEvents:UIControlEventTouchUpInside];
}
return self;
}
- (void) addButton: (UIButton*) button withTitle: (NSString*) title andSize: (CGRect) size{
button = [UIButton buttonWithType:UIButtonTypeRoundedRect];
button.frame = size;
[button setTitle:title forState:UIControlStateNormal];
button.userInteractionEnabled = YES;
[self addSubview:button];
}
- (void)attemptLogin{
NSString *user = usernameTxt.text;
NSString *pass = passwordTxt.text;
NSString *url = [[NSString alloc] initWithFormat:#"http://domain.com/login.php?username=%#&password=%#", user, pass];
NSLog(#"%#", url);
}
Nothing print on screen.
Thanks in advance
The problem is mainly you are allocting a new button, therefore not working with your login button, I commented the allocation on your code and this should work:
//Old version of code removed, please check edit
Edit
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
self.layer.masksToBounds = YES;
self.userInteractionEnabled = YES;
login = [self addButtonWithTitle:#"Login" andSize:CGRectMake(85, 200, 90, 35)];
[login addTarget:self action:#selector(attemptLogin)
forControlEvents:UIControlEventTouchUpInside];
}
return self;
}
- (UIButton) addButtonWithTitle: (NSString*) title andSize: (CGRect) size{
button = [UIButton buttonWithType:UIButtonTypeRoundedRect];
button.frame = size;
[button setTitle:title forState:UIControlStateNormal];
button.userInteractionEnabled = YES;
[self addSubview:button];
return button;
}
- (void)attemptLogin{
NSString *user = usernameTxt.text;
NSString *pass = passwordTxt.text;
NSString *url = [[NSString alloc] initWithFormat:#"http://domain.com/login.php?username=%#&password=%#", user, pass];
NSLog(#"%#", url);
}
This is because you created a button without specifying what selector to call when the button is clicked. Adding this line to your addButton method will fix the problem:
[button addTarget:self action:#selector(attemptLogin) forControlEvents:UIControlEventTouchUpInside];
When you try doing the same through the synthesized login property, the code does not work, because you never set login. When you pass it to the addButton function, the value gets ignored (you re-assign it right away). The assignment never changes the value of login, though, because Objective C passes parameters by value.
An alternative way to fix your code is to pass a pointer to login, rather than login itself, like this:
- (void) addButton: (UIButton**) button withTitle: (NSString*) title andSize: (CGRect) size {
*button = [UIButton buttonWithType:UIButtonTypeRoundedRect];
(*button).frame = size;
[*button setTitle:title forState:UIControlStateNormal];
(*button).userInteractionEnabled = YES;
[self addSubview:*button];
}
I would recommend against this way of fixing your code: using login directly inside addButton would probably be a better choice.
I think that you meant:
- (void) addButton: (UIButton*) button withTitle: (NSString*) title andSize: (CGRect) size{
button = [UIButton buttonWithType:UIButtonTypeRoundedRect];
button.frame = size;
[button setTitle:title forState:UIControlStateNormal];
button.userInteractionEnabled = YES;
[button addTarget:self action:#selector(attemptLogin)
forControlEvents:UIControlEventTouchUpInside];
[self addSubview:button];
}
You should also remove that:
[login addTarget:self action:#selector(attemptLogin)
forControlEvents:UIControlEventTouchUpInside];
from the init method.
I have one table view in that cell is custom. I am adding two button on each cell of table view. when I click on first button at same time second button from same cell is changing its image. for that I have methods as editQuantity and Cancelorder. using #sel. I am getting an issue that when i click on first button insted of changing same cell another button its changing another cells button also when I scroll table view its losses all selected button
Here Is My Code--
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
simpleTableIdentifier = #"MenuNameCell";
MenuNameCell *cell = (MenuNameCell *)[tableView dequeueReusableCellWithIdentifier:simpleTableIdentifier];
if (cell== nil) {
NSArray *nib = [[NSBundle mainBundle] loadNibNamed:#"MenuNameCell" owner:self options:nil];
cell = [nib objectAtIndex:0];
NSLog(#"---------new cell agin");
}
else
{
NSArray *arrayView = [cell.contentView subviews];
for (UIView *vTemp in arrayView)
{
[vTemp removeFromSuperview];
}
NSLog(#"---No New Cell hiiii");
// Setting Tag To UIButton
_checkButton = (UIButton *)[cell.contentView viewWithTag:indexPath.row];
_cancelButton = (UIButton *)[cell.contentView viewWithTag:indexPath.row];
}
// Creating Label Menu Name
_nameLabel = [[UILabel alloc] initWithFrame:CGRectMake(8, 11, 82, 21)];
_nameLabel.backgroundColor = [UIColor clearColor];
_nameLabel.text = [_hotel._orderedMenus objectAtIndex:indexPath.row];
// Creating Label Menu Cost
_amountMenu = [[UILabel alloc] initWithFrame:CGRectMake(167, 13, 44, 21)];
_amountMenu.backgroundColor = [UIColor clearColor];
_amountMenu.text = [[_hotel._menuPrices objectAtIndex:indexPath.row] stringValue];
// Creating Text Field For Order Quantity
_textFieldQuantity = [[UITextField alloc] initWithFrame:CGRectMake(125,14,42,21)];
_textFieldQuantity.userInteractionEnabled = NO;
_textFieldQuantity.text = [[_hotel._selectedQuantity objectAtIndex:indexPath.row] stringValue];
// Creating Button For Check Order
_checkButton = [UIButton buttonWithType:UIButtonTypeCustom];
[_checkButton setFrame:CGRectMake(232, 13, 25, 28)];
[_checkButton setTag:indexPath.row];
_checkButton.titleLabel.tag = indexPath.row;
[_checkButton setBackgroundImage:[UIImage imageNamed:#"edit.png"]forState:UIControlStateNormal];
[_checkButton addTarget:self action:#selector(editQuantity:) forControlEvents:UIControlEventTouchUpInside];
// Creating Button For CANCEL Order
_cancelButton = [UIButton buttonWithType:UIButtonTypeCustom];
[_cancelButton setFrame:CGRectMake(265, 13, 25, 28)];
[_cancelButton setBackgroundImage:[UIImage imageNamed:#"cancel.png"] forState:UIControlStateNormal];
[_cancelButton setTag:indexPath.row];
_cancelButton.titleLabel.tag = indexPath.row;
[_cancelButton addTarget:self action:#selector(cancelOreder:) forControlEvents:UIControlEventTouchUpInside];
// Adding All To Content View
[cell.contentView addSubview:_nameLabel];
[cell.contentView addSubview:_amountMenu];
[cell.contentView addSubview:_textFieldQuantity];
[cell.contentView addSubview:_checkButton];
[cell.contentView addSubview:_cancelButton];
//objc_setAssociatedObject(_checkButton, iindex, indexPath,OBJC_ASSOCIATION_RETAIN );
return cell;
}
-(void)editQuantity:(id)sender{
button = (UIButton *)sender;
row = button.tag;
col = button.titleLabel.tag;
NSLog(#"Check Button index is %d",row);
NSLog(#"cehck title is %d",col);
_textFieldQuantity.userInteractionEnabled = YES;
UIImage *buttonImage = [UIImage imageNamed:#"edit_over.png"];
[_checkButton setBackgroundImage:buttonImage forState:UIControlStateNormal];
UIImage *buttonImageCancel = [UIImage imageNamed:#"check.png"];
[_cancelButton setBackgroundImage:buttonImageCancel forState:UIControlStateNormal];
_cancelButton.tag = 0;
}
-(void)cancelOreder:(id)sender{
button = (UIButton *)sender;
row = button.tag;
NSLog(#"The Row Selected iS At Cancel Order ISSSS----%d", row);
if (_cancelButton.tag == 0){
_textFieldQuantity.userInteractionEnabled = NO;
UIImage *buttonImageCancel = [UIImage imageNamed:#"check_over.png"];
[_cancelButton setBackgroundImage:buttonImageCancel forState:UIControlStateNormal];
UIImage *buttonImageCancel1 = [UIImage imageNamed:#"cancel.png"];
[_cancelButton setBackgroundImage:buttonImageCancel1 forState:UIControlStateNormal];
UIImage *buttonImage = [UIImage imageNamed:#"edit.png"];
[_checkButton setBackgroundImage:buttonImage forState:UIControlStateNormal];
_cancelButton.tag = 1;
}
else
{
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"iHomeDelivery" message:#"Do You Want To Cancel the Order" delegate:self cancelButtonTitle:#"Ok" otherButtonTitles:nil];
[alert show];
[alert release];
}
}
The problem is that the default tag value for any control is set to 0 and you have used the _cancelButton.tag = 0;. Just change the value to 10 and then _cancelButton.tag = 1; change 1 to 11.
This will solve your problem :)
As I see _checkButton, _nameLabel, _amountMenu, _textFieldQuantity & _cancelButton all are instance variable of your view controller class.
In cellForRowAtIndexPath: as you are assigning new objects to all these, they will refere to objects of last cell displayed. Means all these will point to components from last cell.
Hence changing background images for _checkButton & _cancelButton will affect for buttons in last cell.
Also in cellForRowAtIndexPath: while creating these buttons, you are setting background image for them, hence after scrolling your button images are getting changed. Remember cellForRowAtIndexPath: gets called for a row each time that row becomes visible after getting hidden while scrolling.
You need to maintain state of buttons in separate array, so that you can reset state for buttons in cellForRowAtIndexPath: after dequeuing.