Let's say for example that I have MyUITextViewSubclass which inherits from UITextView and MyUITextFieldSubclass which inherits from UITextField and both of those subclasses contain a lot of the same methods and properties to add similar behavior to those UI controls.
Since UITextView and UITextField inherit from different classes, is there an easy way to create an abstract class to combine all of that repeated code? In other words, is it possible to create an abstract class that I could inherit from for both of those subclasses and then just override the methods that are different between the two?
What I know so far:
I know Objective-C doesn't support multiple inheritance (inheritance from two or more classes)
I know I could add common methods using Categories, but I don't think that solves overriding init methods or adding private properties
Building on Amin's answer, this is how you could do it:
Step 1: Create a TextSurrogateHosting protocol that will contain all the methods of your UITextField and UITextView subclasses that you need to access from the methods that you want to add to both subclasses. This might for example be a text and setText: method, so that your methods can access and set the text of either a text field or a text view. It might look like this:
SPWKTextSurrogateHosting.h
#import <Foundation/Foundation.h>
#protocol SPWKTextSurrogateHosting <NSObject>
- (NSString *)text;
- (void)setText:(NSString *)text;
#end
Step 2: Create a TextSurrogate class that contains all the methods that you want to share between both the UITextField and the UITextView subclasses. Add those methods to a protocol so that we can use code completion in Xcode and avoid compiler warnings/errors.
SPWKTextSurrogate.h
#import <Foundation/Foundation.h>
#import "SPWKTextSurrogateHosting.h"
#protocol SPWKTextSurrogating <NSObject>
#optional
- (void)appendQuestionMark;
- (void)appendWord:(NSString *)aWord;
- (NSInteger)characterCount;
- (void)capitalize;
#end
#interface SPWKTextSurrogate : NSObject <SPWKTextSurrogating>
/* We need to init with a "host", either a UITextField or UITextView subclass */
- (id)initWithHost:(id<SPWKTextSurrogateHosting>)aHost;
#end
SPWKTextSurrogate.m
#import "SPWKTextSurrogate.h"
#implementation SPWKTextSurrogate {
id<SPWKTextSurrogateHosting> _host;
}
- (id)initWithHost:(id<SPWKTextSurrogateHosting>)aHost
{
self = [super init];
if (self) {
_host = aHost;
}
return self;
}
- (void)appendQuestionMark
{
_host.text = [_host.text stringByAppendingString:#"?"];
}
- (void)appendWord:(NSString *)aWord
{
_host.text = [NSString stringWithFormat:#"%# %#", _host.text, aWord];
}
- (NSInteger)characterCount
{
return [_host.text length];
}
- (void)capitalize
{
_host.text = [_host.text capitalizedString];
}
#end
Step 3: Create your UITextField subclass. It will contain three necessary boilerplate methods to forward unrecognized method invocations to your SPWKTextSurrogate.
SPWKTextField.h
#import <UIKit/UIKit.h>
#import "SPWKTextSurrogateHosting.h"
#import "SPWKTextSurrogate.h"
#interface SPWKTextField : UITextField <SPWKTextSurrogateHosting, SPWKTextSurrogating>
#end
SPWKTextField.m
#import "SPWKTextField.h"
#implementation SPWKTextField {
SPWKTextSurrogate *_surrogate;
}
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
_surrogate = [[SPWKTextSurrogate alloc] initWithHost:self];
}
return self;
}
#pragma mark Invocation Forwarding
- (void)forwardInvocation:(NSInvocation *)anInvocation
{
if ([_surrogate respondsToSelector:[anInvocation selector]]) {
[anInvocation invokeWithTarget:_surrogate];
} else {
[super forwardInvocation:anInvocation];
}
}
- (NSMethodSignature*)methodSignatureForSelector:(SEL)selector
{
NSMethodSignature* signature = [super methodSignatureForSelector:selector];
if (!signature) {
signature = [_surrogate methodSignatureForSelector:selector];
}
return signature;
}
- (BOOL)respondsToSelector:(SEL)aSelector
{
if ([super respondsToSelector:aSelector] ||
[_surrogate respondsToSelector:aSelector])
{
return YES;
}
return NO;
}
#end
Step 4: Create your UITextView subclass.
SPWKTextView.h
#import <UIKit/UIKit.h>
#import "SPWKTextSurrogateHosting.h"
#import "SPWKTextSurrogate.h"
#interface SPWKTextView : UITextView <SPWKTextSurrogateHosting, SPWKTextSurrogating>
#end
SPWKTextView.m
#import "SPWKTextView.h"
#import "SPWKTextSurrogate.h"
#implementation SPWKTextView {
SPWKTextSurrogate *_surrogate;
}
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
_surrogate = [[SPWKTextSurrogate alloc] initWithHost:self];
}
return self;
}
#pragma mark Invocation Forwarding
- (void)forwardInvocation:(NSInvocation *)anInvocation
{
if ([_surrogate respondsToSelector:[anInvocation selector]]) {
[anInvocation invokeWithTarget:_surrogate];
} else {
[super forwardInvocation:anInvocation];
}
}
- (NSMethodSignature*)methodSignatureForSelector:(SEL)selector
{
NSMethodSignature* signature = [super methodSignatureForSelector:selector];
if (!signature) {
signature = [_surrogate methodSignatureForSelector:selector];
}
return signature;
}
- (BOOL)respondsToSelector:(SEL)aSelector
{
if ([super respondsToSelector:aSelector] ||
[_surrogate respondsToSelector:aSelector])
{
return YES;
}
return NO;
}
#end
Step 5: Use it:
SPWKTextField *textField = [[SPWKTextField alloc] initWithFrame:CGRectZero];
SPWKTextView *textView = [[SPWKTextView alloc] initWithFrame:CGRectZero];
textField.text = #"The green fields";
textView.text = #"What a wonderful view";
[textField capitalize];
[textField appendWord:#"are"];
[textField appendWord:#"green"];
[textField appendQuestionMark];
NSLog(#"textField.text: %#", textField.text);
// Output: The Green Fields are green?
[textView capitalize];
[textView appendWord:#"this"];
[textView appendWord:#"is"];
NSLog(#"textView.text: %#", textView.text);
// Output: What A Wonderful View this is
This pattern should solve your problem. Hopefully :)
Some more background information is available here: https://developer.apple.com/library/mac/documentation/Cocoa/Conceptual/ObjCRuntimeGuide/Articles/ocrtForwarding.html#//apple_ref/doc/uid/TP40008048-CH105
What you want is a mixin. This is not supported in Objective-C. Categories are no mixins, because they add an api to one class not to many (>1) classes. Using categories, what is not possible for many reasons as you said, would not help you.
The usual way to solve that problem is to create a helper class containing the additional code and use it in both classes.
Then you will find yourself typing
[myUITextViewSubclass.helper doSomething]
instead of
[myUITextViewSubclass doSomething]
If this is really a problem, you can solve this with forward invocations. Just write a comment.
No. It is not possible.
The closest thing you could achieve would be to manually add functionality to UITextView to make it mimic UITextField. The obvious downside is that you must do this all manually, with your own code.
You could use a preprocessor macro, but that is error-prone.
Traits or Mixins are not supported by Objective-C, you only have built-in option of Categories.
But fortunately Objective-C Runtime has almost all tools for implementing own idea if mixing or traits with adding methods and properties to your class at runtime. You can read more about opportunities which Objective-C Runtime provides for you on Apple's documentation website Objective-C Runtime Docs
The idea is:
1) You can create an Objective-C protocol (Mixin), in which you will declare properties and methods.
2) Then you create a class (Mixin implementation), which will implement methods from this protocol.
3) You make your some class, in which you want to provide the possibility of composition with mixins, to conform that protocol (Mixin).
4) When your application launches, you add with Objective-C runtime all implementations from (Mixin implementation) class and properties declared in (Mixin) into your class.
5) voilĂ :)
Or you can use some ready open source projects such as "Alchemiq"
Related
I want create a class that can inherit from two custom class.
Do you have any idea to do this please?
Please see below my example:
first class:
#interface UIZoomableView : UIView
{
UITapGestureRecognizer *_tapGestureRecognizer;
}
and implementation:
- (void)onDoubleTap:(UITapGestureRecognizer *)sender
{
CGSize newSize;
CGPoint centerPoint = self.center;
if ([self isSmall])
{
newSize = [self bigSize];
}
else
{
newSize = [self smallSize];
}
[UIView animateWithDuration:0.3 animations:^{
self.size = newSize;
self.center = centerPoint;
}];
}
Second class:
#interface UIDraggableView : UIView
UIPanGestureRecognizer *_panGestureRecognizer;
#end
implementation:
- (void)handlePan:(UIPanGestureRecognizer*)sender
{
..
}
i want to create a custom view that can be zoomable and draggable.
Do you have any idea to do this please? (without copy code..)
I think something like protocols but i want default value for the base classes?
How can i implement this using protocol or something like protocols.
Thanks for any response!
Objective-C doesn't support multiple inheritance. You could use a protocol, composition and message forwarding to achieve the same result.
A protocol defines a set of methods that an object must implement (it's possible to have optional methods too). Composition is basically the technique of include a reference to another object and calling that object when it's functionality is required. Message forwarding is a mechanism that allows objects to pass messages onto other objects, for example, an object that is included via composition.
Apple Reference:
Protocols
Composition
Message Forwarding (and specifically Forwarding and Multiple Inheritance)
So, in your case Composition might be a solution, below is the example code
#interface ClassA : NSObject {
}
-(void)methodA;
#end
#interface ClassB : NSObject {
}
-(void)methodB;
#end
#interface MyClass : NSObject {
ClassA *a;
ClassB *b;
}
-(id)initWithA:(ClassA *)anA b:(ClassB *)aB;
-(void)methodA;
-(void)methodB;
#end
#implementation MyClass
-(id)initWithA:(ClassA *)anA b:(ClassB *)aB {
a = anA ;
b = aB ;
}
-(void)methodA {
[a methodA] ;
}
-(void)methodB {
[b methodB] ;
}
#end
If you don't want to implement all the methods from ClassA and ClassB in MyClass, you can use Message Forwarding in MyClass to handle all the method invocations. Below works fine as long as ClassA and ClassB do not have any common methods.
#implementation MyClass
-(id)initWithA:(ClassA *)anA b:(ClassB *)aB {
a = anA ;
b = aB ;
}
//This method will be called, when MyClass can not handle the method itself
-(void)forwardInvocation:(NSInvocation *)anInvocation
{
if ([a respondsToSelector:[anInvocation selector]])
[a invokeWithTarget:someOtherObject];
else if ([b respondsToSelector:[anInvocation selector]])
[b invokeWithTarget:someOtherObject];
else
[super forwardInvocation:anInvocation];
}
#end
The closest that you can get to multiple inheritance in Objective C is with categories. These are a mechanism for adding additional methods to a class that already exists.
Note that this has some important limitations:
You can't add properties or ivars using a category, though you can use associated objects to get a similar effect;
The compiler won't tell you if you have methods with the same name that are declared in the class and the category, or in two categories, so you have to be careful to avoid name collision;
This won't appear as a proper class (because Objective C does not have multiple inheritance) so you won't have something in your code called ScrollableZoomableView which inherits from ScrollableView and ZoomableView. That's not possible in Objective C (unlike C++ for example).
You need the -ObjC flag when linking files with categories, otherwise you'll get unrecognized selector errors when you run your code;
You can't get your code called during -init or +initialize, because those belong to the base class. You'll need to initialize your properties explicitly. You can still use +load though;
You can't intercept dealloc either, so you may need to be careful to explicitly deregister your listeners too.
You want something like this:
#interface UIView (Zoomable)
#property (nonatomic) UITapGestureRecognizer * my_tapGestureRecognizer;
#end
#implementation UIView (Zoomable)
-(void)my_enableZooming() {
self.my_tapGestureRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(my_onDoubleTap:)];
self.my_tapGestureRecognizer.numberOfTapsRequired = 2;
[self addGestureRecognizer:self.my_tapGestureRecognizer];
}
-(void)my_disableZooming() {
[self removeGestureRecognizer:self.my_tapGestureRecognizer];
self.my_tapGestureRecognizer = nil;
}
-(void)my_onDoubleTap:(UITapGestureRecognizer *)sender {
...
}
-(UITapGestureRecognizer)my_tapGestureRecognizer {
return objc_getAssociatedObject(self, #selector(my_tapGestureRecognizer));
}
-(void)setMy_tapGestureRecognizer:(UITapGestureRecognizer)value {
objc_setAssociatedObject(self, #selector(my_tapGestureRecognizer), value, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
#end
#interface UIView (Draggable)
#property (nonatomic) UIPanGestureRecognizer * my_panGestureRecognizer;
#end
#implementation UIView (Draggable)
-(void)my_enableDragging() {
self.my_panGestureRecognizer = ...;
}
-(void)my_disableDragging() {
...
}
-(void)my_handlePan:(UIPanGestureRecognizer*)sender {
...
}
-(UIPanGestureRecognizer)my_panGestureRecognizer {
return objc_getAssociatedObject(self, #selector(my_panGestureRecognizer));
}
-(void)setMy_panGestureRecognizer:(UIPanGestureRecognizer)value {
objc_setAssociatedObject(self, #selector(my_panGestureRecognizer), value, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
#end
This is the weirdest thing I've ever encountered, and the problem is consistent across an iPhone 4 and iPhone 5s...
I've created a subclass of UITextField to add some custom functionality, and have set a UITextField's custom class to my custom class in the storyboard.
Great, all good - but.. Anytime I tap to open the field, I can type fine - as soon as I hit the emoji globe part of the keyboard, the app instantly locks up. It doesn't crash, I just cannot do anything, the typing indicator stops blinking and the app just hangs infinitely..
So very strange.
Here's the custom class I've created.
Header
#import <UIKit/UIKit.h>
#interface GenericTextField : UITextField <UITextFieldDelegate>
#property id nextField;
#property id nextCallbackTarget;
#property SEL nextCallbackSelector;
#end
Implementation
#import "GenericTextField.h"
#implementation GenericTextField
- (id)initWithCoder:(NSCoder *)aDecoder
{
if (self = [super initWithCoder:aDecoder]) {
[self setup];
}
return self;
}
- (void)setup
{
self.delegate = self;
}
- (BOOL)textFieldShouldBeginEditing:(UITextField *)textField
{
return YES;
}
- (BOOL)textFieldShouldReturn:(UITextField *)textField
{
if ([self.nextField respondsToSelector:#selector(becomeFirstResponder)]) {
[self.nextField becomeFirstResponder];
} else {
[self resignFirstResponder];
if ([self.nextCallbackTarget respondsToSelector:self.nextCallbackSelector]) {
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Warc-performSelector-leaks"
[self.nextCallbackTarget performSelector:self.nextCallbackSelector];
#pragma clang diagnostic pop
}
}
return NO;
}
#end
Here's another interesting part. If I comment out the portion where I'm setting the delegate to self, everything works fine.. However, if I comment out my custom delegate methods and keep the delegate set to self in the setup method, I still get the freeze. This seems to be specifically linked to setting the delegate? Why? Does it have to do with setting it to self from the initWithCoder? If so, why does it just happen in UITextField and none of my other custom classes that set delegates to self like in a UIScrollView subclass I've made?
Alright, took a little searching but maybe this answer will help anyone trying to figure it out.
UITextField is unique AFAIK. You can usually use a class as its own
delegate with no particular problems. For UITextField you must create
an actual delegate (that could, of course, call methods on the
UITextField for which it's a delegate. Just be careful to avoid retain
loops, even if you're using ARC).
Which led me to trying some updated code in my implantation and creating a shared delegate class for handling the delegate in the simplest way I could think of. Here's the updated implementation.
Hope it helps!
#import "GenericTextField.h"
#interface GenericTextFieldDelegate : NSObject <UITextFieldDelegate>
+ (GenericTextFieldDelegate *)sharedDelegate;
#end
#implementation GenericTextFieldDelegate
+ (GenericTextFieldDelegate *)sharedDelegate
{
static GenericTextFieldDelegate *genericTextFieldDelegate;
#synchronized(self) {
if (!genericTextFieldDelegate) {
genericTextFieldDelegate = [[GenericTextFieldDelegate alloc] init];
}
}
return genericTextFieldDelegate;
}
- (BOOL)textFieldShouldBeginEditing:(UITextField *)textField
{
return YES;
}
- (BOOL)textFieldShouldReturn:(GenericTextField *)textField
{
if ([textField.nextField respondsToSelector:#selector(becomeFirstResponder)]) {
[textField.nextField becomeFirstResponder];
} else {
[textField resignFirstResponder];
if ([textField.nextCallbackTarget respondsToSelector:textField.nextCallbackSelector]) {
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Warc-performSelector-leaks"
[textField.nextCallbackTarget performSelector:textField.nextCallbackSelector];
#pragma clang diagnostic pop
}
}
return NO;
}
#end
#implementation GenericTextField
- (id)initWithCoder:(NSCoder *)aDecoder
{
if (self = [super initWithCoder:aDecoder]) {
[self setup];
}
return self;
}
- (void)setup
{
self.delegate = [GenericTextFieldDelegate sharedDelegate];
}
#end
I have a procedure that I'll need in a lot (if not all) of my view controllers. I want to know how I can put it in one place (for code cleanliness and maintenance) and utilize it elsewhere.
There are more ways on how to approach this - depending on what exactly you would like to achieve.
If this methods are tied with UIViewController's life and data you would probably want to subclass UIViewController or make an UIViewController category.
A: Subclassing (you want to add some custom properties, variables, methods or you want to override a method):
MySubclassedViewController.h
#import <UIKit/UIKit.h>
#interface MySubclassedViewController : UIViewController
#property (copy) NSString *myVerySpecialString;
-(void) myVerySpecialMethod;
#end
MySubclassedViewController.m
#import "MySubclassedViewController.h"
#implementation MySubclassedViewController
-(void) initialization
{
self.myVerySpecialString = #"initialized";
}
- (id)initWithCoder:(NSCoder*)aDecoder
{
self = [super initWithCoder:aDecoder];
if (self)
{
[self initialization];
}
return self;
}
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self)
{
[self initialization];
}
return self;
}
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self)
{
[self initialization];
}
return self;
}
-(void) viewDidLoad
{
[super viewDidLoad];
[self myVerySpecialMethod];
}
-(void) myVerySpecialMethod
{
if ([self.myVerySpecialString isEqualToString: #"initialized"])
{
self.backgroundColor = [UIColor yellowColor];
}
}
#end
B: Category (you just want to add some extra method to a class):
UIViewController+SpecialCatrgory.h
#import <UIKit/UIKit.h>
#interface UIViewController (SpecialCategory)
-(void) myVerySpecialMethod;
#end
UIViewController+SpecialCatrgory.m
#import "UIViewController+SpecialCatrgory.h"
#implementation UIViewController (SpecialCategory)
-(void) myVerySpecialMethod
{
self.backgroundColor = [UIColor yellowColor];
}
#end
C: Dedicated helper class
On the other hand if you find yourself using some independent method on more than one place you might
want to consider writing up a helper class and use it as a singleton.
MyHelperClass.h
#interface MyHelperClass : NSObject
+ (instancetype)sharedHelper;
-(NSString *) myVerySpecialMethod;
#end
MyHelperClass.m
#import "MyHelperClass.h"
#implementation MyHelperClass
+ (instancetype)sharedHelper
{
static MyHelperClass *_sharedHelper = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
_sharedHelper = [[MAConnectionClient alloc] init];
});
return _sharedHelper;
}
-(NSString *) myVerySpecialMethod
{
return #"a result from your very special method";
}
#end
You use it simply by importing MyHelperClass.h (or putting it in -Prefix.pch), without explicitly creating an instance. For example:
NSString *someString = [[MyHelperClass sharedHelper] myVerySpecialMethod];
There are many ways to achieve this.
Create a base viewcontroller and add your procedure. Subclass this in all your view controller.
Create a common utility class and add your procedure and make it as a class method.
Add your procedure in .pch file.
We have many ways to do it but in general create one global class, import it in YourProjectName-Prefix.pch file.
We can also go for another way i.e create any class method and you can call it anywhere through it's Class Name.
One example, you might have seen many times in your code-
:
In appDelegate.h file, if we make this method and implement it in appDelegate.m file then
+ (NSString *)applicationDocumentDir
{
return [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject];
}
then we can access it from anywhere in the code like :
NSString *strTemp = [AppDelegate applicationDocumentDir];
To know more better way have a look here.
Use of a singleton for creating a basic style helper class
If you're not sure that the method will be used in all Controllers, I'd recommend creating a category for the functionality you're adding. You can find a good intro to categories here.
If you're sure you'll need it in all UIViewControllers, creating a base Controller and subclassing should be the better approach.
All other methods of implementing (Placing a class method in a utility / Adding to *-Prefix.pch) will work, but might not be ideal solutions (assuming the functionality your're adding is only applicable to UIViewController).
I have an abstract interface in Objective-C where every sub-class needs to set up a property and then do the exact same thing with that property at the end of init. I'm trying to avoid duplicated code with something like this:
Interface File
#interface Shape : NSObject
#property (nonatomic) PropertyType *prop;
- (id)init;
- (void)initProperty;
#end
Implementation File
#implementation Shape
- (id)init
{
if(self = [super init]) {
[self initProperty];
[prop doSomething];
}
return self;
}
- (void)initProperty
{
}
#end
My problem is that every sub-class will need a different set of parameters passed to initProperty in order to implement the method correctly:
#implementation Rectangle
- (void)initPropertyWithRect:(CGRect)rect
{
prop = [RectangleStuff rectangleWithRect:rect];
}
#end
#implementation Circle
- (void)initPropertyWithRadius:(CGFloat)radius
{
prop = [CircleStuff circleWithRadius:radius];
}
#end
Is there a clean way to do what I'm trying to do in Objective-C? So far, my options seem to be:
Create a "property bag", and just pass around an NSDictionary.
Duplicate the [property doSomething]; code in every subclass.
Somehow pass in a factory object to init, and have the factory object create prop. This approach seems the cleanest, but I'd need the factory object to keep the rect and/or radius as internal state somehow, and that doesn't seem clean to me.
Any thoughts?
I would probably choose #2 (to keep it simple). If the property is only set once
(in the subclass init method), you could override the property setter method in the
superclass, and do the additional stuff there.
Untested code:
- (void)setProp:(PropertyType *)prop
{
_prop = prop; // (Assuming ARC)
[_prop doSomething];
}
First, I feel obligated to mention that your init function should not do anything besides initialize the object. That said, every rule has a time and a place to be broken, so I'll offer what suggestions I can.
Your init function is no different than any other function. You can do things before and after you call super. While generally discouraged, this would be a good place to do it. Your init in your subclass would now look like this:
- (id)init
{
self.myProperty = value;
self = [super init];
if (self) {
// more init stuff
}
return self;
}
I ended up using a variant of what was suggested in the other two answers:
Shape.h
#interface Shape : NSObject
#property (nonatomic) PropertyType *prop;
- (id)initWithProperty:(PropertyType *prop);
#end
Shape.m
#implementation Shape
- (id)initWithProperty:(PropertyType *)prop
{
if(self = [super init]) {
_prop = prop;
[_prop doSomething];
}
return self;
}
#end
Rectangle.m/Circle.m
#implementation Rectangle
- (void)initWithRect:(CGRect)rect
{
return [self initWithProperty:[RectangleStuff rectangleWithRect:rect]];
}
#end
#implementation Circle
- (void)initWithRadius:(CGFloat)radius
{
return [self initWithProperty:[CircleStuff circleWithRadius:radius]];
}
#end
I have an ivar which is mentioned in my header
#interface MyClass : UIView{
int thistone;}
- (IBAction)toneButton:(UIButton *)sender;
#property int thistone;
#end
and I have synthesized it in the implementation:
#implementation MyClass
#synthesize thistone;
- (IBAction)toneButton:(UIButton *)sender {
if(thistone<4)
{thistone=1000;} // I hate this line.
else{thistone=thistone+1; }
}
I cannot find (or find in any manual) a way to set a nonzero initial value. I want it to start at 1000 and increase by 1 each time I press the button. The code does exactly what I intend, but I'm guessing there's a more proper way to do it that saves me the if/else statement above. Code fixes or pointers to specific lines in online documentation greatly appreciated.
Every object has a variant of the init method called at instantiation. Implement this method to do such setup. UIView in particular have initWithFrame: and initWithCoder. Best to override all and call a separate method to perform required setup.
For example:
- (void)commonSetup
{
thisTone = 1000;
}
- (id)initWithFrame:(CGRect)frame
{
if (self = [super initWithFrame:frame])
{
[self commonSetup];
}
return self;
}
- (id)initWithCoder:(NSCoder *)coder
{
if (self = [super initWithCoder:coder])
{
[self commonSetup];
}
return self;
}