Can't implement UIView subclass - ios

I am trying to create a UIView which is basically a number with a circular background. I am using a UIView and applying a corner radius of half the dimension for the circle. Then I am adding the number as a UILabel subview to the above view.
What I want is close to this (without the fancy border):
(This is a screenshot from the app Count Battle).
Please help me rewrite by moving the code under the proper methods (drawrect, init, layoutSubviews, or any custom method). This is the code in it's current form. I think my understanding of this thing is muddled up, and this just doesn't look right.
This is the header file:
// CircleNumView.h
#import <UIKit/UIKit.h>
#interface CircleNumView : UIView
#property (nonatomic, strong) UIColor *circleColor;
- (instancetype)initWithRadius:(CGFloat)radius
center:(CGPoint)center
text:(NSString *)text;
#end
This is the implementation file:
// CircleNumView.m
#import "CircleNumView.h"
#interface CircleNumView ()
#property (nonatomic) CGFloat radius;
#property (nonatomic, strong) NSString *text;
#end
#implementation CircleNumView
// designated initializer
- (instancetype)initWithRadius:(CGFloat)radius
center:(CGPoint)center
text:(NSString *)text
{
self = [super init];
self.radius = radius;
self.text = text;
self.frame = CGRectMake ( center.x - radius, center.y - radius, 2 * radius, 2 * radius);
self.circleColor = [UIColor whiteColor];
self = [self createView];
return self;
}
- (CircleNumView *)createView
{
CircleNumView *circularView = [[UIView alloc] initWithFrame:self.frame];
circularView.backgroundColor = self.circleColor;
UILabel *label = [[UILabel alloc] initWithFrame:circularView.bounds];
label.text = self.text;
label.textColor = [UIColor blackColor];
[circularView addSubview:label];
circularView.clipsToBounds = YES;
circularView.layer.cornerRadius = self.radius;
[self addSubview:circularView];
return circularView;
}
#end

You were doing everything pretty well until that self = [createView];
This is the implementation file that I would write:
//
// CircleNumberView.m
//
//
// Created by James Valaitis on 13/04/2014.
//
//
#import "CircleNumberView.h"
#pragma mark - Circle Number View Private Class Extension
#interface CircleNumberView ()
/** The radius of this circular view. */
#property (nonatomic, assign) CGFloat radius;
/** The number to present encapsulated as a string. */
#property (nonatomic, copy) NSString *text;
/** The label that shows the number contents of this view. */
#property (nonatomic, strong) UILabel *textLabel;
#end
#pragma mark - Circle Number View Implementation
#implementation CircleNumberView
#pragma mark - Initialisation
/**
* Initialises a circlular view with a number in the middle.
*
* #param radius The radius of the circle.
* #param center The center point of the circle in it's superview.
* #param text The number as a string to present in the middle of this view.
*
* #return An initialized object.
*/
- (instancetype)initWithRadius:(CGFloat)radius center:(CGFloat)center text:(NSString *)text
{
CGRect frame = CGRectMake(center.x - radius, center.y - radius, radius * 2, radius * 2);
if (self = [super initWithFrame:frame])
{
_radius = radius;
_text = text;
[self configureViewAndSubviews];
}
return self;
}
#pragma mark - Property Accessor Methods - Getters
/**
* The label that shows the number contents of this view.
*
* #return The label that shows the number contents of this view.
*/
- (UILabel *)textLabel
{
if (!_textLabel)
{
_textLabel = [[UILabel alloc] initWithFrame:self.bounds];
_textLabel.numberOfLines = 0;
_textLabel.textColor = [UIColor blackColor];
}
return _textLabel;
}
#pragma mark - Subview Management
/**
* Configures this view as well as it's subviews.
*/
- (void)configureViewAndSubviews
{
self.backgroundColor = [UIColor whiteColor];
self.clipsToBounds = YES;
self.layer.cornerRadius = self.radius;
self.textLabel.text = self.text;
[self addSubview:self.textLabel];
}
#end

