iPhone: Problem with incrementing NSNumber & displaying transparent images (UIImageView) - uiimageview

I have a problem with NSNumber: I don't understand how to increment and decrement it! I've tried int with [NSNumber intValue] and so on, but it didn't work!!!! I just want a page counter which can be converted to an NSNumber at the end.
My second problem is displaying a (partially) transparent image in an UIImageView. It has ever a (white) background.
Thanks for answering,
Le Milonkh

HI there
don't use nsnumbers, use ints. Much easier... (NSNumber is merely a wrapper for storing numbers, whereas int provides the default set of C based mathematical interfaces you are looking for, with relative ease - I'm sure you can do math with NSNumber -> although many people say NSDecimal is better. I say use floats, ints and doubles).
int pagenumber;
for(pagenumber = 0; pagenumber < 5; pagenumber++){
NSLog(#"%i", pagenumber);
}
then if you really need it in an NSNumber then do:
NSNumber *pagenumberns = [NSNumber numberWithInt:pagenumber];
In answer to your second question I have never had that problem, but try doing: [ImageView setOpaque:no] and [ImageView setBackgroundColor:[UIColor clearColor]];
Hope some of that helps.

Thank you for your answer, but I need to declare them globally in my ...ViewController.h & .m files because all my methods use them.
Is is possible to do it like that, or have I to #property and #synthesize the int?
FooViewController.h:
#interface FooViewController : UIViewController {
int *currentPage;
}
-(void)next;
-(void)changePage:(int)page;
FooViewController.m:
#implementation Post_GeheimnisViewController
#synthesize currentPage;
-(void)changePage:(int)page {
//do some stuff here
}
-(void)next {
currentPage++;
[self changePage:currentPage];
}
#end
Thank you for answering!
Le Milonkh

Related

xcode integer shows strange values

