New Object Instances are not running the Customized Initializer - ios

I am working on a project that contains a Singleton instance of a class called Survey. Within that singleton instance is a property called "itemArray," which is an NSMutableArray that contains any number of instances of an Item class.
My Items class contains several NSInteger properties, but for the purposes of the application, I need to initialize all NSIntegers with a value of -1 instead of the default 0.
Now, for my Survey class (the one with the Singleton instance), I use the following method in the implementation to change the default value of a property:
-(id)init {
if (self = [super init]) {
_thingy = -1;
}
return self;
}
This works, but for some reason, the same exact syntax (with different properties) doesn't work for instances of my Item instances. For what it's worth, the following codeblock is the creation of 2 instances of Item, and their insertion into itemArray. I also tried the Item *item1 = [[Item alloc]init; method to no avail.
Item *item1;
[[[Survey sharedInstance]itemArray]insertObject:item1 atIndex:0];
Item *item2;
[[[Survey sharedInstance]itemArray]insertObject:item2 atIndex:1];
}
I would appreciate any assistance.
!!!!!UPDATE!!!!!
I entered the following conditional:
if (![[Survey sharedInstance]itemArray]){
NSLog(#"Test");
}
And the "test" logged onto the console, so it looks like the itemArray isn't being initialized. I'm not sure how to actually initialize it, though. When I try the following:
[[Survey sharedInstance]addressArray] = [[NSMutableArray alloc]init];
I'm getting an error saying "Expression is not assignable."
Survey.h:
#import <Foundation/Foundation.h>
#interface Survey : NSObject
+(instancetype)sharedInstance;
#property (nonatomic, strong) NSString *name;
#property (nonatomic, strong) NSString *emailAddress;
#property (nonatomic, assign) NSInteger trigger1;
#property (nonatomic, assign) NSInteger trigger2;
#property (nonatomic, assign) NSInteger trigger3;
#property (nonatomic, assign) NSInteger activeItem;
#property (nonatomic, strong) NSMutableArray *itemArray;
#end
Survey.m
#import "Survey.h"
#implementation Survey
+ (instancetype)sharedInstance {
static Survey *_instance;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
_instance = [[Survey alloc] init];
});
return _instance;
}
-(id)init {
if (self = [super init]) {
_storage = -1;
}
return self;
}
#end

Instead of
[[Survey sharedInstance]addressArray] = [[NSMutableArray alloc]init];
you need to use
[Survey sharedInstance].addressArray = [[NSMutableArray alloc]init];
or
[[Survey sharedInstance] setAddressArray:[[NSMutableArray alloc]init]];
You were trying to assign a value to the return value of a getter method, which is not possible, so the compiler was saying "Expression not assignable." You need to use the setter method or dot notation instead.

Related

How come the instance of my object is missing the properties I want to assign?

I am trying to create a class in with properties defined in the header. Was planning to populate the object in a for loop. Here is the header, what could I be doing wrong? Am I defining this class wrong?
#import <UIKit/UIKit.h>
#import <CoreLocation/CoreLocation.h>
#interface ViewController : UIViewController<UIPickerViewDataSource,
...
#end
#interface PickerObject : NSObject
{
NSString *minutes;
NSNumber *label;
}
#end
In the viewDidLoad I get message saying property minutes not found.
NSMutableArray *arr = [[NSMutableArray alloc] init];
for(int x = 0; x < total; x++)
{
PickerObject *myObject = [[PickerObject alloc] init];
myObject.minutes = x;
myObject.label = #"%# minutes",x;
[_pickerData addObject:myObject];
//[_pickerData addObject:[NSNumber numberWithInt:x]];
[arr addObject:[NSNumber numberWithInt:x]];
}
Here is a screenshot of the error depicting property not found
To access object variables using the dot '.' operator in Objective-C, you need a setter method. The easiest way to achieve this is by defining a property instead, like this:
#interface PickerObject : NSObject
{
}
#property (nonatomic, strong) NSString *minutes;
#property (nonatomic, strong) NSNumber *label;
#end
The object variables, setter- and getter methods you need will be synthesised automatically.

Add object to NSMUtable Array Singleton

