How to make all constructors of a class private and create static factory methods? - objective-c

In Java, I would do the following:
final class Person {
private Person() { }
public static Person makeNewPerson() {
Person p = new Person();
// any initialization code...
return p;
}
}
In Objective-C, my first attempt would be:
#interface Person : NSObject
// How to hide constructors here?
+ (Person *) makeNewPerson;
#end
#implementation Person
+ (Person *) makeNewPerson
{
Person *p = [[Person alloc] init];
// setup...
return p;
}
#end
The reason I want to do this is mainly because I will have many instances of this class, and I would like to use a cache to reuse instances instead of allowing the creation of copies.
Thanks!

In objective-c is not necessary to create declaration for methods. Create only implementation and is all you need to make method "private".
Private in quotes because there is no way to make truly private methods.

Related

objective-c equivalent to java anonymouse interface implementation

I hope the title is precise enough.
I was wondering, how I can pass a interface implementation to an object in objc language.
In java it would look like:
public interface MyInterface {
void onData();
}
The implementing class
public class ImplementMyInterface {
// ...
// other methods
///
void registerInterface(){
MyInterface myInterface = new MyInterface(){
#Override
public void onData(){
// process data here within the class
}
};
}
}
And in objc?
id myinterface.
How to implement it in the class?
Is there only the possibility to let the class inherit the interface?
Like
interface MyInterface : NSObject
and the implementing class
MyImplementingClass : MyInterface
Or is there another possibility?
Thank you in advance
Objective-C has anonymous functions (blocks), but it doesn't have anonymous classes. So, the only way to implement a protocol (which is the objective-c term for an interface) is to make some class conform to that protocol (using your terminology, make that class "inherit" from that protocol) and add a protocol implementation inside that class' implementation.
I was able to solve my problem.
I was only able to import the MyInterface header file in my ImplementMyInterface.m file, but rather in the ImplementMyInterface.h file.
So everything I could do was inside the ImplementMyInterface.m file.
// ImplementMyInterface.m
#import "MyInterface.h"
// inner class
#interface MyInternalInterface : NSObject<MyInterface>
#property (retain) ImplementMyInterface * implementation;
#end
// the actual class
#implementation ImplementMyInterface
MyInternalInterface * _internalInterface;
+(instancetype) build {
// construct myself
ImplementMyInterface * implementatMyInterface = [[ImplementMyInterface alloc] init];
// init inner class object
_internalInterface = [[MyInternalInterface alloc] init];
// register myself
[_internalInterface setImplementation:implementatMyInterface];
return implementatMyInterface;
}
- (NSString *) theActualData {
return #"The actual data";
}
// end of implementation class
#end
// implementation of inner class
#implementation MyInternalInterface
#synthesize implementation;
- (NSString *) onData {
if(implementation != nil)
return [implementation theActualData];
return #"";
}
// end of ImplementMyInterface.m

Objective C reference to class implementing an protocol

