I try to run programm (http://www.edumobile.org/iphone/iphone-programming-tutorials/calculator-application-in-iphone/) from here, but i have problem with init method. While running programm don't creates variables (current, previous). Where is it call init-method in xCode?
the init method is never called because the ViewController is loaded from a nib file.
You could move those 3 lines into viewDidLoad. But to be honest, I think it's better when you trash the project and look for something better. Because this is not the only problem of the project.
If you learn with these "tutorials" you will have huge problems later.
That guy has obviously never heard about memory management.
But if you want to try, add this method to the #implementation of calciViewController
- (void)viewDidLoad {
[super viewDidLoad];
operator=0;
current =[[NSString stringWithString:#"0"]retain];
previous =[[NSString stringWithString:#"0"]retain];
}
Related
Random crashes occur in my iphone project, see two call stacks, all in web core, all crash after UIWebView deallocate.
See crash 1, seems web core can't close it completely, is it blocked by other running threads?
See crash 2, why it is still dealing with some issues even if UIWebView has been released?
Any idea or discussion will be appreciated, thanks in advance.
Crash 2 has higher reproducible rate than crash 1, scan WebCore source code, it seems be manifest cache has been deleted (who did it?) when try to access it.
My guess is that you're setting some object (probably your view controller) as the delegate of your webView, either via Interface Builder, or via code that looks something like this:
- (void)viewDidLoad
{
[super viewDidLoad];
self.webView.delegate = self;
}
- (void)dealloc
{
[self.webView release];
[super dealloc];
}
This code has a serious bug that's not immediately obvious if you don't know what to look for. Can you spot it?
When the controller gets dealloc'd it releases the webView, but this doesn't necessarily mean the web view no longer exists. It may still be retained by some code down inside its internal implementation, and it may still be loading content.
When it finishes loading, the web view will call a method like webViewDidFinishLoad: on its delegate. The problem is, your view controller was the delegate, and your view controller no longer exists. The section of memory where your view controller used to live has been reclaimed by the operating system, and is no longer accessible to your application process. The web view doesn't know this though. It still has a reference to that memory address in its delegate property. So it tries to call a delegate method on that object, and whoops... EXC_BAD_ACCESS.
Crashes like this appear to be random since they depend on what your app is doing in the background at the time. This makes them tricky to diagnose. Fortunately they're easy to solve. Simply set the object's delegate to nil before you release it your dealloc statement, like this:
- (void)dealloc
{
self.webView.delegate = nil;
[self.webView release];
[super dealloc];
}
By setting the web view's delegate to nil before you release it, you guarantee that the web view won't try to call delegate methods on your object after it's been deallocated.
If you're using ARC, your class may not have a dealloc method. That's normally fine, but in a case like this you should go ahead and add one. You don't want to call release if you're using ARC, but you should still add a dealloc method and set the delegate property to nil.
To avoid similar crashes in the future, apply this best practice any time you set your object as the delegate of another object.
Before releasing the webview, try to reset the delegate an stop loading.
[webView stopLoading];
webView.delegate = nil;
[webView release];
webView = nil;
I'm using ARC
In some tutorials I'm watching, he once made a UILabel and then in the method ViewDidUnload he wrote: self.theLabelVariable = nil;
I have not seen him write anything in ViewDidUnload again since then.. yet.
I'm a bit confused to what code is supposed to go in that method.
1.
What and when should I write in it?
It's commented:
"Release any retained subviews of the main view. E.g. self.myOutlet = nil;"
Not really sure what that's upposed to mean though
2.
It also has a "[super ViewDidUnload]" What does that do?
3.
Someone said "etting it to nil when you don't intend to use it again is a good idea".
But in the tutorial where someone wrote "self.TheLabelVariable = nil", when I hit the home button and then brought the app up again, everything worked fine.
Or is it not cViewDidUnload when you hit the home button?
I suppose the third question is: When is it called?
You should do this with all of your IBOutlets. You should set them all to nil. And [super viewDidUnload]; is unloading the superview! Its sort of like [super viewDidLoad];
1 - You should use viewDidUnload to release (set to nil if it's a property) any object that is not needed when the view is unloaded, like views, and that you'll recreate again on viewDidLoad. Example: You don't need a label when the view is unloaded (by pressing the home button), then you release it, and then you create it again when the view loads (app come up).
2 - [super something] calls the method on the super class. For example, if you have a class that is a descendant of UIViewController calling [super viewDidUnload] will execute the Apple's UIViewController viewDidUnload code (which might be empty... or not).
3 - See the example on 1. But the thing is: when you don't need an object anymore set it to nil so it can be released and you're not wasting memory.
Let me know if I missed something or if there's something you didn't understand.
EDIT
For views that are initialized from a XIB file (interface builder), called IBOutlets, you don't need to do self.label=nil; because UIViewController does it for you. Just like it initialized it for you, it will release it too.
Let me try and explain this. Within a project folder has .m and .h files (we all know that haha) however when you start a new ".m" with a xib like for example:
ViewTwoController *loginView = [[ViewTwoController alloc] initWithNibName:#"contentscreen" bundle:nil];
[self presentModalViewController:loginView animated:YES];
[loginView release];
I was wondering how do I create a method that runs as soon as that class (if I can call it that, I'm new to objective C) similar to a main method that Java would have. I want to run some code as soon as that .m has been called and started. Any help would be valued thanks :)
To be safe try to put this in - (void)viewDidLoad
Everything that happens here happens when the view is loaded onto the screen.
Note that there are number of places where you can put your method, in viewWillAppear or in your AppDelegate etc. But I found putting UI elements like your login popup better in viewDidLoad
Hope this helps...
You can add additional code in viewDidLoad method, which is called as soon as your view controller has been loaded.
Using the initWithNibName:bundle: method, your view controller will be automatically loaded and initialized.
I have deleted my nib file from my UIViewController and now I want to make it so that it calls init instead of initWithNibName. However, even after I deleted my UIViewController, it is still calling the initWithNibName. What do I need to do to change this so that it calls init?
I initialized the rest of the UIViewController via code, in my UITabBarController I have the following:
- (void)viewDidLoad
{
[self setTabURLs:[NSArray arrayWithObjects:#"tt://mygroup",
#"tt://all",
#"tt://search",
nil]];
}
Three20 framework always calls initWithNib, even if the TTViewController is created without a nib file.
Just move your initialization code into the - (void)loadView function as you need to.
Why does it matter to you what init method is called? Just take the code you would put in init and put it in initWithNibName:bundle.
Find where UIViewController is being allocated and initialized and change it to init instead of initWithNib.
I want to make a program that parses an XML file and then updates labels on 2 different tab bar views. On both of these views, I have a refresh button to update the results. What I'd like to do is update both of the views labels from either view. I figure the AppDelegate is probably a good choice to make this happen, but I tried creating classes that the AppDelegate can access but since they're instances of a class they contain no values. I get no errors but the labels don't update even though the data changes. This is the method in my AppDelegate that is called after the XML is parsed:
-(void)callUpdateValues {
NSLog(#"Calling Update from AppDelegate");
home *homeController;
data *dataController;
[homeController updateValues];
[dataController updateValues];
}
One of the update methods looks like:
- (void)updateValues {
NSLog(#"Call Home");
[label1 setText: [[[[totalData objectAtIndex:0] objectForKey:#"nodeChildArray"] objectAtIndex:7] valueForKey:#"nodeContent"]];
[label2 setText:[[[[totalData objectAtIndex:0] objectForKey:#"nodeChildArray"] objectAtIndex:1] valueForKey:#"nodeContent"]];
}
So the view calls the AppDelegate method "callUpdateValues" and then that method should call the individual "updateValues" methods in each view. I am not an expert on this by any means, and I'm really just trying to get an idea of how programming on the iPhone works. I'm probably just not understanding something here, and if someone could give me some sort of answer I'd appreciate it.
Cocoa has a number of classes available for notifying interested parties of changes. Directly calling methods as you describe makes things much more closely coupled than you need to.
In your method that generates the update you'd have:
[[NSNotificationCenter defaultCenter] postNotificationName:#"IGotSomeNewData"
object:newData
userInfo:nil];
And in the classes that want to hear about updates you'd register for the notification:
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(newStuff:)
name:#"IGotSomeNewData" object:nil];
And then implement the method that gets called when something happens:
- (void) newStuff: (NSNotification *)notification {
id newData = [notification object];
// Do stuff
}
There's some really great stuff getting done by Apple for XML on the iPhone: XML Reading Material
The first snippet is out of place. I think what you're missing is that you need to create your instances within the AppDelegate.h, expose them using properties (and synthesizing them in the .m). Then you're update structure should fit better.
If you're just picking up iPhone programming, start digging into the guides that apple provides, and even if you're not into that, start pulling down at least 5 sample code projects a day. The beauty of them is that you can build them (even onto your iphone) and if you like a feature, you can see how it's done. Alternatively, get the grapefruit book from APRESS. Beginning iPhone.
Hope this helped.
In the example you gave, homeController and dataController are not properly initialized. If I understand your project correctly, you would have created instances of the homeController and dataController classes in your main XIB file, and connected them up to the appropriate views (label1 and label2). Your AppDelegate should, then, look something like this:
...
#class homeController;
#class dataController;
#interface AppDelegate
{
IBOutlet homeController * home;
IBOutlet dataController * data;
}
...
#end
With this in place, you would add (in your application XIB file), links from your homeController and dataController instances to the appropriate outlets (labeled home and data) in your application delegate.
Then, you could simply reference them by name in your callUpdateValues method:
-(void)callUpdateValues {
NSLog(#"Calling Update from AppDelegate");
[home updateValues];
[data updateValues];
}
On a side note, Cocoa coding standards usually specify that class names are capitalized. This is, of course, up to your personal taste, but if you're just getting started in Cocoa, it may be worth drinking one more cup of kool-aid at this point, just so your code will "fit in" with what most other developers are doing. Again, totally up to you!