Can't rewrite Setter methods in subclasses - objective-c

I am creating a new class in Obj-C called “Complex” which will deal with complex numbers.
I have 4 instance variables declared in the .h as follows:
#property (nonatomic) double re, im;
#property (nonatomic) double mod, arg;
and later, they are synthesized in the .m file:
#synthesize re, im; //real / imaginary parts
#synthesize mod, arg; //modulus / argument parts
In the complex class, I have many methods which involve functions/operations with complex numbers. Since each of these will only modify the complex number in either Cartesian/Polar form, I need a way to update the other form after a function.
I decided to do this by modifying the setter methods for all 4 variables (which is why I chose them to be nonatomic).
I’ve finished making this class, and everything works fine. However, I now would like to create 2 subclasses of Complex which would be CComplex (Cartesian) and PComplex (Polar). These subclasses would only work with the Cartesian/Polar instance variables.
It would be ideal to use these classes when you don’t need to interact with the other form as it increases speed when you are performing functions with Complex numbers several thousand/million times a second (Since the Updater in the setter methods would be skipped).
The problem I’m coming across is that I cannot rewrite the setter method in the subclasses, and nor can I recreate the instance variables (with the same names).
Can someone help me with this problem please? Thanks
Edit: Here's the relevant code:
Here's how I tried to implement the setter methods in my subclasses at first:
.h
#interface CComplex : Complex
#property (nonatomic) double re, im;
//
////Setter Methods
-(void) setRe:(double)r;
-(void) setIm:(double)i;
////
//
#end
#interface PComplex : Complex
#property (nonatomic) double mod, arg;
//
////Setter Methods
-(void) setMod:(double)m;
-(void) setArg:(double)a;
////
//
#end
.mm
#implementation CComplex
#synthesize re, im;
//
////Setter Methods
-(void) setRe:(double)r {
re = r;
}
-(void) setIm:(double)i {
im = i;
}
////
//
#end
#implementation PComplex
#synthesize mod, arg;
//
////Setter Methods
-(void) setMod:(double)m {
mod = m;
}
-(void) setArg:(double)a {
arg = a;
}
////
//
#end

I don’t know how you are overriding the setter but the common case should be:
#synthesize = re = _re;
- (void)setRe:(double)re {
// your code
_re = re;
}
Or instead of overriding the setter you can use lazy instantiation:
- (double)re {
if(!_re) {
_re = …// your code
}
return _re
}
To declare a public property, put in your class Ex: MyClass.h interface (not in the .m):
#import <Foundation/Foundation.h>
#interface MyClass : NSObject
#property (nonatomic) double re;
#end
To set a superclass property in a subclass you don't have to synthesize or redefine a property in a subclass:
super.re = ...;

Related

add category property to a class confirming to a protocol

