This sounds ridiculous but its not working. Can someone see what I am missing?
I have a ViewController in which I defined a function called ProcessData. I am trying to call ProcessData from the viewDidLoad function but it does not see it. I declared it in the .h file and then defined it in the .m file. Here is the code.
ViewController.h
#interface ViewController : UIViewController
- (void) ProcessData: (NSString *)response;
#end
ViewController.m
#implementation ViewController
- (void)viewDidLoad
{
[super viewDidLoad];
[ProcessData nil];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (void) ProcessData: (NSString *)response
{
}
#end
To call a class / static function you have to write
[ViewController ProcessData: nil];
you have to call the method ProcessData on the class ViewController.
But what you have here is not a class / static method since it is - (void) instead of + (void). Your mistake is basically using the wrong syntax for calling any method. You call methods on objects like
[self ProcessData: nil];
instead of
[ProcessData: nil];
Final Note: method names should start with a lower character! The method should be called processData!
In this case, you haven't declared a class method, you've declared an instance method, so you'd call it by doing:
[self ProcessResponse: nil];
If you want to declare a class function, you need to use a + at the start if the declaration instead of a -:
+ (void) ProcessResponse: (NSString *)response;
You'd call this like this:
[ViewController ProcessResponse: nil];
As a side note, you should actually follow common convention by formatting like this:
+ (void)processResponse:(NSString *)response;
Note pascal case (no capital at the start of the method name), no space between return type and name, and no space between method name and the parameter type.
It is not a class method. It's a instance method. You have to call it like this:
[self ProcessResponse:nil];
Class method is defined with "plus" symbol (+), not a hyphen (-).
And method name should start with lowercase.
Related
e.g. a Person class has a property #property (strong, nonatomic) NSString *name; and two methods: an initialisation method - (instancetype)initWithName:(NSString *)name; and another method - (void)doSomethingWithName:(NSString *)name; as follows:
- (instancetype)initWithName:(NSString *)name
{
self = [super init];
if (self) {
self.name = name;
[self doSomethingWithName:name];
}
return self;
}
- (void)doSomethingWithName:(NSString *)name
{
NSLog(#"My name is: %#", name)
}
While in this case we're passing the local variable name from - initWithName: to - doSomethingWithName:, we could achieve the same result by passing self.name to - doSomethingWithName:. In fact, we could even rewrite the - doSomethingWithName: method as such:
- (void)doSomethingWithName
{
NSLog(#"My name is: %#", self.name)
}
Which of these approaches is considered best practice and why?
The two approaches do different things.
The form
- (void)doSomethingWithName:(NSString *)name
Is more like a global function. It takes a parameter and does something with it.
The form that doesn't take a parameter is an instance method. You ask an object to do something with its name.
Neither is better than the other. It's a question of need/intent.
It's like asking a chef "What's better, a whisk or a spatula?" Neither is better than the other. They are different tools suited to different tasks.
Both approaches could be problematic: you should not use accessors or message self in your init method.
Think about what can happen if some subclass overrides name accessor or doSomethingWithName. A subclass would expect a fully initialised object, while the reality is that its init method is yet to be executed...
I create two function with ObjectiveC, like:
- (void)showName:(NSString *)name, ...;
- (void)showTitle:(NSString *)title;
I can call showTitle: in my swift code, but can't compile if call showName:
Here is my code:
//Objective_C code:
#interface DemoObject : NSObject
- (void)showName:(NSString *)name, ...;
- (void)showTitle:(NSString *)title;
#end
#implementation DemoObject
- (void)showName:(NSString *)name, ... {
NSLog(#"name=%#", name);
}
- (void)showTitle:(NSString *)title {
[self showName:title, #""];
}
#end
//Swift Code:
var obj = DemoObject()
obj.showTitle("");
obj.showName(""); //compile error here
How to fix this problem. Because I use a third library, it contains Variable parameters functions.
Swift does not import C functions or Objective-C methods with varargs.
Any good API that has varargs functions also has an alternative form of the function that takes a va_list (e.g. printf has vprintf); or else it has an easy way to achieve the same thing by adding the arguments one by one.
I have a method called "pauseGame:" that pauses the game and a method called "resumeGame:"
I was wondering how I would call these in my app delegate I tried a few ways but in my debugger it ended up saying "pauseGame: method not found" and i imported my class i declared them in into my app delegate I was trying to figure out how I could solve this.
Here is the code I used for it:
- (void)applicationWillResignActive:(UIApplication *)application
{
[BPGameController pauseGame:];
}
- (void)applicationDidEnterBackground:(UIApplication *)application
{
[BPGameController pauseGame:];
}
- (void)applicationDidBecomeActive:(UIApplication *)application
{
[BPGameController resumeGame:];
}
Try this. and make sure the method resumeGame is working fine.
- (void)applicationDidBecomeActive:(UIApplication *)application {
[super applicationDidBecomeActive:application];
[BPGameController resumeGame:];
}
if resumeGame doesnt take any param it should just be
[BPGameController resumeGame];
lose the ":"
Are your pause/resume methods class methods or instance methods, in your code example it looks like you're calling them as class methods. Can you post more concrete code?
Signatures would help.
If those methods are instance methods, what you can do is add a property to YourAppDelegate, where it might look like:
#property (nonatomic, strong) BPGameController *bpgc;
And then when you instantiate the BPGameController somewhere else, set it on the appdelegate by doing
[(*YourAppDelegate)[[UIApplication sharedApplication] delegate] setBpgc:yourBPGC];
and then in the app delegate methods, you can reference your bpgc by self.bpgc and send messages like pauseGame, etc.
First your code is syntatically incorrect.AS
[BPGameController pauseGame:]; //do not call pauseGame: wihout any parameter.
instead consider calling it with nil if you do not have any value
[BPGameController pauseGame:nil];
or
If you function do not need parameters than remove from method definition.
Secondly I suspect you do not have pauseGame: declared in .h file
declare it in .h file.If not
Third if you want to call pauseGame this way[BPGameController pauseGame:nil]; than your method definition should start with + instead of - something like this.
+(void)pauseGame:(id)param{
}
If you post the definition of pauseGame: it will help more
EDIT: USE
- (void)applicationWillResignActive:(UIApplication *)application{
UIViewController *controller = self.window.rootViewController;
if([controller isKindOfClass:[UINavigationController class]]){
BPGameController *bpGameController;
for (id vc in [((UINavigationController*)controller) viewControllers])
{
if ([vc isKindOfClass:[BPGameController class]])
{
[((BPGameController *) vc) pauseGame];
break;
}
}
}
else if([controller isKindOfClass:[BPGameController class]]){
[((BPGameController *) controller) pauseGame];
}else{
//Not found
}
}
I have an helper class which has a function that makes an api call and get some json data and formats and returns an array. My TableViewController is trying to access that returned array. Yes, as you expected my tableviewcontroller viewDidLoad method is not able to access the array object returned by my helper class.
#interface MyHelperClass : NSObject
#property (nonatomic,retain)NSArray *myArray;
#end
#implementation MyHelperClass
#synthesize myArray;
- (NSArray *) returnArray{
// make api calls and return array
return myArray;
}
#end
#implementation MyTableViewController
{
- (void)viewDidLoad
{
[super viewDidLoad];
MyHelperClass *myhelper = [[MyHelperClass alloc]initWithPath:getSpacePath];
allTopics = (NSArray *)[myhelper returnArray];
NSLog(#"Load my Array%#",allTopics);
}
}
My question is, do I need to implement a delegate to pass the data around or is there any other way to pass around the data to my view controller?
P.S : I do not want to use global variable
Did this code give you any warning ?
You are trying to return an NSArray * from void returning method.
Modify it to
- (NSArray *) returnArray{ // YOU CAN RETURN id AS WELL, AS YOU ARE TYPE CASTING THE RESULT AT CALLING TIME
// make api calls and return array
NSLog (#"myArray :: %#", [myArray description]); // Post the output back here
return myArray;
}
Let me know if the problem persists.
EDIT
Set breakpoints at
allTopics = (NSArray *)[myhelper returnArray]; // AT - (void)viewDidLoad
and
return myArray; // AT HelperClass method
If first one it getting fired first, then You have to implement as #A-Live suggested in the comment.
Sorry for posting the answer so late. I figured out what the problem is. As #A-Live mentioned, the Rest API calls using AFNetworking is using async calls and hence it's not returning the array to the main thread within it's execution time. In my case,
-(void)viewDidLoad {
NSLog(#"I get called first");
MyHelper *helper = [[MyHelper alloc]init];
// returns array. However, [helper getData] is an async call under the hood. Hence myArray is nil
myArray = [helper getData];
}
To solve this problem, I took advantage of NSNotification.
#implementation MyHelper{
-(NSArray *)getData(){
[[NSNotificationCenter defaultCenter] postNotificationName:#"some.name.notification" object:JSON];
}
}
-(void)viewDidLoad(){
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(loadData:) name:#"some.name.notification" object:nil];
}
-(void)loadData:(NSNotification *)notif {
// You can access the JSON object passed by the helper in here
NSArray *myArray = [notif object];
// do whatever you want with the array.
}
I hope I am detailed enough. I hope this helps someone and saves a lot of headache.
How can I define a method that can be called from anywhere, in every viewcontroller class?
I have a method that brings me a json file, and i want it to be reusable, since i have several json calls on my app.
Can you help me?
You can add it through a category:
EDIT
Create a new .h .m file pair and in the .h file:
#interface UIViewController(JSON)
-(void) bringJSON;
-(void) fetchData:(NSData*) data;
# end
Then in the .m file:
#implementation UIViewController(JSON)
-(void) bringJSON {
dispatch_async(dispatch_get_global_queue( DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
[NSData dataWithContentsOfURL:yourURL];
[self performSelectorOnMainThread:#selector(fetchData:)
withObject:data waitUntilDone:YES];
});
}
-(void) fetchData:(NSData*) data {
//parse - update etc.
}
#end
Where I'm just assuming that you'll be returning an NSArray, you can put any method there and extend all UIViewControllers. The method bringJSON will be available to all UIViewControllers and its subclasses.
I believe you are thinking about a static method which would be defined with the "+" symbol.
+ (String) yourFunctionName:(NSInteger)someValue .....
Then you could call it anywhere with the class name first:
[YourClassName yourFunctionName:5];
If you need to have a function that access an object that needs to be instantiated then you will want to do a singleton pattern.
Use a + sign before the return type of the method.
For example:
+ (void) Name: (NSString *) str{
}
I plused the first answer as it is a way of creating (essentially) another object with methods that can be called from any file that includes that object.
Remember also that objective-c also is simply just C. You can have .c files included that are simply contain ANSI-C routines that can be called also.