I am trying to call a web service on page load. Currently I call it on a button click and it works fine. But when I try to do the same on viewDidAppear, it doesn't happen. What i want to achieve is if username and password are saved then it should automatically load the next page. It is filling in the text boxes but not loading the next page.
Here is my code for submit button and ViewDidAppear:
-(IBAction)submitButton{
[apd showCoverView:YES WithActivityIndicator:YES];
PlaceWebService *handler = [[PlaceWebService alloc]init];
[handler setRequestType:Loginparser];
NSString *url = [NSString stringWithFormat:#"http://www.mywebsite.com/api.php?command=auth&cardno=%#&password=%#",username.text,password.text];
[handler sendingLoginRequest:url Respond:self At:#selector(showParsed:)];
}
and for viewDidAppear
-(void)viewDidAppear:(BOOL)animated
{
NSLog(#"Appeared");
[self loginArea];
apd=[[UIApplication sharedApplication]delegate];
NSString *filepath=[self pathOfFile];
if([[NSFileManager defaultManager]fileExistsAtPath:filepath])
{
NSArray *array=[[NSArray alloc]initWithContentsOfFile:filepath];
username.text=[array objectAtIndex:0];
password.text=[array objectAtIndex:1];
[self submitButton];
}
}
What should I do? Please help...
If you want to call the method after loading view and without any event, then you need to that as normal instance method instead of IBAction method.
-(Void)submitButton{
// implementation
}
and then call this method from viewDidAppear.
A couple things could be the problem here.
1)
IBActions usually take a parameter. Declare it as:
- (IBAction) submitButton: (id) sender;
And then call it from your viewDidAppear method as:
[self submitButton: self];
2)
Also make sure UI stuff is happening on the main thread (you didn't specify if the app is multi threaded or not), so maybe:
[self performSelectorOnMainThread: #selector(submitButton:) withObject: self];
And
3)
Set breakpoints to see if your submitButton method (and the lines before it) are actually even called when viewFromAppear: is called.
And Rishi's suggestion is good, too!
Related
I have this piece of code to push a view controller:
// Setup the animation
[self.navigationController pushViewController:self.productView animated:YES];
self.productView.imageURL = [product imageURL];
// Set the title of the view to the product's name
self.productView.title = [product name];
// Set the label text of all the labels in the view
[self.productView.caloriesL setText:[product calories]];
[self.productView.fatL setText:[product fat]];
[self.productView.saturatesL setText:[product saturates]];
[self.productView.sugarL setText:[product sugar]];
[self.productView.fibreL setText:[product fibre]];
[self.productView.saltL setText:[product salt]];
But the delegate method viewDidAppear does not get called when the productView appears. I looked up the problem on google and theres a lot of different solutions, none of which I could apply to my problem.. I had a similar problem in a previous solution but I got around it by manually calling viewDidApear in the viewDidLoad method. Unfortunately in this case I can't do that as viewDidLoad is called only once (on the first push). Does anyone know how to fix this?
Thanks,
Jack Nutkins
EDIT:
Here is the viewDidAppear method in the productView (and selector):
- (void)viewDidAppear:(BOOL)animated{
//Start animating the activity indicator
[indicator startAnimating];
//Perform this method in background
[self performSelectorInBackground:#selector(loadImage) withObject:nil];
}
- (void) loadImage {
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
// Load the animals image into a NSData boject and then assign it to the UIImageView
NSData *imageData = [NSData dataWithContentsOfURL:[NSURL URLWithString:imageURL]];
UIImage *image = [[UIImage alloc] initWithData:imageData];
self.imageView.image = image;
//Stop animating the activity indicator
[indicator stopAnimating];
[pool drain]; //see comment below
}
First: You definitely don't want to be calling any of the standard viewWillLoad, viewDidLoad, viewWillAppear, etc. methods manually. Let the OS do it for you.
Second: Can you show us how your viewDidAppear method is implemented in your self.productView instance? (Just a hunch, you're not expecting this method to be called on your navigation controller, right?) I just want to make sure your method signature is exactly correct. If it's not (due to a mispelling, improper args, etc.) then it definitely won't be called.
Third: I would move your pushViewController: call to after the rest of the code you provided. You don't want the view to be pushed on the screen (so the user can see it) and then have a bunch of on-screen values immediately change. Set your ivars and title property first, then push the view controller. This eliminates any weird flickering.
I solved it, though it doesn't seem conventional, can't believe I didn't try it earlier :
I put this line :
[self.productView viewDidAppear:YES];
Underneath :
// Setup the animation
[self.navigationController pushViewController:self.productView animated:YES];
I also moved the code to set the labels text to run before the above line. (As well as changing my code to send strings to the pushed controller rather that accessing its UI elements.)
Thanks for everyones help,
Jack
Help, I'm deperate..i can't continue my app because of this:
I have setup one message between 2 of my cocoa objective-c clases,
the main appdelegate is messaging a view through NSNotificationCenter
the view receives indeed the notification but somehow it can't update the controls visible on the view.. it's like it can't find the proper instance or something.
here's my code:
mainapp (where the appdelegate messages my view):
helloKey = #"0";
helloString = #"mymessage";
values = [NSMutableDictionary dictionaryWithObject:helloString forKey:helloKey];
[[NSNotificationCenter defaultCenter] postNotificationName:#"NewMessageNotification" object:self userInfo:values];
the function is defined in myuiviewcontoler
- (void)NewMessageNotification:(NSNotification *)notification
{
// key associated with string "Hello String"
helloKey = #"0";
// [notificaiton userInfo] returns "values"
helloFromMain = [[notification userInfo] objectForKey:helloKey];
NSLog(#"newmess=%#",helloFromMain; //this outputs mymessage , perfect right?? not quite..here's the problem
//then if I'm trying to update something visible ..it won't do IT!!!! :( :(
//tested with the debugger and it reaches this line...when the messaging occurs
[self.mybutton setTitle:#"sdsdsdasd" forState:UIControlStateNormal];
//this won't work, not it will give an error!!!
}
So what could it be the problem? nothing that is visible can be modified programaticaly when using this, and I kid of need that..
If I do a IBAction and assign it to a button of this view and do the same :
[self.mybutton setTitle:#"sdsdsdasd" forState:UIControlStateNormal];
it will update my display without no problem... modifying the title...
So what's the difference between the function that is called by the NSnotificationcenter and a function that belongs to the same view...
I tried to see the address of the self variable in both cases,, it results to be the same...
so ..basically uses the same pointer right?
still it doesn't work...
I've put another post back a few days ago..but no-one answered
Programatically created labels and images don't show on screen
It sounds very much like your NewMessageNotification: method is not being called on the main thread; UI updates must only be done from the main thread, or things won't work correctly.
The usual idiom for a situation like this is something along these lines:
- (void)NewMessageNotification:(NSNotification *)notification
{
if (![NSThread isMainThread]) {
[self performSelectorOnMainThread:#selector(NewMessageNotification:) withObject:notification waitUntilDone:NO];
return;
}
// Existing code goes here
}
It sounds like you probably have two different instances of your class, one of which is hooked up to all the stuff in the nib and one of which is registering for the notification. Try logging self in that method and you'll probably see different object addresses when it's triggered by the notification versus the button.
Im having trouble with my code, it seems that it never executes right.
I've tried many things from UIActivity, Sliders, UITextVieweer etc... but it never changes,
The code is running using Navigation based application from xCode. loadingTview is a Textview,
The problem is, see where loadingTview is, that never works, it always hangs, the user presses a button, and this code is executed. The loadingTview is a Textview saying "loading" with a alpha of 0.4 so basiclly whilst its downloading the image form the website, people know its loading.
I tried views as well but same issue.
How can i progress?
loadingTview.hidden = false;
today = [NSDate date];
dateFormat = [[NSDateFormatter alloc] init];
[dateFormat setDateFormat:#"dd-MM-yyyy"];
dateString = [dateFormat stringFromDate:today];
if (PageEntered == #"page1")
{
NSString *url = [NSString stringWithFormat:#"http://www.imagegoeshere.com/%#.jpg",dateString];
imageURL = [NSURL URLWithString:url];
imageData = [NSData dataWithContentsOfURL:url];
image = [UIImage imageWithData:imageData];
FullScreenImage.image = image;
loadingTview.hidden = true;
[navigationController pushViewController:vFullscreen animated:YES];
}
I'm not sure entirely what the problem is but I assume that when you go from view2 to view3 it 'hangs' on view2 until the image is loaded before actually opening view3 to show the loading screen, right?
If that's the case, then what you want to do is load your image in a different thread so that the loading doesn't block the view3 from showing the loading screen.
Have a look at NSThread (although there are cleaner/better ways to do this).
Basically do this in view3's controller:
- (void) viewDidLoad {
// <First, show your 'Loading...' screen here>
// Then create a thread to load the image:
[NSThread detachNewThreadSelector:#selector(loadImage) toTarget:self withObject:nil];
}
// Then somewhere in the same class define the loading method:
- (void)loadImage {
// Remember to create a new autorelease pool for this thread.
// <Load your image here>
// When image is done loading, call the main thread
[self performSelectorOnMainThread:#selector(imageDoneLoading) withObject:nil waitUntilDone:YES];
}
// Then define the method to call when the image is done
- (void) imageDoneLoading {
// Hide the 'Loading...' screen.
}
If this is not the problem you have, then please provide more detail as to what is actually happening and what the problem is.
Good luck.
I don't really understand your question, but I do see something that's almost certainly wrong. This line:
if (PageEntered == #"page1")
should be this:
if ([PageEntered isEqualToString:#"page1"])
Objective-C doesn't do operator overloading, so your code is doing a pointer comparison, not a value comparison.
Whenever the user scrolls map or zooms in/out, this method gets called instantaneously. I want to delay the call to this method by say 2 secs. Is it possible to do that?
You could implement that method like this:
-(void)mapView:(MKMapView *)mapView regionDidChangeAnimated:(BOOL)animated
{
NSNumber *animatedNumber = [NSNumber numberWithBool:animated];
NSArray *args = [[NSArray alloc] initWithObjects:mapView,
animatedNumber,nil];
[self performSelector:#selector(delayedMapViewRegionDidChangeAnimated:)
withObject:args
afterDelay:2.0f];
[args release];
}
Then, somewhere in the same class:
-(void)delayedMapViewRegionDidChangeAnimated:(NSArray *)args
{
MKMapView *mapView = [args objectAtIndex:0];
BOOL animated = [[args objectAtIndex:1] boolValue];
// do what you would have done in mapView:regionDidChangeAnimated: here
}
Of course, if you don't need one of those arguments (either mapView or animated), you could make this considerably simpler by only passing the one you did need.
If you can't just edit the code for your MKMapViewDelegate, perhaps you could do something similar with method swizzling, although then you're getting really hacky.
You can send a delayed message with performSelector:withObject:afterDelay: or one of its related methods.
following situation:
in a TTTableViewController i added some Cells with URLs.
they are opening a class with #"tt://photos" for example. this works quite fine.
the first thing is, i saw some urls in TT Examples like #"tt/photos/1". is it possible to fetch this "1" in my photos class and say, for example okay, please open picture one, ore is this only another URL that was declared in TTNavigatior to open a specific Class?
the other thing is: is it possible to forward an object to the linked class?
clicking a cell opens #"tt://photos" (the linked class in my TTNavigator)
working with normal tableviews i can overwrite my init method and send an object with my initialize method, is this also possible by clicking my TTItems?
thanks!
figured it out myself, for those who need it:
First (passing "subURLs" in your navigator map)
navigating to an URL with #"tt://photos/firstphoto" is possible, you can fetch the "firstphoto" like this:
//Prepare your Navigator Map like this
[map from:#"tt://photos/(initWithNumber:)" toViewController:[PhotoVC class]];
In your PhotoVC you can access this Number:
-(void) initWithNumber: (NSString*)number {
NSLog(#"%#",number);
}
calling your View Controller with this url would look:
PhotoVC* controller = [[PhotoVC alloc] initWithNumber:#"1"];
[navigationController pushViewController:controller animated:YES];
[controller release];
Second (passing objects in an TTTableViewController)
its a bit tricky, but you dont have to Subclass anything.
first, nil the URL in the TableItem
[TTTableLink itemWithText:#"TTTableLink" URL:nil]
in your TTTableViewController write down this method
- (void)didSelectObject:(id)object atIndexPath:(NSIndexPath*)indexPath {
TTURLAction *urlAction = [[[TTURLAction alloc] initWithURLPath:#"tt://photos"] autorelease];
urlAction.query = [NSDictionary dictionaryWithObject:#"firstphoto" forKey:#"photo"];
urlAction.animated = YES;
[[TTNavigator navigator] openURLAction:urlAction];
}
now in your your PhotoVC you need something like this
- (id)initWithNavigatorURL:(NSURL*)URL query:(NSDictionary*)query {
if (self = [super init]) {
NSLog(#"%#",query);
}
return self;
}
and you are done ;)
I was trying to implement choise's answer, learned a lot, and eventually had to get the callouts showing up and keep the implementation with many urls simple, so here's what i did.
Keep URL in the TableItem,
Use this code in the TTTableViewController subclass.
- (void)didSelectObject:(id)object atIndexPath:(NSIndexPath*)indexPath {
NSLog(#"Its url is %#", [object URL]);
TTURLAction *urlAction = [[[TTURLAction alloc] initWithURLPath:(NSString *)[object URL]] autorelease];
urlAction.query = [NSDictionary dictionaryWithObject:self.user forKey:#"user"];
urlAction.animated = YES;
[[TTNavigator navigator] openURLAction:urlAction];
}
- (BOOL)shouldOpenURL:(NSString*)URL {
return NO;
}
That "shouldOpenURL:" was discovered looking through TTTableViewController, I tried it out, and it worked. Now the table view is not opening a duplicate view, and there are callouts!
Thanks choise!
Although choice's answer works for multiple params when u are creating the TTURLAction in code it is not very useful when u want to embed links to view controllers in your TTStyledLabel.One solution to that is to use multiple params in a single string.
<a href='app://view2/param1=value1¶m2=value2&...'>LabelName</a>
if you want the code to parse such urls and get the params please feel free to send me a message and I will send you my parser classes.
(or you can build your own with NSScanner!)
Also dont forget to escape the &s otherwise TTStyledLabel would not like it!
You don't need to run this on current version 1.0.6.2 for TTTableViewController. The "URL" option is working as expected. If it's not working for you, then your URL is broken or your are calling the wrong function on your ViewController. The function you have to call through URL must return an id (be a constructor for a ViewController) of a ViewController. Then it'll work as expected.
I'll changed the example form choise to be like TTNavigator expect it to be.
Add a mapping, which TTNavigator will use to navigate:
//Prepare your Navigator Map like this
[map from:#"tt://photos/(initWithNumber:)" toViewController:[PhotoVC class]];
Create a TTTableLink (or TTStyledText, or other) with an URL set, which should mach your map:
[TTTableLink itemWithText:#"TTTableLink" URL:#"tt://photos/1"]
Add this to your PhotoVC to be called by TTNavigator on the given URL
-(id) initWithNumber: (NSString*)number {
if (self = [super init]) {
self.title = #"Some Title";
NSLog(#"%#",number);
}
return self;
}
You don't need to overwrite the function didSelectObject, as the TTNavigator will call your ViewController through defined constructor function tt://photos/(initWithNumber:)