ObjC : NSLog a pointer name - objective-c

I filled a NSMutableArray with 3 class instances I created. Now I want to iterate this array to get some variable values. I'm able to do so, but not able to print my instance name (bread, water, ...) Instead, I get their addresses.
I guess it's simple but I'm struggling a bit, so if someone knows how to ...
Thank you
#import <Foundation/Foundation.h>
#import "StockHolding.h";
int main (int argc, const char * argv[]) {
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
StockHolding *bread = [[StockHolding alloc] init];
[bread setPurchaseSharePrice:100];
[bread setCurrentSharePrice:120];
[bread setNumberOfShares:100];
StockHolding *water = [[StockHolding alloc] init];
[water setPurchaseSharePrice:100];
[water setCurrentSharePrice:80];
[water setNumberOfShares:10];
StockHolding *tomatoes = [[StockHolding alloc] init];
[tomatoes setPurchaseSharePrice:100];
[tomatoes setCurrentSharePrice:50];
[tomatoes setNumberOfShares:1];
NSMutableArray *myStock = [NSMutableArray arrayWithObjects:bread, water, tomatoes, nil];
for (StockHolding *s in myStock)
{
NSLog(#"Here is what I paid for my %p : %f", s, [s costInDollars]);
NSLog(#"Here is what I earn for my %p : %f", s, [s valueInDollars]);
}
[pool drain];
return 0;
}

Why not implement the -(NSString *)description method on your StockHolding class? Then you can use %# in string formats and it will output the description there.
Alternatively you can also output any other string property of StockHolding instances with %#.

If you want to NSLog an object and it's pointer name you can add this #define in your preprocessor macro #define OLog(x) NSLog(#"%s = %#",#x, x);

Related

Objective-C method_exchangeImplementations result is not as expected

I'm learning Objective-C runtime, and try to use method_exchangeImplementations to exchange addObject: method and removeObject: method of NSMutableArray.
My code like this:
int main(int argc, const char * argv[]) {
#autoreleasepool {
Method removeMethod = class_getInstanceMethod(NSMutableArray.class, #selector(removeObject:));
Method addMethod = class_getInstanceMethod(NSMutableArray.class, #selector(addObject:));
method_exchangeImplementations(addMethod, removeMethod);
NSMutableArray *array = [[NSMutableArray alloc] init];
NSObject *obj = [[NSObject alloc] init];
[array removeObject:obj];
NSLog(#"%lu", (unsigned long)array.count); // expect print 1, actual print 1
[array addObject:obj];
NSLog(#"%lu", (unsigned long)array.count); // expect print 0, actual print 2
}
return 0;
}
I expect exchange add/remove function, but seems like only removeObject: has been exchange to addObject: , addObject: still is addObject to array, now I have two addObject method of NSMutableArray
I'm not sure the reason. I try to exchange other method like uppercaseString/lowercaseString of NSString, that work correct.
OK, I solved problem. Thanks #Willeke for the tip.
The real class of my array is not NSMutableArray, so use NSMutableArray.class in class_getInstanceMethod can't get correct method. Use [array class] is the answer.
int main(int argc, const char * argv[]) {
#autoreleasepool {
NSMutableArray *array = [[NSMutableArray alloc] init];
Method removeMethod = class_getInstanceMethod([array class], #selector(removeObject:));
Method addMethod = class_getInstanceMethod([array class], #selector(addObject:));
method_exchangeImplementations(addMethod, removeMethod);
NSObject *obj = [[NSObject alloc] init];
[array removeObject:obj];
NSLog(#"%lu", (unsigned long)array.count); // expect print 1, actual print 1
[array addObject:obj];
NSLog(#"%lu", (unsigned long)array.count); // expect print 0, actual print 0
}
return 0;
}

Values of array not calculating in subclass when called

Just doing some of the Gold challenges in the BNR iOS book and Chapter 2's challenge has got me stumped.
This is my BNRContainer.m class file that is a subclass of BNRItem. The object of the challenge is to override the object's description and print out some of it's attributes. The one that isn't calculating correctly is the BNRContainer's containerValue.
#import "BNRContainer.h"
...
-(int)containerValue{
int total = 0;
for (BNRItem *item in self.subItems) {
total += item.valueInDollars;
}
return total;
}
-(NSString *)description{
NSString *descriptionstr = [NSString stringWithFormat:#"I'm a container named %#! My total value is %d and my items are %#",self.itemName, containerValue, self.subItems];
return descriptionstr;
}
Here's the Main.m:
#import <Foundation/Foundation.h>
#import "BNRItem.h"
#import "BNRContainer.h"
int main(int argc, const char * argv[])
{
#autoreleasepool {
NSMutableArray *items = [[NSMutableArray alloc] init];
BNRItem *item = [[BNRItem alloc] initWithItemName:#"Red Sofa" valueInDollars:100 serialNumber:#"A1B2C"];
BNRItem *itemWithName = [[BNRItem alloc] initWithItemName:#"Blue Sofa" valueInDollars:45 serialNumber:NULL];
BNRItem *itemWithNoName = [[BNRItem alloc]init];
[items addObject:item];
[items addObject:itemWithName];
[items addObject:itemWithNoName];
BNRContainer *container = [[BNRContainer alloc]init];
container.itemName = #"TheMainContainer";
container.subItems = items;
NSLog(#"%#",container);
items = nil;
}
return 0;
}
my results:
2014-04-08 23:38:58.395 RandomItems[83205:303] I'm a container named TheMainContainer! My total value is 0 and my items are (
"Red Sofa (A1B2C): Worth 100, Recorded on 2014-04-09 03:38:58 +0000",
"Blue Sofa ((null)): Worth 45, Recorded on 2014-04-09 03:38:58 +0000",
"Item (): Worth 0, Recorded on 2014-04-09 03:38:58 +0000"
well there it is... good old exclusion of self
NSString *descriptionstr = [NSString
stringWithFormat:#"I'm a container named %#! My total value is %d and my items are %#",
self.itemName,
self.containerValue, //self was missing
self.subItems];

How to release object of another class in our class?

I have created two classes (FirstClass and SecondClass) in command line application. I created an object of SecondClass in FirstClass method. Now I want to call that method in main and release the memory allocated to that object. My code is as follows..
#implementation FirstClass
+(NSMutableArray *) addObject{
NSMutableArray *namesArray = [[[NSMutableArray alloc]init] autorelease];
SecondClass *second = [[SecondClass alloc]init];
NSLog(#"Before adding object, count = %ld ",[second retainCount]); //RC = 1
[second setName:#"Mobicule"];
[namesArray addObject:second];
NSLog(#"First object addeded, count = %ld ",[second retainCount]); //RC = 2
[second release];
NSLog(#"After release, count = %ld",[second retainCount]); //RC = 1
return namesArray;
}
#end
I want to make retain count to zero..
And main function is as follows..
int main (int argc, const char * argv[]) {
#autoreleasepool {
// insert code here...
// NSLog(#"Hello, World!");
NSMutableArray *arrayMain = [[NSMutableArray alloc]init];
arrayMain = [FirstClass addObject];
for (int i = 0; i<[arrayMain count]; i++) {
NSLog(#"%#",[[arrayMain objectAtIndex:i] name]);
}
NSLog(#"%ld",[arrayMain retainCount]);
}
return 0;
}
I am assuming your synthesised property for name is retain.
+(NSMutableArray *) addObject{
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
NSMutableArray *namesArray = [[NSMutableArray alloc]init];
SecondClass *second = [[[SecondClass alloc]init]autorelease];
NSLog(#"Before adding object, count = %ld ",[second retainCount]); //RC = 1
[second setName:#"Mobicule"]; //implementation will handle the release for you
[namesArray addObject:second];
NSLog(#"First object addeded, count = %ld ",[second retainCount]); //RC = 2
[pool release];
NSLog(#"After pool release, count = %ld",[second retainCount]); //RC=1
return [namesArray autorelease];
}
You should never use -retainCount, because it never tells you anything
useful.
Take a look at When to use -retainCount?

Method Creates an Array with 11 objects, All Out of Scope, Unrecognized Selector Results

Okay, so, I'm doing a simple lookup. I have an array of NSString objects and a string to search for in the array's elements.
It all seems to work up until I try to add a match to a new mutable array made to hold the search results. The stringHolder variable gets the string, and resultsCollectorArray even get the right number of new elements, but each element is empty and "out of range". Here's the method:
#implementation NSArray (checkForString)
-(NSMutableArray *) checkForString: (NSString *) matchSought
{
long unsigned numberofArrayElements;
long unsigned loop = 0;
NSRange searchResults;
NSMutableArray * resultCollectorArray = [[NSMutableSet alloc] init];
id stringHolder;
numberofArrayElements = [self count];
while (loop < numberofArrayElements) {
searchResults.length = 0;
searchResults = [[self objectAtIndex: loop] rangeOfString: matchSought options:NSCaseInsensitiveSearch];
if (searchResults.length > 0) {
stringHolder = [self objectAtIndex: loop];
[resultCollectorArray addObject: stringHolder];
}
loop++;
}
return [resultCollectorArray autorelease];
}
Once we get back to the main portion of the program, I get an unrecognized selector sent to the mutable array that was supposed to receive the result of the method. Here's the main section:
#import <Foundation/Foundation.h>
#import "LookupInArray.h"
int main (int argc, const char * argv[])
{
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
NSString *testString = [[NSString alloc] initWithString: #"ab"];
NSMutableString * resultString = [[NSString alloc] init];
NSArray * theArray = [[NSArray alloc] initWithObjects: ..., nil]; // Actual code has the objects
NSMutableArray *resultArray = [[NSMutableArray alloc] init];
NSUInteger arrayCount = 0;
unsigned long loops = 0;
resultArray = [theArray checkForString: testString];
arrayCount = [resultArray count];
while (loops < arrayCount){
resultString = [resultArray objectAtIndex: loops]; // Here's where we get the unrecognized selector.
NSLog(#"%#", resultString);
loops++;
}
[pool drain]; // Also, I'll release the objects later. I just want to get what's above working first.
return 0;
}
I've searched the other answers (for hours now), but didn't seen anything that solved the issue.
Any and all help would be really appreciated.
And thanks beforehand.
NSMutableArray * resultCollectorArray = [[NSMutableSet alloc] init]; is so incorrect. You are creating a mutable set and assigning it to a mutable array.
You are getting unrecognized selector because objectAtIndex: is not a valid selector for NSMutableSet. Make that statement,
NSMutableArray * resultCollectorArray = [[NSMutableArray alloc] init];
A Better way
NSArray * filteredArray = [array filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:#"SELF contains[cd] %#", searchString]];
You can directly filter the array using predicates. This way you do this in a single step. :)

How to check if NSString is numeric or not [duplicate]

This question already has answers here:
Closed 13 years ago.
Possible Duplicate:
iphone how to check that a string is numeric only
I have one NSString, then i want check the string is number or not.
I mean
NSString *val = #"5555" ;
if(val isNumber ){
return true;
}else{
retun false;
}
How can I do this in Objective C?
Use [NSNumberFormatter numberFromString: s]. It returns nil if the specified string is non-numeric. You can configure the NSNumberFormatter to define "numeric" for your particular scenario.
#import <Foundation/Foundation.h>
int
main(int argc, char* argv[])
{
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
NSLocale *l_en = [[NSLocale alloc] initWithLocaleIdentifier: #"en_US"];
NSLocale *l_de = [[NSLocale alloc] initWithLocaleIdentifier: #"de_DE"];
NSNumberFormatter *f = [[NSNumberFormatter alloc] init];
[f setLocale: l_en];
NSLog(#"returned: %#", [f numberFromString: #"1.234"]);
[f setAllowsFloats: NO];
NSLog(#"returned: %#", [f numberFromString: #"1.234"]);
[f setAllowsFloats: YES];
NSLog(#"returned: %#", [f numberFromString: #"1,234"]);
[f setLocale: l_de];
NSLog(#"returned: %#", [f numberFromString: #"1,234"]);
[l_en release];
[l_de release];
[f release];
[pool release];
}
You could use rangeOfCharacterFromSet::
#interface NSString (isNumber)
-(BOOL)isInteger;
#end
#interface _IsNumber
+(void)initialize;
+(void)ensureInitialization;
#end
#implementation NSString (isNumber)
static NSCharacterSet* nonDigits;
-(BOOL)isInteger {
/* bit of a hack to ensure nonDigits is initialized. Could also
make nonDigits a _IsNumber class variable, rather than an
NSString class variable.
*/
[_IsNumber ensureInitialization];
NSRange nond = [self rangeOfCharacterFromSet:nonDigits];
if (NSNotFound == nond.location) {
return YES;
} else {
return NO;
}
}
#end
#implementation _IsNumber
+(void)initialize {
NSLog(#"_IsNumber +initialize\n");
nonDigits = [[NSCharacterSet decimalDigitCharacterSet] invertedSet];
}
+(void)ensureInitialization {}
#end