No visible #interface for 'CLLocation' declares the selector 'setDesiredAccuracy:' - objective-c

I added the CoreLocation framework, and I keep rereading the code in my book to make sure I copied it down correctly but I am getting a persistent No visible #interface for 'CLLocation' declares the selector 'setDesiredAccuracy:' error.
#import <UIKit/UIKit.h>
#import <CoreLocation/CoreLocation.h>
#interface WhereamiViewController : UIViewController {
CLLocation *locationManager;
}
#end
#import "WhereamiViewController.h"
#interface WhereamiViewController ()
#end
#implementation WhereamiViewController
-(id) initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil {
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
locationManager = [[CLLocation alloc] init
[locationManager setDesiredAccuracy:kCLLocationAccuracyBest];
}
return self;
}
#end

You want CLLocationManager, not CLLocation.

I think you wanted to use CLLocationManager ...
CLLocationManager *locationManager;

Only CLLocationManager declares a selector named -setDesiredAccuracy, not CLLocation.

CLLocation
is a location object, it holds a specific coordinate/location, that can be displayed on a map view. However, CLLocationManager is an object which manages location and heading updates. setDesiredAccuracy is the method where you set the accuracy of the location manager's location and heading updates. If you set the accuracy high, the location manager will update with a very accurate point of where you are, but considerably slow. (Not really, but when you compare to other accuracies).
The delegate method where the location updates it:
- (void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation {
To start the updates, you can first customize it like you said, with the accuracy and distance filter. Then to start, simply write:
[locationManager startUpdatingLocation];
And, so I can guess how you would stop updates.
NOTE: If you are on ARC, make your location manager an instance variable (declared in .h) because it releases the location manager very quickly and the popup to let the user decide if your app can track you location will popup and then disappear in less than a second. And of course your locations wont update.

Related

Is this a correct approach to connect screens?

i am a .net programmer and last week i started to read about objective-c. Class related stuff are kinda clear and today i learnt about protocols and delegates, i can't say it is 100% clear but i got it, it looks a lot with delegates and events from c#.
This is a simple example i created following a tutorial. It is all about 2 screens, the first one(a label and a button) launches the second one(a textbox and a button) which sends back a string. I think of it as a classic example of using events, no matter the programming language.
#import <UIKit/UIKit.h>
#import "ValueViewController.h"
#interface ViewController : UIViewController<ValueViewControllerDelegate>
- (IBAction)btnGetValue:(id)sender;
#property (weak, nonatomic) IBOutlet UILabel *lblCurrentValue;
#end
#import "ViewController.h"
#import "ValueViewController.h"
#interface ViewController ()
#end
#implementation ViewController
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (IBAction)btnGetValue:(id)sender {
ValueViewController *valueVC = [self.storyboard instantiateViewControllerWithIdentifier:#"ValueViewController"];
valueVC.delegate=self;
[self presentViewController:valueVC animated:FALSE completion:nil];
}
-(void) sendValue:(ValueViewController *)controller didFihishWithValue:(NSString *)value
{
self.lblCurrentValue.text=value;
}
#end
#import <UIKit/UIKit.h>
#class ValueViewController;
#protocol ValueViewControllerDelegate<NSObject>
-(void) sendValue:(ValueViewController*) controller didFihishWithValue:(NSString*) value;
#end
#interface ValueViewController : UIViewController<UITextFieldDelegate>
#property (weak, nonatomic) IBOutlet UITextField *txtValue;
- (IBAction)btnSetValue:(id)sender;
#property (weak, nonatomic) id<ValueViewControllerDelegate> delegate;
#end
#import "ValueViewController.h"
#interface ValueViewController ()
#end
#implementation ValueViewController
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
self.txtValue.delegate=self;
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
-(BOOL)textFieldShouldReturn:(UITextField *)textField
{
return [textField resignFirstResponder];
}
- (IBAction)btnSetValue:(id)sender
{
[self.delegate sendValue:self didFihishWithValue:self.txtValue.text];
[self dismissViewControllerAnimated:FALSE completion:nil];
}
#end
My question is the following: Considering a, let's say, 30 screens application, which allows sending and receiving messages, adding friends , etc
Is it a good approach to group those 4-5 message view controller into a storyboard, those friends related view controllers into another storyboard and just make the connection like i did in that simple example, programmatically?
I saw that connections can be done in the designer without writing code, but sometimes i think you have to write code to send some arguments which means mixing the two(graphically and programmatically).
I just feel more comfortable, doing it programatically, maybe because this is how i do it in c#.
I am looking forward to you tips regarding organizing and making connections between screens.
PS: Sorry for writing such a long story(board) in here, i promise to make it shorter in my following posts.
Thanks.
Making two storyboards that communicate with each other would go against the intended flow, because storyboards were not intended for grouping parts of an application. Although an app may definitely have multiple storyboards, the intention behind allowing multiple storyboards was letting you support different screen paradigms (i.e. iPhone vs. iPad) or different localizations, not grouping related screens together.
Note, however, that storyboards are relatively new. You can define your views in NIB files, and use them instead. An unfortunate consequence of this choice is that you would need to make all your connections programmatically, but on the other hand you would be able to group your views inside you Xcode project using file groups or folders.

calling delegates in viewdidload

Quick question,
i have made a custom delegate
PupilView.h
#protocol DismissPupilViewPopoverDelegate
- (int) getPupilViewReason;
#end
#interface PupilView : UIViewController{
id<DismissPupilViewPopoverDelegate> delegate;
}
#property (nonatomic, assign) id<DismissPupilViewPopoverDelegate> delegate;
It is called in PupilView.m like follows
[[self delegate] getPupilViewReason];
in in my maincontroller.h
#import "PupilView.h"
#interface MainScreen : UIViewController<DismissPupilViewPopoverDelegate>
maincontroller.m
-(int) getPupilViewReason
{
return 100;
}
If i put the [[self delegate] getPupilViewReason]; in any function in pupilview.m it works perfectly, returns 100 i can see it with a breakpoint etc.
If i put it in viewdidload it dosn't load, returns 0, dosnt hit breakpoints etc. Any help as to why.
thanks
make a custom init method for the view controller where you pass the delegate so you can set the delegate in the init method before viewdidload is called.
#interface
- initWithDelegate:(id)aDelegate nibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
//...
#end
#implementation
- initWithDelegate:aDelegate nibName:nibNameOrNil bundle:nibBundleOrNil{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
_delegate = aDelegate;
///rest of init implementation
}
}
- (void)viewDidLoad{
[super viewDidLoad];
[self.delegate getPupilViewReason];
}
//...
#end
Go ahead and call. If the delegate is set up properly then it should work. Do you mean when you're doing a segue UI transfer?
Yes, you can call the delegate in viewDidLoad function.
Suppose your delegate(request owner) name is "delegate" then you can call like -
- (void)viewDidLoad
{
[super viewDidLoad];
[<OBJ>.delegate GetPupilViewReason];
}
OBJ - is the instance of a class, have assign the delegate.

trying to subclass UIApplication and implement it in delegate, but am confused by delegates

I'm trying to follow the suggestion in the accepted answer at How to intercept click on link in UITextView? , but I've managed to get myself very confused, partially because I don't understand delegation very well, and by now I've added and deleted so many things I have no idea what's going on.
Here's GHFeedback.h:
#import <UIKit/UIKit.h>
#import "GHApplicationSubclassed.h"
#interface GHFeedback : UIViewController <UIApplicationDelegate>
#property (nonatomic, strong) UITextView *feedbackInstructions;
#property (nonatomic, strong) GHApplicationSubclassed *ghAppSub;
#end
Here's GHFeedback.m:
#import "GHFeedback.h"
#import <MessageUI/MessageUI.h>
#import "GHApplicationSubclassed.h"
#interface GHFeedback () <UIApplicationDelegate, MFMailComposeViewControllerDelegate>
#end
#implementation GHFeedback
#synthesize feedbackInstructions, ghAppSub;
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
self.ghAppSub.delegate=self;
}
return self;
}
-(void)openURL:(NSURL *)url //This is the method I'm trying to add--the text set for self.feedbackInstructions in IB contains an email address, and I want a subject line to appear automatically if the user sends an email.
{
MFMailComposeViewController *mailer = [[MFMailComposeViewController alloc] init];
mailer.mailComposeDelegate = self;
[mailer setSubject:#"feedback on Haiku"];
[self presentViewController:mailer animated:YES completion:NULL];
}
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view from its nib.
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#end
Here's GHApplicationSubclassed.h:
#import <UIKit/UIKit.h>
#interface GHApplicationSubclassed : UIApplication <UIApplicationDelegate>
#property (nonatomic, strong) GHApplicationSubclassed *appli;
#end
Here's GHApplicationSubclassed.m:
#import "GHApplicationSubclassed.h"
#implementation GHApplicationSubclassed
#synthesize appli;
-(BOOL)openURL:(NSURL *)url
{
if ([self.delegate openURL:url]) //This line gets an error, "no known instance method for selector 'openURL'
return YES;
else
return [super openURL:url];
}
#end
I'd love explicit instructions on how to fix this. (By "explicit" I mean that, rather than saying something like, "then implement the delegate method," you could say something like, "then add this method to GHFeedback.m: -(void)openURL {[actual methods, etc., etc.]}.
Thanks so much for your help.
EDIT: What I want to happen is this.
There's a UITextView displayed in the view controller for GHFeedback that says, "if you have any questions/problems with the app, please email me," and then gives my email address. Right now, when the user presses that email address, the iOS Mail program opens an empty draft email. I would like to give the draft email that opens an automatic subject line of "feedback on Haiku."
if ([self.delegate openURL:url])
The return type of openURL: is void, so there is actually nothing to check in this if-statement.
maybe you want to use
if ([(GHFeedback *)self.delegate respondsToSelector:#selector(openURL:)]{
[(GHFeedback *)self.delegate openURL:url];
return YES;
}
if the correct openURL: still wont get fired, the self.delegate must be nil.

Xcode Interface Builder Not showing App Delegate Object

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.

EXC_BAD_ACCESS error on very simple code

I am using the nav controller and pushing another view into the stack and setting a variable too. While trying to access the variable I get EXEC_BAD_ACCESS :(
Here's the code (I am not using any NIB) :
#import <UIKit/UIKit.h>
#interface detailedView : UIViewController {
NSString *movieName2;
}
#property (nonatomic, retain) NSString *movieName2;
#end
and
#import "detailedView.h"
#implementation detailedView
#synthesize movieName2;
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
}
return self;
}
-(void) viewDidAppear:(BOOL)animated
{
self.view=[[UIView alloc] initWithFrame:[[UIScreen mainScreen] applicationFrame]];
self.view.frame=CGRectMake(213, 300, 355, 315);
self.view.backgroundColor=[[UIColor alloc] initWithPatternImage:[UIImage imageNamed:#"black.png"]];
self.title=self.movieName2;
NSLog(#"%#",movieName2);
}
Relevant code in the caller function :
detailedView *details;
#property (nonatomic, retain) detailedView *details;
//properly synthesized and released
-(void) tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
NSLog(#"Did Reach inside...");
status=1;
self.title=#"Back";
details.movieName2=self.movieName;
NSLog(#"```");
NSLog(#"2nd VC %# sdfsdf",details.movieName2); //Getting the ERROR here
NSLog(#"1st VC %# wrewrw",self.movieName);
//viewerSearch *viewerSearchController=[[viewerSearch alloc] init];
[[self navigationController] pushViewController:details animated:NO];
}
init:
details=[[detailedView alloc] init];
//movieName is a NSString and has #property(nonatomic,copy)
When an app crashes, there will be a crash log or you'll be able to get a backtrace from the debugger. Always post that.
Also -- class names should always start with a capital letter.
Try Build and Analyze; make sure your memory management is correct.
Then turn on Zombie detection once you fix any build and analyze found problems.
Based on a test by calling a retain on a alloc-init-released NSString and then following it up by logging it, I think your problem is that self.movieName is deallocated. Please check whether the memory management rules have been properly followed with regards to self.movieName.
On a side note, if you are not using a NIB for detailedView then you should create the view in loadView and not viewDidAppear: as you seem to be doing. viewWillAppear: only if the view exists, right? I suggest you move the related code from viewDidAppear: to loadView.
You should always copy strings instead of retaining them.
So changing
#property (nonatomic, retain) NSString *movieName2;
to
#property (nonatomic, copy) NSString *movieName2;
will probably fix your problem.
Also, if you create the value in self.movieName with #"something", do not release the value.