SAFELY_RELEASE in ViewDidUnLoad - iphone

is there any difference between the two methods?
```
// MACRO FUNCTION
#define SAFELY_RELEASE(__POINTER) { [__POINTER release]; __POINTER = nil; }
// C FUNCTION
void SAFELY_RELEASE(id __POINTER) {
[__POINTER release]; __POINTER = nil;
}
```

Yes. The function won't do what you expect it to, because the pointer will have been passed into it by value, rather than by reference.
Imagine this:
- (void)method {
id object = [[NSObject alloc] init];
SAFELY_RELEASE( object );
}
SAFELY_RELEASE gets object. It can send it messages, but setting it to nil will not change its value in method.
An equivalent function would be:
void SAFELY_RELEASE(id *__POINTER) {
[*__POINTER release]; *__POINTER = nil;
}
Then you'd use it by using:
SAFELY_RELEASE( &object );
The macro has another downside, though: Xcode's refactoring tools will probably not be able to change the parameter inside. For instance:
#interface Foo {
NSObject *var;
}
#implementation Foo
- (id)init {
if (( self = [super init] )) {
var = [[NSObject alloc] init];
}
return self;
}
- (void)dealloc {
SAFELY_RELEASE(var);
[super dealloc];
}
If you try to rename var using the refactor tool, you'll probably find that it won't be able to rename the var in dealloc.
Really, unless you have a really good reason to do this you should be using ARC.

void SAFELY_RELEASE(id __POINTER) is guaranted to __POINTER be an releasable object.
Both of them is wrong, because __POINTER = nil; will have no effects. You should nil it in object (controller)

I was using one of these macros, then I cam across this post.
Makes sense that you don't want to set to nil while in development as you want it to crash on a dealloc reference and not sending it to nil.

Related

Two Independent Delegate Methods in a Class

I have two independent delegate methods in a class.
- (void)delegateMethod1:(id)data {
self.data = data;
}
- (void)delegateMethod2 {
[someClass sendData:self.data];
}
Now, this works fine sometimes but the other times, delegateMethod2 gets called before delegateMethod1.
I need to know how to manage this elegantly so that the line: [someClass sendData:self.data]; gets called only when both delegateMethod1 and delegateMethod2 have been called.
I know I can do it by using a variable to set to something on each delegate call but there has to be an elegant way to do this.
Any help?
Remembering which delegate has been called seems the easiest and cleanest solution to me.
But you can make it symmetric by moving the check to a separate method, so that
is does not matter which delegate is called first:
- (void)checkIfDataCanBeSent {
if (self.method1called && self.method2called) {
[someClass sendData:self.data];
}
}
- (void)delegateMethod1:(id)data {
self.method1called = YES;
// ...
[self checkIfDataCanBeSent];
}
- (void)delegateMethod2 {
self.method2called = YES;
// ...
[self checkIfDataCanBeSent];
}
(I have assumed that all delegate methods are called on the main thread, otherwise
one would have to add some synchronization.)
I believe, using a indicative variable to be the most elegant way to get over this. But this variable has to be kept in the delegate caller object.
Pseudo-type explanation
#interface DelegateCaller
{
BOOL hasCalled1stMethod;
}
#property(nonatomic,weak) id delegate;
#end
#implementation DelegateCaller
-(void)in_some_process_1
{
[self.delegate delegateMethod1]; //call
hasCalled1stMethod = YES; //set indicator
}
-(void)in_some_process_2
{
if(hasCalled1stMethod)
{
[self.delegate delegateMethod2]; //call
hasCalled1stMethod = NO; //reset indicator for reuse, if required.
}
}
#end
This way you'll not have to maintain any variable in the delegate itself, because the regulation of calling is maintained in the caller-object itself.
Another case:
If the delegateMethod1 is called from some object1 and the delegateMethod2 is called from some other object2, then again the indicative variable method is the most elegant way (in this limited scenario)
Pseudo-type explanation:
#interface ClassDelegateObject //aka the callee
{
BOOL hasCalledMethod1;
}
#end
#implementation ClassDelegateObject
-(void)delegateMethod1:(NSData*)data
{
self.data = data;
hasCalledMethod1 = YES; //set the indicator.
}
-(void)delegateMethod2
{
//here relying on the self.data!=nil will not be fruitful
//in case the self.data is not nil and hold some previous garbage data then
//this logic will fail.
if(hasCalledMethod1)
{
[someClass sendData:self.data];
hasCalledMethod1 = NO; //reset the variable for reuse if required.
}
}
#end
I would suggest that you rethink how the code works. Maybe you can check if there is no data and if so send it once it is ready:
- (void)delegateMethod1:(id)data {
self.data = data;
if (self.dataShouldBeSentWhenReady) {
[self sendData];
}
}
- (void)delegateMethod2 {
if (self.data) {
[self sendData];
} else {
[self setDataShouldBeSentWhenReady:YES];
}
}
- (void)sendData {
[self setDataShouldBeSentWhenReady:NO];
[someClass sendData:self.data];
}