I have a generator which returns objects conforming to protocol A.
I would like to add a property, probably with categories, to these objects so i can do something to serve my purposes, which obviously isn't there in the protocol.
is this doable?
The more I've thought about this, the more I agree that it's not a duplicate, and in fact the answer is very straightforward as long as what you say you want is what you really want.
Given that you are returning values that conform to some protocol, create a type that conforms to that protocol, and forwards all protocol methods to a wrapped value. Then you can add whatever additional properties you'd like.
For example, given a protocol like:
#protocol Runnable <NSObject>
- (void)run;
#end
You can create a trivial wrapper like:
#interface AnyRunnable: NSObject <Runnable>
- (instancetype)initWithRunnable:(id<Runnable>)runnable;
#end
#interface AnyRunnable (Private)
#property (nonatomic, readwrite) id<Runnable> wrapped;
#end
#implementation AnyRunnable
- (instancetype)initWithRunnable:(id<Runnable>)wrapped
{
self = [super init];
if (self) {
self.wrapped = wrapped;
}
return self;
}
- (void)run {
[self.wrapped run];
}
#end
Now, AnyRunnable is a Runnable, so you can return that from your method. It's also a type you control, so you can add any properties you like to it. This scales to any protocol; you just need to implement the required methods.
It's not possible to do this via a category for the reasons given in Why can't categories have instance variables? (If it were possible to add properties based on protocols, but not classes, then you could just define a protocol that matched your class, and bypass that limitation.)
Here is possible approach (based on Objective-C associated objects). Tested & worked.
Assume we have some class, which we cannot touch
#interface SomeClass: NSObject
#end
#implementation SomeClass
#end
Then some new properties can inject in the following way
#interface SomeClass (VirtualProperty)
#property (atomic) NSInteger virtualProperty;
#property (nonatomic, readonly) NSInteger calculableProperty;
#end
static const char *kVirtualPropertyKey = "virtualProperty";
#implementation SomeClass (VirtualProperty)
#dynamic virtualProperty;
- (NSInteger)calculableProperty {
return self.virtualProperty * 2;
}
- (NSInteger)virtualProperty {
return [(NSNumber *)objc_getAssociatedObject(self,
kVirtualPropertyKey) integerValue];
}
- (void)setVirtualProperty:(NSInteger)newValue {
objc_setAssociatedObject(self, kVirtualPropertyKey,
#(newValue), OBJC_ASSOCIATION_RETAIN);
}
#end
Usage:
SomeClass *some = SomeClass.new;
some.virtualProperty = 5;
NSLog(#"Result: %lu", some.calculableProperty);

Subclassing PFObject And Overriding Dynamically Added Accessors

I understand how to subclass PFObject, but I am not certain how to perform additional custom code in an accessor, while still calling the generic implementation of that accessor as defined and #dynamic-ally added by Parse (which does the proper thing depending on the property's type, e.g. PFRelation, and so forth).
For instance...
// MyPFObjectSubclass.h
#import <Parse/Parse.h>
#interface MyPFObjectSubclass.h : PFObject<PFSubclassing>
#property (retain, nonatomic) id myProperty;
+ (NSString *)parseClassName;
#end
// MyPFObjectSubclass.m
#import "MyPFObjectSubclass.h"
#import <Parse/PFObject+Subclass.h>
#implementation MyPFObjectSubclass
#dynamic myProperty;
+ (NSString *)parseClassName {
return #"MyPFObjectSubclass";
}
- (void)setMyProperty:(id)someProperty {
// insert some custom code here, e.g. for validation...
// call the generic, dynamic implementation of setMyProperty, but how?
// obviously, you cannot call [super setMyProperty:someProperty];
}
#end
Any help is appreciated.
All you need to do is implement your own accessors and skip #dynamic

Using ObjC class extensions' vars in class category

I declare a class extension interface adding vars to it. Is it possible to access those vars in a category of that class?
Sure - any variable is accessible through the runtime, even if it isn't visible in the #interface:
SomeClass.h
#interface SomeClass : NSObject {
int integerIvar;
}
// methods
#end
SomeClass.m
#interface SomeClass() {
id idVar;
}
#end
#implementation SomeClass
// methods
#end
SomeClass+Category.m
#implementation SomeClass(Category)
-(void) doSomething {
// notice that we use KVC here, instead of trying to get the ivar ourselves.
// This has the advantage of auto-boxing the result, at the cost of some performance.
// If you'd like to be able to use regex for the query, you should check out this answer:
// http://stackoverflow.com/a/12047015/427309
static NSString *varName = #"idVar"; // change this to the name of the variable you need
id theIvar = [self valueForKey:varName];
// if you want to set the ivar, then do this:
[self setValue:theIvar forKey:varName];
}
#end
You can also use KVC to get iVars of classes in UIKit or similar, while being easier to use than pure runtime-hacking.

How can I assign values to other class variable in objective-c

