Cannot read class members values in Objective C - objective-c

I'm trying to learn Objective C with examples, and now I stuck with the following problem. I have a code:
#import <UIKit/UIKit.h>
#import <MapKit/MapKit.h>
#interface ViewController : UIViewController <MKMapViewDelegate> {
IBOutlet MKMapView *mapView;
MKPointAnnotation* startPoint;
MKPointAnnotation* endPoint;
double startPointLat;
double startPointLon;
double endPointLat;
double endPointLon;
}
#property (strong, nonatomic) IBOutlet MKMapView *mapView;
- (IBAction)findPressed:(id)sender;
#end
And implementation:
- (void)viewDidLoad
{
[super viewDidLoad];
self.mapView.delegate = self;
// Add an annotation
startPoint = [[MKPointAnnotation alloc] init];
startPoint.coordinate = CLLocationCoordinate2DMake(0, 0);
startPoint.title = #"Start point";
endPoint = [[MKPointAnnotation alloc] init];
endPoint.coordinate = CLLocationCoordinate2DMake(10, 10);
endPoint.title = #"End point";
startPointLat = 0;
startPointLon = 0;
endPointLat = 10;
endPointLon = 10;
[self.mapView addAnnotation:startPoint];
[self.mapView addAnnotation:endPoint];
NSLog(#"%#, %# -> %#, %#", startPointLat, self->startPointLon, self->endPointLat, self->endPointLon);
}
But values in logs output are nulls. What's wrong?

The format specifier "%#" is for objects, but the variables here are doubles. You want "%f" instead.

Related

Objective C Property Syntax

I have quick question regarding my code:
This is my Animal.h header file:
#import <Foundation/Foundation.h>
#interface Animal : NSObject
#property (nonatomic) int age;
#property (nonatomic, strong) NSString *name;
#property (nonatomic,strong) NSString *breed;
#property (retain, nonatomic) UIImage *image;
-(void) bark;
-(void)barkNumTimes: (int)numOfTimesToBark;
-(void)barknumTimes:(int)numberOfTimes loudly:(bool) isLoud;
-(int) ageInDogYears: (int)humanYears;
#end
For some reason at the line:
#property (retain, nonatomic) UIImage *image;
I get an error saying that "Property with 'retain (or strong)' attribute must be of object type".
My ViewController.m class is where I created three Animal objects and used the UIImage property which I created in Animal.h and set each of the Animal objects UIImage property to a certain image I have in my supporting files:
#import "ViewController.h"
#import "Animal.h"
#import "Puppy.h"
#interface ViewController ()
#end
#implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
self.whichDog = 0;
Animal *whiteDog = [[Animal alloc]init];
[whiteDog setName:#"white"];
[whiteDog setBreed:#"White Dog"];
whiteDog.image = [UIImage imageNamed:#"whitedog.jpeg"];
Animal *brownDog = [[Animal alloc] init];
[brownDog setName:#"brown"];
[brownDog setBreed:#"Brown Dog"];
brownDog.image = [UIImage imageNamed:#"browndog.jpeg"];
Animal *husky = [[Animal alloc] init];
[husky setName:#"husky"];
[husky setBreed:#"Husky Dog"];
husky.image = [UIImage imageNamed:#"husky.jpeg"];
self.myAnimals = [[NSMutableArray alloc] init];
[self.myAnimals addObject:whiteDog];
[self.myAnimals addObject:brownDog];
[self.myAnimals addObject:husky];
Puppy *pup = [[Puppy alloc]init];
[pup setName:#"coby"];
[pup setBreed:#"Portuguese Water Dog"];
pup.image = [UIImage imageNamed:#"puppy.jpeg"];
}
- (IBAction)newDogBarButton:(UIBarButtonItem *)sender{
int numOfDogs = (int)[self.myAnimals count];
int randomIndex = arc4random() % numOfDogs;
Animal *randomAnimal = [self.myAnimals objectAtIndex:randomIndex];
[UIView transitionWithView:self.view duration:1.5 options:UIViewAnimationOptionTransitionCurlDown animations:^{
self.imageView.image = randomAnimal.image;
self.carNAme.text = randomAnimal.name;
self.extra.text = [randomAnimal breed];
} completion:^(BOOL finished) {
}];
sender.title = #"And Another";
self.whichDog = randomIndex;
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#end
For some reason in Animal.h I keep getting that error which says "Property with 'retain (or strong)' attribute must be of object type". I am not very sure on what this retain or strong means in the properties, but can someone please explain to me what I am doing wrong in my code. Thank you so much for the help.
UIImage belongs to UIKit, so import UIKit instead of Foundation

accessing method of custom view in view controller

I am a new-be in Objective C. Here I want to ask a simple question.
I have created a view controller in storyboard, and customized its view with a subclass of UIView.
However, I don't know how to call methods of the view in my view controller. Can anyone help? All I want to do is to call drawLine:pointStore in ChartViewController.m from chartView.m
Here are some of my codes.
ChartViewController.h
#import <UIKit/UIKit.h>
#class chartView;
#interface ChartViewController : UIViewController{
chartView *chart_view;
}
ChartViewController.m
- (void)viewDidLoad
{
[super viewDidLoad];
NSMutableDictionary *pointStore = [[NSMutableDictionary alloc]init];
NSNumber *initX;
NSNumber *initY;
NSMutableDictionary *variableSet = [[NSMutableDictionary alloc]init];
for(initX = [NSNumber numberWithDouble:-10.0f];initX.floatValue<=10.0f;initX = [NSNumber numberWithDouble:(initX.floatValue+0.5f)] )
{
[variableSet setValue:initX forKey:#"x"];
initY = [NSNumber numberWithDouble:[self.brain performOperation:equationOfChart withVariable:variableSet]];
[pointStore setObject:initX forKey:initY];
}
[chart_view drawLine:pointStore];
}
chartView.h
#interface chartView : UIView
#property (nonatomic, strong) NSString *equation;
-(void) getEquation:(NSString *)Equation;
-(void) drawLine:(NSMutableDictionary *)pointsStore;
#end
chartView.m
-(void)drawLine:(NSMutableDictionary *)pointsStore{
CGContextRef c = UIGraphicsGetCurrentContext();
CGFloat red[4] = {1.0f, 0.0f, 0.0f, 1.0f};
CGContextSetStrokeColor(c, red);
CGContextBeginPath(c);
CGContextStrokePath(c);
for(NSNumber *ax = [NSNumber numberWithDouble:-10.0f];ax.floatValue<10.0f;){
float ay = [[pointsStore objectForKey:ax]doubleValue];
ax = [NSNumber numberWithDouble:(ax.floatValue+0.5f)];
int by = [[pointsStore objectForKey:ax]doubleValue];
[self.class line:ax.floatValue y:ay x2:(ax.floatValue+0.5) y2:by];
}
}
ChartViewController.h
#import <UIKit/UIKit.h>
#class chartView;
#interface ChartViewController : UIViewController
#property (string, nonatomic) chartView *chart_view;
#end
chartView.m
- (void)viewDidLoad
{
[super viewDidLoad];
...
// Don't forget to alloc and init
self.chart_view = [[chartView alloc] init];
[self.chart_view drawLine:pointStore];
}
You should check that the instance of chart_view is created and assigned. Probably you have nil in that poiner.
How to do this -- depend on the way you have chosen to create the view: in Interface Builder or dynamically, in code.

random generator to obtain data from array not displaying

I know theres a better solution using arc4random (it's on my to-try-out-function list), but I wanted to try out using the rand() and stand(time(NULL)) function first. I've created a NSMutableArray and chuck it with 5 data. Testing out how many number it has was fine. But when I tried to use the button function to load the object it return me with object <sampleData: 0x9a2f0e0>
- (IBAction)generateNumber:(id)sender {
srand(time(NULL));
NSInteger number =rand()% ds.count ;
label.text = [NSString stringWithFormat:#"object %#", [ds objectAtIndex:number] ];
NSLog(#"%#",label.text);
}
While I feel the main cause is the method itself, I've paste the rest of the code below just incase i made any error somewhere.
ViewController.h
#import <UIKit/UIKit.h>
#import "sampleData.h"
#import "sampleDataDAO.h"
#interface ViewController : UIViewController
#property (weak, nonatomic) IBOutlet UILabel *label;
#property (weak, nonatomic) IBOutlet UIButton *onHitMePressed;
- (IBAction)generateNumber:(id)sender;
#property(nonatomic, strong) sampleDataDAO *daoDS;
#property(nonatomic, strong) NSMutableArray *ds;
#end
ViewController.m
#import "ViewController.h"
#interface ViewController ()
#end
#implementation ViewController
#synthesize label;
#synthesize onHitMePressed;
#synthesize daoDS,ds;
- (void)viewDidLoad
{
[super viewDidLoad];
daoDS = [[sampleDataDAO alloc] init];
self.ds = daoDS.PopulateDataSource;
// Do any additional setup after loading the view, typically from a nib.
}
- (void)viewDidUnload
{
[self setLabel:nil];
[self setOnHitMePressed:nil];
[super viewDidUnload];
// Release any retained subviews of the main view.
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
return (interfaceOrientation != UIInterfaceOrientationPortraitUpsideDown);
}
- (IBAction)generateNumber:(id)sender {
srand(time(NULL));
NSInteger number =rand()% ds.count ;
label.text = [NSString stringWithFormat:#"object %#", [ds objectAtIndex:number] ];
NSLog(#"%#",label.text);
}
#end
sampleData.h
#import <Foundation/Foundation.h>
#interface sampleData : NSObject
#property (strong,nonatomic) NSString * object;
#end
sampleData.m
#import "sampleData.h"
#implementation sampleData
#synthesize object;
#end
sampleDataDAO.h
#import <Foundation/Foundation.h>
#import "sampleData.h"
#interface sampleDataDAO : NSObject
#property(strong,nonatomic)NSMutableArray*someDataArray;
-(NSMutableArray *)PopulateDataSource;
#end
sampleDataDAO.m
#import "sampleDataDAO.h"
#implementation sampleDataDAO
#synthesize someDataArray;
-(NSMutableArray *)PopulateDataSource
{
someDataArray = [[NSMutableArray alloc]init];
sampleData * myData = [[sampleData alloc]init];
myData.object= #"object 1";
[someDataArray addObject:myData];
myData=nil;
myData = [[sampleData alloc] init];
myData.object= #"object 2";
[someDataArray addObject:myData];
myData=nil;
myData = [[sampleData alloc] init];
myData.object= #"object 3";
[someDataArray addObject:myData];
myData=nil;
myData = [[sampleData alloc] init];
myData.object= #"object 4";
[someDataArray addObject:myData];
myData=nil;
myData = [[sampleData alloc] init];
myData.object= #"object 5";
[someDataArray addObject:myData];
myData=nil;
return someDataArray;
}
#end
what i guess is going on is that nslog function cant print the data inside your sample data class because its not a standard class. not standard classes must implement the "description" method. What you get when you print out your class is the pointer to it, because nslog has no way of knowing how to print out the data in your class.
if what you want to print on that label/nslog is the nsstring inside your class "sampledata" you should access the property.
this can be done in the following way:
SampleData *instanceOfSampleData = (SampleData*)[ds objectAtIndex:number];
label.text = [NSString stringWithFormat:#"object %#", instanceOfSampleData.object];

Why is MKMapView delegate method not being called?

I'm very new to iphone development and I'm trying to annotate a map. I've been able to get 3 location points on a map with hardcoded coordinates and now I'm trying to customize the pins. I know to do that you need to implement the:-(MKAnnotationView *)mapView:(MKMapView *)mV viewForAnnotation:(id <MKAnnotation>)annotation { delegate method.
For some reason I've been unable to even get it called. Here is what I have in the controller header:
#import "ArtPiece.h"
#import <UIKit/UIKit.h>
#import <MapKit/MapKit.h>
#interface TestViewController : UIViewController <MKMapViewDelegate> {
MKMapView *mapView;
NSMutableArray *mapAnnotations;
float results_lat[3];
float results_long[3];
NSMutableArray *results_title;
NSMutableArray *Arts;
}
#property (nonatomic, retain) IBOutlet MKMapView *mapView;
#property (nonatomic, retain) NSMutableArray *mapAnnotations;
#end
And here is what I have in the controller implementation:
- (void)viewDidLoad {
results_long[0] = -122.477989;
results_lat[0] = 37.810000;
results_long[1] = -122.480000;
results_lat[1] = 37.820000;
results_long[2] = -122.4850000;
results_lat[2] = 37.830000;
self.mapAnnotations = [[NSMutableArray alloc] initWithCapacity:3];
Arts = [[NSMutableArray alloc] initWithCapacity:3];
for(int x = 0; x<3; x++)
{
// creates an ArtPiece object and sets its lat and long
ArtPiece *a = [[ArtPiece alloc] init];
a.longitude = [NSNumber numberWithDouble:results_long[x]];
a.latitude = [NSNumber numberWithDouble:results_lat[x]];
a.title = #"please show up";
// add objects to annotation array
[self.mapAnnotations insertObject:a atIndex:x];
[a release];
}
// center screen on cali area
[self gotoLocation];
for(int x = 0; x<3; x++)
{
[mapView addAnnotations:mapAnnotations];
}
}
-(MKAnnotationView *)mapView:(MKMapView *)mV viewForAnnotation:(id <MKAnnotation>)annotation {
NSLog(#"This is not printing to to console...");
MKPinAnnotationView *pinView = nil;
if(annotation != mapView.userLocation)
{
static NSString *defaultPinID = #"com.invasivecode.pin";
pinView = (MKPinAnnotationView *)[mapView dequeueReusableAnnotationViewWithIdentifier:defaultPinID];
if ( pinView == nil ) pinView = [[[MKPinAnnotationView alloc]
initWithAnnotation:annotation reuseIdentifier:defaultPinID] autorelease];
pinView.pinColor = MKPinAnnotationColorPurple;
pinView.canShowCallout = YES;
pinView.animatesDrop = YES;
}
else {
[mapView.userLocation setTitle:#"I am here"];
}
return pinView;
}
And here is the ArtPiece class implementation:
#import "TestViewController.h"
#import "ArtPiece.h"
#import <MapKit/MapKit.h>
#import <CoreData/CoreData.h>
#implementation ArtPiece
#synthesize title, artist, series, description, latitude, longitude;
- (CLLocationCoordinate2D)coordinate
{
CLLocationCoordinate2D theCoordinate;
theCoordinate.latitude = [self.latitude doubleValue];
theCoordinate.longitude = [self.longitude doubleValue];
return theCoordinate;
}
#end
It's probably something simple. Is there something wrong with my method declaration? Did I declare the delegate wrong? I can't figure it out, again, I'm very new to this objective c/delegate stuff. Thanks for any help.
The addAnnotations method expects an NSArray of objects that conform to the MKAnnotation protocol.
You are adding objects of type ArtPiece which don't seem to implement MKAnnotation which has a coordinate property (not latitude and longitude properties).
Update your ArtPiece class to conform to MKAnnotation (or use the pre-defined MKPointAnnotation class). But updating your custom class is a better fix.

cannot follow that tutorial

i tried to follow this tutorial:
http://www.youtube.com/watch?v=L-FK1TrpUng&feature=related
around 00:39:00.
Theres a counter which recognizes every switch to the second view controller and counts it.
The number of view switches should be shown on the second view controller.
But it doesn't work, thats the code:
Test2ViewController.h
#interface Test2ViewController : UIViewController <UITextFieldDelegate> {
UINavigationController *navController;
Test21ViewController *test21View;
NSString *text;
IBOutlet UITextField *textField1;
}
#property(nonatomic, retain) UITextField *textField1;
#property (nonatomic, retain) UINavigationController *navController;
#property (copy) NSString *text;
-(IBAction)pushViewController:(id)sender;
#end
Test2ViewController.m:
#import "Test2ViewController.h"
#import "Test21ViewController.h"
#implementation Test2ViewController
#synthesize textField1, navController, text;
-(IBAction)pushViewController:(id)sender {
static int count = 1;
Test21ViewController *test21ViewController = [[Test21ViewController alloc] init];
[self.navigationController pushViewController:test21ViewController animated:YES];
test21ViewController.label = [NSString stringWithFormat:#"Pushed %d", count];
count++;
}
Test21ViewController.h:
#interface Test21ViewController : UIViewController {
UINavigationController *navController;
NSString *label;
IBOutlet UILabel *textLabel;
UITextField *tF1;
}
#property (copy) NSString *label;
#property (nonatomic, retain) UINavigationController *navController;
#property(nonatomic,retain)UITextField *tF1;
-(IBAction)feldeingabe:(id)Sender;
#end
Test21ViewController.m:
#implementation Test21ViewController
#synthesize label;
- (void)viewDidLoad {
textLabel.text = label;
}
Any ideas why it doesn't work?
Thanks in advance
Code for the second question:
static int count = 1;
Test2ViewController *test2ViewController;
test2ViewController.label = [NSString stringWithFormat:#"Pushed %d !!!!!", count];
[[self navigationController] popViewControllerAnimated:NO];
count++;
CURRENT CODE:
#import "Test21ViewController.h"
#implementation Test21ViewController
#synthesize navController, text, parentView;
-(IBAction)pushViewController2:(id)sender {
Test2ViewController *test2ViewController;
static int count = 1;
test2ViewController.parentView = self;
test2ViewController.label = [NSString stringWithFormat:#"Pushed %d !!!!!", count];
[self.navigationController pushViewController:test2ViewController animated:YES]; count++;
}
For the second problem (passing a string from child to parent);
Test2ViewController.h
#interface Test2ViewController : UIViewController <UITextFieldDelegate> {
NSString *receiverPropertyFromChild;
}
#property(nonatomic, retain) NSString *receiverPropertyFromChild;
Test2ViewController.m:
-(IBAction)pushViewController:(id)sender {
static int count = 1;
Test21ViewController *test21ViewController = [[Test21ViewController alloc] init];
test21ViewController.label = [NSString stringWithFormat:#"Pushed %d", count];
test21ViewController.parentView = self;
[self.navigationController pushViewController:test21ViewController animated:YES];
count++;
}
Test21ViewController.h:
#class Test2ViewController;
#interface Test21ViewController : UIViewController {
Test2ViewController *parentView;
}
#property (nonatomic, assign) Test2ViewController *parentView;
Test21ViewController.m
-(IBAction)goToTest2ViewController:(id)sender {
parentView.receiverPropertyFromChild = #"the text you want to pass";
[self.navigationController popViewControllerAnimated:YES];
count++;
}
can you try:
Test21ViewController *test21ViewController = [[Test21ViewController alloc] init];
test21ViewController.label = [NSString stringWithFormat:#"Pushed %d", count];
[self.navigationController pushViewController:test21ViewController animated:YES];
I swapped the last two lines. It could be that you are setting the label after viewDidLoad has already been called, thus not setting the value in the label.
That said, it is better to pass the string as an init parameter, not as a property and then set in viewDidLoad.
edit:
To set it as init parameter, you need to create a new init method to accept that parameter.
- (id) initWithString:(NSString *)labelParam {
self = [super init];
if (self) {
this.label = labelParam;
}
return self;
}