Objective C Property Syntax - objective-c

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

Related

How to save UIImages in view

In my app I have two views: a mapView, and a detail view. The mapView has annotations, and the annotation views have right callout buttons that push the detail view onto the stack when the callout button is pressed. In the detail view, the user can take a picture that appears on the UIImage that is on the detail view controller. What I want is for a different image to be on the detail view controller for each annotation. I have read that I can use a singleton, and I have made a singleton class, but I do not know how to use it. Can someone help me out?
Here is some code:
My MKAnnotation class:
#import <CoreLocation/CoreLocation.h>
#import <MapKit/MapKit.h>
#interface MapPoint : NSObject <MKAnnotation>
{
NSString *_address;
CLLocationCoordinate2D _coordinate;
NSNumber *_identifier;
UIImage *_image;
}
- (id)initWithAddress:(NSString*)address
coordinate:(CLLocationCoordinate2D)coordinate
title:(NSString *)t
identifier:(NSNumber *)ident;
//This is a required property from MKAnnotation
#property (nonatomic, readonly) CLLocationCoordinate2D coordinate;
//This is an optional property from MKAnnotataion
#property (nonatomic, copy) NSString *title;
#property (nonatomic, readonly, copy) NSString *subtitle;
#property (nonatomic) BOOL animatesDrop;
#property (nonatomic) BOOL canShowCallout;
#property (copy) NSString *address;
#property (copy) NSNumber *identifier;
#property (copy,nonatomic) UIImage *image;
#end
#implementation MapPoint
#synthesize title, subtitle, animatesDrop, canShowCallout;
#synthesize address = _address, coordinate = _coordinate, identifier = _identifier, image = _image;
-(id)initWithAddress:(NSString *)address
coordinate:(CLLocationCoordinate2D)coordinate
title:(NSString *)t
identifier:(NSNumber *)ident
{
self = [super init];
if (self) {
_address = [address copy];
_coordinate = coordinate;
_identifier = ident;
[self setTitle:t];
NSDate *theDate = [NSDate date];
subtitle = [NSDateFormatter localizedStringFromDate:theDate
dateStyle:NSDateFormatterMediumStyle
timeStyle:NSDateFormatterMediumStyle];
}
return self;
}
#end
Here is the detail view controller:
#import <UIKit/UIKit.h>
#class P2OViewController;
#interface PinViewController : UIViewController <UINavigationControllerDelegate, UIImagePickerControllerDelegate,UITextFieldDelegate>
{
__weak IBOutlet UILabel *label;
__weak IBOutlet UIButton *removeButton;
NSString *addressForLabel;
__weak P2OViewController *_vc;
__weak NSNumber *_identifier;
}
#property (weak, nonatomic) IBOutlet UIImageView *imageView;
#property (weak, nonatomic) IBOutlet UILabel *label;
#property (weak, nonatomic) IBOutlet UIButton *removeButton;
#property (weak, nonatomic) P2OViewController *vc;
#property (weak, nonatomic) NSNumber *identifier;
-(void)takePicture:(id)sender;
-(void)buttonPressed:(id)sender;
#end
#import "PinViewController.h"
#import "MapPoint.h"
#import "P2OViewController.h"
#implementation PinViewController
#synthesize imageView, label, removeButton;
#synthesize vc = _vc, identifier = _identifier;
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
UIBarButtonItem *pic = [[UIBarButtonItem alloc]initWithBarButtonSystemItem:UIBarButtonSystemItemCamera
target:self
action:#selector(takePicture:)];
[[self navigationItem]setRightBarButtonItem:pic];
}
return self;
}
-(void)takePicture:(id)sender
{
UIImagePickerController *imagePicker = [[UIImagePickerController alloc]init];
//If our device has a camera, we ant to take a picture, otherwise, we just pick from photo library
if ([UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypeCamera]) {
[imagePicker setSourceType:UIImagePickerControllerSourceTypeCamera];
} else {
[imagePicker setSourceType:UIImagePickerControllerSourceTypePhotoLibrary];
}
[imagePicker setDelegate:self];
//Place the image picker on the screen
[self presentViewController:imagePicker
animated:YES
completion:nil];
}
-(void)imagePickerController:(UIImagePickerController *)picker
didFinishPickingMediaWithInfo:(NSDictionary *)info
{
//Get picked image from info dictionary
UIImage *image = [info objectForKey:UIImagePickerControllerOriginalImage];
//Put the image onto the screen in out image view
[imageView setImage:image];
//Take image picker off the screen - you must call this dismiss method
[self dismissViewControllerAnimated:YES
completion:nil];
}
#end
You surely have a class implementing the MKAnnotation protocol.
In this class simply add a UIImage property and assign to every annotation its custom image.
Then when presenting the detailed view you just pass around the annotation and access its image property you defined.
EDIT
In your PinViewController simply declare a property like this
#property(nonatomic, strong) MapPoint * annotation;
Before you present your PinViewController assign the corresponding annotation to it, doing something like
detailedController.annotation = theAnnotation;
Do whatever you need to do to get the image, then store it in the annotation in this way
self.annotation.image = theImage;
Now the annotation is storing the image, so as long as you keep it in memory it will be there available for you.
The next time you push the detailed view you can perform a check to see whether that annotation has already an image or not
if(nil != self.annotation.image) {
// do something
} else {
// do something else
}

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];

