-(void) print {
NSLog(#"%i/%i", numberator, denominator);
}
Fraction *myFraction = [Fraction new];
[myFraction setNumberator:1];
[myFraction setDenominator:3];
Now I have other methods made like dividing both numerator and denominator etc. But i want to add in my [myFraction] in the NSLog with everything else rather than on a new line
NSLog(#"The value of my fraction is: %i/%i which equals to: %.3g * 100 = %.4g%%", [myFraction numberator], [myFraction denominator], [myFraction convertToNum], [myFraction multiplyBy100]);
is there anyway i can add in the [myFractions print] where the two %i %i is, so i don't have to type in [myFraction numerator/denominator]
eg.
NSLog(#"%#", [myFractions Print];
result: 1/3
You can usedescription method. You can override it in your class to return string representation of your class.
In your case you can use the following code:
-(NSString*) description {
return [NSString stringWithFormat:#"%i/%i", numerator, denominator];
}
to print the object you can then use it like this
NSLog("Fraction = %#", yourFractionObj);
See Describing objects.
Instead of your print method, override the description method on your Fraction class like this:
- (NSString *)description {
return [NSString stringWithFormat:#"%i/%i", numberator, denominator];
}
The description method is automatically called when you print an object using NSLog, so you can now write logs like this:
NSLog(#"The value of my fraction is: %# which equals to: %.3g * 100 = %.4g%%", myFraction, [myFraction convertToNum], [myFraction multiplyBy100]);
If you need the print method for another reason you can now write it like this:
- (void) print {
NSLog(#"%#", self);
}
You can use func or FUNCTION. It will print the method name with class name. For Example
NSLog(#"%s",__func__);
Related
I'm trying to extend NSLog that can print any type of object. Means, my custom class gets the value that need to be printed from the user and checks its class type and then it will print as desired format.
Consider my extended class name is, MyLog (So it contains MyLog.h and MyLog.m)
MyLog.h:
void MyLog (id objectValue);
MyLog.m:
#import "MyLog.h"
void MyLog (id objectValue)
{
if ([objectValue isKindOfClass:[NSString class]])
{
NSLog(#"%#",objectValue); //Same for NSArray, NSDictionary, NSMutableArray, NSMutableDictionary
}
else if ([objectValue isKindOfClass:[NSData class]])
{
NSLog(#"%#",[[NSString alloc]initWithData:objectValue encoding:NSUTF8StringEncoding]);
}
....
....
}
So, if I include this class (MyLog.h) in prefix file, I can call the below method from any class to simply print the given object.
MyLog(valueOfObject);
Problems:
The CGRect, CGpoint, CGSize related things (which are not an object) can not be passed as id to MyLog() function.
I tried to print the object name along with its value for more readability. Refer this post.
For example,
NSString *myString = #"Welcome";
MyLog(myString);
This will print myString: Welcome instead of just printing Welcome.
I can achieve this my defining a preprocessor like
#define MYLOG(x) NSLog( #"%s:%#",#x, x)
So, I tried to customize it in the following way
#define MYLOG(x) NSLog(#"%s:%#",#x, MyLog(x))
But it throws "Argument type 'void' is incomplete" error.
Questions:
How can I pass non objects as id to a function?
How can I call a function within a preprocessor macro?
Help needed!! Just Confused!!
If you implement -(NSString*)description you can print any object in NSLog with NSLog(#"%#", myObject).
So just add -(NSString*)description in the classes of objects that you want to print out, and in them just return the NSString value that you think is relevant for that object.
What if I have a method that returns a CGFloat and that method could not find an expected number, I would like to return something like NSNotFound, but that is an NSInteger.
Whats the best practice for this ?
You could use not a number (NaN).
See nan(), nanf() and isnan().
However for these issues, where there is no clearly defined non-value (it's worse with integers), then I prefer to use the following method semantics:
- (BOOL)parseString:(NSString *)string
toFloat:(CGFloat *)value
{
// parse string here
if (parsed_string_ok) {
if (value)
*value = parsedValue;
return YES;
}
return NO;
}
A pretty clean way is to wrap it into an NSNumber:
- (NSNumber *)aFloatValueProbably
{
CGFloat value = 0.0;
if (... value could be found ...) {
return #(value);
}
return nil;
}
Then you can check if the function returned nil for your non-existing value.
I have this method and I need to concatenating parameters so the result should be. Any idea how to do it?
getTyreLabels?width=m125.00&aspect=25&rim=13.00&season=SU&time=269742091
- (NSURL *)getTyreLabels:(NSString*)width :(NSInteger*)aspect : (NSInteger*)rim : (NSString*)season : (NSString*)pattern : (NSInteger*)time;
{
return [[self getBaseUrl] URLByAppendingPathComponent:#"getTyreLabels"];
}
I'm guessing that the string you put at the beginning is the desired output.
In which case your method should be something like...
- (NSString *)parameterStringWithWidth:(NSString *)width
aspect:(NSInteger)aspect
rim:(NSInteger)rim
season:(NSString *)season
pattern:(NSString *)pattern
time:(NSInteger)time
{
return [NSString stringWithFormat:#"getTyreLabels?width=m%#&aspect=%ld&rim=%ld&season=%#&time=%ld", width, (long)aspect, (long)rim, season, (long)time];
}
That will return the string. Not the URL but you should be able to get the point from this.
Note the way the method name is constructed. It makes it MUCH easier to call it from somewhere else as you can see what each parameter is relating to.
NSString *theString = [self parameterStringWithWidth:#"125.00" aspect:25 rim:13 season:#"SU" pattern:#"" time:269742091];
This will result in theString being the value you put in your question.
Might be you want something like this -
- (NSURL *)getTyreLabelsWithWidth:(NSString*)width
andAspect:(NSInteger)aspect
andRim:(NSInteger)rim
andSeason:(NSString *)season
andPattern:(NSString*)pattern
andTime:(NSInteger)time
{
NSString *stringToAppend = [NSString stringWithFormat#"getTyreLabels?width=%#&aspect=%d&rim=%d&season=%d&time=%d", width, aspect, rim, season, time];
return [[self getBaseUrl] URLByAppendingPathComponent: stringToAppend];
}
I i'm getting the error "Implicit conversion of 'int' to 'id' is disallowed with ARC" at the line marked with "faulty line". I guess it have something to do with that i'm checking for an integer in an array, that contains objects instead of integers.
#import "RandomGenerator.h"
#implementation RandomGenerator
NSMutableArray *drawnNumbers;
-(int) randomNumber:(int)upperNumber {
return arc4random_uniform(upperNumber);
}
-(NSMutableArray*) lotteryNumbers :(int)withMaximumDrawnNumbers :(int)andHighestNumber {
for (int i = 1; i <= withMaximumDrawnNumbers; i++)
{
int drawnNumber = [self randomNumber:andHighestNumber];
if ([drawnNumbers containsObject:drawnNumber]) { //faulty line
//foo
}
}
return drawnNumbers;
}
#end
NSArrays can only contain objective-c objects. So actually the method containsObject: is expecting an object, not an int or any other primitive type.
If you want to store number inside an NSArray you should pack them into NSNumber objects.
NSNumber *someNumber = [NSNumber numberWithInt:3];
In your case, if we assume that drawnNumbers is already an array of NSNumbers, you should change the randomNumber: generation to:
-(NSNumber*) randomNumber:(int)upperNumber {
return [NSNumber numberWithInt:arc4random_uniform(upperNumber)];
}
And then when picking it up on the lotteryNumbers method, you should:
NSNumber *drawnNumber = [self randomNumber:andHighestNumber];
Another note would go for the method you defined for lotteryNumbers. You used a really strange name for it, I think you misunderstood how the method naming works in objective-c. You were probably looking for something more like:
-(NSMutableArray*) lotteryNumbersWithMaximumDrawnNumbers:(int)maximumDrawnNumbers andHighestNumber:(int)highestNumber;
Late edit:
Objective-C now allows a way more compact syntax for creating NSNumbers. You can do it like:
NSNumber *someNumber = #(3);
And your method could be rewritten as:
-(NSNumber*) randomNumber:(int)upperNumber {
return #(arc4random_uniform(upperNumber));
}
You are using an int where an object (presumably NSNumber) is expected. So convert before use:
if ([drawnNumbers containsObject:#( drawnNumber )])
iOS 5.0 SDK
I have a method that took a parameter as a 'type' that I defined. Lets call it 'Places'. This type was defined as the following:
typedef enum {
kBar = 0,
kRestaurant = 1,
kCafe = 2
} Places
My method would take a parameter of Places.
Based on the Place type passed in, I would append the type to the url:
ex: http://www.domain.com/place=1
However, the url parameter cannot be a number it has to be a string.
ex: http://www.domain.com/place=restaurant
I know enums cannot be strings so I am trying to figure out the right approach for this. Do I have a plist and then read the plist into a dictionary? Is there another way?
I would do something like:
typedef enum {
PlaceTypeBar = 0,
PlaceTypeRestaurant = 1,
PlaceTypeCafe = 2
} PlaceType
#interface PlaceTypeHelper : NSObject
+ (NSString *) stringForPlace:(PlaceType)place;
#end
#implementation
+ (NSString *) stringForPlace:(PlaceType)place {
NSArray *places = [NSArray arrayWithobjects:#"Bar", #"Restaurant", #"Cafe", nil];
return [places objectForKey:(NSInteger)place];
}
#end
Headups, I've no tested the code yet.
There's a lot of different approaches you could take. Here's what I might do myself.
Assuming there's a finite and known amount of values, you can do a simple function which returns the string for the given type :
(NSString*) StringForPlaceType(PlaceType thePlace) {
switch(thePlace) {
case kBar:
return #"Bar";
case kRestaurant:
return #"Restaurant";
case kCafe:
return #"Cafe";
default:
// ...
}
}
No need for an object or class unless you want for flexibility such as dynamic values and such.