I have a categories class which I put the the image and some color categories that I resuse over the project, I simply use them like:
UIImageView *anImageView = [[UIImageView alloc] initWithFrame: [[UIScreen mainScreen] applicationFrame]];
anImageView.image = [UIImage APP_IMAGE_BCKGROUND];
[window addSubview:anImageView];
[anImageView autorelease];
But I have some memory problems, is this way of category usage is a good practise? or how can I define the pictures in a seperate class and memory efficent way?
Yes, the approach you are taking is good practice. The alternative would be to create a UIImageManager class which does essentially the same thing. When given these types of alternatives, I typically choose to use categories, unless I find myself adding many new methods to support my requirements. In that case I'll create a separate class. But what you have there looks fine.
There are no leaks in your code. What memory problems are you having?
Related
If I have a property like this:
#property (nonatomic, retain) UILabel* lblUsername;
Should I in viewDidLoad do this:
self.lblUsername = [[[UILabel alloc] init...] autorelease];
self.lblUsername.text = #"A label";
self.lblUsername....
Or should I do this:
UILabel* usernameLabel = [[UILabel alloc] init...];
usernameLabel.text = #"A label";
usernameLabel....
self.lblUsername = usernameLabel;
[usernameLabel release];
I have seen both and I am unsure which I should use, any benefits of using one over another? (I know both are "correct" in syntax and both work, but which is preferred?)
I prefer the second method. The only real benefit is reducing stress on the autorelease pool, which is minimal if only initializing a few objects like this. It's unlikely that you are modifying that property on another thread that could potentially cause unintended behavior if using the first method, but I suppose that is a risk. To me it also seems to be the difference of building a component and then installing it versus installing an unfinished component then building it in place.
I'd go for the second one every time. Besides the important fact that it makes little sense to stick half-constructed objects in your public interface (even if you don't yet have a codepath that could expose the bug), the second way is more efficient with zero cost. For every self.thing.otherThing =, you're sending a minimum of two messages, and more if you someday get KVO involved. There is absolutely no benefit to that indirection — it doesn't make your code read more clearly, it doesn't make it more concise, it doesn't make it safer, nothing.
Generally speaking, when should you make a variable in Objective C an instance variable?
For instance, say I got an UIViewController with an UILabel. In what cases would I have the UILabel as an instance variable vs doing something like this:
UILabel *label = [[UILabel alloc] init];
//set text of label
[view.addSubview label];
[label release];
If you need a moderately persistent handle on any resource, you should make it an instance variable, if the resource in question should remain at least moderately persistent.
In the example above, then yes; the label should be an instance variable, probably one assigned using an IBOutlet.
Generally speaking, most things that live in UIKit (as opposed to Foundation) benefit from being instantiated through NIB files and subsequently accessed through outlets.
This isn't solely a performance issue; it also has to do with memory management and fragmentation, as well as simplifying, in most cases, translation and internationalization.
To your specific case, if you are going to need to access that label at a later point in time (say to change the text) keeping an ivar will save you some effort trying to find it again.
General reasons would be for persistence, scope, and convenience.
In your particular example, the object is written as a variable so that it can be sent a release message after adding it to a view (which retains it).
The equivalent code without a variable is:
[view addSubview:[[[UILabel alloc] init] autorelease]];
We don't need to send a release, because we're autoreleasing the object.
I need to draw something on an image, like in the GLPaint sample from Apple, but I need to create the EAGL surface where render the OpenGL programmatically.
In the sample is instatiated in the MainWindow.xib
If I try to create the view programmatically with something like:
self.drawingView = [[PaintingView alloc] initWithCoder:nil];
drawingView.frame = CGRectMake(0, 0, 320, 380);
[self.view addSubview:drawingView];
I got this error:
failed to make complete framebuffer object 8cd6
Maybe something related to the init? Any hints? Thanks.
From a quick glance inside the source, Apple have put all of the significant initialisation stuff for PaintingView inside initWithCoder:, from lines 77 to 168. That's part of the NSCoding protocol, which is used for archiving and unarchiving objects from files. If you call initWithCoder:nil, quite probably the UIView implementation of initWithCoder isn't able to get some relevant value that it needs. At a guess, it probably starts being size zero, which isn't a valid size for a framebuffer object.
I'd suggest you replace initWithCoder:(NSCoder *)coder with initWithFrame:(CGRect)frame, calling the same on super at line 86. For an even better implementation, implement both initWithFrame: and initWithCoder:, having the two call a common section for everything enclosed in the if((self = [super initWithXXX:argument])) block.
I'm new - i'm sorry - but I'm experimenting with multiview iphone apps, and wondered whether the below idea was a) possible and b) sensible.
I want to create a method that can remove and add views based on some parameters - the outgoing view, the incoming view and the incoming class.
- (void)switchViews:(Class)inView:(Class)outView:(Class)inClass{
inClass *tempView = [[inClass alloc]
initWithNibName:#"inView" bundle:nil];
tempView.burgerViewController = self;
self.inView = tempView;
[tempView release];
[outView.view removeFromSuperview];
[self.view insertSubview:tempView.view atIndex:0];
}
This would be called by:
[burgerViewController switchViews:viewMainMenu:viewOptions:ViewMainMenu];
Any help is much appreciated - I have a lot to learn.
Mike.
Your code is wrong, in that (it appears that) you've misunderstood how method names work in Objective-C.
For example, as your method currently stands, it is named:
switchViews:::
That's probably not what you're looking for.
A better name might be:
replaceView:forProperty:withViewOfClass:
Declared, that would look like:
- (void) replaceView:(UIView *)outView forProperty:(NSString *)propertyName withViewOfClass:(Class)inClass;
And you would use it like this:
Class viewOptions = ...;
NSString *viewMainMenu = #"...";
[burgerViewController replaceView:viewMainMenu forProperty:viewMainMenu withViewOfClass:viewOptions];
For more on Objective-C method names and interleaved arguments, check out the Objective-C Programming Language Reference.
Well, your first problem is that you release tempView and then attempt to insert it into the view. Don't release tempView at all, just keep it as-is for insertion into the main view.
There are a lot of cases in which one would alloc an instance, and release it right after it's being assigned to something else, which retains it internally.
For example,
UIView *view = [[UIView alloc] initWithFrame...];
[self addSubView:view];
[view release];
I have heard people suggesting that we go with autorelease rather than release right after.
So the above becomes:
UIView *view = [[[UIView alloc] initWithFrame...] autorelease];
[self addSubView:view];
What's the best practice here? Pros and cons?
In most cases, it wont really matter either way. Since -autorelease simply means that the object will be released at the end of the current iteration of the run loop, the object will get released either way.
The biggest benefit of using -autorelease is that you don't have to worry about the lifetime of the object in the context of your method. So, if you decide later that you want to do something with an object several lines after it was last used, you don't need to worry about moving your call to -release.
The main instance when using -release will make a noticeable difference vs. using -autorelease is if you're creating a lot of temporary objects in your method. For example, consider the following method:
- (void)someMethod {
NSUInteger i = 0;
while (i < 100000) {
id tempObject = [[[SomeClass alloc] init] autorelease];
// Do something with tempObject
i++;
}
}
By the time this method ends, you've got 100,000 objects sitting in the autorelease pool waiting to be released. Depending on the class of tempObject, this may or may not be a major problem on the desktop, but it most certainly would be on the memory-constrained iPhone. Thus, you should really use -release over -autorelease if you're allocating many temporary objects. But, for many/most uses, you wont see any major differences between the two.
I agree with Matt Ball. Let me just add that, if you find yourself using this pattern frequently, it can be handy to write a quick category:
#interface UIView (MyCategories)
- (UIView *)addNewSubviewOfType:(Class)viewType inFrame:(NSRect)frame;
#end
#implementation UIView (MyCategories)
- (UIView *)addNewSubviewOfType:(Class)viewType inFrame:(NSRect)frame
{
UIView * newView = [[viewType alloc] initWithFrame:frame];
[self addSubView:newView];
return [newView autorelease];
}
#end
Which can be used as follows:
UIView * view = [someView addNewSubviewOfType:[UIView class]
inFrame:someFrame];
And it even works with other types, as long as they are derived from UIView:
UIButton * button = [mainView addNewSubviewOfType:[UIButton class]
inFrame:buttonFrame];
I usually go for -release rather than -autorelease whenever possible. This comes from years of experience debugging and enhancing other people's Objective-C code. Code that uses autorelease everywhere makes it harder to debug when an object gets over-released, since the extra release happens far away from the incorrect code.
It's also the case that many folks use autorelease when they just don't understand how cocoa memory management works. Learn the rules, learn the API, and you'll almost never need to autorelease an object.
A last minor point is that if you don't need the autorelease behavior, then using autorelease just needlessly adds extra work for your program to do.