After init have EXC_BAD_ACCESS to NSString - ios

I create a designer initializer with incoming arguments NSString *
In my class, i have property NSString* title.
#property (nonatomic) NSString *title;
...
- (instancetype)initWithTitle:(NSString*)title albumCover:(UIImage *)img {
self = [super init];
if (self) {
self.title = [[NSString alloc] initWithFormat:#"%#",title];
self.img = img;
}
return self;
}
with variable self.img everything good, but with self.title I have problems. If I want to log self.title I get error: Execution was interrupted, reason: EXC_BAD_ACCESS (code=2, address=0x16fcbbff0).
The process has been returned to the state before expression evaluation.
I tried to init before assigning, tried to with NSMutableString. Always the same thing. What I'm doing wrong?

The assignment isn't your problem. The problem is elsewhere. While the property declaration and initialization do not follow the recommended pattern, they aren't going to cause a crash in the code you've shown.
The following runs fine, for example. You should declare your #property as copy and assign to the instance variable directly (doing so avoids any issues that might spring up if you later implement a custom setter with business logic that requires a fully initialized object).
#interface Fo:NSObject
#property (nonatomic) NSString *wrongWay;
#property (nonatomic, copy) NSString *rightWay;
#end
#implementation Fo
- (instancetype)initWithTitle:(NSString*)title
{
self = [super init];
if (self) {
self.wrongWay = [[NSString alloc] initWithFormat:#"%#",title];
_rightWay = [title copy];
}
return self;
}
#end
int main(int argc, const char * argv[]) {
#autoreleasepool {
Fo *f = [[Fo alloc] initWithTitle:#"Fo"];
NSLog(#"%# %# %#", f, f.wrongWay, f.rightWay);
}
return 0;
}

Related

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 error terminating -[__NSArrayM setRoleHistorys:]:

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.

Unable to add object to nsmutable array in singleton

The same code works on iOS 5 but not in iOS 6. That is the count shows as being 0. Any ideas?
It should say atleast 1 as the count since I have verified house.png to be a valid image.
Here is my code:
MyManager * myManager = [MyManager sharedInstance];
NSString *pathOfImageFile = [[NSBundle mainBundle] pathForResource:#"house" ofType:#"png"];
UIImage *myImage = [UIImage imageWithContentsOfFile:pathOfImageFile];
UIImageView * tempImageView = [[UIImageView alloc] initWithImage:myImage];
[myManager.assets addObject:tempImageView];
NSLog(#"image count: %d", [myManager.assets count]);
Here is my singleton:
#import <Foundation/Foundation.h>
#import <MapKit/MapKit.h>
#interface MyManager : NSObject
{
MyManager *_sharedObject;
NSMutableArray * assets;
}
//Property Listing
#property(nonatomic,copy) NSString * postTitle;
#property(nonatomic,copy) NSString * postText;
#property(nonatomic,copy) NSString * postLink;
#property(nonatomic,copy) NSString * postCategory;
//assets
#property (nonatomic, strong) NSMutableArray * assets;
+ (id)sharedInstance;
- (void)reset;
#end
#import "MyManager.h"
#implementation MyManager
//Property Listing
#synthesize postTitle=_postTitle;
#synthesize postText=_postText;
#synthesize postLink=_postLink;
#synthesize postCategory=_postCategory;
#synthesize assets=_assets;
- (id)init
{
self = [super init];
if ( self )
{
assets = [[NSMutableArray alloc] init];
NSLog(#"Singleton Initialized...");
}
return self;
}
+ (id)sharedInstance
{
static dispatch_once_t pred = 0;
__strong static id _sharedObject = nil;
dispatch_once(&pred, ^{
_sharedObject = [[self alloc] init]; // or some other init method
});
return _sharedObject;
}
- (void)reset
{
self.postTitle =#"";
self.postText=#"";
self.postLink=#"";
self.postCategory=#"";
[self.assets removeAllObjects];
}
#end
You have extra ivars related to your assets property.
You define a property named assets. You then (needlessly) synthesize the property specifying that the generated ivar should be named _assets.
You also (needlessly) declare an explicit ivar named assets.
In your init method you assign the array to the assets ivar. In your reset method you clear the assets property (using the _assets ivar).
Get rid of the explicit assets ivar. Get rid of the #synthesize statement. This will leave you with an auto generated ivar of _assets.
Update your code to use either the property or the _assets ivar.
Try:
_assets = [[NSMutableArray alloc] init];
And you are defining sharedObject in your interface as a property: MyManager *_sharedObject;
You don't want that if you'll always grab your instance via [MyManager sharedInstance]; which is holding the initialized instance in that local static var.

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

Resources