I'm having problems using a Singleton to pass an array in Objective-c. (code included)

So I'm creating an array called fruits which I would like to share between multiple views. This is my code:
#import <foundation/Foundation.h>
#interface MyManager : NSObject {
NSMutableArray *fruits;
}
#property (nonatomic, retain) NSMutableArray *fruits;
+ (id)sharedManager;
#end
#import "MyManager.h"
static MyManager *sharedMyManager = nil;
#implementation MyManager
#synthesize fruits;
#pragma mark Singleton Methods
+ (id)sharedManager {
#synchronized(self) {
if (sharedMyManager == nil)
sharedMyManager = [[self alloc] init];
}
return sharedMyManager;
}
- (id)init {
if ((self = [super init])) {
fruits = [[NSMutableArray alloc] init];
}
return self;
}
-(void) dealloc{
self.fruits = nil;
[super dealloc];
}
#end
Now I'm using the following code so that I can use workouts in the new view
#import "MyManager.h"
#interface Chest : UIViewController {
IBOutlet MyManager *fruits;
}
#property (nonatomic, retain) IBOutlet MyManager *fruits;
-(IBAction) goToList: (id) sender;
#end
When a button is clicked, goToList is called, and I populate my array, fruits
#import "Chest.h"
#implementation Chest
#synthesize fruits;
-(IBAction) goToList:(id)sender{
MyManager *fruits = [MyManager sharedManager];
NSString *filePath;
NSString *fileContents;
filePath = [[NSBundle mainBundle] pathForResource:#"chest_strength" ofType:#"csv"];
fileContents = [[NSString alloc] initWithContentsOfFile:filePath encoding:NSUTF8StringEncoding error:nil];
fruits = [fileContents componentsSeparatedByString:#"\n"];
}
When I output the elements of *fruits in this view, everything works fine. Now when I try to access this same variable in the other view, it says the array is null. Here's the code for the second view:
#interface List : UIViewController {
IBOutlet MyManager *fruits;
}
#property (nonatomic, retain) IBOutlet MyManager *fruits;
#end
#import "List.h"
#import "MyManager.h"
#implementation List
#synthesize fruits
NSLog(#"%#", fruits); //This is the part that isn't displaying correctly. I'm getting a null here
So my question is, how do I do this so that I can get the array fruits that I populated in Chest and use it in List so that I can display the contents of the array in that view?
Thank you to everybody who answers. This problem is seriously bogging me down and I need to finish this project ASAP. Much appreciated.
You've changed a few things in this question but the fundamental problem remains: the array is a property of your singleton, and you are not treating it as such.
Whenever you refer to the array, outside of the singleton, do it like this:
[MyManager sharedManager].fruits
If you are accessing it frequently, you can create a local ivar, but you certainly wouldn't have it as an IBOutlet, which you are doing in your last code sample. How is that ever going to be set?

Please help me find the two leaks in this iOS code

In my viewController.m I have this code:
self.movie = [[myMovie alloc]init];
self.movie.name = #"Iron man 2"; \\this line leaks
...
nameLbl = [[UILabel alloc] initWithFrame:CGRectMake(30, 20, 200, 20)]; \\this line leaks
nameLbl.backgroundColor = [UIColor clearColor];
In viewController.h I have this code:
#interface ViewController : UIViewController
{
myMovie * movie;
UILabel * nameLbl;
}
#property (nonatomic, retain) myMovie * movie;
#property (nonatomic, retain) UILabel * nameLbl;
And myMovie.h:
{
NSString* name;
}
#property (nonatomic, retain) NSString* name;
myMovie.m:
#import "myMovie.h"
#implementation myMovie
#synthesize name, gross, desc;
-(void) dealloc
{
self.name = nil;
self.gross = nil;
self.desc = nil;
[super dealloc];
}
#end
Of course this is only the necessary code. I can't figure out why it is leaking. I don't know if this is the cause but my application crashes.
The line that's leaking is the one above: self.movie = [[myMovie alloc]init];
Change it to self.movie = [[[myMovie alloc]init] autorelease]; or add [self.movie release]; as the line immediately afterwards.