3

I used to store the array data downloaded from the server. But I can not save them in the singleton array.

It seems without access to the object.

Why ulatitude, ulongitude, uaccuracy, uplacename is nil?...

in .h file

#import <Foundation/Foundation.h>
@interface LocationData : NSObject
{
    NSMutableArray *ulatitude;
    NSMutableArray *ulongitude;
    NSMutableArray *uaccuracy;
    NSMutableArray *uplacename;
}
@property (nonatomic, retain) NSMutableArray *ulatitude;
@property (nonatomic, retain) NSMutableArray *ulongitude;
@property (nonatomic, retain) NSMutableArray *uaccuracy;
@property (nonatomic, retain) NSMutableArray *uplacename;
+ (LocationData*) sharedStateInstance;
@end

in .m file

#import "LocationData.h"

@implementation LocationData

@synthesize uaccuracy;
@synthesize ulatitude;
@synthesize ulongitude;

+ (LocationData*) sharedStateInstance {
        static LocationData *sharedStateInstance;

        @synchronized(self) {
            if(!sharedStateInstance) {
                sharedStateInstance = [[LocationData alloc] init];
            }
        }
        return sharedStateInstance;
}
@end

use

[manager POST:urlStr parameters:params success:^(AFHTTPRequestOperation *operation, id responseObject)
    {

                 NSLog(@"%@",responseObject);

                 // json response array
                 if ([responseObject isKindOfClass:[NSArray class]]) {

                     NSArray *responseArray = responseObject;
                     NSDictionary *responseDict = [[NSDictionary alloc] init];

                     LocationData* sharedState = [LocationData sharedStateInstance];

                     for(NSUInteger i=0; i < responseArray.count; i++)
                     {
                         responseDict = [responseArray objectAtIndex:i];

                         double dlat = [[responseDict objectForKey:@"lat"] doubleValue];
                         double dlng = [[responseDict objectForKey:@"lng"] doubleValue];

                          [[sharedState ulatitude] addObject:[NSString stringWithFormat:@"%f",dlat]];
                          [[sharedState ulongitude] addObject:[NSString stringWithFormat:@"%f",dlng]];
                          [[sharedState uaccuracy] addObject:[responseDict objectForKey:@"rad"]];
                          [[sharedState uplacename] addObject:[responseDict objectForKey:@"place_name"]];
}
2
  • Why do you have instance variables defined, and why synthesize 3 of the properties (instead of zero)? Commented Feb 15, 2016 at 10:33
  • Also, unless you aren't using ARC, you should define the properties as strong instead of retain. Commented Feb 15, 2016 at 10:35

5 Answers 5

7

You always need to initialize your arrays. You should do somewhere before you try to add something to them:

arrayName = [[NSMutableArray alloc] init];

otherwise you'll always get error because they have not been initialized.

In your case you should override your LocationData init function like this:

- (instancetype)init {
    self = [super init];
    if (self) {
        self.yourArrayName = [[NSMutableArray alloc] init];
        // And so on....
    }
    return self;
}
Sign up to request clarification or add additional context in comments.

1 Comment

"Somewhere" being init.
1

You need to initialize your object properly. Basically your member variables ("ivars") are pointing to nothing ("nil").

This initializer added to your .m file code do the job.

-(instancetype)init {
    if ((self = [super init])) {
                    self.accuracy = [NSMutableArray array];
                    self.latitude = [NSMutableArray array];
                    self.longitude = [NSMutableArray array];
                    self.uplacename = [NSMutableArray array];
    }
    return self;
}

As a singleton pattern, I'd prefer the following:

+ (LocationData*) sharedStateInstance {
    static LocationData *sharedStateInstance = nil;
    static dispatch_once_t onceToken = 0;
    dispatch_once(&onceToken, ^{
        sharedStateInstance = [[LocationData alloc] init];
    });
    return sharedStateInstance;
}

Although singletons might not be as bad they are often said to be, I don't thing that this is a good usage for them. Your specific problem has nothing to do with that design choice, though.

4 Comments

Don't forget this is manual reference counting. Using self.array = is recommended and you should show how what to do in the dealloc method too, regardless of the singleton status of the class (someone may decide to make it not singleton somewhere down the line).
I was assuming that ARC is the standard today unless told otherwise.
@property (nonatomic, retain) tells otherwise.
@trojanfoe Good catch, have missed that one. Fixed. :)
0

Try this code. Write getters for your NSMutableArrays.

#import <Foundation/Foundation.h>
@interface LocationData : NSObject

@property (nonatomic, retain) NSMutableArray *ulatitude;
@property (nonatomic, retain) NSMutableArray *ulongitude;
@property (nonatomic, retain) NSMutableArray *uaccuracy;
@property (nonatomic, retain) NSMutableArray *uplacename;
+ (LocationData*) sharedStateInstance;
@end


#import "LocationData.h"

@implementation LocationData

@synthesize uaccuracy = _uaccuracy;
@synthesize ulatitude = _ulatitude;
@synthesize ulongitude = _ulongitude;

+ (LocationData*) sharedStateInstance {
        static LocationData *sharedStateInstance;

        @synchronized(self) {
            if(!sharedStateInstance) {
                sharedStateInstance = [[LocationData alloc] init];
            }
        }
        return sharedStateInstance;
}


-(NSMutableArray*)uaccuracy
{
    if(_uaccuracy == nil)
    {
        _uaccuracy = [[NSMutableArray alloc]init];
    }
    return uaccuracy;
}

-(NSMutableArray*)ulongitude
{
    if(_ulongitude == nil)
    {
        _ulongitude = [[NSMutableArray alloc]init];
    }
    return ulongitude;
}

-(NSMutableArray*)ulatitude
{
    if(_ulatitude == nil)
    {
        _ulatitude = [[NSMutableArray alloc]init];
    }
    return ulatitude;
}

-(NSMutableArray*)uplacename
{
    if(_uplacename == nil)
    {
        _uplacename = [[NSMutableArray alloc]init];
    }
    return uplacename;
}
@end

8 Comments

It doesn't make any sense to synthesize properties with their default name, and then also have another bunch of differently named ivars around that won't be used at all.
Even though it will work. It will not lead you towards any error. Moreover you can remove @synthesis. It will also work. I just mentioned this in synthesis so that he may know the concept of ivars. Otherwise he would be thinking from where this "_" sign is coming. You can see I haven't used ivar for uplacename property.
Down voting for just getting attention towards your answer isn't appreciated.
I really hate down voting other answers, but this code has severe problems. Fix them, and I'll change the vote. As it stands, this code is a lying mess.
Have you tried this code? Writing getters is a lying mess, this is what I am hearing for the first time.
|
-1

you don't allocate/init any array...

you can create them in your singleton creation method

+ (LocationData*) sharedStateInstance {
        static LocationData *sharedStateInstance;

        @synchronized(self) {
            if(!sharedStateInstance) {
                sharedStateInstance = [[LocationData alloc] init];
                sharedStateInstance.ulatitude = [[NSMutableArray alloc] init];
                // (add others...)
            }
        }
        return sharedStateInstance;
}

5 Comments

No. The init method should allocate and initialize the arrays.
there's no difference, here or in init... it's a singleton class, and so it's supposed to be a MUST passing by the + (LocationData*) sharedStateInstance method
Your answer will certainly solve the OPs issue, however it will do it poorly. init is the place to initialize a class instance, regardless of the number of instances that can exist.
"Your answer will certainly solve the OPs issue"... so why down-vote my answer? it was clear, in the title question too, that we were talking about a singleton class, and it's not a good idea, in general (but exceptions may exits), have a singleton class AND other instances of this class
@trojanfoe: ok, sorry for thinking that
-1

Replace your LocationData.m file with below code , this will work . As you have to alloc and init the array then only you can add object in array

+ (LocationData*) sharedStateInstance {
            static LocationData *sharedStateInstance;
                    @synchronized(self) {
                    if(!sharedStateInstance) {
                        sharedStateInstance = [[LocationData alloc] init];
                        uaccuracy = [[NSMutableArray alloc]init];
                        ulatitude = [[NSMutableArray alloc]init];
                        ulongitude = [[NSMutableArray alloc]init];
                        uplacename = [[NSMutableArray alloc]init];
                    }
                }

            return sharedStateInstance;
    }

6 Comments

This will always work and in shared instance you can alloc and init the array , this will stay as it is and it won't be always allocated and initialized as it is written in shared instance.
Are you sure about that?
Yes , as it is written inside @synchronized(self) and also it will allocate for single time , when the shared instance is allocated , and whenever applicaton is restart during that time it will allocated once.
So you can access the property uaccuracy from a class method then?
Well, how to put it... it won't even compile in the first place because there are four variables that are not declared at all.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.