How do I access properties of an object when inside another custom object in Xcode / Obj C? - object

As I newbie I sort of understand how to create and access properties for an object with dot notation.. eg I have an object golfCourse with a property courseName so golfCourse.courseName=#"My Course" works OK. My problem is that if I create a "holeObject" containing Par and Distance and create Hole1, Hole2 etc inside my Course Object trying to access them by golfCourse.Hole1.Par is returning null... My various searches have not found me any clarity.. Can someone point me in the right direction?
Many thanks
HoleObject.h
#import <Foundation/Foundation.h>
#interface HoleObject : NSObject
#property(nonatomic,strong) NSString* par;
#property(nonatomic,weak) NSString* yellowDistance;
#end
HoleObject.m
#import "HoleObject.h"
#implementation HoleObject
#synthesize
par=_par,
yellowDistance=_yellowDistance,
-(void) encodeWithCoder:(NSCoder*)encoder
{
[encoder encodeObject:self.par forKey:#"Par"];
[encoder encodeObject:self.yellowDistance forKey:#"YellowDistance"];
}
-(id) initWithCoder:(NSCoder*)decoder
{
if((self=[super init]))
{
self.par=[decoder decodeObjectForKey:#"Par"];
self.yellowDistance=[decoder decodeObjectForKey:#"YellowDistance"];
}
return self;
}
#end
CourseObject.h
#import <Foundation/Foundation.h>
#import "HoleObject.h"
#interface CourseObject : NSObject
#property(nonatomic,strong)NSString* courseName;
#property(nonatomic,strong)NSString* courseAddress;
#property(nonatomic,strong)HoleObject* hole1;
#property(nonatomic,weak)HoleObject* hole2;
etc...
#end
CourseObject.m
#import "CourseObject.h"
#implementation CourseObject
#synthesize
courseName=_courseName,
courseAddress=_courseAddress,
hole1=_hole1,
etc;
-(void) encodeWithCoder:(NSCoder*)encoder
{
[encoder encodeObject:self.courseName forKey:#"CourseName"];
[encoder encodeObject:self.courseName forKey:#"CourseAddress"];
[encoder encodeObject:self.hole1 forKey:#"Hole1"];
etc;
}
-(id) initWithCoder:(NSCoder*)decoder
{
if((self = [super init]))
{
self.courseName=[decoder decodeObjectForKey:#"CourseName"];
self.courseAddress=[decoder decodeObjectForKey:#"CourseAddress"];
self.hole1 = [decoder decodeObjectForKey:#"Hole1"];
self.hole2 = [decoder decodeObjectForKey:#"Hole2"];
etc;
}
return self;
}
#end
Then in my main View Controller..
- (void)viewDidLoad
{
[super viewDidLoad];
allCourses=[[NSMutableArray alloc] initWithCapacity:2];
CourseObject*thisCourse;
thisCourse=[[CourseObject alloc]init];
thisCourse.courseName=#"Branston";
thisCourse.courseAddress=#"The World";
thisCourse.hole1.par=#"4";
thisCourse.hole1.yellowDistance=#"336";
but if I then try and NSLog thisCourse.hole1.par Im getting null?
Thanks for looking.

Spent some time trying different things with this as it was pretty clear that the Null was showing the object was not being created properly.. Found that [[CourseObject alloc]init] does not actually do anything for the objects "sub-Objects" and I needed to do course.hole1=[[HoleObject alloc] init] for all 18 holes as well... bit fiddly but seems to work..

Related

Not accessing value from Object

I have a NSObject called GettingHere which has a NSString *content.
I then have a UIViewController on which I create a button programatically as follows (this button working as intended):
byAirButton = [UIButton buttonWithType:UIButtonTypeCustom];
byAirButton.tag = 1;
byAirButton.frame = CGRectMake(25, 140, 280.f, 40.f);
UIImage *airButton = [UIImage imageNamed:#"gettingHereByAirButton.png"];
[byAirButton setBackgroundImage:airButton forState:UIControlStateNormal];
[self.view addSubview:byAirButton];
[byAirButton addTarget:self action:#selector(byAirButtonClicked) forControlEvents:UIControlEventTouchUpInside];
For the action:#selector(byAirButtonClicked), I do the following. gettingHere is an instance of the GettingHere object.
- (void) byAirButtonClicked
{
gettingHere.content = #"This is how to get here by Air";
NSLog(#"Content: %#", gettingHere.content);
[self performSegueWithIdentifier:#"gettingHereSegue" sender:self];
}
The idea is to set the content for my GettingHere object and then just call that from the next view (GettingHereViewController) when the user clicks the byAirButton.
This NSLog shows that content is being set.
In my prepareForSegue, I do the following:
- (void) prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if ([segue.identifier isEqualToString:#"gettingHereSegue"])
{
NSLog(#"Content to be passed: %#", gettingHere.content);
GettingHereViewController *vc = (GettingHereViewController *)segue.destinationViewController;
vc.gettingHere.content = gettingHere.content;
}
}
The segue works fine, but the NSLog shows my gettingHere object values as being (null).
Can anyone tell me where I am going wrong please? I have stepped through it several times but can't figure out where I am going wrong.
EDIT: Here is how I instantiate the GettingHere Object.
In the SubNavViewController.h
#import "GettingHereContent.h"
#interface SubNavViewController : UIViewController
#property GettingHereContent *gettingHere;
In the SubNavViewController.m
#import "SubNavViewController.h"
#import "GettingHereViewController.h"
#import "GettingHereContent.h"
#interface SubNavViewController ()
#end
#implementation SubNavViewController
#synthesize gettingHere;
And here is how I create the GettingHere Object:
GettingHere.h
#import <Foundation/Foundation.h>
#interface GettingHereContent : NSObject
#property (nonatomic, strong) NSString *content;
#end
GettingHere.m
#import "GettingHereContent.h"
#implementation GettingHereContent
#synthesize content;
#end
You never alloc init your gettingHere property. Try this in your init method of your VC
gettingHere = [[GettingHereContent alloc] init];
Also don't forget to release it: answer from here: alloc + init with synthesized property - does it cause retain count to increase by two?
#interface Foo : Bar {
SomeClass* bla;
}
#property (nonatomic, retain) SomeClass* bla;
#end
#implementation Foo
#synthesize bla;
-(id)init {
...
bla = [[SomeClass alloc] init];
...
}
-(void)dealloc {
[bla release];
...
[super dealloc];
}

segue destinationViewController not detecting destiation viewController

ViewController.m
//
// ViewController.m
// WebViewDemo
//
// Created by Vu Van Tiep on 1/15/13.
// Copyright (c) 2013 Vu Van Tiep. All rights reserved.
//
#import "ViewController.h"
#import "WebViewController.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.
}
-(void) prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender{
if([[segue identifier] isEqualToString:#"GoogleSegue"]){
WebViewController *desView = (WebViewController*) [segue destinationViewController];
UIWebView *webView = desView.webView;
if([webView respondsToSelector:#selector(loadRequest:)] || webView != nil){
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"title" message:#"message" delegate:nil cancelButtonTitle:#"OK" otherButtonTitles:nil];
[alert show];
}
//webView is nil
}
}
#end
WebViewController.m
//
// WebViewController.m
// WebViewDemo
//
// Created by Vu Van Tiep on 1/15/13.
// Copyright (c) 2013 Vu Van Tiep. All rights reserved.
//
#import "WebViewController.h"
#interface WebViewController ()
#end
#implementation WebViewController
#synthesize webView;
- (void)viewDidLoad
{
[super viewDidLoad];
self.webView.scalesPageToFit = YES;
}
#end
WebViewController.h
#interface WebViewController : UIViewController
#property (weak, nonatomic) IBOutlet UIWebView *webView;
#end
when i'm using [segue destinationViewController] i got WebViewControlller object, but when i'm access webView property of that object, it's nil
Can someone plz explain to me? :(
Thanks!
The view of your WebViewController is not initialized yet. You need to tell it to initialize. Do it after the line
WebViewController *desView = (WebViewController*) [segue destinationViewController]; }
by adding the line
[desView view];
This is the same problem as in Use destinationViewController button in a custom segue . Although this must be a very common problem, I found it hard to locate information about this.

NSMutableArray Add/Remove Objects (Inherited File)

Okay, so I'm pretty new to xcode but I cannot find something specific to this issue anywhere. So I declare the array and instantiate it in the following files:
//xmlToUrl.h
#import <Foundation/Foundation.h>
#interface xmlToUrl : NSObject {
NSMutableArray *field;
NSMutableArray *name;
}
#property(nonatomic, retain)NSMutableArray *field;
#property(nonatomic, retain)NSMutableArray *name;
#end
and
//xmlToUrl.m
#import "xmlToUrl.h"
#implementation xmlToUrl
#synthesize field;
#synthesize name;
-(void)dealloc
{
[field release];
[name release];
[super dealloc];
}
#end
So this is where I am confused. I don't know how to correctly "alloc" or "init" the mutable arrays, nor how to handle the add/remove operations from another file which inherits xmlToUrl.h.
The code (in the other file) as I have it now just prints null. Its listed below. What am I doing wrong?!?
//nodeContent is just a NSMutableString
[xmlToUrlObject.name addObject:nodeContent];
NSLog(#"xml Name = %#", xmlToUrlObject.name);
//I omitted all the operational code here but if I NSLog nodeContent it prints the correct values
[xmlToUrlObject.field addObject:nodeContent];
NSLog(#"xml Field = %#", xmlToUrlObject.field);
You need an init function in your implementation file, it would look similar to the following
-(id) init
{
self = [super init];
if (self) {
field = [[NSMutableArray alloc] init];
name = [[NSMutableArray alloc] init];
}
return self;
}
Then whenever you create an instance of your xmlToUrl class via [[xmlToUrl alloc] init] you will have an instance of your class that has already initialized your two NSMutableArrays

"Type name requires a specifier or qualifier" error

I have the following code but can't compile it because I have a "Type name requires a specifier or qualifier" error" for (self).
How to fix this error? I have compared it with the original code and there are no differences, so I don't know what's going on.
#import "CurrentTimeViewController.h"
#implementation CurrentTimeViewController
{
// Call the superclass's designated initializer
self = [super initWithNibName:#"CurrentTimeViewController"
bundle:nil];
if (self) {
// Get the tab bar item
UITabBarItem *tbi = [self tabBarItem];
// Give it a label
[tbi setTitle:#"Time"];
}
return self;
}
Here is the code from the mirror file HynososViewController.h, and which I cut, pasted and modified:
#import "HypnososViewController.h"
#implementation HypnososViewController
- (id) init
{
// Call the superclass's designated initializer
self = [super initWithNibName:nil
bundle:nil];
if (self) {
// Get the tab bar item
UITabBarItem *tbi = [self tabBarItem];
// Give it a label
[tbi setTitle:#"Hypnosis"];
}
return self;
}
- (id) initWithNibName:(NSString *)nibName bundle:(NSBundle *)nibBundle
{
// Disregard parameters - nib name is an implementation detail
return [self init];
}
// This method gets called automatically when the view is created
- (void)viewDidLoad
{
[super viewDidLoad];
NSLog(#"Loaded the view for HypnosisViewController");
// Set the background color of the view so we can see it
[[self view] setBackgroundColor:[UIColor orangeColor]];
}
#end
Here is the complete code for CurrentTimeViewController.h:
#import "CurrentTimeViewController.h"
#implementation CurrentTimeViewController
{
// Call the superclass's designated initializer
self = [super initWithNibName:#"CurrentTimeViewController"
bundle:nil];
if (self) {
// Get the tab bar item
UITabBarItem *tbi = [self tabBarItem];
// Give it a label
[tbi setTitle:#"Time"];
}
return self;
}
- (id) initWithNibName:(NSString *)nibName bundle:(NSBundle *)Bundle
{
// Disregard parameters - nib name is an implementation detail
return [self init];
}
// This method gets called automatically when the view is created
- (void)viewDidLoad
{
[super viewDidLoad];
NSLog(#"Loaded the view for CurrentTimeViewController");
// Set the background color of the view so we can see it
[[self view] setBackgroundColor:[UIColor greenColor]];
}
#end
Is the code above a cut-and-paste of EXACTLY what you are trying to compile? If so, I think you are missing something very important that would make that code block a method implementation:
-(id)init // This, or something like it, is missing???
{
...
}
Check your code, here, and in your project. :-)

My custom class object gets released even after retaining it

I have been trying to debug this error like for days and still can't seem to grasp what really is going on with my object.
The code goes like this.
- (BOOL)webView:(UIWebView*)webView shouldStartLoadWithRequest:(NSURLRequest*)request navigationType:(UIWebViewNavigationType)navigationType {
// extract data from clicked link
SongObject *Data = [[SongObject alloc] init];
[Data retain];
selectedSong = Data;
}
selectedSong is public variable in the main class, now the crazy thing is that using the above method works everywhere else but shoulStartLoadWithRequest.
Trying to deubg it gives me "Out Of Scope", could it be by some crazy reason that "shouldStartLoadWithRequest" is autoreleasing my object even when I say don't?
Any idea's?
Edit: This is the H and M file which selectedSong is suppose to hold.
#import <Foundation/Foundation.h>
#import "SongObject.h"
#interface SongObject : NSObject<NSCopying> {
NSString *artist;
NSString *titel;
NSString *album;
NSString *genre;
NSString *songUrl;
NSString *rating;
NSString *image;
BOOL local;
}
#property (readonly) NSString *getArtist;
#property (readonly) NSString *getTitle;
#property (readonly) NSString *getAlbum;
#property (readonly) NSString *getGenre;
#property (readonly) NSString *getSongURL;
#property (readonly) NSString *getRating;
#property (readonly) NSString *getImage;
#property (readonly) BOOL isLocal;
-(void) setInfo:(NSString *) a: (NSString*) t: (NSString*) ab: (NSString*)g: (NSString*)sU: (NSString*)r: (NSString*) i: (BOOL) loc;
#end
#import "SongObject.h"
#implementation SongObject
-(id)init
{
if(self =[super init])
{
NSLog(#"Init songobject");
}
return self;
}
-(id) copyWithZone: (NSZone *) zone {
SongObject *newSong = [[SongObject allocWithZone:zone] init];
NSLog(#"_copy: %#", [newSong self]);
[newSong setInfo:[self getArtist] :[self getTitle] :[self getAlbum] :[self getGenre] :[self getSongURL] :[self getRating] :[self getImage] :[self isLocal]];
return(newSong);
}
-(void)dealloc
{
NSLog(#"Songobject deallocted from memory...");
[super dealloc];
}
-(void) setInfo:(NSString *) a: (NSString*) t: (NSString*) ab: (NSString*)g: (NSString*)sU: (NSString*)r: (NSString*) i: (BOOL) loc{
artist = a;
titel = t;
album = ab;
genre = g;
songUrl = sU;
rating = r;
image = i;
local = loc;
}
-(NSString*)getArtist
{
return artist;
}
-(NSString*)getTitle
{
return titel;
}
-(NSString*)getAlbum
{
return album;
}
-(NSString*)getGenre
{
return genre;
}
-(NSString*)getSongURL
{
return songUrl;
}
-(NSString*)getRating
{
return rating;
}
-(NSString*)getImage
{
return image;
}
-(BOOL)isLocal{
return local;
}
#end
That doesn't seem possible. Be careful, cause you're increasing the reference count twice. Once in the alloc, and again with the retain. What does selectedSong looks like? is it a property with automated retain?
Also, sometimes I cannot read the object in the debugger and I use NSLog. What do you see then?
What about overriding -dealloc. Did you try setting a breakpoint there?
I finally found the problem the SongObject class with the NSString variables was never retained. So the selectedSong was actually never released but the variables within the class it self.
Fixed it by using NSString alloc initWithString and then overriding the dealloc method and releasing them in there.

Resources