iPhone Super/SubClass Example - objective-c

I have a superclass Question:
import <Foundation/Foundation.h>
#import "Answer.h"
#interface Question : NSObject {
NSString* qId;
NSString* qTitle;
NSString* qNumber;
NSString* sectionId;
NSString* type;
Answer* answer;
}
#property (nonatomic, retain) NSString* qId;
#property (nonatomic, retain) NSString* qTitle;
#property (nonatomic, retain) NSString* qNumber;
#property (nonatomic, retain) NSString* sectionId;
#property (nonatomic, retain) NSString* type;
#property (nonatomic, retain) Answer* answer;
#end
#import "Question.h"
#implementation Question
#synthesize qId, qTitle, qNumber, sectionId, type, answer;
-(id)init
{
if (self = [super init])
{
// Initialization code here
answer = [[Answer alloc]init];
}
return self;
}
-(void) dealloc{
[answer release];
[super dealloc];
}
#end
I have several types of Question, one example is a Slider Question. I want this class to subclass Question:
#import <Foundation/Foundation.h>
#import "Question.h"
#interface SliderQuestion : Question {
(NSString*) min;
(NSString*) max;
}
#property (nonatomic, retain) NSString* min;
#property (nonatomic, retain) NSString* max;
#end
}
#import "SliderQuestion.h"
#implementation SliderQuestion
#synthesize min, max;
#end
Is this the correct way to subclass? Will SliderQuestion inherit the properties contained within Question?
SliderQuestion* s = [[SliderQuestion alloc]init];
NSLog(#"%#", s.qId); //is this valid

Do you really want min and max to be instances of NSString? It seems that floats would be more appropriate.
Also, scrap the () in (NSString *) to remove the warning/error message.
Finally, this is the appropriate way to subclass. An instance of SliderQuestion will inherit all properties and methods of the Question class (and NSObject as well)

Notice the ( and ) around the NSStrings, you might wanna remove those.

Related

Undeclared identifier "isGameCenterAvailable"

Following a book tutorial and seem to run into a snag with the "isGameCenterAvailable" error.
Apparently it is undeclared. Everything else seems to work however so I just need to figure this part out.
Helloworldlayer .m init method
#import <GameKit/GameKit.h>
GameKitHelper* gkHelper = [GameKitHelper sharedGameKitHelper]; gkHelper.delegate = self;
[gkHelper authenticateLocalPlayer];
Class gameKitLocalPlayerClass = NSClassFromString(#"GKLocalPlayer"); bool isLocalPlayerAvailable = (gameKitLocalPlayerClass != nil);
// Test if device is running iOS 4.1 or higher
NSString* reqSysVer = #"4.1";
NSString* currSysVer = [[UIDevice currentDevice] systemVersion]; bool isOSVer41 = ([currSysVer compare:reqSysVer
options:NSNumericSearch] != NSOrderedAscending);
isGameCenterAvailable = (isLocalPlayerAvailable && isOSVer41);
-(void) onLocalPlayerAuthenticationChanged {
[delegate onLocalPlayerAuthenticationChanged];
}
-(void) authenticateLocalPlayer {
GKLocalPlayer* localPlayer = [GKLocalPlayer localPlayer];
if (localPlayer.authenticated == NO) {
[localPlayer authenticateWithCompletionHandler: ^(NSError* error) {
[self setLastError:error]; }];
}
}
Gamekit.h
#import "cocos2d.h"
#import <GameKit/GameKit.h>
#protocol GameKitHelperProtocol
-(void) onLocalPlayerAuthenticationChanged; -(void) onFriendListReceived: (NSArray*)friends; -(void) onPlayerInfoReceived:(NSArray*)players; #end
#interface GameKitHelper : NSObject {
id<GameKitHelperProtocol> delegate; bool isGameCenterAvailable; NSError* lastError;
}
#property (nonatomic, retain) id<GameKitHelperProtocol> delegate;
#property (nonatomic, readonly) bool isGameCenterAvailable; #property (nonatomic, readonly) NSError* lastError;
+(GameKitHelper*) sharedGameKitHelper;
// Player authentication, info
-(void) authenticateLocalPlayer;
-(void) getLocalPlayerFriends;
-(void) getPlayerInfo:(NSArray*)players;
#end
helloworld layer.h
#import "GameKitHelper.h"
#interface helloworldlayer : CCLayer <GameKitHelperProtocol>
{
}
gamekithelper. h
#import "cocos2d.h"
#import <GameKit/GameKit.h>
#protocol GameKitHelperProtocol
-(void) onLocalPlayerAuthenticationChanged; -(void) onFriendListReceived:(NSArray*)friends; - (void) onPlayerInfoReceived:(NSArray*)players; #end
#interface GameKitHelper : NSObject {
id<GameKitHelperProtocol> delegate; bool isGameCenterAvailable; NSError* lastError;
}
#property (nonatomic, retain) id<GameKitHelperProtocol> delegate;
#property (nonatomic, readonly) bool isGameCenterAvailable; #property (nonatomic, readonly) NSError* lastError;
+(GameKitHelper*) sharedGameKitHelper;
// Player authentication, info
-(void) authenticateLocalPlayer;
-(void) getLocalPlayerFriends;
-(void) getPlayerInfo:(NSArray*)players;
#end
The problem is you never actually declare isGameCenterAvailable. To fix this, do this:
//HelloWorldLayer.h
#property (nonatomic) BOOL isGameCenterAvailable;
//HelloWorldLayer.m
#synthesize isGameCenterAvailable = _isGameCenterAvailable;
UPDATE:
To fix the delegate error, try this:
//HelloWorldLayer.h
#property (nonatomic, retain) id<GameKitHelperProtocol> delegate;
//HelloWorldLayer.m
#synthesize delegate;
Hope this helps!

