ios error terminating -[__NSArrayM setRoleHistorys:]: - ios

Im trying to make user role page that get data from login. I created the own delegate function to call the webservice but app getting crash due to-[__NSArrayM setRoleHistorys:]: unrecognized selector sent to instance.
Here is my code: in .m file :
- (void)parserDidStartDocument:(NSXMLParser *)parser
{
nodeContent = [[NSMutableString alloc]init];
}
- (void)parserDidEndDocument:(NSXMLParser *)parser
{
arrayitems = [[NSMutableArray alloc] init];
U serRoleDataParser *userroleParser = [[UserRoleDataParser alloc] init];
// UserRole *currentStudent = (UserRole *) arrayitems;
NSString *Username = username.text;
NSLog(#"the String value%#",Username);
[userroleParser getUserHistoryForIndex:0 LoginId:username.text];
NSLog(#"the String user value %#",username.text);
userroleParser.delegate = self;
}
- (void) didrecieveData : (NSArray *) userHistories forIndex :(int) index
{
arrayitems = [[NSMutableArray alloc] init];
UserRole *roles = (UserRole *) arrayitems;
roles.RoleHistorys = userHistories;
datadisplay.text = roles.role;
NSLog(#"the Success data%#", datadisplay.text);
}
in delegate file .h
#interface UserRole : NSObject
#property (nonatomic,copy) NSString *username;
#property (nonatomic,copy) NSString *role;
#property (nonatomic,copy) NSString *empcode;
#property (nonatomic,copy)NSMutableArray * RoleHistorys;
#end
Dataparser.h file (delegate)
#import <Foundation/Foundation.h>
#import "UserRole.h"
#protocol UserRoleDataParserDelegate <NSObject>
- (void) didrecieveData : (NSArray *) userHistories forIndex :(int) index ;
#end
#interface UserRoleDataParser : NSObject<NSXMLParserDelegate>
{
NSMutableData *xmlData;
NSXMLParser *userroleParser;
NSMutableString *capturedString;
BOOL captureCharacters;
NSMutableArray *userHistories;
}
- (void) getUserHistoryForIndex : (int) index LoginId :(NSString*) loginId;
#property (weak,nonatomic) id <UserRoleDataParserDelegate> delegate;
#property (nonatomic) int index;
#end
am getting output in nslog but the app getting crash.

This code isn't correct:
arrayitems = [[NSMutableArray alloc] init];
UserRole *roles = (UserRole *) arrayitems;
You can't just cast an array to your custom class type (unless you have subclassed NSMutableArray and the instance is actually of the subclass type). You need to create an instance of or find the correct instance you want before you try to use it.

You create NSMutableArray and you cast it to UserRole object, after that you try to save data in that: roles.RoleHistorys :
arrayitems = [[NSMutableArray alloc] init];
UserRole *roles = (UserRole *) arrayitems;
roles.RoleHistorys = userHistories; //<- Error happened here
So you try to save data by calling selector setRoleHistorys on object of type NSMutableArray which you cannot do because NSMutableArray doesn't contain that property.

Related

Save NSMutableArray of NSStrings to disk

I have a NSMutableaArray of NSString objects. So i'm using NSKeyedArchiever to save it to disk. So when i try to use
- (void)encodeWithCoder:(NSCoder *)aCoder {
[aCoder encodeObject:self.EventsList forKey:#"Events"];
}
i got an error
Event encodeWithCoder:]: unrecognized selector sent to instance 0x7fd06b542780
Here's my parts of code:
//-------------------Events.h--------------------------
#interface Event : NSObject
#property (strong,nonatomic) NSString *nameOfEvent;
#property (strong,nonatomic) NSString *dateOfEvent;
#property (strong,nonatomic) NSString *placeOfEvent;
#property int priorityOfEvent;
#end
//---------------Singleton.h ----------------
#interface GlobalSingleton : NSObject <NSCoding, NSCopying> {
NSMutableArray *EventsList;
}
#property (nonatomic,retain) NSMutableArray *EventsList;
+(GlobalSingleton *)sharedFavoritesSingleton;
#end
//----------------Singleton.m------------------------
....
#implementation GlobalSingleton
#synthesize EventsList;
....
....
- (void)encodeWithCoder:(NSCoder *)aCoder {
NSLog (#"%#",EventsList); // not nil
[aCoder encodeObject:self.EventsList forKey:#"Events"];
}
- (id)initWithCoder:(NSCoder *)aDecoder {
if ((self = [super init])) {
NSMutableArray *temp = [[NSMutableArray alloc] initWithArray:[aDecoder decodeObjectForKey:#"Events"]];
self.EventsList = temp;
}
return self;
}
- (id)copyWithZone:(NSZone *)zone {
GlobalSingleton *copy = [[GlobalSingleton allocWithZone:zone] init];
copy.EventsList = self.EventsList;
return copy;
}
#end
I get textdata from Web-server using ASIFormDataRequest in JSON format, and then i add this object to NSMutableArray, which is also a Singleton, so it looks like this:
NSDictionary *responseDict = [responseString JSONValue];
GlobalSingleton *Singleton = [GlobalSingleton sharedFavoritesSingleton];
for (NSDictionary *str in responseDict) {
Event *newEvent = [[Event alloc] init];
newEvent.nameOfEvent = [str objectForKey:#"EventName"];
newEvent.dateOfEvent = [str objectForKey:#"EventDate"];
newEvent.placeOfEvent = [str objectForKey:#"EventPlace"];
[Singleton.EventsList addObject:newEvent];
}
//------------------Save this data stored in NSMutableArray to disk-------------------------
[NSKeyedArchiver archiveRootObject:Singleton toFile:[self save_path]];
So, again, execution stops on this:
[aCoder encodeObject:self.EventsList forKey:#"Events"];
But when i try to code single NSString object everything goes with no errors.
eventList doesn't contain NSStrings, it contains Event objects.
Your Event class needs to implement encodeWithCoder: - as the exception message says, the Event class doesn't implement this method.
Also you should use a lowercase s for singleton as it is an instance, not a class, and you should probably not use singletons.

Trouble setting an NSMutableDictionary inside of another NSMutableDictionary

I need to take information submitted by a user, store that information in an NSMutableDictionary, then store that NSMutableDictionary inside another NSMutableDictionary which is then encoded inside another class. For whatever reason, I can't seem to store the first NSMutableDictionary inside of the other.
I had to slim down the code that's in here due to work rules, so sorry if it seems to be missing anything. I only posted the parts that I'm having trouble with.
UserInfo.h:
#import <Foundation/Foundation.h>
#interface MyPlanInfo : NSObject <NSCoding>
#property (nonatomic, strong) NSMutableDictionary *emergencyDictionary;
#end
UserInfo.m:
#import <Foundation/Foundation.h>
#import "MyPlanInfo.h"
static NSString *emergencyDictionaryKey = #"emergencyDictionaryKey";
#implementation MyPlanInfo
#synthesize emergencyDictionary;
- (id) initWithCoder:(NSCoder *)coder
{
self = [super init];
self.emergencyDictionary = [coder decodeObjectForKey:emergencyDictionaryKey];
return self;
}
- (void)encodeWithCoder:(NSCoder *)coder
{
[coder encodeObject:self.emergencyDictionary forKey:emergencyDictionaryKey];
}
#end
infoView.h
#import <UIKit/UIKit.h>
#import "MyPlanInfo.h"
#interface infoView : UIViewController <NSCoding>
{
NSMutableDictionary *emergencyContactInfo;
NSArray *userInfo;
NSArray *userKeys;
NSMutableArray *tempArray;
}
#property (nonatomic, strong) MyPlanInfo *myPlanInfoObject;
-(void)saveUserInfo;
-(void)loadUserInfo;
#end
infoView.m:
#import "infoView.h"
#interface infoView ()
#end
#implementation infoView
static NSString *userInfoKey = #"userInfoKey";
static NSString *userName;
-(void)viewDidLoad
{
[super viewDidLoad];
if(!self.myPlanInfoObject)
{
self.myPlanInfoObject = [[MyPlanInfo alloc] init];
}
[self loadUserInfo];
}
-(void)addToDictionary
{
emergencyContactInfo = [NSMutableDictionary dictionaryWithObjects:userInfo forKeys:userKeys];
if([userInfo count] != 0 || userInfo == nil)
{
self.myPlanInfoObject.emergencyDictionary = [NSMutableDictionary dictionaryWithObject:emergencyContactInfo forKey:userName];
}
[self saveUserInfo];
}
- (void)saveUserInfo
{
NSData *userInfoData = [NSKeyedArchiver archivedDataWithRootObject:self.myPlanInfoObject];
[[NSUserDefaults standardUserDefaults] setObject:userInfoData forKey:userInfoKey];
}
- (void)loadUserInfo
{
NSData *userInfoData = [[NSUserDefaults standardUserDefaults] objectForKey:userInfoKey];
if(userInfoData)
{
self.myPlanInfoObject = [NSKeyedUnarchiver unarchiveObjectWithData:userInfoData];
}
}
#end
In infoView.m, in the addToDictionary method, userInfo is an array of user inputted information, and userKey's is an array of key's. The emergencyContactInfo NSMutableDictionary works just fine, everything is in it, but when I try to set that as an object in a new NSMutableDictionary, for a key, it doesn't work. Everything is nil.
Anyone have any ideas on how what I'm doing wrong?
Edit: If you down vote, please leave a reason as to why so that I can avoid doing whatever I did wrong in the future.
In the following line you’re creating an instance of MyPlanInfo using plain alloc/init:
self.myPlanInfoObject = [[MyPlanInfo alloc] init];
However, at least in the code provided, you haven’t overridden init in MyPlanInfo, but instead, initWithCoder::
- (id) initWithCoder:(NSCoder *)coder
{
self = [super init];
self.emergencyDictionary = [coder decodeObjectForKey:emergencyDictionaryKey];
return self;
}
When you use just plain init, the MyPlanInfo’s emergencyDictionary instance variable will be nil. You should likely add something like the following to MyPlanInfo to override init:
- (id) init
{
if ((self = [super init])) {
emergencyDictionary = [[NSMutableDictionary alloc] init];
}
return self;
}
That will assure that the newly created MyPlanInfo instance has a proper NSMutableDictionary that can be manipulated from other classes.

How to create an array outside of a function, and be able to add to it in other functions

It seems if I do something like:
NSMutableArray *randomSelection = [[NSMutableArray alloc] init];
Then this needs to be in a function, and I can't modify it later using a different function.
I tried just instantiating it in the .h file,
#interface ViewController:
{
NSMutableArray *Values;
}
But then when I try to append to it during runtime, nothing happens. I try to append to it with this:
int intRSSI = [RSSI intValue];
NSString* myRSSI = [#(intRSSI) stringValue];
[Values addObject:myRSSI];
But the array remains empty when I do this.
How can I fix this?
The recommended way is to create a property;
// ViewController.h
#interface ViewController : UIViewController
{
}
#property (nonatomic, strong) NSMutableArray *values;
#end
Then override the getter for that property, to lazy-initialize it, i.e. the array will be allocated and initialized on first call of the NSMutableArray property's getter:
// ViewController.m
#interface ViewController ()
#end
#implementation ViewController
- (NSMutableArray *)values
{
if (!_values) {
_values = [[NSMutableArray alloc] init];
}
return _values;
}
- (void)viewDidLoad
{
[super viewDidLoad];
//int intRSSI = [RSSI intValue];
//NSString *myRSSI = [#(intRSSI) stringValue];
//[self.values addObject:myRSSI];
// Keep it simple:
[self.values addObject:RSSI];
}
#end

iOS: Object returning *nil description* after alloc and init

Let me preface this question by saying that I believe it to be a memory management mistake on my end. I just can't seem to figure out why it is happening.
I have a viewcontroller and a model class named Part.
#import <Foundation/Foundation.h>
#interface Part : NSObject
#property (nonatomic, strong) NSString *name;
#property (nonatomic, strong) NSString *partType;
#property (nonatomic, strong) NSString *description;
#property (nonatomic, strong) NSNumber *price;
- (id)initWithName:(NSString *)name AndType:(NSString *)type;
#end
In the view controller I have a property set as follows:
#property (nonatomic, strong) Part *part;
In the init function of ViewController I create some static arrays and create objects out of them:
- (id)init {
self = [super init];
self.partList = [[NSMutableArray alloc] init];
NSArray *inputArray = #[#"Part1",
#"Part2",
#"Part3",
#"Part4",
#"Part5",
#"Part6",
#"Part7",
#"Part8"];
NSString *tempType = #"PartCategory";
// Add dummy static data
for (int i = 0; i < [inputArray count]; i++) {
Part *partInput = [[Part alloc] initWithName:[inputArray objectAtIndex:i] AndType:tempType];
//partInput.name = [inputArray objectAtIndex:i];
//partInput.partType = tempType;
NSLog(#"Inserting Part %#", partInput);
[self.partList addObject:partInput];
}
return self;
}
The NSLog I call in that loop returns Inserting Part *nil description* for every part. I just can't track down what is happening here.
EDIT: Here is the initWithName method from Part that the controller uses:
- (id)initWithName:(NSString *)name AndType:(NSString *)type {
if(self = [super init]) {
self.name = name;
self.partType = type;
}
return self;
}
When using %# to print NSObject, it calls debugDescription that by default calling the description method of that object and your Part object always have nil description.
You better solve this by changing the description property name to something else, because it conflicts with the description method of NSObject.
See also: NSObject description and debugDescription

Can't add entry to NSMutableDictionary in singleton

I have a singleton with an NSMutableDictionary in it. I want to add an entry to that dictionary from one of my views. For a reason that I can't comprehend it's not working and I'm receiving the 'NSDictionary setObject:forKey: unrecognized selector sent to instance' error. This doesn't seem like it should be so hard but I can't find an answer to the problem.
So I've wired up a button in my .xib to call the createKey method and kablooey. I've also tested to ensure that the dictionary exists and it does.
Here's my singleton header:
#import <Foundation/Foundation.h>
#interface SharedAppData : NSObject <NSCoding>
{
NSMutableDictionary *apiKeyDictionary;
}
+ (SharedAppData *)sharedStore;
#property (nonatomic, copy) NSMutableDictionary *apiKeyDictionary;
-(BOOL)saveChanges;
#end
My singleton implementation (important bits)
#interface SharedAppData()
#end
#implementation SharedAppData
#synthesize apiKeyDictionary;
static SharedAppData *sharedStore = nil;
+(SharedAppData*)sharedStore {
#synchronized(self){
if(sharedStore == nil){
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *testFile = [documentsDirectory stringByAppendingPathComponent:#"testfile.sav"];
Boolean fileExists = [[NSFileManager defaultManager] fileExistsAtPath:testFile];
if(fileExists) {
sharedStore = [NSKeyedUnarchiver unarchiveObjectWithFile:testFile];
}
else{
sharedStore = [[super allocWithZone:NULL] init];
}
[sharedStore setSaveFile:testFile];
}
return sharedStore;
}
}
- (id)init {
if (self = [super init]) {
apiKeyDictionary = [[NSMutableDictionary alloc] init];
}
return self;
}
In my view controller header...
#import <UIKit/UIKit.h>
#import "SharedAppData.h"
#interface AddKeyViewController : UIViewController <UITextFieldDelegate>
{
UIButton *addKey;
}
#property (weak, nonatomic) IBOutlet UITextField *apiName;
#property (weak, nonatomic) IBOutlet UITextField *apiKey;
-(IBAction)createKey:(id)sender;
#end
View controller implementation:
#import "AddKeyViewController.h"
#import "SharedAppData.h"
#interface AddKeyViewController ()
#end
#implementation AddKeyViewController
#synthesize apiName, apiKey, toolbar;
-(IBAction)createKey:(id)sender {
NSString *name = [apiName text];
NSString *key = [apiKey text];
[[[SharedAppData sharedStore] apiKeyDictionary] setObject:key forKey:name];
}
#end
Your apiKeyDictionary property is set to copy. That will send the copy message to the NSMutableDictionary instance you create in your init method - returning not an NSMutableDictionary but an NSDictionary. Change it to strong or retain instead.
I suspect that the problem is with your property being "copy" rather than "strong"; when you set it, mutanle dictionsry gets copied into an immutable one.
Try changing your property to "strong".

Resources