Expected getter method not found, Xcode iOS - iphone

I am using Apple's newest Xcode for MacOS 10.7(Lion). I am trying to make a iPhone application. I'm new to the language and decided to load up apples guides. 'Your first iOS application'. It was good, taught me a few things but Its not working. I get Expected Getter Method Not Found On Object Of Type 'TestAppDelegate *'
How do i Fix this?
Heres the code:
TestAppDelegate.m
#import "TestAppDelegate.h"
#import "MyViewController.h"
#implementation TestAppDelegate
#synthesize window=_window;
#synthesize myViewController=_myViewController;
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
MyViewController *aViewController = [[MyViewController alloc] initWithNibName:#"MyViewController" bundle:nil];
self.myViewController = aViewController;
// Or, instead of the line above:
// [self setMyViewController:aViewController];
[aViewController release];
self.window.rootViewController = self.MyViewController;
[self.window makeKeyAndVisible];
return YES;
}
/* Other methods omitted from the listing. */
- (void)dealloc {
[_myViewController release];
[_window release];
[super dealloc];
}
#end
The line:
self.window.rootViewController = self.MyViewController;
Has the problem

objective-c is case-sensitive. You wrote an upper-case M instead of lower-case.
self.window.rootViewController = self.myViewController;

Your window doesn't exist yet (at least from what I can see in your code). Add this before the line causing the SIGABRT:
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];

Related

Linking facebook sdk to ios

I have a dead line and dont know what to do with that. IM tryin to use react-native-fbsdk with firebase on and wanted to link the sdk to ios. Everything is good but this function:
[[FBSDKApplicationDelegate sharedInstance] application:application
didFinishLaunchingWithOptions:launchOptions];
// Add any custom logic here.
return YES;
Im trying to put this here:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
NSURL *jsCodeLocation;
jsCodeLocation = [[RCTBundleURLProvider sharedSettings] jsBundleURLForBundleRoot:#"index.ios" fallbackResource:nil];
RCTRootView *rootView = [[RCTRootView alloc] initWithBundleURL:jsCodeLocation
moduleName:#"tzawajna"
initialProperties:nil
launchOptions:launchOptions];
rootView.backgroundColor = [[UIColor alloc] initWithRed:1.0f green:1.0f blue:1.0f alpha:1];
self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
UIViewController *rootViewController = [UIViewController new];
rootViewController.view = rootView;
self.window.rootViewController = rootViewController;
[self.window makeKeyAndVisible];
return YES;
[[FBSDKApplicationDelegate sharedInstance] application:application
didFinishLaunchingWithOptions:launchOptions];
// Add any custom logic here.
return YES;
}
And Its giving an error of
use of undeclared identifier FBSDKApplicationDelegate
What should I do.
Thanks
Check whether In your application:openURL:options implementation ( or for any other method in the file), the parameter is named app and not application.
You can either change the parameter name in the method signature to application:
- (BOOL)application:(UIApplication *)application
openURL:(NSURL *)url
options:(NSDictionary<UIApplicationOpenURLOptionsKey,id> *)options
This error can be caused because of the difference in the parameter of such method.

iOS 6 - State Preservation and Restoration

