How to reference a singleton? - objective-c

I am trying to use singleton in my app. I want to share 8 strings using a singleton.
This is the tutorial I referred to -> http://www.galloway.me.uk/tutorials/singleton-classes/
My code:
- MyManager.h
#import <foundation/Foundation.h>
#interface MyManager : NSObject {
NSString *someProperty1;
NSString *someProperty2;
NSString *someProperty3;
NSString *someProperty4;
NSString *someProperty5;
NSString *someProperty6;
NSString *someProperty7;
NSString *someProperty8;
}
#property (nonatomic, retain) NSString *someProperty1;
#property (nonatomic, retain) NSString *someProperty2;
#property (nonatomic, retain) NSString *someProperty3;
#property (nonatomic, retain) NSString *someProperty4;
#property (nonatomic, retain) NSString *someProperty5;
#property (nonatomic, retain) NSString *someProperty6;
#property (nonatomic, retain) NSString *someProperty7;
#property (nonatomic, retain) NSString *someProperty8;
+ (id)sharedManager;
#end
MyManager.m
#import "MyManager.h"
#implementation MyManager
#synthesize someProperty;
#pragma mark Singleton Methods
+ (id)sharedManager {
static MyManager *sharedMyManager = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
sharedMyManager = [[self alloc] init];
});
return sharedMyManager;
}
- (id)init {
if (self = [super init]) {
someProperty1 = [[NSString alloc] initWithString:#"Default Property Value"];
someProperty2 = [[NSString alloc] initWithString:#"Default Property Value"];
someProperty3 = [[NSString alloc] initWithString:#"Default Property Value"];
someProperty4 = [[NSString alloc] initWithString:#"Default Property Value"];
someProperty5 = [[NSString alloc] initWithString:#"Default Property Value"];
someProperty6 = [[NSString alloc] initWithString:#"Default Property Value"];
someProperty7 = [[NSString alloc] initWithString:#"Default Property Value"];
someProperty8 = [[NSString alloc] initWithString:#"Default Property Value"];
}
return self;
}
- (void)dealloc {
// Should never be called, but just here for clarity really.
}
#end
I want to use this singleton to use these string variables to add string in one other view and then use it to store in database in another third view.
Can someone please tell me how to reference them and store string in these variables and again access them in the third different view?

import MyManager.h where you use singleton.
[[MyManager sharedManager] setSomeProperty1:#abc"]; //for setting
[[MyManager sharedManager] someProperty1]; // for getting
or you can use like this also
MyManager *manager = [MyManager sharedManager];
manager.someProperty1 = #"abc";
NSString *str = manager.someProperty1;

Related

create Model class to parse without any library

I want to create a model class for the json.
My JSON example is given below
json response from API:
msg = '{"type":"TYPE_NM","payload":{"responseCode":0,"nextCheckTime":30}}';
I want to create a codable(Swift) properties is like in Objective-C.
I have created two nsobject interfaces as "type" and "payload". Below I am giving my class snippets.
//msg model
#interface MessageModel : NSObject
#property (nonatomic) NSString *type;
#property (nonatomic) Payload *payload;
#end
//for payload
#interface Payload : NSObject
#property (nonatomic) NSUInteger responseCode;
#property (nonatomic) NSUInteger nextCheckTime;
#end
You can convert json string to NSDictionary object and use it to create MessageModel
Payload
#interface Payload : NSObject
#property (nonatomic) NSUInteger responseCode;
#property (nonatomic) NSUInteger nextCheckTime;
#end
#implementation Payload
- (instancetype)initWithDictionary:(NSDictionary *)dict {
self = [super init];
if (self) {
_responseCode = [dict[#"responseCode"] integerValue];
_nextCheckTime = [dict[#"nextCheckTime"] integerValue];
}
return self;
}
#end
MessageModel
#interface MessageModel : NSObject
#property (nonatomic) NSString *type;
#property (nonatomic) Payload *payload;
#end
#implementation MessageModel
- (instancetype)initWithDictionary:(NSDictionary *)dict {
self = [super init];
if (self) {
_type = dict[#"type"];
_payload = [[Payload alloc] initWithDictionary:dict[#"payload"]];
}
return self;
}
- (instancetype)initWithJson:(NSString *)json {
self = [super init];
if (self) {
NSData *data = [json dataUsingEncoding:NSUTF8StringEncoding];
NSDictionary *dict = [NSJSONSerialization JSONObjectWithData:data options:0 error:nil];
_type = dict[#"type"];
_payload = [[Payload alloc] initWithDictionary:dict[#"payload"]];
}
return self;
}
#end
Usage
NSString *input = #"{\"type\":\"TYPE_NM\",\"payload\":{\"responseCode\":0,\"nextCheckTime\":30}}";
MessageModel *model = [[MessageModel alloc] initWithJsonString:input];

Pulling coordinates for MapView annotations from MySQL database, but annotations aren't showing?

I'm trying to pull coordinates for my MapView from a MySQL database, but for some reason my coordinates just aren't showing up on the MapView?
See below my code.
MapViewController.h file
#import <UIKit/UIKit.h>
#import <MapKit/MapKit.h>
#interface MapViewController : UIViewController <MKMapViewDelegate>
#property (nonatomic, strong) IBOutlet MKMapView *mapView;
#property (nonatomic, retain) NSMutableArray *dispensaries;
#property (nonatomic, retain) NSMutableData *data;
#end
MapViewController.m
#import "MapViewController.h"
#import "MapViewAnnotation.h"
#import "JSONKit.h"
#implementation MapViewController
#synthesize mapView;
#synthesize dispensaries;
#synthesize data;
#pragma mark - View lifecycle
- (void)viewDidLoad {
[super viewDidUnload];
NSLog(#"Getting Device Locations");
NSString *hostStr = #"http://stylerepublicmagazine.com/dispensaries.php";
NSData *dataURL = [NSData dataWithContentsOfURL:[NSURL URLWithString:hostStr]];
NSString *serverOutput = [[NSString alloc] initWithData:dataURL encoding: NSASCIIStringEncoding];
NSLog(#"server output: %#", serverOutput);
NSMutableArray *array = [[[serverOutput objectFromJSONString] mutableCopy] autorelease];
dispensaries = [serverOutput objectFromJSONString];
NSLog(#"%#", [serverOutput objectFromJSONString]);
for (NSDictionary *dictionary in array) {
assert([dictionary respondsToSelector:#selector(objectForKey:)]);
CLLocationCoordinate2D coord = {[[dictionary objectForKey:#"lat"] doubleValue], [[dictionary objectForKey:#"lng"] doubleValue]};
MapViewAnnotation *ann = [[MapViewAnnotation alloc] init];
ann.title = [dictionary objectForKey:#"Name"];
ann.coordinate = coord;
[mapView addAnnotation:ann];
}
[mapView setMapType:MKMapTypeStandard];
[mapView setZoomEnabled:YES];
[mapView setScrollEnabled:YES];
self.mapView.delegate = self;
}
- (void)mapView:(MKMapView *)mapView didUpdateUserLocation:(MKUserLocation *)userLocation {
MKCoordinateRegion region = MKCoordinateRegionMakeWithDistance(userLocation.coordinate, 800, 800);
[self.mapView setRegion:[self.mapView regionThatFits:region] animated:YES];
MKPointAnnotation *point = [[MKPointAnnotation alloc] init];
point.coordinate = userLocation.coordinate;
point.title = #"You Are Here";
point.subtitle = #"Your current location";
[self.mapView addAnnotation:point];
}
MapViewAnnotation.h
#import <Foundation/Foundation.h>
#import <MapKit/MKAnnotation.h>
#import <CoreLocation/CoreLocation.h>
#interface MapViewAnnotation : NSObject <MKAnnotation> {
CLLocationCoordinate2D coordinate;
NSString *title;
NSString *subtitle;
}
#property (nonatomic, assign) CLLocationCoordinate2D coordinate;
#property (nonatomic, copy) NSString *title;
#property (nonatomic, copy) NSString *subtitle;
#end
MapViewAnnotation.m
#import "MapViewAnnotation.h"
#implementation MapViewAnnotation
#synthesize title, coordinate, subtitle;
-(void)dealloc{
[title release];
[super dealloc];
}
#end
this seems to be an issue with you expecting the wrong JSON:
You wrap the serverOutput in an array:
NSMutableArray *array = [NSMutableArray arrayWithObject:[serverOutput objectFromJSONString]];
You try to access a JKDictionary (Json Kit dictionary) WITCH is infact an array and therefore doesn't answer to objectForKey:
try to make sure:
for (NSDictionary *dictionary in array) {
assert([dictionary respondsToSelector:#selector(objectForKey:)]);
--
potential Solution
I believe your extra wrapping makes it bad. try:
NSMutableArray *array = [[[serverOutput objectFromJSONString] mutableCopy] autorelease];

Map coordinates not decoding

In my app, I am trying to save the pins that are on the map so that they are there when the user opens the app after it is terminated. I have conformed my mkAnnotation class to NSCoding, and implemented the two required methods. The annotations are all stored in a NSMutableArray in a singleton class, so I am really just trying to save the array in the singleton class. Everything is being encoded fine, but I do not think they are being decoded. Here is some code:
This is my MKAnnotation class:
#import <CoreLocation/CoreLocation.h>
#import <MapKit/MapKit.h>
#interface MapPoint : NSObject <MKAnnotation, NSCoding>
{
}
- (id)initWithAddress:(NSString*)address
coordinate:(CLLocationCoordinate2D)coordinate
title:(NSString *)t;
#property (nonatomic, readwrite) CLLocationCoordinate2D coordinate;
//This is an optional property from MKAnnotataion
#property (nonatomic, copy) NSString *title;
#property (nonatomic, readonly, copy) NSString *subtitle;
#property (nonatomic) BOOL animatesDrop;
#property (nonatomic) BOOL canShowCallout;
#property (copy) NSString *address;
#property (nonatomic, copy) NSString *imageKey;
#property (nonatomic, copy) UIImage *image;
#end
#implementation MapPoint
#synthesize title, subtitle, animatesDrop, canShowCallout, imageKey, image;
#synthesize address = _address, coordinate = _coordinate;
-(id)initWithAddress:(NSString *)address
coordinate:(CLLocationCoordinate2D)coordinate
title:(NSString *)t {
self = [super init];
if (self) {
_address = [address copy];
_coordinate = coordinate;
[self setTitle:t];
NSDate *theDate = [NSDate date];
subtitle = [NSDateFormatter localizedStringFromDate:theDate
dateStyle:NSDateFormatterShortStyle
timeStyle:NSDateFormatterShortStyle];
}
return self;
}
- (void)encodeWithCoder:(NSCoder *)aCoder {
[aCoder encodeObject:_address forKey:#"address"];
NSLog(#"ENCODING coordLatitude %f coordLongitude %f ", _coordinate.latitude, _coordinate.longitude);
[aCoder encodeDouble:_coordinate.longitude forKey:#"coordinate.longitude"];
[aCoder encodeDouble:_coordinate.latitude forKey:#"coordinate.latitude"];
[aCoder encodeObject:title forKey:#"title"];
}
- (id)initWithCoder:(NSCoder *)aDecoder {
self = [super init];
if (self) {
[self setAddress:[aDecoder decodeObjectForKey:#"address"]];
NSLog(#"DECODING coordLatitude %f coordLongitude %f ", _coordinate.latitude, _coordinate.longitude);
_coordinate.longitude = [aDecoder decodeDoubleForKey:#"coordinate.longitude"];
_coordinate.latitude = [aDecoder decodeDoubleForKey:#"coordinate.latitude"];
[self setTitle:[aDecoder decodeObjectForKey:#"title"]];
}
return self;
}
#end
Here is my singleton class:
#import <Foundation/Foundation.h>
#class MapPoint;
#interface Data : NSObject
{
NSMutableArray *_annotations;
}
#property (retain, nonatomic) NSMutableArray *annotations;
+ (Data *)singleton;
- (NSString *)pinArchivePath;
- (BOOL)saveChanges;
#end
#implementation Data
#synthesize annotations = _annotations;
+ (Data *)singleton {
static dispatch_once_t pred;
static Data *shared = nil;
dispatch_once(&pred, ^{
shared = [[Data alloc] init];
shared.annotations = [[NSMutableArray alloc]init];
});
return shared;
}
- (id)init {
self = [super init];
if (self) {
NSString *path = [self pinArchivePath];
_annotations = [NSKeyedUnarchiver unarchiveObjectWithFile:path];
if (!_annotations) {
_annotations = [[NSMutableArray alloc]init];
}
}
return self;
}
- (NSString *)pinArchivePath {
NSArray *cachesDirectories = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES);
NSString *cachesDirectory = [cachesDirectories objectAtIndex:0];
return [cachesDirectory stringByAppendingPathComponent:#"pins.archive"];
}
- (BOOL)saveChanges {
NSString *path = [self pinArchivePath];
return [NSKeyedArchiver archiveRootObject:[Data singleton].annotations
toFile:path];
}
#end
In my viewDidLoad method on the map view controller, I try and place the annotations in the singleton array on the map with this:
for (MapPoint *mp in [Data singleton].annotations) {
[_worldView addAnnotation:mp];
}
The main problem is in the singleton method in these lines:
dispatch_once(&pred, ^{
shared = [[Data alloc] init];
shared.annotations = [[NSMutableArray alloc]init]; //<-- problem line
});
The shared = [[Data alloc] init]; line decodes and initializes the annotations array.
Then the shared.annotations = [[NSMutableArray alloc]init]; line re-creates and re-initializes the annotations array thus discarding the just-decoded annotations so the singleton always returns an empty array.
Remove the shared.annotations = [[NSMutableArray alloc]init]; line.
As already mentioned in the comment, the other minor issue, which causes simply confusion, is the placement of the NSLog where the coordinate is being decoded. The NSLog should be after the decode is done.

objective-c Object memory management

I have this simple class which I know is ok in terms of memory leaks.
#interface location : NSObject {
NSString *name;
float lat;
float lon;
NSString *subtitle;
}
#property (nonatomic, retain) NSString *name;
#property (nonatomic, retain) NSString *subtitle;
#property (nonatomic, assign) float lat;
#property (nonatomic, assign) float lon;
#end
#implementation location
#synthesize name;
#synthesize lon;
#synthesize lat;
#synthesize subtitle;
-(void)dealloc{
[name release];
[subtitle release];
[super dealloc];
}
#end
There is retain in the #property so i release in the dealloc method. Now, my question is: If I alloc one of the strings in a init method or some other method I create, should I do another release? If so, when?
#implementation location
#synthesize name;
#synthesize lon;
#synthesize lat;
#synthesize subtitle;
-(void) init{
name = [[NSString alloc] init];
}
-(void)dealloc{
[name release]; // IS THIS CORRECT?!
[subtitle release];
[super dealloc];
}
#end
If you are assigning value using self. notation then you should release (as retain was called automatically, if you use synthesize) if your were using alloc + init approach for creating new object. Example:
NSString *str = [[NSString alloc] init];
self.name = str;
[str release];
If you are assigning value using self. notation and assigning autoreleased object then you shouldn't retain and release. Example:
NSString *str = [NSString string];
self.name = str;
If you are assigning value without self. prefix then you should not assign autorelease object and should not release, you just should alloc + init object. Example:
NSString *str = [[NSString alloc] init];
name = str;
Or if you want to assign autoreleased object without self. prefix then you should retain it. Example:
NSString *str = [NSString string];
name = [str retain];
In dealloc method you should release objects if you didn't do that earlier.
Basically you don't need retain here as you are not reatining anything. Your code is same as if all the properties are assigned.
until you don't call self.name, the retain semantics is not applied.
There is a code style which remove that confusion. keep the property name and instance name different and assign instance name to property name at #synthesize.
Like this:
#interface location : NSObject {
NSString *name;
}
#property (nonatomic, retain) NSString *nameProp;
#end
#implementation location
#synthesize nameProp = name;

Adding objects to a NSMutableArray property

this is my data strucure:
group [1...n] {
id,
name,
elements : [1...n]
}
I define a class for element with all properties and a class for group as:
#interface Group : NSObject {
NSInteger groupID;
NSString *groupName;
NSMutableArray *elements;
}
#property (assign, readwrite) NSInteger groupID;
#property (assign, readwrite) NSString *groupName;
#property (assign, readwrite) NSMutableArray *elements;
and single element with:
#interface Element : NSObject {
NSInteger elementID;
NSString *elementName;
}
#property (assign, readwrite) NSInteger elementID;
#property (assign, readwrite) NSString *elementName;
Both classes have properties and synthesize.
When application start I inserted data on data structure with this:
arrGroup = [NSMutableArray array];
[arrGroup retain];
Element *element1 = [[Element alloc] init];
element1.elemenID = 1;
element1.elemenName = #"Andrea";
Element *element = [[Element alloc] init];
element2.elementID = 2;
element2.elementName = #"Andrea2";
Group *group = [[Group alloc] init];
group.groupID = 1;
group.groupName = #"Grup 1";
[group.elements addObject:element1];
[group.elements addObject:element2];
[contact1 release];
[contact2 release];
[arrGroup addObject:group];
The problem is this the [group.elements addObjct:element1]. Nothing has been written on elements NSMutableArray.
Could you help me to find the error? There is a better method to retrieve structure data (groups of elemens)?
thanks for help!
Andrea
#synthesize only generates the getter and the setter for your property, you have to take care of initialization yourself if needed.
To initialize the mutable array do e.g. this in your initializer:
- (id)init { // or however it is named
if ((self = [super init])) {
elements = [[NSMutableArray alloc] init];
// ... more?
}
return self;
}
- (void)dealloc {
[elements release]; // don't forget to clean up
// ... more?
[super dealloc];
}