I'm writing a "blackbox" library. In this library I need to add a subView to any app which uses my library.
Therefore, I don't have any reference to the appDelegate nor to the UIWindow of the application.
The only thing the external app is doing now is the following :
myRec = [[Rec alloc] init];
myRec.delegate = self;
[myRec start];
where Rec is the blackbox library and myRec is the instance that's used by an external app.
Of course, I can't get any reference to the view of the app through the delegate member cause it's not defined like the specific type of the external app.
Any ideas on how to get a grasp on the UIWindow object / appDelegate object without knowing their identity in advance ?? Thanks !!
Getting the App Delegate:
id<UIApplicationDelegate> appDelegate = [[UIApplication sharedApplication] delegate];
Getting the UIWindow object:
UIWindow* window = [[UIApplication sharedApplication] keyWindow];
[[UIApplication sharedApplication] delegate]
Will always returns something conform to id<UIApplicationDelegate>
Btw, this is the proper way of doing it, create a protocol that some class in your application is supposed to conform to (i.e. the appDelegate) and pass that class to your library. You library can check that the class is well conform to the protocol and fail with a message in the log if not.
#phix23 his answer in Swift 3:
if let appDelegate = UIApplication.shared.delegate, let window = appDelegate.window {
let yourview = window?.rootViewController?.view
}
Related
We have a requirement to change UIDocumentInteractionController preview screen? Is it possible to change the rect of UIDocumentInteractionController? I want to open document preview in my custom view?
in creating an AIR Native Extension, I needed to create a view window for my custom view controller.
make sure you are doing:
#import "MyCustomViewController.h"
in my function:
MyCustomViewController *myViewController;
id delegate = [[UIApplication sharedApplication] delegate];
UIWindow *win = [delegate window];
myViewController = [[MyCustomViewController alloc]init];
[win addSubview:myViewController.view];
[myViewController previewDocument: (parameters to method)];
return (_bridge FREObject)(myViewController);
where you implement this may be different depending on your structure. Since I am using it as an ANE, I put it right into the Context function call.
hope it gives you a starting point if you haven't gotten it yet.
I have an object that is used between all my viewControllers so I have stuck it inside the application delegate. (I assume this is the correct place?).
If an action inside a viewController fires that needs to send something to said object I am performing the following:
- (IBAction)sliderMoved:(id) sender{
MyAppDelegate *delegate = [[UIApplication sharedApplication] delegate];
[[delegate myObject] setSpeed:(int)slider];
// [delegate release];
}
I am a bit concerned I am not releasing the delegate object anywhere, is this ok? If I remove the commented line [delegate release] it just crashes the application.
You don't own the delegate object that you create in this snippet. You haven't created it with alloc, new, or a copy. Nor have you retained it. So, it is not your responsibility to release it.
As for putting an object in the Application delegate just to be able to access it from other parts of your code - that is poor OOP design IMO.
Edited to add
I suppose I had better give an example
Suppose you have a class MyClass that you want to create an object of that you can pass around.
You create it in the Application delegate, which it seems you are already doing:
MyObject *myObject = [[MyObject alloc] init];
Then you create another view controller - which you would normally do, except that this view controller has a property:
#property(retain) MyObject *object;
And then you set this property when you create the view controller:
YourViewController *vc = [[YourViewController alloc] init];
vc.object = myObject;
And, if you pass this object to other view controllers as you require.
basically i have parsed some data from XML into a NSMutableArray that is shared in the appDelegate.
in my secondViewController i have a uiPickerView that i am wanting to load the details of the array into it.
My question is... how?
i have briefly worked with uiPickerView's before and had to load the data in first to assign to the uiPickerView like so:
titleDB = [[NSMutableArray alloc] init];
[titleDB addObject:#"MR"];
[titleDB addObject:#"Mrs"];
[titleDB addObject:#"Ms"];
[titleDB addObject:#"Miss"];
[titleDB addObject:#"DR"];
[titlePickerView selectRow:1 inComponent:0 animated:YES];
but since the data is coming from the appDelegate i don't know how i should load it into the uiPickerview, is it something to do with the datasource?
I'm asking to throw code at me I'm just asking for the best way to do it.
Any help on this would be great
Thanks
Jonn4y
This is a common pattern. You will want to access UIApplication's sharedApplication instance. So assuming your appDelegate class is named YourAppDelegate, the array ivar in YourAppDelegate and viewController is titleDB then you could do this in your viewController's viewDidLoad method
YourAppDelegate *appDelegate=(YourAppDelegate *)[[UIApplication sharedApplication] delegate];
// assuming you are using #property and #synthesize for your ivars
self.titleDB=appDelegate.titleDB;
Good luck
Basically, you want to access the appDelegate object from random places in code. This is not an unusual request. Remember that Objective C is a superset of the C language. And as such, you can use a global variable. What more natural variable would there be in a Cocoa program than the app delegate, for the reasons stated above. So, in your appDelegate .h file, add:
<MyAppDelegateClass> * appDelegate;
Substitute MyAppDelegateClass for the name of your appDelegate class name. Then just include your appDelegate's .h file anywhere you want to use the appDelegate variable, and just use (in your example):
[appDelegate titleDB]
or create a local iVar:
NSMutableArray * titleDB = [appDelegate titleDBData];
Then in your app delegate method didFinishLaunchingWithOptions, add the following line:
appDelegate = self;
how to call an AppDelegate method from RootViewController without passing a delegate?
Just wondering whether there is a way to do this? (or do I need to create a delegate object in the RootViewController to hold a reference to the AppDelegate)
[[[UIApplication sharedApplication] delegate] someMethod];
Works like a charm!
You can get access to the app delegate from any controller using
MyDelegate* aDelegate = (MyDelegate *)[[UIApplication sharedApplication] delegate];
This happens so frequently, that I always add a method to MyCustomAppDelegate to do this for me (so I don't have a lot of casting in my code.
#implementation MyCustomAppDelegate ()
- (MyCustomAppDelegate *)appDelegate {
return (MyCustomAppDelegate *)[[UIApplication sharedApplication] delegate];
}
#end
now anywhere i can call
[MyCustomAppDelgate appDelegate]
I have only one window and I tried
UIWindow* mWindow = [[UIApplication sharedApplication] keyWindow];
but this returned nil.
I also tried:
UIWindow* mWindow = (UIWindow*)[[UIApplication sharedApplication].windows objectAtIndex:0];
But this raised an exception and the app closed, when I tried to print out
[[UIApplication sharedApplication].windows count]
It printed 0
Note: I am putting this in my only view controller's viewDidLoad method and this is completely a new iPad View Based Application so I changed nothing, just trying to get the window
Please help me to get this object
If your main window is an outlet of your AppDelegate (which should be the case), you may simply use
MyAppDelegate* myDelegate = (((MyAppDelegate*) [UIApplication sharedApplication].delegate));
[myDelegate.window ...]
Easiest way is to get the window from the app delegate instead:
UIWindow *keyWindow = [[[UIApplication sharedApplication] delegate] window];
// Do something with the window now
Your application's key window isn't set until [window makeKeyAndVisible] gets called in your app delegate. Your UIViewController is probably being loaded from a NIB before this call. This explains why keyWindow is returning nil.
Luckily, your view controller doesn't need to go through UIApplication to get the window. You can just do:
UIWindow *mWindow = self.view.window;
[[[UIApplication sharedApplication] windows] objectAtIndex:0]; // You can also check the count of this to make sure, because if there are no windows it will crash.
With iOS 13+ you should use:
if let currentScene = UIApplication.shared.connectedScenes.first as? UIWindowScene,
let window = currentScene.keyWindow {
// now window contains the active window
}
You can achieve this in multiple ways. I like to use one of the following.
Use this when you need to access it just once.
if let window = UIApplication.shared.windows.first as UIWindow? {
// Action
}
If you need to access the UIWindow multiple times, I would suggest extending a class. I like to extend the UIViewController.
extension UIViewController {
/// Returns the UIWindow if available.
public var window: UIWindow? {
UIApplication.shared.windows.first as UIWindow?
}
}