I am new to Objective-C. So I have a table view that leads to a webView. Some how the WebView won't load. In my view controller for the webView I have
NSURL *URL = [NSURL URLWithString:[self.url
stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]]];
NSURLRequest *request = [NSURLRequest requestWithURL:URL];
[self.webView loadRequest:request];
The TableView controller has
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
[tableView deselectRowAtIndexPath:indexPath animated:NO];
XYZToDoItem *tappedItem = [self.toDoItems objectAtIndex:indexPath.row];
[self performSegueWithIdentifier:#"showArticle" sender:nil];
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
if ([[segue identifier] isEqualToString:#"showArticle"]) {
I think I am missing something under prepareForSegue but I don't know.
Related
At first i just send data to server using GET method, I receive a response like below
2015-11-16 14:21:42.168 smartschool[1963:348015] Item actcode: ZQRTNN68
2015-11-16 14:21:42.169 smartschool[1963:348015] Item parentid: 8
How can i display the activation code to a label of the next viewController.
Here is my code:
#import "RegistrationViewController.h"
#interface RegistrationViewController ()
#end
#implementation RegistrationViewController
{
NSMutableData *mutableData;
#define URL #"http://192.168.1.166/bustracking/activation/requestActivationCode"
}
- (void)viewDidLoad
{
[super viewDidLoad];
}
-(IBAction)sendDataUsingGet:(id)sender{
[self sendDataToServer : #"GET"];
}
-(void) sendDataToServer : (NSString *) method
{
NSString *parentName = parent_name.text;
NSString *contactNumber = contact_number.text;
NSString *beaconid = #"145801000095";
//NSString *beaconMacAdd = #"14:58:01:00:00:95";
if(parentName.length > 0 && contactNumber.length > 0){
NSLog (#"Getting response from server...");
NSMutableURLRequest *request = nil;
// Only Difference between POST and GET is only in the way they send parameters
if([method isEqualToString:#"GET"]){
NSString *getURL = [NSString stringWithFormat:#"%#?parent_name=%#&contact_number=%#&beacon_id=%#", URL, parentName, contactNumber, beaconid];
//url = [NSURL URLWithString: getURL];
getURL = [getURL stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
NSURL *url = [NSURL URLWithString: getURL];
request = [NSMutableURLRequest requestWithURL:url];
NSLog(#"urlinfo: %#", url);
NSLog(#"link: %#", getURL);
}
[request setHTTPMethod:method];
[request addValue: #"application/x-www-form-urlencoded; charset=utf-8" forHTTPHeaderField:#"Content-Type"];
NSURLConnection *connection = [[NSURLConnection alloc] initWithRequest:request delegate:self];
NSLog(#"connection: %#", connection);
if( connection )
{
mutableData = [NSMutableData new];
}
else
{
NSLog (#"NO_CONNECTION");
return;
}
}
else
{
NSLog(#"NO_VALUES");
}
}
#pragma mark NSURLConnection delegates
-(void) connection:(NSURLConnection *) connection didReceiveResponse:(NSURLResponse *)response
{
[mutableData setLength:0];
}
-(void) connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
{
[mutableData appendData:data];
}
-(void) connection:(NSURLConnection *)connection didFailWithError:(NSError *)error
{
NSLog (#"NO_CONNECTION");
return;
}
-(void)connectionDidFinishLoading:(NSURLConnection *)connection
{
NSError *error = nil;
NSDictionary *json = [NSJSONSerialization JSONObjectWithData:mutableData options:kNilOptions error:&error];
NSArray *fetchedArr = [json objectForKey:#"response"];
NSString *responseActCode;
for (NSDictionary *user in fetchedArr)
{
responseActCode = [user objectForKey:#"activation_code"];
NSLog(#"Item actcode: %#", responseActCode);
NSLog(#"Item parentid: %#", [user objectForKey:#"parent_id"]);
//NSLog(#"Item actcode: %#", [user objectForKey:#"activation_code"]);
}
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
[defaults setObject:responseActCode forKey:#"HighScore"];
[defaults synchronize];
NSLog(#"from data: %#", [defaults objectForKey:#"HighScore"]);
UIAlertView *alert = [[UIAlertView alloc]
initWithTitle:#"Activation Code"
message:(#"%#", responseActCode)
delegate:nil //or self
cancelButtonTitle:#"OK"
otherButtonTitles:nil];
[alert show];
}
#end
If the returning data is in dictionary format, declare nsdictionary in header.h class on which you wan to transfer data, similarly you can use array and string, now if you are using a storyboard, below is the method.
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
// Make sure your segue name in storyboard is the same as this line
if ([[segue identifier] isEqualToString:#"YOUR_SEGUE_NAME_HERE"])
{
// Get reference to the destination view controller
YourViewController *vc = [segue destinationViewController];
// Pass any objects to the view controller here, like...
vc.dictionary = self.dictionary.
}
}
and you want to transfer data upon cell tap this is what you have to do.
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
[self performSegueWithIdentifier:#"YOUR_SEGUE_NAME_HERE"" sender:self];
}
When "performSegueWithIdentifier" is called, this method automatically redirected to "prepareForSegue" method:
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
NSIndexPath *indexPath= [self.tableView indexPathForSelectedRow];
// Make sure your segue name in storyboard is the same as this line
if ([[segue identifier] isEqualToString:#"YOUR_SEGUE_NAME_HERE"])
{
// Get reference to the destination view controller
YourViewController *vc = [segue destinationViewController];
// Pass any objects to the view controller here, like...
now this time its array.
vc.array= [array[indexpath.row] valueforkey#"jsonkey"];
}
}
There are many ways to pass data between view controllers. Here's one example:
Create a public property in "SomeViewController" class(eg: responseActCodeString) and set that property to your activation code(eg: responseActCode).
SomeViewController *someViewController = [[SomeViewController alloc] initWithNib:#"SomeViewController " bundle:nil];
someViewController.responseActCodeString = responseActCode;
[self pushViewController:someViewController animated:YES];
You can also use notifications, user defaults as an alternatives.
Also look at this link.
For storyboards add following method in initial view controller:
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender{
if([segue.identifier isEqualToString:#"someIdentifier"]){
SomeViewController*someViewController= (SomeViewController*)segue.destinationViewController;
someViewController.responseActCodeString = responseActCode;
}
}
I am fetching images synchronously from an array which stores URLs of images but it work very slowly. Now i want to load them asynchronously for fast working.
Heres the code and provide answer with coding.
#import "DetailViewController.h"
#import "FinalViewController.h"
#interface DetailViewController ()
#end
#implementation DetailViewController
#synthesize jsonData;
- (void)viewDidLoad {
[super viewDidLoad];
self.title = #"Select a Photo";
// Do any additional setup after loading the view.
[UIApplication sharedApplication].networkActivityIndicatorVisible = YES;
NSURL *url = [NSURL URLWithString:#"http://json.code.com/albums/1/photos"];
NSURLRequest *request = [NSURLRequest requestWithURL:url];
[[NSURLConnection alloc] initWithRequest:request delegate:self];
}
-(void)connection:(NSURLConnection *)connection didReceiveResponse:(nonnull NSURLResponse *)response
{
data1 = [[NSMutableData alloc] init];
}
-(void)connection:(NSURLConnection *)connection didReceiveData:(nonnull NSData *)theData
{
[data1 appendData:theData];
}
-(void)connectionDidFinishLoading:(NSURLConnection *)connection
{
[UIApplication sharedApplication].networkActivityIndicatorVisible = NO;
jsonArray1 = [NSJSONSerialization JSONObjectWithData:data1 options:nil error:nil];
[mainTableView reloadData];
}
-(void)connection:(NSURLConnection *)connection didFailWithError:(nonnull NSError *)error
{
UIAlertView *errorView = [[UIAlertView alloc]initWithTitle:#"Error" message:#"Please make sure you are connected to either 3G or Wi-Fi." delegate:nil cancelButtonTitle:#"Dismiss" otherButtonTitles:nil, nil];
[errorView show];
[UIApplication sharedApplication].networkActivityIndicatorVisible = NO;
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (int)numberOfSectionInTableView:(UITableView *)tableView
{
return 1;
}
- (int) tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return [jsonArray1 count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(nonnull NSIndexPath *)indexPath
{
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"Cell"];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:#"Cell"];
}
cell.textLabel.text = [[jsonArray1 objectAtIndex:indexPath.row] objectForKey:#"title"];
cell.detailTextLabel.text = [NSString stringWithFormat:#"URL : %#", [[jsonArray1 objectAtIndex:indexPath.row] objectForKey:#"url"]];
NSURL *URL = [[NSURL alloc] initWithString:[[jsonArray1 objectAtIndex:indexPath.row] valueForKey:#"thumbnailUrl"]];
NSData *URLData = [[NSData alloc] initWithContentsOfURL:URL];
[[cell imageView]setImage:[UIImage imageWithData:URLData]];
return cell;
}
-(void)tableView:(UITableView *)tableview didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
FinalViewController *fvc = [[FinalViewController alloc] initWithNibName:#"FinalViewController" bundle:nil];
fvc.jsonData2 = [jsonArray1 objectAtIndex:indexPath.row];
[self.navigationController pushViewController:fvc animated:YES];
}
#end
We can use dispatch_async to run the operation asynchronously.
Try this:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
myCell *cell = [tableView dequeueReusableCellWithIdentifier:#"cell"];
if (cell == nil) {
cell = [[myCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:#"cell"];
}
cell.poster.image = nil; // or cell.poster.image = [UIImage imageNamed:#"placeholder.png"];
dispatch_async(kBgQueue, ^{
NSData *imgData = [NSData dataWithContentsOfURL:[NSURL URLWithString:[NSString stringWithFormat:#"http://myurl.com/%#.jpg",[[myJson objectAtIndex:indexPath.row] objectForKey:#"movieId"]]]];
if (imgData) {
UIImage *image = [UIImage imageWithData:imgData];
if (image) {
dispatch_async(dispatch_get_main_queue(), ^{
myCell *updateCell = (id)[tableView cellForRowAtIndexPath:indexPath];
if (updateCell)
updateCell.poster.image = image;
});
}
}
});
return cell;
}
You can do like this:
cell.tag = indexPath.row;
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0ul);
dispatch_async(queue, ^(void) {
NSData *imageData = [NSData dataWithContentsOfURL: URL];
UIImage* image = [[UIImage alloc] initWithData:imageData];
if (image) {
dispatch_async(dispatch_get_main_queue(), ^{
if (cell.tag == indexPath.row) {
cell.imageView.image = image;
[cell setNeedsLayout];
}
});
}
});
Ref: Asynchronous downloading of images for UITableView with GCD
Just by simply setting the following works fine for me .
cell.imageView.image =[UIImage imageWithData:[NSData dataWithContentsOfURL:[NSURL URLWithString:[NSString stringWithFormat:#"%#",[imageArray objectAtIndex:i]]]]];
You can use the activity indicator as you have asked . Just drag and drop UIActivityIndicatorView onto the UIImageView of the UITableViewCell and set the needed constraints . Once the image gets loaded you can set it as hidden .
To do it programmatically , you can add a subview to the Image view in the UITableViewCell. Once the Image gets loaded you can remove the sub view .
UIActivityIndicatorView* actInd = [[UIActivityIndicatorView alloc]init];
[cell.imageView addSubview:actInd];
When my web viewDidLoad fires it correctly sets the starting URL for my web view and logs "Load Request: http://xxxxxx.dev/login". Just as you would expect.
When calling loadRequestFromString from SidebarViewController, the webview does not change to the correct URL. However, thanks to NSLog I can see that it is getting to that point just not refreshing the URL "Load Request: http://xxxxxx.dev/this-is-the-url-that-should-load".
SidebarViewController.m
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{
[tableView deselectRowAtIndexPath:indexPath animated:YES];
NSString *url = self.tableData[indexPath.row][#"url"];
[self.revealViewController setFrontViewPosition: FrontViewPositionLeft animated: YES];
WebAppViewController *wvc = [[WebAppViewController alloc] initWithNibName:#"webappController" bundle:kNilOptions];
[wvc loadRequestFromString:url];
}
WebAppViewController.m
- (void)viewDidLoad
{
[super viewDidLoad];
self.webView.delegate = self;
// Do any additional setup after loading the view, typically from a nib.
[self loadRequestFromString:#"http://xxxxxx.dev/login"];
}
.....
- (void)loadRequestFromString:(NSString*)urlString
{
self.webView.delegate = self;
NSLog(#"Load Request: %#", urlString);
NSString *properlyEscapedURL = [urlString stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
NSURL *url = [NSURL URLWithString:properlyEscapedURL];
NSURLRequest *urlRequest = [NSURLRequest requestWithURL:url];
[self.webView loadRequest:urlRequest];
}
I have two view controllers connected by a modal segue. The destination controller also has a UIWebView.
Reading the docs I would like to elect the first controller to be responsible for dismissing the webview controller and my action for doing so would be in a webview delegate method.
I'm trying this:
First controller:
#interface ABISignInViewController : UIViewController <UIWebViewDelegate>
...
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
...
} else if ([[segue identifier] isEqualToString:#"showWebViewForSignUp"]) {
ABIWebBrowserViewController *webViewController = (ABIWebBrowserViewController *)segue.destinationViewController;
[webViewController.webView setDelegate:self];
[webViewController setUrlString:#"https://myurl"];
}
}
- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType {
NSLog(#"%#", request);
return YES;
}
The second controller fires up and start loading the requested url:
- (void)viewDidAppear:(BOOL)animated {
NSURL *url = [NSURL URLWithString:self.urlString];
NSURLRequest *requestObj = [NSURLRequest requestWithURL:url];
[self.webView loadRequest:requestObj];
}
However the delegate method in the first controller is never called.
Any directions?
Why not pass the URL as an NSString or an NSURL and then let the ViewController with the WebView handle the delegate methods?
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
...
} else if ([[segue identifier] isEqualToString:#"showWebViewForSignUp"]) {
ABIWebBrowserViewController *webViewController = (ABIWebBrowserViewController *)segue.destinationViewController;
webViewController.urlString = #"https://myurl";
}
}
WebView ViewController:
- (void)viewDidAppear:(BOOL)animated {
NSURL *url = [NSURL URLWithString:self.urlString];
NSURLRequest *requestObj = [NSURLRequest requestWithURL:url];
[self.webView loadRequest:requestObj];
}
- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType {
NSLog(#"%#", request);
return YES;
}
I am trying to push to a new view and send a url to the webview in that view but it's not getting the url request. storyLink is declared earlier on, but even if I try to request http://www.google.com it doesn't even work either, so I know the problem is it's not accepting the url for some reason.
DetailViewController *newviewController=[[[DetailViewController alloc] initWithNibName:#"DetailViewController" bundle:nil]autorelease];
NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:storyLink]];
[newviewController.rssview loadRequest:request];
[self.navigationController pushViewController:newviewController animated:YES];
Better you declare a property in next view for NSURL and set the value from the parent view.
For example, set following code in your DetailViewController.h file
#interface DetailViewController : UIViewController
{
NSURL *request;
}
#property (nonatomic, assign) NSURL *request;
In your DetailViewController.m file...
#synthesize request;
And modify your current code as below...
DetailViewController *newviewController=[[[DetailViewController alloc] initWithNibName:#"DetailViewController" bundle:nil]autorelease];
NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:storyLink]];
newviewController.request = request;
//[newviewController.rssview loadRequest:request];
[self.navigationController pushViewController:newviewController animated:YES];
In reference to your code...:
Following are some missing things that you have to modify in your code and it will start working fine.
Set delegate for UIWebview control.
self.rssview.delegate = self;
[self.rssview loadRequest:self.request];
In your DetailViewController.h, modify following lines.
#interface DetailViewController : UIViewController <UIWebViewDelegate>
{
IBOutlet UIWebView *rssview;
NSURLRequest *request;
}
#property(nonatomic, retain, readonly)UIWebView *rssview;
#property (nonatomic, assign) NSURLRequest *request;
#end
In DetailViewController.m add delegate method of UIWebview as given below...
- (BOOL)webView:(UIWebView *)myWebView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType
{
return YES;
}
Replace following code in
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
int storyIndex = [indexPath indexAtPosition: [indexPath length] - 1];
NSString * storyLink = [[stories objectAtIndex: storyIndex] objectForKey: #"link"];
// clean up the link - get rid of spaces, returns, and tabs...
storyLink = [storyLink stringByReplacingOccurrencesOfString:#" " withString:#""];
storyLink = [storyLink stringByReplacingOccurrencesOfString:#"\n" withString:#""];
storyLink = [storyLink stringByReplacingOccurrencesOfString:#" " withString:#""];
storyLink = [storyLink stringByAddingPercentEscapesUsingEncoding: NSStringEncodingConversionAllowLossy];
NSLog(#"link: %#", storyLink);
if(indexPath.row==0)
{
DetailViewController *newviewController=[[[DetailViewController alloc] initWithNibName:#"DetailViewController" bundle:nil]autorelease];
NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:storyLink]];
//[newviewController.rssview loadRequest:request];
newviewController.request = request;
[self.navigationController pushViewController:newviewController animated:YES];
}
else
{
DetailViewController *newviewController=[[[DetailViewController alloc] initWithNibName:#"DetailViewController" bundle:nil]autorelease];
NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:storyLink]];
//[newviewController.rssview loadRequest:request];
newviewController.request = request;
[self.navigationController pushViewController:newviewController animated:YES];
}
}