Is [NSMutableString string] same as [[NSMutableString string] autorelease]? - objective-c

I noticed a piece of code somewhere it does
NSMutableString *myString = [[NSMutableString string] autorelease];
Is it overkill? Shouldn't it be the same as [NSMutableString string]?

NSMutableString *myString = [[NSMutableString string] autorelease];
will lead to a crash if they aren't calling retain on it elsewhere.
[NSMutableString string]
is the same as
[[[NSMutableString alloc] init] autorelease]

Doesn't look right to me. Are you sure that the example you saw is actually doing this?
[NSMutableString string] is equivalent to
[[[NSMutableString alloc] init] autorelease]
So with the example you provided, you would get
[[[[NSMutableString alloc] init] autorelease] autorelease]
which would result in an over release and an exc_bad_access error.

Related

What are the differences between [[NSMutableArray alloc] init] and [#[] mutableCopy]?

NSMutableArray *myArray = [[NSMutableArray alloc] init];
vs
NSMutableArray *myArray = [#[] mutableCopy]
What are the differences between declaring arrays in these two separate ways?
Think of the 2nd line as:
NSMutableArray *myArray = [[[NSArray alloc] init] mutableCopy];
So the clear difference is the 1st way is more efficient and the 2nd way needlessly creates an extra object that is promptly discarded.

memory menagement in ios

Can anybody explain me why does the case1 and case2 crashes while the others does not in case of non-ARC?
Case1:
NSString *rr = [[NSString alloc] initWithString:#"AB"];
[rr release];
[rr autorelease];
Case2:
NSString *rrr = [[NSString alloc] initWithString:#"AB"];
[rrr autorelease];
[rrr release];
Case3:
NSMutableString *rr1 = [[NSMutableString alloc] initWithString:#"AB"];
[rr1 release];
[rr1 autorelease];
Case4:
NSMutableString *rrr1 = [[NSMutableString alloc] initWithString:#"AB"];
[rrr1 autorelease];
[rrr1 release];
Case5:
NSArray *rr3 = [[NSArray alloc] initWithObjects:#"jj", nil];
[rr3 release];
[rr3 autorelease];
Case6:
NSArray *rrr3 = [[NSArray alloc] initWithObjects:#"jj", nil];
[rrr3 autorelease];
[rrr3 release];
Case7:
NSMutableArray *rr2 = [[NSMutableArray alloc] initWithObjects:#"jj", nil];
[rr2 release];
[rr2 autorelease];
Case8:
NSMutableArray *rr2 = [[NSMutableArray alloc] initWithObjects:#"jj", nil];
[rr2 autorelease];
[rr2 release];
All are are incorrect because eventually all will be released twice, but some may coincidentally not crash.
The alloc allocates the object with a retain count of 1. release decreases the retain count 1. autorelease eventually decreases the retain count 1. That means that all are over released.
But as #Chuck mentions some instances are constants, are created at compile time and never released so release and autorelease can be called to many tines with no crash.
String constants are one instance of this this where over-releasing will not cause a crash:
NSString *s = #"aa";
Even over-releasing this is OK because the compiler is smart enough:
NSString *s = [NSString stringWithString:#"aa"];
But you will get a warning from the current LLVM compiler that using stringWithString with a literal is redundant.

Force release an autorelease object

Can I force an Autorelase object by calling a release without autorelease pool like that:
NSString *myString = [[[NSString alloc] init] autorelease];
[myString release];
Normally it's like that:
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
NSString *myString = [[[NSString alloc] init] autorelease];
[pool release];
The first sample will crash, since the string will get over-released. If you want to have control over the lifetime of your autoreleased objects, the correct approach is what your second sample does – create a local autorelease pool that you can drain when you want.
Your code will crash because global auto release pool will try to release the object later. Results in malloc double free error
You can do this:
NSString *myString = [[[NSString alloc] init] autorelease];
Or this:
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
NSString *myString = [[[NSString alloc] init] autorelease];
[pool release];
But not this:
NSString *myString = [[[NSString alloc] init] autorelease];
[myString release];

Objective C How to fill rangeOfString of a NSArray?

I wonder if it is possible to fill rangeOfString objects of a NSArray. Because I have a long list of objects for after rangeOfString:
NSArray biglist´s count is higher than list´s count.
I want to filter away the objects from the small list of the main list.
Please tell me if this is not clear.
My codes below:
NSArray *biglist = [[NSArray alloc] initWithArray:
[[NSString stringWithContentsOfFile:[[NSBundle mainBundle] pathForResource:#"mainlist" ofType:#"txt"]
encoding:NSUTF8StringEncoding error:NULL] componentsSeparatedByString:#"\n"]];
NSArray *list = [[NSArray alloc] initWithArray:
[[NSString stringWithContentsOfFile:[[NSBundle mainBundle] pathForResource:#"smalllist" ofType:#"txt"]
encoding:NSUTF8StringEncoding error:NULL] componentsSeparatedByString:#"\n"]];
for (NSString *listword in list);
NSMutableArray *wordlist = [[NSMutableArray alloc] init];
NSMutableArray *worindex = [[NSMutableArray alloc] init];
NSMutableIndexSet *mindexes = [[NSMutableIndexSet alloc] init];
NSMutableDictionary *mutdic = [[NSMutableDictionary alloc] init];
NSMutableArray *mutarray = [[NSMutableArray alloc] init];
for (NSString *s in mainlist)
{
NSRange ran = [s rangeOfString:listword];
if (ran.location !=NSNotFound)
{
//my codes here
}
}
EDIT:
I think I can solve this by writing
int i;
for (i = 0; i<[list count]; i++)
{
NSString *same = [list objectAtIndex:i];
NSLog (#"listword: %#", same);
}
But I am not sure where to place it, inside the for loop s in mainlist or outside.
EDIT: This for loop works inside the main for loop.
EDIT:
Tried these codes, but it doesnt work somehow..
NSArray *list = [[NSArray alloc] initWithArray:
[[NSString stringWithContentsOfFile:[[NSBundle mainBundle] pathForResource:#"small" ofType:#"txt"]
encoding:NSUTF8StringEncoding error:NULL] componentsSeparatedByString:#"\n"]];
NSArray *mainlist = [[NSArray alloc] initWithArray:
[[NSString stringWithContentsOfFile:[[NSBundle mainBundle] pathForResource:#"mainlist" ofType:#"txt"]
encoding:NSUTF8StringEncoding error:NULL] componentsSeparatedByString:#"\n"]];
NSMutableArray *large = [NSMutableArray arrayWithArray:mainlist];
NSArray *newlarge;
for (NSString *listword in list)
{
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"(SELF beginswith[c] %#)",listword];
newlarge = [large filteredArrayUsingPredicate:predicate];
}
NSLog (#"large: %#", newlarge);
NSLog (#"finished!");
"I want to filter away the objects from the small list of the main list."
If I understand correctly, you want to remove an array of items from another array. You don't want to do that much work and allocations inside an n^2 loop.
This removes an array of items from another array. Depending on how large your array is you may need to optimize further but this works:
NSArray *small = [NSArray arrayWithObjects:#"three", #"two", nil];
NSMutableArray *large = [NSMutableArray arrayWithObjects:#"one", #"two", #"three", #"four", nil];
[large removeObjectsInArray:small];
// print
for (NSString *current in large)
{
NSLog(#"item: %#", current);
}
This outputs:
2011-10-13 08:39:21.176 Craplet[5235:707] item: one
2011-10-13 08:39:21.178 Craplet[5235:707] item: four
I figured it out by myself and solved this :)
It works almost perfectly.
My codes:
NSArray *big = [[NSArray alloc] initWithObjects:#"hello ->mache", #"heisann hoppsann ->hiya", #"nei men ->da", #"however ->what", #"may ->april", #"mai ->maj", nil];
NSArray *small = [[NSArray alloc] initWithObjects: #"heisann ", #"nei men ", #"however ", #"mai", nil];
NSMutableArray *smallwithh = [[NSMutableArray alloc] init];
NSMutableIndexSet *mindexes = [[NSMutableIndexSet alloc] init];
for (NSString *same in small)
{
NSLog (#"listword: %#", same);
for (NSString *s in big)
{
NSRange ran = [s rangeOfString:same];
if (ran.location !=NSNotFound)
{
[smallwithh addObject:s];
NSUInteger ind = [big indexOfObject:s];
[mindexes addIndex:ind];
}
}
}
NSLog (#"smallwith: %#", smallwithh);
[smallwithh release];
NSMutableArray *newWords =[NSMutableArray arrayWithArray: big];
[newWords removeObjectsAtIndexes: mindexes];
[big release];
[small release];
NSLog (#"newWords: %#", newWords);

NSString Memory Warning in objective c

NSString* strSubject = [[NSString alloc] initWithData: temp encoding:
NSISO2022JPStringEncoding];
i got a memory message "Potential leak of an object allocated" on above line.
Is there any alternate way to write same.
You will get that sort of message unless you either release it or put it in the autorelease pool.
This can be done by:
NSString* str = [[NSString alloc] initWithData: blah blah blah ... ];
[str release];
to do it immediately. You can also use:
NSString* str = [[NSString alloc] initWithData: blah blah blah ... ];
[str autorelease];
to have it released at some point in the future.
You need to do [strSubject release] later, or [strSubject autorelease] either later or immediately. I'd use this:
NSString* strSubject = [[[NSString alloc] initWithData:temp encoding:NSISO2022JPStringEncoding] autorelease];
Sadly there isn't a NSString factory method stringWithData:, but that's equivalent.
In fact any [NSString stringWithBlah:xx] method is more or less equivalent to [[[NSString alloc] initWithBlah:xx] autorelease]