The below coding is working and I can see the values in my second screen. But I am using the same in other classes with different variables in this format. But it dosent show me the variable if after i type the classname with a dot. I cant figure this out. Is there any way to pass values to other class.
InstallProfiler_2 *installProfiler2 = [[InstallProfiler_2 alloc] initWithNibName:#"InstallProfiler_2" bundle:nil];
installProfiler2.profilerType2 = profilerType;
[self.navigationController pushViewController:installProfiler2 animated:NO];
[installProfiler2 release];
Make sure that:
You have imported the class header.
The #property declarations are in this header and not a class extension.
#property refers to ivars so when you say
if after i type the classname with a dot
this terminology is incorrect, you probably mean after you start typing the name of the variable which has points to an instance of a class.
ClassA.h
#interface ClassA : NSObject
#property (nonatomic, weak) NSInteger myInt;
#end
ClassA.m
#implementation ClassA
#synthesize myInt = _myInt;
#end
ClassB.m
#import "ClassA.h" // <- Import the header of the class
# implementation ClassB
// .. other methods and stuff
- (void)myMethod;
{
ClassA *instanceOfClassA = [[ClassA alloc] init]; // <- Working with an instance not a class
instanceOfClassA.myInt = 1;
}
#end
UPDATE
Make sure your #property () does not have readonly between the round brackets.
Also make sure you have either #synthesize'd the ivar in the implementation or have provided both a getter and a setter for the ivar.
Failing that show some relevant code so we can actually see what your doing - we are answering pretty blindly here.
The dot syntax is only available with property/synthesize
Create a custom setter/getter:
+ (BOOL)awesomeClassVar {
return _classVar;
}
+ (void)setAwesomeClassVar:(BOOL)newVar {
_classVar = newVar;
}
then call as a method from the other class:
BOOL theOtherClassVar = [AwesomeClass awesomeClassVar];
[AwesomeClass setAwesomeClassVar:!theOtherClassVar];

Hide instance variable from header file in Objective C

I came across a library written in Objective C (I only have the header file and the .a binary).
In the header file, it is like this:
#interface MyClass : MySuperClass
{
//nothing here
}
#property (nonatomic, retain) MyObject anObject;
- (void)someMethod;
How can I achieve the same thing? If I try to declare a property without its corresponding ivar inside the interface's {}, the compiler will give me an error. Ultimately, I want to hide the internal structure of my class inside the .a, and just expose the necessary methods to the header file. How do I declare instance variables inside the .m? Categories don't allow me to add ivar, just methods.
For 64 bit applications and iPhone applications (though not in the simulator), property synthesis is also capable of synthesizing the storage for an instance variable.
I.e. this works:
#interface MyClass : MySuperClass
{
//nothing here
}
#property (nonatomic, retain) MyObject *anObject;
#end
#implementation MyClass
#synthesize anObject;
#end
If you compile for 32 bit Mac OS X or the iPhone Simulator, the compiler will give an error.
You may use of the same idiom used in Cocoa classes. If you have a look to NSString class interface in NSString.h you'll see that there is no instance variable declared. Going deeper in GNUstep source code you'll find the trick.
Consider the following code.
MyClass.h
#interface MyClass : NSObject
// Your methods here
- (void) doSomething;
#end
MyClass.m
#interface MyClassImpl : MyClass {
// Your private and hidden instance variables here
}
#end
#implementation MyClass
+ (id) allocWithZone:(NSZone *)zone
{
return NSAllocateObject([MyClassImpl class], 0, zone);
}
// Your methods here
- (void) doSomething {
// This method is considered as pure virtual and cannot be invoked
[self doesNotRecognizeSelector: _cmd];
}
#end
#implementation MyClassImpl
// Your methods here
- (void) doSomething {
// A real implementation of doSomething
}
#end
As you can see, the trick consist in overloading allocWithZone: in your class. This code is invoked by default alloc provided by NSObject, so you don't have to worry about which allocating method should be used (both are valid). In such allocWithZone:, you may use the Foundation function NSAllocateObject() to allocate memory and initialize isa for a MyClassImpl object instead of MyClass. After that, the user is dealing with a MyClassImpl object transparently.
Of course, the real implementation of your class shall be provided by MyClassImpl. The methods for MyClass shall be implemented in a way that considers a message receiving as an error.
You can use a class extension. A class extension is similar as category but without any name. On the Apple documentation they just define private methods but in fact you can also declare your internal variables.
MyClass.h
#class PublicClass;
// Public interface
#interface MyClass : NSObject
#property (nonatomic, retain) PublicClass *publicVar;
#property (nonatomic, retain) PublicClass *publicVarDiffInternal;
- (void)publicMethod;
#end
MyClass.m
#import "PublicClass.h"
#import "InternalClass.h"
// Private interface
#interface MyClass ( /* class extension */ )
{
#private
// Internal variable only used internally
NSInteger defaultSize;
// Internal variable only used internally as private property
InternalClass *internalVar;
#private
// Internal variable exposed as public property
PublicClass *publicVar;
// Internal variable exposed as public property with an other name
PublicClass *myFooVar;
}
#property (nonatomic, retain) InternalClass *internalVar;
- (void)privateMethod;
#end
// Full implementation of MyClass
#implementation MyClass
#synthesize internalVar;
#synthesize publicVar;
#synthesize publicVarDiffInternal = myFooVar
- (void)privateMethod
{
}
- (void)publicMethod
{
}
- (id)init
{
if ((self = [super init]))
{
defaultSize = 512;
self.internalVar = nil;
self.publicVar = nil;
self.publicVarDiffInternal = nil; // initialize myFooVar
}
return self;
}
#end
You can give MyClass.h to anyone with just your public API and public properties. On MyClass.m you declare your member variable private and public, and your private methods, on your class extension.
Like this it's easy to expose public interfaces and hide detail implementation. I used on my project without any troubles.
According to the documentation I've been looking at there is no problem. All you have to do to hide instance variables is to declare them at the start of the #implementation section, inside { ... }. However, I'm a relative newcomer to Objective C and there's a chance I have misunderstood something - I suspect that the language has changed. I have actually tried this system, using XCode 4.2, building code for the iPad, and it seems to work fine.
One of my sources for this idea is the Apple developer documentation at http://developer.apple.com/library/ios/#documentation/cocoa/conceptual/objectivec/Chapters/ocDefiningClasses.html, which gives this pattern:
#implementation ClassName
{
// Instance variable declarations.
}
// Method definitions.
#end
Two possibilities:
It could be taking advantage of the modern runtime's ability to synthesize instance variables, as bbum suggested.
The property might not have an underlying instance variable in that class. Properties do not necessarily have a one-to-one mapping with instance variables.
No you can't. But you can do this if you're not using #property:
.h
#interface X : Y {
struct X_Impl* impl;
}
-(int)getValue;
#end
.m
struct X_Impl {
int value;
};
...
#implementation X
-(void)getValue {
return impl->value * impl->value;
}
#end
How about a macro trick?
Have tested code below
have tested with dylibs - worked fine
have tested subclassing - Warning! will break, I agree this makes the trick not that useful, but still I think it tells some about how ObjC works...
MyClass.h
#interface MyClass : NSObject {
#ifdef MYCLASS_CONTENT
MYCLASS_CONTENT // Nothing revealed here
#endif
}
#property (nonatomic, retain) NSString *name;
#property (nonatomic, assign) int extra;
- (id)initWithString:(NSString*)str;
#end
MyClass.m
// Define the required Class content here before the #import "MyClass.h"
#define MYCLASS_CONTENT \
NSString *_name; \
int _extra; \
int _hiddenThing;
#import "MyClass.h"
#implementation MyClass
#synthesize name=_name;
#synthesize extra=_extra;
- (id)initWithString:(NSString*)str
{
self = [super init];
if (self) {
self.name = str;
self.extra = 17;
_hiddenThing = 19;
}
return self;
}
- (void)dealloc
{
[_name release];
[super dealloc];
}
#end
DON'T do this, but I feel it should be noted that the runtime has the ability to add ivars whenever you want with class_addIvar
I was able to do the following in my library:
myLib.h:
#interface MyClass : SomeSuperClass <SomeProtocol> {
// Nothing in here
}
- (void)someMethods;
#end
myLib.m
#interface MyClass ()
SomeClass *someVars;
#property (nonatomic, retain) SomeClass *someVars;
#end
#implementation MyClass
#synthesize someVar;
- (void)someMethods {
}
#end
The protocol is optional of course. I believe this also makes all your instance variables private though I'm not 100% certain. For me it's just an interface to my static library so it doesn't really matter.
Anyway, I hope this helps you out. To anyone else reading this, do let me know if this is bad in general or has any unforeseen consequences. I'm pretty new to Obj-C myself so I could always use the advice of the experienced.
I don't think the following code written in another answer is working as expected.
The "SomeClass *someVars" defined in the extension class is not an instance variable of MyClass. I think it is a C global variable. If you synthesize someVars, you will get compile error. And self.someVars won't work either.
myLib.h
#interface MyClass : SomeSuperClass <SomeProtocol> {
// Nothing in here
}
- (void)someMethods;
#end
myLib.m
#interface MyClass ()
SomeClass *someVars;
#property (nonatomic, retain) SomeClass *someVars;
#end
#implementation MyClass
#synthesize someVar;
- (void)someMethods {
}
#end