Related

how Draw a percentage of a circle objective c

i can need layout like same as image
but i can not draw like this so any idea about this,
The easiest approach would be to have a view with two subviews, one for the green "percent filled" level, and one for the label for the text. Then you can update the frame for the "percent filled" based upon, obviously, what percent filled you want it. And then apply a circular mask to the whole thing.
For example:
// CircleLevelView.h
//
// Created by Robert Ryan on 10/28/17.
#import <UIKit/UIKit.h>
IB_DESIGNABLE
#interface CircleLevelView : UIView
/// Percent filled
///
/// Value between 0.0 and 1.0.
#property (nonatomic) IBInspectable CGFloat percent;
/// Text to show up in center of view
///
/// Value between 0.0 and 1.0.
#property (nonatomic, strong) IBInspectable NSString *text;
#end
And
// CircleLevelView.m
//
// Created by Robert Ryan on 10/28/17.
#import "CircleLevelView.h"
#interface CircleLevelView()
#property (nonatomic, weak) CAShapeLayer *circleMask;
#property (nonatomic, weak) UILabel *label;
#property (nonatomic, weak) UIView *fillView;
#end
#implementation CircleLevelView
#synthesize percent = _percent;
- (instancetype)initWithCoder:(NSCoder *)aDecoder {
self = [super initWithCoder:aDecoder];
[self configure];
return self;
}
- (instancetype)initWithFrame:(CGRect)frame {
self = [super initWithFrame:frame];
[self configure];
return self;
}
- (instancetype)init {
return [self initWithFrame:CGRectZero];
}
- (void)configure {
self.clipsToBounds = true;
UILabel *fillView = [[UILabel alloc] init];
fillView.translatesAutoresizingMaskIntoConstraints = false;
fillView.backgroundColor = [UIColor colorWithRed:169.0 / 255.0
green:208.0 / 255.0
blue:66.0 / 255.0
alpha:1.0];
[self addSubview:fillView];
self.fillView = fillView;
UILabel *label = [[UILabel alloc] init];
label.translatesAutoresizingMaskIntoConstraints = false;
label.backgroundColor = [UIColor clearColor];
label.textColor = [UIColor blackColor];
label.textAlignment = NSTextAlignmentCenter;
[self addSubview:label];
self.label = label;
[NSLayoutConstraint activateConstraints:#[
[label.topAnchor constraintEqualToAnchor:self.topAnchor],
[label.bottomAnchor constraintEqualToAnchor:self.bottomAnchor],
[label.leadingAnchor constraintEqualToAnchor:self.leadingAnchor],
[label.trailingAnchor constraintEqualToAnchor:self.trailingAnchor],
[fillView.topAnchor constraintEqualToAnchor:self.topAnchor],
[fillView.bottomAnchor constraintEqualToAnchor:self.bottomAnchor],
[fillView.leadingAnchor constraintEqualToAnchor:self.leadingAnchor],
[fillView.trailingAnchor constraintEqualToAnchor:self.trailingAnchor]
]];
CAShapeLayer *circleMask = [CAShapeLayer layer];
circleMask.fillColor = [UIColor whiteColor].CGColor;
circleMask.strokeColor = [UIColor blackColor].CGColor;
circleMask.lineWidth = 0;
self.layer.mask = circleMask;
self.circleMask = circleMask;
}
- (void)layoutSubviews {
[super layoutSubviews];
CGPoint center = CGPointMake(self.bounds.origin.x + self.bounds.size.width / 2.0, self.bounds.origin.y + self.bounds.size.height / 2.0);
CGFloat radius = MIN(self.bounds.size.width, self.bounds.size.height) / 2.0;
self.circleMask.path = [UIBezierPath bezierPathWithArcCenter:center radius:radius startAngle:0 endAngle:M_PI * 2.0 clockwise:true].CGPath;
[self updatePercentFill];
}
- (void)updatePercentFill {
CGFloat circleHeight = MIN(self.bounds.size.width, self.bounds.size.height);
CGFloat percentHeight = circleHeight * self.percent;
self.fillView.frame = CGRectMake(0,
(self.bounds.size.height - circleHeight) / 2 + (circleHeight - percentHeight),
self.bounds.size.width,
circleHeight);
}
// MARK: - Custom Accessor Methods
- (CGFloat)percent {
return _percent;
}
- (void)setPercent:(CGFloat)percent {
_percent = percent;
[self updatePercentFill];
}
- (NSString *)text {
return self.label.text;
}
- (void)setText:(NSString *)text {
self.label.text = text;
}
#end
That yields:
If you know the chord position you can fill to the chord by setting the clip region and then filling the circle.
To work out the position of the chord to give an area of x% you'll need to do some geometry/trigonometry. Every chord which does not pass through the centre forms and isosceles triangle with the centre, and the two sides of that triangle which are radii delimit a segment of the circle. So the area on one side of a chord which does not pass through the centre is the difference of the area of a triangle and a segment, and you can work out how the chord divides the area or where the chord needs to be to divide the area in a particular ratio.
If that all sounds like gobbledegook try looking up chord geometry and you'll undoubtedly find books/sites with helpful diagrams and formulas.
HTH

