I have an SKShapeNode and I am setting the shape as a RoundedRectangle but when I analyze the code I am receiving a warning that states there is a potential leak of an object.
My interfaceFile is as follows:
#import <SpriteKit/SpriteKit.h>
#interface letterSpace : SKShapeNode
-(instancetype) initWithCharacter:(NSString *)character xPosition:(float)x yPosition:(float)y device:(NSString *)device;
#property(nonatomic, assign) BOOL occupied;
#property(nonatomic, assign) BOOL whiteSpace;
#property(nonatomic, retain) NSString *character;
#property (atomic) float secondLineX;
#property (atomic) float secondLineY;
#end
And then the implementation is
#import "letterSpace.h"
#implementation letterSpace
-(instancetype) initWithCharacter:(NSString *)character xPosition:(float)x yPosition:(float)y device:(NSString *)device{
self = [super init];
if(self){
if ([device isEqualToString:#"IPHONE"]) {
[self setPath:CGPathCreateWithRoundedRect(CGRectMake(0, 0, 30, 2), 1, 1, nil)]; // Potential Leak of an object on this line
_secondLineX = 36*8;
_secondLineY = -36;
}else{
[self setPath:CGPathCreateWithRoundedRect(CGRectMake(0, 0, 60, 3.5), 1, 1, nil)]; // Potential Leak of an object on this line
_secondLineX = 575;
_secondLineY = -71;
}
self.strokeColor = [UIColor clearColor];
if ([character isEqual: #" "]) {
self.occupied = TRUE;
self.fillColor = [UIColor clearColor];
self.character = character;
self.whiteSpace = TRUE;
}else{
self.whiteSpace = FALSE;
self.occupied = FALSE;
self.fillColor = [UIColor colorWithRed:80.0f/255.0f
green:227.0f/255.0f
blue:194.0f/255.0f
alpha:1];
}
if (y <8) {
self.position = CGPointMake(x, 0);
}
else{
self.position = CGPointMake(x - _secondLineX, _secondLineY);
}
self.name = character;
}
return self;
}
#end
Any ideas how to solve this leak? or what's causing it?
When you use Core Foundation objects, you own an object if you call function that*:
have “Create” embedded in the name;
have "Copy" embedded in the name;
*however, this does not apply to a methods that return Objective-C objects.
If you are an owner of an object, you must relinquish ownership when you have finished using it using CFRelease (or the corresponding type-specific variants).
In ARC environment, the compiler does not automatically manage the lifetimes of Core Foundation objects. You must call CFRetain and CFRelease (or the corresponding type-specific variants)
Also you need to tell the compiler about the ownership of the object if you cast between Objective-C and Core Foundation objects:
__bridge transfers a pointer between Objective-C and Core Foundation with no transfer of ownership;
__bridge_retained or CFBridgingRetain casts an Objective-C pointer to a Core Foundation pointer and also transfers ownership to you. You are responsible for calling CFRelease or a related function to relinquish ownership of the object;
__bridge_transfer or CFBridgingRelease moves a non-Objective-C pointer to Objective-C and also transfers ownership to ARC. ARC is responsible for relinquishing ownership of the object.
So, in your case:
path has a type of CGPathRef, which from a Core Graphics frameworks that adopts to Core Foundation memory management conventions. So, we apply the rule "If you call the method that have a "Create" embedded in the name - you own it". It is not matter whether it is Manual (in manual you must) or Automatic (ARC environment does not automatically manage the lifetimes of Core Foundation objects) Memory Management you must release this object.
CGPathRef path = CGPathCreateWithRoundedRect(CGRectMake(0, 0, 30, 2), 1, 1, nil);
[self setPath:path];
CGPathRelease(path);
or you can use Cocoa analogue bezierPathWithRoundedRect:(NSRect)rect xRadius:(CGFloat)xRadius yRadius:(CGFloat)yRadius.
Also, I would recommend you to use NULL instead of nil in CGPathCreateWithRoundedRect.
Memory Management Programming Guide for Core Foundation
Advanced Memory Management Programming Guide
Transitioning to ARC Release Notes
Related
i dont know what is wrong with code below
#import "ViewController.h"
#interface ViewController ()
{
NSMutableArray * buttons;
NSMutableArray * centers;
int counter;
int index;
}
#end
#implementation ViewController
-(void)viewDidLoad
{
[super viewDidLoad];
buttons = [NSMutableArray new];
centers = [NSMutableArray new];//error here expected identifier or '('
}
//other methods
#end
i am getting two arrays, xcode works normally for buttons but it gives error for centers when creating. What may be the problem?
note: i tried deleting derived data.
Okay, I know this isn't the question you asked, but I would like to suggest an alternative to instantiating variables in viewDidLoad. It's something called "lazy instantiation", and it looks like this:
- (NSMutableArray *)buttons
{
if (!_buttons) _buttons = [NSMutableArray new];
return _buttons;
}
When you need to reset the array, just set it to nil. It won't reallocate the memory until you call it again.
P.S. Whatever you do, don't call self.buttons within that method, or you will create an infinite loop.
I'm unable to create an NSData object from a UIColor (with a pattern) created with the factory method
[UIColor colorWithPatternImage:image]
works fine for standard UIColor objects. Wondering if there is another way to save a UIColor with a pattern into Core Data.
I am using the following code to archive the UIColor (with a pattern)...
- (id)transformedValue:(id)value {
NSData *data = [NSKeyedArchiver archivedDataWithRootObject:value];
return data;
}
and these are the errors I'm receiving...
-[NSKeyedArchiver dealloc]: warning: NSKeyedArchiver deallocated without having had -finishEncoding called on it.
Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Only support RGBA or the White color space, this method is a hack.'
Oh Yes! I got it. With a lot of help from the following people/posts...
Gave me the idea to use associatedObjects
Explanation of associatedObjects
and method swizzling
Create a category on UIColor. Use an Associated Object to set a reference to the pattern image in the UIColor instance (kind of like a dynamic property), don't forget to import <objc/runtime.h>. When you create your UIColor color = [UIColor colorWithPatternImage:selectedImage], also set the associated object on the color [color setAssociatedObject:selectedImage].
Then implement custom encodeWithCoder and initWithCoder methods in the category to serialize the UIImage.
And finally do some method swizzling in the main.m file so you can invoke the original UIColor encodeWithCoder and initWithCoder methods from within your UIColor Category. Then you don't even need to write your own Value Transformer for Core Data because UIColor implements the NSCoding protocol. Code below...
UIColor+patternArchive
#import "UIColor+patternArchive.h"
#import <objc/runtime.h>
#implementation UIColor (UIColor_patternArchive)
static char STRING_KEY; // global 0 initialization is fine here, no
// need to change it since the value of the
// variable is not used, just the address
- (UIImage*)associatedObject
{
return objc_getAssociatedObject(self,&STRING_KEY);
}
- (void)setAssociatedObject:(UIImage*)newObject
{
objc_setAssociatedObject(self,&STRING_KEY,newObject,OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
- (void)encodeWithCoderAssociatedObject:(NSCoder *)aCoder
{
if (CGColorSpaceGetModel(CGColorGetColorSpace(self.CGColor))==kCGColorSpaceModelPattern)
{
UIImage *i = [self associatedObject];
NSData *imageData = UIImagePNGRepresentation(i);
[aCoder encodeObject:imageData forKey:#"associatedObjectKey"];
self = [UIColor clearColor];
} else {
// Call default implementation, Swizzled
[self encodeWithCoderAssociatedObject:aCoder];
}
}
- (id)initWithCoderAssociatedObject:(NSCoder *)aDecoder
{
if([aDecoder containsValueForKey:#"associatedObjectKey"])
{
NSData *imageData = [aDecoder decodeObjectForKey:#"associatedObjectKey"];
UIImage *i = [UIImage imageWithData:imageData];
self = [[UIColor colorWithPatternImage:i] retain];
[self setAssociatedObject:i];
return self;
}
else
{
// Call default implementation, Swizzled
return [self initWithCoderAssociatedObject:aDecoder];
}
}
main.m
#import <UIKit/UIKit.h>
#import <objc/runtime.h>
#import "UIColor+patternArchive.h"
int main(int argc, char *argv[])
{
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
// Swizzle UIColor encodeWithCoder:
Method encodeWithCoderAssociatedObject = class_getInstanceMethod([UIColor class], #selector(encodeWithCoderAssociatedObject:));
Method encodeWithCoder = class_getInstanceMethod([UIColor class], #selector(encodeWithCoder:));
method_exchangeImplementations(encodeWithCoder, encodeWithCoderAssociatedObject);
// Swizzle UIColor initWithCoder:
Method initWithCoderAssociatedObject = class_getInstanceMethod([UIColor class], #selector(initWithCoderAssociatedObject:));
Method initWithCoder = class_getInstanceMethod([UIColor class], #selector(initWithCoder:));
method_exchangeImplementations(initWithCoder, initWithCoderAssociatedObject);
int retVal = UIApplicationMain(argc, argv, nil, nil);
[pool release];
return retVal;
}
Since UIColor implements the NSCoding protocol, you don't have to write your own transformer but can just tell Core Data to use the NSKeyedUnarchiveFromDataTransformerName transform (which is the default.)
To my knowledge, that transform handles patterns in UIColor objects.
Im sure theres a way to convert uicolor into hex strings, you could simply store the hex string has "NSString" in core data model.
How can I convert RGB hex string into UIColor in objective-c?
This is the follow up to my question earlier about the Xcode 4 static analyzer. It is not specifically a problem since I have the code now working as it needs to, but I am just wondering how things are working behind the scenes. Consider the following code:
- (IBAction)cameraButtonPressed:(id)sender
{
if ([UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypeCamera] == NO)
{
return;
}
UIImagePickerController *cameraUI = [[UIImagePickerController alloc] init];
cameraUI.sourceType = UIImagePickerControllerSourceTypeCamera;
cameraUI.allowsEditing = NO;
cameraUI.delegate = self;
[self presentModalViewController:cameraUI animated:YES];
NSString *theString = [[NSString alloc] initWithString:#"cameraButtonPressed done"];
NSLog(#"%#", theString);
}
To me, the way this code looks, there are two objects (cameraUI and theString) that need to be released. However, the analyze function correctly identifies that only theString needs to be released at the end of the method, even though both objects are returned from alloc-init, which in my experience has always meant that you release when you are done.
The question I have here is, how does the static code analyzer know not to flag cameraUI as an issue?
I would call this a bug with the static analyzer. The UIImagePickerController instance assigned to cameraUI should be released or autoreleased in a non-garbage-collected environment (like iOS).
From wikipedia explanation about thread-safety,thread safe codes can be run in multithreads.
For iOS 3.x, UIKit is not thread safety, since 4.0, UIKIt is thread safety.
In our implementations, we can use synchronized to build thread safety codes. My questions about thread safety are:
1). How to detect thread safety coding issue with instruments tools or other ways ?
2). Any good practices to write thread safety codes for iOS development ?
since 4.0, UIKIt is thread safety.
Basically, UIKit is not thread-safe. Only drawing to a graphics context in UIKit is thread-safe since 4.0.
1) Hmm, I also want to know about that :-)
2) How about Concurrency Programming Guide?
To make a non thread-safe object thread safe, consider using a proxy (see the code below). I use it for example for NSDateFormatter, which is not a thread safe class, when parsing data in a background thread.
/**
#brief
Proxy that delegates all messages to the specified object
*/
#interface BMProxy : NSProxy {
NSObject *object;
BOOL threadSafe;
}
#property(atomic, assign) BOOL threadSafe;
- (id)initWithObject:(NSObject *)theObject;
- (id)initWithObject:(NSObject *)theObject threadSafe:(BOOL)threadSafe;
#end
#implementation BMProxy
#synthesize threadSafe;
- (id)initWithObject:(NSObject *)theObject {
object = [theObject retain];
return self;
}
- (id)initWithObject:(NSObject *)theObject threadSafe:(BOOL)b {
if ((self = [self initWithObject:theObject])) {
self.threadSafe = b;
}
return self;
}
- (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector {
return [object methodSignatureForSelector:aSelector];
}
- (void)forwardInvocation:(NSInvocation *)anInvocation {
if (self.threadSafe) {
#synchronized(object) {
[anInvocation setTarget:object];
[anInvocation invoke];
}
} else {
[anInvocation setTarget:object];
[anInvocation invoke];
}
}
- (BOOL)respondsToSelector:(SEL)aSelector {
BOOL responds = [super respondsToSelector:aSelector];
if (!responds) {
responds = [object respondsToSelector:aSelector];
}
return responds;
}
- (void)dealloc {
[object release];
[super dealloc];
}
#end
Dear community.
I have NSOperation subclass with property:
#property(readwrite, getter=isCancelled) BOOL cancelled;
from where i was create object of subclass NSObject (from init):
database = [[[MySQLIXC alloc] initWithQuene:iQuene andCarrier:startForCarrier withState:cancelled] retain];
In this custom object i try to declare local iVar:
#interface MySQLIXC : NSObject {
BOOL _currentQueueStatus;
In init:
- (id)initWithQuene:(NSUInteger)quene andCarrier:(NSString *)carrierName withState:(BOOL)currentQueueStatus;
_currentQueueStatus = currentQueueStatus;
But currentQueueStatus allways null.
Can somebody suggest a problem location?
1) you should avoid re-declaring implemented subclass interface for your additions (e.g. -[NSOperation isCancelled] exists)
2) it is very unusual to start with two retain counts:
database = [[MySQLIXC alloc] initWithQuene:iQuene andCarrier:startForCarrier withState:cancelled];
[otherThingThatHoldsAReference setDatabase:database];
instead of:
database = [[[MySQLIXC alloc] initWithQuene:iQuene andCarrier:startForCarrier withState:cancelled] retain];
3) _currentQueueStatus is not null it's a BOOL, which is a signed char. it should be 0 (NO) or 1 (YES).
4) what is currentQueueStatus? more code would help you receive more specific answers.
EDIT: updated for clarification in response to comments
/* things would look different if you subclass MONOperation */
#interface MONOperation : NSOperation
{
#private
MySQLIXC * sqlIxc;
BOOL didCancelDatabaseRequest;
}
/*
do not use isCancelled for your name - NSOperation declares this method, and
its implementation is well defined. this would override the implementation
and likely cause runtime errors.
specifically, NSOperation/NSOperationQueue uses cancel and isCancelled in its
interface and state. if you must cancel, then call cancel from cancelDatabaseRequest.
you may override cancel, but call [super cancel] in your implementation.
*/
#property (readonly) BOOL didCancelDatabaseRequest;
#property (retain) MySQLIXC * sqlIxc;
#end
#implementation MONOperation
/* ... */
- (BOOL)didCancelDatabaseRequest
{
return didCancelDatabaseRequest;
}
- (void)cancelDatabaseRequest /* in this example, there is no sense making cancelDatabaseRequest publicly visible */
{
/* for example */
assert(self.sqlIxc);
self.sqlIxc = nil;
didCancelDatabaseRequest = YES;
[self cancel]; /* do this rather than overriding NSOperation's cancellation interfaces in your subclass */
}
- (void)main
{
NSAutoreleasePool * pool = [NSAutoreleasePool new];
assert(self.sqlIxc);
self.sqlIxc.doStuff;
if (self.sqlIxc.didTimeout || self.sqlIxc.couldNotAccessFile) {
[self cancelDatabaseRequest];
}
else {
/* use the result */
}
[pool release];
}
#end