How to write OCUnit Test Case

I want to write unit tests using Apple's default SenTestingKit for the below method:
- (NSDictionary*)getValueTags {
return _tags;
}
- (NSString*)getFlag {
NSString* jo = #"";
for (NSString* key in _tags) {
jo = [jo stringByAppendingFormat:#"%#=\"%#\"&", key, [_tags objectForKey:key]];
}
if ([jo length] > 0) {
jo = [jo substringToIndex:[jo length] - 1];
}
return jo;
}
I used default SenTesting
- (void)setUp
{
[super setUp];
// Set-up code here.
}
- (void)tearDown
{
// Tear-down code here.
[super tearDown];
}
-(void)testValueTags{
}
-(void)testGetFlag{
}
I am new to writing TestCases, I need some guideline for sample methods to write test cases
A test case has four distinct phases:
set up
exercise
verify
tear down
Some of these phases can be empty. For example, most tear down happens automatically if you use ARC.
When you're starting, don't put anything into the setUp or tearDown methods. Just write a single unit test. Here's a worked example. (I'm going to change the names, because Objective-C idiom is not to use the word "get". So instead of getFlag let's just call it flag.) I'm going to call the class `Example, and I'll use ARC. And I use the abbreviation "sut" for "system under test".
- (void)testFlagGivenOneEntry
{
// set up
Example *sut = [[Example alloc] init];
[sut setTags:#{ #"key1" : #"value1" }];
// execute & verify
STAssertEqualObjects([sut flag], #"key1=\"value1\"", nil);
}
That's one test. Let's add another.
- (void)testFlagGivenTwoEntries
{
// set up
Example *sut = [[Example alloc] init];
[sut setTags:#{ #"key1" : #"value1",
#"key2" : #"value2" }];
// execute & verify
STAssertEqualObjects([sut flag], #"key1=\"value1\"&key2=\"value2\"", nil);
}
At this point, we have duplicate code: the creation of the sut. Now we can promote the variable up to an instance variable of the class. Then we create it in setUp and destroy it in tearDown:
#interface ExampleTest : SenTestCase
#end
#implementation ExampleTest
{
Example *sut;
}
- (void)setUp
{
[super setUp];
sut = [[Example alloc] init];
}
- (void)tearDown
{
sut = nil;
[super tearDown];
}
- (void)testFlagGivenOneEntry
{
[sut setTags:#{ #"key1" : #"value1" }];
STAssertEqualObjects([sut flag], #"key1=\"value1\"", nil);
}
- (void)testFlagGivenTwoEntries
{
[sut setTags:#{ #"key1" : #"value1",
#"key2" : #"value2" }];
STAssertEqualObjects([sut flag], #"key1=\"value1\"&key2=\"value2\"", nil);
}
#end
For a more involved example, see Objective-C TDD: How to Get Started.

run time catch method [duplicate]

I am developing an Objective-C application, and what I want to do, is something like the following:
+-----------------+ +---------------+
| Some Object | <---------- | Synchronize |
|(Not Thread Safe)| | Proxy |
+-----------------+ / +---------------+
/
/ Intercepts [someobject getCount]
/ #synchronize (someObject)
/
[someObject getCount] /
+----------------------+
| Some Calling Object |
+----------------------+
What I've asking is, how can I create an object in objective-c, that intercepts messages sent to another object, in order to perform code before the message is sent to that object.
Some things that I think will not work:
Categories (I need this to only happen for certain instances of a class)
Rewriting the object (I don't have access to the source of the object)
Method swizzling (once again, this need to only happen for certain instances of a class)
You would implement an NSProxy that forwards messages to your non-thread-safe object.
Here is a nice writeup of message forwarding in Objective-C, and here is Apple's documentation.
To handle thread safety, it depends on what you need. If your non-thread-safe object must run on a specific thread then you can use a NSRunLoop on said thread to serialize messages to that object.
Here is an example of using NSInvocation in conjunction with NSRunLoop. In that example they're using performSelector:withObject:afterDelay: but to use it with performSelector:onThread:withObject:waitUntilDone: would be very similar.
Otherwise, just use a single NSRecursiveLock in your proxy.
If you know exactly what instances should have the behavior you are trying to achieve you can go with method swizzling and call the base implementation if the instance is not the one you are looking for.
You can have a global shared object that lists the "interesting" instances and use it in the swizzling implementation whether you have to call the base one or your custom one.
So, I bit the bullet, and decided to make my own proxy class. To subclass, you simply override the 'forwardInvocation:' message, and you call any code you need there, before calling [super forwardInvocation:]. Please not this will NOT work with vardic methods, as NSInvocation doesn't work with vardic methods.
#import <Foundation/Foundation.h>
#import <objc/runtime.h>
#import <objc/objc.h>
#import <objc/message.h>
#interface RJProxy : NSObject {
#private
NSObject *target;
}
#property(readwrite, retain) NSObject *target;
-(NSObject *) getTarget;
#end
#implementation RJProxy
#synthesize target;
-(NSMethodSignature *) methodSignatureForSelector:(SEL)aSelector
{
if (objc_getAssociatedObject(self, "isProxy"))
{
IMP NSObjectImp = [NSObject instanceMethodForSelector:#selector(methodSignatureForSelector:)];
NSMethodSignature *methodSignature = (NSMethodSignature *) NSObjectImp(self, #selector(methodSignatureForSelector:), aSelector);
if (methodSignature)
return methodSignature;
return [target methodSignatureForSelector:aSelector];
}
else
{
Class subClass = self->isa;
#try {
self->isa = objc_getAssociatedObject(self, "realSuperclass");
return [super methodSignatureForSelector:aSelector];
}
#finally {
self->isa = subClass;
}
}
}
-(void) forwardInvocation:(NSInvocation *)anInvocation
{
if (objc_getAssociatedObject(self, "isProxy"))
{
Class subClass = target->isa;
target->isa = objc_getAssociatedObject(self, "realSuperclass");
[anInvocation invokeWithTarget:target];
target->isa = subClass;
}
else
{
Class realSuperclass = objc_getAssociatedObject(self, "realSuperclass");
Class subclass = self->isa;
self->isa = realSuperclass;
if ([self respondsToSelector:[anInvocation selector]])
{
[anInvocation invokeWithTarget:self];
}
else
{
[self doesNotRecognizeSelector:[anInvocation selector]];
}
self->isa = subclass;
}
}
-(NSObject *) getTarget
{
if (objc_getAssociatedObject(self, "isProxy"))
{
return target;
}
return self;
}
#end
BOOL object_setProxy(NSObject *object, RJProxy *proxy);
BOOL object_setProxy(NSObject *object, RJProxy *proxy)
{
proxy.target = object;
Class objectClass = object_getClass(object);
Class objectSub = objc_allocateClassPair(objectClass, [[NSString stringWithFormat:#"%s_sub%i", class_getName(objectClass), objc_getAssociatedObject(objectClass, "subclassTimes")] UTF8String], 0);
objc_setAssociatedObject(objectClass, "subclassTimes", (id) ((int) objc_getAssociatedObject(objectClass, "subclassTimes") + 1), OBJC_ASSOCIATION_ASSIGN);
objc_registerClassPair(objectSub);
Class proxyClass = object_getClass(proxy);
Class proxySub = objc_allocateClassPair(proxyClass, [[NSString stringWithFormat:#"%s_sub%i", class_getName(proxyClass), objc_getAssociatedObject(proxyClass, "subclassTimes")] UTF8String], 0);
objc_setAssociatedObject(proxyClass, "subclassTimes", (id) ((int) objc_getAssociatedObject(proxyClass, "subclassTimes") + 1), OBJC_ASSOCIATION_ASSIGN);
objc_registerClassPair(proxySub);
object_setClass(object, proxySub);
object_setClass(proxy, proxySub);
objc_setAssociatedObject(object, "isProxy", (id) NO, OBJC_ASSOCIATION_ASSIGN);
objc_setAssociatedObject(proxy, "isProxy", (id) YES, OBJC_ASSOCIATION_ASSIGN);
objc_setAssociatedObject(object, "realSuperclass", objectClass, OBJC_ASSOCIATION_ASSIGN);
objc_setAssociatedObject(proxy, "realSuperclass", proxyClass, OBJC_ASSOCIATION_ASSIGN);
return NO;
}
#interface SynchronizeProxy : RJProxy
#end
#implementation SynchronizeProxy
-(void) forwardInvocation:(NSInvocation *)anInvocation {
#synchronized ([self getTarget])
{
[super forwardInvocation:anInvocation];
}
}
#end
int main (int argc, const char * argv[])
{
#autoreleasepool {
NSArray *arrayToSynchronize = [NSArray arrayWithObjects:#"This, is, a, test!", nil];
SynchronizeProxy *myProxy = [SynchronizeProxy new];
object_setProxy(arrayToSynchronize, myProxy);
// now all calls will be synchronized!
NSLog(#"Array at address 0x%X with count of %lu, and Objects %# ", (unsigned) arrayToSynchronize, [arrayToSynchronize count], arrayToSynchronize);
[myProxy release];
[arrayToSynchronize release];
}
return 0;
}

how to stop creating object Instance when its not need

The class do have
-(void) trackByPage : (NSString*) pageName {
TrackPage *track_p;
= [[TrackPage alloc] init];
track_p.page1 = #"welcome";
track_p.page2= self.String1;
[track_p release];
}
I am accessing from controller class this method.
- (void)viewDidLoad {
[super viewDidLoad];
TrackPageMeasurement *trackPage_Measurement = [[TrackPageMeasurement alloc]init];
[trackPage_Measurement trackByPage:#"Msg"];
[trackPage_Measurement release];
}
- (void)selectedDataValue {
TrackPageMeasurement *trackPage_Measurement = [[TrackPageMeasurement alloc]init];
[trackPage_Measurement trackByPage:#"DataValue"];
[trackPage_Measurement release];
}
I am accessing that through another class. trackByPage. by passing string ..
Each time i am accessing each time object instance is created how to stop those thing.
selectedDataValue shouldn't be calling [super viewDidLoad]; The code doesn't exactly inspire me with confidence; it looks to me more like that you want to retrieve some tracking object rather than creating a new one each time. Do you know what a singleton is?
Using a singleton would look more like:
TrackPage *track_p = [TrackPage instance];
track_p.page1 = #"welcome";
track_p.page2 = self.String1;
How about
TrackPage *track_p;
if(track_p==nil)
{
track_p= [[TrackPage alloc] init];
track_p.page1 = #"welcome";
track_p.page2= self.String1;
}
[track_p release];

I'm getting two errors having to do with incorrect Xcode grammar

(MemberPage *)initWithString: (NSString *) s {
self = [super init];
if ( self ) {
//DO STUFF;
UserNAME.text = s;
}
}
return self;
I'm getting:
use of undeclared identifier initWithString
expected ; before : token
I've haven't been able to fix this after an hour so far,
Thanks
There are a few tweaks that will solve this. See comments inline:
// Add '-' to show it is instance method
-(MemberPage *)initWithString: (NSString *) s {
self = [super init];
if ( self ) {
//DO STUFF;
UserNAME.text = s;
}
// Include this inside of the brace
return self;
}
As a note, by convention your instance variables should begin with a lower case letter and then use camel casing. So, UserNAME.text should be userName.text. The compiler expects this.
You are missing the - token before your method signature and the return statement is outside the method body. Should look like:
- (MemberPage *)initWithString: (NSString *) s {
self = [super init];
if ( self ) {
//DO STUFF;
UserNAME.text = s;
}
return self;
}
You may also eventually have a problem on the UserNAME.text = s line but without seeing your header file its hard to tell.