Use of undeclared identifier in my Objective-C code - objective-c

I'm a newbie to Objective-C and I'm trying to a access a global variable and I can not. What have I missed?
This is the variable: getShoppingCartRequestSuccessful
-(void)setShoppingCartGetRequestWithNetworkManager//watch the bag button->4 {
//Sets the loading indicator on. [self setLoadingIndicator];
//NetworkManager [[NetworkManager sharedManager] setDelegate:self];
//GetShoppingCart [[NetworkManager sharedManager]
requestGetShoppingCartWithParameters:[[ServerRequestBuilder sharedManager]
returnParametersDictionaryForGetShoppingCartWithCustomerID:strCustomerID]];
//update shopping cart-getShoppingCartRequestSuccessful [[GlobalVariables sharedManager] setObject:shoppingCartSummary
forKey:GLOBALVARIABLES_SHOPPINGCARTSUMMARY overwrite:YES];
}
This is the argument I want to pass:
-(void)getShoppingCartRequestSuccessful:(MNShoppingCart *)shoppingCart withOpertaion:(AFHTTPRequestOperation *)operation
{
if (shoppingCart) {
MNShoppingCartSummary *shoppingCartSummary = [[MNShoppingCartSummary alloc] initShoppingCartSummaryWithCustomerID:[[shoppingCart getCustomerInfoModel] getCustomerInfoID] andWithTotalAmountOfProducts:[shoppingCart getAmountOfProducts] andWithTotalPrice:[shoppingCart getTotalPrice]];
[[GlobalVariables sharedManager] setObject:shoppingCartSummary forKey:GLOBALVARIABLES_SHOPPINGCARTSUMMARY overwrite:YES];
NSLog(#"price val call Func #6");
[self setShoppingCartScreenWithShoppingCartModel:shoppingCart withDeliveryAreaChange:YES];
}

getShoppingCartRequestSuccessful is an instance method. Not a variable. Instance method is basically a "function" that can return something or even nothing (void) to the caller. In your case, is returning a void.
When you see instance method, like this
-(void)goDoSomething:(NSString *)name
To call it, if the method is in the same Viewcontroller (ie. Class), then you do it like this:
[self goDoSomething:#"Moran"];
As you can see, goDoSomething expects ONE parameter of type NSString, so you have to give it that. This will execute the method.
In your case,
-(void)getShoppingCartRequestSuccessful:(MNShoppingCart *)shoppingCart withOpertaion:(AFHTTPRequestOperation *)operation
means, you need to pass 2 parameters to it.
To use this method, you call:
[self getShoppingCartRequestSuccessful:yourCart withOpertaion:operation];
you need to have the yourCart and operation ready before passing it to this method.
ps. withOpertaion is wrong spelling.

Related

NSTimer selector method not getting accessed from another class

I have one class (Sample) defined in sample.m where I have the following methods:
-(NSInteger)refreshValue:(id)sender{
//Do some thing here and return value.
NSLog(#"Print something here");
return something;
}
-(IBAction)monitorValue:(id)sender {
NSLog(#"In here");
timer = [NSTimer scheduledTimerWithTimeInterval: 1
target: self
selector: #selector(refreshValue:)
userInfo: nil
repeats: YES];
}
Now I have another class, test.m. From test.m, I do this:
Sample *test = [Sample alloc]
[test monitorValue:(id)sender]
WHen I run this code, I can see the monitor value method get called. But the refreshValue method never gets called from within monitorValue, which is what I want. If I call monitorValue from sample.m, then everything works. It just does not work when called from a different object.
Any ideas ? Thanks.
Your timer callback method signature is not correct. Per the documentation, it should be:
- (void)timerFireMethod:(NSTimer*)theTimer

What to do with useless init?

This is currently what I have for my init,
- (id)init
{
self = [super init];
if (self) {
self.url = [[NSURL alloc] init];
self.blurb = [[NSString alloc] init];
self.author = [[NSString alloc] init];
}
return self;
}
It does nothing, but I have another method called initWithObject: that will use its argument to fill up the instance variables url, blurb, and author. I don't know what I should be doing with this init. Should I throw an exception? What other options do I have?
If you want to override your standard -init method you could either return nil (if you do not want -init to be used) or do:
- (instancetype)init
{
return [self initWithObject:nil];
}
If you want to stop the use of -init completely you can tag it as an unavailable attribute or use NSAssert:
// .h
// ...
- (instancetype)init UNAVAILABLE_ATTRIBUTE;
// ...
// .m
- (instancetype)init
{
NSAssert(NO, #"This method should not be used");
return nil;
}
You can use either UNAVAILABLE_ATTRIBUTE or NSAssert(), but if you use UNAVAILABLE_ATTRIBUTE you need some kind of implementation of -init, even if it just returns nil.
You don't have to have a plain init—you can simply have your initWithObject: method. If you're doing any basic setup that will remain the same 80% of the time, or if you have some common code in all your initializers, you can override init, but you are not required to.
Also consider changing your initWithObject: name to be more specific, to something like initWithPost: (I'm assuming this is some kind of blog-entry fetcher based on your ivars) so it's more apparent what object is desired.
I think you misinterpreted what you read. I don't think you would throw an exception. You could; however, leak memory. If your initWithObject: method looks like this:
- (id)initWithObject:(id)obj {
if ((self = [self init])) {
self.url=[obj url];
self.blurb=[obj blurb];
self.author=[obj author];
}
return self;
}
And you would be perfectly fine. You could get an exception if your object was instantiated with -init and you used a variable which was assigned, assuming it was real. So in your subsequent methods be sure to check that the objects exist before using them.
If you made your object with -init rather than -initWithObject this could throw an exception:
- (void)dealloc {
[url release];
[blurb release];
[author release];
[super dealloc];
}
The rule that Apple has established for Cocoa programming is that every class must have one initializer method which is the "Designated Initializer". Every other initializer for the class must call that D.I.* The D.I. itself must call the superclass's D.I. Generally, the initializer with the greatest number of arguments (the one that most completely specifies the state of the new object) is the D.I.
In your case, with the bare init, and initWithObject:, the second would likely be the D.I. You would therefore override init to call initWithObject: with some default argument:
- (id) init {
return [self initWithObject:[Object objectWithURL:[NSURL URLWithString:#"http://www.apple.com"]
blurb:#""
author:#""]];
}
This will result in a sort of dummy object, which is correctly initialized with useless data. (Outside of ARC, be sure to watch the memory management of the default argument(s) -- you want to use an autoreleased/unowned object(s).)
*Sometimes an exception is made for initWithCoder:.
If you have any method that you don't want called and that you don't want your subclass to support, throwing an exception in a Debug build is perfectly reasonable.

Using a block object instead of a selector?

I have:
[self schedule:#selector(tickhealth)];
And tickHealth method only has one line of code:
-(void)tickHealth
{
[hm decreaseBars:0.5];
}
is it possible to use block objects in place of a selector. for example something like:
[self schedule:^{
[hm decreaseBars:0.5];
}];
As Caleb & bbum correctly pointed out you cannot simply pass a block to your existing (and unchanged) - (void)schedule:(SEL)selector; method.
You can however do this:
Define block type:
typedef void(^ScheduleBlock)();
Change schedule: method to be defined similar to this:
- (void)schedule:(ScheduleBlock)block {
//blocks get created on the stack, thus we need to declare ownership explicitly:
ScheduleBlock myBlock = [[block copy] autorelease];
//...
myBlock();
}
Then call it like this:
[self schedule:^{
[hm decreaseBars:0.5];
}];
Further Objective-C block goodness compiled by Mike Ash that will get you kickstarted with blocks:
http://mikeash.com/pyblog/friday-qa-2008-12-26.html
http://mikeash.com/pyblog//friday-qa-2009-08-14-practical-blocks.html
http://mikeash.com/pyblog/friday-qa-2011-06-03-objective-c-blocks-vs-c0x-lambdas-fight.html
You can't just pass a block in place of a selector because those two things have different types. However, if you have control over the -schedule: method, you can easily modify it to accept and use a block in place of a selector.

How to call my method in cocoa, self doesn't work

Working on a program that will record some things from the webcam when a user presses physical buttons connected to the mac via phidgets. Have call methods on other places in my app simply doing [self method: input], but on one place it doesn't work. What could be wrong?
This is the method i want to run if i get inputchange in my program.
Also i do -(void)reportButton2:(NSInteger)inputVal:(NSInteger)inputInd; in my .h file.
-(void)reportButton2:(NSInteger)inputVal:(NSInteger)inputInd {
//NSLog(#"phidget för port = %%d med signal %%d", ind, val);
if(inputVal == 1)
{
NSError* error;
NSFileManager* deleteMgr = [NSFileManager defaultManager];
NSString* path = #"/Users/Shared/tempFile.mov";
[deleteMgr removeItemAtPath:path error:&error];
[mCaptureMovieFileOutput recordToOutputFileURL:[NSURL fileURLWithPath:#"/Users/Shared/tempFile.mov"]];
}
else if(inputVal == 0)
{
[mCaptureMovieFileOutput recordToOutputFileURL:nil];
}
}
The code below give me result if imput from the buttons change. Here i just can't seem to call reportbutton2.
If i try to use [self reportButton2..] in gives me "Use of undeclared identifier 'self'"
int gotInputChange(CPhidgetInterfaceKitHandle phid, void *context, int ind, int val) {
what to do here?
return 0;
}
The problem is that gotInputChange is a C function not a Objective C method and so has no udea what self is as it does not belong to a class.
for [self reportButton2... = to work it needs to be a method in your class
I usually put something like this at the top of callbacks like gotInputChange:
MyObject *self = (id)context;
Then I can use self throughout the function as if it were a method.
The other thing being in a function makes harder is asserting conditions. The regular assertion macros, such as NSAssert and NSParameterAssert, require both of the implicit arguments to every method (self is one of them) to exist. In a C function, you must use NSCAssert, NSCParameterAssert, etc. instead.
You can also use your delegate.
SomeNameAppDelegate *delegate = (SomeNameAppDelegate *)[[NSApplication sharedApplication] delegate];
[delegate yourMethodName];
It works like in example if your target method in AppDelegate class. But when you have an access to delegate, you can create a pointers to necessary classes and use them over delegate.
Quickest but not soo nice way is to make your Class a singleton and access it from the gotInputChange function.
Okay thanks! Din't have any clue that it was C would never have solved it by myself. Did some googeling and this one did the trick for me.
[(id)context performSelectorOnMainThread:#selector(reportButton2:)withObject:[NSArray arrayWithObjects:[NSNumber numberWithInt:ind], [NSNumber numberWithInt:val], nil] waitUntilDone:NO];

Objective-C Blocks - use as an object

With reference to the code below, once a block has been put into an array, how could you take that block object and run the actual code in the block.
Another Question: If I call a method in a block like below, does that block encapsulate the code in that method or capture the signature of the method and call it that way?
-(void)blockCalledMethod
{
NSLog(#"Hello World");
}
-(void)programStart
{
NSArray * array = [[NSArray alloc] initWithObjects:[[^ { [self blockCalledMethod];} copy] autorelease],nil];
id pointerToBlock = [array lastObject];
}
Call it like this:
void (^pointerToBlock)(void) = [array lastObject];
pointerToBlock(); // because ^ {} is void(^)(void)
You cannot declare pointerToBlock as an id if you want to call it directly, because the compiler has to recognize it as a block type and not just an object.
If I call a method in a block like above, does that block encapsulate the code in that method or capture the signature of the method and call it that way?
I should think self refers to the calling class.