CoreLocation object, can't assign longitude

I'm building an app that works with MapKit and I need to get coordinates from Google Maps.
I made a function that does this (and through debugging I know I get the good coordinates), but it then crashes when I try to assign it to my event object's coordinates.
Below is the code and I've clearly commented with // <---------------- where it fails...
AppDelegate.h
#import <UIKit/UIKit.h>
#import <MapKit/MapKit.h>
#import <CoreLocation/CoreLocation.h>
#import "MapViewController.h"
#import "Event.h"
#interface AppDelegate : UIResponder <UIApplicationDelegate, MKMapViewDelegate, CLLocationManagerDelegate>{
CLLocationManager *locationManager;
}
//-(void)makeTestData:(int)amount;
-(void) addressLocation:(NSString*)adres:(Event*)event;
#property (strong, nonatomic) UIWindow *window;
//#property (strong, nonatomic) NSMutableArray *events;
#end
AppDelegate.m
#import "AppDelegate.h"
#import "ListViewController.h"
#import "Event.h"
#import <RestKit/RestKit.h>
#implementation AppDelegate{
NSMutableArray *events;
/* for test data */
NSMutableArray *titles;
}
#synthesize window = _window;
//#synthesize events;
-(void) addressLocation:(NSString*)adres: (Event*)event {
NSString *urlString = [NSString stringWithFormat:#"http://maps.google.com/maps/geo?q=%#&output=csv&key=MYKEY",
[adres stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]];
NSString *locationString = [NSString stringWithContentsOfURL:[NSURL URLWithString:urlString]];
NSArray *listItems = [locationString componentsSeparatedByString:#","];
double latitude = 0.0;
double longitude = 0.0;
if([listItems count] >= 4 && [[listItems objectAtIndex:0] isEqualToString:#"200"]) {
latitude = [[listItems objectAtIndex:2] doubleValue];
longitude = [[listItems objectAtIndex:3] doubleValue];
}
else {
//Show error
}
CLLocationCoordinate2D location;
location.latitude = latitude;
location.longitude = longitude; // <----- Checked in debugging, coords are good
event.coordinate.latitude = latitude; // <----- can't assign the latitude here =/
event.coordinate.longitude = longitude; // <----- can't assign the longitude here =/
}
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
// START COMMUNICATOIN WITH REST INTERFACE
//RKClient* client = [RKClient clientWithBaseURL:#"link"];
//NSLog(#"I am your RKClient singleton : %#", [RKClient sharedClient]);
// -------------------TEST OBJECTS
//makeTestData(3);
events = [NSMutableArray arrayWithCapacity:3];
titles = [NSMutableArray arrayWithCapacity:3];
[titles addObject:#"Gent Jazz Festival"];
[titles addObject:#"Over blauw bloed en witte billenbijters - zoektocht in het Prinsenhof (zonder gids)"];
[titles addObject:#"DuveltTent"];
Event *event = [[Event alloc] init];
event.title = [titles objectAtIndex:(rand()*100)%3];
event.description = #"omminommie!!!";
event.zone = #"fzfzefez";
event.gemeente = #"Gent";
event.plaats = #"";
event.straat = #"Sint-Veerleplein";
NSString *adres = [NSString stringWithFormat:#"%#, %#", event.gemeente, event.straat];
[self addressLocation:adres:event]; //<---- This function fails, see above for def
event.zone = #"blub";
[events addObject:event];
...
---- EDIT
Like the code is, as above, it doesn't even compile and gives the error:
Expression is not assignable
When I use = location (which I did before) as suggested above I get the following error:
2012-07-13 17:14:20.608 Zone-It-new[565:707] -[Event setCoordinate:]: unrecognized selector sent to instance 0x283ab0
2012-07-13 17:14:20.621 Zone-It-new[565:707] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[Event setCoordinate:]: unrecognized selector sent to instance 0x283ab0'
*** First throw call stack:
(0x3748488f 0x35189259 0x37487a9b 0x37486a83 0x373e1650 0x6a319 0x6a5c9 0x31190cab 0x3118a7dd 0x31158ac3 0x31158567 0x31157f3b 0x33b9a22b 0x37458523 0x374584c5 0x37457313 0x373da4a5 0x373da36d 0x3118986b 0x31186cd5 0x6a097 0x6a03c)
terminate called throwing an exception
Here are my event.h and event.m
event.h
#import <Foundation/Foundation.h>
#import <CoreLocation/CoreLocation.h>
#import <MapKit/MapKit.h>
#import <RestKit/RestKit.h>
#interface Event : NSObject <MKAnnotation>
// required property from mkanotation
#property (nonatomic, readonly) CLLocationCoordinate2D coordinate;
// Optional
#property (nonatomic, copy) NSString *title;
#property (nonatomic, copy) NSString *description;
#property (nonatomic, copy) NSString *zone;
#property (nonatomic, assign) NSString *gemeente;
#property (nonatomic, copy) NSString *straat;
#property (nonatomic, assign) int deelnemers;
#property (nonatomic, copy) NSDate *start;
#property (nonatomic, copy) NSDate *einde;
#property (nonatomic, copy) NSString *plaats;
#property (nonatomic, readonly) int id_nr;
#property (nonatomic, assign) int huisnummer;
#end
event.m
#import "Event.h"
#implementation Event
#synthesize coordinate, title, zone, gemeente, straat, deelnemers, start, einde, plaats, id_nr, huisnummer, description;
#end
Important to note, maybe, is that ARC is on.
Have you tried changing the coordinate property to readwrite? (assign would be a good choice.)

Objective C serialize a collection to JSON/XML

I have a classes looking like this:
#interface AISlideItem: NSObject <NSCoding>
{
NSString* PlaceHolderName;
NSInteger PlaceHolderID;
}
#property (nonatomic, strong) NSString* PlaceHolderName;
#property (nonatomic) NSInteger PlaceHolderID;
#end
#interface AITitleSlideItem : AISlideItem
{
NSString* Title;
}
#property (nonatomic, strong) NSString* Title;
#end
#interface AIParagraphSlideItem : AISlideItem
{
NSMutableArray* Paragraphs;
}
#property (nonatomic, strong) NSMutableArray* Paragraphs;
#end
#interface AITextSlideItem : AISlideItem
{
NSString* Text;
}
#property (nonatomic, strong) NSString* Text;
#end
#interface AIPictureSlideItem : AISlideItem
{
NSMutableData* Picture;
}
#property (nonatomic, strong) NSMutableData* Picture;
#end
#interface AISlideContent : NSObject
{
NSString* LayoutName;
NSMutableArray* Items;
}
#property (nonatomic,strong) NSString* LayoutName;
#property (nonatomic,strong) NSMutableArray* Items;
#end
#interface ContentParaghraph : NSObject
{
NSInteger Level;
NSString* Text;
}
#property (nonatomic) NSInteger Level;
#property (nonatomic, strong) NSString* Text;
#end
I create a complex collection from these classes like this:
NSMutableArray* l = [[NSMutableArray alloc]init ];
AITitleSlideItem* tis1 = [[AITitleSlideItem alloc]init];
[tis1 setPlaceHolderName:#"I don't think we're using this..."];
[tis1 setPlaceHolderID:1];
[tis1 setTitle:#"This is a title"];
AITextSlideItem* tes1 = [[AITextSlideItem alloc]init];
[tes1 setPlaceHolderName:#"I don't think we're using this..."];
[tes1 setPlaceHolderID:2];
[tes1 setText:#"This is the description"];
AISlideContent* slide1 = [[AISlideContent alloc]init];
[slide1 setLayoutName:#"Title content"];
[[slide1 Items]addObject:tis1];
[[slide1 Items]addObject:tes1];
[l addObject:slide1];
[l addObject:slide1];
What i want to to serialize the NSMutableArray l into any portable format like json or xml.
Could you please post some code doing so?
Sincerely
Zoli
After further investigation i found nothing more suitable for my needs.
I decided to learn a bit more about JSON and create a function that creates the JSON structure manually. Even if it took 2-3 hours, it did worth all the effort.

Objective-C NSKeyedUnarchiver unloading

In some AppDelegate class I have property NSDictionary *dict;
In applicationDidFinishLaunching i'm loading it like:
dict = (NSDictionary*) [NSKeyedUnarchiver unarchiveObjectWithFile:
#"/Users/username/Desktop/storage"];
Then, I have Outlet for button click. But inside click-action handler I could not access to dict's elements. What am I doing wrong?
EDIT:
here's .h-file:
#import <Cocoa/Cocoa.h>
#interface tttAppDelegate : NSObject <NSApplicationDelegate> {
NSWindow *window;
NSDictionary *dict;
}
#property (assign) IBOutlet NSWindow *window;
- (IBAction)click:(id)sender;
#end
and .m-file:
#import "tttAppDelegate.h"
#implementation tttAppDelegate
#synthesize window;
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification
{
dict = (NSDictionary*) [NSKeyedUnarchiver unarchiveObjectWithFile:#"/some/storage"];
NSLog(#">>>>>>> %#", [dict valueForKey:#"test"]); // ok
}
- (IBAction)click:(id)sender {
NSLog(#">>>>>>> %#", [dict valueForKey:#"test"]); // fail
}
#end
You should use property accessors instead of directly accessing your instance variables:
In your .h file:
#interface tttAppDelegate : NSObject <NSApplicationDelegate> {
NSWindow *window;
NSDictionary *dict;
}
#property (assign) IBOutlet NSWindow *window;
#property (nonatomic, retain) NSDictionary *dict;
- (IBAction)click:(id)sender;
#end
In your .m:
#implementation tttAppDelegate
#synthesize window;
#synthesize dict;
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification
{
self.dict = (NSDictionary*) [NSKeyedUnarchiver unarchiveObjectWithFile:#"/some/storage"];
NSLog(#">>>>>>> %#", [self.dict valueForKey:#"test"]); // ok
}
- (IBAction)click:(id)sender {
NSLog(#">>>>>>> %#", [self.dict valueForKey:#"test"]); // fail
}
#end
There are several reasons for doing this, but the most important in this case is that that way the accessor methods can handle memory management of the instance variable.

access variable of another class

How to access variables of other class? This is how I implemented it.
#interface Class1 :NSObject {
NSString *Data;
}
#property (nonatomic, retain) NSString *Data;
#implementation Class1
#synthesize Data;
someMethod{
self.Data = #"something";
}
and in Class2 :
#implementation Class2
someMethodOfClass2{
Class1 *c=[[Class1 alloc]init];
[c someMethod];
NSString *str=c.Data;
}
I get c.Data as null in Class2. Am I doing anything wrong here?
-----------myClass1--------------
#interface APIManager : NSObject {
NSString *Data;
}
#property (nonatomic, retain) NSString *Data;
-(void)getData;
#end
#implementation APIManager
#synthesize Data;
-(void)getData{
self.Data=#"response";
}
--------myClass2-------------
#interface Search : NSObject {
}
-(void)searchForItems:(NSString *)query;
#end
#implementation Search
-(void)searchForItems:(NSString *)query {
APIManager *apiManager=[[APIManager alloc]init];
[apiManager getData];
NSLog(#"%#",[apiManager Data]);
}
You should probably use self.Data = #"something" instead of self.Data = "something"
In Objective-C you have to use #"something" instead of "something". Also aren't you missing the variable declaration? In your #interface you should do something like NSString *Data.