Making UIImage redraw on new position on #IB_Designable

I am creating this IB_Designable class. It is like a slider. See picture. Both elements are created with little stretchable UIImages.
I have this red square that is 66x66 pt. This square has to slide in X inside the gray rectangle.
I have create this class:
HEADER
#import <UIKit/UIKit.h>
IB_DESIGNABLE
#interface MyClass : UIView
// minimum and maximum slider value
#property (assign, nonatomic) IBInspectable CGFloat minimumValue;
#property (assign, nonatomic) IBInspectable CGFloat maximumValue;
#property (assign, nonatomic) IBInspectable CGFloat value;
#end
IMPLEMENTATION
#import "MyClass.h"
#interface MyClass() {
__weak IBOutlet UIView *topContainer;
CGFloat minimumThumbCoordinate;
CGFloat maximumThumbCoordinate;
}
#property (weak, nonatomic) IBOutlet UIImageView *thumb;
#end
#implementation MyClass
- (void)awakeFromNib {
[super awakeFromNib];
// topContainer contains everything
CGRect topContainerBounds = [topContainer bounds];
CGRect thumbBounds = [self.thumb bounds];
CGFloat topContainerWidth = CGRectGetWidth(topContainerBounds);
CGFloat thumbWidth = CGRectGetWidth(thumbBounds);
minimumThumbCoordinate = floorf(thumbWidth / 2.0f);
maximumThumbCoordinate = floorf(topContainerWidth - minimumThumbCoordinate);
}
-(void)setValue:(CGFloat)value {
if ((value < self.minimumValue) || (value > self.maximumValue)) return;
// normalize values
CGFloat minimumValueNormalized = self.minimumValue;
CGFloat maximumValueNormalized = self.maximumValue;
CGFloat desiredValue = value;
if ((minimumValueNormalized < 0) && (maximumValueNormalized > 0)) {
CGFloat absoluteMinimum = fabsf(self.minimumValue);
minimumValueNormalized = 0;
maximumValueNormalized += absoluteMinimum;
desiredValue += absoluteMinimum;
}
CGFloat percentage = desiredValue/maximumValueNormalized;
// find coordinate
CGFloat coordinateRange = maximumThumbCoordinate - minimumThumbCoordinate;
CGFloat relativeCoordinate = percentage * coordinateRange;
CGPoint center = CGPointMake(relativeCoordinate, self.thumb.center.y);
[self.thumb setCenter: center];
}
The problem is that the setValue method does not make the thumb move when I set the value on interface builder... any ideas?
You cannot have components of your thumbnail added in your storyboard. In this case, I suspect your thumb image view outlet is nil while it's being previewed in IB, and thus changing the value it is likely not updating any subview.
You generally get around this by adding the subviews programmatically, e.g. something like:
// MyClass.h
#import <UIKit/UIKit.h>
IB_DESIGNABLE
#interface MyClass : UIView
#property (nonatomic, strong) IBInspectable UIImage *thumbnailImage;
#property (nonatomic) IBInspectable CGFloat minimumValue;
#property (nonatomic) IBInspectable CGFloat maximumValue;
#property (nonatomic) IBInspectable CGFloat value;
#property (nonatomic, readonly) CGFloat percent;
#end
And
// MyClass.m
#import "MyClass.h"
#interface MyClass ()
#property (weak, nonatomic) UIImageView *thumbnailView;
#property (nonatomic) CGFloat thumbWidth;
#end
#implementation MyClass
- (instancetype)initWithFrame:(CGRect)frame {
self = [super initWithFrame:frame];
if (self) {
[self configureView];
}
return self;
}
- (instancetype)initWithCoder:(NSCoder *)coder {
self = [super initWithCoder:coder];
if (self) {
[self configureView];
}
return self;
}
- (void)configureView {
UIImageView *thumb = [[UIImageView alloc] initWithImage:self.thumbnailImage];
[self addSubview:thumb];
thumb.backgroundColor = [UIColor lightGrayColor]; // in case no image has been set
thumb.clipsToBounds = true; // in case you change your `contentMode`
thumb.contentMode = UIViewContentModeScaleToFill;
_thumbnailView = thumb;
_thumbWidth = 44; // maybe you have another IBInspectable property for this...
[self layoutThumbnail];
}
- (void)setThumbnailImage:(UIImage *)image {
self.thumbnailView.image = image;
}
- (CGFloat)percent {
CGFloat range = self.maximumValue - self.minimumValue;
return range ? (self.value - self.minimumValue) / range : 0;
}
- (void)layoutSubviews {
[super layoutSubviews];
[self layoutThumbnail];
}
- (void)layoutThumbnail {
CGFloat minX = self.thumbWidth / 2;
CGFloat maxX = self.bounds.size.width - self.thumbWidth / 2;
CGRect frame = CGRectMake(self.percent * (maxX - minX) + minX - self.thumbWidth / 2, 0, self.thumbWidth, self.bounds.size.height);
self.thumbnailView.frame = frame;
}
- (void)setValue:(CGFloat)value {
if (value < self.minimumValue)
_value = self.minimumValue;
else if (value > self.maximumValue) {
_value = self.maximumValue;
} else {
_value = value;
}
[self layoutThumbnail];
}
#end
Note, I update the thumbnail frame not only when you change the value, but also upon layoutSubviews. You want to make sure that the thumbnail frame updates if your control changes size at runtime (e.g. user rotates the device and the control changes size). I also made the thumbnail image a property so you could set this in IB, too, if you wanted. But maybe you have some hardcoded/default image that you use. I also thought that the percent that we use for laying out the thumbnail might potentially be useful by the code that used that control, so I exposed that property.
Now, you're using image views, but if all you wanted were rounded corners of the main control and the thumbnail, I wouldn't use images, but rather just round the corners of the layer for the appropriate UIView objects. Also, I was unclear about your intent of certain things (e.g., I'm not sure what your topContainer is referring to ... you wouldn't generally reference views outside the view hierarchy of the designable view). And you reference the top level view being an image view, which you'd do if you wanted a background image there, too.
But those are details that aren't relevant to your broader question. Hopefully this illustrates the idea, that if you create the subviews programmatically, you can see the thumbnail move as you change your IBInspectable value.
I have seen some implementations here where people wanted to define all of the view hierarchy of the designable view with outlets. But in that case, you have a self-contained NIB for all of these subviews. If you search StackOverflow for "IBDesignable NIB", you'll see links to related answers.