I have implemented iOS 6 API for state saving, it works - after I quit the app and launch back in for some milliseconds the restored view controller fly in, but then it's replaced by the main view controller I display at launch.
I'm setting every time the app launch the root view of the main window, so this must be the issue.
Here is my code:
- (BOOL)application:(UIApplication *)application willFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
[self commonInitializationLaunching:launchOptions];
return YES;
}
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
[self commonInitializationLaunching:launchOptions];
return YES;
}
- (void)commonInitializationLaunching:(NSDictionary *)launchOptions
{
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
// Override point for customization after application launch.
static NSString *const kKeychainItemName = #"OAuthGoogleReader";
self.viewController = [[ViewController alloc] initWithNibName:#"ViewController" bundle:nil];
self.navController = [[UINavigationController alloc] initWithRootViewController:self.viewController];
GTMOAuth2Authentication *auth;
auth = [GTMOAuth2ViewControllerTouch authForGoogleFromKeychainForName:kKeychainItemName
clientID:kClientID
clientSecret:kClientSecret];
self.window.rootViewController = self.navController;
[self.window makeKeyAndVisible];
BOOL isSignedIn = [auth canAuthorize];
if (isSignedIn) {
NSLog(#"Signed");
}else{
NSString *scope = #"https://www.google.com/reader/api/";
GTMOAuth2ViewControllerTouch *viewController;
viewController = [[GTMOAuth2ViewControllerTouch alloc] initWithScope:scope
clientID:kClientID
clientSecret:kClientSecret
keychainItemName:kKeychainItemName
delegate:self
finishedSelector:#selector(viewController:finishedWithAuth:error:)];
[self.navController pushViewController:viewController animated:YES];
// self.window.rootViewController = viewController;
}
});
}
You can see that in -(void)commonInitializationLaunching:(NSDictionary *)launchOptions
I'm setting my window's root view. I don't know what to put in there. Perhaps check if there is saved state and then load this method? But how?
Thanks!
Here is what I've tried following Rob's advice:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
if (!self.isRestored) {
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
}
[self commonInitializationLaunching:launchOptions];
[self.window makeKeyAndVisible];
return YES;
}
with nothing in willFinishLaunching...
I also removed by window code from my commonInitializationLaunching method.
Storyboards will do most of the heavy lifting for you, such as restoring the window. Using code, however, will not restore the window. You will need to hold on to your root view controller using the encoder. Your code will look something like this:
NSString * const AppDelegateRootVCKey = #"AppDelegateRootVCKey";
- (void)application:(UIApplication *)application willEncodeRestorableStateWithCoder:(NSCoder *)coder {
[coder encodeObject:self.window.rootViewController forKey:AppDelegateRootVCKey];
}
- (void)application:(UIApplication *)application didDecodeRestorableStateWithCoder:(NSCoder *)coder {
// Grabs the preserved root view controller.
UIViewController * vc = [coder decodeObjectForKey:AppDelegateRootVCKey];
if (vc) {
UIWindow * window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
window.rootViewController = vc;
window.restorationIdentifier = NSStringFromClass([window class]);
// The green color is just to make it obvious if our view didn't load properly.
// It can be removed when you are finished debugging.
window.backgroundColor = [UIColor greenColor];
self.window = window;
}
}
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
if (!self.window) {
UIWindow *window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
// The blue color is just to make it obvious if our view didn't load properly.
// It can be removed when you are finished debugging.
window.backgroundColor = [UIColor blueColor];
UIViewController *root = // However you create your root.
window.rootViewController = root;
window.restorationIdentifier = NSStringFromClass([window class]);
self.window = window;
}
[self commonInitializationLaunching:launchOptions];
[self.window makeKeyAndVisible];
return YES;
}
Another gotcha to watch out for is to make sure that your UINavigationControllers and UITabBarControllers have restoration identifiers.
State restoration is generally integrated with storyboards. If you're using a storyboard, you should not be creating your own window, view controllers, etc. You should let the storyboard do this for you. What's happening is that the storyboard is doing all the state restoration, and then you're creating a new window and laying it on top of all that. If that's the case, you're probably creating two copies of your UI on every launch. You're just not noticing it.
If you are constructing your entire interface in code (not a recommended approach, but it does work), then you need to determine whether state restoration happened before creating your UI. This is fairly simple:
In your commonInitializationLaunching:, initialize only non-UI elements (things that wouldn't ever be in state-preservation). This is the place to handle things that the UI elements might rely on during state restoration. You don't have any of these in your current code.
In application:didDecodeRestorableState:, set an app delegate ivar to indicate that state was restored.
In application:didFinishLaunchingWithOptions:, after running commonInitializationLaunching:, check your ivar. If state wasn't restored, create a UI.
Do remember that the commonInitializationLaunching: pattern only exists for backward compatibility with iOS 5. If you don't need that, then just put non-UI in willFinish and UI in didFinish (if state wasn't restored).

No known instance method for selector

