Error with presentViewController - no visible #interface for AppDelegate - xcode

I am making a splitview application for ipad and I need to display a different view controller for login purposes.
I call this in the didFinishLaunchingWithOptions function in Appdelegate:
LoginViewController *login = [[LoginViewController alloc] init];
[info setModalTransitionStyle: UIModalTransitionStyleCrossDissolve];
[self presentViewController:login animated:YES completion: nil];
but I get the error "No visible #interface for AppDelegate declares the selector presentViewController" on the third line.
The view controller I want to display is set to the LoginViewController class.
I have Imported all classes.
I am pretty new to programming and would really appreciate any help!
Thanks!!

What the error message says is that the class AppDelegate does not contain a method called presentViewController. Indeed, that method belongs to UIViewController class.
What you should do depends on how you created your project, whether it uses a navigation controller, a tab bar controller, or a simple view controller.
From your comment, I understand you used the Window-based template (or Empty application) to create your project. In this case, in your application:didFinishLaunching: you should have something like this:
self.login = [[LoginViewController alloc] init];
[self.window addSubview:self.login.view];
and also add to your AppDelegate.h the following declaration:
#property (nonatomic, strong) LoginViewController* login;
If this seems not to apply to your case, please, post your definition of application:didFinishLaunching:

Related

The new UISplitViewController in iOS8 using objective c without storyboard