I have a shared singleton classNSMutableArray [ICGlobals sharedApplianceCount](first time using this pattern so bear with me if ive done something really silly here)
.h
#import <Foundation/Foundation.h>
#interface ICGlobals : NSObject
{
NSMutableArray* applianceCount;
}
#property (nonatomic, retain) NSString *applianceCount;
+ (ICGlobals *)sharedApplianceCount;
#end
.m
#import "ICGlobals.h"
#implementation ICGlobals
static ICGlobals *sharedApplianceCount = nil;
+ (ICGlobals *)sharedUser {
if(sharedApplianceCount == nil){
sharedApplianceCount = [[super allocWithZone:NULL] init];
}
return sharedApplianceCount;
}
+ (id)allocWithZone:(NSZone *)zone {
return [self sharedApplianceCount];
}
- (id)copyWithZone:(NSZone *)zone {
return self;
}
#end
In "another view controller" im trying to add the row count of my table view (changeable amount of rows) = self.circuits.count
Having tried this
[[ICGlobals sharedApplianceCount] addObject: self.circuits.count,nil]];
and
[[ICGlobals sharedApplianceCount] = [[NSMutableArray alloc] init];
[[ICGlobals sharedApplianceCount] addObject: self.circuits.count,Nil]];
I get no visible #interface error saying my singleton class declares the selector
same with
NSNumber* numberOfRows = [NSNumber numberWithInteger:self.circuits.count];
[[ICGlobals sharedApplianceCount]addObject:[NSMutableArray arrayWithObjects:numberOfRows, nil]];
and with
[ICGlobals sharedApplianceCount] = self.circuits.count;
I get expression assignable. Singleton class has been imported.
You have an inconsistency in your interface declaration. You declare ivar of type NSMutableArray and then a NSString property. Firstable, you don't need to declare ivar, declaring a property does it for you. So your interface should look like:
#interface ICGlobals : NSObject
#property (nonatomic, retain) NSMutableArray *applianceCount;
+ (ICGlobals *)sharedApplianceCount;
#end
Furthermore, you have a naming glitch. You should not use name applianceCount for an array. In general, naming convention of Cocoa suggests that count should be a number (int or NSUInteger). I would change this property name to applianceCounts.
Then, when you initialize your singletone, you can also initialize the array:
+ (ICGlobals *)sharedUser
{
if(sharedApplianceCount == nil)
{
sharedApplianceCount = [[super allocWithZone:NULL] init];
sharedApplianceCount.applianceCounts = [[NSMutableArray alloc] init];
}
return sharedApplianceCount;
}
Finally, here is how to add data to your singletone's applianceCounts array from view controller.
NSNumber* numberOfRows = [NSNumber numberWithInteger:self.circuits.count];
[[ICGlobals sharedApplianceCount].applianceCounts addObject:numberOfRows];
This should point you to right direction.
I don't fully get what you are trying to achieve like I don't understand why you want to have an array there, so if you need further help please let me know in the comments.
I fully recommend you reading about naming conventions. A good start is this article:
Introduction to Coding Guidelines for Cocoa.
I would recommend some refactoring to your class.
First you make the interface like this:
#interface ICGlobals : NSObject
// add the app count but make it private, because you will provide methods to access it
#property (nonatomic, readonly) NSString *applianceCount;
// return ICGlobals instance
+ (ICGlobals)sharedCounter;
- (NSInteger)count;
- (void)addObject:(id)object;
now in .m file
#implementation ICGlobals
static ICGlobals *sharedApplianceCount = nil;
// this is your method, just changed the name
+ (ICGlobals *)sharedCounter {
if(sharedApplianceCount == nil){
sharedApplianceCount = [[super allocWithZone:NULL] init];
}
return sharedApplianceCount;
}
// instance methods goes here
- (NSInteger)count
{
return _applicationCount.count;
}
- (void)addObject:(id)object
{
[_applicationCount addObject:object];
}
Now call [[ICGlobals sharedCount]addObject:object] from any viewController

Issue passing object to NSMutableArray in AppDelegate

