EXC_BAD_ACCESS when setting Integer to anything else than zero - iphone

I have this object:
#interface Song : NSManagedObject
#property (nonatomic, strong) NSString *songName;
#property (nonatomic) int32_t achievedPoints;
When I set the properties like this
Song *song1 = [[SongStore sharedStore] createSong];
song1.songName = #"Song 1";
song1.achievedPoints = 0;
everything works, however once I try to set the achievedPoints variable to something else than 0 I get an EXC_BAD_ACCESS.
This is what the createSong method does:
- (Song *)createSong {
double order;
if ([allSongs count] == 0) {
order = 1.0;
} else {
order = [[allSongs lastObject] orderingValue] + 1.0;
}
Song *p = [NSEntityDescription insertNewObjectForEntityForName:#"Song" inManagedObjectContext:context];
[p setOrderingValue:order];
[allSongs addObject:p];
return p;
}
I have no idea why getting the value and setting it to 0 works but anything else than zero crashes the program. Any help is highly appreciated.

This has happened to me once before. I don't know exactly which settings gets messed up, but there is a setting in your managed object model, I think, that controls whether or not the class should use primitive values (int, float, etc) or object values (NSNumber *, etc) to set its values. If this gets messed up, and you think you are setting a primitive when you are actually setting an object the following will happen:
//song1.achievedPoints = 0;
song1.achievedPoints = (NSNumber *)0x00000000;
//This is OK because it is the same as nil
//song1.achievedPoints = 1;
song1.achievedPoints = (NSNumber *)0x00000001; //You can see why this is bad!
My solution was to regenerate the class via the Create NSManagedObject Subclass template, making sure that Use Scalar Values for Primitives was checked.

This issue happened to me because the entity wasn't correctly linked to my class files. When this happened, Core Data creates its own subclass dynamically, rather than using my own, and that subclass's setters expect boxed primitives.
You can fix this by ensuring the "Class" property of your entity in the model file is set to the correct class, and not the default NSManagedObject.
When you use XCode's Create NSManagedObject Subclass template, XCode will automatically set this value for the corresponding entity in the model file. This is probably what fixed borrrden's problem. However, you should be able to achieve the same result without creating new files by ensuring this value is set correctly.

Related

Problem with class methods in objective c

i have a tableview controller like so,
NSString *selectedindex;
#interface ContactsController : UITableViewController<ABPeoplePickerNavigationControllerDelegate> {
NSMutableArray *names;
NSMutableArray *phonenumbers;
NSMutableArray *contacts;
DatabaseCRUD *sampledatabase;
}
+(NSString *) returnselectedindex;
#end
in the implementation file i have
+(NSString *) returnselectedindex
{
return selectedindex;
}
when a row is selected in the tableview i put have the following code.
selectedindex = [NSString stringWithFormat:#"%d", indexPath.row];
NSLog(#"selected row is %#",selectedindex);
in a different class i am trying to access the selectedindex. like so
selected = [ContactsController returnselectedindex];
NSLog(#"selected is %#",selected);
it gives me a warning: 'ContactsController' may not respond to '+returnselectedindex'
and crashes. i am not sure why. i have used class methods previously lot of times , and never had a problem. any help please. Thank You.
The reason you're crashing is that you're assigning a value to a global variable (selectedindex), but you're never taking ownership of it by calling -retain. As a result, the string doesn't know you need it to stay around, so the system deallocates it. Later, when you try to access it, it's already deallocated.
In order to avoid the crash, you need to add a retain call when you assign the value. Of course, since a selected index is something that's likely to be changing often, you'd want to release the previous value before overwriting it and retaining the new one. Thus, you should have this code:
[selectedindex release];
selectedindex = [[NSString stringWithFormat:#"%d", indexPath.row] retain];
That will fix your crash.
Now that your crash is fixed, though, you should really rethink your design. There's no reason for selectedindex to be a global variable; since the selected index is very likely specific to that instance of your ContactsController, it should be an instance variable of that class. Instead, you've declared it as a global variable, which means that there is only one selectedIndex shared between ALL instances of ContactsController. Then, in turn, your +returnselectedindex method should be an instance method, not a class method. (It should also be renamed in order to follow Cocoa naming conventions, but that's well off topic.)
I think You didn't allocated the selectedindex NSString.Thats why it will not crash on the same class and it crashes in the new Class.
So You allocate it in the setter method of "returnselectedindex"
Otherwise, Copy or retain the receive value of returnselectedindex value like this,
selected = [[ContactsController returnselectedindex]copy];

Filling an NSMutableArray with a Set of Classes and Then Getting them Back

Hopefully I can make this clear, but I am new to Objective-C and to be honest not great with Arrays in the first place.
So, I have a Singleton class (called SingletonState) that I am using to pass variables around my app (please can we leave the whether I should use Singleton classes out of this - I will fix that later). In this class, I have an NSMutableArray (called arrayMyEvents). I have also created a class that I am going to store a list of events (called EventClass). When the user logs in, I call a web service and get back 3 strings. The 3rd string is a comma separated list of value. I parse the data and populate the custom class EventClass. I then add this class to the SingletonState.arrayMyEvents.
I have all of this working. I can go to another ViewController and access the "count" of items in arrayMyEvents.
PROBLEM: I now want to edit one of the ScheduledEventsClass"es" in my array. How do I get access to it and edit some of the properties and update the one in my SingletonState class?
Here is some of the code, that I've tried:
NSString *sWebServiceEvents = [[NSString alloc] initWithFormat:#"%#", [result objectAtIndex:2]];
if ( [ sWebServiceEvents isEqualToString:#"NULL" ] != true ) {
NSArray *arrayEvents = [sWebServiceEvents componentsSeparatedByString:#","];
// If the array has not been initialized they initialize it.
if (sharedState.arrayMyEvents == nil) {
sharedState.arrayMyEvents = [[NSMutableArray alloc ] init ];
}
for (NSString * sEvent in arrayEvents) {
// Set equal to the value of the array (the Event Number) at the same
// position as the row that we are being asked to return a cell/row for.
EventClass *eventClass = [[EventClass alloc] retain];
eventClass.sEvent = sEvent;
[ sharedState.arrayEvents addObject:eventClass ];
}
NSLog(#"LoginView - sharedState.arrayMyEvents Count: %d", [sharedState.arrayMyEvents count]);
}
Here is me trying to access it in another ViewController:
EventClass *eventClass =
[sharedState.arrayMyEvents objectAtIndex:row ];
NSLog(#"eventClass.sEventNumber: ", eventClass.sEventNumber);
eventClass.sLocation = #"Jason's Big Location";
You're going to have some memory leaks from the sEvent loop. [[EventClass alloc]retain] leaves you an uninitialized EventClass object with a reference count of 2. You'll need to change that to [[[EventClass alloc] init] autorelease] to keep it from leaking. The arrayEvents NSMutableArray will retain it during the addObject: call. (Shouldn't that be [sharedState.arrayMyEvents addObject: eventClass] in the loop?)
After that, all you have to do to edit the EventClass object in the second block of code is edit it. The eventClass variable is a pointer to an object in the array. Anything done to that object doesn't affect the pointer referencing it, it affects data referenced by it. The code you have in the second block should change the sLocation of the selected object as you intend.
You have a few more memory leaks in there, too. Use Cmd-Shift-A to build with the static analyzer and it'll tell you where.
Maybe the problem is that you put them in sharedState.arrayEvents but try to take them out of sharedState.arrayMyEvents. Different variables.
Also, lots of memory leaks.
Thanks John and St3fan, your answers and time are appreciated!!!
I think that I figured out my issue:
Basically, the class that I created (EventClass) had the properties setup like this:
#property (nonatomic, assign) NSString *sStudyNumber;
#property (nonatomic, assign) NSString *sTheater;
but, they should be (or at least I got it to work like this):
#property (nonatomic, retain) NSString *sStudyNumber;
#property (nonatomic, retain) NSString *sTheater;
Then, in my second view I was able to do this:
EventClass *eventClass = [sharedState.arrayMyEvents objectAtIndex:row ];
NSLog(#"MyEvents: %#", eventClass.sEventNumber);
eventClass.sLocation = #"Jason's Big Location";
I then checked it in another method of the view using this and it was still there:
EventClass *eventClass = [sharedState.arrayMyEvents objectAtIndex:row ];
NSLog(#"MyEvents: %#", eventClass.sEventNumber);
NSLog(#"MyEvents: %#", eventClass.sLocation);
I also, checked it in yet another view and the value was maintained in the SharedState.arrayMyEvents without issue. :)
In the end, I believe that I boiled down to the difference between "assign" and "retain".
Now, on to the memory leaks :(
Please, let me know if you see any other issues with this.
Thanks,
Jason

Sharing variables amongst 2 ViewControllers

Here is a simple one for you guys . I'm defining a class to store variables in so I can reuse those variables in different ViewControllers .
Here is how I do it, it`s obviously not working ( that's why I'm asking a question ... ):
I declare a class :
VariableStore.h
#interface VariableStore : NSObject {
int evTe;
}
#property (nonatomic) int evTe;
+ (VariableStore *)shareInstance;
#end
VariableStore.m
#implementation VariableStore
#synthesize evTe;
+ (VariableStore *)sharedInstance {
static VariableStore *myInstance = nil;
return myInstance;
}
#end
Now in my FirstViewController I want to set the value for evTe :
[[VariableStore sharedInstance] setEvte:2];
NSLog(#"value testing, %i", evTe);
And this keeps on returning 0 unfortunately, Im obviously missing something important here but I can't figure out what it is .
Later on Id like to set the value for evTe here in the FirstViewController and then reuse it back in the SecondViewController ..
You are setting your shared instance to nil and then returning it:
static VariableStore *myInstance = nil;
return myInstance;
A nil instance won't hold your variable. It's nil.
First off you shouldn't be using a singleton to pass around variables. If you're going to do that then you might as well just use global variables instead (don't do that either by, the way). Second, if you insist on using a singleton, you need to read up on how to use them.
Finally, if you want to pass variables between view controllers, you either need another view controller that is a parent to the two to facilitate passing data between them, or one needs to call the other and take the first one or its data as a parameter.
Well, you're asking for the value of evTe without calling the object to which it belongs. Try this:
NSLog(#"value testing, %i", [[VariableStore sharedInstance] evTe]);
If you keep using the singleton for a number of times, you might want to do:
VariableStore *vStore = [VariableStore sharedInstance];
so you can do:
[vStore setEvTe:2];
NSLog(#"value testing, %i", [vStore evTe]);
And look out for what Matt said about nilling your singleton ;)
I think in nslog you should output not just evTe, but [[VariableStore sharedInstance] evTe].
First, you have to declare the static variable outside the function, in a way both controllers can access.
static VariableStore* myInstance = nil;
The singleton sharedInstance should be:
if(myInstance == nil)
{
myInstance = [[VariableStore] alloc] init];
}
return myInstance;

Obj-C: Creating an object with a String name

Hey all. I know this sounds simple, but I can't find a way to do it. I have a method in Obj-C that takes in a NSString and then should create a new class with the String as its title.
-(DataModel *)createDataModel:(NSString *)dataModel_name {
DataModel *[initWithString:dataModel_name] = [[DataModel alloc] init];
}
I know I have some problems in this. For starters, I don't know how to define a return on an object whose name could change. Second, I know this doesn't compile considering the initWithString method is wrong. I just don't know what to do or what method to use so that I can create this DataModel object with the specified name...
If your title is setup correctly, as a property:
-(DataModel *)createDataModel:(NSString *)dataModel_name {
DataModel *model = [[DataModel alloc] init];
model.title = dataModel_name;
return model;
}
That would require in your datamodel.h:
#interface DataModel {
NSString *title;
}
#property (nonatomic, retain) NSString *title;
#end
And in your .m:
#implementation DataModel
#synthesize title;
#end
But your question isn't clear if your real purpose is trying to instantiate different classes based on the dataModel_name or if you just have a single generic class with a title that should be set to dataModel_name.
Depending on what you want to do, there are different answers. If you really want different classes based on the name, then you should do things differently. You can use the Cocoa specific type: id, to return any object from a method. Then the method, NSClassFromString() to create the object:
- (id)createDataModel:(NSString *)dataModel_name {
id model = [[NSClassFromString(dataModel_name) alloc] init];
[model setTitle:dataModel_name];
return model;
}
Or you can define a Protocol (Interface in java parlance) that declares the features of your data model. Your method would return that instead.
NSClassFromString() will do what you want. Also, initially declaring variables as type id allows you to set their explicit type later on. So:
id dataModel = [[NSClassFromString(dataModel_name) alloc] init];
To locate or create a new class:
Class arbitraryClass = NSClassFromString(dataModel_name);
if ( nil == arbitraryClass ) arbitraryClass = objc_allocateClassPair( [DataModel class] , [dataModel_name UTF8String] , 0 );
To create a new instance of an object with your newly created class:
DataModel *modelWithArbitratyClassName = [[arbitraryClass alloc] init];
Creating new classes at runtime is not usually a good idea.
So, it seems you want to dynamically add an Instance variable to an object at runtime. You don't get this for free. CALayer and CAAnimation can do something similar to this, you can read about it here
You could add similar functionality to your own objects using Key-value-coding, and more specifically the method valueForUndefinedKey. There will be some KVC specific caveats so you should really make sure you are familiar with and understand KVC. Take a look at this, it might be just want you want.
A dictionary is used to store the value and key, and to retrieve the value when you try to access it.

UISlider how to set the initial value

I'm pretty new at this iphone dev stuff and i'm working on some existing code at a company. The uislider i'm trying to set the initial value on is actually in a UITableViewCell and is a custom control. I was thinking in the cell init
cell = (QuantitiesCell *)[self loadCellWithNibName:#"QuantitiesCell" forTableView:ltableView withStyle:UITableViewCellStyleDefault];
i could just call something like
((QuantitiesCell *)cell).value = 5;
The actual QuantitiesCell class has the member value and the following functions
-(void)initCell;{
if (listOfValues == nil) {
[self initListOfValues];
}
quantitiesSLider.maximumValue = [listOfValues count]-1;
quantitiesSLider.minimumValue = 0;
quantitiesSLider.value = self.value;
}
-(void)initListOfValues;{
listOfValues = [[NSMutableArray alloc] initWithCapacity:10];
int j =0;
for (float i = minValue; i <= maxValue+increment; i=i+increment) {
[listOfValues addObject:[NSNumber numberWithFloat: i]];
if (i == value) {
quantitiesSLider.value = j;
}
j++;
}
}
like i said, i'm pretty new at this so if i need to post more of the code to show whats going to get help, let me know,
This slider always is defaulting to 1, the slider ranges usually from 1-10, and i want to set it to a specific value of the item i'm trying to edit.
Setting slider.value is the correct way if your linkage is correct (you have made the connections in Interface Builder). If you have created a UISlider in code, all you have to do is set the value property. If that is not working then be sure firstly that the object is "live" (correctly allocated, not released, not out of scope etc.) and secondly that the functions in which you set slider.value are actually being called.
If you are using Interface Builder and are not sure of how to connect your slider as an IBOutlet, you should check out iTunes University - search for "CS193P" to find some excellent videos from Stanford University. The first couple will take you through making those connections. If using IB and you have not made the connection - nothing will happen.
PS I had the same issuer - you need to add the UISlide view first then you can change the value.