iOS Storing a pointer - ios

In my ios application i want to store an object's reference. This object can be an instance from interface A,B,C or D. I know that it's always going to be one from these four, but never know which one. How can i represent this object in my code?
Sincerely, Zoli

Represent it as type id.
id ptr;
Also, be aware of the possibility that you can specialise type id to some protocol.
id <SomeProtocol>;

what i understand that you should make a shared instance of that object.
example:-
make a new class named SavedReference.
and write in implementation file this code
Code:
static SavedReference *sharedInstance = nil; //if using iOS5 or above no need to nil it.
+(SavedReference*)sharedInstance
{
#synchronized(self)
{
if(!sharedInstance)
{
sharedInstance = [[self alloc]init];
return sharedInstance;
}
}
return nil;
}
-(id)init
{
self = [super init];
if(self)
{
//initialize variables
}
return self;
}
And Call this class as [[SavedReference sharedInstance] write ur method]

Related

How to create referencing variables?

I'm making an app for practice. This app shares with a simple model through AppDelegate. To manipulate the model, I got an NSDictionary object from the model and allocate it to a viewController property. but It seems too verbose.
// viewController.h
#property (nonatomic, strong) NSMutableDictionary *bookDetail;
#property (nonatomic, strong) bookModel *modelBook;
// viewController.m
- (void)setLabel {
self.label_name.text = self.bookDetail[#"name"];
self.label_author.text = self.bookDetail[#"author"];
}
- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
id appDelegate = [[UIApplication sharedApplication] delegate];
self.modelBook = [appDelegate modelBook];
self.bookDetail = self.modelBook.bookList[self.modelBook.selectedId];
[self setLabel];
self.editMod = NO;
}
- (IBAction)editSave:(id)sender {
if (self.editMod == NO) {
....
[self.nameField setText:self.bookDetail[#"name"]];
[self.authorField setText:self.bookDetail[#"author"]];
....
} else {
self.bookDetail = [#{#"name" : self.nameField.text,
#"author" : self.authorField.text} mutableCopy];
[self setLabel];
....
}
}
#end
*bookDetail work like a copy of self.modelBook.bookList[self.modelBook.selectedId] not a reference. Using self.modelBook.bookList[self.modelBook.selectedId] works well, but I don't want to. How Can I simplify this code?
*bookDetail work like a copy of self.modelBook.bookList[self.modelBook.selectedId] not a reference. Using self.modelBook.bookList[self.modelBook.selectedId] works well, but I don't want to.
Your question is not clear to me so this might be wrong, but hopefully it helps.
bookDetail is not a "copy" in the usual sense, rather it is a reference to the same dictionary that self.modelBook.bookList[self.modelBook.selectedId] references at the time the assignment to bookDetail is made.
Given that you say that using the latter "works well" is sounds as though self.modelBook.selectedId is changing and you expected bookDetail to automatically track that change and now refer to a different dictionary. That is not how assignment works.
How Can I simplify this code?
You could add a property to your modelBook class[1], say currentBook, which returns back bookList[selectedID] so each time it is called you get the current book. In your code above you then use self.modelBook.currentBook instead of self.bookDetail and can remove the property bookDetail as unused (and incorrect).
HTH
[1] Note: this should be called ModelBook to follow naming conventions. Have you noticed the syntax coloring is incorrect? That is because you haven't followed the convention.
Create the shared instance of BookModel then you can access it anywhere:
Write this in bookModel:
+ (instancetype)sharedInstance
{
static bookModel *sharedInstance = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
sharedInstance = [[bookModel alloc] init];
// Do any other initialisation stuff here
});
return sharedInstance;
}
Then you can access this like bookModel.sharedInstance.bookList

How to create a singleton object A from inside B's method by preventing direct access of A from A?

In a static library, I have two classes A, B inheriting from NSObject. I want to create an object of A in some method of B. User should be able to access reference of A only through B and only single object of A and b should be created. After user add static library in their Xcode project, they shouldn't be able to created an object of A directly, due to which I have raised an exception in the init of A. But, after doing this I cannot create an object of A in B also. I don't want to create shared instance of A, that will allow the library user to access A, before B is created. My main goal is to create an object of A inside B, only after B is created and user should be able to access the A object through a property of B
#implementation A
//This will prevent library user to create A
- (instancetype)init {
[self doesNotRecognizeSelector:_cmd];
return nil;
}
#implementation B
- (void)initialiseSDK{
A *a = [B sharedA]; //won't work, A's init raises exception
+ (A *)sharedA{
static dispatch_once_t d;
static OncamAccount *sharedA = nil;
dispatch_once(&d, ^{
sharedA = [[A alloc]init]; //A's init raise exception
});
return shared;
}
+ (B *)sharedB{
static dispatch_once_t pred;
static OnCamSDK *sharedB = nil;
dispatch_once(&pred, ^{
sharedB = [[B alloc] init];
});
return sharedB;
}
If I remove the exception from A's init, then I think user will be able to create an object of A directly, which I don't want.
Here's another option that gives A more control of what's going on:
Declare variables in A.m outside the implementation.
static BOOL initialized = NO;
static NSLock *initLock;
Add initialization code to support locking.
+ (void)initialize
{
initLock = [[NSLock alloc] init];
}
Make the init conditional.
- (instancetype)init
{
[initLock lock];
if (initialized) {
[self doesNotRecognizeSelector:_cmd];
return nil;
}
initialized = YES;
[initLock unlock];
self = [super init];
return self;
}

Objective C - Return instance of child class without knowing what it is

I have class RestModel : NSObject that handles interaction with a Rest API, with the intention being to subclass for each model accessible via the API (e.g., PageModel : RestModel or PhotoModel : RestModel)
What I want to do is have a generic forgeFromDictionary static method which will return an instance of the subclass, but will be the same for each subclass unless there is some custom instantiation involved. So ideally the forgeFromDictionary method would be on my RestModel, but I could call PageModel* myPage = [PageModel forgeFromDictionary:previouslyDefinedDictionary]; and get an actual PageModel object.
Is this possible in objective-c?
Here's what I've tried, not sure if I'm on the right track:
I know I can set the return type of a static method to instancetype, which apparently references whichever class is actually calling the method, like so:
+ (instancetype) forgeFromDictionary: (NSDictionary*) dictionary
But using instancetype anywhere in the actual method gives a fatal error, so this doesn't work:
+ (instancetype) forgeFromDictionary: (NSDictionary*) dictionary {
instancetype *object = [[instancetype alloc] init]; # red alert!
# "use of undeclared identifier 'instancetype'
object.properties = dictionary;
object.original = dictionary;
return object;
}
Inside your method, replace:
instancetype *object = [[instancetype alloc] init];
with:
RestModel *object = [[self alloc] init];
If you want to return the instance class and not the super class maybe you can use something like this:
+(id)forgeFromDictionary:(NSMutableDictionary *)dict{
Class t = [self class];
id test = [t new];
// if you have a common property you can set it here by doing
if([test respondsToSelector:#selector(property)]){
//set value here
[test setProperty:val];
}
return test;
}
using it will just be like:
// you need to cast the object since creating it with id type
YourClass *instance = (YourClass *)[YourClass forgeFromDictionary:yourDictionary];
This will return the instance class and not the super class

Is it possible to return Singleton's value without executing it's methd? [duplicate]

This question already has an answer here:
Is it possible to initialize a Singleton from a specific method and not when application is executed? [closed]
(1 answer)
Closed 9 years ago.
I have a singleton that looks like this
+(DataController*)sharedInstance
{
static DataController *sharedInstance = nil;
static dispatch_once_t oncePredicate;
dispatch_once(&oncePredicate,
^{
if (sharedInstance == nil)
{
sharedInstance = [[DataController alloc]init];
}
});
return sharedInstance;
}
Now, I have a couple methods where it's return value depends on Singleton's sharedInstance value.
I want to do something like this:
DataController *nilInstance = [DataController sharedInstance];
if (nilInstance == nil)
{
// do this
}
else
{
// do something else
}
When I run my application and it goes to this line
DataController *nilInstance = [DataController sharedInstance];
It goes to my Singleton class and it runs the whole method and so it will never be nil. What could be an approach to this solution?
Since It is a singleton class, It will return the same object every time where you will call this. You will not get nil. Why do you want to get nil if you are using singleton class.
The point of creating a shared instance is to access the singleton instance of class throughout the application. When you first run the code singleton is created and it persist throughout the app life cycle as it is defined as static. This method will never return nil.

Removing an Observer when it gets Deallocated

I have the following 2 classes:
EventDispatcher:
#interface EventDispatcher()
-(id)initEventDispatcher;
-(NSMutableArray*)getSubscriptionsToEvent:(EVENT_TYPE)eventType;
-(NSNumber*)getKeyToEvent:(EVENT_TYPE)eventType;
#end
#implementation EventDispatcher
static EventDispatcher* eventDispatcher;
// Singleton.
+(EventDispatcher*)instance
{
if (eventDispatcher == nil)
{
eventDispatcher = [[EventDispatcher alloc] initEventDispatcher];
}
return eventDispatcher;
}
-(id)initEventDispatcher
{
self = [super init];
if (self)
{
eventSubscriptions = [[NSMutableDictionary alloc] init];
}
return self;
}
// Let anyone subscribe to an event. Return the EventSubscriber so they can dispatch events if needed, and to be able to unsubscribe.
-(EventSubscriber*)subscribe:(EVENT_TYPE)eventType :(void(^)(id package))operateEvent
{
// Create the object.
EventSubscriber* eventSubscriber = [[EventSubscriber alloc] initEventSubscriber:eventType :operateEvent];
// Now get the list it belongs to (we sort subscriptions in a dictionary so that when we dispatch an event, it's fast (we don't need to iterate through all EventSubscribers to find who subscribe to an event).
NSMutableArray* subscriptionsToThisEvent = [self getSubscriptionsToEvent:eventType];
if(subscriptionsToThisEvent == nil)
{
// If the list is nil, no one has subscribed to it yet, so make that list and add it to the dictionary.
subscriptionsToThisEvent = [[NSMutableArray alloc] init];
NSNumber* key = [self getKeyToEvent:eventType];
[eventSubscriptions setObject:subscriptionsToThisEvent forKey:key];
[subscriptionsToThisEvent release];
}
// Add the EventSubscriber to the subscription list.
[subscriptionsToThisEvent addObject:eventSubscriber];
[eventSubscriber release];
return eventSubscriber;
}
-(void)unsubscribe:(EventSubscriber*)eventSubscriber
{
// Get the list it belongs to, and remove it from that list.
EVENT_TYPE eventType = [eventSubscriber getEventType];
NSMutableArray* subscriptionsToThisEvent = [self getSubscriptionsToEvent:eventType];
if (subscriptionsToThisEvent != nil)
{
[subscriptionsToThisEvent removeObject:eventSubscriber];
}
}
-(void)dispatch:(EVENT_TYPE)eventType :(id)package
{
NSMutableArray* subscriptionsToThisEvent = [self getSubscriptionsToEvent:eventType];
// If no one has subscribed to this event, it could be nil, so do nothing.
if (subscriptionsToThisEvent != nil)
{
// Otherwise, let them all know that the event was dispatched!
for (EventSubscriber* eventSubscriber in subscriptionsToThisEvent)
[eventSubscriber dispatch:package];
}
}
// Helper methods to get stuff (lists, keys) from event types.
-(NSMutableArray*)getSubscriptionsToEvent:(EVENT_TYPE)eventType
{
NSNumber* key = [self getKeyToEvent:eventType];
NSMutableArray* subscriptionsToThisEvent = [eventSubscriptions objectForKey:key];
return subscriptionsToThisEvent;
}
-(NSNumber*)getKeyToEvent:(EVENT_TYPE)eventType
{
return [NSNumber numberWithInt:eventType];
}
-(void)dealloc
{
[eventSubscriptions release];
[super dealloc];
}
#end
EventSubscriber:
#import "EventSubscriber.h"
#implementation EventSubscriber
-(id)initEventSubscriber:(EVENT_TYPE)newEventType :(void(^)(id package))newOperateEvent
{
self = [super init];
if (self)
{
operateEvent = [newOperateEvent copy];
eventType = newEventType;
}
return self;
}
-(void)dispatch:(id)package
{
operateEvent(package);
}
-(EVENT_TYPE)getEventType
{
return eventType;
}
-(void)dealloc
{
[operateEvent release];
[super dealloc];
}
#end
Onto the big question: How do I unburden a programmer who is using this system with having to unsubscribe from an event during deallocation? When multiple classes are using this system, programmers will have to remember to unsubscribe during deallocation (if not an earlier time), or REALLY bad/weird/unexpected things could happen (I would prefer a compile-time check, or a big, obvious, debuggable crash, but more-so the former). Ideally, I'd like to restructure this system (or do anything) so that when an object is deallocated, the EventDispatcher gracefully handles it.
One quick fix is to have objects allocate EventSubscribers directly, then in the EventSubscriber constructor, it subscribes itself to EventDispatcher (but that's obviously bad, maybe make EventDispatcher's stuff static? Ugh now we're just getting worse).
Side notes:
I'm not using ARC, but, that does not matter here (at least I think it does not, if there are ARC-based solutions, I'd like to hear them).
I do plan on adding a method in EventDispatcher to be able to remove EventSubscribers by those who did the subscription (so now when subscribing, objects will have to pass 'self'). I also plan on making the enumerated EVENT_TYPE use strings, but that's a different topic altogether.
I also plan on translating a lot of my code (including these classes) to C++. So I'd appreciate a conceptual solution as opposed to Objective-C specific solutions.
So, is this possible?
Thanks a bunch!

Resources