I try to implement adaptive UI in my app. By making UISplitViewController as the rootview controller, I can run the iPhone's code in iPad too.
I red Apple's documentation about UISplitViewController and some samples. All are using storyboards and the sample codes are available in swift only. I can not find a working version of code. So I started the code myself.
See my splitview controller class (BaseSplitViewController)
BaseSplitViewController.h:
#import <UIKit/UIKit.h>
#interface BaseSplitViewController : UISplitViewController <UISplitViewControllerDelegate>
#end
BaseSplitViewController.m:
#import "BaseSplitViewController.h"
#import "TabBarViewController.h"
#interface BaseSplitViewController ()
#property(nonatomic, strong) TabBarViewController *primaryTabBarVC;
#property(nonatomic, strong) UINavigationController *primaryNavigationController;
#property(nonatomic, strong) UINavigationController *secondaryNavigationController;
#end
#implementation BaseSplitViewController
- (instancetype)init
{
self = [super init];
if (self)
{
[self setViewControllers:#[self.primaryNavigationController, self.secondaryNavigationController]];
self.delegate = self;
self.preferredDisplayMode = UISplitViewControllerDisplayModeAutomatic;
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(cellTapped:) name:#"cellTapped" object:nil];
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
[self assignPrimaryViewController];
}
- (void)assignPrimaryViewController
{
// Need to assign tab bar controller as primary view controller here
}
- (void)assignSecondaryViewController:(UIViewController *)vc
{
// Need to update the secondary controller each time the primary controller was tapped
}
- (UINavigationController *)primaryNavigationController
{
if (!_primaryNavigationController)
{
_primaryNavigationController = [[UINavigationController alloc] init];
}
return _primaryNavigationController;
}
- (UINavigationController *)secondaryNavigationController
{
if (!_secondaryNavigationController)
{
_secondaryNavigationController = [[UINavigationController alloc] init];
}
return _secondaryNavigationController;
}
- (UITabBarController *)primaryTabBarVC
{
if (!_primaryTabBarVC)
{
_primaryTabBarVC = [[TabBarViewController alloc] init];
}
return _primaryTabBarVC;
}
#end
Some points:
The above class "BaseSplitViewController" is the rootview controller of my app.
That is, self.window.rootViewController = [[BaseSplitViewController alloc] init];
From Apple's Documentation,
"When designing your split view interface, it is best to install
primary and secondary view controllers that do not change. A common
technique is to install navigation controllers in both positions and
then push and pop new content as needed. Having these types of anchor
view controllers makes it easier to focus on your content and let the
split view controller apply its default behavior to the overall
interface."
So, I created two navigation controllers (primary/secondary) and set them as split view controllers's primary & secondary views. setViewControllers: can be used for this.
My primary view here is, tab bar view. So, inside the assignPrimaryViewController: method, I should assign my TabBarViewController as split view controller's primary view.
Here, I found two ways.
1. [self.primaryNavigationController showViewController:self.primaryTabBarVC sender:nil];
2. [self.primaryNavigationController pushViewController:self.primaryTabBarVC animated:YES];
Here, I tried with [self showViewController:self.primaryTabBarVC sender:nil]; but my tab bar view was never shown. From my understanding, here "self" means the UISplitViewController. Calling showViewController: here makes the confusion to choose the navigation controller. Because we have two navigation controllers. So we need to clearly tell that navigation controller which needs to hold the primary controller.
Primary view controller part is over. Now the real problem starts. Consider my primary view controller is the tab bar which have tableview's in it. If I tap on the cell, I need to update the secondary view's content. This is the case in Regular mode. In compact mode, I expect when the user taps on the cell, it should push the detail view (secondary view) with back button.
I expect to put the below code within assignSecondaryViewController: vc: method
[self.secondaryNavigationController pushViewController:vc animated:NO];
[self.primaryNavigationController showDetailViewController:self.secondaryNavigationController sender:nil];
But it does not works.
Questions:
What should be placed inside assignPrimaryViewController & assignSecondaryViewController: methods to get my expected result?
And I really, yes really don't know how to implement UISplitViewController's following delegate methods.
primaryViewControllerForCollapsingSplitViewController:
splitViewController:collapseSecondaryViewController:ontoPrimaryViewController:
primaryViewControllerForExpandingSplitViewController:
splitViewController:separateSecondaryViewControllerFromPrimaryViewController:
Would be really helpful, if someone explains this new UISplitViewController's behavior.
Thanks

Set view as delegate to viewcontroller

I'm having problem passing data and executing functions in the viewcontroller from the view. I want to access label outlets in the viewcontroller from the view (yeah I know it might be bad structure of my app).
Got delegations working on UIPopovers but how can I set the delegate of the view to viewcontroller?
For example, you have a subclass of UIView. Let's name it SubClassUIView;
In another view, you want to use the data, from SubClassUIView.
So, your SubClassUIView should be done like this:
SubClassUIView.h
#interface SubClassUIView:UIView
#property (nonatomic, retain) UILabel* someLabelYouWantToUse;
#end.
SubClassUIView.m
#implementation SubClassUIView
#synthesize someLabelYouWantToUse;
#end.
And to access someLabelYouWantToUse
SubClassUIView* scView = [SubClassUIView alloc]init];
NSLog(#"%#", scView.someLabelYouWantToUse.text);

Change IBOutlet text to property of object returned from custom class

I'm using xCode 4.2.1 - I have an app that uses a web service and fetches some data using a custom class and NSURLConnection. The user taps a "refresh" button which starts a series of events that happen in some custom classes in my project, and I can get the object, along with the properties I want to return in a method in the MainViewController, I'm just not able to change the text of an IBOutlet to a property (NSString) of the returned object.
In my "MainViewController.h, I have an IBOutlet (and it's wired to a button in the MainViewController.xib):
IBOutlet UILabel *textLabel;
and:
#property (nonatomic, retain) IBOutlet UILabel *textLabel;
And I've synthesized the label in MainViewController.m
#synthesize textLabel;
The process looks like this: Refresh Button Tapped --> Fires a mthod in MainViewController --> Fires another method in a custom class (retrieves data from web, creates object) --> Sends Object to MainViewController via: (in my custom class implementation)
// parsing, etc.. and define a string for priceString property of mp object
MainViewController *mvc = [[MainViewController alloc] init];
[mvc log:mp];
And in my MainViewController.m I can access a property of that object and print it in NSLog just fine from this method.
- (void) log:(Price *)mp {
self.textLabel.text = mp.priceString;
NSLog(#"%#", mp.priceString);
}
At this point, I can see the data in the log, but the textLabel text won't change.
I've been trying to read examples for a week, and I've heard everything from delegation, to NSNotication answers, but nothing seems to work.
All I need to do is populate an IBOutlet from a -(void) method.
Any help would be greatly appreciated, and I'm down for implementing delegation, but I'm very new to it, and seeking an example.
EDIT - more details.
After further research, I think I should note that my NSURLConnection that is returning my objects is in a separate class, and I've been reading a lot of threads where people are starting the connection in viewDidLoad.
The problem is that you are calling [mvc log:mp]; just after initializing the view controller. At that stage, the view is still not loaded from the xib file.
you can change log to see that:
- (void) log:(Price *)mp {
if (self.textLabel) {
self.textLabel.text = mp.priceString;
} else {
NSLog(#"textLabel is nil.");
}
}
You can call [mvc log:mp]; in the view controller viewDidLoad method, or after viewDidLoad has been executed.
To understand this better, add NSLog(#"viewDidLoad."); in viewDidLoad method, and add NSLog(#"viewController initialized."); just after the code where you initialized the view controller.
You will see the following
viewController initialized.
textLabel is nil. // if you call log as usual after initializing the view controller.
viewDidLoad.

Delegate not working, when using a modal presented NavigationController ( iOS 5 - Storyboard )

I have a problem with a protocol.
My "initial View Controller" is a Navigation Controller. On the root page i show an other Navigation Controller in which is View Controller embedded. onclick a segue should be fired...this works perfectly but the delegate method from the "ViewController" is never called.
The image I added is a example how I build the connection between the 2 NavigationControllers with the InterfaceBuilder in iOS 5.
MyViewController.h
#protocol MyProtocol <NSObject>
#required
- (void) myFunction:(NSString *)string;
#end
#interface MyViewController : UIViewController <MyProtocol>
#property (nonatomic, assign) id<MyProtocol> delegate;
#end
MyViewController.m
#import "MyViewController.h"
#implementation PropertyController
#synthesize delegate = _delegate;
- (void) myFunction:(NSString *)string {
[_delegate myFunction:string];
}
- (IBAction) callDelegate:(id)sender {
![enter image description here][1][self myFunction:#"test"];
}
And this is the code for the ViewController which is showing the NavigationController from above
ViewController.h
#import "MyViewController.h"
#interface ViewController : UIViewController <MyProtocol>
ViewController.m
#import "ViewController.h"
#implementation ViewController
- (void) myFunction:(NSString *)string {
NSLog(#"myFunction was called");
}
- (void) prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
[((MyViewController *) segue.destinationViewController) setDelegate:self];
}
- (IBAction) showModalNavigationController {
[self performSegueWithIdentifier:#"NameFromSegueInInterfaceBuilder" sender:self];
}
I cant find a solution for my problem.
I hope somebody can help me
thank you :)
I see a couple of problems here:
In your storyboard screenshot, you have a second navigation controller. You should not not need to embed your PropertyController in a navigation controller. Instead, have the root view controller segue directly to the PropertyController. If for some reason you do need that navigation controller, then you would need to change your prepareForSegue implementation above, because segue.destinationViewController in this case points to the UINavigationController. So you would need to get that nav controller object, and then send setDelegate to the rootViewController of that nav controller object. But again, only if you decide to keep that navigation controller.
How does MyViewController relate to your ViewController and PropertyController classes? The PropertyController class (or a superclass) needs to have the #property and synthesize statements for the delegate property.
I've been having the same issue, to make it work, I found a work around which xcode does not really like, but it still is working though --> setting your delegate as you do it, makes your navigation controller have your view as delegate, if you NSLog self.delegate in your destination controller it will be null. To prevent this do -->
self.delegate = self.navigationController.delegate;
in your destination controller (viewdidload), it will get the delegation you created on the navigation controller, and allow you yo use it in your destination controller
It is dirty but it's the only way I found. Hope it helps.

displaying an image in cocoa

I am totally new at this, but here goes:
I want to press a button in my application, and have an image display (I am planning to read it off of a camera, but to start with, I will open a .TIF file.) However, within the interface builder, I can make buttons within an NSObject object, but the literature makes it sound like I need to make an NSView object to display a file. The problem is, when I do this, the NSObject object does not seem to talk to the NSView object. I am trying to do something like:
NSString *inFilePath;
inFilePath = #"/Volumes/Data/Temp/Smiles.tiff";
NSImage *TestImage = [[NSImage alloc] initWithContentsOfFile:inFilePath];
[MyView setImage:TestImage];
Here, MyView is the NSView object. I get warnings that MyView may not respond to setImage. I have tried to define an IBOutlet within the NSObject object, and although I can connect it within the interface builder, console gives me the error:
unrecognized selector sent to class 0x1e080
So, it's not clear what the next step is. Is there an easy way to get two different objects to "talk to" each other?
Thanks
You want an NSImageView object. In the Interface Builder library this is called an Image Well, but you can configure it so that it doesn't have a bezel.
NSImageView is a subclass of NSView that is optimised for displaying images.
In your header (.h) file, you should have something like this:
#interface MyController : NSObject
{
//this declares an outlet so you can hook up the
//image view in Interface Builder
IBOutlet NSImageView* imageView;
}
#end
And in your implementation (.m) file:
#implementation MyController
//called once the nib is loaded and all outlets are available
- (void)awakeFromNib
{
NSString *inFilePath = #"/Volumes/Data/Temp/Smiles.tiff";
NSImage *testImage = [[NSImage alloc] initWithContentsOfFile:inFilePath];
#if !__has_feature(objc_arc)
[testImage autorelease];
#endif
//imageView is your outlet
[imageView setImage:testImage];
}
#end
In Interface Builder you should hook up the imageView outlet of your class to point to the NSImageView you placed on your view.

Resources