Possible to use UIActionSheet from Application Delegate? - iphone

I have a common UIActionSheet which I use across about 10 different view/view controllers. I'm wondering if it's possible to use UIActionSheet from the app delegate in order to prevent code duplication?
So far my attempts to use an action sheet from the delegate haven't worked, I suspect my problem lies when calling the showInView method - do I need to instantiate an object of my view controller then use viewController.view here? If so how can I then tell which view called the action sheet method from the delegate?

I didn't try the approach proposed by c_phlat, but I wonder to what self.view is mapped.
I did manage to do it like this:
[actionSheet showInView:window];
it works just as well.

I was having the same problem, and I recently figured out a way to fix it in my app. The key for me was to make my app delegate class an extension of UIViewController rather than NSObject. (I think UIViewController is a subclass of NSObject anyway, so this shouldn't affect your app too much.)
In other words, change the main implementation line in your app delegate interface file from something like this:
#interface YourAppDelegate : NSObject <UIApplicationDelegate, UIActionSheetDelegate> {
To this:
#interface YourAppDelegate : UIViewController <UIApplicationDelegate, UIActionSheetDelegate> {
You should now be able to use the showInView: method with your action sheet within your app delegate implementation:
[yourActionSheet showInView:self.view];

Related

Assigning ViewController to a delegate, Is it good?

I am newbie in iOS programming, Recently I came across a tutorial where author assigned a ViewController to a textField delegate. Is it good to do this? As Xcode is giving me warning.
discussIDTextField.delegate = self;
self is DiscussViewController and above code is inside DiscussViewController.m
Code works fine but I don't like yellow bubbles showing on my screen while writing codes. If I want to get rid of this warning what should I do?
Warning : Assigning id from incompatible type
'DiscussViewController'.
The view controller (self) has to implement the UITextFieldDelegate protocol. So your #interface definition should look something like this:
#interface DiscussViewController : UIViewController <UITextViewDelegate>
And then of course in the implementation implement some of the delegated protocol methods.
In your .h file add UITextFieldDelegate between < > so that your view controller becomes text field delegate and then in the .m file implement delegate methods that you need.
#interface DiscussViewController : UIViewController <UITextFieldDelegate>

How to access variables of a ViewController in a subclass?

I guess this is basic, but I can't get my head around this.
I used to have only one ViewController in which all my variables were defined, e.g. an UITextView named myTextView. I also had methods in this ViewController for handling events that relate to myTextView, such as - ()hideKeyboard { // do something with myTextView or - (void)keyboardWillShow:(NSNotification *)notification { // do something with myTextView.
As my program became bigger and bigger, I thought about using subclasses, especially for other views. So I started a subclass, eg. mySubClass.h and mySubClass.m, in which I had another UITextView (for argument's sake myOtherTextView). In order to incorporate mySubClass, I #imported it into my ViewController and added a #class mySubClass; and could then produce instances of this class so as to use it in my App.
So far so good. As you can imagine, all the nice methods I defined in my ViewController for what should happen when an UITextView is edited (such as hiding keyboard etc.) didn't work for the UITextView in mySubClass.
It was then suggested to me that I should make another class in which I had all the keyboard events and subclass my ViewController and mySubView to it:
#interface ViewController : MyKeyboardEventsViewController
Now, the problem I am seeing is that I won't be able to access all the views, textviews, textfields etc. that I have created in my ViewController (e.g. myTextView which I mentioned earlier).
How can I achieve that all the variables that I have defined in my ViewController will also be available for MyKeyboardEventsViewController? Or is there another way to handle this?
Basically, I don't get how MyKeyboardEventsViewController will be able to access variables in my ViewController which it will need (e.g. the UITextView in question, or the accessoryView which will pop up etc. etc.).
Any suggestions would be very much welcome.
Example:
Class A contains a ivar UITextField textField
Class B subclasses Class A and thus it already contains ivar textField
Note: it's not the other way around. Class A does not "see" what ever is created in Class B.
When ever you subclass a class you give your new class the same ivars end methods of that subclassed class.
I hope this is what you were asking for.
EDIT
So for your example I would do the follwing:
Create a class "MyUIKeybordEventResponder"
Implement all the responder methods like - (BOOL)textFieldShouldReturn:(UITextField *)textField
Subclass your ViewController from "MyUIKeybordEventResponder"
Note method textFieldSHouldReturn has a parameter UITextField so it knows which textfield was pressed. So in a way it receives your textField from the subclass.
If I'm understanding this correctly, you have a UIViewController with MyKeyboardEventsViewController as an instance variable and you want to communicate between the two? If that is the case, one option would be to create a protocol.
#protocol MyKeyboardDelegate
- (void)closeAccessoryView;
#end
(Note - make whatever methods in the protocol that you need, this is simply an example)
In your MyKeyboardEventsViewController you then include the protocol file, and create an ivar
id <MyKeyboardDelegate> delegate;
Also make it a property and synthesize it.
Whatever class that is going to create the keyboardviewcontroller should delcare themselves as conforming to the protocol.
#interface MyViewController : UIViewController <MyKeyboardDelegate>
...
#end
When you create the MyKeyboardEventsViewController, set the delegate.
MyKeyboardEventsViewController *eventsVC = [[MyKeyboardEventsViewController alloc] init];
[eventsVC setDelegate:self];
Now just implement the delegate method and perform whatever action that is necessary.

iPhone - Accessing superviews methods?

So essentially I'm inserting "startViewController" into "mainViewController" now of course I can access startViewControllers methods from mainViewController but I was wondering how to do the opposite? Occasionally startViewController will need to call something in mainViewController and I was just wondering how I do this?
Thanks in advance.
Add an ivar of your mainViewController to your startViewController and set this when showing the view.
Or you can design a nice clean protocol, and make one view the delegate of the other.

Creating a new ViewController and xib for programmatic display (with addSubview)

I am writing a library to be used by developers for the iPhone (similar to the way that OpenFeint is implemented) and I am trying to create a ViewController with an associated XIB so that I can instantiate it in my code with
SplashScreenViewController *splashScreenViewController = [[SplashScreenViewController alloc] init];
UIWindow *topApplicationWindow = [self getTopWindow];
[topApplicationWindow addSubview:splashScreenViewController.view];
However, while this works with simple controls (UIButtons, etc), nothing shows up with my SplashScreenViewController. SplashScreenViewController is very simple:
#import <UIKit/UIKit.h>
#import <Foundation/Foundation.h>
#interface SplashScreenView : UIViewController {
}
#end
and the implementation is empty. In my View XIB (SplashScreenView.xib), I have tried setting the File's Owner's class to SplashScreenViewController which didn't work, then I tried it the way I've seen it done in OpenFeint which is to add a View Controller in IB and make the main UIView a child of it and make it of class SplashScreenViewController instead. That also does not work (does not display).
I'm wondering if anyone has a good idea for what I might be missing, or if someone can recommend a walkthrough for creating new ViewControllers the way that I'm attempting to.
Thanks!
Try 2 things :
Call initWithNibName not just init. Maybe the OpenFeint you were talking about were overriding the init to call initWithNibName , that's why you don't see it.
Set SplashScreenViewController as your file owner, and connect his view outlet to your
view in IB.
Hope it helps.
Instead of [splashScreenViewController alloc], try [SplashScreenViewController alloc]. I'm surprised you didn't get a compiler warning.

MKMapView not calling delegate methods

In a UIViewController I add a MKMapView to the view controlled by the controller.
- (void)viewDidLoad {
[super viewDidLoad];
CGRect rect = CGRectMake(0, 0, 460, 320);
map = [[MKMapView alloc] initWithFrame:rect];
map.delegate = self;
[self.view addSubview:map];
}
Later in the controller I have
- (void)mapViewDidFinishLoadingMap:(MKMapView *)mapView
{
NSLog(#"done.");
}
Done never gets printed. None of the other delegate methods get called either like mapView:viewForAnnotation: I use a MKMapView in an another app, but this seems to happen on any new application I make. Has anyone else seen this behavior?
EDIT:
The problem seems to be when UIViewController is made the delegate of the MKMapView, a direct subclass of NSObject seems to work okay. I can work around like this, still seems very odd since I've done it before.
I had the exact same problem: I had assigned < MKMapViewDeledate> to my controller, and linked the delegate to "File owner" in Interface Builder, but still my implemented delegate methods were not called.
The reason is that since iOS 4, maps are cached, and whenever an app display a cached map then methods such as "mapViewDidFinishLoadingMap" are not called. Resetting "contents and settings" in the simulator clears the cached maps and therefore solves the issue.
A bit old, but since iOS 7 there is a new method that might work. solved my problem
- (void)mapViewDidFinishRenderingMap:(MKMapView *)mapView fullyRendered:(BOOL)fullyRendered
Perhaps you need to go to the IB and control-drag from the MKMapView to the view conroller, then select delegate to make it a delegate???
maybe quite obvious, but just checking:
Have you made sure your viewcontroller declaration is correctly done.
Something like:
#interface YourViewController : UIViewController <MKMapViewDelegate>
I had a similar problem with the methods of MKMapViewDelegate not being called.
My issue was setting the MKCoordinateRegionMakeWithDistance and regionThatFits in the controller's -viewDidLoad() I wanted to only show the region around my house and not start with the world view. So after adding annotations in the controller's viewDidLoad, I started a timer. When it expires in one second, I zoom in on the region I want with the above APIs and the delegate methods fire. It just makes me a little dizzy and inclined to vomit on my iPad.
Now I only have to deal with the darn low memory warnings.
I had a similar issue in XCode 6.1 building for iOS 8.1 where none of the MKMapViewDelegate methods were being called. In a 2nd application the identical code resulted in the MKMapViewDelegate methods being called as expected.
In ViewController.m the mapView delegate was set as follows:
- (void)viewDidLoad {
...
self.mapView.delegate = self;
In ViewController.h:
#interface myMapViewController : UIViewController <MKMapViewDelegate>
#property (strong, nonatomic) IBOutlet MKMapView *mapView;
#end
I had manually added the IBOutlet line above to the header file, but only in the app where the delegate methods were not being received.
The solution was to delete the IBOutlet line I had added manually to the header, and then go to the storyboard and CTRL-drag from the MKMapView to the #interface block in my ViewController.h. The identical IBOutlet was recreated in the header file with the result that all the delegate methods were called correctly.
I just ran into this again on iOS 7 and figured out something that works consistently. The issue we're typically fighting is calling setRegion before the region has context (view rendered). iOS 7 adds new delegate methods representing all tiles being rendered but pre-iOS 7 the cached tiles prevents the delegate method mapViewDidFinishLoadingMap from being called. Instead I use a "pendingRegion" variable to check if I have "queued" a region change for when the map is rendered and then simply use the viewDidAppear method as a signal the map has been rendered to the screen and hence a region will have context.
Add a variable to your header:
MKCoordinateRegion pendingRegion;
Add this method to your code:
-(void)initPendingRegion {
pendingRegion.center = CLLocationCoordinate2DMake(0.0, 0.0);
}
Add this to your viewDidAppear:
if(pendingRegion.center.latitude != 0.0) {
MKCoordinateRegion useRegion = pendingRegion;
[self initPendingRegion];
[self.mapView setRegion:useRegion animated:YES];
}
My problem is that I forget to set location in the simulator. Go to Simulator -> Debug -> Location -> Custom location... and the MKMapViewDelegate methods will start calling
For me, it worked after adding NSLocationWhenInUseUsageDescription string in Info.plist
I also met same issue as yours. I found that: with the iPhone SDK 3.2 - when I create a new UIViewController with an associated xib file (the checkbox option in UIViewController creating dialog), delegate methods of MKMapViewDelegate are never called.
However, when I follow below steps, it runs well.
Create a new UIViewController class (never check the option: create xib file associated with the controller)
Create a new xib file. Add the map using Interface Builder + setting the Owner class with the class on step 1 + setting delegate object of the map point to the owner class.
Implement delegate methods for the UIViewController class in step 1.
When I want to use my ViewController (with the added map), I load it with the nib name as below example:
MapPreviewController* mapPreviewController = [[MapPreviewController alloc]
initWithNibName:#"MapPreviewController" bundle:[NSBundle mainBundle]];
[self.centerPanelView addSubview:mapPreviewController.view];
The code runs ok. I don't know what Apple changes or did with the xib file when I create my UIViewController using the wizard, but it may the root cause of my problem. It takes me 1 day to find this stupid solution.
If you found another one, please share to me.
Thanks