I have a fully operational web browser application that stores bookmarked pages. When the bookmarks button is clicked, a listview of the stored websites is displayed. Instead of showing the URL, I would like the listview to display the title of the page. I am able to get the title of the page with the code below, but do not know how or where to implement it.
NSString *webSiteTitle = [self.webView stringByEvaluatingJavaScriptFromString:#"document.title"];
I have included the .m and .h files for the two ViewControllers below. Please show/tell me what to do.
Thank you!
ExplorerViewController.h
#interface ExplorerViewController : UIViewController <UITextFieldDelegate, UIWebViewDelegate, UIActionSheetDelegate>{
UITextField *urlField;
UIBarButtonItem *refreshButton;
UIBarButtonItem *backButton;
UIBarButtonItem *forwardButton;
UIBarButtonItem *bookMarksButton;
UIActivityIndicatorView *loadingActivity;
UIWebView *webView;
UINavigationBar *navigationBar;
}
#property (nonatomic, retain) IBOutlet UITextField *urlField;
#property (nonatomic, retain) IBOutlet UIBarButtonItem *refreshButton;
#property (nonatomic, retain) IBOutlet UIBarButtonItem *backButton;
#property (nonatomic, retain) IBOutlet UIBarButtonItem *forwardButton;
#property (nonatomic, retain) IBOutlet UIBarButtonItem *bookMarksButton;
#property (nonatomic, retain) IBOutlet UIActivityIndicatorView *loadingActivity;
#property (nonatomic, retain) IBOutlet UIWebView *webView;
#property (nonatomic, retain) IBOutlet UINavigationBar *navigationBar;
-(NSString*)repairURL:(NSString*)url;
-(IBAction)refreshWebView;
-(IBAction)goBack;
-(IBAction)goForward;
-(void)actualizeButtons;
-(IBAction)bookmarksButtonTapped;
-(IBAction)addBookmarkButtonTapped;
#end
ExplorerViewController.m
#import "ExplorerViewController.h"
#import "BookmarksViewController.h"
#implementation ExplorerViewController
#synthesize urlField;
#synthesize refreshButton;
#synthesize backButton;
#synthesize forwardButton;
#synthesize bookMarksButton;
#synthesize loadingActivity;
#synthesize webView;
#synthesize navigationBar;
-(void)actionSheet:(UIActionSheet *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex {
if (buttonIndex == 0) {
NSMutableArray *bookmarks = [[[NSUserDefaults standardUserDefaults] arrayForKey:#"Bookmarks"] mutableCopy];
if (!bookmarks) {
bookmarks = [[NSMutableArray alloc] init];
}
[bookmarks addObject:[[[[self webView]request] URL] absoluteString]];
[[NSUserDefaults standardUserDefaults] setObject:bookmarks forKey:#"Bookmarks"];
[bookmarks release];
}
}
BookmarksViewController.h
#class ExplorerViewController;
#interface BookmarksViewController : UIViewController <UITableViewDelegate, UITableViewDataSource>{
NSMutableArray *bookmarks;
ExplorerViewController *explorerView;
}
#property (nonatomic, retain) NSMutableArray *bookmarks;
#property (nonatomic, retain) ExplorerViewController *explorerView;
-(IBAction)cancelButtonTapped;
#end
BookmarksViewController.m
#import "BookmarksViewController.h"
#import "ExplorerViewController.h"
#implementation BookmarksViewController
#synthesize bookmarks, explorerView;
-(IBAction)cancelButtonTapped {
[self.parentViewController dismissModalViewControllerAnimated:true];
}
-(NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return 1;
}
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return [bookmarks count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *cellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithFrame:CGRectZero reuseIdentifier:cellIdentifier] autorelease];
}
cell.textLabel.text = [bookmarks objectAtIndex:indexPath.row];
return cell;
}
In ExplorerViewController.m, replace :
[bookmarks addObject:[[[[self webView]request] URL] absoluteString]];
by :
[bookmarks addObject:[self.webView stringByEvaluatingJavaScriptFromString:#"document.title"]];
If you need to have also the URL, add an NSArray instead the NSString to store either the URL and the title.
Related
First here is the code showing the uiviewcontroller which contain the uitableview:
//View Controller with navigation bar
InAppPurchaseViewController *purchaseViewController = [[InAppPurchaseViewController alloc] init];
purchaseViewController.title = #"Liste de packs";
purchaseViewController.navigationItem.rightBarButtonItem = [[[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemDone target:self action:#selector(dismissViewController:)] autorelease];
//Creation de la navigation bar et release du viewcontroller
UINavigationController *navController = [[[UINavigationController alloc] initWithRootViewController:purchaseViewController] autorelease];
[purchaseViewController release];
container = [[UIViewController alloc] init];
[container setView:[[CCDirector sharedDirector] openGLView]];
[container setModalTransitionStyle: UIModalTransitionStyleCoverVertical];
[container presentModalViewController: navController animated: YES];
here is my uitableviewcell:
InAppPurchaseCell.h
#interface InAppPurchaseCell : UITableViewCell
#property (strong, nonatomic) IBOutlet UIImageView *ImageThumbnail;
#property (strong, nonatomic) IBOutlet UIButton *BuyButton;
#property (strong, nonatomic) IBOutlet UILabel *TitleLabel;
#property (strong, nonatomic) IBOutlet UILabel *PriceLabel;
#end
InAppPurchaseCell.m
#implementation InAppPurchaseCell
#synthesize PriceLabel;
#synthesize TitleLabel;
#synthesize BuyButton;
#synthesize ImageThumbnail;
-(id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self)
{
}
return self;
}
- (void)setSelected:(BOOL)selected animated:(BOOL)animated
{
[super setSelected:selected animated:animated];
}
#end
InAppPurchaseCell.xib
All the iboutlet are linked correctly
And :
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
NSString *cellIdentifierCasual = #"ShopCell";
InAppPurchaseCell *cell = (InAppPurchaseCell*)[tableView dequeueReusableCellWithIdentifier:cellIdentifierCasual];
if (cell == nil)
{
cell = (InAppPurchaseCell*)[[[NSBundle mainBundle] loadNibNamed:#"InAppPurchaseCell" owner:nil options:nil]lastObject];
cell.selectionStyle = UITableViewCellSelectionStyleGray;
}
else
{
cell.selectionStyle = UITableViewCellSelectionStyleGray;
}
Packages *packages = [PackagesParser loadData];
Package *package = [packages.Packages objectAtIndex:indexPath.row];
cell.ImageThumbnail.image = [UIImage imageNamed:#"Icon-Small.png"];
cell.PriceLabel.text = #"0,75$";
cell.TitleLabel.text = package.Name;
return cell;
}
What's hapenning when the table pop up :
2012-07-13 13:56:55.378 Testing[1276:1c103] *** Terminating app due to uncaught
exception 'NSUnknownKeyException', reason: '[<NSObject 0xa10da00>
setValue:forUndefinedKey:]: this class is not key value coding-compliant for the key ImageThumbnail.'
At this line :
cell = (InAppPurchaseCell*)[[[NSBundle mainBundle] loadNibNamed:#"InAppPurchaseCell" owner:nil options:nil]lastObject];
Does someone has an idea ?
this may help you
InAppPurchaseCell *cell=[tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell==nil) {
cell=[[InAppPurchaseCell alloc]initWithFrame:CGRectMake(0, 0, 200, 100)
reuseIdentifier:#"ShopCell"];
}
I have a view containing a UITableView using prototype cells. It contains a few labels I have connected to a subclassed UITableViewCell in interface builder.
When I click a row, I have created a segue in a storyboard to a detail view. This view can also be accessed via a segue from another class.
My table and detail views use a navigation controller.
My problem is that when I transition from the table view to the detail view and back again multiple times, I've noticed that after a while the transition from the detail view back to the table view starts getting jerky. The table scrolling begins to be slightly jerky too.
I'm using ARC.
If anyone can give me tips on what is likely to cause this, or tools I should use to investigate it would be really appreciated.
I'll put down some of my source code in case that helps. Please let me know if there's anything else I should provide.
The table view is populated from a remote service, however the problem occurs after the table is already populated and I'm not calling the service again.
Table view header:
#import <UIKit/UIKit.h>
#import "SearchManager.h"
#interface SearchViewController : UIViewController <UISearchBarDelegate, UITableViewDelegate, UITableViewDataSource, FreeTextSearchClient>
#property (nonatomic, retain) IBOutlet UITableView *TableView;
#end
Table view code:
#import "SearchViewController.h"
#import "SearchManager.h"
#import "LocationTableViewCell.h"
#import "StarRatingDisplay.h"
#import "LocationViewController.h"
#interface SearchViewController ()
#end
#implementation SearchViewController
#synthesize TableView;
SearchManager *searchManager;
NSArray *locations;
bool isSearching = false;
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
}
return self;
}
- (void)viewWillAppear:(BOOL)animated {
//hide nav bar
[self.navigationController setNavigationBarHidden:true];
//deselect cell
NSIndexPath *selectedPath = [self.TableView indexPathForSelectedRow];
[self.TableView deselectRowAtIndexPath:selectedPath animated:false];
}
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view.
searchManager = [[SearchManager alloc] initWithFreeTextClient:self];
}
- (void)viewDidUnload
{
[super viewDidUnload];
// Release any retained subviews of the main view.
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
return (interfaceOrientation == UIInterfaceOrientationPortrait);
}
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
// Make sure your segue name in storyboard is the same as this line
if ([[segue identifier] isEqualToString:#"LocationDetails"])
{
// Get reference to the destination view controller
LocationViewController *vc = [segue destinationViewController];
NSIndexPath *indexPath = [self.TableView indexPathForSelectedRow];
vc.location = [locations objectAtIndex:indexPath.row];
}
}
- (void)showStarRating:(LocationTableViewCell*) cell: (float) score {
int x = cell.titleLabel.frame.origin.x;
int y = cell.ratingLabel.frame.origin.y + 2;
//add rating
NSArray *stars = [StarRatingDisplay GetTinyStarsForScore:score];
NSEnumerator *enumerator = [stars objectEnumerator];
UIImage *thisStar;
int i = 0;
//create image views for stars and place them on the callout
while(thisStar = [enumerator nextObject]) {
UIImageView *view = [[UIImageView alloc] initWithImage:thisStar];
view.frame = CGRectMake(x+(thisStar.size.width + 2)*i, y, thisStar.size.width, thisStar.size.height);
[cell.contentView addSubview:view];
i++;
}
}
#pragma mark - UITableView
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
// Return the number of sections.
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
// Return the number of rows in the section.
if([locations count] == 0 && isSearching) {
return 1;
}
else {
return [locations count];
}
}
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
if ([locations count] == 0) {
return 53;
} else {
return 77;
}
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
if([locations count] > 0) {
LocationTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"LocationCell"];
Location *location = [locations objectAtIndex:indexPath.row];
cell.titleLabel.text = location.Name;
cell.addressLabel.text = location.Address.description;
cell.ratingLabel.text = [NSString stringWithFormat:#"%d rating%#", location.Ratings, (location.Ratings != 1 ? #"s" : #"")];
[self showStarRating:cell :location.Score];
return cell;
}
else {
//if there are no locations, show the no results cell
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"NoResults"];
return cell;
}
}
#pragma mark - UISearchBarDelegate
- (void) searchBarSearchButtonClicked:(UISearchBar *)searchBar {
if(searchBar.text.length > 0) {
[searchManager FreeTextSearch:searchBar.text];
[searchBar resignFirstResponder];
isSearching = true;
}
}
- (void) searchBarCancelButtonClicked:(UISearchBar *)searchBar {
//clear search and remove keyboard
searchBar.text = #"";
[searchBar resignFirstResponder];
isSearching = false;
}
#pragma mark - SearchClient delegate
- (void) ReceiveTextSearchResponse:(NSArray *) response {
NSLog(#"Response received");
locations = response;
[self.TableView reloadData];
}
#end
Table cell header:
#import <UIKit/UIKit.h>
#protocol RatingTableViewDelegate <NSObject>
#required
- (void) changeCommentCellHeight:(int) height;
- (void) setEditingOffset;
- (void) removeEditingOffset;
#end
Table cell:
#interface RatingTableCellViewController : UITableViewCell <UITextViewDelegate>
#property (nonatomic, unsafe_unretained) id <RatingTableViewDelegate> tableViewDelegate;
#property (nonatomic, assign) bool hasRating;
#property (nonatomic, assign) float rating;
#property (nonatomic, retain) IBOutlet UILabel *label;
#property (nonatomic, retain) IBOutlet UILabel *yourRatingLabel;
#property (nonatomic, retain) IBOutlet UITextView *textView;
#property (nonatomic, retain) IBOutlet UIImageView *star1;
#property (nonatomic, retain) IBOutlet UIImageView *star2;
#property (nonatomic, retain) IBOutlet UIImageView *star3;
#property (nonatomic, retain) IBOutlet UIImageView *star4;
#property (nonatomic, retain) IBOutlet UIImageView *star5;
- (IBAction) submitClicked:(id)sender;
- (IBAction) cancelClicked:(id)sender;
- (void) openCell;
- (void) closeCell;
- (void) cancelRating;
#end
Detail view header:
#import <UIKit/UIKit.h>
#import "Location.h"
#import "RatingTableCellViewController.h"
#interface LocationViewController : UITableViewController <RatingTableViewDelegate>
#property (retain, nonatomic) Location *location;
#property (retain, nonatomic) IBOutlet UITableViewCell *averageRatingCell;
#property (retain, nonatomic) IBOutlet RatingTableCellViewController *yourRatingCell;
#property (retain, nonatomic) IBOutlet UILabel *ratingLabel;
#property (retain, nonatomic) IBOutlet UILabel *address;
#end
Detail View:
#import "LocationViewController.h"
#import "StarRatingDisplay.h"
#import "RatingViewController.h"
#import "RatingTableCellViewController.h"
#interface LocationViewController ()
#end
#implementation LocationViewController
#synthesize location;
#synthesize averageRatingCell, yourRatingCell;
#synthesize ratingLabel;
#synthesize address;
int commentCellHeight = 45;
- (id)initWithStyle:(UITableViewStyle)style
{
self = [super initWithStyle:style];
if (self) {
// Custom initialization
}
return self;
}
- (void)viewWillAppear:(BOOL)animated {
[self showStarRating:averageRatingCell];
ratingLabel.Text = [NSString stringWithFormat: #"%d Rating%#:", location.Ratings, location.Ratings != 1 ? #"s" : #""];
self.navigationItem.title = location.Name;
address.text = location.Address.description;
address.lineBreakMode = UILineBreakModeWordWrap;
address.numberOfLines = 5;
yourRatingCell.tableViewDelegate = self;
// Show the nav bar. It might be hidden if coming from search view.
[self.navigationController setNavigationBarHidden:false];
}
- (void) setEditingOffset {
[self.tableView setContentOffset:CGPointMake(0, 60)];
}
- (void) removeEditingOffset {
[self.tableView setContentOffset:CGPointMake(0, 0)];
}
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
if (indexPath.section == 0 && indexPath.row == 1) {
return commentCellHeight;
}
else if(indexPath.section == 1 && indexPath.row == 0) {
return 70;
}
return 45;
}
- (void) changeCommentCellHeight:(int) height {
commentCellHeight = height;
[self.tableView beginUpdates];
[self.tableView endUpdates];
}
- (void)showStarRating:(UITableViewCell*) cell {
int x = 132;
int y = 12;
//add rating
NSArray *stars = [StarRatingDisplay GetStarsForScore:location.Score];
NSEnumerator *enumerator = [stars objectEnumerator];
UIImage *thisStar;
int i = 0;
//create image views for stars and place them on the callout
while(thisStar = [enumerator nextObject]) {
UIImageView *view = [[UIImageView alloc] initWithImage:thisStar];
view.frame = CGRectMake(x+(thisStar.size.width + 2)*i, y, thisStar.size.width, thisStar.size.height);
[cell.contentView addSubview:view];
i++;
}
}
- (void) viewWillDisappear:(BOOL)animated {
//reset the comment/rating cell height
NSIndexPath *commentPath = [NSIndexPath indexPathForRow:1 inSection: 0];
RatingTableCellViewController *ratingCell = (RatingTableCellViewController*)[self.tableView cellForRowAtIndexPath:commentPath];
[ratingCell cancelRating];
}
- (void)viewDidLoad
{
[super viewDidLoad];
// Uncomment the following line to preserve selection between presentations.
// self.clearsSelectionOnViewWillAppear = NO;
// Uncomment the following line to display an Edit button in the navigation bar for this view controller.
// self.navigationItem.rightBarButtonItem = self.editButtonItem;
}
- (void)viewDidUnload
{
[super viewDidUnload];
// Release any retained subviews of the main view.
// e.g. self.myOutlet = nil;
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
return (interfaceOrientation == UIInterfaceOrientationPortrait);
}
#end
I have a Card Object, which have 4 instance variables namely name(NSString), pin(NSString), points(NSNumber), pointsToDeduct(NSMutableArray).
Card.h
#interface Card : NSObject
#property (nonatomic, strong) NSString *name;
#property (nonatomic, strong) NSString *pin;
#property (nonatomic, strong) NSNumber *points;
#property (nonatomic, strong) NSMutableArray *pointsToDeduct;
#end
This pointsToDeduct array is always present for every new instance of Card I make. What I want is to fill it's values with another array's values which are static through a button click. But before that, in my code below, I cast those static values into an NSNumber so that the pointsToDeduct's values will be of type NSNumber. I'm thinking of delegation to do this though not sure if it's best. For now I want to access that pointsToDeduct array so I can add values in it.
*this is part of PerksDetailsViewController.m
- (IBAction)redeemPressed:(id)sender {
NSNumber *pointsRequired;
NSNumberFormatter * formatter = [[NSNumberFormatter alloc] init];
[formatter setNumberStyle:NSNumberFormatterDecimalStyle];
pointsRequired = [formatter numberFromString: (self.pointsLabel.text)];
NSLog(#"points required by the perk %#", pointsRequired);
// now insert pointsRequired's value to pointsToDeduct array instance variable of a Card
Below are the other codes that I have.
Main View
CardWalletViewController.h
#import <UIKit/UIKit.h>
#interface CardWalletViewController : UITableViewController
#property (nonatomic, strong) NSMutableArray *myWallet;
-(void) printArrayContents;
CardWalletViewController.m
#import "CardWalletViewController.h"
#import "AddCardViewController.h"
#import "Card.h"
#import "CardDetailsViewController.h"
#interface CardWalletViewController () <AddCardDelegate>
#end
#implementation CardWalletViewController
#synthesize myWallet = _myWallet;
- (NSMutableArray *) myWallet
{
if (_myWallet == nil) _myWallet = [[NSMutableArray alloc] init];
return _myWallet;
}
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if ([segue.identifier isEqualToString:#"showAddCardVC"]) {
AddCardViewController *addCardVC = (AddCardViewController *)segue.destinationViewController;
addCardVC.delegate = self;
}
}
- (void)printArrayContents
{
// I want to show the name of each instance
for ( int i = 0; i < self.myWallet.count; i++) {
Card *cardDummy = [self.myWallet objectAtIndex:i];
NSLog(#"Element %i is %#", i,cardDummy.name );
}
}
- (void)addCardViewController:(AddCardViewController *)sender didCreateCard:(Card *)newCard
{
// insert a new card to the array
[self.myWallet addObject:newCard];
[self printArrayContents];
[self.tableView reloadData];
}
- (void)saveMyWallet: (NSMutableArray *)myWallet
{
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
[defaults setObject:self.myWallet forKey:#"myWalletArray"];
[defaults synchronize];
NSLog(#"I am saved");
}
- (NSMutableArray *)loadWallet
{
NSMutableArray *boom;
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
boom = [defaults objectForKey: #"myWalletArray"];
if (!boom) {
boom = [[NSMutableArray alloc] init];
}
return boom;
}
- (void)viewDidLoad
{
[self loadWallet];
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
}
- (void)viewDidUnload
{
[super viewDidUnload];
// Release any retained subviews of the main view.
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
//this method will return the number of rows to be shown
return self.myWallet.count;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = (UITableViewCell *) [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier];
}
Card *cardDummy = [self.myWallet objectAtIndex:indexPath.row];
cell.textLabel.text = cardDummy.name;
cell.detailTextLabel.text = [NSString stringWithFormat:#"%#", cardDummy.points];
return cell;
}
- (void) tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
//this method is responsible for showing the details of a selected card
//make another view controller - DetailVC perhaps
CardDetailsViewController *details = [self.storyboard instantiateViewControllerWithIdentifier:#"cardDetails"];
Card *cardDummy = [self.myWallet objectAtIndex:indexPath.row];
details.myPoints = [NSString stringWithFormat:#"%#", cardDummy.points];
[self.navigationController pushViewController:details animated:YES];
}
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
return 60;
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
return (interfaceOrientation != UIInterfaceOrientationPortraitUpsideDown);
}
#end
The way I create a new Card
AddCardViewController.m
#import "AddCardViewController.h"
#import "Card.h"
#import "CardWalletViewController.h"
#interface AddCardViewController ()
#end
#implementation AddCardViewController
#synthesize cardNameTextField = _cardNameTextField;
#synthesize pinTextField = _pinTextField;
#synthesize pointsTextField = _pointsTextField;
#synthesize delegate = _delegate;
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
}
return self;
}
- (void) viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
[self.cardNameTextField becomeFirstResponder];
}
- (BOOL) textFieldShouldReturn:(UITextField *)textField{
if ([textField.text length]) {
[self.cardNameTextField resignFirstResponder];
[self.pinTextField resignFirstResponder];
[self.pointsTextField resignFirstResponder];
return YES;
}
else {
return NO;
}
}
- (void)viewDidLoad
{
self.cardNameTextField.delegate = self;
self.pinTextField.delegate = self;
self.pointsTextField.delegate = self;
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
}
- (void)viewDidUnload
{
[self setCardNameTextField:nil];
[self setPinTextField:nil];
[self setPointsTextField:nil];
[super viewDidUnload];
// Release any retained subviews of the main view.
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
return (interfaceOrientation == UIInterfaceOrientationPortrait);
}
- (IBAction)addCard:(id)sender
{
Card *myNewCard = [[Card alloc] init];
myNewCard.name = self.cardNameTextField.text;
myNewCard.pin = self.pinTextField.text;
NSNumber *myPoints;
NSNumberFormatter * f = [[NSNumberFormatter alloc] init];
[f setNumberStyle:NSNumberFormatterDecimalStyle];
myPoints = [f numberFromString: (self.pointsTextField.text)];
myNewCard.points = myPoints;
//method here that will dismiss the modal view
// if condition forces the user to fill up all the text field
if ([self.cardNameTextField.text length] && [self.pinTextField.text length] && [self.pointsTextField.text length])
{
//method here that will dismiss the modal view
[[self presentingViewController] dismissModalViewControllerAnimated:YES];
//checking...
NSLog(#"name saved %#", myNewCard.name);
NSLog(#"pin saved %#", myNewCard.pin);
NSLog(#"points saved %#", myNewCard.points);
[self.delegate addCardViewController:self didCreateCard:myNewCard];
// to check if there is a delegate
/*
if (self.delegate){
NSLog(#"delegate is not nil");
}
*/
}
}
#end
AddCardViewController.h
#import <UIKit/UIKit.h>
#import "Card.h"
#class AddCardViewController;
#protocol AddCardDelegate <NSObject>
- (void)addCardViewController:(AddCardViewController *)sender
didCreateCard:(Card *) newCard;
#end
#interface AddCardViewController : UIViewController <UITextFieldDelegate>
#property (strong, nonatomic) IBOutlet UITextField *cardNameTextField;
#property (strong, nonatomic) IBOutlet UITextField *pinTextField;
#property (strong, nonatomic) IBOutlet UITextField *pointsTextField;
#property (nonatomic, strong) id <AddCardDelegate> delegate;
#end
CardDetailsViewController.m
#import "CardDetailsViewController.h"
#import "PerksDetailsViewController.h"
#import "Card.h"
#interface CardDetailsViewController ()
#end
#implementation CardDetailsViewController
#synthesize pointsLabel = _pointsLabel;
#synthesize myPoints = _myPoints;
#synthesize perks = _perks;
#synthesize datasource = _datasource;
#synthesize datasourcePoints = _datasourcePoints;
-(void)setupArray
{
self.perks = [[NSMutableDictionary alloc] init];
[self.perks setObject:#"200" forKey:#"10% Discount"];
[self.perks setObject:#"100" forKey:#"250Php Off"];
self.datasource = [self.perks allKeys]; //contains perk's description
self.datasourcePoints = [self.perks allValues]; //contains perk's required points
}
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return 2;
}
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = (UITableViewCell *) [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (!cell) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier];
}
cell.textLabel.text = [self.datasource objectAtIndex:indexPath.row];
cell.detailTextLabel.text = [self.datasourcePoints objectAtIndex:indexPath.row];
return cell;
}
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
PerksDetailsViewController *perksDetails = [self.storyboard instantiateViewControllerWithIdentifier:#"detailsOfMyPerks"];
[self.navigationController pushViewController:perksDetails animated:YES];
perksDetails.perkDetailsLabel.text = [self.datasource objectAtIndex:indexPath.row];
perksDetails.pointsLabel.text = [self.perks objectForKey:perksDetails.perkDetailsLabel.text];
}
- (void)viewDidLoad
{
//show the number of points of the selected Card
self.pointsLabel.text = self.myPoints;
self.navigationItem.title = #"Your Points";
[self setupArray];
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
}
- (void)viewDidUnload
{
[self setPointsLabel:nil];
[super viewDidUnload];
// Release any retained subviews of the main view.
}
#end
CardDetailsViewController.h
#import <UIKit/UIKit.h>
#interface CardDetailsViewController : UIViewController <UITableViewDelegate, UITableViewDataSource>
{
}
#property (nonatomic, retain) NSMutableDictionary *perks;
#property (nonatomic, retain) NSArray *datasource;
#property (nonatomic, retain) NSArray *datasourcePoints;
-(void)setupArray;
#property (strong, nonatomic) IBOutlet UILabel *pointsLabel;
#property (nonatomic, weak) NSString *myPoints;
#end
PerksDetailsViewController.m
#import "PerksDetailsViewController.h"
#import "Card.h"
#import "CardWalletViewController.h"
#interface PerksDetailsViewController ()
#end
#implementation PerksDetailsViewController
#synthesize pointsLabel = _pointsLabel;
#synthesize perkDetailsLabel = _perkDetailsLabel;
#synthesize perkDetailText = _perkDetailText;
#synthesize pointsText = _pointsText;
- (IBAction)redeemPressed:(id)sender {
// get required points of a perk selected
// cast the NSString value to an int/NSInteger
NSNumber *pointsRequired;
NSNumberFormatter * f = [[NSNumberFormatter alloc] init];
[f setNumberStyle:NSNumberFormatterDecimalStyle];
pointsRequired = [f numberFromString: (self.pointsLabel.text)];
NSLog(#"points required by the perk %#", pointsRequired);
// now insert this value to points array instance variable of a Card
}
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
}
return self;
}
- (void)viewDidLoad
{
//self.perkDetailsLabel.text = self.perkDetailText;
//self.pointsLabel.text = self.pointsText;
NSLog(#"perk detail:%#", self.perkDetailText);
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
}
- (void)viewDidUnload
{
[self setPerkDetailsLabel:nil];
[self setPointsLabel:nil];
[super viewDidUnload];
// Release any retained subviews of the main view.
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
return (interfaceOrientation == UIInterfaceOrientationPortrait);
}
#end
PerksDetailsViewController.h
#import <UIKit/UIKit.h>
#interface PerksDetailsViewController : UIViewController
{
NSString *perkDetailText;
NSString *pointsText;
IBOutlet UILabel *perkDetailsLabel;
IBOutlet UILabel *pointsLabel;
}
#property (nonatomic, retain) IBOutlet UILabel *perkDetailsLabel, *pointsLabel;
#property (nonatomic, retain) NSString *perkDetailText, *pointsText;
#end
Your PerksDetailViewController needs to have a property of the current Card object. Then, it's simply a matter of
[self.card.pointsToDeduct addObject:pointsRequired];
I can't see in all your sample code where you are actually using any Card objects.
in current class
NSMutable Array from One Class to Another Class in iPhone
#import "SecondViewController"
SecondViewController *NextViewController = [[SecondViewController alloc]initWithNibName:#"SecondViewController" bundle:nil];
NextViewController.nextClasssArray = thisClassarray;
in second class .h
#property(nonatomic,retain) NSMutableArray *nextClasssArray;
in second class .m
#synthesize nextClasssArray;
I have a fully operational web browser application that stores bookmarked pages. When the bookmarks button is clicked, a listview of the stored websites is displayed. Instead of showing the URL, I would like the listview to display the title of the page, but I would like the UIWebView to go to the URL when the title is clicked.
I have included the code below. I have also put the properties in both header files, but can't get it to work. Please help!
ExplorerViewController.h
#import <UIKit/UIKit.h>
#interface ExplorerViewController : UIViewController <UITextFieldDelegate, UIWebViewDelegate, UIActionSheetDelegate>{
UITextField *urlField;
UIBarButtonItem *refreshButton;
UIBarButtonItem *backButton;
UIBarButtonItem *forwardButton;
UIBarButtonItem *bookMarksButton;
UIActivityIndicatorView *loadingActivity;
UIWebView *webView;
UINavigationBar *navigationBar;
}
#property (nonatomic, retain) IBOutlet UITextField *urlField;
#property (nonatomic, retain) IBOutlet UIBarButtonItem *refreshButton;
#property (nonatomic, retain) IBOutlet UIBarButtonItem *backButton;
#property (nonatomic, retain) IBOutlet UIBarButtonItem *forwardButton;
#property (nonatomic, retain) IBOutlet UIBarButtonItem *bookMarksButton;
#property (nonatomic, retain) IBOutlet UIActivityIndicatorView *loadingActivity;
#property (nonatomic, retain) IBOutlet UIWebView *webView;
#property (nonatomic, retain) IBOutlet UINavigationBar *navigationBar;
-(NSString*)repairURL:(NSString*)url;
-(IBAction)refreshWebView;
-(IBAction)goBack;
-(IBAction)goForward;
-(void)actualizeButtons;
-(IBAction)bookmarksButtonTapped;
-(IBAction)addBookmarkButtonTapped;
#end
ExplorerViewController.m
-(void)actionSheet:(UIActionSheet *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex {
if (buttonIndex == 0) {
NSMutableArray *bookmarks = [[[NSUserDefaults standardUserDefaults] arrayForKey:#"Bookmarks"] mutableCopy];
NSMutableArray *websitetitle = [[[NSUserDefaults standardUserDefaults] arrayForKey:#"Websitetitle"] mutableCopy];
if (!bookmarks) {
bookmarks = [[NSMutableArray alloc] init];
}
[bookmarks addObject:[[[[self webView]request] URL] absoluteString]];
[websitetitle addObject:[self.webView stringByEvaluatingJavaScriptFromString:#"document.title"]];
[[NSUserDefaults standardUserDefaults] setObject:bookmarks forKey:#"Bookmarks"];
[[NSUserDefaults standardUserDefaults] setObject:websitetitle forKey:#"Websitetitle"];
[bookmarks release];
[websitetitle release];
}
}
BookmarksViewController.h
#import <UIKit/UIKit.h>
#class ExplorerViewController;
#interface BookmarksViewController : UIViewController <UITableViewDelegate, UITableViewDataSource>{
NSMutableArray *bookmarks;
NSMutableArray *websitetitle;
ExplorerViewController *explorerView;
}
#property (nonatomic, retain) NSMutableArray *bookmarks;
#property (nonatomic, retain) NSMutableArray *websitetitle;
#property (nonatomic, retain) ExplorerViewController *explorerView;
-(IBAction)cancelButtonTapped;
#end
BookmarksViewController.m
#import "BookmarksViewController.h"
#import "ExplorerViewController.h"
#implementation BookmarksViewController
#synthesize bookmarks, websitetitle, explorerView;
-(IBAction)cancelButtonTapped {
[self.parentViewController dismissModalViewControllerAnimated:true];
}
-(NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return 1;
}
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return [bookmarks count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *cellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithFrame:CGRectZero reuseIdentifier:cellIdentifier] autorelease];
}
cell.textLabel.text = [websitetitle objectAtIndex:indexPath.row];
return cell;
}
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
explorerView.urlField.text = [bookmarks objectAtIndex:indexPath.row];
[explorerView textFieldShouldReturn:explorerView.urlField];
[self.parentViewController dismissModalViewControllerAnimated:true];
}
-(void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath {
if (editingStyle == UITableViewCellEditingStyleDelete) {
[bookmarks removeObjectAtIndex:indexPath.row];
[tableView deleteRowsAtIndexPaths:[NSArray arrayWithObjects:indexPath, nil] withRowAnimation:UITableViewRowAnimationFade];
[[NSUserDefaults standardUserDefaults] setObject:bookmarks forKey:#"Bookmarks"];
}
}
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
}
return self;
}
- (void)dealloc
{
[super dealloc];
// e.g. self.myOutlet = nil;
[explorerView release];
explorerView = nil;
[bookmarks release];
bookmarks = nil;
}
You have to implement tableView:didSelectRowAtIndexPath:, roughly as follows:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{
NSString *url=[bookmarks objectAtIndex:indexPath.row];
// open url here
}
A few considerations about your code:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
explorerView.urlField.text = [bookmarks objectAtIndex:indexPath.row];
[explorerView textFieldShouldReturn:explorerView.urlField];
[self.parentViewController dismissModalViewControllerAnimated:true];
}
are you trying to replicate Mobile Safari?
you should probably avoid storing your bookmarks in the NSUserDefaults storage, and use a proper store.
you should not attempt to trigger a navigation action by simulating interaction events; the proper way to make a UIWebView (your underlying browser object) load a webpage is by using loadRequest:
The following code might work for you (I am relying on a lot of assumptions here):
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
// Get your url from the bookmarks object
NSString *urlString = [bookmarks objectAtIndex:indexPath.row];
// Convert to a URL object.
NSURL *url = [NSURL URLWithString:urlString];
// Create request
NSURLRequest *requestObj = [NSURLRequest requestWithURL:url];
//Load the request in the UIWebView.
[explorerView.webView loadRequest:requestObj];
// dismiss
[self.parentViewController dismissModalViewControllerAnimated:true];
}
I have setup a table view controller and connected a sub view so when I click on the rows the new subview appears. I followed a few tutorials step by step, but from some reason, nothing comes up when I click on the rows (the row is being selected though).
Here is my main view controller:
#interface TableViewsViewController : UIViewController <UITableViewDelegate, UITableViewDataSource> {
IBOutlet UITableView *tblSimpleTable;
IBOutlet UINavigationBar *navBar;
NSArray *arryData;
NSMutableArray *listOfItems;
}
#property (nonatomic, retain) IBOutlet UITableView *tblSimpleTable;
#property (nonatomic, retain) IBOutlet UINavigationBar *navBar;
#property (nonatomic, retain) NSArray *arryData;
#property (nonatomic, retain) NSMutableArray *listOfItems;
.m (relevant portions)
// Customize the appearance of table view cells.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle: UITableViewCellStyleValue1 reuseIdentifier:CellIdentifier];
}
NSDictionary *dictionary = [listOfItems objectAtIndex:indexPath.section];
NSArray *array = [dictionary objectForKey:#"Computers"];
NSString *cellValue = [array objectAtIndex:indexPath.row];
cell.textLabel.text = cellValue;
return cell;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *) indexPath
{
NSDictionary *dictionary = [listOfItems objectAtIndex:indexPath.section];
NSArray *array = [dictionary objectForKey:#"Computers"];
NSString *selectedCountry = [array objectAtIndex:indexPath.row];
//Initialize the detail view controller and display it.
DetailViewController *dvController = [[DetailViewController alloc] initWithNibName:#"DetailView" bundle:[NSBundle mainBundle]];
dvController.selectedComputer = selectedCountry;
[self.navigationController pushViewController:dvController animated:YES];
dvController = nil;
}
And the subview controller:
.h
#interface DetailViewController : UIViewController {
IBOutlet UILabel *lblText;
NSString *selectedComputer;
}
#property (nonatomic, retain) IBOutlet UILabel *lblText;
#property (nonatomic, retain) NSString *selectedComputer;
#end
.m
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view from its nib.
//Display the selected country.
lblText.text = selectedComputer;
//Set the title of the navigation bar
self.navigationItem.title = #"Selected Computer";
}
I am pretty sure everything is well connected in IB.
Thanks for any help!
Is the table view inside a navigation controller. You can put a breakpoint on
[self.navigationController pushViewController:dvController animated:YES];
and take a loot at the self.navigationController property. if it is nil, you will not be able to push anything onto it but it will not give you an error as sending a message to nil will merely return nil in most cases.
Might be a small over look. If you created your DetailedViewController from a template and you check to create a nib file for it, the nib file should have the same name as the .h and .m files. So check for the name of your nib class. It might should be:
DetailViewController *dvController = [[DetailViewController alloc] initWithNibName:#"DetailViewController" bundle:nil];
P.S. use self. here:
self.dvController = nil;
Otherwise you will leak.