- (UIImage*)returnRandomBackground{
int selectedImage = (arc4random() % 4) + 1;
UIImage *imageToReturn;
if (selectedImage == 1) {
imageToReturn = Image1;
}
else if (selectedImage == 2) {
imageToReturn = Image2;
}
else if (selectedImage == 3) {
imageToReturn = Image3;
}
else if (selectedImage == 4) {
imageToReturn = Image4;
}
return imageToReturn;
}
UnDefined or garbage value returned to caller.
To me this code looks legal, whats wrong with it?
The compiler is not smart enough to deduce that (arc4random() % 4) + 1 is always in the range [1..4]. Just initialize imageToReturn to null and the warning will go away.
Note: if you use this, and at some point you change the modulus in the random number generation, you're liable to return nulls to the caller (with no warning from your friendly compiler) if you don't adapt your if/else sequence accordingly.
If that is not something you want, use an assertion somewhere (possibly by adding a "catch-all" else clause and asserting there).
Also, consider using a switch block here instead of the if/else sequence, that's the most natural construct here in my opinion.
The compiler will think that it's possible that there's a selectedImage = 5, which means there's a possibility of imageReturn remaining unassigned. You'll have to change the last else if to just an else to make sure imageReturn is always assigned.
Look at what the code would do if selectedImage = 5. It'll break.
Alternatively - you could just initialise imageToReturn
UIImage *imageToReturn = nil;
Then, whatever happens, you won't be returning a garbage value.
Related
Annoying newbie problem here. This variable isPlayerTouchingAnotherPlayer is being set to true as soon as I touch the piece. I'm almost positive I know why but I can't find a way to display this in log to confirm. I could probably do it by setting different flag numbers for each of the objects but I was hoping there is another way.
The problem is that piece is an object that is also located in p1Array so as soon as I touch it it hits itself and isPlayerTouchingAnotherPlayer is evaluated to true.
Is there a way I could print out the view or image name of the objects touching somehow to confirm this? And furthermore, is there a way to somehow avoid this annoying conflict.
for (int i = 0; i <[p1Array count]; i++) {
UIImageView *tempP1;
tempP1 =[p1Array objectAtIndex:i];
if (CGRectIntersectsRect(piece.frame, tempP1.frame)) {
NSLog(#"selected piece: %#, touched piece: %# ", piece, tempP1);
isPlayerTouchingAnotherPlayer = TRUE;
}
}
why not use fast enumeration and skip the image view you are not interested in checking.
for (UIImageView *imageView in p1Array) {
if (imageView == piece)
continue;
if (CGRectIntersectsRect(imageView.frame, piece.frame)) {
// do whatever
}
}
it seems like you are already printing out the names of the objects touching in the code sample you have provided. if you want to print out specific properties of the objects you can do that to.
as soon as i touch it it hits itself and isPlayerTouchingAnotherPlayer
is evaluated to true.
Then you should get a log message that shows the same object for the selected piece and the touched piece. If that's what's happening, then just add a condition to your if to prevent it:
if (piece != tempP1 && CGRectIntersectsRect(piece.frame, tempP1.frame)) {
Simply
NSLog(#"%# %#", piece, tempP1);
or
NSLog(#"%ld %ld", (NSInteger) piece, (NSInteger) tempP1);
The first will show you the description of the object, the second the address in memory, if it's same address, it's the same object.
You can simply check if it's the same object (pointer) with a simple equal check to exclude the same object :
if (piece != tempP1) {
if (CGRectIntersectsRect(piece.frame, tempP1.frame)) {
...
}
Furthermore, you would like to write this:
for ( int i = 0;
( ( i < [p1Array count] )
&& ( ! isPlayerTouchingAnotherPlayer )
);
i++
) {
...
}
What is the best way to "slice" an NSArray from the end, rather than the beginning, of the array (for example, finding the subarray containing the last few elements of a NSArray of unknown length)? In Python, you can use negative indices to accomplish this, e.g.:
new_list = old_list[-5:-3]
What's the most natural way to do this in Objective-C?
There's nothing to match Python's nice syntax for this, but you could do:
NSUInteger count = [myArray count];
NSArray * slice = [myArray subarrayWithRange:(NSRange){count-n, n}];
You could also write up a category for NSArray, something like:
#interface NSArray (jrdioko_slice)
- (NSArray *) jrdioko_sliceFrom:(NSInteger)start to:(NSInteger)stop;
#end
If you want to go this route, the Python source will certainly repay study. A list object creates a slice object when a slice operation is performed. The relevant method on a slice object is PySlice_GetIndicesEx. You'll just have to be careful turning those indexes into an NSRange. As the comment in that function warns "this is harder to get right than you might think". (I'll try to take a crack at this later.)
UPDATE: Here we have a slice category on NSArray. The index calculation logic is pretty much straight out of the Python code that I linked to above.* It's actually a lot easier than I thought at first if you don't have to worry about the stride part of a Python slice. I've run this through a few tests and it seems to work the same as the Python version.
#interface NSArray (WSS_Slice)
- (NSArray *)WSS_arrayBySlicingFrom:(NSInteger)start to:(NSInteger)stop;
#end
// Python allows skipping any of the indexes of a slice and supplies default
// values. Skipping an argument to a method is not possible, so (ab)use
// NSNotFound as "not specified" index value. The other way to do this would
// be with varargs, which might be even handier if one decided to implement
// the stride functionality.
enum {
WSS_SliceNoIndex = NSNotFound
};
#implementation NSArray (WSS_Slice)
- (NSArray *)WSS_arrayBySlicingFrom:(NSInteger)start to:(NSInteger)stop {
// There's an important caveat here: specifying the parameters as
// NSInteger allows negative indexes, but limits the method's
// (theoretical) use: the maximum size of an NSArray is NSUIntegerMax,
// which is quite a bit larger than NSIntegerMax.
NSUInteger count = [self count];
// Due to this caveat, bail if the array is too big.
if( count >= NSIntegerMax ) return nil;
// Define default start and stop
NSInteger defaultStart = 0;
NSInteger defaultStop = count;
// Set start to default if not specified
if( start == WSS_SliceNoIndex ){
start = defaultStart;
}
else {
// If start is negative, change it to the correct positive index.
if( start < 0 ) start += count;
// Correct for out-of-bounds index:
// If it's _still_ negative, set it to 0
if( start < 0 ) start = 0;
// If it's past the end, set it to just include the last item
if( start > count ) start = count;
}
// Perform all the same calculations on stop
if( stop == WSS_SliceNoIndex ){
stop = defaultStop;
}
else {
if( stop < 0 ) stop += count;
if( stop < 0 ) stop = 0;
if( stop > count ) stop = count;
}
// Calculate slice length with corrected indexes
NSInteger sliceLength = stop - start;
// If no slice, return a new empty array
if( sliceLength <= 0 ){
return [NSArray array];
}
else {
return [self subarrayWithRange:(NSRange){start, sliceLength}];
}
}
#end
*Therefore I think I need to include a link to the Python License and also note that this may still be “Copyright © 2001-2010 Python Software Foundation; All Rights Reserved”, because although this looks to me like a separately-copyrightable derivative work, I ain't a lawyer.
I am trying to implement a simple method, however I am still quite a newbie on objective-c.
I have this simple method which is trying to convert from an id to a specific value in enum, if matched.
This is the enum
typedef enum {
DXTypeUnknown = 0,
DXDatasource = 1,
DXGroup = 2
} DXPropertyType;
And this is the relevant method:
-(DXPropertyType)typeFromObject:(id)_type {
int _t = [_type intValue];
switch (_t) {
case DXDatasource:
return [NSNumber numberWithInt:DXDatasource];
case DXGroup:
return [NSNumber numberWithInt:DXGroup];
default:
return [NSNumber numberWithInt:DXTypeUnknown];
}
}
The very first check I would to implement is if the id can be converted to an int, then see if it falls in the two relevant categories group or datasource, or return a default value if not. Could you tell me if the switch/case I implemented is a proper solution or not ?
I would like also this method not to causing crash of an application, so what could be advisable to check, keeping in mind that in any case the default value is to be returned.
thanks
[EDIT]
I forgot to say that this value is going to be stored in a field of a NSManagedObject, which by CoreData restriction can be an NSNumber, so probably there's a better solution instead of an enum.
It might be a good idea to include this code to check if the id can be used:
if (![_type respondsToSelector:#selector(intValue)])
return nil;
However, if you'll always pass a NSNumber go ahead and declare the method as:
- (DXPropertyType)typeFromObject:(NSNumber)_type;
In your code, you're returning a NSNumber. I don't think that's what you really
want, as you'd be doing nothing with the NSNumber passed. Return the enum
item:
-(DXPropertyType)typeFromObject:(id)_type {
if (![_type respondsToSelector:#selector(intValue)])
return nil;
int _t = [_type intValue];
switch (_t) {
case DXDatasource:
return DXDatasource;
case DXGroup:
return DXGroup;
default:
return DXTypeUnknown;
}
}
And then this can be simplified to:
- (DXPropertyType)typeFromObject:(id)_type {
if ([_type respondsToSelector:#selector(intValue)]) {
int t = [_type intValue];
DXPropertyType property_t;
if (t >= 1 && t <= 2)
property_t = t;
else
property_t = DXTypeUnknown;
return property_t;
}
return nil;
}
Your switch statement is a good solution and will not cause a crash.
However, your method returns a NSNumber when it expects a different return. I suggest changing the method to
-(NSNumber)typeFromObject:(id)_type
You specify that your method returns an enum, but you return objects. So either return the enum values or specify the return type to be NSNumber *.
A different solution could be using singleton objects instead of an enum, but that's probably more work than it's worth. Think [NSNull null].
I'm temped to use an int, and make 0 == NO, 1 == YES, and anything else == undefined.
Obviously there are a million ways to do something like this, but what seems like the best way to you? Concerns I can think of include simplicity and memory footprint (e.g. what if I have a lot of these?).
Another way is to use two BOOLs, one for isDefined, and one for value
Another way,
typedef enum { CPStatusUndefined, CPStatusAvailable, CPStatusUnavailable } CPStatus;
Edit, the use case is:
I have a yes/no property that is difficult to calculate. When it is being checked, it is checked frequently (by UIMenuController, OFTEN), but unless the user selects it, it is never checked. The way I chose to deal with this is a tri-type variable. The first time you check, if it is undefined you calculate the yes/no value and return it, after that you just return the yes/no value.
Use an enum. In Objective-C they work just like they do in C/C++
typedef enum {
No = 0,
Yes,
Other
} tri_type;
tri_type myVar = No;
if( myVar == Yes || myVar == Other ) {
// whatever
}
How about NSNumber, since it can be nil?
[number boolValue] == YES;
[number boolValue] == NO;
[number boolValue] == nil; // or just number == nil
If you want to conserve the most amount of memory, use a char.
char == 0, false
char == 1, true
else, undefined.
Obviously, you'll want to initialize it at something like -1.
This is the way obj-c does comparator return values:
if 0, they are equal.
if positive, a > b
if negative, a < b
Same idea as above.
People I'd like to see if an element at index[i] is not present in a different (or current ) array.
So for instance if my array looked somewhat like this
[wer, wer4 , wer5 , werp , klo ...
Then I would like to see if aExerciseRef.IDE ( which is "sdf" for instance ) does or does not exist at index[i].
I assume I'd have to use some sort of iterator ..
for( int i = 0; i < 20; i++ )
{
if([instruct objectAtIndex:index2 + i] != [instruct containsObject:aExerciseRef.IDE] )
NSLog(#"object doesn't exist at this index %i, i );
else
NSLog(#"well does exist")
}
I know this doesn't work , it's just to elaborate what I'd like to achieve.
edit:
I'm going to try to elaborate it a little more and be more specific.
1) First of all aExerciseRef.IDE changes everytime it get's called so one time it is "ret" another time it's "werd".
2) Imagine an array being filled with aExerciseRef.IDE's then I would like to compare if the elements in this array exist in the instruct array.
So I would like to see if the element at let's say position 2 (wtrk)
[wer, wtrk, wer , sla ...
exists in the array which was being filled with the aExerciseRef.IDE's.
I hope I've been more clear this time.
Sir Lord Mighty is partially correct. Yes, your comparison is wrong. No, his solution won't work.
Here's one that will:
if (index < [anArray count] && [[anArray objectAtIndex:index] isEqual:anObject]) {
NSLog(#"Got it!");
} else {
NSLog(#"Don't have it.");
}
Alternatively, you can use the containsObject: method to achieve the same thing:
if ([anArray containsObject:aExerciseRef.IDE]) {
NSLog(#"Got it!");
} else {
NSLog(#"Don't have it.");
}
The second option will not give you the index of the object, but that is easily rectified using:
NSInteger index = NSNotFound;
if ([anArray containsObject:aExerciseRef.IDE]) {
index = [anArray indexOfObject:aExerciseRef.IDE];
...
}
Your example makes no sense at all, and does nothing to clarify the question. You are doing a comparison between an expression with type (id)
[instruct objectAtIndex:index2 + i]
and one with type BOOL
[instruct containsObject:aExerciseRef.IDE]
And if the object you are looking for is at index x in an array, then it goes without saying that containsObject on the array will return YES for that object.
If what you want to accomplish is simply what you state in the title, then it's as easy as:
if ([[anArray objectAtIndex:index] == anObject])
NSLog (#"Got it!");
else
NSLog (#"Don't have it.");