I use cocos2dV3 i create some color:
#define color_red ccc3(253, 93, 70)
#define color_green ccc3(138,233,145)
#define color_yellow ccc3(230,219,37)
#define color_violet ccc3 (153,93,181)
#define color_turquoise ccc3(138,188,255)
#define color_default ccc3(225,225,225)
How i can save it as array : NSArray , NSmutableAraay ... ?
NSmutableArray * _arrColors =[[NSMutableArray alloc]init];
[_arrColors addObject:color_turquoise];
When i create array it alway show errors : " Sending 'ccColor3B' (aka 'struct _ccColor3B') to parameter of incompatible type 'id'"
What i do worng ?
Using cocos2d does not relieve you of the responsibility of knowing Objective-C. A ccColor3B is not an object - it is a struct - so it cannot be put into an NSArray. You could, if you really want to do this, wrap it in an object, something like this perhaps:
ccColor3B c = color_turquoise;
[_arrColors addObject:[NSValue valueWithBytes:&c objCType:#encode(ccColor3B)]];
Related
Hi i'm wondering how to use BOOL in macro in xCode?
like this:
#define IS_IPHONE5 (([[UIScreen mainScreen] bounds].size.height-568)?NO:YES)
#ifdef IS_IPHONE5
# define VIEW_HEIGHT_HALF 284
#else
# define VIEW_HEIGHT_HALF 240
#endif
doesn't work..
so only i can code like this?
#define VIEW_HEIGHT_HALF (([[UIScreen mainScreen] bounds].size.height-568)?240:284)
Thanks.
Hell again all. I seem to be unable to assign RGBA colors to the setBorderColor method of a layer.
I tried:
UIColor *myColor = [UIColor colorWithRed:51.0f/255.0f green:102.0f/255.0f blue:153.0f/255.0f alpha:1.0f];
[l setBorderColor:myColor];
Where l is of type CALayer and I get the warning: Incompatible pointer types sending 'UIColor*' to parameter of type 'CGColorRed ('aka 'struct CGColor *').
Do you know what the reason may be? The warning appears on the last line.
On the internet I find this code over and over again, so I thought it should be valid... Thanks!
CALayer.borderColor is defined as
#property CGColorRef borderColor;
Note that the type here is CGColorRef. You're trying to pass a UIColor*, which is a different beast. Luckily, UIColor has a property that returns a CGColorRef. Try using
[l setBorderColor:myColor.CGColor];
I have the following method in a NSDictionary category, to do a deep copy, which works fine.
I just upgraded from Xcode 4.1 to 4.2, and the Analyze function gives two analyzer warnings for this code, as indicated:
- (id)deepCopy;
{
id dict = [[NSMutableDictionary alloc] init];
id copy;
for (id key in self)
{
id object = [self objectForKey:key];
if ([object respondsToSelector:#selector(deepCopy)])
copy = [object deepCopy];
else
copy = [object copy];
[dict setObject:copy forKey:key];
// Both -deepCopy and -copy retain the object, and so does -setObject:forKey:, so need to -release:
[copy release]; // Xcode 4.2's Analyze says this is an incorrect decrement of the reference count?!
}
return dict; // Xcode 4.2's Analyze says this is a potential leak
}
Are these bugs in Xcode's analyzer, or are there changes I can make to avoid these warnings?
I'm not using ARC yet, though I am interested if there are additional changes needed to support ARC for this method.
Presumably, it is because deepCopy does not begin with the prefix copy.
So you may want to change to something like copyWithDeepCopiedValues (or something like that), and then see if the analyzer flags that.
Update
As Alexsander noted, you can use attributes to denote reference counting intent. This should (IMO) be the exception to the rule, and used rarely, if ever. Personally, I will not use attributes for objc methods because it is fragile.
The only attribute I have used so far has been consume, and every time I use these attributes has been in statically typed contexts (e.g. C functions and C++ functions and methods).
The reasons you should avoid attributes when possible:
1) Stick with conventions for the programmers' sake. The code is clearer and you do not need to refer to the documentation.
2) The approach is fragile. You can still introduce reference count imbalances, and attributes can be used to introduce build errors due to conflicts in attributes.
The following cases are all built with ARC enabled:
Case #1
#import <Foundation/Foundation.h>
#interface MONType : NSObject
- (NSString *)string __attribute__((objc_method_family(copy)));
#end
#implementation MONType
- (NSString *)string
{
NSMutableString * ret = [NSMutableString new];
[ret appendString:#"MONType"];
return ret;
}
#end
int main (int argc, const char * argv[])
{
#autoreleasepool {
id obj = nil;
if (random() % 2U) {
obj = [[NSAttributedString alloc] initWithString:#"NSAttributedString"];
}
else {
obj = [MONType new];
}
NSLog(#"Result: %#, %#", obj, [obj string]);
}
/* this tool's name is ARC, dump the leaks: */
system("leaks ARC");
return 0;
}
This program produces the following error: error: multiple methods named 'string' found with mismatched result, parameter type or attributes.
Great, the compiler's doing what it can to prevent these issues. What that means is that conflicts in attributes can introduce errors based on the translation. This is bad because when nontrivial codebases are combined and attributes conflict, you will have errors to correct and programs to update. This also means that simply including other libraries in translation units can break existing programs when attributes are used.
Case #2
Header.h
extern id NewObject(void);
Header.m
#import <Foundation/Foundation.h>
#import "Header.h"
#interface MONType : NSObject
- (NSString *)string __attribute__((objc_method_family(copy)));
#end
#implementation MONType
- (NSString *)string
{
NSMutableString * ret = [NSMutableString new];
[ret appendString:#"-[MONType string]"];
return ret;
}
#end
id NewObject(void) {
id obj = nil;
if (random() % 2U) {
obj = [[NSAttributedString alloc] initWithString:#"NSAttributedString"];
}
else {
obj = [MONType new];
}
return obj;
}
main.m
#import <Foundation/Foundation.h>
#import "Header.h"
int main (int argc, const char * argv[])
{
#autoreleasepool {
for (size_t idx = 0; idx < 8; ++idx) {
id obj = NewObject();
NSLog(#"Result: %#, %#", obj, [obj string]);
}
}
/* this tool's name is ARC, dump the leaks: */
system("leaks ARC");
return 0;
}
Ok. This is just bad. We've introduced leaks because the necessary information was not available in the translation unit. Here's the leaks report:
leaks Report Version: 2.0
Process 7778: 1230 nodes malloced for 210 KB
Process 7778: 4 leaks for 192 total leaked bytes.
Leak: 0x1005001f0 size=64 zone: DefaultMallocZone_0x100003000 __NSCFString ObjC CoreFoundation mutable non-inline: "-[MONType string]"
Leak: 0x100500320 size=64 zone: DefaultMallocZone_0x100003000 __NSCFString ObjC CoreFoundation mutable non-inline: "-[MONType string]"
Leak: 0x100500230 size=32 zone: DefaultMallocZone_0x100003000 has-length-byte: "-[MONType string]"
Leak: 0x100500390 size=32 zone: DefaultMallocZone_0x100003000 has-length-byte: "-[MONType string]"
note: the count may differ because we used random()
This means that because MONType is not visible to main(), the compiler bound the ARC properties to methods which were visible to the current TU (that is, string from declarations in Foundation, all of which follow convention). As a result, the compiler got it wrong and we were able to introduce leaks into our program.
Case 3
Using a similar approach, I was also able to introduce negative reference count imbalances (premature releases, or a messaged zombie).
note: Code not provided because Case #2 already illustrates how one can accomplish a reference count imbalance.
Conclusion
You can avoid all these problems and improve readability and maintainability by sticking with convention, rather than using attributes.
Bringing the conversation back to non-ARC code: Using attributes makes manual memory management more difficult for programmers' readability, and for the tools which are there to help you (e.g. compiler, static analysis). If the program is suitably complex such that the tools can't detect such errors, then you should reconsider your design, because it will be equally complex for you or somebody else to debug these issues.
Adding onto #Justin's answer, you can tell the compiler that -deepCopy returns a retained object by appending the NS_RETURNS_RETAINED attribute to the method's declaration like so:
- (id) deepCopy NS_RETURNED_RETAINED;
Alternatively, you can use explicitly control the method's "family" using the objc_method_family attribute like so:
- (id) deepCopy __attribute__((objc_method_family(copy)));
If you do this, the compiler will know that this method is in the copy family and returns a copied value.
Im trying to set an array for a timer program im writing in xcode. the values are in seconds, and what i want is to have a button in the interface builder that starts a timer with that number of seconds. This is the struct im trying to declare to provide the times in a .h header file. its just an array with 2 arrays in it, that i could call with #collegeTimes.constructive or something similar.
Thanks in advance!
- (NSDictionary *)debateTimes;
id debateTimes = [[NSDictionary alloc] initWithObjectsAndKeys:
[NSDictionary dictionaryWithObjectsAndKeys:
#"540", #"constructive",
#"360", #"rebuttal",
#"180", #"cx",
#"600", #"prep",
nil], #"collegeTimes",
[NSDictionary dictionaryWithObjectsAndKeys:
#"480", #"constructive",
#"300", #"rebuttal",
#"180", #"cx",
#"480", #"prep",
nil], #"hsTimes",
nil]; \\error is called here.
This is the struct im trying to declare to provide the times in a .h header file
This is the problem. You can not create constant NSDictionary objects (or most other NS objects, for that matter) outside of a function. One way to do what wou want would be as follows:
SomeThing.h
#interface SomeThing : NSObject
{
...
}
+ (NSDictionary *)debateTimes;
#end
SomeThing.m
static NSDictionary * staticDebateTimes = nil;
#implementation SomeThing
...
+ (NSDictionary *)debateTimes
{
if (staticDebateTimes == nil)
{
staticDebateTimes = [[NSDictionary alloc] initWithObjectsAndKeys:
[NSDictionary dictionaryWithObjects:...
}
return staticDebateTimes;
}
#end
This code would now be used externally as follows:
NSDictionary * debateTimes = [SomeThing debateTimes];
You cannot assign an objective-c object to a variable outside of a function. When a variable is assigned outside a function, its value becomes part of the executable. Since the value of the pointer to a object is not known until runtime, you cannot assign the object until it is created. (Constant NSStrings are an exception to this as they are also part of the executable)
The best way to store a structure like this would be to use an array of c structures.
typedef struct {
char *name;
NSTimeInterval constructive;
NSTimeInterval rebuttal;
NSTimeInterval cx;
NSTimeInterval prep;
} DebateTime;
DebateTime[2] = {{"collegeTimes", 540, 360, 180, 600},
{"hsTimes", 480, 300, 180, 480}};
You can also change the name and time intervals to constant strings if you wish.
How can I store a variable of type int32_t (e.g. for ABPropertyID) in an NSDictionary?
[NSNumber numberWithInt:...] doesn't seem to work.
Thanks
From the comments:
NSLog(#" %# %# ", [NSNumber numberWithLong:kABPersonFirstNameProperty], kABPersonFirstNameProperty);
Prints: 0 (null) Any ideas?
+[NSNumber numberWithInteger:] will hold a 32-bit number nicely on all 32-bit and 64-bit systems. +[NSNumber integerValue] will retrieve it. If you need it unsigned you can use ``+[NSNumber numberWithUnsignedInteger:]`.
I assume here that Dave's issue is specific to the kAB... constants--I may be mistaken in which case ignore the following :)
I believe that the issue here is not that you are using incorrect syntax; it's an order-of-initialization problem. I'm guessing that you are attempting this operation before having initialized the kAB... constants -- e.g., by calling ABAddressBookCreate(). Somewhat confusing the issue is the snippet:
NSLog(#" %# %# ", [NSNumber numberWithLong:kABPersonFirstNameProperty], kABPersonFirstNameProperty);
which should be:
NSLog(#" %# %d ", [NSNumber numberWithLong:kABPersonFirstNameProperty], kABPersonFirstNameProperty);
Here's my output -- prior to calling ABAddressBookCreate():
NSLog(#"Check: %d %d %d", kABPersonFirstNameProperty,kABPersonMiddleNameProperty,kABPersonLastNameProperty);
produces
Check: 0 0 0
after the call, the same log statement produces
Check: 0 6 1
As everyone else has said, NSNumber will work for this. However, there are two other options you should be at least vaguely aware of: CFDictionary (the same thing as NSDictionary under the hood, but it lets you store arbitrary pointers or pointer-sized integers) and NSMapTable.
In this case, using NSNumber seems like the best idea.
For harder cases, you can always use NSValue or NSData to put any type or pointer into a Objective-C object that can be stored in Cocoa collections.
int32_t myInt = 42;
NSValue *myValue = [NSValue value:&myInt withObjCType:#encode(int32_t)];
Number and Value Programming Topics for Cocoa: Using Values
NSValue Class Reference