I'm developing an iOS 4 application using latest SDK, XCode 4.2 and ARC.
I've added a method to appDelegate.h
#import <UIKit/UIKit.h>
#class ViewController;
#class SecondViewController;
#interface AppDelegate : UIResponder <UIApplicationDelegate>
{
UINavigationController* navController;
ViewController* viewController;
SecondViewController* secondViewController;
}
#property (strong, nonatomic) UIWindow *window;
- (void) showSecondViewController;
#end
And it's implemented in appDelegate.m
#import "AppDelegate.h"
#import "ViewController.h"
#import "SecondViewController.h"
#implementation AppDelegate
#synthesize window = _window;
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
viewController = [[ViewController alloc] initWithNibName:#"ViewController" bundle:nil];
viewController.title = #"First";
navController = [[UINavigationController alloc] initWithRootViewController:viewController];
self.window.rootViewController = navController;
[self.window makeKeyAndVisible];
return YES;
}
- (void)applicationWillResignActive:(UIApplication *)application
{
...
}
- (void)applicationDidEnterBackground:(UIApplication *)application
{
...
}
- (void)applicationWillEnterForeground:(UIApplication *)application
{
...
}
- (void)applicationDidBecomeActive:(UIApplication *)application
{
...
}
- (void)applicationWillTerminate:(UIApplication *)application
{
...
}
- (void) showSecondViewController
{
secondViewController = [[SecondViewController alloc] initWithNibName:#"SecondViewController" bundle:nil];
secondViewController.title = #"Second";
[navController pushViewController:secondViewController animated:YES];
}
#end
But, when I send a message to that method in ViewController.m
- (IBAction)goSecondClicked:(id)sender
{
[[[UIApplication sharedApplication] delegate] showSecondViewController];
}
I get the following compiler error:
Automatic Reference Counting Issue
No known instance method for selector 'showSecondViewController'
Any clue?
You will need to cast the delegate object that you get as:
AppDelegate *appDelegate = (AppDelegate*)[[UIApplication sharedApplication] delegate];
Then call the method on appDelegate
Change your goSecondClicked action method to this:
- (IBAction)goSecondClicked:(id)sender
{
[[[UIApplication sharedApplication] delegate] performSelector:#selector(showSecondViewController)];
}
EDIT: although this alternative works for the given situation, it should be noted that the compiler won't help you if you change the method name in your delegate and forget to change the name on the selector call. So, this should be used carefully.
You can also define this macro on your AppDelegate.h
#define APP_DELEGATE (AppDelegate *)[[UIApplication sharedApplication] delegate]
After this, you can invoke your selector with:
[APP_DELEGATE showSecondViewController];

releasing objects?

I'm really new to iPhone programming.
This app is a simple quiz. FirstAppDelegate.m creates an instance of QuizViewController and adds its view to the window.
#import "FirstAppDelegate.h"
#import "ResultViewController.h"
#import "QuizViewController.h"
#implementation FirstAppDelegate
#synthesize window;
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions (NSDictionary *)launchOptions {
UIViewController *vc = [[QuizViewController alloc] init];
[window addSubview:[vc view]];
[window makeKeyAndVisible];
[vc release];
return YES;
}
- (void)dealloc {
[window release];
[super dealloc];
}
#end
I thought I could release vc like I do hear since window will retain it (?) but it generated an error :
2011-06-28 23:06:34.190 First[14289:207] -[__NSCFType foo:]: unrecognized selector sent to instance 0x4e1fc90
2011-06-28 23:06:34.193 First[14289:207] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[__NSCFType foo:]: unrecognized selector sent to instance 0x4e1fc90'
...so I commented it and now it works fine. But where should I release vc? Here's QuizViewController.h:
#import <UIKit/UIKit.h>
#interface QuizViewController : UIViewController {
IBOutlet UILabel *questionLabel;
IBOutlet UIButton *button1;
IBOutlet UIButton *button2;
IBOutlet UIButton *button3;
int currentQuestionIndex;
int corrects;
NSMutableArray *questions;
NSMutableArray *answers;
NSMutableArray *correctAnswers;
}
- (IBAction)foo:(id)sender;
#end
...and QuizViewController.m:
#import "QuizViewController.h"
#implementation QuizViewController
- (id)init {
NSLog(#"QuizViewController init");
[super initWithNibName:#"QuizViewController" bundle:nil];
questions = [[NSMutableArray alloc] init];
answers = [[NSMutableArray alloc] init];
correctAnswers = [[NSMutableArray alloc] init];
[questions addObject:#"Vad betyder det engelska ordet \"though\"?"];
[answers addObject:#"Tuff"];
[answers addObject:#"Dock"];
[answers addObject:#"Tanke"];
[correctAnswers addObject:#"Dock"];
[questions addObject:#"Vad hette frontpersonen i Popbandet Queen?"];
[answers addObject:#"Pierre Bouviere"];
[answers addObject:#"Freddie Mercury"];
[answers addObject:#"Stevie Wonder"];
[correctAnswers addObject:#"Freddie Mercury"];
return self;
}
- (IBAction)foo:(id)sender {
NSLog(#"foo");
}
- (void)loadView {
NSLog(#"QuizViewController loadView");
[questionLabel setText:[questions objectAtIndex:currentQuestionIndex]];
[button1 setTitle:[answers objectAtIndex:currentQuestionIndex] forState:UIControlStateNormal];
[button2 setTitle:[answers objectAtIndex:currentQuestionIndex + 1] forState:UIControlStateNormal];
[button3 setTitle:[answers objectAtIndex:currentQuestionIndex + 2] forState:UIControlStateNormal];
[super loadView];
}
- (void)viewDidLoad {
NSLog(#"QuizViewController viewDidLoad");
[super viewDidLoad];
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
}
- (void)viewDidUnload {
[super viewDidUnload];
}
- (void)dealloc {
[super dealloc];
}
#end
You should create an instance variable to hold the VC. The reason you are losing it when you release it is that the window is only retaining the view and not the controller.
I thought I could release vc like I do hear since window will retain it...
Notice that you are adding the view associated to the view controller ([vc view]) to your UIWindow. That object will be retained, not your controller.
You can fix this by defining a variable in your FirstAppDelegate to store the controller there and release it in FirstAppDelegate dealloc.
#interface FirstAppDelegate
.....
#property (nonatomic, retain) QuizViewController* controller;
.....
#end
#implementation FirstAppDelegate
#synthesize window;
#synthesize controller;
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions (NSDictionary *)launchOptions {
self.controller = [[QuizViewController alloc] init] autorelease];
[window addSubview:[vc view]];
[window makeKeyAndVisible];
return YES;
}
- (void)dealloc {
....
[controller release]; controller = nil;
....
}
The views/windows do retain their child views, the view controllers retain their views, but the views don't retain their controllers. It's a "one-way" relationship, a clear has-a. This also comes in handy to prevent retain cycles.
You probably want to save the controller in an ivar in the class you alloc/init it, and release it in dealloc or when you pull the view from screen.
View controllers often get retained by other view controllers, i.e. when you push them onto a navigation stack, or put them in tabs.
If you don't mind dropping support for iOS 3.0/3.1/3.2, you can use the UIWindow.rootViewController property:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions (NSDictionary *)launchOptions {
UIViewController *vc = [[[QuizViewController alloc] init] autorelease];
window.rootViewController = vc;
[window makeKeyAndVisible];
return YES;
}

AppDelegate viewController memory leak?

I am just curious with regards to the correct way to create a view controller programatically. When I compile this code with the static analyser I get a leak (as you would expect) from the alloc. Should I just leave it as it needs to stay until the app exits anyways, or is there a cleaner way?
- (BOOL)application:(UIApplication *)application
didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
NSLog(#"UIApplication application:");
RectViewController *myController = [[RectViewController alloc] init];
[window addSubview:[myController view]];
[window makeKeyAndVisible];
return YES;
}
cheers Gary
In this case, keep a reference to your view controller as an instance variable on the AppDelegate and release it in the AppDelegate's dealloc method.
#interface AppDelegate : NSObject {
// ...
RectViewController *myController;
}
// ...
#end
#implementation AppDelegate
// ...
- (BOOL)application:(UIApplication *)application
didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
NSLog(#"UIApplication application:");
myController = [[RectViewController alloc] init];
[window addSubview:[myController view]];
[window makeKeyAndVisible];
return YES;
}
- (void) dealloc {
// ...
[myController release];
[super dealloc];
}
// ...
#end
Keep a reference to the view controller in you app delegate (instance, property, synthesize and release in dealloc).
And then instantiate it like this:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
NSLog(#"UIApplication application:");
RectViewController *rootControllerTemp = [RectViewController new];
self.rootController = rootControllerTemp;
[rootControllerTemp release];
[window addSubview:[self.rootController view]];
[window makeKeyAndVisible];
return YES;
}