I'm doing Universal Application and it has isPad() method inside of main.m class. I want to use this method inside of both AppDelegates (iPad, iPhone).
Yes, it is currently accessible in a AppDelegates
**From AppDelegate
- (void)applicationDidFinishLaunching:(UIApplication *)application
{
if (isPad()) // isPad() method locates main.m and is accessible through delegate.
// but I gets warning message 'Implicit declaration of function isPad()
{
}
}
From main.m
BOOL isPad();
int main(int argc, char *argv[])
{ //detecting iPad and iPhone }
BOOL isPad()
{
// method that detects the device.
}
Why Am I getting warning message 'Implicit declaration of function isPad()?
Do I need to #include main.m inside of AppDelegate.m ? then how to ?
I want to be use this method in any other classes.
[[UIApplication sharedApplication].delegate isPad()];
Yes, I made mistake!!
I have used two delegate one for pad, and other for phone.
It could be done in just using one delegate.
Sorry everyone!
Why have you put your isPad() method in main.m? Why can't you put that method in your shared app delegate, and that way all classes inside your app can access it? I would recommend simply creating your isPad() method inside of your shared app delegate and avoiding putting it in main.m all together.
You are trying to call isPad() function on Objective C object.
You defined your isPad() function inside main(), what's that?
The warning message you receive in the AppDelegate code is because there is no function prototype for isPad. You can get rid of the warning by putting BOOL isPad(); in your AppDelegate implementation file.
I strongly recommend you move this logic out of the main file.
Related
I attended to a watchkit hackathon yesterday and I had some problems regarding calling a method on an NSObject class which uses the Google Maps API and send local notifications. If I call this method from my Watchkit extension, the code doesn't compile, but If I call from the ViewController, for example, everything works perfectly
#import "InterfaceController.h"
#import "Methods.h"
#interface InterfaceController()
#end
#implementation InterfaceController
- (instancetype)initWithContext:(id)context {
self = [super initWithContext:context];
if (self){
// Initialize variables here.
// Configure interface objects here.
NSLog(#"%# initWithContext", self);
}
return self;
}
- (IBAction)butRoute
{
Methods *mt = [[Methods alloc]init];
[mt notif:#"ARRIVING!"];
//***** If I call this method, my code won't compile!!! *****
}
- (void)willActivate {
// This method is called when watch view controller is about to be visible to user
NSLog(#"%# will activate", self);
}
- (void)didDeactivate {
// This method is called when watch view controller is no longer visible
NSLog(#"%# did deactivate", self);
}
#end
The error I get is:
Check the target for your Methods class and make sure it is in your watch kit extensions target.
Alternately, look at building a framework for your shared classes. https://developer.apple.com/videos/wwdc/2014/?id=416
I don't know what xcode version you are using but take into account that the initWithContext method is no longer valid. You should be using:
- (void)awakeWithContext:(id)context
And you shouldn't be overwriting it, just use it.
just remove #import line and replace it with WatchKit framework.
I am new to Objective-C and i was trying out a sample program in Threads from the book "Learn Objective-C for java developers".
I am getting 6 errors on the function definition.
Its with errors.
Is there any link that gives good threading example for beginners like me.
Thread2.m
#import <Foundation/Foundation.h>
#import "Process.h"
int main (int argc, const char * argv[]) {
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
Process* process = [Process new];
NSProgressIndicator* indicator = [NSProgressIndicator new];
Heartbeat* heartbeat = [Heartbeat startHeartbeatProcess:process withIndicator:indicator];
[heartbeat stop];
[pool drain];
return 0;
}
Process.h
#import <Foundation/Foundation.h>
#interface Process : NSObject {
}
#property double progress;
#end
#interface NSProgressIndicator : NSObject {
}
#end
#interface Heartbeat : NSObject {
#public
NSThread* thread;
NSProgressIndicator* indicator;
Process* monitor;
}
+(Heartbeat*)startHeartbeatProcess:(id)process withIndicator:(NSProgressIndicator*)progress;
-(void)stop;
-(void)heartbeatThread:(id)ignored;
-(void)updateIndicator;
#end
Process.m
#import "Process.h"
#implementation Process
+(Heartbeat*)startHeartbeatProcess:(id)process withIndicator:(NSProgressIndicator*)progress {
Heartbeat* heartbeat = [Heartbeat new];
heartbeat->monitor = process;
heartbeat->indicator = progress;
heartbeat->thread = [[NSThread alloc]initWithTarget:heartbeat selector:(heartbeatThread:) object:nil]; //'heartbeatThread' undeclared
[heartbeat->thread start];
return heartbeat;
}
-(void)stop {
[thread cancel]; //thread undeclared
}
-(void)heartbeatThread:(id)ignored {
while (![thread isCancelled]) {
//thread undeclared
[self performSelectorOnMainThread:#selector(updateIndicator) withObject:nil waitUntilDone:YES];
[NSThread sleepForTimeInterval:0.5];
}
}
-(void)updateIndicator {
[indicator setDoubleValue:monitor.progress];
}
#end
Could not find the setDoubleValue method in the class NSProgressIndicator.
Could not find the setDoubleValue method in the class NSProgressIndicator
For this one, that's because NSProgressIndicator is part of AppKit (the Cocoa GUI library), and you're only linking against Foundation (which is the non-GUI stuff). It seems in your code you've attempted to define an interface for NSProgressIndicator yourself, but you haven't declared any methods on it — that's why it's complaining about not being able to find the setDoubleValue method.
What should you do about it? Well, if you're wanting to use Cocoa's GUI stuff, you need to structure your program in the way Cocoa's GUI system expects. In Xcode, if you create a new Cocoa application it should give you a sample project to build on. In particular, your main() function should contain return NSApplicationMain(argc, (const char **) argv);, which handles starting a run loop to receive events.
If you just want to learn about threading, it may be better to abandon trying to get GUI stuff in the same program, and adapt your code to just print stuff to the console instead.
I find it hard to believe that this is an example from a book, since it seems fairly fundamentally broken!
Other errors I found when I tried running it:
Expected ')' before ':' token
This is on the line heartbeat->thread = [[NSThread alloc]initWithTarget:heartbeat selector:(heartbeatThread:) object:nil];.
The problem there is the syntax for declaring a selector: instead of just saying selector:(heartbeatThread:), you need to say selector:#selector(heartbeatThread:).
'thread' undeclared (first use in this function'
In your header file, you claimed that the class Heartbeat has a method called stop. (That is, you defined -(void)stop; in the #interface section for the Heartbeat class).
However, you implemented that method in the #implementation section for the Process class.
You'd make it easier for yourself if you had one pair of .h and .m files per class, rather than trying to cram multiple class definitions into a single pair of files. That way you could make sure you were putting the implementation of the stop method in the correct class's .m file.
property 'progress' requires method '-progress' to be defined - use #synthesize, #dynamic or provide a method implementation
In the implementation for process you defined an #property called progress. If you define a property, you either have to write getters and setters for it yourself, or write #synthesize progress within your implementation. Doing the latter is equivalent to Objective-C generating your getters and setters automatically at runtime.
thread is not a member of the Process class; it belongs to the Heartbeat class. You have to define a member in the Process class to keep a reference on the Heartbeat instance so you can call methods on its thread member.
Could someone please explain how control of execution flows in an iOS application? I know that UIApplicationMain is called first from main. Then what? What is the relationship between my defined methods and main? Is it all event-driven or can there be some structured sequence?
I don't mean to be so vague, I just need to know where to start. Perhaps I'm looking at this in the wrong way.
For example, in C++ I would do something like:
#include "myMethods.h"
int main (int argc, char * const argv[]) {
Method1(); // Initialization
Method2(); // Opening views and options
Method3(); // Meat of the program
return 0;
}
Thanks in advance.
So, as you mentioned, the main() function in main.m is the starting point, which then calls UIApplicationMain(). If you check the docs, you'll see that UIApplicationMain takes four arguments:
argc,
*argv[],
*principalClassName
*delegateClassName.
The first two of those are just the argument count and variable list passed from main(). But the third and fourth arguments are pointers to NSStrings. The third argument specifies which class should be UIApplication. Unless you intend on subclassing UIApplication, you specify nil for the third argument. The fourth argument specifies which class should be UIApplication's delegate class, which will respond to anything specified in the UIApplicationDelegate Protocol. You don't have to muck with this directly, as it's included in all of the Xcode templates:
int main(int argc, char *argv[])
{
#autoreleasepool {
return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
}
}
Don't let the NSStringFromClass([AppDelegate class])) bit throw you. That's just a fancy way of specifying the fourth argument so that the right delegate gets called should you later change the name of AppDelegate.m.
UIApplication starts the main event loop and calls -application:didFinishLaunchingWithOptions:, one of the methods its delegate has to handle. Take a look at AppDelegate.m, and you'll find some template code for this method. This is where you can start customizing, creating things that need to be in place before the UIWindow and other instances of UIView get created:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
// Override point for customization after application launch.
self.viewController = [[ViewController alloc] initWithNibName:#"ViewController" bundle:nil];
self.window.rootViewController = self.viewController;
[self.window makeKeyAndVisible];
return YES;
}
So, now the application window and root view controller are defined, and the app is off and running.
All of this, and quite a bit more, is excellently explained here: http://oleb.net/blog/2012/02/app-launch-sequence-ios-revisited/
As you said UIApplicationMain creates an application execution in the system. Among the stuff the application loading process does, I assume you are interested in what is relevant to a specific application. Also I assume a typical case, which is illustrated in many project templates that Xcode provides.
The application loading process looks into the application's information property list. There it finds 'Main nib file base name', and the UIApplication instance of your application loads the corresponding nib file from the application bundle. This nib file specifies an application delegate class, and tells to connect an instance of the class to the delegate property of your UIApplication instance.
Depending on the main nib file, other objects may be created and connected as well, for example, the application's window, the main view controller, etc.
Now the loading sequence ends, and everything is all event-driven, starting from your application delegate class to get the famous -applicationDidFinishLaunching: message.
From Apple Documents -
The application life cycle constitutes the sequence of events that occurs between the launch and termination of your application. In iOS, the user launches your application by tapping its icon on the Home screen. Shortly after the tap occurs, the system displays some transitional graphics and proceeds to launch your application by calling its main function. From this point on, the bulk of the initialization work is handed over to UIKit, which loads the application’s main nib file and readies the event loop.
Application Life Cycle
main.m
#import <Cocoa/Cocoa.h>
int main(int argc, char *argv[])
{
return NSApplicationMain(argc, (const char **) argv);
}
CoolClass.h
#import <Cocoa/Cocoa.h>
#interface CoolClass : NSObject <NSApplicationDelegate> {
}
- (void) applicationDidFinishLaunching : (NSNotification *) aNotification;
#end
CoolClass.m
#import "CoolClass.h"
#implementation CoolClass
- (void) applicationDidFinishLaunching : (NSNotification *) aNotification {
NSLog(#"THIS SHOULD BE PRINTED TO THE DEBUG CONSOLE");
}
#end
I tried this with "applicationWillFinishLaunching" as well, but still no luck. Any help at all would be appreciated. Thanks.
What you're missing is that adopting the protocol makes objects of kind CoolClass ready to function as delegates of any NSApplication object (provided you follow through on the declaration and implement all required methods of the protocol). Declaring conformance to the protocol also prevents compiler warnings when you set instances of the class as an application's delegate.
But for a specific application object (say, the shared NSApplication object that Cocoa creates for you) to know to send messages from the protocol to a specific CoolClass object, you must set the object you want to receive those messages as the specific application object's delegate.
What this means is that some time before the messages you want to receive would be sent by the application, something needs to instantiate a CoolClass object - call it c - and tell the application, "Hey, your delegate is c over here, so send delegate messages to the little feller from now on."
What that boils down to is that these lines of code must execute before the application finishes launching:
CoolClass *c = [[CoolClass alloc] init];
[[NSApplication sharedApplication] setDelegate:c];
The easiest way to have this happen is to let Interface Builder do the work for you: let the MainMenu nib instantiate your CoolClass and also set the cool class object as the application's delegate when the nib is loaded, as others have suggested.
To do so, open MainMenu.xib. Drag a Custom Object into the xib and change its class to CoolClass in the inspector. Ctrl-drag (or right-click drag) from the application object in the xib to the CoolClass object and choose "delegate". Save, build, and run.
You should define your CoolClass as applications delegate in Interface Builder (Ctrl+Drag from App instance to your CoolClass instance
applicationDidFinishLaunching is an instance method, not a class method. That is, you'll need an instantiation of your class to receive that message. Plus, it can't be just -any- instantiation; your application needs to know about your instantiation and know that it's supposed to send delegate messages to it. The easiest and most common way to do this is...
First, you'll instantiate your CoolClass. Open your application's MainMenu.nib file in Interface Builder. Drag an "Object" (it'll look like a blue cube) out of the Library window. Select it and use the Identity tab of the Inspector to change its class from NSObject to CoolClass. Now, you have an instance of your CoolClass.
Now, you'll set that instance as the application's delegate. Control-drag from "Application" (still in Interface Builder) to your new instance of CoolClass. A window will pop up (showing outlets of Application that could be connected to your object). Choose "delegate". Now your application has an instance of your CoolClass set as its delegate, and thus, your applicationDidFinishLaunching will run.
I appreciate you may be trying to learn from scratch, but why did you not just create a new project using one of the XCode templates? It sets all this up for you to begin with. Life involves enough debugging without having to add more atop it!
To start at the beginning: your call to NSApplicationMain should be wrapped in an NSAutoreleasePool. You will be in trouble if you don't do that.
i working with geocoding at the moment. The geocoding service allways works with delegates.
So let's say, I've got a
AskingClass and AnsweringClass(geocoding)
The AskingClass calls a function in the AnsweringClass to return the adress of the current location.
AnsweringClass should handle and capsulate the geocoding stuff. My Problem is, with all these delegates, I do not manage to come back to the orginal function, which the asking class has called. So I cannot give easily the adress back:
AskingClass.Adress= [AnsweringClass giveAdress];
I managed it, doing it with delegates, so the result comes back in a delegate function (somewhere) in the askingClass. But I'm not happy with that. It's seems oversized and complex.
with best regards
Klaus-Dieter
It is unclear why you are using a delegate pattern at all. Why not just use straight up classes?
Something like this (assuming that you are using a PCH file for your header files or otherwise importing 'em as needed):
AnsweringClass.h
#interface AnsweringClass:NSObject
- (MyAnswer *)answerThisDude;
#end
AskingClass.h
#class AnsweringClass; // just in case you including AskingClass.h before AnsweringClass.h
#interface AskingClass : NSObject
// {
// declare the ivar if you need support for 32 bit "classic" ABI
// AnsweringClass *theThingThatAnswers;
// }
#property(retain) AnsweringClass *theThingThatAnswers;
#end
Then you can do this:
AskingClass.m
#implementation AskingClass
#synthesize theThingThatAnswers;
- (void) setUpMyStuff // probably invoked by your designated initializer or app launch handler
{
self.theThingThatAnswers = [AnsweringClass new];
MyAnswer *theFirstAnswer = [self.theThingThatAnswers answerThisDude];
}
// don't forget a -dealloc if you aren't running GC'd
#end
No delegation necessary.