IB_DESIGNABLE tintColor issues

I'm getting into IB_DESIGNABLE, and I've stumbled over an issue.
When I set the tintColor of my custom view with IB, it is rendered in the right way in the IB.
But when I run it on the device it is displayed with default tintColor.
#pragma mark - UIView
- (void)drawRect:(CGRect)rect {
[self drawCircleRadius:MIN(rect.size.width / 2, rect.size.height / 2) - self.lineWidth / 2.f
rect:rect
startAngle:self.startAngleRadians
endAngle:self.endAngleRadians
lineWidth:self.lineWidth];
}
#pragma mark - private methods
- (void)drawCircleRadius:(CGFloat)radius
rect:(CGRect)rect
startAngle:(CGFloat)startAngle
endAngle:(CGFloat)endAngel
lineWidth:(CGFloat)lineWidth {
UIBezierPath* bezierPath = [UIBezierPath bezierPath];
[self.tintColor setStroke];
[bezierPath addArcWithCenter:CGPointMake(rect.size.width / 2, rect.size.height / 2)
radius:radius
startAngle:startAngle
endAngle:endAngel
clockwise:YES];
bezierPath.lineWidth = lineWidth;
[bezierPath stroke];
}
What the difference? Why is it displayed with the default tint color in the device, and correctly displayed in IB?
UPDATE:
#import <UIKit/UIKit.h>
IB_DESIGNABLE
#interface PKCircleView : UIView
#property (nonatomic, assign) IBInspectable CGFloat startAngleRadians;
#property (nonatomic, assign) IBInspectable CGFloat endAngleRadians;
#property (nonatomic, assign) IBInspectable CGFloat lineWidth;
#end
The issue was on that line
self.tintColor = [UIColor defaultDwonloadButtonBlueColor];
:
static PKCircleView *CommonInit(PKCircleView *self) {
if (self != nil) {
self.backgroundColor = [UIColor clearColor];
self.startAngleRadians = M_PI * 1.5;
self.endAngleRadians = self.startAngleRadians + (M_PI * 2);
self.lineWidth = 1.f;
self.tintColor = [UIColor defaultDwonloadButtonBlueColor];
}
return self;
}
#implementation PKCircleView
#pragma mark - initialization
- (id)initWithCoder:(NSCoder *)decoder {
return CommonInit([super initWithCoder:decoder]);
}
- (instancetype)initWithFrame:(CGRect)frame {
return CommonInit([super initWithFrame:frame]);
}
it seems like setTintColor from IB is called before init... methods.

