iPhone Bookmark UIWebView - Displaying Page Title and Storing URL - iphone

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];
}

Related

Master-Detail - Different cells to different UiTablevIewControllers

Im having a problem connecting the different tableViewCells to different UiTableViewControllers. The first cellrow gets connected to the right TableViewController but after that cant get any further because I really dont know how to set the "else if" statement here.
Thanks in advance!
Please see the .m(master):
#import "GuideTableViewController.h"
#import "GuideDetailTableViewController.h"
#import "GuideDetailTableViewController2.h"
#import "GuideDetailTableViewController3.h"
#import <QuartzCore/QuartzCore.h>
#interface GuideTableViewController (){
NSArray *guide;
NSMutableData *weatherResponseData;
}
#property (weak, nonatomic) IBOutlet UITableView *tableView;
#property (weak, nonatomic) IBOutlet UIImageView *imgHeader;
#property (weak, nonatomic) IBOutlet UIImageView *ImgTitle;
#property (weak, nonatomic) IBOutlet UIImageView *ImgWeather;
#property (weak, nonatomic) IBOutlet UIButton *btnMap;
#property (weak, nonatomic) IBOutlet UILabel *LabelWeather;
#end
#implementation GuideTableViewController
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
}
return self;
}
//JSON method
- (void) loadJSON{
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
//code
NSData *data = [NSData dataWithContentsOfURL:[NSURL URLWithString:#"https://dl.dropbox.com/u/100670549/test.json"]];
NSError *error;
if (data)
{
guide = [NSJSONSerialization JSONObjectWithData:data options:0 error:&error];
for (NSDictionary *dictionary in guide){
//NSLog([dictionary description]);
}
}else
{
NSLog(#"Could not load data");
}
dispatch_sync(dispatch_get_main_queue(), ^{
// code
[self.tableView reloadData];
});
});
}
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view.
//Call json
[self loadJSON];
[self loadWeather];
//set background
self.view.backgroundColor = [UIColor colorWithPatternImage:[UIImage imageNamed:#"background.jpg"]];
//rounded corners
[self.tableView.layer setCornerRadius:9.0];
[self.ImgWeather.layer setCornerRadius:9.0];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
//TableView
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
return 3;
}
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"Cell"];
NSDictionary *dict = [guide objectAtIndex:indexPath.row];
cell.textLabel.text = [dict valueForKey:#"title"];
return cell;
}
//To detailView
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender{
if ([segue.identifier isEqualToString:#"showStay"]){
GuideDetailTableViewController *tvc = [segue destinationViewController];
NSIndexPath *index = sender;
NSDictionary *dict = [guide objectAtIndex:index.row];
tvc.stay = dict;
}
else if([segue.identifier isEqualToString:#"showEat"]){
GuideDetailTableViewController2 *tvc = [segue destinationViewController];
NSIndexPath *index = sender;
NSDictionary *dict = [guide objectAtIndex:index.row];
tvc.eat = dict;
}
else if([segue.identifier isEqualToString:#"showDo"]){
GuideDetailTableViewController3 *tvc = [segue destinationViewController];
NSIndexPath *index = sender;
NSDictionary *dict = [guide objectAtIndex:index.row];
tvc.todo = dict;
}
}
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{
[self performSegueWithIdentifier:#"showStay" sender:indexPath];
}
- (void) viewWillAppear:(BOOL)animated{
UITableViewCell *cell = [self.tableView cellForRowAtIndexPath:self.tableView.indexPathForSelectedRow];
//ta bort markeringen när man går tillbaka till master från detailView.
[cell setSelected:NO];
//Hide navbar
[self.navigationController setNavigationBarHidden:YES];
}
//Show navbar in detailView
-(void)viewWillDisappear:(BOOL)animated{
[self.navigationController setNavigationBarHidden:NO];
}
#end

Delegation in iOS

I have 2 ViewControllers, in 1st - TableView and in 2nd - button with label on it. When I click on the button in 2nd ViewController I need to go back on TableView and set in
cell.detailTextLabel.text
text from label on the button.
Here is my code, but it does not work:
ViewController.h:
#import <UIKit/UIKit.h>
#import "TestControl.h"
#interface ViewController : UIViewController <UITableViewDataSource, UITableViewDelegate, myTestProtocol>
{
TestControl *myProtocol;
}
#property (strong, nonatomic) IBOutlet UITableView * tableTest;
#end
ViewController.m:
#import "ViewController.h"
#import "TestControl.h"
#implementation ViewController
#synthesize tableTest;
#pragma mark - View lifecycle
- (void)viewDidLoad
{
[super viewDidLoad];
self.navigationController.navigationBarHidden = YES;
myProtocol = [[TestControl alloc]init];
myProtocol.delegate = self;
// Do any additional setup after loading the view, typically from a nib.
}
- (NSInteger) numberOfSectionsInTableView:(UITableView *)tableView
{
return 1;
}
- (NSInteger) tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return 3;
}
- (void) tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
TestControl * test = [[TestControl alloc] initWithNibName:#"TestControl" bundle:nil];
[self.navigationController pushViewController:test animated:YES];
}
- (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];
}
switch (indexPath.row) {
case 0:
cell.textLabel.text = #"Firs Cell";
cell.detailTextLabel.text = myProtocol.myLabel.text;
break;
case 1:
cell.textLabel.text = #"Second Cell";
break;
case 2:
cell.textLabel.text = #"Third Cell";
break;
default:
break;
}
return cell;
}
#end
TestControl.h:
#import <UIKit/UIKit.h>
#protocol myTestProtocol <NSObject>
#end
#interface TestControl : UIViewController
{
UILabel *myLabel;
}
#property (nonatomic, assign) id <myTestProtocol> delegate;
#property (strong, nonatomic) IBOutlet UILabel *myLabel;
- (IBAction)testButton:(id)sender;
#end
TestControl.m:
#implementation TestControl
#synthesize myLabel;
#synthesize delegate;
- (IBAction)testButton:(id)sender
{
myLabel.text = #"TEXT LABEL";
[self.navigationController popToViewController:[self.navigationController.viewControllers objectAtIndex:0] animated:YES];
}
What is the problem in this???
A couple of things....
You are creating two different TestControl objects, setting the delegate for one of them and pushing the other one, so the one handling the button tap has no delegate.
The delegate logic would work better the other way around. That is, TestControl should have the code that communicates with its delegate rather than the delegate "pulling" from TestControl.

Access UITableView cell and swipe between them from DetailView using XCode 4

I'm making my first app and I’m using XCode 4 with a Storyboard. Thanks to this place, lots of tutorials, Apple’s archives databases and a bit of me, I’m slowly getting the basics together. It’s an app populated from a plist. The plist is an array with dictionaries, the dictionarires containing stings with info about different red wines in Norway. First, the plist populates a TableView. I’m using NSSortDescritor to sort the TableView and added a button to the navigation bar for resorting if I want it displayed by another value. It looks like this:
RootTableViewController.h:
#import <UIKit/UIKit.h>
#interface RootTableViewController : UITableViewController <UIActionSheetDelegate> {
NSMutableArray *sortedObjects;
}
-(IBAction)sortButtonPressed:(id)sender;
#end
RootTableViewController.m:
#import "RootTableViewController.h"
#import "ObjectCell.h"
#import "DetailViewController.h"
#interface RootTableViewController ()
#end
#implementation RootTableViewController
- (IBAction)sortButtonPressed:(id)sender;
{
UIActionSheet *sort = [[UIActionSheet alloc]
//InitWithStyle etc for sheet
}
-(void)actionSheet:(UIActionSheet *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex
{
NSSortDescriptor *sortDesc;
if (buttonIndex == 0) {
sortDesc = [[NSSortDescriptor alloc] initWithKey:#"Name" ascending:YES];
[sortedWines sortUsingDescriptors:[NSArray arrayWithObject:sortDesc]];
}
if (buttonIndex == 1) {
sortDesc = [[NSSortDescriptor alloc] initWithKey:#"Country" ascending:YES];
[sortedWines sortUsingDescriptors:[NSArray arrayWithObject:sortDesc]];
}
[self.tableView reloadData];
}
- (void)viewDidLoad
{
[super viewDidLoad];
NSString *myfile = [[NSBundle mainBundle]
pathForResource:#"Objects" ofType:#"plist"];
sortedObjects = [[NSMutableArray alloc]initWithContentsOfFile:myfile];
NSSortDescriptor * sortDesc = [[NSSortDescriptor alloc] initWithKey:#"Popularity" ascending:YES];
[sortedObjects sortUsingDescriptors:[NSArray arrayWithObject:sortDesc]];
[super viewDidLoad];
}
- (void)viewDidUnload
{
[super viewDidUnload];
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
return (interfaceOrientation == UIInterfaceOrientationPortrait);
}
#pragma mark - Table view data source
- (void)viewWillAppear:(BOOL)animated {
[self.tableView deselectRowAtIndexPath:[self.tableView indexPathForSelectedRow] animated:YES];
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return [sortedObjects count];
}
//(I’m using a Custom Cell for the TableView)
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"objectCell";
ObjectCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[[ObjectCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
}
cell.nameLabel.text = [[sortedObjects objectAtIndex:indexPath.row] valueForKey:#"Name"];
cell.countryLabel.text = [[sortedObjects objectAtIndex:indexPath.row] valueForKey:#"Country"];
return cell;
}
#pragma mark - Table view delegate
//Then the selected object is sent to the DetailViewController in this segue:
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
if ([[segue identifier] isEqualToString:#"DetailSegue"]) {
NSIndexPath *selectedRowIndex = [self.tableView indexPathForSelectedRow];
DetailViewController *detailViewController = [segue destinationViewController];
detailViewController.selectedObject = [sortedObjects objectAtIndex:selectedRowIndex.row];
}
}
#end
Then the DetailViewController recieves the selected object to populate the Labels and ImageViews with the data from it.
DetailViewController.h:
#import <UIKit/UIKit.h>
#interface DetailViewController : UIViewController
#property (nonatomic, strong) IBOutlet UILabel *districtLabel;
#property (nonatomic, strong) IBOutlet UILabel *countryLabel;
#property (nonatomic, strong) IBOutlet UIImageView *bottleImageView;
#property (nonatomic, strong) NSString *selectedObject;
#end
DetailViewController.m:
#import "WinesDetailViewController.h"
#interface WinesDetailViewController ()
#end
#implementation WinesDetailViewController
#synthesize districtLabel,countryLabel,bottleImageView;
#synthesize selectedObject;
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
}
return self;
}
- (void)viewDidAppear:(BOOL)animated
{
self.title = [selectedObject valueForKey:#"Name"];
[super viewDidAppear:animated];
}
- (void)viewDidLoad
{
[super viewDidLoad];
districtLabel.text = [selectedObject valueForKey:#"District"];
countryLabel.text = [selectedObject valueForKey:#"Country"];
bottleImageView.image = [UIImage imageNamed:[selectedObject valueForKey:#"Image"]];
self.navigationController.navigationBar.translucent = YES;
self.wantsFullScreenLayout = YES;
//Then I’ve added recognizers for left and right swiping:
UISwipeGestureRecognizer *leftGesture = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:#selector(swipeDetectedLeft:)];
leftGesture.direction = UISwipeGestureRecognizerDirectionLeft;
[self.view addGestureRecognizer:leftGesture];
UISwipeGestureRecognizer *rightGesture = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:#selector(swipeDetectedRight:)];
rightGesture.direction = UISwipeGestureRecognizerDirectionRight;
[self.view addGestureRecognizer:rightGesture];
}
//And the voids to handle the swipes:
- (void)swipeDetectedRight:(UISwipeGestureRecognizer *)sender
{
//Access previous cell in TableView
}
- (void)swipeDetectedLeft:(UISwipeGestureRecognizer *)sender
{
//Access next cell in TableView
}
//Some more besic code for the view..
#end
As you can see, I’ve added UISwipeGestureRecognizers in the DetailViewController, because I want to reload it with data from the previous cell to when swiped to the right, and next cell when swiped to the left. Now I have no idea how to handle the voids for swipe detected, how can I reach selectedRowIndex from DetailView and swipe through cells? I’m new to programming, have been trying to figure this out for a long time now, so code examples would be great so the answer don't lead to 100 new questions if you know what I mean. Thank you so much if you can help me.
One way to go about this is to pass the "sorted" datasource array to the DetailViewController and the indexpath through the "prepareForSegue" method.
RootTableViewController.h:
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
if ([[segue identifier] isEqualToString:#"DetailSegue"]) {
NSIndexPath *selectedRowIndex = [self.tableView indexPathForSelectedRow];
DetailViewController *detailViewController = [segue destinationViewController];
detailViewController.selectedObject = [sortedObjects objectAtIndex:selectedRowIndex.row];
//added code
detailViewController.detailsDataSource = [[NSArray alloc]initWithArray:sortedObjects];
detailViewController.detailIndex = selectedRowIndex.row;
}
}
Then you could reload the UI elements of the DetailViewController.
Here is the declaration of the new properties.
DetailViewController.h:
#import <UIKit/UIKit.h>
#interface DetailViewController : UIViewController
#property (nonatomic, strong) IBOutlet UILabel *districtLabel;
#property (nonatomic, strong) IBOutlet UILabel *countryLabel;
#property (nonatomic, strong) IBOutlet UIImageView *bottleImageView;
#property (nonatomic, strong) NSString *selectedObject;
// added code
#property (strong, nonatomic) NSArray *detailsDataSource;
#property int detailIndex;
#end
Don't forget to synthesize the new properties
#synthesize detailsDataSource,detailIndex;
//And the voids to handle the swipes:
- (void)swipeDetectedRight:(UISwipeGestureRecognizer *)sender
{
//Access previous cell in TableView
if (detailIndex != 0) // This way it will not go negative
detailIndex--;
districtLabel.text = [[detailsDataSource objectAtIndex: detailIndex] valueForKey:#"District"]];
countryLabel.text = [[detailsDataSource objectAtIndex: detailIndex] valueForKey:#"Country"];
bottleImageView.image = [UIImage imageNamed:[[detailsDataSource objectAtIndex: detailIndex] valueForKey:#"Image"]];
}
- (void)swipeDetectedLeft:(UISwipeGestureRecognizer *)sender
{
//Access next cell in TableView
if (detailIndex != [detailsDataSource count]) // make sure that it does not go over the number of objects in the array.
detailIndex++; // you'll need to check bounds
districtLabel.text = [[detailsDataSource objectAtIndex: detailIndex] valueForKey:#"District"]];
countryLabel.text = [[detailsDataSource objectAtIndex: detailIndex] valueForKey:#"Country"];
bottleImageView.image = [UIImage imageNamed:[[detailsDataSource objectAtIndex: detailIndex] valueForKey:#"Image"]];
}
//Some more besic code for the view..
#end
Give this a try it might work for you. Otherwise, I think you might want to take a look at Scrollview and "paging." iPhone/iPad users are used to this UI design, and you might be able to modify it to fit what you are doing.

iPhone Bookmark UIWebView - Displaying Page Title Instead of URL

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.

Why I got a "sent to freed object error"?

I have a Table View, and CharTableController, the CharTableController works like this:
.h:
#import <Foundation/Foundation.h>
#interface CharTableController : UITableViewController <UITableViewDelegate, UITableViewDataSource>{
// IBOutlet UILabel *debugLabel;
NSArray *listData;
}
//#property (nonatomic, retain) IBOutlet UILabel *debugLabel;
#property (nonatomic, retain) NSArray *listData;
#end
The .m:
#import "CharTableController.h"
#implementation CharTableController
#synthesize listData;
- (void)viewDidLoad {
NSArray *array = [[NSArray alloc] initWithObjects:#"Sleepy", #"Sneezy", #"Bashful", #"Happy", #"Doc", #"Grumpy", #"Dopey", #"Thorin", #"Dorin", #"Nori", #"Ori", #"Balin", #"Dwalin", #"Fili", #"Kili", #"Oin", #"Gloin", #"Bifur", #"Bofur", #"Bombur", nil];
self.listData = array;
[array release];
[super viewDidLoad];
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return [self.listData count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *SimpleTableIdentifier = #"SimpleTableIdentifier";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier: SimpleTableIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc]
initWithStyle:UITableViewCellStyleDefault
reuseIdentifier:SimpleTableIdentifier] autorelease];
NSUInteger row = [indexPath row]; cell.textLabel.text = [listData objectAtIndex:row];
}
return cell;
}
#end
And I Use the IB to link the TableView's dataSource and delegate to the CharTableController.
In the CharTableController's view is the TableView in IB obviously. Reference Object in dataSource > TableView and delegate > TableView. What's wrong with my setting? thz.
How is listData filled ?
Maybe you add objects in the Array, then somewhere, these objects are released.
So listData reference a not more existing object.
Put a breakpoint in your object dealloc method to see when is being released and try to enable NSZombie.
Thierry