How to use drawRect to draw in a existing view? - objective-c

I'm doing a GPS tracking app. Every time it receives a Latitude/Longitude it converts it to (x,y) coordinates and calls drawRect to draw a line between two (x,y) pairs.
However, the drawRect method just clear all the old contents before it draw new thing. How I can make the drawRect to draw new thing on the existing canvas? Thanks in advance
here is my viewController.h
#import <UIKit/UIKit.h>
#import <CoreLocation/CoreLocation.h>
#class routetrack;
#interface simpleDrawViewController : UIViewController <CLLocationManagerDelegate> {
CLLocationManager *locationManager;
IBOutlet routetrack *routeroute;
float latOld;
float longOld;
float latNew;
float longNew;
}
- (IBAction) gpsValueChanged;
#property (nonatomic,retain) CLLocationManager *locationManager;
#property (retain,nonatomic) routetrack *routeroute;
ViewController.m
#import "simpleDrawViewController.h"
#import "routetrack.h"
#implementation simpleDrawViewController
#synthesize locationManager,btn,routeroute;
- (IBAction) gpsValueChanged{
[routeroute setLocationX:longNew setLocationY:latNew
oldLocation:longOld oldLocationY:latOld ];
[routeroute setNeedsDisplay];
}
- (void)viewDidLoad {
[super viewDidLoad];
if (nil == locationManager)
locationManager = [[CLLocationManager alloc] init];
locationManager.delegate = self;
locationManager.desiredAccuracy = kCLLocationAccuracyBest;
[locationManager startUpdatingLocation];
}
- (void)didReceiveMemoryWarning {
// Releases the view if it doesn't have a superview.
[super didReceiveMemoryWarning];
// Release any cached data, images, etc that aren't in use.
}
- (void)viewDidUnload {
[super viewDidUnload];
// Release any retained subviews of the main view.
// e.g. self.myOutlet = nil;
}
- (void) locationManager:(CLLocationManager *)manager
didUpdateToLocation:(CLLocation *)newLocation
fromLocation:(CLLocation *)oldLocation
{
if (oldLocation) {
latOld=oldLocation.coordinate.latitude;
longOld=oldLocation.coordinate.longitude;
latNew=newLocation.coordinate.latitude;
longNew=newLocation.coordinate.longitude;
}
else {
latOld=53.3834;
longOld=-6.5876;
latNew=53.3835;
longNew=-6.5877;
}
[self gpsValueChanged];
}
- (void) locationManager:(CLLocationManager *)manager didFailwithError:
(NSError *)error
{
if([error code] == kCLErrorDenied)
[locationManager stopUpdatingLocation];
NSLog(#"location manger failed");
}
- (void)dealloc {
[locationManager release];
[super dealloc];
}
#end
my drawing class, a subclass of UIView
#import "routetrack.h"
#implementation routetrack
- (void) setLocationX:(float) loX setLocationY:(float) loY
oldLocation:(float) oldX oldLocationY:(float) oldY {
self->locationX = loX;
self->locationY = loY;
self->oldLoX = oldX;
self->oldLoY = oldY;
scaleX= 36365.484375;
scaleY= 99988.593750;
maxLat= 53.3834;
maxLog= -6.5976;
drawX = locationX;
drawY = locationY;
tempX=(maxLog - drawX) * scaleX;
tempY=(maxLat - drawY) * scaleY;
lastX = (int) tempX;
lastY = (int) tempY;
drawX = oldLoX;
drawY = oldLoY;
tempX=(maxLog - drawX) * scaleX;
tempY=(maxLat - drawY) * scaleY;
startX = (int) tempX;
startY = (int) tempY;
}
- (id)initWithFrame:(CGRect)frame {
self = [super initWithFrame:frame];
if (self) {
}
return self;
}
- (void)drawRect:(CGRect)rect {
int firstPointX = self->startX;
int firstPointY = self->startY;
int lastPointX = self->lastX;
int lastPointY = self->lastY;
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextSetRGBStrokeColor(context, 1.0, 0.0, 0.0, 1.0);
CGContextSetLineWidth(context, 2.0);
CGContextMoveToPoint(context, firstPointX, firstPointY);
CGContextAddLineToPoint(context, lastPointX , lastPointY);
CGContextStrokePath(context);
}

UIView does not have a canvas model. If you want to keep a canvas, you should create a CGLayer or a CGBitmapContext and draw onto that. Then draw that in your view.
I would create an ivar for a CGLayerRef, and then drawRect: would look something like this (untested):
- (void)drawRect:(CGRect)rect {
if (self.cgLayer == NULL) {
CGLayerRef layer = CGLayerCreateWithContext(UIGraphicsContextGetCurrent(), self.bounds, NULL);
self.cgLayer = layer;
CGLayerRelease(layer);
}
... various Core Graphics calls with self.cgLayer as the context ...
CGContextDrawLayerInRect(UIGraphicsContextGetCurrent(), self.bounds, self.cgLayer);
}
Whenever you wanted to clear your canvas, just self.cgLayer = NULL.
setCgLayer: would be something like this:
- (void)setCgLayer:(CGLayerRef)aLayer {
CGLayerRetain(aLayer);
CGLayerRelease(cgLayer_);
cgLayer_ = aLayer;
}

What exactly to you mean by "old contents"? If you want to draw a line from your GPS data, you have to draw all points every time in the implementation of drawRect.

Related

getting into the loop when doing progress view, ios

I am creating progress view by using CALayer by following
Header class
#import <UIKit/UIKit.h>
#import <QuartzCore/QuartzCore.h>
#interface ProgressBar : UIView
#property (strong, nonatomic) CALayer *subLayer;
#property (nonatomic) CGFloat progress;
#end
Implementation class
#implementation ProgressBar
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
self.progress = 0;
self.backgroundColor = [UIColor whiteColor];
self.subLayer = [CALayer layer];
self.subLayer.frame = self.bounds;
self.subLayer.backgroundColor = [UIColor orangeColor].CGColor;
[self.layer addSublayer:self.subLayer];
}
return self;
}
- (void)setProgress:(CGFloat)value {
NSLog(#"what is going on here");
if (self.progress != value) {
self.progress = value;
[self setNeedsLayout];
}
}
- (void)layoutSubviews {
CGRect rect = [self.subLayer frame];
rect.size.width = CGRectGetWidth([self bounds]) * self.progress;
[self.subLayer setFrame:rect];
}
In my viewcontroller, I am doing
#implementation ViewController
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
self.pBar = [[ProgressBar alloc] initWithFrame:CGRectMake(0, 50, 320, 10)];
[self.view addSubview:self.pBar];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (IBAction)click:(id)sender {
[self.pBar setProgress:.8];
}
When (IBAction)click is fired, I am getting into the infinitive loop like the picture below
Does anyone know what I am getting into this loop. Please advice me on this issue. Thanks
The problem is that your setProgress: method calls the setProgress: method - recursion.
- (void)setProgress:(CGFloat)value {
NSLog(#"what is going on here");
if (self.progress != value) {
self.progress = value; // <-- This calls [self setProgress:value]
[self setNeedsLayout];
}
}
Change the bad line to:
_progress = value;
Setting the ivar directly is always required when you implement the setter method of a property.

UITextView underlined text

I have UITextView and want to underline selected text.
It is working by this code
NSRange range = selectedTextView.selectedRange;
NSTextStorage *textStorage = selectedTextView.textStorage;
[textStorage addAttribute: NSUnderlineStyleAttributeName
value:[NSNumber numberWithInt:NSUnderlineStyleSingle]
range:range];
But letters which have "a tail" under baseline (as q y g p) are not underlined (screenshot: http://i.stack.imgur.com/dRrEH.png).
Also I noticed that space between baseline and underline depends on font.
How can I underline text without any breakings/spacing?
#import <UIKit/UIKit.h>
#interface TextViewWithUnderline : UITextView
#end
#import "TextViewWithUnderline.h"
#implementation TextViewWithUnderline
- (id)initWithFrame:(CGRect)frame {
self = [super initWithFrame:frame];
if (self) {
//self.contentMode = UIViewContentModeRedraw;
}
return self;
}
- (void)drawRect:(CGRect)rect {
//Get the current drawing context
CGContextRef context = UIGraphicsGetCurrentContext();
//Set the line color and width
CGContextSetStrokeColorWithColor(context, [UIColor lightGrayColor].CGColor);
CGContextSetLineWidth(context, 1.0f);
//Start a new Path
CGContextBeginPath(context);
//Find the number of lines in our textView + add a bit more height to draw lines in the empty part of the view
NSUInteger numberOfLines = (self.contentSize.height + self.bounds.size.height) / self.font.leading;
//Set the line offset from the baseline. (I'm sure there's a concrete way to calculate this.)
CGFloat baselineOffset = 6.0f;
//iterate over numberOfLines and draw each line
for (int x = 1; x < numberOfLines; x++) {
//0.5f offset lines up line with pixel boundary
CGContextMoveToPoint(context, self.bounds.origin.x + 10, self.font.leading*x + 0.5f + baselineOffset);
CGContextAddLineToPoint(context, self.bounds.size.width - 10, self.font.leading*x + 0.5f + baselineOffset);
}
//Close our Path and Stroke (draw) it
CGContextClosePath(context);
CGContextStrokePath(context);
}
#end
#import <UIKit/UIKit.h>
#import "TextViewWithUnderline.h"
#interface CustomTextView : UIViewController
#property (weak, nonatomic) IBOutlet TextViewWithUnderline *textView;
#end
#import "CustomTextView.h"
#interface CustomTextView ()
#end
#implementation CustomTextView
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view.
self.textView.contentMode = UIViewContentModeRedraw;
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#end

MKMapView zoom User Location and Annotation

I want my MKMapView to zoom 'User Location' and the Annotation as close as possible.
The map already show both, but is zoomed out to the whole country.
How can I do that?
And I don’t know why the Annotation and Pin are not animated.
My Code:
//Coords User
CLLocationCoordinate2D user_location;
user_location.latitude = mapView.userLocation.location.coordinate.latitude;
user_location.longitude = mapView.userLocation.location.coordinate.longitude;
//Coords Annotation
CLLocationCoordinate2D club_location;
club_location.latitude = [self.clubInfo.latitude doubleValue];
club_location.longitude = [self.clubInfo.longitude doubleValue];
MKMapPoint userPoint = MKMapPointForCoordinate(user_location);
MKMapPoint annotationPoint = MKMapPointForCoordinate(club_location);
MKMapRect userRect = MKMapRectMake(userPoint.x, userPoint.y, 0, 0);
MKMapRect annotationRect = MKMapRectMake(annotationPoint.x, annotationPoint.y, 0, 0);
MKMapRect unionRect = MKMapRectUnion(userRect, annotationRect);
MKMapRect unionRectThatFits = [mapView mapRectThatFits:unionRect];
[mapView setVisibleMapRect:unionRectThatFits animated:YES];
// Add an annotation
MKPointAnnotation *annotation = [[MKPointAnnotation alloc] init];
annotation.coordinate = club_location;
annotation.title = self.clubInfo.clubName;
annotation.subtitle = #"Pin!";
[mapView addAnnotation:annotation]; // This was missing
[mapView selectAnnotation:annotation animated:YES];
Logs:
userRect: {{134217728.0, 134217728.0}, {0.0, 0.0}}
annotationRect: {{99775488.0, 152579328.0}, {0.0, 0.0}}
unionRect: {{99775488.0, 134217728.0}, {34442240.0, 18361600.0}}
mapView.visibleMapRect: {{96025087.6, 116070015.1}, {41943040.7, 54657025.8}}
If I understand well, you want those two annotations to be visible with maximum possible zoom. I found this solution that does not reqire any calculations.
// You have coordinates
CLLocationCoordinate2D user = ...;
CLLocationCoordinate2D annotation = ...;
// Make map points
MKMapPoint userPoint = MKMapPointForCoordinate(user);
MKMapPoint annotationPoint = MKMapPointForCoordinate(annotation);
// Make map rects with 0 size
MKMapRect userRect = MKMapRectMake(userPoint.x, userPoint.y, 0, 0);
MKMapRect annotationRect = MKMapRectMake(annotationPoint.x, annotationPoint.y, 0, 0);
// Make union of those two rects
MKMapRect unionRect = MKMapRectUnion(userRect, annotationRect);
// You have the smallest possible rect containing both locations
MKMapRect unionRectThatFits = [mapView mapRectThatFits:unionRect];
[mapView setVisibleMapRect:unionRectThatFits animated:YES];
CoreLocation and MapKit structures are hell.
For anyone coming here later: The shortest way of doing this is (iOS7+) this:
Assuming you have a #property MKMapView *mapView, and an MKPointAnnotation *theAnnotation, call:
[self.mapView showAnnotations:#[theAnnotation, self.mapView.userLocation] animated:NO];
Now this could cause some problems if called too early (i.e. when self.mapView.userLocation is not yet set). If so, you can call in viewWillAppear:
[self.mapView.userLocation addObserver:self forKeyPath:#"location" options:0 context:NULL];
Then, implement:
-(void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context {
if ([keyPath isEqualToString:#"location"]) {
[self.mapView showAnnotations:#[theAnnotation, self.mapView.userLocation] animated:NO];
}
}
That way you're sure it's set. Don't forget to remove the observer at viewWillDisappear:
[self.mapView.userLocation removeObserver:self forKeyPath:#"location"];
Use these 4 classes - it works like a charm!
//MapViewController.h file
#import <UIKit/UIKit.h>
#import <MapKit/MapKit.h>
#interface MapViewController : UIViewController <CLLocationManagerDelegate> {
IBOutlet UIButton *buttonBack;
IBOutlet MKMapView *mapView;
IBOutlet UILabel *labelTitle;
NSString *lon,*lat,*nickName;
BOOL isFirstLaunch;
}
#property(nonatomic,retain) NSString *lon,*lat,*nickName;
#property(nonatomic,retain) IBOutlet UIButton *buttonBack;
#property(nonatomic,retain) IBOutlet UILabel *labelTitle;
#property(nonatomic,retain) IBOutlet MKMapView *mapView;
-(IBAction)buttonBackAction:(UIButton *)_btn;
-(void)zoomToFitMapAnnotations;
#end
//
// MapViewController.m
//
#import "MapViewController.h"
#import "Annotation.h"
#implementation MapViewController
#synthesize buttonBack,mapView,labelTitle;
#synthesize lon,lat,nickName;
// The designated initializer. Override if you create the controller programmatically and want to perform customization that is not appropriate for viewDidLoad.
/*
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil {
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization.
}
return self;
}
*/
-(IBAction)buttonBackAction:(UIButton *)_btn{
[self.navigationController popViewControllerAnimated:1];
}
// Implement viewDidLoad to do additional setup after loading the view, typically from a nib.
- (void)viewDidLoad {
CLLocationManager* locationManager = [[CLLocationManager alloc] init];
[locationManager setDelegate:self];
[locationManager setDesiredAccuracy:kCLLocationAccuracyBest];
[locationManager startUpdatingLocation];
NSLog(#"MapViewController");
labelTitle.text = #"anscacorona.blogspot.in"
CLLocationCoordinate2D location;
location.latitude = [self.lat floatValue];
location.longitude = [self.lon floatValue];
Annotation *annotation = [[Annotation alloc] init];
annotation.theCoordinate = location;
annotation.theTitle = [NSString stringWithFormat:#"%#",labelTitle.text];
[mapView addAnnotation:annotation];
[annotation release];
mapView.showsUserLocation = 1;
[self zoomToFitMapAnnotations];
[super viewDidLoad];
}
// Shows the location of both users. called when the device location changes to move the map accordinly. necessary ONLY once when the window is opened. afterwards the user can move the map as he choises.
- (void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation
{
if (isFirstLaunch) {
CLLocationCoordinate2D topLeftCoord;
CLLocationCoordinate2D bottomRightCoord;
topLeftCoord.longitude = fmin([self.lon floatValue], newLocation.coordinate.longitude);
topLeftCoord.latitude = fmax([self.lat floatValue], newLocation.coordinate.latitude);
bottomRightCoord.longitude = fmax([self.lon floatValue], newLocation.coordinate.longitude);
bottomRightCoord.latitude = fmin([self.lat floatValue], newLocation.coordinate.latitude);
MKCoordinateRegion region;
region.center.latitude = topLeftCoord.latitude - (topLeftCoord.latitude - bottomRightCoord.latitude) * 0.5;
region.center.longitude = topLeftCoord.longitude + (bottomRightCoord.longitude - topLeftCoord.longitude) * 0.5;
region.span.latitudeDelta = fabs(topLeftCoord.latitude - bottomRightCoord.latitude) * 1.5; // Add a little extra space on the sides
region.span.longitudeDelta = fabs(bottomRightCoord.longitude - topLeftCoord.longitude) * 1.5; // Add a little extra space on the sides
region = [mapView regionThatFits:region];
[mapView setRegion:region animated:YES];
isFirstLaunch = NO;
}
}
-(void)zoomToFitMapAnnotations
{
if([mapView.annotations count] == 0)
return;
CLLocationCoordinate2D topLeftCoord;
CLLocationCoordinate2D bottomRightCoord;
topLeftCoord.longitude = fmin(mapView.userLocation.location.coordinate.longitude, [self.lon floatValue]);
topLeftCoord.latitude = fmax(mapView.userLocation.location.coordinate.latitude, [self.lat floatValue]);
bottomRightCoord.longitude = fmax(mapView.userLocation.location.coordinate.longitude, [self.lon floatValue]);
bottomRightCoord.latitude = fmin(mapView.userLocation.location.coordinate.latitude, [self.lat floatValue]);
MKCoordinateRegion region = { {0.0, 0.0 }, { 0.0, 0.0 } };
CLLocationCoordinate2D userCoord = {[self.lat floatValue],[self.lon floatValue]};
region.center = userCoord;
region.span.latitudeDelta = 0.05f;//fabs(topLeftCoord.latitude - bottomRightCoord.latitude) * 1.1; // Add a little extra space on the sides
region.span.longitudeDelta = 0.05f;//fabs(bottomRightCoord.longitude - topLeftCoord.longitude) * 1.1; // Add a little extra space on the sides
[mapView setRegion:region animated:YES];
[mapView regionThatFits:region];
}
/*
// Override to allow orientations other than the default portrait orientation.
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
// Return YES for supported orientations.
return (interfaceOrientation == UIInterfaceOrientationPortrait);
}
*/
- (void)didReceiveMemoryWarning {
// Releases the view if it doesn't have a superview.
[super didReceiveMemoryWarning];
// Release any cached data, images, etc. that aren't in use.
}
#pragma mark - View Lifecycle
-(void)viewWillAppear:(BOOL)animated{
isFirstLaunch=YES;
}
- (void)viewDidUnload {
[super viewDidUnload];
// Release any retained subviews of the main view.
// e.g. self.myOutlet = nil;
}
- (void)dealloc {
[super dealloc];
}
#end
//anotation classes- Annotation.h
#import <MapKit/MapKit.h>
#interface Annotation : NSObject <MKAnnotation>{
CLLocationCoordinate2D theCoordinate;
NSString *theTitle;
NSString *restId;
NSString *theSubtitle;
}
#property(nonatomic,retain) NSString *restId;
#property(nonatomic,retain) NSString *theTitle;
#property(nonatomic,retain) NSString *theSubtitle;
#property CLLocationCoordinate2D theCoordinate;
#end
//Annotation.m
#import "Annotation.h"
#implementation Annotation
#synthesize theCoordinate,theTitle,theSubtitle,restId;
- (CLLocationCoordinate2D)coordinate;
{
return theCoordinate;
}
// required if you set the MKPinAnnotationView's "canShowCallout" property to YES
- (NSString *)title
{
return theTitle;
}
// optional
- (NSString *)subtitle
{
return theSubtitle;
}
- (void)dealloc
{
[super dealloc];
}
#end

Cant call methods on instance

While working on a project i made a class i instantiate in another class (nothing special) but if i try to call a method for this instance i get this:
Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[CALayer animate]: unrecognized selector sent to instance
here is the class .h :
#import <QuartzCore/QuartzCore.h>
#interface SFStripe : CALayer {
NSTimer *animation;
}
- (id)initWithXPosition:(NSInteger)positionX yPosition:(NSInteger)positionY;
- (id)initEndedWithXPosition:(NSInteger)positionX yPosition:(NSInteger)positionY;
- (void)animate;
- (void)reduceSize;
- (void)logSomething;
#property NSTimer *animation;
#end
and here the .m :
#import "SFStripe.h"
#implementation SFStripe
#synthesize animation;
- (id)initWithXPosition:(NSInteger)positionX yPosition:(NSInteger)positionY {
self = [CALayer layer];
self.backgroundColor = [UIColor blackColor].CGColor;
self.frame = CGRectMake(positionX, positionY, 5, 20);
self.cornerRadius = 5;
return self;
}
- (id)initEndedWithXPosition:(NSInteger)positionX yPosition:(NSInteger)positionY {
self = [CALayer layer];
self.backgroundColor = [UIColor grayColor].CGColor;
self.frame = CGRectMake(positionX, (positionY + 7.5), 5, 5);
self.cornerRadius = 2;
self.delegate = self;
return self;
}
- (void) logSomething {
NSLog(#"It did work!");
}
- (void)reduceSize {
if (self.frame.size.width > 0 && self.frame.size.height >= 5) {
self.frame = CGRectMake(self.frame.origin.x, (self.frame.origin.y - 0.5), self.frame.size.width, (self.frame.size.height - 0.5));
[self setNeedsDisplay];
NSLog(#"Width: %d", (int)self.frame.size.width);
NSLog(#"Height: %d", (int)self.frame.size.height);
} else {
self.backgroundColor = [UIColor grayColor].CGColor;
self.frame = CGRectMake(self.frame.origin.x, (self.frame.origin.y + 7.5), 5, 5);
[animation invalidate];
}
}
- (void)animate {
animation = [NSTimer scheduledTimerWithTimeInterval:0.03 target:self selector:#selector(reduceSize) userInfo:nil repeats:YES];
}
#end
i imported this class into a fresh project just to see if it is working there but get the same error. here is how i call one of the methods for an instance of the class (i get the same error for all of the methods)
in the mainview.h (of the clean project):
#import <UIKit/UIKit.h>
#import "SFStripe.h"
#import <QuartzCore/QuartzCore.h>
#interface STViewController : UIViewController {
SFStripe *stripe;
}
- (IBAction)animate:(id)sender;
#end
i created the instance and in the .m i let the action call the method for the instance:
#import <QuartzCore/QuartzCore.h>
#import "STViewController.h"
#import "SFStripe.h"
#interface STViewController ()
#end
#implementation STViewController
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
stripe = [[SFStripe alloc] initWithXPosition:30 yPosition:30];
[self.view.layer addSublayer:stripe];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (IBAction)animate:(id)sender {
[stripe animate];
}
#end
sorry for all the code but i cant find an answer for this problem that helps and hope someone can help me!
This is not the correct way to write an initializer:
- (id)initWithXPosition:(NSInteger)positionX yPosition:(NSInteger)positionY
{
self = [CALayer layer];
...
You're assigning self to be a plain old CALayer instance, rather than an instance of your subclass.
Use self = [super init] instead, and then check that self is not nil.

Subclass of UIView. How to add through Interface Builder?

I have a subclass of UITextField and want to be able to add it to the view in IB. What I did is added UITextField and changed its class to my subclass in Identity tab of Inspector. But I can only see UITextField on the view.
Code:
#interface ExtendedTextField : UITextField {
}
//implementation
#implementation ExtendedTextField
- (void)baseInit
{
UIImage * curImage = [UIImage imageNamed:#"tfbg.png"];
[self baseInitWithImage : curImage];
}
- (void)baseInitWithImage : (UIImage *) aImage
{
aImage = [aImage stretchableImageWithLeftCapWidth:29 topCapHeight:29];
self.background = aImage;
self.contentVerticalAlignment = UIControlContentVerticalAlignmentCenter;
UIView * curLeftView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 10, self.frame.size.height)];
self.leftView = curLeftView;
self.rightView = curLeftView;
[curLeftView release];
self.leftViewMode = UITextFieldViewModeAlways;
self.rightViewMode = UITextFieldViewModeAlways;
[self setTextColor:[UIColor greenColor]];
}
- (void)awakeFromNib
{
[super awakeFromNib];
[self baseInit];
}
/*
- (id)initWithCoder:(NSCoder *)aDecoder
{
self = [super initWithCoder:aDecoder];
if (self) {
[self baseInit];
}
return self;
}
*/
- (id)initWithFrame:(CGRect)frame {
self = [super initWithFrame:frame];
if (self)
{
[self baseInit];
}
return self;
}
- (id)initWithFrame:(CGRect)frame withImage:(UIImage*)aImage
{
self = [super initWithFrame:frame];
if (self) {
[self baseInitWithImage : aImage];
}
return self;
}
- (void)dealloc {
[super dealloc];
}
#end
EDIT: I noticed several things:
-- if I put [super initWithFrame:...] instead of [super initWithCoder:...] inside
(id)initWithCoder:(NSCoder *)aDecoder
it works well.
-- Now I am using awakefromnib instead of initwithcoder and the only thing that get changed in textfield is textColor.
Could someone explain why so?
Solution I needed to set border style to none. BS overlayed bg image.
While showing your .xib in Xcode, reveal the right pane, select your view and in the third tab, change Classto whatever you want it to be.