Unexpected result when overriding a method of a class cluster - ios

While implementing a subclass of NSArray (a class cluster), I was surprised to see that my overridden description method was not called. Can somebody explain what is happening here?
#interface MyArrayClassCluster : NSArray
#end
#implementation MyArrayClassCluster
{
NSArray *_realArray;
}
// Implement the class cluser stuff here
- (NSUInteger)count
{
return [_realArray count];
}
- (id)objectAtIndex:(NSUInteger)index
{
return [_realArray objectAtIndex:index];
}
// lifeCycle
- (id)initWithItems:(NSArray *)items
{
self = [super init];
_realArray = [items retain];
return self;
}
- (void)dealloc
{
[_realArray release];
[super dealloc];
}
- (NSString *)description
{
return [NSString stringWithFormat:#"My Custom Array: %p, objs:%#", self, _realArray];
}
#end
int main(int argc, const char * argv[])
{
#autoreleasepool {
NSArray *a = #[#1, #2, #3];
NSLog(#"a: %#", a);
MyArrayClassCluster *clzCluster = [[MyArrayClassCluster alloc] initWithItems:a];
NSLog(#"clzCluster: %#", clzCluster);
}
return 0;
}
Output
2013-01-29 18:52:38.704 ClassClusterTester[31649:303] a: (
1,
2,
3
)
2013-01-29 18:52:38.707 ClassClusterTester[31649:303] clzCluster: (
1,
2,
3
)

The link #Rob pointed to had the correct answer at the bottom. An obscure fact: if something implements descriptionWithLocale:, NSLog will call that instead. Since my class is a subclass of NSArray, and NSArray implements that, my version of description was not called.

Related

Objective-C How to add objects to NSMutableArray from other place?

Hello I'm junior in Objective-C and Swift programming.
I have NSMutableArray in ExampleMenuViewController.m or(and) SomeClass.m declared as vcTabs.
NSMutableArray *vcTabs;
When I have two declares 'vcTabs' Xcode returns duplicate symbol '_vcTabs' (...)
How to add objects to an existing NSMutableArray init in other class (ExampleMenuViewController.m)?
I need append new objects from another class (SomeClass.m) to vcTabs (NSMutableArray).
I wrote in SomeClass.m this code:
if ([Tools isNonullValueForKey:[dictionary valueForKey:#"additional_tabs"]]) {
additional_tabs = [dictionary valueForKey:#"additional_tabs"];
NSLog(#"additionalTabs count: %lu", [additional_tabs count]);
for (int i = 0; i < [additional_tabs count]; i++) {
if ([Tools isNonullValueForKey:[additional_tabs valueForKey:#"_id"]]) {
additional_tab_id = [[additional_tabs valueForKey:#"_id"] objectAtIndex:i];
}
if ([Tools isNonullValueForKey:[additional_tabs valueForKey:#"names"]]) {
NSDictionary *dic = [[additional_tabs valueForKey:#"names"] objectAtIndex:i];
_en_additional_tab_name = [dic valueForKey:#"en"];
_pl_additional_tab_name = [dic valueForKey:#"pl"];
}
if ([Tools isNonullValueForKey:[additional_tabs valueForKey:#"url"]]) {
additional_tab_url = [[additional_tabs valueForKey:#"url"] objectAtIndex:i];
//NSLog(#"additional_tab_url: %#", _additional_tab_url);
}
[vcTabs addObject:[[VCTab alloc] initWithIdAndTypeAndUrl:additional_tab_id :VCTabAdditional :additional_tab_url]];
NSLog(#"%# %d %# %# %# %#", #"pos", i, #"id: ", additional_tab_id, #"url: ", additional_tab_url);
}
}
ExampleMenuViewController method with initVCTabs
- (void)initVCTabs {
vcTabs = [[NSMutableArray alloc] init];
[vcTabs removeAllObjects];
if ([Tools getBooleanUserDefault:#"example_visible_tab_attendees" :YES]) {
[vcTabs addObject:[[VCTab alloc] initWithType:VCTabAttendees]];
}
(...)
if ([Tools getBooleanUserDefault:#"example_visible_tab_user_info" :YES]) {
[vcTabs addObject:[[VCTab alloc] initWithType:VCTabUserInfo]];
}
if ([Tools getStringUserDefault:#"example_additional_tab_id" :#""]) {
NSString *additionalTabId = [Tools getStringUserDefault:#"conference_additional_tab_id" :#""];
NSString *additionalTabUrl = [Tools getStringUserDefault:#"conference_additional_tab_url" :#""];
NSLog(#"additionalTabId %#", additionalTabId);
NSLog(#"additionalTabUrl %#", additionalTabUrl);
[vcTabs addObject:[[VCTab alloc] initWithIdAndTypeAndUrl:additionalTabId :VCTabAdditional :additionalTabUrl]];
}
}
PS. If I use from ExampleMenuViewController I have only one tab with last object properties... but additional_tabs array have 17 objects.
Do you have any ideas or advices?
All the best for you everyone!
When are you calling initVCTabs?
When / how is the code in SomeClass.m running?
For being a "junior in Objective-C and Swift programming" you seem to have a lot going on that you don't understand yet. Try creating a new project and learn how things work -- then implement that in your full project.
Here is a very, very simple example. With the information you provided in your question, this may or may not relate directly - but it should give you an idea of where to go:
SomeClass.h
// SomeClass.h
// Created by Don Mag on 8/30/20.
#import <Foundation/Foundation.h>
NS_ASSUME_NONNULL_BEGIN
#interface SomeClass : NSObject
- (void)moreTabs:(NSMutableArray *)a;
#end
NS_ASSUME_NONNULL_END
SomeClass.m
// SomeClass.m
// Created by Don Mag on 8/30/20.
#import "SomeClass.h"
#interface SomeClass()
#end
#implementation SomeClass
- (void)moreTabs:(NSMutableArray *)a {
[a addObject:#"B"];
[a addObject:#"C"];
[a addObject:#"D"];
[a addObject:#"E"];
}
#end
ExampleMenuViewController.h
// ExampleMenuViewController.h
// Created by Don Mag on 8/30/20.
#import <UIKit/UIKit.h>
NS_ASSUME_NONNULL_BEGIN
#interface ExampleMenuViewController : UIViewController
#end
NS_ASSUME_NONNULL_END
ExampleMenuViewController.m
// ExampleMenuViewController.m
// Created by Don Mag on 8/30/20.
#import "ExampleMenuViewController.h"
#import "SomeClass.h"
#interface ExampleMenuViewController ()
{
NSMutableArray *vcTabs;
}
#end
#implementation ExampleMenuViewController
- (void)viewDidLoad {
[super viewDidLoad];
// add a button to the view
//UIButton *b = [UIButton new];
UIButton *b = [UIButton buttonWithType:UIButtonTypeSystem];
[b setTitle:#"Tap Me" forState:UIControlStateNormal];
b.frame = CGRectMake(0, 0, 200, 50);
b.center = self.view.center;
[self.view addSubview:b];
[b addTarget:self action:#selector(btnTapped) forControlEvents:UIControlEventTouchUpInside];
[self initVCTabs];
[self logArray];
}
- (void)initVCTabs {
// instantiate NSMutableArray
vcTabs = [NSMutableArray new];
// add one object
[vcTabs addObject:#"A"];
}
- (void)btnTapped {
SomeClass *sc = [SomeClass new];
[sc moreTabs:vcTabs];
[self logArray];
}
- (void)logArray {
NSLog(#"vcTabs has %ld objects", [vcTabs count]);
for (NSString *s in vcTabs) {
NSLog(#"%#", s);
}
}
#end
When ExampleMenuViewController loads, it will add a button to the center of the view, then instantiate the vcTabs array and add one object - #"A".
We log the array to the debug console and see:
vcTabs has 1 objects
A
When you tap the button, an instance of SomeClass will be created, we call the moreTabs method in that class, passing a reference to vcTabs. That method will add 4 objects to the array - #"B" #"C" #"D" #"E".
We then log the array to the debug console and see:
vcTabs has 5 objects
A
B
C
D
E
#DonMag
It's working but I have one question to you. I added for loop to increment. When I add [additional_tabs count] is return nil. Why this method adds the same objects? My code in addMore function:
- (void)moreTabs:(NSMutableArray *)a {
for (int i = 1; i < additional_tab_count; i++) {
NSString *additionalTabId = [Tools getStringUserDefault:#"conference_additional_tab_id" :#""];
NSString *additionalTabUrl = [Tools getStringUserDefault:#"conference_additional_tab_url" :#""];
[a addObject:[[VCTab alloc] initWithIdAndTypeAndUrl:additionalTabId :VCTabAdditional :additionalTabUrl]];
}
}
Do you know how to get THIS "dictionary" or "additional_tabs". I tried but always return nil (looks like a new other instance and is not this dictionary or additional_tabs from initFromJSON). I only managed to make variable additional_tab_count and it's return 17 (correct count), but I'd rather have access to array from additional_tabs declared in if statements.

#NotEmpty annotation in Objective C?

Is there possibility to create custom annotation which will check if parameter of method is empty array or empty string? Something like #NotEmpty in Java. I already use _Nonnull and check parameter with NSParameterAssert but I am curious does we can write custom annotation?
Thanks.
You can use macros to define an inline function.
#define isNil(x) nil ==x
Objective-C has no customizable annotations of this sort, but one of its major strengths is the versatility of its runtime.
And so, if we really wanted to, we could implement this with a wrapper class type:
#interface NotEmpty<Object> : NSProxy
#property(readonly,copy) Object object;
+ (instancetype)notEmpty:(Object)object;
- (instancetype)initWithObject:(Object)object;
#end
#implementation NotEmpty {
id _object;
}
- (id)object {
return _object;
}
+ (instancetype)notEmpty:(id)object {
return [[self alloc] initWithObject:object];
}
- (instancetype)initWithObject:(id)object {
if ([object respondsToSelector:#selector(length)]) {
NSParameterAssert([object length] != 0);
} else {
NSParameterAssert([object count] != 0);
}
_object = [object copy];
return self;
}
- (NSMethodSignature *)methodSignatureForSelector:(SEL)selector {
if (selector == #selector(object)) {
return [NSMethodSignature signatureWithObjCTypes:"#:"];
} else {
return [_object methodSignatureForSelector:selector];
}
}
- (void)forwardInvocation:(NSInvocation *)invocation {
invocation.target = _object;
[invocation invoke];
}
#end
#interface SomeClass : NSObject
#end
#implementation SomeClass
- (void)method:(NotEmpty<NSString*> *)nonEmptyString {
// Call NSString methods, option 1
unsigned long length1 = [(id)nonEmptyString length];
// Call NSString methods, option 2
unsigned long length2 = nonEmptyString.object.length;
// Note that just printing `nonEmptyString` (not nonEmptyString.object)
// will print an opaque value. If this is a concern, then also forward
// #selector(description) from -methodSignatureForSelector:.
NSLog(#"Received: %# (length1: %lu length2: %lu)", nonEmptyString.object, length1, length2);
}
#end
int main() {
SomeClass *sc = [SomeClass new];
[sc method:[NotEmpty notEmpty:#"Not an empty string"]];
// [sc method:[NotEmpty notEmpty:#""]]; // Raises error
}
Do note that this will cause some small performance penalties.

is it possible to swizzle addObject: in NSMutableArray?

Is it possible to swizzle the addObject: method of NSMutableArray?
Here is what I am trying.
#import <Foundation/Foundation.h>
#import <objc/runtime.h>
#implementation NSMutableArray (LoggingAddObject)
+ (void)load {
Method addObject = class_getInstanceMethod(self, #selector(addObject:));
Method logAddObject = class_getInstanceMethod(self, #selector(logAddObject:));
method_exchangeImplementations(addObject, logAddObject);
Method original = class_getInstanceMethod(self, #selector(setObject:atIndexedSubscript:));
Method swizzled = class_getInstanceMethod(self, #selector(swizzled_setObject:atIndexedSubscript:));
method_exchangeImplementations(original, swizzled);
}
- (void)logAddObject:(id)anObject {
[self logAddObject:anObject];
NSLog(#"Added object %# to array %#", anObject, self);
}
-(void)swizzled_setObject:(id)obj atIndexedSubscript:(NSUInteger)idx
{
NSLog(#"This gets called as expected!!-----");
[self swizzled_setObject:obj atIndexedSubscript:idx];
}
I am able to swizzle some of the methods like setObject:atIndexedSubscript: but I am worried that I cant do it do the addObject: and others.
I think the below can not be swizzled? Can someone explain why ? what I am doing wrong and or a way around this?
/**************** Mutable Array ****************/
#interface NSMutableArray : NSArray
- (void)addObject:(id)anObject;
- (void)insertObject:(id)anObject atIndex:(NSUInteger)index;
- (void)removeLastObject;
- (void)removeObjectAtIndex:(NSUInteger)index;
- (void)replaceObjectAtIndex:(NSUInteger)index withObject:(id)anObject;
#end
You can try this with NSProxy, but I don't suggest you to use it on production code because:
it will break something (some framework may require NSMutableArray to throw exception when add nil into it to prevent more serious error later. i.e. Fail fast)
it is slow
If you really want to avoid nil checking, I suggest you to make a subclass of NSMutableArray and use it everywhere in your code. But really? There are so many ObjC code using NSMutableArray, most of them doesn't need this feature. So why you are so special?
#import <objc/runtime.h>
#interface XLCProxy : NSProxy
+ (id)proxyWithObject:(id)obj;
#end
#implementation XLCProxy
{
id _obj;
}
+ (void)load
{
Method method = class_getClassMethod([NSMutableArray class], #selector(allocWithZone:));
IMP originalImp = method_getImplementation(method);
IMP imp = imp_implementationWithBlock(^id(id me, NSZone * zone) {
id obj = ((id (*)(id,SEL,NSZone *))originalImp)(me, #selector(allocWithZone:), zone);
return [XLCProxy proxyWithObject:obj];
});
method_setImplementation(method, imp);
}
+ (id)proxyWithObject:(id)obj
{
XLCProxy *proxy = [self alloc];
proxy->_obj = obj;
return proxy;
}
- (void)forwardInvocation:(NSInvocation *)invocation
{
[invocation setTarget:_obj];
[invocation invoke];
const char *selname = sel_getName([invocation selector]);
if ([#(selname) hasPrefix:#"init"] && [[invocation methodSignature] methodReturnType][0] == '#') {
const void * ret;
[invocation getReturnValue:&ret];
ret = CFBridgingRetain([XLCProxy proxyWithObject:CFBridgingRelease(ret)]);
[invocation setReturnValue:&ret];
}
}
-(NSMethodSignature *)methodSignatureForSelector:(SEL)sel
{
return [_obj methodSignatureForSelector:sel];
}
- (Class)class
{
return [_obj class];
}
- (void)addObject:(id)obj
{
[_obj addObject:obj ?: [NSNull null]];
}
- (BOOL)isEqual:(id)object
{
return [_obj isEqual:object];
}
- (NSUInteger)hash {
return [_obj hash];
}
// you can add more methods to "override" methods in `NSMutableArray`
#end
#interface NSMutableArrayTests : XCTestCase
#end
#implementation NSMutableArrayTests
- (void)testExample
{
NSMutableArray *array = [NSMutableArray array];
[array addObject:nil];
[array addObject:#1];
[array addObject:nil];
XCTAssertEqualObjects(array, (#[[NSNull null], #1, [NSNull null]]));
}
#end
You can iterate over all registered classes, check if current class is a subclass of NSMutableArray, if so, swizzle.
I would advice against it, rather act on case-by-case basis to have more predictable behavior - you never know which other system frameworks rely in this particular behavior (e.g. I can see how CoreData might rely on this particular behavior)
You can swizzle any NSMutableArray method in the following way:
#implementation NSMutableArray (Swizzled)
+ (void)load
{
Method orig = class_getInstanceMethod(NSClassFromString(#"__NSArrayM"), NSSelectorFromString(#"addObject:"));
Method override = class_getInstanceMethod(NSClassFromString(#"__NSArrayM"), #selector(addObject_override:));
method_exchangeImplementations(orig, override);
}
- (void)addObject_override:(id)anObject
{
[self addObject_override:anObject];
NSLog(#"addObject called!");
}

Calling a method from a different view controller

I've been exploring virtual card deck randomisation and drawing of cards as a little side hobby recently, and have been focussing on a great tutorial found at Ontswedder. However, I've run into a minor issue which I'm hoping you can help me with!
Below, I've included some key aspects of the code for your viewing.
In my viewController, I'm wanting to call both the shuffle and draw methods, found in Deck.m. This is possible if I do the following:
Deck *d = [[Deck alloc] init];
[d shuffle];
[d deal];
However, I need to be able to split these. For example, clicking one button initialises the deck, and shuffles it, whilst another new button draws a new card (until the deck is empty).
I am having issues with this, and I could do the following:
Deck *d = [[Deck alloc] init];
[d shuffle];
Deck *d = [[Deck alloc] init];
[d deal];
But this is useless to me, as if I call the init then a NEW, UNSHUFFLED deck is created and the card is dealt from this new deck.
I've tried declaring Deck *DeckObject in viewController.h, then simply calling [DeckObject draw];, however this provides a null value.
Ultimately, I would like to call these two methods separately. Without needing to init a new deck every time if possible!! :-)
I greatly appreciate both everyone's help on this post but also site-wide!
I hope this makes sense, too. Please let me know if you would like more information.
Also, I apologise if any of my terminology is incorrect - still a bit of a newbie!
Included code for context:
Card.h
typedef enum {
Hearts,
Diamonds,
Spades,
Clubs
} Suit;
#define Ace 1
#define Jack 11
#define Queen 12
#define King 13
#interface Card : NSObject {
NSInteger value;
Suit suit;
}
#property (nonatomic) NSInteger value;
#property (nonatomic) Suit suit;
- (id) initWithValue:(NSInteger) aValue suit:(Suit) aSuit;
#end
Card.m
#interface Card(Private)
- (NSString *) valueAsString;
- (NSString *) suitAsString;
#end
#implementation Card
#synthesize value,suit;
- (id) initWithValue:(NSInteger) aValue suit:(Suit) aSuit {
if(self = [super init]) {
self.value = aValue;
self.suit = aSuit;
}
return self;
}
- (NSString *) valueAsString {
switch (self.value) {
case Ace:
return #"Ace";
break;
case Jack:
return #"Jack";
break;
case Queen:
return #"Queen";
break;
case King:
return #"King";
break;
default:
return [NSString stringWithFormat:#"%d",self.value];
break;
}
}
- (NSString *) suitAsString {
switch (self.suit) {
case Hearts:
return #"Hearts";
break;
case Diamonds:
return #"Diamonds";
break;
case Spades:
return #"Spades";
break;
case Clubs:
return #"Clubs";
break;
default:
return nil;
break;
}
}
- (NSString *) description {
return [NSString stringWithFormat:#"%# %#",
[self valueAsString],
[self suitAsString]];
}
#end
Deck.h
#interface Deck : NSObject {
#private
NSMutableArray *cards;
}
- (void) shuffle;
- (Card *) draw;
- (NSInteger) cardsRemaining;
#end
Deck.m
#implementation Deck
- (id) init {
if(self = [super init]) {
cards = [[NSMutableArray alloc] init];
for(int suit = 0; suit <= 3; suit++) {
for(int value = 1; value <= 13; value++) {
Card *card = [[Card alloc] initWithValue:value suit:suit];
[cards addObject:card];
[card release];
}
}
}
return self;
}
int randomSort(id obj1, id obj2, void *context ) {
// returns random number -1 0 1
return (arc4random()%3 - 1);
}
- (void) shuffle {
for(int x = 0; x < 500; x++) {
[cards sortUsingFunction:randomSort context:nil];
}
}
- (Card *) draw {
if([self cardsRemaining] > 0) {
Card *card = [[cards lastObject] retain];
[cards removeLastObject];
return [card autorelease];
}
NSException* myException = [NSException
exceptionWithName:#"OutOfCardsException"
reason:#"Tried to draw a card from a deck with 0 cards." userInfo:nil]; #throw
myException;
}
- (NSInteger) cardsRemaining {
return [cards count];
}
- (NSString *) description {
NSString *desc = [NSString stringWithFormat:#"Deck with %d cards\n",[self
cardsRemaining]];
for(int x = 0; x < [self cardsRemaining]; x++) {
desc = [desc stringByAppendingFormat:#"%#\n",[[cards objectAtIndex:x] description]];
}
return desc;
}
- (void) dealloc {
[cards release];
[super dealloc];
}
#end
When you declare the property deckObject, that just creates the pointer, you still have to alloc init a Deck object to create an instance.
self.deckObject = [[Deck alloc] init];
Then, you can use [self.deckObject shuffle] and [self.deckObject deal]in different button methods.
you have to declaring Deck *DeckObject in viewController.h as below
#interface firstViewController : UIViewController {
Deck *DeckObject;
}
Now in viewController.m file's viewDidLoad method initialize it like below
Deck *DeckObject = [[Deck alloc] init];
after that you can call methods in uibutton's action method
- (IBAction)BtnShuffle:(id)sender
{
if (DeckObject) {
[DeckObject shuffle];
}
}
and
- (IBAction)BtnDraw:(id)sender
{
if (DeckObject) {
[DeckObject draw];
}
}

Objective C - sample Singleton implementation

*I definitely need a break... cause was simple - array was not allocated... Thanks for help. Because of that embarrassing mistake, I flagged my post in order to delete it. I do not find it useful for Users ;) *
I have just tried to create a singleton class in iOS, but I probably I am making a mistake. Code (no ARC is a requirement):
#import "PeopleDatabase.h"
#import "Person.h"
#import <Foundation/Foundation.h>
#interface PeopleDatabase : NSObject{objetive
NSMutableArray* _arrayOfPeople;
}
+(PeopleDatabase *) getInstance;
#property (nonatomic, retain) NSMutableArray* arrayOfPeople;
#end
--
#implementation PeopleDatabase
#synthesize arrayOfPeople = _arrayOfPeople;
static PeopleDatabase* instance = nil;
-(id)init{
if(self = [super init]) {
Person* person = [[[Person alloc] initWithName:#"John" sname:#"Derovsky" descr:#"Some kind of description" iconName:#"johnphoto.png" title:Prof] retain];
[_arrayOfPeople addObject:person];
NSLog(#"array count = %d", [_arrayOfPeople count]); // <== array count = 0
[person release];
}
return self;
}
+(PeopleDatabase *)getInstance {
#synchronized(self)
{
if (instance == nil)
NSLog(#"initializing");
instance = [[[self alloc] init] retain];
NSLog(#"Address: %p", instance);
}
return(instance);
}
-(void)dealloc {
[instance release];
[super dealloc];
}
#end
When invoking getInstance like here:
PeopleDatabase *database = [PeopleDatabase getInstance];
NSLog(#"Adress 2: %p", database);
Address 2 value the same value as in getInstance.
The standard way of creating a singleton is like...
Singleton.h
#interface MySingleton : NSObject
+ (MySingleton*)sharedInstance;
#end
Singleton.m
#import "MySingleton.h"
#implementation MySingleton
#pragma mark - singleton method
+ (MySingleton*)sharedInstance
{
static dispatch_once_t predicate = 0;
__strong static id sharedObject = nil;
//static id sharedObject = nil; //if you're not using ARC
dispatch_once(&predicate, ^{
sharedObject = [[self alloc] init];
//sharedObject = [[[self alloc] init] retain]; // if you're not using ARC
});
return sharedObject;
}
#end
Check this apple doc on how to create singleton instance:
https://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/CocoaFundamentals/CocoaObjects/CocoaObjects.html
#synchronized(self)
{
if (instance == nil)
NSLog(#"initializing");
instance = [[[self alloc] init] retain];
NSLog(#"Address: %p", instance);
}
You appear to be missing your braces for that if statement. As written, the only thing you do different when instance == nil is emit a log message.
After web reading and personal practicing, my current singleton implementation is:
#interface MySingleton
#property myProperty;
+(instancetype) sharedInstance;
#end
#implementation MySingleton
+ (instancetype) sharedInstance
{
static dispatch_once_t pred= 0;
__strong static MySingleton *singletonObj = nil;
dispatch_once (&pred, ^{
singletonObj = [[super allocWithZone:NULL]init];
singletonObj.myProperty = initialize ;
});
return singletonObj;
}
+(id) allocWithZone:(NSZone *)zone
{
return [self sharedInstance];
}
-(id)copyWithZone:(NSZone *)zone
{
return self;
}
this is a thread safe implementation and avoids the risk to create new objects by calling "alloc init" on your class. Attributes initialization has to occur inside the block, not inside "init" override for similar reasons.
This is an error that can be avoided by some disziplined convention which is to always use curly brackets followed by if and else.
+(PeopleDatabase *)getInstance {
#synchronized(self)
{
if (instance == nil)
NSLog(#"initializing");
instance = [[[self alloc] init] retain];
NSLog(#"Address: %p", instance);
}
return(instance);
}
If instance is nil then the very next statement and only that is executed. And that is the nslog and not the allocation. Then instance is allocated anyway, regardless wether it was used before or not. This will provide you with a new singleton on each call. BTW that causes a leak.
+(PeopleDatabase *)getInstance {
#synchronized(self)
{
if (instance == nil) {
NSLog(#"initializing");
instance = [[[self alloc] init] retain];
NSLog(#"Address: %p", instance);
}
}
return(instance);
}
But this error came in while debugging. It may confuse you but does not solve your original problem. Please add an alloc and init and retain for _arrayOfPeople as well.
-(id)init{
if(self = [super init]) {
Person* person = [[[Person alloc] initWithName:#"John" sname:#"Derovsky" descr:#"Some kind of description" iconName:#"johnphoto.png" title:Prof] retain];
_arrayOfPeople = [[[NSMutableArray alloc] init] retain]; //dont forget the release
[_arrayOfPeople addObject:person];
NSLog(#"array count = %d", [_arrayOfPeople count]); // <== array count = 1 !!!
[person release];
}
return self;
}
In your code _arrayOfPeople is nil and addObject is sent to nil which does not cause an abort but does not do anything either. Then count is sent to nil wich returns 0/nil.
in this function +(PeopleDatabase *)getInstance i think you need to place curly Braces correctly : like this
+(PeopleDatabase *)getInstance {
#synchronized(self)
{
if (instance == nil)
{
NSLog(#"initializing");
instance = [[[self alloc] init] retain];
NSLog(#"Address: %p", instance);
}
return instance ;
}
}

Resources