I have declared NSString with some string value in ViewdidLoad like..
int i=1;
strval=[NSString stringWithFormat:#"%03d",i];
strval=[NSString stringWithFormat:#"S%#",strval];
NSLog(#"Value %#",strval);
it gives correct result as S001, but when i print this same in IBAction like,
- (IBAction)stringvalue:(id)sender {
NSLog(#"Value %#",strval);
}
it gives unknown values each time.Sometimes it throws EXEC_BAD_ACCESS error.
Please help me..
Try something like this
in .h
#property (nonatomic, strong) NSString *strval;
in .m
#synthesize strval = _strval
- (void)viewDidLoad
{
int i = 4;
// ARC
_strval = [NSString stringWithFormat:#"hello %d", i];
// None ARC
// strcal = [[NSString alloc] initwithFormat:#"hello %d",i];
NSLog(#"%#", _strval);
// Prints "hello 4" in console (TESTED)
}
- (IBAction)buttonPress:(id)sender
{
NSLog(#"%#", _strval);
// Prints "hello 4" in console (TESTED)
}
using ARC. This has been tested and works the way the question has been asked.
Looks like you aren't using ARC, so the string is being released the next time the autorelease pool drains. You need to explicitly retain it in viewDidLoad and explicitly release it in your overwridden dealloc method:
- (void)viewDidLoad
{
...
strval = [[NSString stringWithFormat:#"%03d", i] retain];
....
}
- (void)dealloc
{
[strval release];
...
[super dealloc];
}
(I am assuming you've actually declared strval as an instance method).
in .h
#property (nonatomic, strong) NSString *strval;
in .m
#synthesize strval = _strval
- (void)viewDidLoad
{
...
self.strval = [NSString stringWithFormat:#"%03d", i];
....
}
- (void)dealloc
{
self.strval = nil;
...
[super dealloc];
}
This one works either, with ARC and without.
Just one addition: With ARC the statement [super dealloc]; must be omitted.
Related
I have this code:
// .m
- (void)viewDidLoad {
NSMutableArray *array = [[NSMutableArray alloc] init];
[self addToArray];
}
- (void)addToArray {
NSString *stringA;
[stringA isEqualToString:#"door"];
NSString *stringB;
[stringB isEqualToString:textField.text];
[array addObject:stringA];
if ([stringA isEqual:stringB]) {
[stringA isEqual:nil];
[tableView reloadData];
} else {
[array addObject:stringB];
[tableView reloadData];
}
}
When I call the method addToArray it keeps returning me an error called Thread 1: Program recived signal "EXC_BAD_ACCESS", and the debugger output says : Single stepping until exit from function objc_msgSend, which has no line number information. at the line [self addToArray]. Any idea of how to solve it? I have wasted to much time with it, please help me!
As was said by others, array should be an instance variable or property of the class, declared in the .h file:
#property (strong) NSMutableArray *array;
Or, without ARC:
#property (retain) NSMutableArray *array;
Now you #synthesize array; in your implementation file and can access it from anywhere. Then you can do:
- (void) viewDidLoad
{
self.array = [[NSMutableArray alloc] init];
[self addToArray];
}
You seem to assume that isEqualToString does an assignment. It doesn't, it checks strings for (textual) equality. Try this:
- (void) addToArray
{
NSString *stringA = #"door";
NSString *stringB = textField.text;
[array addObject: stringA];
if (![stringA isEqualToString: stringB])
[array addObject: stringB];
[tableView reloadData];
}
These two variables are uninitialized and will cause you big problems:
NSString *stringA;
[stringA isEqualToString:#"door"];
NSString *stringB;
[stringB isEqualToString:textField.text];
You have not assigned anything to either stringA or stringB. Besides the result of your call to isEqualToString is never used.
Two things I can notice in your code:
1) Make array a class variable, so you can access it from your -[addToArray] method. Better do this in your .h file, for example:
#interface MyViewController : UIViewController {
#private
// ...skipped...
NSMutableArray * array;
// ...rest of class skipped...
}
#end
Then, in your .m file the method should look like this:
// .m
- (void)viewDidLoad {
array = [[NSMutableArray alloc] init];
[self addToArray];
}
And don't forget to release the array:
- (void)dealloc {
[array release];
[super dealloc];
}
2) Do not mess up -[NSString isEqualToString:] method with simple assigment to a variable. So in your -[addToArray] method, for example, replace this:
NSString *stringA;
[stringA isEqualToString:#"door"];
with this:
NSString *stringA = #"door";
And this:
NSString *stringB;
[stringB isEqualToString:textField.text];
with this:
NSString *stringB = textField.text;
3) Check the logic of -[addToArray] method - it is not very clear what are you going achieve.
Objective-C is really wierd, i can't get the hang of it...
I have a NSstring that is losing it's value if I try to reassign it...
Here's how I use it..
Can anyone tell me what am I doing wrong? it's happening at the assigning of the new value..
#interface PageViewController : UIViewController {
NSString *mystring;
}
- (void)viewDidLoad {
mystring=[ [NSString alloc] initWithString:#""];
}
-(void) function_definition:(NSString *) param {
.............
mystring=param;
.........
}
Most commonly, you would want to designate this as a property:
#interface PageViewController : UIViewController {
NSString *mystring;
}
#property (nonatomic, retain) NSString *mystring;
Then in your implementation,
#synthesize mystring;
- (void)dealloc {
[mystring release];
[super dealloc];
}
And finally, anywhere in your implementation, set the value of mystring by using either:
[self setMystring:#"something"];
or
self.mystring = #"somethingelse";
If you're allocating a new string, be sure to release it. It's retained automatically using the property.
self.mystring = [[[NSString alloc] initWithString:#"hello"] autorelease];
Lastly, in your function:
-(void) function_definition:(NSString *) param {
.............
self.mystring = param;
.........
}
It's not completely clear what you mean by 'losing its value', but I think the problem here is one of memory management- you need to do some reading of how Cocoa handles this, but in this case you'll need to do:
-(void) function_definition:(NSString *) param {
.............
if (mystring != param) {
[mystring release];
mystring = [param retain];
}
.........
}
This is really twisting my mind… I'm trying to access an NSMutableArray in an IBAction which I defined in viewDidLoad. Unfortunately I keep getting a EXC_BAD_ACCESS.
I'm new to all this so I'd really appreciate some insight in what I'm doing wrong.
Below find the corresponding code excerpts.
CounterViewController.h:
#interface CounterViewController : UIViewController{
NSMutableArray *countHistoryArray;
}
#property(nonatomic, retain) NSMutableArray *countHistoryArray;
CounterViewController.m:
#implementation CounterViewController
#synthesize countHistoryArray;
- (void)viewDidLoad {
[super viewDidLoad];
//Fill array with some dummy data
self.countHistoryArray = [[NSMutableArray alloc] init];
NSDate *now = [[[NSDate alloc] init] autorelease];
CurrentCount *historicCount = [[[CurrentCount alloc]
initWithCount:[NSNumber numberWithInteger:22]
description:#"Testcount"
dateAndTime:now] autorelease];
[self.countHistoryArray addObject: historicCount];
//Do some logging - everything is working fine here!
NSLog(#"%#", [self.countHistoryArray description]);
}
//Later on we click on a button and want to use the array
- (IBAction)doSomeStuff {
//Let's look at the array again - and now it crashes with EXC_BAD_ACCESS
NSLog(#"%#", [self.countHistoryArray description]);
}
Thanks a lot!
Manuel
EDIT Additional code as asked for by #jamapag
CurrentCount.h
#import <Foundation/Foundation.h>
#interface CurrentCount : NSObject {
NSNumber *counterLevel;
NSString *description;
NSDate *dateAndTime;
}
- (id)initWithCount:(NSNumber *)newCounterLevel description:(NSString *)newDescription dateAndTime:(NSDate *)newDateAndTime;
#property(nonatomic, copy) NSNumber *counterLevel;
#property(nonatomic, copy) NSString *description;
#property(nonatomic, copy) NSDate *dateAndTime;
#end
CurrentCount.m
#import "CurrentCount.h"
#implementation CurrentCount
#synthesize counterLevel;
#synthesize description;
#synthesize dateAndTime;
- (id)initWithCount:(NSNumber *)newCounterLevel description:(NSString *)newDescription dateAndTime:(NSDate *)newDateAndTime{
self = [super init];
if(nil != self){
self.counterLevel = newCounterLevel;
self.description = newDescription;
self.dateAndTime = newDateAndTime;
}
return self;
}
-(void) dealloc{
self.counterLevel = nil;
self.description = nil;
self.dateAndTime = nil;
[super dealloc];
}
#end
Are you sure that your code actually looks like this?
- (IBAction)doSomeStuff {
//Let's look at the array again - and now it crashes with EXC_BAD_ACCESS
NSLog(#"%#", [self.countHistoryArray description]);
}
Your question title says "NSMutableArray count causes EXC_BAD_ACCESS" - if that line of code actually says NSLog(#"%#", [self.countHistoryArray count]);, you'll almost certainly get a crash, since NSLog will attempt to treat a primitive type (the type returned by -[NSArray count]) as an object. In order to use -[NSArray count] in NSLog, use %u instead of %#:
- (IBAction)doSomeStuff {
// This time it should work!
NSLog(#"Array Count = %u", [self.countHistoryArray count]);
}
Remove autorelease from:
currentCount *historicCount = [[[CurrentCount alloc]
initWithCount:[NSNumber numberWithInteger:22]
description:#"Testcount"
dateAndTime:now] autorelease];
It looks like you are accidentally releasing countHistoryArray somewhere. Try removing all calls to it except for those two you showed. Additionally you can try enabling zombies to debug the problem.
Oh and by the way you probably don't really want a public NSMutableArray property and if you do you probably want it to be copy, not retain. Otherwise incapsulation kinda goes down the drain.
I know this question has already been solved and accepted but its for others who are or will face this issue.
I was facing the same issue, I tried all solutions but no solution worked for me. The project I am working on is NON-ARC.
I tried and made a simple change in property
Previously my property for NSMUTABLEARRAY was
#property (nonatomic, assign) NSMutableArray * dataArray;
I changed it to:
#property (nonatomic, retain) NSMutableArray * dataArray;
Changed it from ASSIGN to RETAIN
And it solved my problem
I am getting errors when trying to add items to a NSMutableArray which is encapsulated within an object.
Code follows:
#import <Foundation/Foundation.h>
#interface TestObject : NSObject {
NSMutableArray *myArray;
}
#property (nonatomic, retain) NSMutableArray *myArray;
#end
#import "TestObject.h"
#implementation TestObject
#synthesize myArray;
- (id) init {
if(self= [super init]){
// Initialise the Mutable Array
myArray = [[NSMutableArray alloc] init];
}
return self;
}
- (void) dealloc {
[super dealloc];
[myArray release];
}
#end
Calling:
TestObject *testObject = [[TestObject alloc] init];
NSString *someString = #"blah blah blah";
NSLog(#"%#", someString);
[testObject.myArray addObject:someString];
NSLog(#"Test Object Array Count: %#", [testObject.myArray count]);
[testObject release];
Can anyone tell me why this throws an error when calling count?
I have also tried the copy the Mutable Array to a local variable and get the same result when calling count on the local variable.
Warning warning warning!!!
[super dealloc] is the last thing you should do in your -dealloc method, not the first!
It's a good thing it just showed a warning, when I have done the same it has crashed.
The reason is that %# is an object placeholder. But the count method returns NSInteger which is a primitive datatype and the placeholder for it is %d, as you have correctly noted in the comment.
I hope to add objects to a NSMutableArray "myArray", The NSMutableArray is the array for FileObj which has a NSString property "fileName"
#import <UIKit/UIKit.h>
#interface FileObj : NSObject {
NSString *fileName;
}
-(void) setfileName:(NSString *)s ;
-(NSString *) getfileName ;
#end
//
// File.m//
#import "File.h"
#implementation FileObj
-(void) setfileName:(NSString *)s ;
{
fileName=s;
}
-(NSString *) getfileName ;
{
return fileName;
}
#end
I initialize the myArray here:
NSMutableArray *temarray;
temarray=[[NSMutableArray alloc] init];
self.myArray=temarray;
[temarray release];
the codes to add object to myArray
FileObj *newobj=[[FileObj alloc]init ];
NSString *fieldValue2 = [[NSString alloc] initWithUTF8String:#"aaaa"];
[newobj setfileName:fieldValue2];
[myArray addObject:newobj];
[fieldValue2 release]; //**if I enabled the line, it will cause crash**
//**if I disable the line, it will cause memory leak**
[newobj release];
Welcome any comment
Thanks
interdev
First you should look into ObjC naming conventions. There is no -get methods in ObjC. It's also a good idea to prefix your classes with your own 2 letters (like NS).
Your setter value assignment is invalid and the NSString initialization unnecessary.
I would strongly recommend introductory material to you!
#interface MYFileObject : NSObject {
NSString *_fileName;
}
- (void)setFileName:(NSString *)theString;
- (NSString *)fileName;
#end
and the implementation
#implementation MYFileObject
- (void)setFileName:(NSString *)theString {
[_fileName release];
_fileName = [theString copy];
}
- (NSString *)fileName {
return [[_fileName copy] autorelease];
}
- (void)dealloc {
[_fileName release];
[super dealloc];
}
#end
You would add an object like this...
NSMutableArray *myAry = [[NSMutableArray alloc] init];
MYFileObject *obj = [[MYFileObject alloc] init];
[obj setFileName:#"thefilename.txt"];
[myAry addObject:obj];
[obj release];
I would recommend using properties instead of defining your own getters/setters.
You could also use the NSMutableArrays' designated initializers for fast array creation.
Look here for how to use properties: http://developer.apple.com/mac/library/documentation/cocoa/Conceptual/ObjectiveC/Articles/ocProperties.html
Why bother with getters and setters? Use declared property already!
#interface FileObj : NSObject {
NSString *fileName;
}
#property(retain,nonatomic) NSString* fileName; // <---
#end
...
#implementation FileObj
#synthesize fileName; /// <---
-(void)dealloc {
[fileName release]; // Remember to release the object on dealloc.
[super dealloc];
}
#end
...
FileObj *newobj=[[FileObj alloc] init];
NSString *fieldValue2 = [[NSString alloc] initWithUTF8String:#"aaaa"];
newobj.fileName = fieldValue2; /// <----
[myArray addObject:newobj];
[fieldValue2 release];
[newobj release];
The crash occurs because the NSString instance is not retained anymore.
A common pattern is to retain NSString properties, either declaratively with #property or by hand.
You should modify the setter like this:
-(void) setfileName:(NSString *)s ;
{
[s retain]; // <- Retain new value
[filename release]; // <- Release old value
fileName=s;
}