I'm trying to change the text color in a custom label in a custom UITableViewCell.
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
//////////////////////
// Unselect the prevoius selected Cell and select this one
WSLanguageTableViewCell *aPreviousSelectedCell= (WSLanguageTableViewCell*)[self.tableView cellForRowAtIndexPath:[NSIndexPath indexPathForRow:selectedRow inSection:0]];
aPreviousSelectedCell.languageLabel.textColor = [UIColor lightGrayColor];
// Select the new one
WSLanguageTableViewCell *aSelectedCell = (WSLanguageTableViewCell*)[self.tableView cellForRowAtIndexPath:indexPath];
aSelectedCell.languageLabel.textColor = [UIColor colorLanguageCellLanguageLabelText];
selectedRow = indexPath.row;
///////////////////////
// Get the new language
PFObject* languageObject = [self.objects objectAtIndex:indexPath.row];
NSString* language = [languageObject objectForKey:kWSLanguageNameKey];
//////////////////////
// Check if it's setup -- if not, then show alert
if (![[languageObject objectForKey:kWSLanguageIsSetupKey] boolValue]) {
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:kPromptChangeLanguageNotSetup message:nil delegate:nil cancelButtonTitle:nil otherButtonTitles:#"OK", nil];
[alert show];
return;
}
//////////////////////
// Check if it's the current language -- only change if not
if (![language isEqualToString:[[WSWordlistManager shared] languageTarget]]) {
// Show HUD view
AppDelegate *appDel = (AppDelegate *)[[UIApplication sharedApplication]delegate];
[appDel showGlobalProgressHUDWithTitle:kLocalizedChangingLanguage];
//////////////////////
// Load the wordlist
[[WSWordlistManager shared] loadWordlist:language completion:^() {
//////////////////////
// Add the language to user (and vice versa) in DB
[WSUserManager addLanguage:language forUser:[PFUser currentUser]];
///////////////////
// Reload User Words
WSDatabaseManager* databaseManager = [[WSDatabaseManager alloc] init];
[databaseManager retrieveUserWordlistForCurrentUserWithCallback:^(NSError *error) {
// Dismiss the HUD
AppDelegate *appDel = (AppDelegate *)[[UIApplication sharedApplication]delegate];
[appDel dismissGlobalHUD];
// Navigate to root
[self.navigationController popToRootViewControllerAnimated:YES];
}];
}];
}
}
The problem is, the color change is delayed for a while. If I take out everything below the 6 lines setting the textColor of the two cells, the change is instantaneous. What method(s) do I run right after changing the textColor so it displays?
Check UILabel's highlightedTextColor property. This is correct way to change color of selected cell's label.
Related
I am new to iOS development and currently making a sleep tracker application. I want to know if it is possible to put or set up a segue and pass data in one of the buttons that is shown to user after swiping a UITableViewCell like in this screenshot
For reference, here is what I did to the buttons. It works for UIAlertView and changing of ViewControllers, but I don't know if I can apply segues here to pass data from one ViewController to another.
//tableview swipe action iOS8
-(NSArray *)tableView:(UITableView *)tableView editActionsForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewRowAction *delete = [UITableViewRowAction rowActionWithStyle:UITableViewRowActionStyleDefault title:#"Delete" handler:^(UITableViewRowAction *action, NSIndexPath *indexPath)
{
UIAlertView *confirmDelete = [[UIAlertView alloc] initWithTitle:#"Delete Sleep Record" message:#"Do you want to delete this entry?\n\nWARNING: This action cannot be undone." delegate:self cancelButtonTitle:#"Cancel" otherButtonTitles:#"Delete", nil];
[confirmDelete show];
}];
delete.backgroundColor = [UIColor redColor];
UITableViewRowAction *edit = [UITableViewRowAction rowActionWithStyle:UITableViewRowActionStyleDefault title:#" Edit " handler:^(UITableViewRowAction *action, NSIndexPath *indexPath)
{
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:#"Main" bundle:nil];
ViewController *evc = [storyboard instantiateViewControllerWithIdentifier:#"edit"];
[evc setModalPresentationStyle:UIModalPresentationFullScreen];
[self presentViewController:evc animated:YES completion:nil];
}];
edit.backgroundColor = [UIColor colorWithRed:0.188 green:0.514 blue:0.984 alpha:1];
return #[delete, edit]; //array with all the buttons you want. 1,2,3, etc...
}
If it is possible, how can I do it programmatically or through the XIB?
Have u tried
[self performSegueWithIdentifier:#"idSegue" sender:self];
in your delete and edit action handler.
Then implement prepareForSegue
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if([segue.identifier isEqualToString:#"idSegue"])
{
BViewController *BViewController = [segue destinationViewController];
BViewController.myarray = myarray; // access data and methods of BViewController here using its object
}
}
Hope it helps.. Happy Coding.. :)
I try to open an AlertView even I hold the tableview row 0.5 seconds.
I use for that following code:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{
UILongPressGestureRecognizer *longTap = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:#selector(handleTapGesture:)];
[longTap setMinimumPressDuration:0.5];
longTap.delegate = (id)self;
[self.view addGestureRecognizer:longTap];
UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
NSString *cellText = cell.textLabel.text;
[[NSUserDefaults standardUserDefaults] setObject:cellText forKey:#"CellNameToEdit"];
}
- (void)handleTapGesture:(UILongPressGestureRecognizer *)sender{
if (sender.state == UIGestureRecognizerStateBegan) {
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"Titel" message:#"message" delegate:self cancelButtonTitle:#"cancel" otherButtonTitles:nil, nil];
alert.tag = 1;
[alert show];
}
}
This code will work, but the problem is, I have to click the row first before it opens the alert view. I hope you understand what I mean.
Why are you adding UILongPressGestureRecognizer to self.view if you want it to get called when you click table..add UILongPressGestureRecognizer to your UITableView([self.youTableViewName addGestureRecognizer:longTap]) and it will work fine.
For more insight of how to do it..check out below link..
https://stackoverflow.com/a/3924965/1865424
I have used below GestureRecognizer Code, may be Helpful to You.
#pragma mark - View Controller Life Cycle
#implementation ViewController <UIGestureRecognizerDelegate>
- (void)viewDidLoad
{
UILongPressGestureRecognizer *gesture1 = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:#selector(gestureAction:)];
[gesture1 setDelegate:self];
[gesture1 setMinimumPressDuration:1];
Tableview.userInteractionEnabled = YES;
[Tableview addGestureRecognizer:recognizer];
}
#pragma mark - DidSelcelect kindof method
-(void)gestureAction:(UITapGestureRecognizer *) sender
{
CGPoint touchLocation = [sender locationOfTouch:0 inView:self.Tableview];
//here is indexpath
NSIndexPath *indexPath = [self.Tableview indexPathForRowAtPoint:touchLocation];
NSLog(#"%ld", (long)indexPath.row);
//Do here what you want to do with Cell
[self.Tableview selectRowAtIndexPath:indexPath
animated:YES
scrollPosition:UITableViewScrollPositionNone];
}
I've got a tableview containing array of names. The search bar works perfectly filtering the names in the table view.
The problem is the didSelectRowAtIndexpath is not getting fired when clicking the search tableview cell. Could you help me out?
What is the thing that I'm missing? Should I include any special delegate to involve search tableview cell click.
Below is the image and code.
-(void)search
{
nameArray = [[NSMutableArray alloc] init];
searchBar = [[UISearchBar alloc] initWithFrame:CGRectMake(0, 0, 160, 44)];
searchDisplayController = [[UISearchDisplayController alloc] initWithSearchBar:searchBar contentsController:self];
searchDisplayController.delegate = self;
searchDisplayController.searchResultsDataSource = self;
self.tableViewFriendsList.tableHeaderView = searchBar;
}
- (void)searchDisplayController:(UISearchDisplayController *)controller
willShowSearchResultsTableView:(UITableView *)tableView
{
[tableView setRowHeight:70];
[tableView reloadData];
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
if (tableView == self.tableViewFriendsList) {
NSString *friendsID =[[[self.friendsDictionary objectForKey:#"data"] objectAtIndex:indexPath.row] objectForKey:#"id"];
[[FacebookHelper sharedFacebookHelper] postOnWallWithDelegate:self andID:friendsID];
}
if (tableView == self.searchDisplayController.searchResultsTableView) {
NSLog(#"I ve come here");
NSString *friendsID =[friendsListIdArray objectAtIndex:indexPath.row];
[[FacebookHelper sharedFacebookHelper] postOnWallWithDelegate:self andID:friendsID];
}
}
You forgot to set
searchController.searchResultsDelegate = self;
I do something in one of my projects that may be of assistance:
// add gesture to detect when table view is being tapped so that keyboard may be dismissed
UITapGestureRecognizer *gestureRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self
action:#selector(dismissKeyboard)];
gestureRecognizer.cancelsTouchesInView = NO;
[self.tableView addGestureRecognizer:gestureRecognizer];
Moreover I am wondering why you have a search bar within a table cell. Would you mind posting a screen shot of it in your app? I am afraid you may be doing more work than is necessary.
I have an iOS 5 application with a storyboard and two scenes. Scene 1 is a selection list while Scene 2 shows details for each selection
In Scene 1 I need to pass a variable and I do that with:
//Handles the selection
-(void)tableView:(UITableView *)tableView accessoryButtonTappedForRowWithIndexPath:(NSIndexPath *)indexPath
{
Guests *myGuests =[guestList objectAtIndex:[indexPath row]];
selectedGuest = [[NSString alloc] initWithFormat:#"You have selected %#", myGuests.guestID];
[self performSegueWithIdentifier:#"TGG" sender:self];
}
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender{
if([[segue identifier] isEqualToString:#"TGG"]){
GuestDetailsViewController *vc = [segue destinationViewController];
[vc setGuestSelected:selectedGuest];
}
}
In Scene 2 (details) I use this to verify that the right variable was received like this
// Implement viewDidLoad to do additional setup after loading the view, typically from a nib.
- (void)viewDidLoad
{
NSString *msg = [[NSString alloc] initWithFormat:#"You have selected %#", guestSelected];
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"Selection" message:msg delegate:nil cancelButtonTitle:#"OK" otherButtonTitles:nil];
[alert show];
nameCell.textLabel.text= msg;
[super viewDidLoad];
}
All of this works fine and the alert box shows the right variable and there is a transition to the new scene. HOWEVER, the alert box displays a total of 5 times over & over and, once completed, the whole window is black. Nothing from my scene (Scene 2) is displayed at that point. So I know I have the right segue, it transitions as desired, I just can't see anything on my screen.
i ran into a situation very similar. i had unintentionally un-commented the method:
-(void)loadView
i believe this method overrides the IB interface and created it from this code instead. check to make sure it is either removed or commented out IMHO.
I've got a fairly important conceptual issue that many people have asked about, but there isn't a readily available clear answer to be found by searching.
My application is simple: Several rows of TableViewCells populated with data from a parsed JSON feed. When a cell is clicked on, that cell's info is passed to a SecondViewController and displayed. The JSON feed is also stored to a .plist and in the case that the internet is not available, the TableViewCells are populated from the .plist.
This is all working great.
However, the last thing I need is a refresh button at the top of my FirstViewController to refresh the JSON feed, and all of the cells in the table with the new data from the new variables. However, I've encountered an issue with implementing this:
My original JSON call, and variables to populate the cells are located in the ViewDidLoad method. When the view loads, these variables are "set" and don't refresh. Further, I can move the JSON call and variables into viewWillLoad - which will refresh the table each time after clicking on a cell, and then clicking "back" to the firstViewController -- this will update the JSON and cells successfully, however it does impact the speed and makes the view controller "pause" when going back to the MainViewController, which makes calling my original JSON and setting my variables in viewWillLoad an unviable option.
I have created a reload button in ViewDidLoad, which is linked to an IBAction method "refresh":
Create Button Programitically in ViewDidLoad:
// Reload issues button
UIBarButtonItem *button = [[UIBarButtonItem alloc]
initWithBarButtonSystemItem:UIBarButtonSystemItemRefresh
target:self
action:#selector(refresh:)];
self.navigationItem.rightBarButtonItem = button;
[button release];
Action Method it's linked to:
- (IBAction)refresh:(id)sender {
myRawJson = [[NSString alloc] initWithContentsOfURL:[NSURL
URLWithString:#"http://www.yoursite.com/json.JSON"]
encoding:NSUTF8StringEncoding
error:nil];
SBJsonParser *parser = [[SBJsonParser alloc] init];
NSDictionary * myParsedJson = [parser objectWithString:myRawJson error:NULL];
// New updated dictionary built from refreshed JSON
allLetterContents = [myParsedJson objectForKey:#"nodes"];
// Log the new refreshed JSON
NSLog(#"You clicked refresh. Your new JSON is %#", myRawJson);
//Maybe use the notification center?? But don't know how to implement.
//[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(refreshView:)
name:#"refreshView" object:nil];
//[[NSNotificationCenter defaultCenter] postNotificationName:#"refreshView"
object:nil];
}
[self.tableView reloadRowsAtIndexPaths:[self.tableView indexPathsForVisibleRows]
withRowAnimation:UITableViewRowAnimationNone];
[myRawJson release];
}
In the code above you can see that I'm re-calling the JSON each time the button is clicked and logging a message to console with the new JSON. This is working. I've even re-built a dictionary which is successfully adding the new content.
My question is: How can I make the tableViewCells "refresh" with this new data as well? Can I just make the button re-load the entire view controller - so it would call ViewDidLoad again? Do I need to re-think my apps structure, or move my original variables out of viewDidLoad?
I've been reading some posts on the NSNotificationCenter, but the implementation of this still baffles me, as I'm fairly new to iOS development.
Thanks~
Update:
It's still not updating. Here is my full refresh button code with [self.tableView reloadData]; called at the end of my IBAction.
- (IBAction)refresh:(id)sender {
[DSBezelActivityView newActivityViewForView:
self.navigationController.navigationBar.superview
withLabel:#"Loading Feed..." width:160];
myRawJson = [[NSString alloc] initWithContentsOfURL:[NSURL
URLWithString:#"http://site.com/mobile.JSON"]
encoding:NSUTF8StringEncoding
error:nil];
SBJsonParser *parser = [[SBJsonParser alloc] init];
NSDictionary * myParsedJson = [parser objectWithString:myRawJson error:NULL];
allLetterContents = [myParsedJson objectForKey:#"nodes"];
BOOL isEmpty = ([myParsedJson count] == 0);
if (isEmpty) {
NSString *refreshErrorMessage = [NSString
stringWithFormat:#"An internet or network connection is required."];
UIAlertView *alert = [[UIAlertView alloc]
initWithTitle:#"Alert"
message: refreshErrorMessage
delegate:self
cancelButtonTitle:#"Close"
otherButtonTitles:nil];
[alert show];
[alert release];
allLetterContents = [NSMutableDictionary
dictionaryWithContentsOfFile:[self saveFilePath]];
//NSLog(#"allLetterContents from file: %#", allLetterContents);
} else {
NSLog(#"Your new allLetterContents is %#", allLetterContents);
// Fast enumeration through the allLetterContents NSMutableDictionary
for (NSMutableDictionary * key in allLetterContents) {
NSDictionary *node = [key objectForKey:#"node"];
NSMutableString *contentTitle = [node objectForKey:#"title"];
NSMutableString *contentNid = [node objectForKey:#"nid"];
NSMutableString *contentBody = [node objectForKey:#"body"];
// Add each Title and Nid to specific arrays
//[self.contentTitleArray addObject:contentTitle];
[self.contentTitleArray addObject:[[contentTitle
stringByReplacingOccurrencesOfString:#"&"
withString:#"&"] mutableCopy]];
[self.contentNidArray addObject:contentNid];
[self.contentBodyArray addObject:contentBody];
}
}
[self.tableView reloadData];
[DSBezelActivityView removeViewAnimated:YES];
[myRawJson release];
}
I'm configuring the cell at cellForRowAtIndexPath (Updated: Posted entire method):
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier] autorelease];
if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPhone) {
cell.accessoryType = UITableViewCellAccessoryDetailDisclosureButton;
}
}
// Configure the cell.
cell.textLabel.text = [self.contentTitleArray objectAtIndex: [indexPath row]];
cell.detailTextLabel.text = [self.contentNidArray objectAtIndex: [indexPath row]];
return cell;
}
Setting it on didSelectRowAtIndexPath:
self.detailViewController.currentNodeTitle = [contentTitleArray
objectAtIndex:indexPath.row];
self.detailViewController.currentNodeNid= [contentNidArray
objectAtIndex:indexPath.row];
self.detailViewController.currentNodeBody = [contentBodyArray
objectAtIndex:indexPath.row];
So when clicking my refresh button the table should* refresh with the new json, but does not.. Am I missing a step?
Additionally this may not be important, but I'm changing the colors for every other row with:
// Customize the appearance of table view cells.
-(void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath {
if (indexPath.row % 2)
{
[cell setBackgroundColor:[UIColor colorWithRed:221.0/255.0 green:238.0/255.0 blue:255.0/255.0 alpha:1]];
cell.textLabel.textColor = [UIColor colorWithRed:2.0/255.0 green:41.0/255.0 blue:117.0/255.0 alpha:1];
cell.detailTextLabel.textColor = [UIColor colorWithRed:2.0/255.0 green:41.0/255.0 blue:117.0/255.0 alpha:1];
} else [cell setBackgroundColor:[UIColor clearColor]];
}
Update
You need to call the reload method.
[self.tableView reloadData];
This will fire the dataSource and delegate events an will refresh the UITableView.
You can find more info in the UITableView Class Reference:
Call this method to reload all the data that is used to construct the table, including cells, section headers and footers, index arrays, and so on. For efficiency, the table view redisplays only those rows that are visible.