autoreleasepool for nested methods - ios

Say I have following code:
- (void) abc
{
#autoreleasepool
{
NSString *str = [NSString stringWithFormat:#"ABC %d", 12];
[self pqr];
}
}
- (void) pqr
{
NSString *str2 = [NSString stringWithFormat:#"PQR %d", 14];
}
For the above code, after the execution of method abc, will only str be released or str2 will also be released?

Both. If you are not sure, create your custom class and override dealloc implementation and add there some log message to not only believe me but experienced it on your own.

Related

Recursive method Objective-C

I'm checking is first letter of string is 0, if it is remove it and call again method to check is there is still 0. I've debugged this and it seems like when it accomplish number without 0, it goes backwards. Code:
-(NSString *)deleteZerosOnFirst:(NSString *)card
{
NSString *firstLetter = [card substringToIndex:1];
if ([firstLetter isEqualToString:#"0"]) {
card = [card substringFromIndex:1];
[self deleteZerosOnFirst:card];
NSLog(#"CARD: %#", card);
return card;
}
else {
NSLog(#"CARD: %#", card);
return card;
}
}
The main problem is that you're not using the result of the recursion. The line of code where you call yourself should say this:
card = [self deleteZerosOnFirst:card];
Also, you're calling deleteZerosOnFirst before you do the NSLog. Reverse the order of these two lines. That will at least give you your debug output in the right sequence.
Here's your recursive call:
[self deleteZerosOnFirst:card];
That doesn't modify the string that card references. It creates and returns a new string. You're ignoring the returned string. You want this:
card = [self deleteZerosOnFirst:card];
But this is really a lot simpler:
#implementation NSString (withoutLeadingZeroes)
- (NSString *)withoutLeadingZeroes {
NSString *s = self;
while ([s hasPrefix:#"0"]) {
s = [s substringFromIndex:1];
}
return s;
}
#end

Undefined selector with Objective-C runtime - blocks

I'm trying to create a function where multiple times I do the same thing. I've deceided to go with a block this time. However after writing following code:
- (BOOL)readyForProcessing {
void (^notDeclaredError)(id) = ^(id missingObject) {
NSString *missingObjectName = NSStringFromSelector(#selector(missingObject));
NSString *errorDescription = [NSString stringWithFormat:#"You need to provide %# property", missingObjectName];
[self configureErrorWithLocalizedDescription:errorDescription];
};
if (!self.delegate) notDeclaredError(self.delegate);
return (self.error == nil);
}
I get a warning in the line, where I declare missingObjectName.
Undeclared selector 'missingObject'
I know it will probably try to make a NSString from missingObject instead of delegate. How to pass it this way, that the output will be delegate and the code will be inside the block?
Here you are:
- (BOOL)readyForProcessing {
void (^notDeclaredError)(SEL) = ^(SEL missingObject) {
NSString *missingObjectName = NSStringFromSelector(missingObject);
NSString *errorDescription = [NSString stringWithFormat:#"You need to provide %# property", missingObjectName];
[self configureErrorWithLocalizedDescription:errorDescription];
};
if (!self.delegate) notDeclaredError(#selector(delegate));
return self.error ? NO : YES;
}

isEqualToString always returns False

A little background here before I get started, basically we are looking to compare a UDP response with a string stored in Parse's database for our app. This issue is that I can't seem to get the strings to be considered equal by the isEqualToString function. Here's the code I have running now, I have tried a few work-arounds I've seen in other questions but it still doesn't work.
- (BOOL) onUdpSocket:(AsyncUdpSocket *)sock didReceiveData:(NSData *)data withTag:(long)tag fromHost:(NSString *)host port:(UInt16)port
{
if(tag == TAG_SINGLE_GRILL)
{
NSString *grillId = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
if(grillId.length > 11)
{
grillId = [grillId substringToIndex:11];
}
grillId = [NSString stringWithFormat:#"%#", grillId];
if([grillId hasPrefix:#"GMG"])
{
for(int i = 0; i < [parseGrills count]; i++)
{
NSString *parseGrillId = [[parseGrills objectAtIndex:i] grillId];
parseGrillId = [NSString stringWithFormat:#"%#", parseGrillId];
//If we match the id, add it to found grills
if([grillId isEqualToString:parseGrillId])
{
//do stuff
}
}
}
NSLog(#"Grill ID : %#", grillId);
}
return TRUE;
}
parseGrills is an NSMutableArray with a very basic Grill object, I use synthesize for the properties, otherwise the .m file is essentially empty.
#import <Foundation/Foundation.h>
#interface Grill : NSObject
#property (nonatomic) NSString* grillId;
#property (nonatomic) NSString* ipAddress;
#end
Here's a screen shot of the debugger after it returns false
Any help would be greatly appreciated. Thanks.
I guess that they are of different encoding.
I have run this experiment and see that if the encoding is different, it will return NO. So, try converting parseGrillId to utf8 with the code below.
NSString *s1 = [NSString stringWithCString:"HELLO123" encoding:NSUTF8StringEncoding];
NSString *s2 = [NSString stringWithCString:"HELLO123" encoding:NSUTF16StringEncoding];
NSString *s3 = [NSString stringWithUTF8String:s2.UTF8String];
if ([s1 isEqualToString:s2]) {
NSLog(#"s1 == s2");
}
if ([s1 isEqualToString:s3]) {
NSLog(#"s1 == s3");
}
Will print s1 == s3.

Objective-C exercises undeclared identifier error

I'm currently teaching myself Objective-C as a first language. I understand the difficulty involved, but I'm quiet a persevering individual. I've began to do the exercises on the Apple Objective-C documentation. My goal is to have my program log out my first and last name instead of a generic Hello World greeting.
I keep receiving a Use of Undeclared identifier error. I'm trying to figure out what is causing the error.
Here is the introClass.h
#import <UIKit/UIKit.h>
#interface XYZperson : NSObject
#property NSString *firstName;
#property NSString *lastName;
#property NSDate *dateOfBirth;
- (void)sayHello;
- (void)saySomething:(NSString *)greeting;
+ (instancetype)person;
-(int)xYZPointer;
-(NSString *)fullName;
#end
Here is IntroClass.m
#import "IntroClass.h"
#implementation XYZperson
-(NSString *)fullName
{
return[NSString stringWithFormat:#" %# %#", self.firstName, self.lastName];
}
-(void)sayHello
{
[self saySomething:#"Hello %#", fullName]; //use of undeclared identifier "fullName"
};
-(void)saySomething:(NSString *)greeting
{
NSLog(#"%#", greeting);
}
+(instancetype)person{
return [[self alloc] init];
};
- (int)xYZPointer {
int someInteger;
if (someInteger != nil){
NSLog(#"its alive");
}
return someInteger;
};
#end
The problem is that fullName is the name of a method. It should be invoked on self with square brackets.
Since saySomething: expects a single parameter, you need to either (1) remove the #"Hello %#" portion of the call, like this:
-(void)sayHello {
[self saySomething:[self fullName]];
};
or to make a single string from #"Hello %#" and [self fullName], like this:
-(void)sayHello {
[self saySomething:[NSString stringWithFormat:#"Hello %#", [self fullName]]];
};
You are passing back a string of first and last name but I don't see anywhere that you had set a value for them. As others noted try
-(void)sayHello
{
_firstName = [NSString stringWithFormat:#"John"];
_lastName = [NSString stringWithFormat:#"Doe"];
//if you want to see what's happening through out your code, NSLog it like
NSLog(#"_firstName: %# ...", _firstName);
NSLog(#"_lastName: %# ...", _lastName);
NSString *strReturned = [self fullName];
NSString *concatStr = [NSString stringWithFormat:#"Hello %#", strReturned];
NSLog(#"strReturned: %# ...", strReturned);
NSLog(#"concatStr: %# ...", concatStr);
[self saySomething:concatStr];
};
-(NSString *)fullName
{
return[NSString stringWithFormat:#" %# %#", self.firstName, self.lastName];
}
use
[self saySomething:#"Hello %#", self.fullName]];
or
[self saySomething:#"Hello %#", [self fullName]];

gettin EXC_BAD_ACCESS while using nsstring

I am getting crazy during 4 hours and I really need help. Here is the code:
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
//check if strGroup has prefix and suffix #
BOOL result;
result = [strGroup hasPrefix: #"#"];
if (result)
{
result = [strGroup hasSuffix: #"#"];
if (result)
{
NSMutableString* string = [NSMutableString stringWithString: strGroup];
str = [strGroup substringWithRange: NSMakeRange (1, [string length]-2)];
strToHoldAllContact = [NSString stringWithFormat:#"%#",str];
}
}
NSLog(#"strToHoldAllContact=%#",strToHoldAllContact);
}
I am gettin the value of strToHoldAllContact correctly. But when I try to access strToHoldAllContact from another method I am getting the error:
[CFString respondsToSelector:]: message sent to deallocated instance 0x856f2a0
Use
strToHoldAllContact = [NSString stringWithFormat:#"%#",str];
[[strToHoldAllContact retain] autorelease];
and forget about release.
where ever you are initializing or setting the string do this [strToHoldAllContact retain]; and don't forget to release it once you are done using it
Just replace
strToHoldAllContact = [NSString stringWithFormat:#"%#",str];
to
strToHoldAllContact = [[NSString alloc] initWithFormat:#"%#",str];
And release it after you don't need it anymore.
with ARC, in .h declare strToHoldAllContact as:
#property(strong) NSString *strToHoldAllContact;
in .m, use it (after #synthesize) as self.strToHoldAllContact = [NSString stringWithFormat:#"%#",str];
this way you will not have problems.
without ARC,in .h declare strToHoldAllContact as:
#property(retain) NSString *strToHoldAllContact;
and use it same ways as with ARC in.m file.

Resources