ios how to get data from webservice with WSDL2ObjC - ios5

I am unable to show data in iPhone. Please advise.
getdata.h
#interface GetDataFromPhoneService_GetPhoneInfoResponse : NSObject {
/* elements */
tns2_GetPhoneInfoModel * GetPhoneInfoReturn;
/* attributes */
}
/* elements */
#property (retain) tns2_GetPhoneInfoModel * GetPhoneInfoReturn;
/* attributes */
- (NSDictionary *)attributes;
#end
#interface GetDataFromPhoneService_GetPhoneInfo : NSObject {
/* elements */
NSString * phoneNo;
/* attributes */
}
#property (retain) NSString * phoneNo;
#end
#interface GetDataFromPhoneSoapBinding_GetPhoneInfo : GetDataFromPhoneSoapBindingOperation {
GetDataFromPhoneService_GetPhoneInfo * parameters;
}
#property (retain) GetDataFromPhoneService_GetPhoneInfo * parameters;
getdata.m
#implementation GetDataFromPhoneService_GetPhoneInfo
- (id)init
{
if((self = [super init])) {
phoneNo = 0;
}
return self;
}
- (void)dealloc
{
if(phoneNo != nil) [phoneNo release];
[super dealloc];
}
- (NSString *)nsPrefix
{
return #"GetDataFromPhoneService";
}
getview.m
- (IBAction)buttonClick:(id)sender {
GetDataFromPhoneSoapBinding *binding = [[GetDataFromPhoneService GetDataFromPhoneSoapBinding] initWithAddress:#"http://..."];
binding.logXMLInOut = YES; // to get logging to the console.
GetDataFromPhoneService_GetPhoneInfo *request = [[GetDataFromPhoneService_GetPhoneInfo alloc] init];
request.phoneNo = #"66875920808"; // insert your phone number here.
GetDataFromPhoneSoapBindingResponse *resp = [binding GetPhoneInfoUsingParameters:request];
for (id mine in resp.bodyParts)
{
if ([mine isKindOfClass:[GetDataFromPhoneService_GetPhoneInfoResponse class]])
{
greeting.text = [mine GetPhoneInfoReturn];
}
}
Here is the data.
<p372:GetPhoneInfoResponse xmlns:p372="http://Bean.crew.cw.tg">
<GetPhoneInfoReturn>
<zimPersno>40347</zimPersno>
<firstname>WANCHART</firstname>
<lastname>SANGSUK</lastname>
</GetPhoneInfoReturn>
</p372:GetPhoneInfoResponse>

Related

Accessing changeable values in a singleton?

First off, I come from Lua, don't blame me for being global variable minded lol. So, I've been reading up on how to use this whole "Singleton system" and I'm not sure if I'm completely missing the point or if I'm just implementing it incorrectly?
The goal of my code is to create a way for multiple files to access a variable that holds the size of an array in a specific file. Here is my singleton:
.h
#import <Foundation/Foundation.h>
#interface GlobalVariables : NSObject
{
NSNumber *currentGameArrayCount;
BOOL *isGamePaused;
}
#property (nonatomic, readwrite) NSNumber *currentGameArrayCount;
#property (nonatomic, readwrite) BOOL *isGamePaused;
+ (GlobalVariables *)sharedInstance;
#end
.m
#import "GlobalVariables.h"
#implementation GlobalVariables
#synthesize currentGameArrayCount, isGamePaused;
static GlobalVariables *gVariable;
+ (GlobalVariables *)sharedInstance
{
if (gVariable == nil) {
gVariable = [[super allocWithZone:NULL] init];
}
return gVariable;
}
- (id)init
{
self = [super init];
if (self)
{
currentGameArrayCount = [[NSNumber alloc] initWithInt:0];
isGamePaused = NO;
}
return self;
}
#end
and in another file with the array I use:
GlobalVariables *sharedData = [GlobalVariables sharedInstance];
NSNumber *tmpArrayCount = [sharedData currentGameArrayCount];
NSInteger tmpCount = [whereStuffActuallyHappens.subviews count]; // Subviews is the array
NSNumber *currentCount = [NSNumber numberWithInteger:tmpCount];
tmpArrayCount = currentCount;
the hope of this code was to get the variable in the singeton (currentGameArrayCount) and set it too what the current array count was (currentCount). Am I incorrectly interpreting the purpose of a singleton? Am I just bad at singletons and didn't set it up correctly? Does anyone know how I could achieve the result of getting my array count to be accesible to all my files?
You have a few issues. Try these changes:
GlobalVariables.h:
#import <Foundation/Foundation.h>
#interface GlobalVariables : NSObject
#property (nonatomic, assign) int currentGameArrayCount;
#property (nonatomic, assign) BOOL gamePaused;
+ (GlobalVariables *)sharedInstance;
#end
GlobalVariables.m:
#import "GlobalVariables.h"
static GlobalVariables *gVariable = nil;
#implementation GlobalVariables
+ (GlobalVariables *)sharedInstance {
if (gVariable == nil) {
gVariable = [[self alloc] init];
}
return gVariable;
}
- (id)init {
self = [super init];
if (self) {
self.currentGameArrayCount = 0;
self.gamePaused = NO;
}
return self;
}
#end
Now in your other code you can do:
GlobalVariables *sharedData = [GlobalVariables sharedInstance];
int tmpArrayCount = sharedData.currentGameArrayCount;
NSInteger tmpCount = [whereStuffActuallyHappens.subviews count]; // Subviews is the array
sharedData.currentGameArrayCount = tmpCount;

iPhone - writign a class that can be instanciated many times, each instance being able to access a shared property

I know this can be done with many languages, but I don't see how to do it using Objective-C. I've read about singletons but as they are designed to be instanciated only once, they do not feed this need.
So this class could be called like this :
MyClass* obj1 = [[MyClass alloc] initWithKey:#"oneKey"];
NSString* lib = obj1.lib;
or
int id = [MyClass idForKey:#"anotherKey"];
I've tried this code but I'm pretty sure it's really bad, but I don't see how to achieve this :
.h file
#interface MyClass : NSObject {
NSString* key;
}
#property(nonatomic, retain) NSString* key;
#property(nonatomic, readonly) int id;
#property(nonatomic, readonly) NSString* lib;
#property(nonatomic, readonly) int value;
+ (id) classWithKey:(NSString*)theKey;
#end
.m file
#import "MyClass.h"
#interface MyClass.h (Private)
-(id)initWithKey:(NSString*)theKey;
#end
#implementation MyClass
#synthesize key;
static NSMutableDictionary* vars = nil;
-(id)init
{
if (!(self = [super init])) return nil;
self.key = nil;
[MyClass initVars];
return self;
}
-(id)initWithKey:(NSString*)theKey
{
if (!(self = [super init])) return nil;
self.key = theKey;
[MyClass initVars];
return self;
}
+ (id) classWithKey:(NSString*) theKey
{
return [[[MyClass alloc] initWithKey:theKey] autorelease];
}
+(void)initVars
{
if (vars != nil) return;
#define mNum(x) [NSNumber numberWithInt:x]
#define k0 #"id"
#define k1 #"lib"
#define k2 #"val"
vars = [NSMutableDictionary dictionary];
[vars setObject:[NSDictionary dictionaryWithObjectsAndKeys:mNum(5), k0, #"One value", k1, mNum(0), k2, nil] forKey:#"oneKey"];
[vars setObject:[NSDictionary dictionaryWithObjectsAndKeys:mNum(8), k0, #"Another value", k1, mNum(1), k2, nil] forKey:#"anotherKey"];
...
[vars retain];
}
- (int)id { return [[[vars objectForKey:self.key] objectForKey:k0] intValue]; }
- (NSString*)lib { return [[vars objectForKey:self.key] objectForKey:k1]; }
- (int)value { return [[[vars objectForKey:self.key] objectForKey:k2] intValue]; }
-(void)dealloc
{
self.key = nil;
[vars release];
[super dealloc];
}
+(int) idForKey:(NSString*)theKey
{
if (vars == nil) [self initVars];
return [[[vars objectForKey: theKey] objectForKey:k0] intValue];
}
#end
take a look at singleton class concept
there are a lot of answer for singletons, just search
here's' one:
Is this really a singleton?

What alternatives to a switch statement could I use to update my UITableViewCells? [duplicate]

This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
Alternative to switch statement in objective C
I have json data from an url which I display in the table cell using a switch statement. Since I have only 6 cells, I had used a switch statement but I am curious to know if there is any other method in place of switch statement to do so.
switch(indexPath.row)
{
case 0 :
cell.textLabel.text = [NSString stringWithFormat:#"%# %#",[dictionary valueForKey:#"firstname"],
[dictionary valueForKey:#"lastname"]];
break;
case 1:
cell.textLabel.text = [NSString stringWithFormat:#"%# : %#",#"Address",[dictionary valueForKey:#"address"]];
break;
case 2:
cell.textLabel.text = [NSString stringWithFormat:#"%# : %#",#"Age",[dictionary valueForKey:#"age"]];
break;
case 3:
cell.textLabel.text = [NSString stringWithFormat:#"%# : %#",#"Occupation",[dictionary valueForKey:#"occupation"]];
break;
case 4:
cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
cell.textLabel.text = [NSString stringWithFormat:#"%# : %#",#"Rating",[rate valueForKey:#"average"]];
break;
case 5:
cell.textLabel.text = [NSString stringWithFormat:#"%# : %#",#"Total Rating",[rate valueForKey:#"totalRatings"]];
break;
}
Here's a way to completely overengineer the problem, but you may find some useful nuggets in there which will help you with your specific problem:
typedef enum MONTableViewCellID {
MONTableViewCellID_Name = 0,
MONTableViewCellID_Address,
MONTableViewCellID_Age,
MONTableViewCellID_Occupation,
MONTableViewCellID_Rating,
MONTableViewCellID_TotalRating
} MONTableViewCellID;
#interface MONTableViewStuff : NSObject
{
#private
NSDictionary * dictionary;
NSDictionary * rate;
UITableViewCell * cell;
NSIndexPath * indexPath;
}
#end
#implementation MONTableViewStuff
- (UITableViewCellAccessoryType)tableViewAccessoryTypeForRow:(NSUInteger)row
{
if (MONTableViewCellID_Rating == row) {
return UITableViewCellAccessoryDisclosureIndicator;
}
return UITableViewCellAccessoryNone;
}
- (NSString *)lhsTextForRow:(NSUInteger)row
{
switch (row) {
case MONTableViewCellID_Name :
return [dictionary objectForKey:#"firstname"];
case MONTableViewCellID_Address :
return #"Address";
case MONTableViewCellID_Age :
return #"Age";
case MONTableViewCellID_Occupation :
return #"Occupation";
case MONTableViewCellID_Rating :
return #"Rating";
case MONTableViewCellID_TotalRating :
return #"Total Rating";
default : {
assert(0 && "invalid row");
return #"";
}
}
}
- (NSString *)rhsTextForRow:(NSUInteger)row
{
switch (row) {
case MONTableViewCellID_Name :
return [dictionary objectForKey:#"lastname"];
case MONTableViewCellID_Address :
return [dictionary objectForKey:#"address"];
case MONTableViewCellID_Age :
return [dictionary objectForKey:#"age"];
case MONTableViewCellID_Occupation :
return [dictionary objectForKey:#"occupation"];
case MONTableViewCellID_Rating :
return [rate objectForKey:#"average"];
case MONTableViewCellID_TotalRating :
return [rate objectForKey:#"totalRatings"];
default : {
assert(0 && "invalid row");
return #"";
}
}
}
- (NSString *)separatorForRow:(NSUInteger)row
{
switch (row) {
case MONTableViewCellID_Name :
return #" ";
case MONTableViewCellID_Address :
case MONTableViewCellID_Age :
case MONTableViewCellID_Occupation :
case MONTableViewCellID_Rating :
case MONTableViewCellID_TotalRating :
return #" : ";
default : {
assert(0 && "invalid row");
return #"";
}
}
}
- (NSString *)textLabelTextForRow:(NSUInteger)row
{
return [NSString stringWithFormat:#"%#%#%#", [self lhsTextForRow:row], [self separatorForRow:row], [self rhsTextForRow:row]];
}
- (void)updateTextLabel
{
cell.textLabel.text = [self textLabelTextForRow:indexPath.row];
cell.accessoryType = [self tableViewAccessoryTypeForRow:indexPath.row];
}
#end
Another overengineered option that you may be able to steal some nuggets from is the object based approach:
MONTableViewStuff.h
typedef enum MONTableViewCellID {
MONTableViewCellID_Name = 0,
MONTableViewCellID_Address,
MONTableViewCellID_Age,
MONTableViewCellID_Occupation,
MONTableViewCellID_Rating,
MONTableViewCellID_TotalRating
} MONTableViewCellID;
#interface MONTableViewStuff : NSObject
#property (nonatomic, copy, readonly) NSDictionary * dictionary;
#property (nonatomic, copy, readonly) NSDictionary * rate;
#end
MONTableViewStuff.m
#implementation MONTableViewStuff
#synthesize dictionary;
#synthesize rate;
- (id)init
{
self = [super init];
if (0 != self) {
/* create an array of presenters ordered by MONTableViewCellID */
presenters =
[NSArray arrayWithObjects:
[[NamePresenter new] autorelease],
[[AddressPresenter new] autorelease],
[[AgePresenter new] autorelease],
[[OccupationPresenter new] autorelease],
[[RatingPresenter new] autorelease],
[[TotalRatingPresenter new] autorelease],
nil
];
}
return self;
}
- (void)updateTableViewCell
{
NSObject<MONUITableViewCellPresenter>* presenter = [presenters objectAtIndex:indexPath.row];
[presenter updateUITableViewCell:cell tableViewStuff:self];
}
#end
Where the presenters' interface looked like so:
#protocol MONUITableViewCellPresenter < NSObject >
#required
- (void)updateUITableViewCell:(UITableViewCell *)cell tableViewStuff:(MONTableViewStuff *)tableViewStuff;
#end
// our base presenter which handles the cells
#interface DefaultPresenter : NSObject
/** #return UITableViewCellAccessoryNone */
- (UITableViewCellAccessoryType)cellAccessoryTypeForTableViewStuff:(MONTableViewStuff *)tableViewStuff;
- (void)updateUITableViewCell:(UITableViewCell *)cell tableViewStuff:(MONTableViewStuff *)tableViewStuff;
#end
// required overrides
#protocol DefaultPresenterSubclass <MONUITableViewCellPresenter>
#required
- (NSString *)cellTextForTableViewStuff:(MONTableViewStuff *)tableViewStuff;
#end
// our specializations
#interface NamePresenter : DefaultPresenter <DefaultPresenterSubclass>
#end
#interface AddressPresenter : DefaultPresenter <DefaultPresenterSubclass>
#end
#interface AgePresenter : DefaultPresenter <DefaultPresenterSubclass>
#end
#interface OccupationPresenter : DefaultPresenter <DefaultPresenterSubclass>
#end
#interface RatingPresenter : DefaultPresenter <DefaultPresenterSubclass>
#end
#interface TotalRatingPresenter : DefaultPresenter <DefaultPresenterSubclass>
#end
And their implementations looked like so:
#implementation DefaultPresenter
- (UITableViewCellAccessoryType)cellAccessoryTypeForTableViewStuff:(MONTableViewStuff *)tableViewStuff
{
#pragma unused (tableViewStuff)
return UITableViewCellAccessoryNone;
}
- (NSString *)cellTextForTableViewStuff:(MONTableViewStuff *)tableViewStuff
{
#pragma unused (tableViewStuff)
assert(0 && "specialization required");
return 0;
}
- (void)updateUITableViewCell:(UITableViewCell *)cell tableViewStuff:(MONTableViewStuff *)tableViewStuff
{
cell.accessoryType = [self cellAccessoryTypeForTableViewStuff:tableViewStuff];
cell.textLabel.text = [self cellTextForTableViewStuff:tableViewStuff];
}
#end
#implementation NamePresenter
- (NSString *)cellTextForTableViewStuff:(MONTableViewStuff *)tableViewStuff
{
return [NSString stringWithFormat:#"%# %#",[tableViewStuff.dictionary valueForKey:#"firstname"], [tableViewStuff.dictionary valueForKey:#"lastname"]];
}
#end
#implementation AddressPresenter
- (NSString *)cellTextForTableViewStuff:(MONTableViewStuff *)tableViewStuff
{
return [NSString stringWithFormat:#"%# : %#",#"Address",[tableViewStuff.dictionary valueForKey:#"address"]];
}
#end
#implementation AgePresenter
- (NSString *)cellTextForTableViewStuff:(MONTableViewStuff *)tableViewStuff
{
return [NSString stringWithFormat:#"%# : %#",#"Age",[tableViewStuff.dictionary valueForKey:#"age"]];;
}
#end
#implementation OccupationPresenter
- (NSString *)cellTextForTableViewStuff:(MONTableViewStuff *)tableViewStuff
{
return [NSString stringWithFormat:#"%# : %#",#"Occupation",[tableViewStuff.dictionary valueForKey:#"occupation"]];
}
#end
#implementation RatingPresenter
+ (UITableViewCellAccessoryType)cellAccessoryType
{
return UITableViewCellAccessoryDisclosureIndicator;
}
- (NSString *)cellTextForTableViewStuff:(MONTableViewStuff *)tableViewStuff
{
return [NSString stringWithFormat:#"%# : %#",#"Rating",[tableViewStuff.rate valueForKey:#"average"]];
}
#end
#implementation TotalRatingPresenter
- (NSString *)cellTextForTableViewStuff:(MONTableViewStuff *)tableViewStuff
{
return [NSString stringWithFormat:#"%# : %#",#"Total Rating",[tableViewStuff.rate valueForKey:#"totalRatings"]];
}
#end
The thing you could do would be to make some kind of data objet containing the information you need to display in your stringWithFormat method.
And then make a NSDictionary that key value pair those object with the indexes...
But is all that work worth it in this particular case?
I doubt it.

invalid CFArrayRef problem with Singleton object

I've built a singleton object to manage some data in my app
#interface MyCommon : NSObject {
NSArray *quizz;
int iCurrentQuestion;
};
+ (MyCommon *)singleton;
#property (retain) NSArray *quizz;
#property (assign) int iCurrentQuestion;
#end
MyCommon.m
#import "MyCommon.h"
// MyCommon.m:
#implementation MyCommon
static MyCommon * MyCommon_Singleton = nil;
#synthesize iCurrentQuestion;
+ (MyCommon *)singleton
{
if (nil == MyCommon_Singleton)
{
MyCommon_Singleton = [[MyCommon alloc] init];
NSLog(#"allocating MyCommon_Singleton at %#",MyCommon_Singleton);
}
else {
NSLog(#"accessing singleton : %#", MyCommon_Singleton);
}
return MyCommon_Singleton;
}
- (NSArray*) getQuizz{
return quizz;
}
- (void) setQuizz:(NSArray *)array {
quizz = [NSArray arrayWithArray:array];
NSLog(#"setQuizz : %#",quizz);
}
There is no problem for writing the quizz object (setQuizz), however when I try to access it for reading, I get a crash : the quizz looks invalid and Xcode notify me an invalid CFArrayRef
I don't know what's wrong with my code.
You provide a custom setter for quizz but it doesn't comply with how the property is declared.
You're not retaining quizz when you're setting a new value. It's likely to be released just after, leading to a crash when you access it.
You should write
- (void)setQuizz:(NSArray *)array {
if (quizz != array) {
NSArray *tmp = quizz;
quizz = [array retain]; // retain the new value
[tmp release]; // release the old one
}
NSLog(#"setQuizz : %#",quizz);
}
this is way more code than it needs to be. First if you are going to be providing your own method you should declare so in the #property declaration which you didn't. Also your not properly retaining your variables. Additionally you should be using dispatch_once() for a thread safe & fast way to guarantee the singleton is only created once.
#interface MyCommon : NSObject {}
#property(nonatomic, retain) NSArray *quiz;
#property (assign) int iCurrentQuestion;
+ (MyCommon *)singleton;
#end
#implementation MyCommon
#synthesize quiz;
#synthesize iCurrentQuestion;
-(id)init {
self = [super init];
if(self) {
quiz = [[NSMutableArray alloc init];
iCurrentQuestion = 0;
}
return self;
}
+ (MyCommon *)singleton {
static MyCommon *singleton = nil;
static dispatch_once_t pred;
dispatch_once(&pred, ^{
singleton = [[MyCommon alloc] init];
});
return singleton;
}
#end
then you just do
[MyCommon singleton].quiz = //some array

how do you make a "concurrent queue safe" lazy loader (singleton manager) in objective-c

I made this class that turns any object into a singleton, but I know that it's not "concurrent queue safe." Could someone please explain to me how to do this, or better yet, show me the code. To be clear I want to know how to use this with operation queues and dispatch queues (NSOperationQueue and Grand Central Dispatch) on iOS.
Thanks in advance,
Rich
EDIT: I had an idea for how to do it. If someone could confirm it for me I'll do it and post the code. The idea is that proxies make queues all on their own. So if I make a mutable proxy (like Apple does in key-value coding/observing) for any object that it's supposed to return, and always return the same proxy for the same object/identifier pair (using the same kind of lazy loading technique as I used to create the singletons), the proxies would automatically queue up the any messages to the singletons, and make it totally thread safe.
IMHO this seems like a lot of work to do, so I don't want to do it if it's not gonna work, or if it's gonna slow my apps down to a crawl.
Here's my non-thread safe code:
RMSingletonCollector.h
//
// RMSingletonCollector.h
// RMSingletonCollector
//
// Created by Rich Meade-Miller on 2/11/11.
// Copyright 2011 Rich Meade-Miller. All rights reserved.
//
#import <Foundation/Foundation.h>
#import "RMWeakObjectRef.h"
struct RMInitializerData {
// The method may take one argument.
// required
SEL designatedInitializer;
// data to pass to the initializer or nil.
id data;
};
typedef struct RMInitializerData RMInitializerData;
RMInitializerData RMInitializerDataMake(SEL initializer, id data);
#interface NSObject (SingletonCollector)
// Returns the selector and data to pass to it (if the selector takes an argument) for use when initializing the singleton.
// If you override this DO NOT call super.
+ (RMInitializerData)designatedInitializerForIdentifier:(NSString *)identifier;
#end
#interface RMSingletonCollector : NSObject {
}
+ (id)collectionObjectForType:(NSString *)className identifier:(NSString *)identifier;
+ (id<RMWeakObjectReference>)referenceForObjectOfType:(NSString *)className identifier:(NSString *)identifier;
+ (void)destroyCollection;
+ (void)destroyCollectionObjectForType:(NSString *)className identifier:(NSString *)identifier;
#end
// ==--==--==--==--==Notifications==--==--==--==--==
extern NSString *const willDestroySingletonCollection;
extern NSString *const willDestroySingletonCollectionObject;
RMSingletonCollector.m
//
// RMSingletonCollector.m
// RMSingletonCollector
//
// Created by Rich Meade-Miller on 2/11/11.
// Copyright 2011 Rich Meade-Miller. All rights reserved.
//
#import "RMSingletonCollector.h"
#import <objc/objc-runtime.h>
NSString *const willDestroySingletonCollection = #"willDestroySingletonCollection";
NSString *const willDestroySingletonCollectionObject = #"willDestroySingletonCollectionObject";
RMInitializerData RMInitializerDataMake(SEL initializer, id data) {
RMInitializerData newData;
newData.designatedInitializer = initializer;
newData.data = data;
return newData;
}
#implementation NSObject (SingletonCollector)
+ (RMInitializerData)designatedInitializerForIdentifier:(NSString *)identifier {
return RMInitializerDataMake(#selector(init), nil);
}
#end
#interface RMSingletonCollector ()
+ (NSMutableDictionary *)singletonCollection;
+ (void)setSingletonCollection:(NSMutableDictionary *)newSingletonCollection;
#end
#implementation RMSingletonCollector
static NSMutableDictionary *singletonCollection = nil;
+ (NSMutableDictionary *)singletonCollection {
if (singletonCollection != nil) {
return singletonCollection;
}
NSMutableDictionary *collection = [[NSMutableDictionary alloc] initWithCapacity:1];
[self setSingletonCollection:collection];
[collection release];
return singletonCollection;
}
+ (void)setSingletonCollection:(NSMutableDictionary *)newSingletonCollection {
if (newSingletonCollection != singletonCollection) {
[singletonCollection release];
singletonCollection = [newSingletonCollection retain];
}
}
+ (id)collectionObjectForType:(NSString *)className identifier:(NSString *)identifier {
id obj;
NSString *key;
if (identifier) {
key = [className stringByAppendingFormat:#".%#", identifier];
}
else {
key = className;
}
if (obj = [[self singletonCollection] objectForKey:key]) {
return obj;
}
// dynamic creation.
// get a class for
Class classForName = NSClassFromString(className);
if (classForName) {
obj = objc_msgSend(classForName, #selector(alloc));
// if the initializer takes an argument...
RMInitializerData initializerData = [classForName designatedInitializerForIdentifier:identifier];
if (initializerData.data) {
// pass it.
obj = objc_msgSend(obj, initializerData.designatedInitializer, initializerData.data);
}
else {
obj = objc_msgSend(obj, initializerData.designatedInitializer);
}
[singletonCollection setObject:obj forKey:key];
[obj release];
}
else {
// raise an exception if there is no class for the specified name.
NSException *exception = [NSException exceptionWithName:#"com.RMDev.RMSingletonCollector.failed_to_find_class" reason:[NSString stringWithFormat:#"SingletonCollector couldn't find class for name: %#", [className description]] userInfo:nil];
[exception raise];
[exception release];
}
return obj;
}
+ (id<RMWeakObjectReference>)referenceForObjectOfType:(NSString *)className identifier:(NSString *)identifier {
id obj = [self collectionObjectForType:className identifier:identifier];
RMWeakObjectRef *objectRef = [[RMWeakObjectRef alloc] initWithObject:obj identifier:identifier];
return [objectRef autorelease];
}
+ (void)destroyCollection {
NSDictionary *userInfo = [singletonCollection copy];
[[NSNotificationCenter defaultCenter] postNotificationName:willDestroySingletonCollection object:self userInfo:userInfo];
[userInfo release];
// release the collection and set it to nil.
[self setSingletonCollection:nil];
}
+ (void)destroyCollectionObjectForType:(NSString *)className identifier:(NSString *)identifier {
NSString *key;
if (identifier) {
key = [className stringByAppendingFormat:#".%#", identifier];
}
else {
key = className;
}
[[NSNotificationCenter defaultCenter] postNotificationName:willDestroySingletonCollectionObject object:[singletonCollection objectForKey:key] userInfo:nil];
[singletonCollection removeObjectForKey:key];
}
#end
RMWeakObjectRef.h
//
// RMWeakObjectRef.h
// RMSingletonCollector
//
// Created by Rich Meade-Miller on 2/12/11.
// Copyright 2011 Rich Meade-Miller. All rights reserved.
//
// In order to offset the performance loss from always having to search the dictionary, I made a retainable, weak object reference class.
#import <Foundation/Foundation.h>
#protocol RMWeakObjectReference <NSObject>
#property (nonatomic, assign, readonly) id objectRef;
#property (nonatomic, retain, readonly) NSString *className;
#property (nonatomic, retain, readonly) NSString *objectIdentifier;
#end
#interface RMWeakObjectRef : NSObject <RMWeakObjectReference>
{
id objectRef;
NSString *className;
NSString *objectIdentifier;
}
- (RMWeakObjectRef *)initWithObject:(id)object identifier:(NSString *)identifier;
- (void)objectWillBeDestroyed:(NSNotification *)notification;
#end
RMWeakObjectRef.m
//
// RMWeakObjectRef.m
// RMSingletonCollector
//
// Created by Rich Meade-Miller on 2/12/11.
// Copyright 2011 Rich Meade-Miller. All rights reserved.
//
#import "RMWeakObjectRef.h"
#import "RMSingletonCollector.h"
#implementation RMWeakObjectRef
#dynamic objectRef;
#synthesize className, objectIdentifier;
- (RMWeakObjectRef *)initWithObject:(id)object identifier:(NSString *)identifier {
if (self = [super init]) {
NSString *classNameForObject = NSStringFromClass([object class]);
className = classNameForObject;
objectIdentifier = identifier;
objectRef = object;
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(objectWillBeDestroyed:) name:willDestroySingletonCollectionObject object:object];
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(objectWillBeDestroyed:) name:willDestroySingletonCollection object:[RMSingletonCollector class]];
}
return self;
}
- (id)objectRef {
if (objectRef) {
return objectRef;
}
objectRef = [RMSingletonCollector collectionObjectForType:className identifier:objectIdentifier];
return objectRef;
}
- (void)objectWillBeDestroyed:(NSNotification *)notification {
objectRef = nil;
}
- (void)dealloc {
[[NSNotificationCenter defaultCenter] removeObserver:self];
[className release];
[super dealloc];
}
#end
The easiest (and thread safe) acces to singleton:
static SomeClass* shared_instance;
+(SomeClass*) sharedInstance {
#synchronized( shared_instance ) {
if( !shared_instance ) {
shared_instance = [[SomeClass alloc] init];
//some additional initialization here
}
}
return shared_instance;
}
Edit:
I think particular singleton class would be your best choice. Even for lazy loading. E.g. you need to access some array of users all over your app. Then you can create singleton class:
UserManager:
+(UserManager*) sharedManager;
-(NSArray*) allUsers;
-(NSArray*) recentUsers;
-(NSArray*) featuredUsers;
-(void) addUser:(User*) user;
-(void) removeUser:(User*) user;
etc...
Then you will be able to access that arrays in every view controller.
You should create singleton for other types.