Code to give different color for each pagination dots in ios

Is that possible to give each pagination dots with different colors? Suppose if i have 4 dots means is that possible to give 4 different color for each dots in ios?
http://muthesblog.blogspot.in/2011/11/custompagecontrol.html
by using the above code in the blog you will get different color dots as shown below image with yellow rectangle.
For your convenience adding the code
implemetation of the custompagecontrol
PageControl *<pageControl> = [[[PageControl alloc] initWithFrame:f] autorelease];
<pageControl>.numberOfPages = 5;
<pageControl>.currentPage = 1;
<pageControl>.delegate = self;
[self.view addSubview:<pageControl>];
/// .h file
#import <UIKit/UIKit.h>
#protocol PageControlDelegate;
#interface PageControl : UIView {
#private
NSInteger _currentPage;
NSInteger _numberOfPages;
UIColor *dotColorCurrentPage;
UIColor *dotColorOtherPage;
NSObject<PageControlDelegate> *delegate;
}
// Set these to control the PageControl.
#property (nonatomic) NSInteger currentPage;
#property (nonatomic) NSInteger numberOfPages;
// Customize these as well as the backgroundColor property.
#property (nonatomic, retain) UIColor *dotColorCurrentPage;
#property (nonatomic, retain) UIColor *dotColorOtherPage;
// Optional delegate for callbacks when user taps a page dot.
#property (nonatomic, assign) NSObject<PageControlDelegate> *delegate;
#end
#protocol PageControlDelegate<NSObject>
#optional
- (void)pageControlPageDidChange:(PageControl *)pageControl;
#end
//.m file
#import "PageControl.h"
// Tweak these or make them dynamic.
#define kDotDiameter 10.0
#define kDotSpacer 7.0
#implementation PageControl
#synthesize dotColorCurrentPage;
#synthesize dotColorOtherPage;
#synthesize delegate;
- (NSInteger)currentPage{
return _currentPage;
}
- (void)setCurrentPage:(NSInteger)page{
_currentPage = MIN(MAX(0, page), _numberOfPages-1);
[self setNeedsDisplay];
}
- (NSInteger)numberOfPages{
return _numberOfPages;
}
- (void)setNumberOfPages:(NSInteger)pages{
_numberOfPages = MAX(0, pages);
_currentPage = MIN(MAX(0, _currentPage), _numberOfPages-1);
[self setNeedsDisplay];
}
- (id)initWithFrame:(CGRect)frame {
if ((self = [super initWithFrame:frame]))
{
// Default colors.
self.backgroundColor = [UIColor clearColor];
self.dotColorCurrentPage = [UIColor greenColor];
self.dotColorOtherPage = [UIColor whiteColor];
}
return self;
}
- (void)drawRect:(CGRect)rect {
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextSetAllowsAntialiasing(context, true);
CGRect currentBounds = self.bounds;
CGFloat dotsWidth = self.numberOfPages*kDotDiameter + MAX(0, self.numberOfPages-1)*kDotSpacer;
CGFloat x = CGRectGetMidX(currentBounds)-dotsWidth/2;
CGFloat y = CGRectGetMidY(currentBounds)-kDotDiameter/2;
for (int i=0; i<_numberOfPages; i++)
{
CGRect circleRect = CGRectMake(x, y, kDotDiameter, kDotDiameter);
if (i == _currentPage)
{
CGContextSetFillColorWithColor(context, self.dotColorCurrentPage.CGColor);
}
else
{
if(i==0) {
CGContextSetFillColorWithColor(context, [UIColor magentaColor].CGColor);
} else if(i==1) {
CGContextSetFillColorWithColor(context, [UIColor orangeColor].CGColor);
} else if (i==2) {
CGContextSetFillColorWithColor(context, [UIColor yellowColor].CGColor);
} else if (i==3) {
CGContextSetFillColorWithColor(context, [UIColor whiteColor].CGColor);
} else if (i==4) {
CGContextSetFillColorWithColor(context, [UIColor blueColor].CGColor);
}
}
CGContextFillEllipseInRect(context, circleRect);
x += kDotDiameter + kDotSpacer;
}
}
- (void)dealloc {
[dotColorCurrentPage release];
[dotColorOtherPage release];
[super dealloc];
}
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
if (!self.delegate) return;
CGPoint touchPoint = [[[event touchesForView:self] anyObject] locationInView:self];
CGFloat dotSpanX = self.numberOfPages*(kDotDiameter + kDotSpacer);
CGFloat dotSpanY = kDotDiameter + kDotSpacer;
CGRect currentBounds = self.bounds;
CGFloat x = touchPoint.x + dotSpanX/2 - CGRectGetMidX(currentBounds);
CGFloat y = touchPoint.y + dotSpanY/2 - CGRectGetMidY(currentBounds);
if ((x<0) || (x>dotSpanX) || (y<0) || (y>dotSpanY)) return;
self.currentPage = floor(x/(kDotDiameter+kDotSpacer));
if ([self.delegate respondsToSelector:#selector(pageControlPageDidChange:)])
{
[self.delegate pageControlPageDidChange:self];
}
}
#end
There is no native way to change the colour of each page indicator due to iOS restrictions.
You can however use the following code to change the colour of the currently selected indicator and that of the rest which might be a good compromise.
pageControl.pageIndicatorTintColor = [UIColor purpleColor];
pageControl.currentPageIndicatorTintColor = [UIColor magentaColor];
If this functionality is essential for your app I would advise creating a custom page indicator that serves your purpose or maybe find a library online that allows you to to do this.
I hope that answers your questions :)
Check this below code
pageControl.pageIndicatorTintColor = [UIColor purpleColor];
pageControl.currentPageIndicatorTintColor = [UIColor magentaColor];
or Please refer this link
http://stackoverflow.com/questions/2942636/how-can-i-change-the-color-of-pagination-dots-of-uipagecontrol

