passing data to a view controller - ios

Here is my button function where I pass the data.
The problem is Area and Country details are passed to the next ViewController but latitude and longitude return null.
In ViewController.m :
- (IBAction)forecast:(UIButton *)sender
{
ForecastViewController *sendDetails = [[ForecastViewController alloc] init];
NSArray *seperate = [full componentsSeparatedByString:#", "];
Area = seperate[0];
Country = seperate[1];
sendDetails.Area = Area;
sendDetails.Country = Country;
NSLog(#"%#%#",self.longitude,self.latitude);
NSString *lt = self.latitude;
NSString *ln = self.longitude;
sendDetails.longitude = lt;
sendDetails.latitude = ln;
}
In ForecastViewController.h
//
// ForecastViewController.h
// Weather App
//
// Created by Mac-Mini-2 on 10/02/16.
// Copyright © 2016 Mac-Mini-2. All rights reserved.
//
#import <UIKit/UIKit.h>
#import <CoreData/CoreData.h>
#import <Reachability.h>
#interface ForecastViewController : UIViewController <UITableViewDataSource,UITableViewDelegate>
#property (weak, nonatomic) IBOutlet UILabel *place;
#property (weak, nonatomic) IBOutlet UITableView *table;
#property (weak, nonatomic) IBOutlet UIActivityIndicatorView *activityIndicator;
#property NSString *Area;
#property NSString *Country;
#property NSString *latitude;
#property NSString *longitude;
#end
In ForecastViewController.m
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view.
self.table.delegate = self;
self.table.dataSource = self;
self.place.text = [NSString stringWithFormat:#"%#, %#",self.Area,self.Country];
locationName = [NSString stringWithFormat:#"%#, %#",self.Area,self.Country];
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
metric = [defaults boolForKey:#"metric"];
Reachability *reach = [Reachability reachabilityWithHostName:#"www.google.com"];
NSInteger x = [reach currentReachabilityStatus];
if (x > 0)
{
reachable = YES;
NSLog(#"%#, %#",self.latitude,self.longitude);
[self getForecast:self.latitude longitudes:self.longitude];
}
else
{
reachable = NO;
[self getData];
errorMsg = #"Because of unavailability of Network Realtime information wont be available.";
[self performSelectorOnMainThread:#selector(displayAlert) withObject:NULL waitUntilDone:YES];
}
[reach startNotifier];
}
Please let me know where I could have gone wrong here.
I checked by logging the data onto console. The area and country is printed but longitude and latitude give null values.

if you are doing a push to ForecastViewController, maybe implementing prepareForSegue:sender: is your best option.
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if ([[segue identifier] isEqualToString:#"viewForecast"]){
NSArray *seperate = [full componentsSeparatedByString:#", "];
Area = seperate[0];
Country = seperate[1];
[(ForecastViewController *) [segue destinationViewController] setArea:area];
[(ForecastViewController *) [segue destinationViewController] setCountry:country];
...
...
}
}

Could I the that latitude and longitude are stored as numbers in the first controller? Are you sure that 'sendDetails.latitude' and 'longitude' are set correctly in 'ViewController'?

I think you need to edit two point firstly in ForecastViewController.h set
#property (Strong, nonatomic) NSString *Area;
#property (Strong, nonatomic) NSString *Country;
#property (Strong, nonatomic) NSString *latitude;
#property (Strong, nonatomic) NSString *longitude;
and #synthsize it in ForecastViewController.m.
secondly:-
- (IBAction)forecast:(UIButton *)sender
{
ForecastViewController *sendDetails = [self.storyboard instantiateViewControllerWithIdentifier:#"your ForecastViewController name in storyboard"];
NSArray *seperate = [full componentsSeparatedByString:#", "];
Area = seperate[0];
Country = seperate[1];
sendDetails.Area = Area;
sendDetails.Country = Country;
NSLog(#"%#%#",self.longitude,self.latitude);
NSString *lt = self.latitude;
NSString *ln = self.longitude;
sendDetails.longitude = lt;
sendDetails.latitude = ln;
[self.navigationController pushViewController:sendDetails animated:YES];
}

Related

Passing data using calloutAccessoryControlTapped Xcode

I am developing an app in Xcode (objective-c). My app has a TableView with a list of restaurants and when you press one row, another view is opened with the restaurant information. The method I am using is that I am sending the title in the row to the new view and depending on the title I load the information of the restaurant. I want to do exactly the same using a map pin button. My problem is that I am trying to send the TitleLabel to other ViewController but this is not working and I don't know why.
This is my map pin: RestMapPin.h:
#import <Foundation/Foundation.h>
#import <MapKit/MapKit.h>
#interface RestMapPin : NSObject <MKAnnotation> {
CLLocationCoordinate2D coordinate;
NSString *title;
NSString *subtitle;
}
#property (nonatomic, assign) CLLocationCoordinate2D coordinate;
#property (nonatomic, copy) NSString *title;
#property (nonatomic, copy) NSString *subtitle;
#end
This is my RestMappin.m:
#import "RestMapPin.h"
#implementation RestMapPin
#synthesize coordinate, title, subtitle;
#end
This is my MapViewController.h:
#import <UIKit/UIKit.h>
#import <MapKit/MapKit.h>
#interface MapViewController : UIViewController {
MKMapView *mapView;
}
#property (weak, nonatomic) IBOutlet UIBarButtonItem *barButton;
#property (nonatomic, retain) IBOutlet MKMapView *mapView;
-(IBAction)setMap:(id)sender;
#end
This is my MapViewController.m:
#import "MapViewController.h"
#import "SWRevealViewController.h"
#import "RestMapPin.h"
#import "RestViewController.h"
#import "MainTableViewController.h"
#interface MapViewController ()
#end
#implementation MapViewController
#synthesize mapView;
- (void)viewDidLoad {
[super viewDidLoad];
_barButton.target = self.revealViewController;
_barButton.action = #selector(revealToggle:);
[self.view addGestureRecognizer:self.revealViewController.panGestureRecognizer];
mapView.delegate = self;
/*Babelia*/
MKCoordinateRegion region_Babelia = { {0.0, 0.0}, {0.0, 0.0}};
region_Babelia.center.latitude = 40.4234778;
region_Babelia.center.longitude = -3.686283000000003;
region_Babelia.span.longitudeDelta = 0.1f;
region_Babelia.span.latitudeDelta = 0.1f;
[mapView setRegion:region_Babelia animated:YES];
RestMapPin *ann_Babelia = [[RestMapPin alloc] init];
ann_Babelia.title = #"Babelia";
ann_Babelia.subtitle = #"Barrio de Salamanca";
ann_Babelia.coordinate = region_Babelia.center;
[mapView addAnnotation:ann_Babelia];
/*Bacira*/
MKCoordinateRegion region_Bacira = { {0.0, 0.0}, {0.0, 0.0}};
region_Bacira.center.latitude = 40.43375390000001;
region_Bacira.center.longitude = -3.699036299999989;
region_Bacira.span.longitudeDelta = 0.1f;
region_Bacira.span.latitudeDelta = 0.1f;
[mapView setRegion:region_Bacira animated:YES];
RestMapPin *ann_Bacira = [[RestMapPin alloc] init];
ann_Bacira.title = #"Bacira";
ann_Bacira.subtitle = #"Chamberí";
ann_Bacira.coordinate = region_Bacira.center;
[mapView addAnnotation:ann_Bacira];
/*Indicador de posicion del mapa (para centrarlo)*/
MKCoordinateRegion region_posicion = { {0.0, 0.0}, {0.0, 0.0}};
region_posicion.center.latitude = 40.44934744420573;
region_posicion.center.longitude = -3.695504665374756;
region_posicion.span.longitudeDelta = 0.08f;
region_posicion.span.latitudeDelta = 0.08f;
[mapView setRegion:region_posicion animated:YES];
/*************************************************/
}
-(MKAnnotationView *)mapView:(MKMapView *)mV viewForAnnotation:(id <MKAnnotation>)annotation
{
MKAnnotationView *pinView = nil;
if(annotation != mapView.userLocation) {
static NSString *defaultPinID = #"com.invasivecode.pin";
pinView = (MKAnnotationView *)[mapView dequeueReusableAnnotationViewWithIdentifier:defaultPinID];
if ( pinView == nil )
pinView = [[MKAnnotationView alloc]
initWithAnnotation:annotation reuseIdentifier:defaultPinID];
pinView.canShowCallout = YES;
pinView.image = [UIImage imageNamed:#"pin2#2x.png"];
}
else {
//[mapView.userLocation setTitle:#"I am here"];
}
UIButton *pinButton = [UIButton buttonWithType:UIButtonTypeDetailDisclosure];
//if ([[annotation title] isEqualToString:#"Marieta"]) {
//[pinButton addTarget:self action:#selector(annotationView:) forControlEvents:UIControlEventTouchUpInside];
//}
pinView.rightCalloutAccessoryView = pinButton;
return pinView;
}
- (void)mapView:(MKMapView *)mapView annotationView:(MKAnnotationView *)view calloutAccessoryControlTapped:(UIControl *)control {
RestMapPin *selectedAnnotation = view.annotation;
NSLog(#"Title of selected pin - %#", selectedAnnotation.title);
// Here you get the title of selected annotation
//RestViewController *objYourVC = [[RestViewController alloc]init];
RestViewController *objYourVC = [self.storyboard instantiateViewControllerWithIdentifier:#"MyIdentifier"];
objYourVC.TitleLabel = selectedAnnotation. title;
NSLog(#"objYourVC.TitleLabel - %#", objYourVC.TitleLabel);
//objYourVC.DetailModal.title = selectedAnnotation.title;
//NSLog(#"objYourVC.TitleLabel - %#", objYourVC.TitleLabel);
objYourVC.DescriptionLabel = selectedAnnotation. subtitle;
NSLog(#"objYourVC.DescriptionLabel - %#", objYourVC.DescriptionLabel);
[self.navigationController pushViewController:objYourVC animated:YES];
}
-(IBAction)setMap:(id)sender {
switch (((UISegmentedControl *) sender).selectedSegmentIndex) {
case 0:
mapView.mapType = MKMapTypeStandard;
break;
case 1:
mapView.mapType = MKMapTypeSatellite;
break;
case 2:
mapView.mapType = MKMapTypeHybrid;
break;
default:
break;
}
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#end
Then I am going to show you the view that where I want to get the data of the objYourVC.TitleLabel
This is my RestViewController.h:
#import <UIKit/UIKit.h>
#import "Restaurant.h"
#interface RestViewController : UIViewController
#property (strong, nonatomic) IBOutlet UILabel *TitleLabel;
#property (strong, nonatomic) IBOutlet UILabel *DescriptionLabel;
#property (strong, nonatomic) IBOutlet UIImageView *ImageView;
//#property (strong, nonatomic) IBOutlet NSArray *DetailModal;
#property (weak, nonatomic) IBOutlet UITextView *phoneTextView;
#property (weak, nonatomic) IBOutlet UIButton *webButton;
#property (weak, nonatomic) IBOutlet UITextView *adressTextView;
#property (weak, nonatomic) IBOutlet UIButton *cartaButton;
#property (weak, nonatomic) IBOutlet UITextView *reviewTextView;
#property (weak, nonatomic) IBOutlet UILabel *updateLabel;
#property (nonatomic, strong) Restaurant *DetailModal;
#end
This is my RestViewController.m:
#import "RestViewController.h"
#import <QuartzCore/QuartzCore.h>
#interface RestViewController ()
#end
#implementation RestViewController
- (void)viewDidLoad {
[super viewDidLoad];
NSString *decDate = #"11/2016";
if ([_DetailModal.title isEqualToString:#"Babelia"]) {
_TitleLabel.text = _DetailModal.title;
_DescriptionLabel.text = _DetailModal.desc;
_ImageView.image = [UIImage imageNamed:_DetailModal.image];
_phoneTextView.text = #"(+34) 918 31 71 79";
_adressTextView.text = #"\n• Callejón de Puigcerdá, 6, Madrid, España";
[_webButton setTitle:#"Web" forState:UIControlStateNormal];
[_webButton addTarget:self action:#selector(openWeb_babelia_Url) forControlEvents:UIControlEventTouchUpInside];
[_cartaButton setTitle:NSLocalizedString (#"Menu", nil) forState:UIControlStateNormal];
[_cartaButton addTarget:self action:#selector(openCarta_babelia) forControlEvents:UIControlEventTouchUpInside];
_reviewTextView.text = NSLocalizedString(#"No reviews available.", nil);
_updateLabel.text = [NSString stringWithFormat:NSLocalizedString(#"Updated: %#", nil), decDate];
}
if ([_DetailModal.title isEqualToString:#"Bacira"]) {
_TitleLabel.text = _DetailModal.title;
_DescriptionLabel.text = _DetailModal.desc;
_ImageView.image = [UIImage imageNamed:_DetailModal.image];
_phoneTextView.text = #"(+34) 91 866 40 30";
_adressTextView.text = #"\n• Calle Del Castillo, 16, Madrid, España";
[_webButton setTitle:#"Web" forState:UIControlStateNormal];
[_webButton addTarget:self action:#selector(openWeb_bacira_Url) forControlEvents:UIControlEventTouchUpInside];
[_cartaButton setTitle:NSLocalizedString (#"Menu", nil) forState:UIControlStateNormal];
[_cartaButton addTarget:self action:#selector(openCarta_bacira) forControlEvents:UIControlEventTouchUpInside];
_reviewTextView.text = NSLocalizedString(#"No reviews available.", nil);
_updateLabel.text = [NSString stringWithFormat:NSLocalizedString(#"Updated: %#", nil), decDate];
}
}
-(void)openWeb_babelia_Url{
UIApplication *application = [UIApplication sharedApplication];
NSURL *URL = [NSURL URLWithString:#"http://babeliarestaurante.com/contactar/"];
[application openURL:URL options:#{} completionHandler:^(BOOL success) {
if (success) {
NSLog(#"Opened url");
}
}];
}
-(void)openWeb_bacira_Url{
UIApplication *application = [UIApplication sharedApplication];
NSURL *URL = [NSURL URLWithString:#"http://www.bacira.es/contacto/4585843222"];
[application openURL:URL options:#{} completionHandler:^(BOOL success) {
if (success) {
NSLog(#"Opened url");
}
}];
}
-(void)openCarta_babelia{
UIApplication *application = [UIApplication sharedApplication];
NSURL *URL = [NSURL URLWithString:#"http://babeliarestaurante.com/nuestra-cocina/las-cartas/"];
[application openURL:URL options:#{} completionHandler:^(BOOL success) {
if (success) {
NSLog(#"Opened url");
}
}];
}
-(void)openCarta_bacira{
UIApplication *application = [UIApplication sharedApplication];
NSURL *URL = [NSURL URLWithString:#"http://www.bacira.es/carta/4591994095"];
[application openURL:URL options:#{} completionHandler:^(BOOL success) {
if (success) {
NSLog(#"Opened url");
}
}];
}
#end
The problem is that the method calloutAccessoryControlTapped: is not working well because the RestViewController.m is not receiving the objYourVC.TitleLabel. What can I do?
When I run the project, the objYourVC.TitleLabel is good in the MapViewController.m (#"Bacira" for example), but when the project goes to RestViewContoller.m the TitleLable is not good, it shows (#"Label").
I know I have a low level of Xcode and I need your help. I am trying to learn more every day. Can anyone help me? Thank you very much.
Edit: This is my Restaurant.h:
#import <Foundation/Foundation.h>
#interface Restaurant : NSObject
#property (nonatomic, copy) NSString *title;
#property (nonatomic, copy) NSString *desc;
#property (nonatomic, copy) NSString *image;
- (instancetype)init:(NSString *)title descripiton:(NSString *)description image:(NSString *)image;
#end
And this is my restaurant.m:
#import "Restaurant.h"
#implementation Restaurant
- (instancetype)init:(NSString *)title descripiton:(NSString *)description image:(NSString *)image {
self = [super init];
if (self != nil) {
self.title = title;
self.desc = description;
self.image = image;
}
return self;
}
#end
You cannot directly deal with IBoutlet , because they have weak reference. o you need to store it an varaible and then in viewDidLoad you need to update the appropriate IBOutlets.
MapViewController.m
- (void)mapView:(MKMapView *)mapView annotationView:(MKAnnotationView *)view calloutAccessoryControlTapped:(UIControl *)control {
RestMapPin *selectedAnnotation = view.annotation;
NSLog(#"Title of selected pin - %#", selectedAnnotation.title);
// Here you get the title of selected annotation
//RestViewController *objYourVC = [[RestViewController alloc]init];
RestViewController *objYourVC = [self.storyboard instantiateViewControllerWithIdentifier:#"MyIdentifier"];
objYourVC.DetailModal.pagetitle= selectedAnnotation.title;
objYourVC.DetailModal.pageDescription = selectedAnnotation.desc;
[self.navigationController pushViewController:objYourVC animated:YES];
}
RestViewController.h:
#import <UIKit/UIKit.h>
#import "Restaurant.h"
#interface RestViewController : UIViewController
#property (nonatomic, strong) NSString *pageTitle;
#property (nonatomic, strong) NSString *pageDescription ;
#end
RestViewController.m:
#import "RestViewController.h"
#import <QuartzCore/QuartzCore.h>
#interface RestViewController ()
#end
#implementation RestViewController
- (void)viewDidLoad {
[super viewDidLoad];
_TitleLabel.text = _pageTitle;
_DescriptionLabel.text = _pageDescription;
}
#end

about sharedInstance SOMotionDetector and SOStepDetector objective-c

I'm working on the following code, which has the steps of a person walking. but every time I step from one view to another the counter stops. I am working with SOMotionDetector.
NOTE: when printing to console the steps that continues to function even changing views.
#import "SOMotionDetector.h"
#import "SOStepDetector.h"
#interface ContarPasos ()<SOMotionDetectorDelegate>
{
int stepCount;
}
#property (weak, nonatomic) IBOutlet UILabel *speedLabel;
#property (weak, nonatomic) IBOutlet UILabel *stepCountLabel;
#property (weak, nonatomic) IBOutlet UILabel *motionTypeLabel;
#property (weak, nonatomic) IBOutlet UILabel *isShakingLabel;
#end
#implementation ContarPasos
- (void)viewDidLoad
{
[super viewDidLoad];
__strong ContarPasos *weakSelf = self;
[SOMotionDetector sharedInstance].motionTypeChangedBlock = ^(SOMotionType motionType) {
NSString *type = #"";
switch (motionType) {
case MotionTypeNotMoving:
type = #"No estas moviendote";
break;
case MotionTypeWalking:
type = #"Caminando";
break;
case MotionTypeRunning:
type = #"Corriendo";
break;
case MotionTypeAutomotive:
type = #"Automotive";
break;
}
weakSelf.motionTypeLabel.text = type;
};
[SOMotionDetector sharedInstance].locationChangedBlock = ^(CLLocation *location) {
weakSelf.speedLabel.text = [NSString stringWithFormat:#"%.2f km/h", [SOMotionDetector sharedInstance].currentSpeed * 3.6f];
};
[SOMotionDetector sharedInstance].accelerationChangedBlock = ^(CMAcceleration acceleration) {
BOOL isShaking = [SOMotionDetector sharedInstance].isShaking;
weakSelf.isShakingLabel.text = isShaking ? #"Corriendo":#"No corriendo";
};
if (SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(#"7.0")) {
[SOMotionDetector sharedInstance].useM7IfAvailable = YES; //Use M7 chip if available, otherwise use lib's algorithm
}
[[SOMotionDetector sharedInstance] startDetection];
[[SOStepDetector sharedInstance] startDetectionWithUpdateBlock:^(NSError *error) {
if (error) {
NSLog(#"%#", error.localizedDescription);
return;
}
stepCount++;
weakSelf.stepCountLabel.text = [NSString stringWithFormat:#"Pasos: %d", stepCount];
NSLog(#"always printed on console but not in the view: %d", stepCount);
}];
}

ios cannot add new marker after passing data back to parent ViewController with EXEC_BAD_ACCESS

I am trying to implement the module for setting the map parameters before adding the new marker.
The flow is initialing new SliderViewCOntroller from parent mapViewController. After setting the values at SliderViewController and saving their values, it passes back to the parent mapViewCOntroller with new coordinates added. For the time being, the variable for the coordinates are only the global variables on the mapViewCOntroller
Actually, after saving the parameters, it shows the EXEC_BAD)ACCESS (code=1 , address = 0xc)
The code highlights at the
[[self presentingViewController] dismissViewControllerAnimated:NO completion:nil];
on the SliderViewController.m
Would you please tell me are there any other alternatives to pass the data back from child viewController to parent ViewController using protocols and delegate ?
The below is my working:
MapViewController.h
#import <MessageUI/MessageUI.h>
#import <GoogleMaps/GoogleMaps.h>
#import <UIKit/UIKit.h>
#import "SliderViewController.h"
#interface MapViewController : UIViewController<GMSMapViewDelegate , SliderViewControllerDelegate>{
}
#property (nonatomic) float verticalSliderValue;
#property (nonatomic) float circleSliderValue;
#end
MapViewController.m
//initiaing
-(void) mapView:(GMSMapView *)mapView didLongPressAtCoordinate:(CLLocationCoordinate2D)coordinate{
p = coordinate;
SliderViewController * sliderVC = [self.storyboard instantiateViewControllerWithIdentifier:#"SliderViewController"];
sliderVC.view.backgroundColor = [UIColor colorWithWhite:1.0 alpha:1.0];
sliderVC.modalPresentationStyle = UIModalPresentationCurrentContext;
[self presentViewController:sliderVC animated:YES completion:NULL];
[sliderVC release];
}
//receiving
- (void)passValue:(float )value1 : (float )valueCiruclar
{
NSLog(#"This was returned from ViewControllerB %ff",value1);
NSLog(#"This was returned from ViewControllerSlider %ff",valueCiruclar);
CheckPoints *myCar=[[CheckPoints alloc] init];
[myCar setState:0];
[myCar setLatitude:p.latitude];
[myCar setLongitude:p.longitude];
NSString* theTextValue = #"Desitnation";
[myCar setDesp:theTextValue];
[array addObject:myCar];
CheckPoints *lastChk = array.lastObject;
[self writeToTextFile:[NSString stringWithFormat:#"%#%#%#%#%#%#", lastChk.getDesp , #"\n",[NSString stringWithFormat:#"%f", lastChk.getLatitude],
#"\n", [NSString stringWithFormat:#"%f", lastChk.getLongitude], #"\n" ]];
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
[defaults setFloat:lastChk.getLatitude forKey:#"lati"];
[defaults setFloat:lastChk.getLongitude forKey:#"longi"];
[defaults setObject:lastChk.getDesp forKey:#"desp"];
[defaults synchronize];
for (int i = 0; i < [array count]; i++) {
CheckPoints *current = [array objectAtIndex:i];
if(current.getLatitude != lastChk.getLatitude && current.getLongitude != lastChk.getLongitude){
[current setState:1];
NSString* previousTitle = [NSString stringWithFormat:#"%#%#", #"Checkpoint" ,[NSString stringWithFormat:#"%i", i+1]];
[current setDesp:previousTitle];
}
}
[self addMarkers];
}
SliderViewController.h
#import <UIKit/UIKit.h>
#import "EFCircularSlider.h"
#protocol SliderViewControllerDelegate <NSObject>
- (void)passData:(float )itemVertical : (float )itemCircular ;
#end
#interface SliderViewController : UIViewController
#property (strong, nonatomic) IBOutlet UILabel *uiValue;
#property (strong, nonatomic) IBOutlet UISlider *uiSlider;
#property (strong, nonatomic) IBOutlet UIButton *btnReset;
#property (strong, nonatomic) IBOutlet UILabel *uiValue2;
#property (strong, nonatomic) EFCircularSlider* circularSlider;
#property (nonatomic) float verticalSliderValue;
#property (nonatomic) float circleSliderValue;
#property (nonatomic) id <SliderViewControllerDelegate> delegate;
- (IBAction)reset:(id)sender;
- (IBAction)sliderChange:(id)sender;
- (void)buttonClicked: (id)sender;
#end
SliderViewController.m
- (IBAction)reset:(id)sender {
[self writeToTextFile:valueV :valueC];
self.uiValue.text =[NSString stringWithFormat:#"%.2f" , 0.00];
[self.uiSlider setValue:0.00];
self.uiValue2.text =[NSString stringWithFormat:#"%.2f" , 0.00];
[_circularSlider setCurrentValue:0.0f];
MapViewController * sliderVC = [self.storyboard instantiateViewControllerWithIdentifier:#"MapViewController"];
[self.delegate passData:_uiSlider.value :_circularSlider.currentValue ];
sliderVC.modalPresentationStyle = UIModalPresentationCurrentContext;
[[self presentingViewController] dismissViewControllerAnimated:NO completion:nil];
}

Set button title programmatically

I made a button in storyboard and associated it with an IBAction in my header file. How can I set the title of this button to the variable I made displayPhone and have it call that number as well?
.h
#import <UIKit/UIKit.h>
#import <Parse/Parse.h>
#interface IBThirdViewController : UIViewController
#property (nonatomic, strong) PFRelation *agentRelation;
#property (nonatomic, strong) NSArray *agent;
#property (weak, nonatomic) IBOutlet UILabel *agentName;
#property (strong, nonatomic) IBOutlet UILabel *agentPhone;
#property (strong, nonatomic) IBOutlet UILabel *agentEmail;
#property (strong, nonatomic) IBOutlet UIImageView *agentImage;
- (IBAction)phoneButton:(id)sender;
#end
.m
#import "IBThirdViewController.h"
#import "IBAgentsTableViewController.h"
#interface IBThirdViewController ()
#end
#implementation IBThirdViewController
- (void)viewDidLoad {
[super viewDidLoad];
}
- (void)viewDidAppear:(BOOL)animated {
[super viewDidAppear:animated];
//Find the Agent and show it
self.agentRelation = [[PFUser currentUser] objectForKey:#"agentRelation"];
PFQuery *query = [self.agentRelation query];
[query findObjectsInBackgroundWithBlock:^(NSArray *objects, NSError *error) {
if (!error) {
// success
self.agent = objects;
// Do something with the found objects
for (PFObject *object in objects) {
NSLog(#"name: %#", [object objectForKey:#"name"]);
NSLog(#"email: %#", [object objectForKey:#"email"]);
NSString *displayEmail = [object objectForKey:#"email"];
NSString *displayName = [object objectForKey:#"name"];
NSString *displayPhone = [object objectForKey:#"phone"];
PFFile *thumbnail = [object objectForKey:#"profilePic"];
NSURL *imageFileURL = [[NSURL alloc] initWithString:thumbnail.url];
NSData *imageData = [NSData dataWithContentsOfURL:imageFileURL];
self.agentEmail.text = displayEmail;
self.agentName.text = displayName;
self.agentPhone.text = displayPhone;
self.agentImage.image = [UIImage imageWithData:imageData];
}
} else {
// Log details of the failure
NSLog(#"Error: %# %#", error, [error userInfo]);
}
}];
}
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
if ([segue.identifier isEqualToString:#"showEditAgent"]) {
IBAgentsTableViewController *viewController = (IBAgentsTableViewController *)segue.destinationViewController;
viewController.agents = [NSMutableArray arrayWithArray:self.agent];
}
}
- (IBAction)phoneButton:(id)sender {
}
#end
First of all you need connect button from xib with IBOutlet object:
#property (nonatomic, weak) IBOutlet UIButton *displayPhone;
Then set it's title in -(void)viewDidAppear:(BOOL)animated after loading data:
- (void)viewDidAppear:(BOOL)animated {
[super viewDidAppear:animated];
//...
// Load data here
//...
[self.displayPhone setTitle:displayPhone forState:UIControlStateNormal];
}
Finally implement IBAction method for button:
- (IBAction)phoneButton:(id)sender {
NSString *phone = [sender titleForState:UIControlStateNormal];
// Remove all chars except of digits
static NSString *const kDigitsString = #"0123456789";
phone = [[phone componentsSeparatedByCharactersInSet:[[NSCharacterSet characterSetWithCharactersInString:kDigitsString] invertedSet]] componentsJoinedByString:#""];
// Initiate call
[[UIApplication sharedApplication] openURL:[NSURL URLWithString:[NSString stringWithFormat:#"tel:%#", phone]]];
}
It looks like you haven't connected the button to an outlet but only to an action.
First you need to connect it to an outlet (like you've done with the labels).
Then use...
[self.button setTitle:#"blah" forState:UIViewControlStateNormal];
Something like that anyway. I'm currently on my iPhone so I don't have auto complete.
If you want to change the title inside the IBAction method do:
[sender setTitle:#"My title" forState:UIControlStateNormal];
If you want to change in any other place you need a #property of uibutton, something like this
#property (strong, nonatomic) IBOutlet UIButton *phoneButtonProperty;
and connect it to your button and then
[phoneButtonProperty setTitle:#"My title" forState:UIControlStateNormal];

Objective-C Trouble: EXC_BAD_ACCESS code=2

I'm trying to write a calculator program, but I'm running into this error when pressing a particular key that is linked to the function expressionEvaluation. My calculator works fine, but I am trying to add in the ability to use/store variables. For this, I use the expressionEvaluation button. However, as soon as I press the button linked to that method, the whole app crashes, and xcode gives me the error EXC_BAD_ACCESS code=2. I'm new to objective-c, so I'm not sure how to debug this error. As far as I can tell, though, the issue is with the line
double result = [CalculatorBrain evaluateExpression:self.brain.expression usingVariableValues:testValues];
...in my view controller. I set a break point before this line and it didn't crash, but setting it at this line resulted in the crash I'm experiencing.
I tried to cut the code down below, and have included only the things directly linked to the expressionEvaluation button. Thank you for your help!
Here's the .h for my brain method:
// CalculatorBrain.h
#import <Foundation/Foundation.h>
#interface CalculatorBrain : NSObject
- (void) pushOperand:(double)operand;
- (void) setVariableAsOperand:(NSString *)variableName;
- (void) performWaitingOperation;
- (double) performOperation:(NSString *)operation;
#property (readonly) id expression;
+ (double)evaluateExpression: (id)anExpression
usingVariableValues: (NSDictionary *)variables;
+ (NSSet *)variablesInExpression:(id)anExpression;
+ (NSString *)descriptionOfExpression:(id)anExpression;
+ (id)propertyListForExpression:(id)anExpression;
+ (id)expressionForPropertyList:(id)propertyList;
#end
Here's the .m:
// CalculatorBrain.m
#import "CalculatorBrain.h"
#define VARIABLE_PREFIX #"^"
#interface CalculatorBrain()
#property (nonatomic) double operand;
#property (nonatomic, strong) NSString *waitingOperation;
#property (nonatomic) double waitingOperand;
#property (nonatomic) double storedOperand;
#property (nonatomic) NSMutableArray *internalExpression;
#end
#implementation CalculatorBrain
#synthesize operand = _operand; //operand in use
#synthesize waitingOperation = _waitingOperation; //waiting to be computed
#synthesize waitingOperand = _waitingOperand; //waiting to be used
#synthesize storedOperand = _storedOperand; //stored in memory
#synthesize internalExpression = _internalExpression; //private expression stored
#synthesize expression = _expression;
- (id) expression {;
return [NSMutableArray arrayWithArray:self.internalExpression];
}
//here I have instance methods that add objects to the array internalExpression
//these work fine as far as I can tell
+ (double) evaluateExpression:(id)anExpression usingVariableValues:(NSDictionary *)variables {
double result = 0;
int count = [anExpression count];
CalculatorBrain *brain;
for (int i = 0; i < count; i++) {
if([[anExpression objectAtIndex:i] isKindOfClass:[NSNumber class]]) {
double operand = [[anExpression objectAtIndex:i] doubleValue];
[brain pushOperand:operand];
}
if([[anExpression objectAtIndex:i] isKindOfClass:[NSString class]]) {
NSString *string = [anExpression objectAtIndex:i];
if([string characterAtIndex:0] == '^') {
NSString* variable = [NSString stringWithFormat:#"%c",[string characterAtIndex:1]];
double valueOfVariable = [[variables objectForKey:variable] doubleValue];
[brain pushOperand:valueOfVariable];
}
else {
NSString* operator = [anExpression objectAtIndex:i];
result = [brain performOperation:operator];
}
}
}
return result;
}
#end
Here's the .h for my view controller:
// CalcViewController.h
#import <UIKit/UIKit.h>
//view controller for calculator
#interface CalcViewController : UIViewController
#property (weak, nonatomic) IBOutlet UILabel *display; //real-time display
#property (strong, nonatomic) IBOutlet UILabel *miniDisplay; //past display
#property (strong, nonatomic) IBOutlet UILabel *memDisplay; //display stored digits
- (IBAction)digitPressed:(UIButton *)sender; //pressed number
- (IBAction)operandPressed:(UIButton *)sender; //pressed operation
- (IBAction)variablePressed:(UIButton *)sender; //pressed variable
- (IBAction)expressionEvaluation:(UIButton *)sender; //evaluate expression with variables
#end
Here's the .m:
// CalcViewController.m
#import "CalcViewController.h"
#import "CalculatorBrain.h"
#interface CalcViewController ()
#property (nonatomic, strong) CalculatorBrain *brain;
#property (nonatomic) BOOL userIsInTheMiddleOfTypingANumber;
#end
#implementation CalcViewController
- (CalculatorBrain *) brain {
if (!_brain) _brain = [[CalculatorBrain alloc] init];
return _brain;
}
- (IBAction)expressionEvaluation:(UIButton *)sender {
NSDictionary* testValues = [NSDictionary dictionaryWithObjectsAndKeys:#"x", 2, #"y", 3, #"z", 4, nil];
double result = [CalculatorBrain evaluateExpression:self.brain.expression usingVariableValues:testValues];
NSString *resultString = [NSString stringWithFormat:#"%g", result];
self.display.text = resultString;
}
#end
EDIT: Just as a side note, I am not getting any errors, only one warning: incomplete implementation. This is because I haven't finished a couple class methods yet, but I don't think it is causing the crash.
NSDictionary* testValues = [NSDictionary dictionaryWithObjectsAndKeys:#"x", 2, #"y", 3, #"z", 4, nil];
turned out to be the erroneous line. It should have been:
NSDictionary* testValues = [NSDictionary dictionaryWithObjectsAndKeys:#"x", [NSNumber numberWithInt:2], #"y", [NSNumber numberWithInt:3], #"z", [NSNumber numberWithInt:4], nil];
Thanks to everyone who helped!
You will get more information on the code line raising the exception by adding an exception breakpoint in xCode.

Resources