I have just figured out how to make a tabbed navigation controller open in two table views. I would like to be able to click on one of the table cells (6 on a page), and for this to open the url in a webview.
This is my code:
#import "FlashTopicsEViewController.h"
#import "ADVTheme.h"
#implementation FlashTopicsEViewController
#synthesize webView;
NSArray *flashtopicsEth;
NSArray *urlLinks;
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view.;
self.view.backgroundColor = [ADVTheme viewBackgroundColor];
self.view.tintColor = [UIColor whiteColor];
flashtopicsEth = [NSArray arrayWithObjects:#"Topic1",#"Topic2", nil];
urlLinks = [[NSArray alloc] initwithObjects:#"http://url1.com", #"http://url2.com",nil];
webView.delegate = self;
NSURL *URL = [NSURL URLWithString: urlLinks[indexPath.row]];
NSURLRequest *requestObj = [NSURLRequest requestWithURL:URL];
[webView loadRequest:requestObj];
}
and this is the code below it:
- (UITableViewCell *)tableView:(UITableView *)tableView
cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *simpleTableIdentifier = #"FlashTopicECell";
UITableViewCell *cell = [tableView
dequeueReusableCellWithIdentifier:simpleTableIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc]
initWithStyle:UITableViewCellStyleDefault
reuseIdentifier:simpleTableIdentifier];
}
UIImage *image1 = [UIImage imageNamed:#"flashImage.png"];
cell.imageView.image = image1;
cell.textLabel.text = [flashtopicsEth objectAtIndex:indexPath.row];
return cell;
}
and this is what I have in my .h file
#import <UIKit/UIKit.h>
#interface FlashTopicsEViewController : UIViewController
#property NSArray *urlLinks;
#property NSArray *flashtopicsEth;
#property (nonatomic,strong) IBOutlet UIWebView *webView;
#end
#matt is right, this is beyond trivial to do lol :) But anyway, what you need to do is to make use of one of UITableView's delegate methods called "didSelectRowAtIndexPath". This will detect when a cell is tapped:
Your question is very basic and not detailed, so for the purposes of this basic answer, I am going to declare a UIWebView in the header file and then use that. You will need to add it to your ViewController and link it up. I also do NOT know how you are storing your URLs, I presume you are using an array? Well for the purposes of this answer, I will too.
IBOutlet UIWebView *websiteView;
NSArray *urlLinks;
Now on to the implementation code:
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
// Get the cell number that was tapped and then
// use that to access your array of URLs.
// Then pass that URL to a UIWebView.
NSURL *URL = [NSURL URLWithString:urlLinks[indexPath.row]];
NSURLRequest *requestObj = [NSURLRequest requestWithURL:URL];
[websiteView loadRequest:requestObj];
}
Also in the viewDidLoad, set the webview delegate like so:
websiteView.delegate = self;
Update - In answer to your comments
Ok so in my answer I just assumed you are using an array for the list of URLs. But there are other ways too. You don't have to use an array if you don't want to.
As to how you populate the array? Well that depends on quite a few things:
1) Are you downloading a list of URLs from a server?
2) Are you setting the list of URLs in your code?
If you are doing option 1, then you are probably parsing something like a JSON file which you are downloading from a server. In this case you may want to use something a long the lines of:
urlLinks = [[feed objectForKey:#"items"] valueForKey:#"url"];
The above code will put all the url links into your array. (This is just a very tiny snippet - not the whole code - just to give you an idea).
If you are going with option 2, so you already know the list of URLs and you want to define them in your app, then just do this:
NSArray *urlLinks = [[NSArray alloc] initwithObjects:#"http://url1.com", #"http://url2.com", ...etc.... , nil];
Right so to then access the URLs, you need to basically get the string from the correct array object and then turn that into an NSURL and then pass that to your webview like so:
NSURL *URL = [NSURL URLWithString:urlLinks[indexPath.row]];
NSURLRequest *requestObj = [NSURLRequest requestWithURL:URL];
[websiteView loadRequest:requestObj];
Lastly, how you present your UIWebView is up to you. It doesn't have to be in a seperate ViewController if you dont want it to. Thats up to you. But if you do, then yes, the next bit is to present the next view controller on screen. Just remember you will have to pass your URL to it, if you want the UIWebView in that view controller to present your website.
Update 2 - in answer to your question/code
Ok there are a few things wrong with your code:
Get rid of the "etc...." bit in your array declaration.... Lol I only added that to help you understand how to populate the array. So it should really be:
flashtopicsEth = [NSArray arrayWithObjects:#"Topic1",#"Topic2", nil];
You have just randomly inserted your array code in your implementation (.m) file.... that's not where you put it. You can insert it in methods such as the viewDidLoad or other methods that you make yourself. You can't just randomly add it wherever you feel like. So for the purposes of keeping things simple, lets start with just assigning the arrays in the viewDidLoad like so:
-(void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view.
flashtopicsEth = [NSArray arrayWithObjects:#"Topic1", #"Topic2", nil];
urlLinks = [[NSArray alloc] initwithObjects:#"http://url1.com",#"http://url2.com", nil];
webView.delegate = self;
NSURL *URL = [NSURL URLWithString: urlLinks[indexPath.row]];
NSURLRequest *requestObj = [NSURLRequest requestWithURL:URL];
[webView loadRequest:requestObj];
}
Declare your NSArray's in your header file and assign them in the implementation (.m) file. Don't declare them in the viewDidLoad because they will then be local to the viewDidLoad and the other UITableView methods will not be able to access them unless your pass the array to them. For the purposes of keeping things simple (as you are a beginner), just declare them like this in your header (.h) file:
#import <UIKit/UIKit.h>
#interface FlashTopicsEViewController : UIViewController {
NSArray *flashtopicsEth;
NSArray *urlLinks;
}
#property (nonatomic,strong) IBOutlet UIWebView *webView;
#end
Related
I'm a newbie in iOS programming, i am trying to make an iOS library that can be useful on my future applications. The app will have a button that will call the library and will load a website(the address link will come from the application).
I tried searching but none of it is working.
WebLibrary.h
#import <Foundation/Foundation.h>
#interface WebLibrary : NSObject
- (void)showUIWebView:(NSURL*)urlToOpen
{
/* UIViewController *myVC = [self.navigationController.viewControllers lastObject];
//This is your last view in the navigationController hierarchy.
UIWebView *newWebView = [[UIWebView alloc] initWithFrame:myVC.view.frame];
[myVC.view addSubview:newWebView];
*/
}
#end
WebLibrary.m
#import "WebLibrary.h"
#implementation WebLibrary
/* -(void) showUIWebView:(NSURL*)urlToOpen
{
//some codes here
}
*/
#end
If you want to load an URL on your webview, you need to call the loadRequest: method to perform it, example:
NSMutableURLRequest *request = [[NSMutableURLRequest alloc]initWithURL:[NSURL URLWithString:_urlPath]];
[request addValue:#"YES" forHTTPHeaderField:#"Mobile-App"];
[_webView loadRequest:request];
You can add the webview to your viewcontroller in viewDidLoad method:
-(void) viewDidLoad{
[super viewDidLoad];
//custom your view
_webView = [[UIWebView alloc] initWithFrame: self.view.frame];
_webView.scalesPageToFit = YES;
[self.view addSubView: _webView];
}
You should read about UIViewController and the methods in it to understand clearly.
I'm running into a bit of a strange problem here. One of my NSURLSessions is in charge of getting information for restaurant information that I have stored (restaurant name, restaurant's logo URL, etc), and then the second NSURLSession is in charge of using the restaurant's logo URL to retrieve the specific image and set it for each UITableView's cell.
The problem, however, is that my UITableView does not load anything at all sometimes so the cells are empty, but at other times when I add an extra [_tableView reload] in the NSURLSessions' completion block in the fetchPosts method, it'll work, but then the cells will stop displaying anything again if I re-run it. Something is definitely wrong. Have a look at my code below:
#import "MainViewController.h"
#import "SWRevealViewController.h"
#import "RestaurantNameViewCell.h"
#import "RestaurantList.h"
#interface MainViewController ()
#end
#implementation MainViewController
- (void)viewDidLoad
{
[super viewDidLoad];
//List of restaurants needed to load home page
_restaurantInformationArray = [[NSMutableArray alloc] init];
self.tableView.dataSource = self;
self.tableView.delegate = self;
//setup for sidebar
SWRevealViewController *revealViewController = self.revealViewController;
if ( revealViewController )
{
[self.sidebarButton setTarget: self.revealViewController];
[self.sidebarButton setAction: #selector( revealToggle: )];
[self.view addGestureRecognizer:self.revealViewController.panGestureRecognizer];
}
//Get list of restaurants and their image URLs
[self fetchPosts];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
-(NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return 1;
}
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return [_restaurantInformationArray count];
}
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
RestaurantNameViewCell *cell = (RestaurantNameViewCell *)[_tableView dequeueReusableCellWithIdentifier:#"restaurantName" forIndexPath:indexPath];
RestaurantList *currentRestaurant = [_restaurantInformationArray objectAtIndex:indexPath.row];
cell.restaurantName.text = currentRestaurant.name;
cell.imageAddress = currentRestaurant.imageURL;
cell.restaurantClicked = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(tapDetected:)];
cell.restaurantClicked.numberOfTapsRequired = 1;
cell.restaurantLogo.userInteractionEnabled = YES;
[cell.restaurantLogo addGestureRecognizer:cell.restaurantClicked];
cell.restaurantLogo.tag = indexPath.row;
//Add restaurant logo image:
NSString *URL = [NSString stringWithFormat:#"http://private.com/images/%#.png",cell.imageAddress];
NSURL *url = [NSURL URLWithString:URL];
NSURLSessionDownloadTask *downloadLogo = [[NSURLSession sharedSession]downloadTaskWithURL:url completionHandler:^(NSURL *location, NSURLResponse *response, NSError *error) {
UIImage *downloadedImage = [UIImage imageWithData:[NSData dataWithContentsOfURL:location]];
cell.restaurantLogo.image = downloadedImage;
}];
[downloadLogo resume];
return cell;
}
-(void)fetchPosts {
NSString *address = #"http://localhost/xampp/restaurants.php";
NSURL *url = [NSURL URLWithString:address];
NSURLSessionDataTask *downloadRestaurants = [[NSURLSession sharedSession]dataTaskWithURL:url completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
NSError *someError;
NSArray *restaurantInfo = [NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:&someError];
for(NSDictionary *dict in restaurantInfo) {
RestaurantList *newRestaurant = [[RestaurantList alloc]init];
newRestaurant.name = [dict valueForKey:#"name"];
newRestaurant.imageURL = [dict valueForKey:#"image"];
[_restaurantInformationArray addObject:newRestaurant];
//Refresh table view to make sure the cells have info AFTER the above stuff is done
[_tableView reloadData];
}
}];
[downloadRestaurants resume];
}
#end
It's probably a very stupid mistake that I'm making, but I'm not certain how I should correct this. I'm new to iOS development, so would greatly appreciate some guidance :)
Besides assuming that your network requests aren't erroring (you should at least log if there are network errors), there are threading issues.
Your NSURLSession callback probably runs on a background thread. This makes it unsafe to call UIKit (aka - [_tableView reloadData]). UIKit isn't thread safe. This means invoking any of UIKit's APIs from another thread creates non-deterministic behavior. You'll want to run that piece of code on the main thread:
dispatch_async(dispatch_get_main_queue(), ^{
[_tableView reloadData];
});
Likewise for fetching the images. It's slightly more complicated because of table view cell reuse which could cause the wrong image to display when scrolling. This is because the same cell instance is used for multiple values in your array as the user scrolls. When any of those callbacks trigger, it'll replace whatever image happens to be in that cell. The generally steps to reproduce this is as follows:
TableView requests 5 cells
MainViewController requests 5 images (one for each cell)
User scrolls down one cell
The first cell gets reused as the 6th cell.
MainViewController requests another image for the 6th cell.
The 6th image is retrieved, the callback is triggered, image of the first cell is set to image #6.
The 1st image is retrieved, the callback is triggered, image of the first cell is set to image #1 (incorrect).
You'll need to make sure the cell is displaying the correct cell before attempting to assign the image to it. If you rather not implement that logic for image fetching in cells, you could use SDWebImage instead. Using SDWebImage's [UIImageView sd_setImageWithURL:] is thread safe (it will set the image on the main thread).
Side notes:
You only need to reload data once all your changes are in _restaurantInformationArray, and not every time in the for loop.
I have an iOS project with the following files inside it:
**PopOverContentViewController.h,
PopOverContentViewController.m,
MasterViewController.h,
MasterViewController.m,
DetailViewController.h,
DetailViewController.m.**
I created some buttons in PopOverViewController which have this method as their action:
- (void) buttonPressed
{
NSLog(#"The button was pressed");
UIWebView *myWebView = [[UIWebView alloc]
initWithFrame:self.detailViewController.view.bounds];
NSURL *myUrl = [NSURL URLWithString:#"http://www.lau.edu.lb"];
NSURLRequest *myRequest = [NSURLRequest requestWithURL:myUrl];
[myWebView loadRequest:myRequest];
[self.detailViewController.view addSubview:myWebView];
if ([self isInPopover])
{
[self.myPopOver dismissPopoverAnimated:YES];
}
}
The problem is that I am not seeing the webpage opening, the DetailviewController doesn't change.
Keep in mind I have the following lines written in PopOverContentViewController.h:
#class DetailViewController;
#property DetailViewController *detailViewController;
And that I have imported DetailViewController.h to the implementation file of PopOverViewController.
I tried loading a page from information in the masterviewcontroller and it appeared in the detailviewcontroller, but I'm clueless as to why it isn't working from the popover.
Thank you!
I have implemented a browser in my application by using UIWebView, by default I'm loading google page in my browser.
When I search something in the google page ,the UIWebViewDelegate's webView:shouldStartLoadWithRequest:navigationType: method is called.
The problem is when I tap on the back button from this search page no delegates are getting called, so I am having a problem disabling my back button.
This problem happens only in an iPad application not in an iPhone application.
This code may help u...
A UIWebView is a UIView that can load a web page while remaining in the user's application.
Navigation to other webpages is allowed through the use of imbedded links in a web page itself. Forward and backward navigation through history can be set up with instance methods goForward and goBack, but the programmer must supply the buttons.
The following example uses a UIWebView, and
1) adds forward and backward buttons. The buttons are enabled and highlighted using UIWebViewDelegate optional methods webViewDidStartLoad: and webViewDidFinishLoad:
2) adds a UIActivityIndicatorView which displays while the web page is loading
In the .h file for the WebViewController :
Declare the UIWebView, Optionally : add buttons to control moving forward and backward through browsing history and IBActions for pressing the buttons, Optionally again : add a UIActivityIndicatorView.
#interface WebViewController : UIViewController <UIWebViewDelegate>
{
UIWebView *webView;
UIButton *back;
UIButton *forward;
UIActivityIndicatorView *activityIndicator;
}
#property(nonatomic,retain)IBOutlet UIWebView *webView;
#property(nonatomic,retain)IBOutlet UIButton *back;
#property(nonatomic,retain)IBOutlet UIButton *forward;
#property(nonatomic,retain)IBOutlet UIActivityIndicatorView *activityIndicator;
-(IBAction)backButtonPressed: (id)sender;
-(IBAction)forwardButtonPressed: (id)sender;
#end
//In the .m file for the WebViewController
#implementation WebViewController
#synthesize webView;
#synthesize back;
#synthesize forward;
#synthesize activityIndicator;
//method for going backwards in the webpage history
-(IBAction)backButtonPressed:(id)sender {
[webView goBack];
}
//method for going forward in the webpage history
-(IBAction)forwardButtonPressed:(id)sender
{
[webView goForward];
}
//programmer defined method to load the webpage
-(void)startWebViewLoad
{
//NSString *urlAddress = #"http://www.google.com";
NSString *urlAddress = #"http://cagt.bu.edu/page/IPhone-summer2010-wiki_problemsandsolutions";
//Create a URL object.
NSURL *url = [NSURL URLWithString:urlAddress];
//URL Requst Object
NSURLRequest *requestObj = [NSURLRequest requestWithURL:url];
//Load the request in the UIWebView.
[webView loadRequest:requestObj];
}
// acivityIndicator is set up here
- (void)viewDidLoad
{
//start an animator symbol for the webpage loading to follow
UIActivityIndicatorView *progressWheel = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleGray];
//makes activity indicator disappear when it is stopped
progressWheel.hidesWhenStopped = YES;
//used to locate position of activity indicator
progressWheel.center = CGPointMake(160, 160);
self.activityIndicator = progressWheel;
[self.view addSubview: self.activityIndicator];
[self.activityIndicator startAnimating];
[progressWheel release];
[super viewDidLoad];
//call another method to do the webpage loading
[self performSelector:#selector(startWebViewLoad) withObject:nil afterDelay:0];
}
- (void)dealloc
{
[webView release];
[back release];
[forward release];
[activityIndicator release];
[super dealloc];
}
#pragma mark UIWebViewDelegate methods
//only used here to enable or disable the back and forward buttons
- (void)webViewDidStartLoad:(UIWebView *)thisWebView
{
back.enabled = NO;
forward.enabled = NO;
}
- (void)webViewDidFinishLoad:(UIWebView *)thisWebView
{
//stop the activity indicator when done loading
[self.activityIndicator stopAnimating];
//canGoBack and canGoForward are properties which indicate if there is
//any forward or backward history
if(thisWebView.canGoBack == YES)
{
back.enabled = YES;
back.highlighted = YES;
}
if(thisWebView.canGoForward == YES)
{
forward.enabled = YES;
forward.highlighted = YES;
}
}
#end
/*****************************/
//In viewDidLoad for the class which adds the WebViewController:
WebViewController *ourWebVC = [[WebViewController alloc] initWithNibName:#"WebViewController" bundle:nil];
ourWebVC.title = #"WebView";
[self.view addSubview:ourWebVC];
//release ourWebVC somewhere else
In your case ,You have to ignore/avoid "caching data". Following lines of code may help.
NSURLRequest *requestObj = [NSURLRequest requestWithURL:[NSURL URLWithString:#"http://www.google.com"] cachePolicy: NSURLRequestReloadIgnoringLocalAndRemoteCacheData timeoutInterval:10.0];
[webView loadRequest:requestObj];
In my project iPad, I have a TableView that opens in a popoverController, tableView have this particular company in each cell, which was clicking to the site clicked COMPANY,
but found means to launch the User descomodo out of going to the safari app.
As I already had one in my WebView viewController which is a site with background, I decided to make the site selected in the table open in the background of the app.
How are separate classes I need a way to access the webViewHome or simply call the function that loads the site with another parameter.
I tried to access in tableView.m as follows:
viewController *varViewController = [[viewController alloc]init];
.....
- (void)mostraSite:(NSString *)endereco{
NSURL *url = [NSURL URLWithString:endereco];
NSURLRequest *requestObj = [NSURLRequest requestWithURL:url];
[varViewController.webViewHome loadRequest:requestObj];
}
and each index of TableView call the function with a different parameter, but does not work.
if they have something to suggest I am grateful.
explaining more clearly
In my ViewController I have a webview.
eg
# import <UIKit/UIKit.h>
# interface iPhoneStreamingPlayerViewController: UIViewController
{
...
IBOutlet UIWebView * webViewHome;
...
}
# property (nonatomic, retain) UIWebView * IBOutlet webViewHome;
...
- (Void) mostraSite: (NSString *) address;
...
# end
the ... where I is Outlets and other functions. Not posted because it's just unnecessary.
I have a TabBar Controllers other that opens in a popover.
one of the items of the TabBar is a TableView that each cell contains a link, and when an item is selected, I want to open the site in the WebView I have in the ViewController.
in TableView,
imported the viewController
didSelectRowAtIndexPath and call the function passing the parameters as index
eg
viewController varViewController * = [[viewController alloc] init];
switch (indexPath.row) {
case 0:
[self mostraSite: # "http://www.radiobento.com.br"];
break;
calling the function
- (void) mostraSite: (NSString *) address {
NSURL * url = [NSURL URLWithString: address];
NSURLRequest requestObj * = [NSURLRequest requestWithURL: url];
[varViewController.webViewHome loadRequest: requestObj];
}