ARC warning - "Not safe to remove an unused autorelease" - iphone

I'm getting the following warnings and I haven't got a clue where to start, any ideas?
NSObject+Be.m:36:3: [rewriter] it is not safe to remove an unused 'autorelease' message; its receiver may be destroyed immediately
NSObject+Be.m:35:40: [rewriter] NSInvocation's getReturnValue is not safe to be used with an object with ownership other than __unsafe_unretained
NSObject+Be.m:36:4: ARC forbids explicit message send of 'autorelease'
The code came from here....
https://github.com/tylerneylon/moriarty/blob/c0d6daf65d86c22b8e5853aef00980f059c92fbc/NSObject%2BBe.m
#import "NSObject+Be.h"
#interface BeProxy : NSProxy {
id target;
}
+ (BeProxy *)beProxyForClass:(Class)class;
- (void)forwardInvocation:(NSInvocation *)anInvocation;
- (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector;
#end
#implementation BeProxy
+ (BeProxy *)beProxyForClass:(Class)class {
BeProxy *beProxy = [BeProxy alloc];
beProxy->target = [class alloc];
return beProxy;
}
//
// We assume the method called is an init method. The return value
// may be a new value for self.
- (void)forwardInvocation:(NSInvocation *)anInvocation {
[anInvocation setTarget:target];
[anInvocation invoke];
id object;
[anInvocation getReturnValue:(void *)&object]; //HERE
[object autorelease]; //HERE
[self release];
}
- (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector {
return [target methodSignatureForSelector:aSelector];
}
#end
//
#implementation NSObject (Be)
+ (id)be {
return [BeProxy beProxyForClass:[self class]];
}
+ (id)beInit {
return [[[self class] new] autorelease];
}
- (id)beCopy {
return [[self copy] autorelease];
}
#end

From the documentation:
NSObject+Be This category is designed to help with memory management.
Specifically, this makes it easy to only work with autoreleased
objects outside of a small number of ownership-allowed methods.
So the posted code is to help with manual retain count memory management. Don't compile it with ARC, then.

Related

how to implement Singleton Pattern in my IPhone project?

i am working on a project in wich i want to use Singleton Pattern model.
i want to any data model of my this project fallow Singleton Pattern.
i study the apple documentation regarding this
http://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/CocoaFundamentals/CocoaDesignPatterns/CocoaDesignPatterns.html#//apple_ref/doc/uid/TP40002974-CH6-SW6
and
http://www.oodesign.com/singleton-pattern.html
http://www.daveoncode.com/2011/12/19/fundamental-ios-design-patterns-sharedinstance-singleton-objective-c/
now i know my custom object classes should fallow the main rule of allocing a object but the i need the complete implementation like using of this class object
i am new in iphone app development so if i am wrong in any place in this Question please guide
Try this:
#implementation Singleton
+ (Singleton *)sharedInstance
{
static Singleton *obj = nil;
if (obj == nil)
obj = [[self alloc] init];
return obj;
}
#end
static MyClass *_sharedInstance;
+ (MyClass *)sharedMyClass
{
#synchronized([MyClass class]) {
if (_sharedInstance == nil)
[[self alloc] init];
return _sharedInstance;
}
return nil;
}
+(id) alloc
{
#synchronized([MyClass class]) {
NSAssert(_sharedInstance == nil, #"Attempted to allocate a second instance of MyClass.");
_sharedInstance = [super alloc];
return _sharedInstance;
}
return nil;
}
+ (id) allocWithZone:(NSZone *)zone
{
#synchronized([MyClass class]) {
NSAssert(_sharedInstance == nil, #"Attempted to allocate a second instance of MyClass.");
_sharedInstance= [super allocWithZone:zone];
return _sharedInstance;
}
return nil; //on subsequent allocation attempts return nil
}
- (id) copyWithZone:(NSZone *)zone
{
return self;
}
- (id)retain
{
return self;
}
- (NSUInteger)retainCount
{
return NSUIntegerMax;
}
- (oneway void)release
{
// Do nothing
}
- (id)autorelease
{
return self;
}
If you can target iOS 4 or above, I will take the following way:
//.h
+(MySingletonClass *)mySharedInstance;
-(void)doSomething;
//.m
+(MySingletonClass *)mySharedInstance {
static dispatch_once_t pred;
static MySingletonClass *shared = nil;
dispatch_once(&pred, ^{
shared = [[MySingletonClass alloc] init];
});
return shared;
}
-(void)doSomething
{
}
// override also the init if you want
To access it, do an #import MySingletonClass.h and use it wherever you want like the following:
MySingletonClass* mySharedInstance = [MySingletonClass mySharedInstance];
[mySharedInstance doSomething];
I want to any data model of my this project fallow Singleton Pattern.
Based on my experience, I would not abuse on singletons. The application could become difficult to maintain. To avoid this, put the data models within your singleton. You can access data model directly (creating properties around them) or using public methods (like for example doSomething) as wrappers.
Hope this helps.
This might be a useful reference: http://cocoasamurai.blogspot.com/2011/04/singletons-your-doing-them-wrong.html
Typically I create the object in the
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
method and have it live in that object. I make it available to the rest of the app with a macro:
#define APPLICATION ((AppDelegate*)([UIApplication sharedApplication].delegate))
as a readonly property of the app delegate
The benefit of this type of approach if you are in to mocking is that it is just another object property rather than a hidden static object.
I use:
#import <Foundation/Foundation.h>
#interface iCode_Framework : NSObject
#property (readonly, nonatomic) unsigned int iBufCapacity;
#property (readonly, nonatomic) unsigned int iPort;
#property (readonly, nonatomic) NSString * urlStr;
#end
#import "iCode_Framework.h"
static iCode_Framework * instance;
#implementation iCode_Framework
#dynamic iBufCapacity;
#dynamic iPort;
#dynamic urlStr;
- (unsigned int)iBufCapacity
{
return 1024u;
};
- (unsigned int)iPort
{
return 1978u;
};
- (NSString *)urlStr
{
return #"localhost";
};
+ (void)initialize
{
if (!instance) {
instance = [[super allocWithZone:NULL] init];
}
}
+ (id)allocWithZone:(NSZone * const)notUsed
{
return instance;
}
#end
Which is used exactly like a normal class, you call alloc and init! It is often convenient to assign to a variable to give a shorthand, because alloc and init are long to type, e.g.:
#import "iCode_FrameworkTests.h"
#import "iCode_Framework.h"
static iCode_Framework * c;
#implementation iCode_FrameworkTests
+ (void)initialize
{
c = [[iCode_Framework alloc] init];
}
- (void)setUp
{
[super setUp];
// Set-up code here.
}
- (void)tearDown
{
// Tear-down code here.
[super tearDown];
}
- (void)testSingletonNotNil
{
STAssertNotNil(c, nil);
}
- (void)testSingletonProperty
{
STAssertEqualObjects(c, [iCode_Framework alloc], nil);
}
- (void)testIBufCapacity
{
STAssertEquals(c.iBufCapacity, 1024u, nil);
}
#end
The advantage of this approach is it is used exactly like any other class and can therefore be mocked for testing.

singleton class in objective-C

I want to have one object that is initialized in the delegate and I want to be able to use this object anywhere across view controllers (doesn't depend on what view I am currently at). I am guessing the solution to this would be to have a singleton class, so far I have the following:
#interface LocationManager : NSObject <CLLocationManagerDelegate>{
NSDate *enter;
NSDate *exit;
CLLocationManager * manager;
}
#property (nonatomic, retain) NSDate * enter;
#property (nonatomic, retain) NSDate * exit;
- (BOOL)registerRegionWithLatitude:(double)latitude andLongitude:(double)longitude;
+ (LocationManager *)instance;
#end
#import "LocationManager.h"
#implementation LocationManager
#synthesize enter;
#synthesize exit;
#pragma mark - CLLocationManager delegate
static LocationManager *gInstance = NULL;
+ (LocationManager *)instance
{
#synchronized(self)
{
if (gInstance == NULL)
gInstance = [[self alloc] init];
}
return(gInstance);
}
#end
Is this correct? So all I need to do to access this is just to call instance? Inside LocationManager I also want to have only one CLLocationManager, called manager.. however, where do I initialize it so I only have one? Can I do the following? Most other singleton examples doesn't have any variables in the class, so that's where I got confused
+ (LocationManager *)sharedLocationManager
{
#synchronized(self)
{
if (lm == NULL){
lm = [[self alloc] init];
lm.manager = [[CLLocationManager alloc] init];
lm.manager.delegate = lm;
}
}
return(lm);
}
Basically -- yes.
Just a couple of small things:
static LocationManager *gInstance = NULL;
instead of NULL, you should use nil, it's a convention in Objective-C.
You should also overwrite alloc, new, copyWithZone:, and mutableCopyWithZone:. From Buck/Yacktman: "Cocoa Design Patterns", p. 153:
+ (id)hiddenAlloc
{
return [super alloc];
}
+ (id)new
{
return [self alloc];
}
+ (id)allocWithZone:(NSZone *)zone
{
return [[self sharedInstance] retain];
}
- (id)copyWithZone:(NSZone *)zone
{
[self retain];
return self;
}
- (id)mutableCopyWithZone:(NSZone *)zone
{
return [self copyWithZone:zone];
}
This way, your singleton object cannot be copied. You need to call hiddenAlloc from your instance method (by the way, the method to access a Singleton object is often called sharedInstance in Objective-C).
For other singleton styles with their pros and cons, check out this question.
Personally, I prefer this style (copied from one of the answers on that link):
static MySingleton *sharedSingleton;
+ (void)initialize
{
static BOOL initialized = NO;
if(!initialized)
{
initialized = YES;
sharedSingleton = [[MySingleton alloc] init];
}
}
In fact, there's a tried-and-true method to create singletons already. Download the SynthesizeSingleton.h file (from a Cocoa with Love article). It contains a massive amount of pre-processor code which will generate any singleton for you. Hit the article for more details.
Since the factory method "instance" is a class-level method, the #synchronized block should be
#synchronized([LocationManager class]) {
//}

Memory Management in Objective-C

I wanna ask if I allocated an instance variable for private use in that class, should i release it immediately on site, or i can depend on dealloc function. (because maybe i will need it on other function) ?
//Player.h
#interface Player : NSObject
{
NSMutableArray * objectArray;
}
- (void)awake;
- (void)add;
#end
//Player.m
#implementation Player : NSObject
{
-(id) init {
self = [super init];
if (self != nil ){
[self awake];
[self add];
}
return self;
}
- (void) awake {
objectArray = [[NSMutableArray alloc] init]; //is it cause leakage?
[objectArray addObject:#"foobar"];
}
- (void) add {
[objectArray addObject:#"foobar2"];
}
- (void) dealloc {
[objectArray release];
[super dealloc];
}
}
#end
or should i using property to set the objectArray iVar?
//Player.h
#interface Player : NSObject
{
NSMutableArray * objectArray;
}
#property (nonatomic,retain)NSMutableArray* objectArray;
- (void)awake;
- (void)add;
#end
//Player.m
#implementation Player : NSObject
{
-(id) init {
self = [super init];
if (self != nil ){
[self awake];
[self add];
}
return self;
}
- (void) awake {
self.objectArray = [[NSMutableArray alloc] init autorelease]; //cause leakage?
[objectArray addObject:#"foobar"];
}
- (void) add {
[objectArray addObject:#"foobar2"];
}
- (void) dealloc {
[objectArray release];
[super dealloc];
}
}
#end
if both of them doesn't cause a leakage, what type should i use?
should i always set iVar property, and access iVar value with self even if i only want to use it in this class?
I like to take the stance that if the instance variable should not be visible outside of the class then it should not be implemented as a property. But it's a personal thing that other developers may not agree with.
Either way you would need to release the objectArray in your classes dealloc method - which is what you're currently doing.
However you need to be careful with your awake method - if it's invoked multiple times then objectArray is leaked. This is the downside of not using properties. A use of self.objectArray = [[NSMutableArray alloc] init] here would have released the previous object.
In my opinion, you should only declare properties in your header if other objects are allowed to use them. There is no good reason why you would provide an -add: method (as in your example) that adds something to your array while also providing a getter for your array so other objects can manipulate it directly. It's called encapsulation.
If you do want to have the benefits of generated getters/setters for your implementation file, you can always use a class continuation (a nameless category) inside your implementation file and include your property declarations there. That way you get real, auto-generated properties that are only visible to your class' implementation.
Personally, I wouldn't use any getter or setter methods in your example. Just allocate the NSArray in your -init and release it in -dealloc. If this -awake method of yours might be called multiple times, just add an [objectArray removeAllObjects] call and you're sure to have an empty array without worrying about memory management.
It is very likely that memory will leak in your first example because you are not sending release to the previously set instance variable (if it already existed).
This is why you should use property setters - they handle all of this stuff for you.
Also, since you are obtaining ownership of the instance variable through the property (which is defined with the retain keyword), you will definitely leak memory if you don't send the instance variable the -release message in your -dealloc method.
So the verdict is that you should use the second example, not the first.

Subclass NSCache - App Singleton

I am writing an iPhone app and I want to create a NSCache singleton.
I am having trouble, here's the code that I have:
MyAppCache.h:
#import <Foundation/Foundation.h>
#interface MyAppCache : NSCache {}
+ (MyAppCache *) sharedCache;
#end
MyAppCache.m:
#import "SpotmoCache.h"
static MyAppCache *sharedMyAppCache = nil;
#implementation MyAppCache
+ (MyAppCache *) sharedCache {
if (sharedMyAppCache == nil) {
sharedMyAppCache = [[super allocWithZone:NULL] init];
}
return sharedMyAppCache;
}
+ (id)allocWithZone:(NSZone *)zone {
return [[self sharedCache] retain];
}
- (id)copyWithZone:(NSZone *)zone {
return self;
}
- (id)retain {
return self;
}
- (NSUInteger)retainCount {
return NSUIntegerMax; //denotes an object that cannot be released
}
- (void)release{
//do nothing
}
- (id)autorelease {
return self;
}
#end
When I want to add something or get something from the cache I might write:
#import "MyAppCache.h"
MyAppCache *theCache = [MyAppCache sharedCache];
Then:
NSData *someData = [[theCache objectForKey: keyString] retain];
Or:
[theCache setObject: someData forKey: keyString cost: sizeof(someData)];
The problem: the compiler complains 'MyAppCache' may not respond to 'method' for each of those lines.
I might be doing something completely wrong here - know how to make this work?
If the first listing is MyAppCache.h, then you're sticking #implementation in a header file, which isn't likely to do the right thing (the linker will probably complain).
If the first listing is MyAppCache.m, then you need to move the #interface into MyAppCache.h.
Also note that your code suffers from double-initing: [[MyAppCache alloc] init] is effectively [[[MyAppCache sharedCache] retain] init]. I don't know what NSCache does when inited twice, but it probably isn't good. I really wouldn't bother implementing copyWithZone: (I'm pretty sure objects aren't copyable by default), and you can just override allocWithZone: to raise an exception.
(And +sharedCache isn't thread-safe, which may or may not be an issue.)
OK, got it. I had a copy (previous version) of the MyAppCache.h and MyAppCache.m files still sitting in a folder in the project!

Newbie question: NSOperation for iphone SDK

Hi I got some problem with NSOperation .
I always got error at self = [super init]; (already use break point to find this)
it always return "Program received signal: EXC_BAD_ACCESS" all the time
//AddThread.h
#interface AddThread : NSOperation
{
NSString * str;
}
#property (nonatomic,retain) NSString * str;
-(id) initWithString:(NSString *) tmpStr;
#end
and for .m
//AddThread.m
#import "AddThread.h"
#implementation AddThread
#synthesize str;
- (id) initWithString:(NSString *)tmpStr
{
self = [super init];
if (self != nil)
{
self.str = tmpStr;
}
//NSLog(self);
//[super init];
return self;
}
- (void) main
{
NSLog(self.str);
}
- (void) dealloc{
[str release];
str = nil;
[super dealloc];
}
#end
well I stuck with this for while and if possible any resources ,articles things for basic example of NSoperation?
In your main method, you are calling NSLog(self.str) - While this will work if the object you pass in is a string, it won't work if you continue to try and log other objects. NSLog takes a format string as a parameter. If you just do NSLog(self) like you are in some of your commented code, and self is not a string, it'll crash because it expected a string. You should do NSLog(#"self: %#", self) the %# will print out the string returned by an objects description method.
Other than that, your init method looks fine, how exactly are you creating an instance of this object? Could you show the code for that? The problem may lie there.