Xcode Interface Builder Not showing App Delegate Object - objective-c

I am teaching myself Objective-C and iOS programming with "IOS Programming: The Big Nerd Ranch guide (2nd Edition) and I have run into an issue where the tutorial wants me to create connections to an App Delegate object, but this object does not appear in the Objects list in Interface builder for me. I am pretty sure its either a typo or perhaps a version different as the book is slightly behind my version of Xcode (4.2). I have included the code. I am fairly certain that the MOCAppDelegate object is what should be showing up in IB, but I am not yet familiar enough to know what code changes I need to make that happen. Specific question: How do I adjust the code below so that I get an object in the Objects list in IB so that I can perform the connections as instructed in the tutorial graphic?
Note: I researched and found this: Having trouble hooking up instance variables to AppDelegate but this solution did not work for me (or I did not implement it correctly)
Header File
#import <UIKit/UIKit.h>
#import <CoreLocation/CoreLocation.h>
#import <MapKit/MapKit.h>
#interface MOCAppDelegate : UIResponder <UIApplicationDelegate, CLLocationManagerDelegate>
{
CLLocationManager *locationManager;
IBOutlet MKMapView *worldView;
IBOutlet UIActivityIndicatorView *activityIndicator;
IBOutlet UITextField *locationTitleField;
}
#property (strong, nonatomic) IBOutlet UIWindow *window;
#end
Implementation File
#import "MOCAppDelegate.h"
#implementation MOCAppDelegate
#synthesize window = _window;
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
//Create location manager object
locationManager = [[CLLocationManager alloc] init];
[locationManager setDelegate:self];
//We want all results from the location manager
[locationManager setDistanceFilter:kCLDistanceFilterNone];
//And we want it to be as accurate as possible
//regardless of how much time/power it takes
[locationManager setDesiredAccuracy:kCLLocationAccuracyBest];
//Tell our location manager to start looking for it location immediately
[locationManager startUpdatingLocation];
//We also want to know our heading
if (locationManager.headingAvailable == true) {
[locationManager startUpdatingHeading];
}
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
// Override point for customization after application launch.
self.window.backgroundColor = [UIColor darkGrayColor];
[self.window makeKeyAndVisible];
return YES;
}
- (void)locationManager:(CLLocationManager *)manager
didUpdateToLocation:(CLLocation *)newLocation
fromLocation:(CLLocation *)oldLocation
{
NSLog(#"%#", newLocation);
}
- (void)locationManager:(CLLocationManager *)manager
didUpdateHeading:(CLHeading *)newHeading
{
NSLog(#"%#", newHeading);
}
- (void)locationManager:(CLLocationManager *)manager
didFailWithError:(NSError *)error
{
NSLog(#"Could not find location: %#", error);
}
- (void)dealloc
{
if( [locationManager delegate] == self)
[locationManager setDelegate:nil];
}
- (void)applicationWillResignActive:(UIApplication *)application
{
/*
Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.
Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game.
*/
}
- (void)applicationDidEnterBackground:(UIApplication *)application
{
/*
Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later.
If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
*/
}
- (void)applicationWillEnterForeground:(UIApplication *)application
{
/*
Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background.
*/
}
- (void)applicationDidBecomeActive:(UIApplication *)application
{
/*
Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
*/
}
- (void)applicationWillTerminate:(UIApplication *)application
{
/*
Called when the application is about to terminate.
Save data if appropriate.
See also applicationDidEnterBackground:.
*/
}
#end

Drag an instance of NSObject into your .xib and drop it in the Objects section just as in the instructions you've got. Then select it and change its type in the identity inspector (on the right side, where it says "Custom Class") to "MOCAppDelegate" (or whatever class you like).

You should drag an "NSObject" from the Object Library onto your storyboard on the black bar underneath the view controller you want to connect. Then, click on the NSObject and in the identity inspector change the class to AppDelegate. Then you can create the connection to the AppDelegate.

MOCAppDelegate = AppDelegate
The code was generated for you when you named the project. The delegate of the UIApplication object is usually named slightly different depending on the name of the project.
(There's no doubt that any book in print was using an older Xcode.)
Select Files Owner and the Identity Inspector (command-alt-2) to confirm the file's owner is a place holder for the app delegate.

Related

didUpdateLocations is not called in ios 9.3.2

didUpdateLocations is never called, instead didFailWithError is called with denied code kCLErrorDenied.
Here are the things that i did:
#import "ViewController.h"
#import CoreLocation;
#interface ViewController () <CLLocationManagerDelegate>
#property (strong, nonatomic) CLLocationManager *locationManager;
#end
#implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
self.locationManager = [[CLLocationManager alloc] init];
self.locationManager.delegate = self;
// Check for iOS 8. Without this guard the code will crash with "unknown selector" on iOS 7.
if ([self.locationManager respondsToSelector:#selector(requestWhenInUseAuthorization)]) {
[self.locationManager requestWhenInUseAuthorization];
}
[self.locationManager startUpdatingLocation];
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (void)locationManager:(CLLocationManager *)manager didUpdateLocations:(nonnull NSArray<CLLocation *> *)locations
{
NSLog(#"update");
}
- (void)locationManager:(CLLocationManager *)manager didFailWithError:(nonnull NSError *)error
{
NSLog(#"error");
}
#end
Inserted NSLocationWhenInUseUsageDescription and NSLocationAlwaysUsageDescription to the info.plist of the app. Enabled Background Modes in Capabilities with Location updates selected. Get help from the very famous blog post. I receive Location Access Request popup and allow the app to access location.
But i couldnt managed to get location updates. It works in IPAD with IOS 8 but not work at ipad with IOS version 9.3.2. How can i make location updates work in IOS 9.3.2?
trying following thing may resolve your issue:
go to settings and reset your location services
reset your network settings
restarting the simulator
also, if you have Scheme/Edit Scheme/Options/Allow Location Simulation checked but don't have a default location set.
Add NSLocationAlwaysUsageDescription to your plist as type string if using Always authorization. Also, do the same for NSLocationWhenInUseUsageDescription same way if using WhenInUse authorization.
For detail check answers here:
didFailWithError: Error Domain=kCLErrorDomain Code=0 "The operation couldn’t be completed. (kCLErrorDomain error 0.)"
and IOS 9 Error Domain=kCLErrorDomain Code=0 "(null)"

How to fix "property implementation must have its declaration in interface 'Appdelegate'"

//
// AppDelegate.m
// Foody
//
// Created by Iceeiei on 5/2/15.
// Copyright (c) 2015 pondandfriend. All rights reserved.
//
#import "AppDelegate.h"
#import "ViewController.h"
#import "RecipeList.h"
#interface AppDelegate ()
#end
#implementation AppDelegate
#synthesize window = _window;
#synthesize viewController = _viewController;
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
self.viewController = [[ViewController alloc]initWithNibName:#"ViewController" bundle:nil];
RecipeList *recipeList = [[RecipeList alloc] initWithNibName:#"RecipeList" bundle:nil];
self.window.rootViewController = recipeList;
[self.window makeKeyAndVisible];
return YES;
}
- (void)applicationWillResignActive:(UIApplication *)application {
// Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.
// Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game.
}
- (void)applicationDidEnterBackground:(UIApplication *)application {
}
- (void)applicationWillEnterForeground:(UIApplication *)application {
}
- (void)applicationDidBecomeActive:(UIApplication *)application {
// Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
}
- (void)applicationWillTerminate:(UIApplication *)application {
// Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
}
#end
Error 1:
property implementation must have its declaration in interface 'Appdelegate'
Error 2:
Property'viewController' not found on object of type 'AppDelegate'
Is there any way to fix this?
It looks like you haven't added the #property notation for your ViewController in the .h. Add the following to AppDelegate.h:
#propery (nonatomic) ViewController *viewController;

NSView/NSViewController memory management

In a very simple test app, I have an NSViewController (strongly retained) in the appdelegate. I put this NSView inside the contentView of my NSWindow (which I have set to Release on Close in Interface Builder). But, when I exit the app, the NSView's dealloc method is never called. I would have expected it to be called by the following flow - NSWindow dealloc -> removes content view -> removes all subviews.
Also, TestViewController is not dealloced, unless I set the strong reference to it, to be nil in AppDelegate's applicationWouldTerminate method. Again, I would have expected it to be dealloced. But, it looks like AppDelegate is never dealloced.
I must be missing something basic in my understanding of Objective-C memory management. Could it be because on Mavericks Apple does a force quit of apps and hence there is no cleanup? I would appreciate being pointed in the right direction on this. Thanks
My Code
#import "AppDelegate.h"
#interface TestView : NSView
#end
#implementation TestView
- (void)dealloc { NSLog(#"TestView - Dealloc"); }
#end
#interface TestViewController : NSViewController
#end
#implementation TestViewController
- (void)loadView { self.view = [[TestView alloc] init]; }
- (void)dealloc { NSLog(#"TestViewController - dealloc"); }
#end
#interface AppDelegate ()
#property (weak) IBOutlet NSWindow* window;
#property (strong) TestViewController* testViewController;
#end
#implementation AppDelegate
- (void)dealloc { NSLog(#"AppDelegate - dealloc"); }
- (void)applicationDidFinishLaunching:(NSNotification*)aNotification
{
// Insert code here to initialize your application
TestViewController* testViewController = [[TestViewController alloc] init];
self.testViewController = testViewController;
[self.window.contentView addSubview:testViewController.view];
}
- (void)applicationWillTerminate:(NSNotification*)aNotification
{
// Insert code here to tear down your application
// self.testViewController = nil;
}
#end
App termination doesn't bother cleaning up all of the individual objects. When the process terminates, the OS X kernel simply reclaims all of the resources used by the process. This is much faster.
From the Advanced Memory Management Programming Guide:
When an application terminates, objects may not be sent a dealloc message. Because the process’s memory is automatically cleared on exit, it is more efficient simply to allow the operating system to clean up resources than to invoke all the memory management methods.
If you have stuff that really needs to be done just before the app terminates, either put it in the app delegate's -applicationWillTerminate: method or observe the NSApplicationWillTerminateNotification notification posted by the application object. Also, you need to not opt-in to sudden termination or, if your app is generally opted in to it, temporarily disable it for as long as it has something it really needs to do at termination.

Calling view controller method from appdelegate doesn't work when using Storyboard

Good day everyone,
I am not able to call the method refresh in my ViewController when using a Storyboad. However it works if I create the project without the Storyboard, just a NIB. Why it doesn't work and how to overcome this issue?
Here is my code:
AppDelegate.h
#import <UIKit/UIKit.h>
#class ViewController;
#interface AppDelegate : NSObject <UIApplicationDelegate>
{
UIWindow *window;
ViewController *viewController;
}
#property (nonatomic, retain) IBOutlet UIWindow *window;
#property (nonatomic, retain) IBOutlet ViewController *viewController;
#end
AppDelegate.m
#import "AppDelegate.h"
#import "ViewController.h"
#implementation AppDelegate
#synthesize window;
#synthesize viewController;
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
// Override point for customization after application launch.
return YES;
}
- (void)applicationWillResignActive:(UIApplication *)application
{
// Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.
// Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game.
}
- (void)applicationDidEnterBackground:(UIApplication *)application
{
// Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later.
// If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
}
- (void)applicationWillEnterForeground:(UIApplication *)application
{
// Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background.
NSLog(#"app will enter foreground");
[viewController refresh:NULL];
}
- (void)applicationDidBecomeActive:(UIApplication *)application
{
// Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
}
- (void)applicationWillTerminate:(UIApplication *)application
{
// Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
}
#end
ViewController.h
#import <UIKit/UIKit.h>
#interface ViewController : UIViewController
-(IBAction) refresh:(id)sender;
#end
ViewController.m
#import "ViewController.h"
#interface ViewController ()
#end
#implementation ViewController
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
}
- (void)viewDidUnload
{
[super viewDidUnload];
// Release any retained subviews of the main view.
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
return (interfaceOrientation != UIInterfaceOrientationPortraitUpsideDown);
}
- (void)loadData {
// contains information the ViewController makes use of
}
-(IBAction)refresh:(id) sender {
[self loadData];
}
#end
The viewController property in your app delegate are not populated when using a storyboard. Include the value in your log statement for confirmation - it will be null.
Register your view controller for the notification instead, and let it handle it's own refreshing.
In viewDidLoad:
[super viewDidLoad];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(refresh:)
name:UIApplicationDidBecomeActiveNotification
object: nil];
You'll want to remove this observer in dealloc / viewDidUnload as well.

Show new window from status menu [duplicate]

OK, what am I doing wrong?
1. Created cocoa app and appDelegate named: window2AppDelegate
2. window2AppDelegate.h
#import "PrefWindowController.h"
#interface window2AppDelegate : NSObject <NSApplicationDelegate> {
NSWindow *window;
PrefWindowController * ctrl;
}
#property (assign) IBOutlet NSWindow *window;
- (IBAction) buttonClick:(id)sender;
- (IBAction) buttonCloseClick:(id)sender;
#end
3. in xib editor, window connected to window controller - set to appdelegate, buttonclick actions to buttons
4, created
#import <Cocoa/Cocoa.h>
#interface PrefWindowController : NSWindowController {
#private
}
#end
#import "PrefWindowController.h"
#implementation PrefWindowController
- (id)init {
self = [super initWithWindowNibName: #"PrefWindow"];
return self;
}
- (void)dealloc {
// Clean-up code here.
[super dealloc];
}
- (void)windowDidLoad {
[super windowDidLoad];
// Implement this method to handle any initialization after your window controller's window has been loaded from its nib file.
}
#end
5. created new xib file named PrefWindow window IBOutlet connected to window from its controller (also controller set to PrefWindowController) Option "Visible At Launch" UNCHECKED! i want to see this window on buttonclick.
6. implemented window2AppDelegate
#import "window2AppDelegate.h"
#implementation window2AppDelegate
#synthesize window;
- (id) init {
if ((self = [super init])) {
ctrl = [[PrefWindowController alloc] init];
if ([ctrl window] == nil)
NSLog(#"Seems the window is nil!\n");
}
return self;
}
- (BOOL)applicationShouldTerminateAfterLastWindowClosed:(NSApplication *)sender {
return YES;
}
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification {
// Insert code here to initialize your application
}
- (IBAction) buttonClick:(id)sender {
// [[ctrl window] makeKeyAndOrderFront:self]; this doesn't work too :(
NSLog(#"it is here");
[ctrl showWindow:sender];
}
- (IBAction) buttonCloseClick:(id)sender {
[window close];
}
#end
7. After I build and run app: closebutton closes the app but buttonclick - won't show me PrefWindow!? Why and what am i doing wrong? Don't dell me that to show other window in cocoa objective-c is more difficult than in "stupid" Java or C#?
Finally i've managed the problem! In the nib editor for PrefWindow I had to do: Set File's owner class to: NSWindowController then connect window IBOutlet from File's owner to my (preferneces) window. After 6 days of unsuccessful attempts, google works.
Anyway, thanks for all your responses and time!
I'd suggest you move the creation of the PrefWindowController to applicationDidFinishLaunching:
I am not sure the application delegate's init method is called. Probably only initWithCoder: gets called when unarchiving the object from the NIB.
- (id) init {
if ((self = [super init])) {
ctrl = [[PrefWindowController alloc] init];
if ([ctrl window] == nil)
NSLog(#"Seems the window is nil!\n");
}
return self;
}
init is way too early in the scheme of things to be trying to test IBOutlets. They will still be nil yet. Not until later on in the object creation process will the nib outlets be "hooked up". The standard method where you can know that everything in the nib file has been hooked up is:
- (void)awakeFromNib {
}
At that point, all of your IBOutlets should be valid (provided they're not purposely referencing an object in a separate, yet-unloaded nib).
If PrefWindowController is a class that will only be used after the user chooses Preferences from the app menu, I would have to disagree with the others and say that I would not create the instance of the PrefsWindowController at all during the initial load. (Your main controller should be able to function independently from the prefs window). If you have a method that is meant to load the preferences window, then when that method is called, you should check to see if the PrefsWindowController instance is nil, and if it is, create it, then proceed to show the prefs window.