Objective-C exam [closed]
I had a job interview yesterday and they said list all thats wrong with this code: Think I got most but not sure...
MyView.h:
#import "UIKit.h"
@interface MyView : UIView {
NSString* name;
UIButton* button;
}
@property(assign, copy) NSString* dateString;
@property(nonatomic, retain) UIButton* button;
- (void)buttonPressed;
@end
MyView.m:
#import "MyView.h"
@implementation MyView
@synthesize dateString, button;
- (id)init {
self = [super init];
if (self != nil) {
button = [UIButton initWithFrame:CGRectMake(0, 0, 50, 50)];
[button setImage:[UIImage imageNamed:@"buttonImage.png"] forState: UIControlStateNormal];
[button addTarget:self
action:@selector(buttonPressed)
forControlEvents:UIControlEventTouchUpInside];
[button release];
[self addSubview:button];
NSDateFormatter *headerDateFormatter = [[[NSDateFormatter alloc] init] autorele开发者_如何学Case];
[headerDateFormatter setLocale:[[[NSLocale alloc] initWithLocaleIdentifier:@"en_US_POSIX"] autorelease]];
[headerDateFormatter setDateFormat:@"EEE, d MMM yyyy HH:mm:ss Z"];
[self setDateString:[headerDateFormatter stringFromDate: [NSDate date]]];
[headerDateFormatter release];
for(NSInteger i=0; i<=10; i++){
NSLog(@"i = ", i);
}
}
-(void)buttonPressed {
NSLog(dateString);
}
- (void)dealloc {
[button removeFromSuperView];
[button release];
[dateString release];
[super dealloc];
}
Answer:
==========
[headerDateFormatter release];
not necessary as already autoreleased
==========
NSLog(@"i = ", i);
should be
NSLog(@"i = %d", i);
==========
[button release];
[self addSubview:button];
WRONG WAY ROUND
[self addSubview:button]; //addSubView retains button
[button release]; //so release after
=========
NSLog(dateString);
NSLog(@"%@",dateString);
=========
- (void)dealloc {
[button removeFromSuperView]; //unnecessary - whole view is about to be dealloc'd no need to break it apart
=========
you could also set images for other states for the button you only set it for one
[button setTitle:title forState:UIControlStateNormal];
[button setTitle:title forState:UIControlStateHighlighted];
[button setTitle:title forState:UIControlStateSelected];
=========
- (void)buttonPressed {
Event handler
- (void)buttonPressed:(UIButton *)button {
Lots of things wrong...
#import "UIKit.h"
Should be #import <UIKit/UIKit.h>
@interface MyView : UIView {
NSString* name;
UIButton* button;
}
@property(assign, copy) NSString* dateString;
Should be (nonatomic, copy)
@property(nonatomic, retain) UIButton* button;
- (void)buttonPressed;
@end
The rest looks reasonable.
#import "MyView.h"
@implementation MyView
@synthesize dateString, button;
- (id)init {
self = [super init];
This should be calling the designated initializer: initWithFrame:
if (self != nil) {
button = [UIButton initWithFrame:CGRectMake(0, 0, 50, 50)];
This should probably be self.button = ...
;
Also, there's no +initWithFrame:
method. It's -initWithFrame:
.
[button setImage:[UIImage imageNamed:@"buttonImage.png"] forState:UIControlStateNormal];
[button addTarget:self
action:@selector(buttonPressed)
forControlEvents:UIControlEventTouchUpInside];
[button release];
The button should not be released, since we do not have an owning reference to it. If we used self.button = ...
above, then we still wouldn't release it here, because the property is declared as retain
.
[self addSubview:button];
NSDateFormatter *headerDateFormatter = [[[NSDateFormatter alloc] init] autorelease];
[headerDateFormatter setLocale:[[[NSLocale alloc] initWithLocaleIdentifier:@"en_US_POSIX"] autorelease]];
[headerDateFormatter setDateFormat:@"EEE, d MMM yyyy HH:mm:ss Z"];
[self setDateString:[headerDateFormatter stringFromDate: [NSDate date]]];
[headerDateFormatter release];
The extra release
on the formatter is wrong, since we autorelease
'd it already.
for(NSInteger i=0; i<=10; i++){
NSLog(@"i = ", i);
This is missing the %d
(or %i
or whatever)
}
}
The return self;
statement is missing.
-(void)buttonPressed {
NSLog(dateString);
You shouldn't ever log strings directly. This should be NSLog(@"%@", dateString);
}
- (void)dealloc {
[button removeFromSuperView];
This is unnecessary, but is fine to have here.
[button release];
This is technically incorrect since we never retained button
in the initializer. However, if we fixed the initializer to correctly retain the button, then this is correct.
[dateString release];
[super dealloc];
}
Also, the name
ivar is never used.
A few more:
The ivar
name
is never used and should be removed.The
for
loop in-init
doesn't do anything useful (except provide a forum for the incorrectNSLog()
) and should be removed.The designated initializers for UIView are
-initWithFrame:
and-initWithCoder:
. At the very least, MyView's-init
should call either[self initWithFrame:]
or[super initWithFrame:]
, but it would be better to just override-initWithFrame:
in the first place.-buttonPressed
should not return dateString directly, but should instead use the property accessor:self.dateString
A couple that you got wrong:
The
[button release];
in-init
isn't just in the wrong place, it's just plain wrong. Thebutton
property is markedretain
, so the object should not release the button (assuming it was properly alloc'ed in the first place) in-init
. If you fix the order of the-retain
and-addSubView:
in-init
, the code will work until either thebutton
setter or-dealloc
releases the button again, at which point you'll probably crash.The
-buttonPressed
method is fine as an action -- no need to make it-(void)button:(UIButton*)button
. In Cocoa Touch, actions can take zero, one, or two parameters. It would be nice, however, if the action were marked withIBAction
to better communicate its purpose.
#import "UIKit.h"
should be
#import <UIKit/UIKit.h>
and
button = [UIButton initWithFrame:CGRectMake(0, 0, 50, 50)]; was never alloced.
You are missing
@property(assign, copy) NSString* dateString;
You cannot have the property as both assign and copy.
That button init also doesn't have the alloc call before initWithFrame. While you're on the button, I don't even know if button has that method. As of current sdk, you would use the class method UIButton buttonWithType to init a button.
Another error - dateString is property, it should be called with self. Also seems to be to link it with some class field or getter metod
精彩评论