How to reference to a class (not an instance of it!) which implements a specific protocol?
+(id<Data>) dataForName:(NSString *)name {
id<DataManager> manager = SpecializedDataManager; // <-- which datatype does "manager" have to be?
return [[manager sharedManager] get:name]; //Getting data over a singleton of manager
}
Where Data and DataMangerare protocols and SpecializedDataManager is a class implementing the DataManager protocol.
I haven't tried this myself, but you should be able to use a pointer-to-class, although I doubt that you could specify that the class must implement a certain protocol:
static Class manager = NULL;
+ (void)someInitMethod
{
manager = [SpecializedDataManager class];
NSAssert([manager conformsToProtocol:#protocol(DataManager)], #"Achtung!");
}
If I understood you correct you want to write something like this:
id<SomeProtocol> someObject = AnotherObjectConformingThisProtocol;
Class class = [(NSObject*)SomeObject class];
if ([someObject isKindOfClass:[AnotherObjectConformingThisProtocol class]]) {}
if (class == [AnotherObjectConformingSomeProtocol class]) {}
If no - please clarify what exactly do you mean.
UPDATE: I've read your comment near another post and got it:
Create wrapper classes for your DataManager and Data protocols:
#interface DataClass : NSObject <Data>
#end
#interface DataManagerClass : NSObject <DataManager>
#end
And use code like this:
+(DataClass*) dataForName:(NSString *)name {
DataManagerClass* manager = SpecializedDataManager; // <-- which datatype does "manager" have to be?
return [[manager sharedManager] get:name]; //Getting data over a singleton of manager
}
Is this what you're looking for:
+(id<Data>) dataForName:(NSString *)name {
Class<DataManager> manager = [SpecializedDataManager class];
return [[manager sharedManager] get:name];
}

Traverse a class hierarchy from base to all descendants

In an iOS app I am writing I want to traverse a class hierarchy to make an inventory of all subclasses. My intent is to use each subclass type as a key -- via NSStringForClass() -- in a dictionary.
My motivation is to be able to automatically discover all variants of a base class so that I can call methods associated with that class. For reasons of division of labor I prefer not to use method overriding here.
Is it possible to do such a traversal? How would it work?
Here's an example. This method will return all subclasses descending from the class you send the message to.
#interface NSObject (Debugging)
+ (NSArray *) allSubclasses;
#end
#implementation NSObject (Debugging)
+ (NSArray *) allSubclasses
{
Class myClass = [self class];
NSMutableArray *mySubclasses = [NSMutableArray array];
unsigned int numOfClasses;
Class *classes = objc_copyClassList(&numOfClasses);
for (unsigned int ci = 0; ci < numOfClasses; ci++) {
// Replace the code in this loop to limit the result to immediate subclasses:
// Class superClass = class_getSuperclass(classes[ci]);
// if (superClass == myClass)
// [mySubclasses addObject: classes[ci]];
Class superClass = classes[ci];
do {
superClass = class_getSuperclass(superClass);
} while (superClass && superClass != myClass);
if (superClass)
[mySubclasses addObject: classes[ci]];
}
free(classes);
return mySubclasses;
}
#end
Modify it as needed, make recursive calls, etc.

Objective-C Static Class Level variables

I have a class Film, each of which stores a unique ID. In C#, Java etc I can define a static int currentID and each time i set the ID i can increase the currentID and the change occurs at the class level not object level. Can this be done in Objective-C? I've found it very hard to find an answer for this.
Issue Description:
You want your ClassA to have a ClassB class variable.
You are using Objective-C as programming language.
Objective-C does not support class variables as C++ does.
One Alternative:
Simulate a class variable behavior using Objective-C features
Declare/Define an static variable within the classA.m so it will be only accessible for the classA methods (and everything you put inside classA.m).
Overwrite the NSObject initialize class method to initialize just once the static variable with an instance of ClassB.
You will be wondering, why should I overwrite the NSObject initialize method. Apple documentation about this method has the answer: "The runtime sends initialize to each class in a program exactly one time just before the class, or any class that inherits from it, is sent its first message from within the program. (Thus the method may never be invoked if the class is not used.)".
Feel free to use the static variable within any ClassA class/instance method.
Code sample:
file: classA.m
static ClassB *classVariableName = nil;
#implementation ClassA
...
+(void) initialize
{
if (! classVariableName)
classVariableName = [[ClassB alloc] init];
}
+(void) classMethodName
{
[classVariableName doSomething];
}
-(void) instanceMethodName
{
[classVariableName doSomething];
}
...
#end
References:
Class variables explained comparing Objective-C and C++ approaches
As of Xcode 8, you can define class properties in Obj-C. This has been added to interoperate with Swift's static properties.
Objective-C now supports class properties, which interoperate with Swift type properties. They are declared as: #property (class) NSString *someStringProperty;. They are never synthesized. (23891898)
Here is an example
#interface YourClass : NSObject
#property (class, nonatomic, assign) NSInteger currentId;
#end
#implementation YourClass
static NSInteger _currentId = 0;
+ (NSInteger)currentId {
return _currentId;
}
+ (void)setCurrentId:(NSInteger)newValue {
_currentId = newValue;
}
#end
Then you can access it like this:
YourClass.currentId = 1;
val = YourClass.currentId;
Here is a very interesting explanatory post I used as a reference to edit this old answer.
2011 Answer: (don't use this, it's terrible)
If you really really don't want to declare a global variable, there another option, maybe not very orthodox :-), but works... You can declare a "get&set" method like this, with an static variable inside:
+ (NSString*)testHolder:(NSString*)_test {
static NSString *test;
if(_test != nil) {
if(test != nil)
[test release];
test = [_test retain];
}
// if(test == nil)
// test = #"Initialize the var here if you need to";
return test;
}
So, if you need to get the value, just call:
NSString *testVal = [MyClass testHolder:nil]
And then, when you want to set it:
[MyClass testHolder:testVal]
In the case you want to be able to set this pseudo-static-var to nil, you can declare testHolder as this:
+ (NSString*)testHolderSet:(BOOL)shouldSet newValue:(NSString*)_test {
static NSString *test;
if(shouldSet) {
if(test != nil)
[test release];
test = [_test retain];
}
return test;
}
And two handy methods:
+ (NSString*)test {
return [MyClass testHolderSet:NO newValue:nil];
}
+ (void)setTest:(NSString*)_test {
[MyClass testHolderSet:YES newValue:_test];
}
Hope it helps! Good luck.
On your .m file, you can declare a variable as static:
static ClassName *variableName = nil;
Then you can initialize it on your +(void)initialize method.
Please note that this is a plain C static variable and is not static in the sense Java or C# consider it, but will yield similar results.
In your .m file, declare a file global variable:
static int currentID = 1;
then in your init routine, refernce that:
- (id) init
{
self = [super init];
if (self != nil) {
_myID = currentID++; // not thread safe
}
return self;
}
or if it needs to change at some other time (eg in your openConnection method), then increment it there. Remember it is not thread safe as is, you'll need to do syncronization (or better yet, use an atomic add) if there may be any threading issues.
As pgb said, there are no "class variables," only "instance variables." The objective-c way of doing class variables is a static global variable inside the .m file of the class. The "static" ensures that the variable can not be used outside of that file (i.e. it can't be extern).
Here would be an option:
+(int)getId{
static int id;
//Do anything you need to update the ID here
return id;
}
Note that this method will be the only method to access id, so you will have to update it somehow in this code.
(Strictly speaking not an answer to the question, but in my experience likely to be useful when looking for class variables)
A class method can often play many of the roles a class variable would in other languages (e.g. changed configuration during tests):
#interface MyCls: NSObject
+ (NSString*)theNameThing;
- (void)doTheThing;
#end
#implementation
+ (NSString*)theNameThing { return #"Something general"; }
- (void)doTheThing {
[SomeResource changeSomething:[self.class theNameThing]];
}
#end
#interface MySpecialCase: MyCls
#end
#implementation
+ (NSString*)theNameThing { return #"Something specific"; }
#end
Now, an object of class MyCls calls Resource:changeSomething: with the string #"Something general" upon a call to doTheThing:, but an object derived from MySpecialCase with the string #"Something specific".
u can rename the class as classA.mm and add C++ features in it.
Another possibility would be to have a little NSNumber subclass singleton.

How to obtain the address of object in objective-C

I have to call an objective C method from a cpp Function.
I have a class C, whose object address is required in this function. I did come across another link which guided me on how to have a reference to the class C, and use it for invocation from the cpp function.
In my case, there is one small difference in that the Class C is already instantiated, and I would not want to allocate an object again. So how can I get its object address?
The code looks like this:
C.h
import Cocoa/Cocoa.h
id refToC
#interface C: NSObject
{
;
somemethod;
;
}
#end
C.m
#implementation C
- (void) somemethod
{
;
;
}
#end
B.mm
import C.h
void func()
{
//I need the address of object here, so as to invoke:
[refToC somemethod];
}
Thanks in Advance
~ps7
The id type is already a pointer to an object. Once you have created a valid object, e.g.:
refToC = [[C alloc] init]
The easiest way is to make use of the singleton design pattern. Here's a common way to make use of that pattern in Objective-C:
Widget.h
#interface Widget : NSObject {
// ...
}
// ...
- (void)someMethod;
+ (Widget *)sharedWidget;
#end
Widget.m
#implementation Widget
// ...
+ (Widget *)sharedWidget {
static Widget *instance;
#synchronized (self) {
if (!instance)
instance = [[Widget alloc] init];
}
return instance;
}
#end
CppWrapper.mm
void methodWrapper() {
[[Widget sharedWidget] someMethod];
}
Thanks a lot for your pointers. I had missed telling that the class C is a controller class. I tried assigning refToC to self in awakeFromNib, and the invocation in func() worked like a charm.
Thanks Matt and John for your pointers.
~ ps7