Calling a superclasses designated initialiser calls the subclasses

I have what seems like a straightforward enough issue, but I just have no idea why it's working the way it is.
I have a class Shape which has a subclass of Square.
When I call Square and call its designated initialiser, in self = [super init] it calls the super class. However when the superclass calls its designated initialiser, named the same as one of the subclasses, it calls the subclass.
What I end up with is an infinite loop of the subclass calling init on the superclass and that calling the subclasses initialiser.
How can I solve this issue? Should I make sure the names of my initialisers are different enough so this can't happen?
Shape.h
#import <Foundation/Foundation.h>
#interface Shape : NSObject
#property (nonatomic) CGPoint position;
#property (nonatomic) float width;
#property (nonatomic) float height;
#property (nonatomic, readonly) float area;
- (id)initWithWidth:(float)width andHeight:(float)height andPosition:(CGPoint)position;
- (id)initWithWidth:(float)width andHeight:(float)height;
- (id)initWithWidth:(float)width;
- (id)init;
- (NSString *)drawShape;
#end
-
Shape.m
#import "Shape.h"
#implementation Shape
- (id)initWithWidth:(float)width andHeight:(float)height andPosition:(CGPoint)position
{
self = [super init];
if (self) {
self.width = width;
self.height = height;
self.position = position;
}
return self;
}
- (id)initWithWidth:(float)width andHeight:(float)height
{
return [self initWithWidth:width andHeight:height andPosition:CGPointMake(100, 100)];
}
- (id)initWithWidth:(float)width
{
return [self initWithWidth:width andHeight:1.0f andPosition:CGPointMake(100, 100)];
}
- (id)init
{
CGPoint defaultPoint = CGPointMake(100, 100);
return [self initWithWidth:1.0 andHeight:1.0 andPosition:defaultPoint];
}
- (NSString *)drawShape
{
NSString *outputShape = [NSString stringWithFormat:#"Drawing shape - (%.2f,%.2f), width - %f, height - %f", self.position.x, self.position.y, self.width, self.height];
NSLog(#"%#", outputShape);
return outputShape;
}
#end
-
Square.h
#import <Foundation/Foundation.h>
#import "Shape.h"
#interface Square : Shape
- (id)initWithWidth:(float)width andPosition:(CGPoint)position;
- (id)initWithWidth:(float)width andHeight:(float)height andPosition:(CGPoint)position;
- (id)initWithWidth:(float)width andHeight:(float)height;
- (id)initWithWidth:(float)width;
#end
-
Square.m
#import "Square.h"
#implementation Square
- (id) initWithWidth:(float)width andPosition:(CGPoint)position
{
self = [super init];
if (self) {
self.width = width;
self.height = width;
self.position = position;
}
return self;
}
// Returning the width as the width and height as you can't make a square with different sides
- (id)initWithWidth:(float)width andHeight:(float)height andPosition:(CGPoint)position
{
return [self initWithWidth:width andPosition:position];
}
- (id)initWithWidth:(float)width andHeight:(float)height
{
return [self initWithWidth:width andPosition:CGPointMake(100, 100)];
}
- (id)initWithWidth:(float)width
{
return [self initWithWidth:width andPosition:CGPointMake(100, 100)];
}
- (NSString *)drawShape
{
NSString *outputShape = [NSString stringWithFormat:#"Drawing shape - (%.2f,%.2f), width - %.2f, height - %.2f", self.position.x, self.position.y, self.width, self.height];
NSLog(#"%#", outputShape);
return outputShape;
}
#end
The thing to do here is to reimplement -[Square initWithWidth:andPosition:] like:
- (id)initWithWidth:(float)width andPosition:(CGPoint)position
{
self = [super initWithWidth:width andHeight:width andPosition:position];
return self;
}

Resources