I'm having trouble making a shopping cart sort-of concept in my app. I have my AppDelegate (named ST2AppDelegate) that contains an NSMutableArray called myCart. I want RecipeViewController.m to pass an NSString object to myCart, but every time I pass it the NSString and use NSLog to reveal the contents of the array, it is always empty.
Can anyone please tell me what I am doing wrong? I have worked on this code for days, and there is a line of code in which I don't understand at all what's going on (in the RecipeViewController.m, labeled as such).
Any help would be so appreciated... I'm just a beginner. Here are the relevant classes:
ST2AppDelegate.h:
#import <UIKit/UIKit.h>
#interface ST2AppDelegate : UIResponder <UIApplicationDelegate>
#property (strong, nonatomic) UIWindow *window;
#property (strong, nonatomic) NSMutableArray* myCart;
- (void)addToCart:(NSString*)item;
- (void)readCartContents;
#end
ST2AppDelegate.m:
#import "ST2AppDelegate.h"
#implementation ST2AppDelegate
#synthesize myCart;
// all the 'applicationDid...' methods...
- (void)addToCart:(NSString *)item
{
[self.myCart addObject:item];
}
- (void)readCartContents
{
NSLog(#"Contents of cart: ");
int count = [myCart count];
for (int i = 0; i < count; i++)
{
NSLog(#"%#", myCart[count]);
}
}
#end
RecipeDetailViewController.h:
#import <UIKit/UIKit.h>
#import "ST2AppDelegate.h"
#interface RecipeDetailViewController : UIViewController
#property (nonatomic, strong) IBOutlet UILabel* recipeLabel;
#property (nonatomic, strong) NSString* recipeName;
#property (nonatomic, strong) IBOutlet UIButton* orderNowButton;
- (IBAction)orderNowButtonPress:(id)sender;
#end
RecipeDetailViewController.m:
#import "RecipeDetailViewController.h"
#implementation RecipeDetailViewController
#synthesize recipeName;
#synthesize orderNowButton;
// irrelevant methods...
- (IBAction)orderNowButtonPress:(id)sender
{
// alter selected state
[orderNowButton setSelected:YES];
NSString* addedToCartString = [NSString stringWithFormat:#"%# added to cart!",recipeName];
[orderNowButton setTitle:addedToCartString forState:UIControlStateSelected];
// show an alert
NSString* addedToCartAlertMessage = [NSString stringWithFormat:#"%# has been added to your cart.", recipeName];
UIAlertView* addedToCartAlert = [[UIAlertView alloc] initWithTitle:#"Cart Updated" message:addedToCartAlertMessage delegate:nil cancelButtonTitle:#"OK" otherButtonTitles:nil, nil];
[addedToCartAlert show];
// add to cart (I don't understand this, but it works)
[((ST2AppDelegate*)[UIApplication sharedApplication].delegate) addToCart:recipeName];
// read cart contents
[((ST2AppDelegate*)[UIApplication sharedApplication].delegate) readCartContents];
}
#end
You need to initialize myCart when your application launches:
self.myCart = [[NSMutableArray alloc] init];
otherwise you are just attempting to add objects to a nil object which while it won't throw an exception because of the way objective-c handles nil objects it will not function as expected until you initialize it.
Do you ever initalize the shopping cart variable?
Try doing lazy instantiation.
-(NSMutableArray *) myCart{
if (!_myCart){
_myCart = [[NSMutableArray alloc] init];
}
return _myCart;
}
This way you will know it will always get allocated. Basically, this method makes it so that whenever someone calls your classes version of the object it checks to see if that object has been allocated and then allocates it if it has not. It's a common paradigm that you should employ with most of your objects.
This method should go in the app delegate (where the object was declared).

iOS/iPhone - passing custom object between views. Object returns always null

I'm trying to pass a custom class between views. I have set a property for that class but when i access the property, the attributes return always null:
firstview.m:
- (void)initNextEventView{
NSDate *eventDate = [eventDatePicker date];
NSString *eventName = eventNameTextfield.text;
LocateEventViewController *locView = [[LocateEventViewController alloc]init];
locView.eventDTO.name = eventName;
locView.eventDTO.date = eventDate;
[[self navigationController] pushViewController:locView animated:YES];
}
LocateEventVC.h (2. view):
#interface LocateEventViewController : UIViewController<MKMapViewDelegate, UISearchBarDelegate, BSForwardGeocoderDelegate>
#property (strong, nonatomic) IBOutlet UIImageView *imageBackground;
#property (strong, nonatomic) EventDTO *eventDTO;
so when i log a attribute of eventDTO it returns null..
any help would be great
EDIT 1 (2. view):
Thats how I log:
NSLog(#"name on 2. view: %#", eventDTO.name);
self.eventDTO.place = tmpEventPlace;
// init friends view!
//passing to next view
EventMembersViewController *members = [[EventMembersViewController alloc]init];
members.eventDTO = self.eventDTO;
EventDTO.h
#interface EventDTO : NSObject
#property (nonatomic, retain) NSString * name;
#property (nonatomic, retain) UserDTO * creatorIsAppUser;
#property (nonatomic, retain) ContactDTO * creatorIsNotAppUser;
#property (nonatomic, retain) NSString * description;
#property (nonatomic, retain) NSDate * date;
#property (nonatomic, readwrite) NSInteger *eventID;
#property (nonatomic, retain) CustomPlacemark * place;
#property (nonatomic, retain) NSMutableArray *invitedMembers;
#property (nonatomic, retain) NSMutableArray *acceptedMembers;
- (NSNumber*)getLatidude;
- (NSNumber*)getLongitude;
EventDTO.m
#synthesize place, date, eventID, name, acceptedMembers, description, invitedMembers;
- (NSNumber*)getLatidude{
return [NSNumber numberWithDouble:place.coordinate.latitude];
}
- (NSNumber*)getLongitude{
return [NSNumber numberWithDouble:place.coordinate.longitude];
}
LocateEventViewController *locView = [[LocateEventViewController alloc]init];
locView.eventDTO.name = eventName;
locView.eventDTO.date = eventDate;
When you initiating locView, the object eventDTO doesn't exists. You have to initiate a new eventDTO right there, e.g.:
LocateEventViewController *locView = [[LocateEventViewController alloc]init];
YourClass *eventDTO = [[YourClass alloc] init];
locView.eventDTO = eventDTO;
locView.eventDTO.name = eventName;
locView.eventDTO.date = eventDate;
or directly in the -initmethod of your LocateEventViewController by adding
-(id)init {
...
self.eventDTO = [[YourClassHere alloc] init];
...
}
Please see this post for a full explanation. In short, you're going about it wrong:
Passing Data between View Controllers
Are you sure that the property eventDTO is set or allocated before accessing eventName and eventDate?
My guess is that eventDTO itself is nil. Calling method or accessing properties on nil objects is allowed in Objective-C. It does not crash as it would do in C++ or Java, it simply does nothing and returns nil if ht method has a return value.
I guess the property eventDTO is not properly initialized and it is nil itself.
Sending message to nil is legal in Objective-C, it simply fails silently and returns nil. It's a common pitfall when learning Objetive-C. And accessing property is just a syntactic sugar of sending messages.
BTW, "empty object" in Objective-C is represented by nil, not null, NULL or NO, although they are all zero.

Global Variable with SharedInstance not up to date

I have a little problem with a global variable. This is the class.h:
#import <Foundation/Foundation.h>
#interface GlobalVariables : NSObject{
NSMutableArray *categories;
}
#property (nonatomic, retain) NSMutableArray *categories;
+ (GlobalVariables *)sharedInstance;
#end
And this is the class.m file:
#import "GlobalVariables.h"
#implementation GlobalVariables
#synthesize categories;
+ (GlobalVariables *)sharedInstance
{
// the instance of this class is stored here
static GlobalVariables *myInstance = nil;
// check to see if an instance already exists
if (nil == myInstance) {
myInstance = [[[self class] alloc] init];
// initialize variables here
}
// return the instance of this class
return myInstance;
}
#end
So I now have 4 tabs with UITableViewController and each Tab needs data from the category array above.
The problem is, in the first tab an update algorithm is running to update this array but however this update is only available in tab 2 if I restart the app.
What can I do to immediately see these changes in all other tabs?

Resources