i created a Single View Application in XCode..
My Integer shows up strange values..
I declared the integer score with the value of 0 in the viewDidLoad method and
if two UIImageViews gets hitting each other the value of score gets every time 10 points bigger..
Game.h
#import <UIKit/UIKit.h>
#import <AudioToolbox/AudioToolbox.h>
int score;
#interface Game : UIViewController{
Game.m:
//score
score = 0;
Score.text = [NSString stringWithFormat:#"Score: %i", score];
Collision:
if(CGRectIntersectsRect(BulletFive.frame, Asteroid.frame)){
BulletFive.hidden = NO;
[self Score];
[self PlaceAsteroid];
Score:
-(void)Score{
Score.text = [NSString stringWithFormat:#"Score: %i", score];
score = score + 10;
if (score > HighScore) {
[[NSUserDefaults standardUserDefaults] setInteger:score forKey:#"HighScoreSaved"];
}
}
My problem:
If I click on a store button in the main menu and go to the game again, it shows up very strange values ​​like 16060 or 26110 in a UILabel. The storebutton has nothing to do with the other view controller. What could be wrong or what is wrong with XCode ?
Sorry for my english, Google Translator isn´t very helpful..
when you declare the int or NSInteger make sure, it's not a pointer.
Wrong :
int *variable1;
NSInteger *variable1;
Right one:
int variable1;
NSInteger variable1;
Please add more description, so I can help you further.

The Idea? creating sorted array from NSDictionary key values (with objects)

I know there are a whole bunch of questions that have been asked and answered in stackoverflow about the challenge of getting keys in an NSDictionary sorted by putting those keys into sort order in an array. I understand that objects are not stored in sort order within the actual dictionary and that is, I think, for reasons of efficiency or maybe memory management on the part of Foundation code.
I have been working on trying out examples from several answers out here and in apple documentation and blogs (some I can get to work, others not!) , but I can't seem to find an example that solves my confusion.
I think my confusion is that the examples I'm encountering both here, in apple documentation and in the different helpful blogs, all seem to have examples where there is just a key value pair and the second value is not an object - it's more like just a value. (However isn't it really an object at some level? I would think it is)
One example, that I couldn't get to work (Sorting an NSArray by an NSDictionary value ) , uses this idea
[array sortedArrayUsingComparator:^(NSDictionary *item1, NSDictionary *item2) {
NSString *age1 = [item1 objectForKey:#"age"];
NSString *age2 = [item2 objectForKey:#"age"];
return [age1 compare:age2 options:NSNumericSearch];
}];
I thought maybe this idea, specifying the key in a more specific manner, might be my problem.
I wonder if maybe I'm not communicating to the compiler what the key is, and what the object is, and that is why I'm getting an "unrecognized selector sent to instance" error.
..... Code Snips Follow .....
1)
I have a class called "Dog". A given dog object has several properties, including an NSString key.
My key is "licenseString" is an alphanumeric key - I'm also wondering if I should use decimalNumberWithString but that's not the question here
#property (strong,nonatomic) NSString *licenseString;
#property (strong, nonatomic) NSString *dogName;
#property (strong, nonatomic) NSString *whatMakesDogSpecial;
#property (strong, nonatomic) UIImage *dogPhoto;
2) I have an NSDictionary
#property (nonatomic, strong) NSDictionary *dogDictionary;
I hardcode information into the dogDictionary in this not very sophisticated way,
Dog *aDog;
// Dog one
aDog = [[Dog alloc]init] ;
aDog.licenseString = #"1";
aDog.dogName = #"Oscar";
aDog.whatMakesDogSpecial = #"This animal was found at the Mid-Penn humane society. He is super friendly, plays well with other dogs and likes people too. He enjoys fetching balls and frisbees too. He also goes to the park daily." ;
aDog.dogPhoto = [UIImage imageNamed:#"webVuMiniAppDogOscar.jpg"];
[self.dogDictionary setValue:aDog forKey:aDog.licenseString];
3) Then once I have several dog objects in my dogDictionary, I want to sort on the license tag values, so that I can populate a table view with dog names, but by order of their license tags.
BTW it seems that the compiler does recognize "vars.dogDictionary" which appears in the code snip below, because when I look at the debugger I can see that two valid instances are coming up from my dog dictionary. The debugger output is in an attachment
So, using ideas from a stackoverflow answer and the apple documentation, I write this
NSArray *sortedKeys = [vars.dogDictionary keysSortedByValueUsingComparator:
^NSComparisonResult(id obj1, id obj2) {
return [obj1 compare:obj2];
}];
NSLog(#" The sorted array is %#", sortedKeys);
And that's where my problem happens. I recognize that 0x1182f740 refers to "obj1" as shown in the debugger attachment
2013-08-06 15:13:58.276 SortDogLIcenseTags[3876:11303] -[Dog compare:]: unrecognized selector sent to instance 0x1182f740
(lldb)
Attachment is a picture showing debugger values - they don't like to paste very well
Here's how I resolved this challenge. It works and was pretty straightforward to integrate into my Master/Detail project
I know I found a tutorial on the web somewhere that led me to this solution , I'm sorry I can't find it now.
Note that sortedDogDictionaryArray and dogDictionaryArray are declared as properties in the .h file.
self.dogDictionaryArray = [vars.dogDictionary allValues];
// Sort
NSSortDescriptor *sortDescriptorDog =
[[NSSortDescriptor alloc] initWithKey:#"licenseString" ascending:YES];
NSArray *sortDescriptorsDogs =
[NSArray arrayWithObject:sortDescriptorDog];
self.sortedDogDictionaryArray =
[self.dogDictionaryArray sortedArrayUsingDescriptors:sortDescriptorsDogs];
NSLog(#"%#",self.sortedDogDictionaryArray );
int doggie;
Dog *someDogName;
NSLog(#"Sorted Order is...");
for (doggie = 0; doggie < [self.sortedDogDictionaryArray count]; doggie++) {
//NSLog(#"%#", [sortedArray objectAtIndex:i]);
//NSLog(#"%#", [sortedArrayDogs objectAtIndex:doggie]);
someDogName = [self.sortedDogDictionaryArray objectAtIndex:doggie];
//NSLog(#"name is %#", someDogName.dogName);
NSLog(#"name is %# tag is %#", someDogName.dogName, someDogName.licenseString);
}

analyze and memory alerts in xcode

I ran 'analyze" in xcode on a current iOS project to try to track down a freeze issue and there are a number of memory alerts that I don't understand (screenshot of one below).
What is going on there: I have a custom ObjC class extending NSObject; in the init method I alloc/init an NSMutableArray and then in a loop, populate it with NSMutableArrays. This nested array is declared as a property and released in dealloc(). It lives for the life of the app.
Am I doing this wrong? I don't understand the alert#3: # object not referenced in this execution path and has a retain count of +1.
Since my class allocs the outer array, it owns it and will clean it up. Do the inner arrays need to be released?
Thanks for any tips - still new at this.
EDIT/ADDITION
Trying to stamp out the additional memory warnings I am getting so I thought I would add to the question here in the event someone stumbles upon this w/ the same issue.
I am getting the following alert with the code below (the 2nd line "[keyArray addObject: etc"). What is going on: I have a custom class (Key - based on NSObject) that I instance and store in an array. Based on answers to my previous question, I guess my alloc increases the retain count and then when it is added to the array, the retain count isn't decremented - so the memory warning occurs.
What is the proper way to handle something like this? Use a placeholder like this:
Key * k = [[Key alloc] initKeyWithPath:path isBlackKey:NO]];
[keyArray addObject: k];
[k release];
Is that the proper way to do it? Or is there I way to write the custom class to return an autoreleased obj? (thanks and sorry to be so long winded!).
Potential leak of an object allocated on line 460
Method returns an Objective-C object with a +1 retain count (owning reference)
Object allocated on line 460 is not referenced later in this execution path and has a retain count of +1 (object leaked)
-(void) addOctaveToArraysWithTransform:(CGAffineTransform*)trans andPath: (CGMutablePathRef) path
{
path = [self createCF_keyUsingTransform: trans];
[keyArray addObject:[[Key alloc] initKeyWithPath:path isBlackKey:NO]];
}
Key.h
#import <Foundation/Foundation.h>
#import "Key.h"
#interface Key : NSObject {
#public
CGMutablePathRef keyPath;
BOOL isBlackKey;
NSValue * path;
int keyState;
BOOL needsRedraw;
}
#property (nonatomic, assign) int keyState;
#property (nonatomic, assign) BOOL needsRedraw;
#property (nonatomic) CGMutablePathRef keyPath;
-(id) initKeyWithPath:(CGMutablePathRef) aPath isBlackKey:(BOOL)flag;
-(CGMutablePathRef) getKeyPath;
#end
Key.m
#import "Key.h"
#implementation Key
#synthesize keyState, needsRedraw, keyPath;
-(id) initKeyWithPath:(CGMutablePathRef) aPath isBlackKey:(BOOL)flag
{
if ((self = [super init])){
isBlackKey = flag;
keyState = 0;
needsRedraw = NO;
keyPath = aPath;
CGPathRetain(keyPath);
}
return self;
}
-(CGMutablePathRef) getKeyPath
{
return keyPath;
}
#end
Yes, you have to release the inner arrays to balance the alloc/init. Remember the outer array will retain each inner array, and the outer array will presumably release those later. But here you are still responsible for the alloc/init you just did.
Hope that helps.
You have an allocation of an NSMutableArray on each iteration of the for-loop. Instead use: NSMutableArray array] which is a convenience method that return an autoreleased NSMUtableArray suitable for adding to fieldNotes which will retain the NSMutableArray.

NSArray multiply each argument

Is the there a way to multiply each NSNumber contained in the array by 10?
Here is what I have so far:
NSMutableArray *vertex = [NSMutableArray arrayWithCapacity:3];
[vertex addObject:[NSNumber numberWithFloat:1.0]];
[vertex addObject:[NSNumber numberWithFloat:2.0]];
[vertex addObject:[NSNumber numberWithFloat:3.0]];
[vertex makeObjectsPerformSelector:#selector(doSomethingToObject:)];
I am not sure what selector to use to do this, please help!
Not easily, no. You would have to loop through the entire thing and replace all those instances of NSNumber with new instances of NSNumber (NSNumber itself is immutable). So, for example:
for( int i = 0; i < [vertex count]; i++ )
[vertex replaceObjectAtIndex:i withObject:[NSNumber numberWithFloat:[[vertex objectAtIndex:i] floatValue] * 10.0f]];
Obviously this is rather hard to read. You are probably better off just using a regular, primitive array of floats if you are going to be manipulating them often (e.g., applying transformations to them).
Short answer - no.
NSNumber of merely a container for a primitive value. It does not do any mathematical work. The makeObjectsPerformSelector method can be used to tell each object in the array to do something. But the class of each of those objects has to have the method the selector is for. NSNumber also does not provide any method for changing the stored value. So even if you added a category to NSNumber to do the math, you would still have to replace the old value in the array with the newly computed one.
I think a better solution would be to add a category method to NSMutableArray to do the work. It would look through the contents, calculate each new value and then replace each array member with the new one.

Easiest way to format a number with thousand separators to an NSString according to the Locale

I can't seem to find an easy way to do it. The exact thing I need is:
[NSString stringWithFormat:#"%d doodads", n];
Where n is an int. So for 1234 I'd want this string (under my locale):
#"1,234 doodads"
Thanks.
For 10.6 this works:
NSNumberFormatter* numberFormatter = [[NSNumberFormatter alloc] init];
[numberFormatter setFormatterBehavior: NSNumberFormatterBehavior10_4];
[numberFormatter setNumberStyle: NSNumberFormatterDecimalStyle];
NSString *numberString = [numberFormatter stringFromNumber: [NSNumber numberWithInteger: i]];
And it properly handles localization.
I have recently discovered this one-liner:
[#1234567 descriptionWithLocale:[NSLocale currentLocale]]; // 1,234,567
Or in Swift 2:
1234567.descriptionWithLocale(NSLocale.currentLocale()) // 1,234,567
Swift 3/4:
(1234567 as NSNumber).description(withLocale: Locale.current)
Formatted per the question:
[#(n) descriptionWithLocale:[NSLocale currentLocale]];
Formatted without Objective-C literals:
[[NSNumber numberWithInt:n] descriptionWithLocale:[NSLocale currentLocale]];
This is the solution I was looking for when I asked the question. Available since iOS 2.0 and OS X 10.0, documented to return a string version of the number formatted as per the locale provided. stringValue is even documented to use this method but passing nil.
Seeing as it is my question and this fits my answer best, I am tempted to change the tick, but it seems cruel. Update I changed the tick, this answer is the answer.
The below doesn't address the locale, but it is a better way (in my opinion) of setting the thousand separator on the number formatter.
NSNumberFormatter *numberFormat = [[[NSNumberFormatter alloc] init] autorelease];
numberFormat.usesGroupingSeparator = YES;
numberFormat.groupingSeparator = #",";
numberFormat.groupingSize = 3;
Todd Ransom answered this perfectly.
I would just like to add (in a separate comment, so I can show some nicely formatted code), that if you plan to do this regularly, it's worth creating an NSString helper class.
So, create yourself an NSStringHelper.h containing this:
#import <Foundation/Foundation.h>
#interface NSString (NSStringHelper)
+(NSString*)formatWithThousandSeparator:(NSInteger)number;
#end
..and an NSStringHelper.m file containing this:
#import "NSStringHelper.h"
#implementation NSString (NSStringHelper)
+(NSString*)formatWithThousandSeparator:(NSInteger)number
{
// Format a number with thousand seperators, eg: "12,345"
NSNumberFormatter* numberFormatter = [[NSNumberFormatter alloc] init];
[numberFormatter setFormatterBehavior: NSNumberFormatterBehavior10_4];
[numberFormatter setNumberStyle: NSNumberFormatterDecimalStyle];
NSString *result = [numberFormatter stringFromNumber:[NSNumber numberWithInteger:number]];
return result;
}
#end
This gives you the perfect way to reuse this code in future projects.
#import "NSStringHelper.h"
NSInteger numOfUsers = 12345;
NSString* strNumberOfUsers = [NSString formatWithThousandSeparator:numOfUsers];
Cool, hey ?
Again, apologies for reposting Todd's answer (which was exactly what I was looking for !), but this is a great way to solve the problem, and have it ready to be used in your future XCode projects.
Use an NSNumberFormatter.

Resources