Objective C: No #interface declares the selector error - ios

I have a class called TAPJSONPoster. It's .h is as follows:
#import <Foundation/Foundation.h>
#interface TAPJsonPoster : NSObject
-(id)initWithURL:(NSURL*)url WithJson:(NSData*)jsondata;
-(NSData*)getResponse;
#end
It's .m is:
#import "TAPJsonPoster.h"
#interface TAPJsonPoster()
#property NSURL *url;
#property NSData *jsondata;
#end
#implementation TAPJsonPoster
-(id)initWithURL:(NSURL*)url WithJson:(NSData*)jsondata
{
self=[super init];
self.url=url;
self.jsondata=jsondata;
return self;
}
-(NSData*)getResponse
{
return self.jsondata;
}
#end
I still have tto fill in getResponse, but the init itself is not working. In my ViewController I have
#import "TAPJSONPostConnector.h"
and a method to login:
- (IBAction)loginValidate:(id)sender {
NSString *username=self.unTextField.text;
NSString *password=self.pwdTextField.text;
NSArray *params=[NSArray arrayWithObjects:#"userId",#"password", nil];
NSDictionary *dictionary=[NSDictionary dictionaryWithObjectsAndKeys:
#"_requestName", #"login",
#"_ParamNames", params,
#"userId", username,
#"password", password,
nil];
NSData *data=[NSJSONSerialization dataWithJSONObject:dictionary options:NSJSONWritingPrettyPrinted error:nil];
NSURL *url=[NSURL URLWithString:#"loginURL"];
TAPJSONPostConnector *connector=[[TAPJSONPostConnector alloc] initWithURL:url WithJson:data];
}
The last line where I am making the PostConnector is giving me an error saying that
No #interface in TAPJSONPostConnector declares the selector initWithURL:WithJson
What am I doing wrong?
EDIT
I put in [connector getResponse] below the connector initialization and I get the same error for this method also, am I doin something wrong in importing?

Well, you're calling the initWithURL:withJson: initializer on TAPJSONPostConnector
TAPJSONPostConnector *connector=[[TAPJSONPostConnector alloc] initWithURL:url WithJson:data];
But it looks like this is declared on the TAPJsonPoster class. Perhaps this is what you meant.
TAPJsonPoster *connector=[[TAPJsonPoster alloc] initWithURL:url WithJson:data];

Either you're allocating a wrong object TAPJSONPostConnector instead of TAPJsonPoster
TAPJsonPoster *connector=[[TAPJsonPoster alloc] initWithURL:url WithJson:data];
Or you forgot to change the super class for TAPJSONPostConnector as TAPJsonPoster
#interface TAPJSONPostConnector : TAPJsonPoster
Change whatever fits your needs
One tip if you can change the name of method initWithURL: withJson: that will be according to the naming convetion

Related

Exception 'Invalid type in JSON write

I have an interface that looks like this: #import <Foundation/Foundation.h>
#import <AVFoundation/AVFoundation.h>
NS_ASSUME_NONNULL_BEGIN
#interface AVBase : NSObject
#property NSString *portName;
#property NSString *uid;
#property NSString* port;
- (id) initWithPortName:(NSString *)portName andUID:(NSString *)uid andPort:(AVAudioSessionPort)port;
#end
NS_ASSUME_NONNULL_END
and the .m file
#implementation AVBase
- (id)initWithPortName:(NSString *)portName andUID:(NSString *)uid andPort:(AVAudioSessionPort)port
{
self = [super init];
if (self)
{
self.portName = portName;
self.uid = uid;
self.port = [port description];
}
return self;
}
#end
I want to create an array of current outputs for the AVAudioSession, so I do it like this:
NSMutableArray *myArray = [[NSMutableArray alloc] init];
AVAudioSession *session = AVAudioSession.sharedInstance;
NSArray *outputs = [[session currentRoute] outputs];
for(AVAudioSessionPortDescription* output in outputs)
{
AVBase* av = [AVBase alloc];
av = [av initWithPortNumber:output.portName andUID:output.UID andPort:output.portType];
[myArray addObject:av];
}
NSError *error;
NSData *jsonData = [NSJSONSerialization dataWithJSONObject:myArray options:NSJSONWritingPrettyPrinted error:&error];
But when I try to serialize myArray I get an error that says:
Exception 'Invalid type in JSON write (AVBase)
I don't understand what's wrong, all the properties in my class are of type NSString so it should work.
NSJSONSerialization accepts only NSArray, NSDictionary, NSString, NSNumber (and NSNull), for its top level, but all sublevels/subproperties too.
myArray is a NSArray of AVBase, and AVBase isn't one of them.
You need to convert an AVBase into a NSDictionary first.
-(NSDictionary *)toDict {
return #{#"portName": portName, #"uid": uid, #"port": port};
}
Then:
[myArray addObject:[av toDict]];
If you don't use AVBase, or just for it, you can construct the NSDictionary directly from AVAudioSessionPortDescription *output, no need to use the AVBase here.

Access and change values of an NSMutableDictionary from one class to another iOS

I am dealing with NSMutableDictionary in one class, But I want to change it's value in an another class.
Here is the code where it is declared.
#interface MyClass0 : NSObject
{
#public
NSMutableDictionary *valuee;
}
#property (nonatomic, copy) NSMutableDictionary *valuee;
#end
and in the implementation of myClass0 I do
#synthesize valuee;
and I also declare value as
valuee = #{#"name" : #"Aryan"};
Now I want to access and change the value of this dictionary in an another class.
Use #property (nonatomic, strong) NSMutableDictionary *valuee;
Now assign the value as
self.valuee = [[NSMutableDictionary alloc] init];
You can do this in the init method of your MyClass0.
Now you can access the value from another class like
MyClass0 *myClassInstance = [[MyClass0 alloc] init];
NSMutableDictionary *dict = myClassInstance.valuee;
You can write the getter by hand --
- valuee {
return valuee;
}
so the code instance.valuee will give you the original object not the copy.

Why can I not initialize this NSArray With Objects?

I have an array containing objects of a custom-made class. However, on initialization the compiler gives me an error - "Lexical or Preprocessor" Expected ':'
interface myClass : NSObject
#property (readwrite, strong) NSString* name;
#property (readwrite, strong) NSString* home;
#property (readwrite, strong) Preference pref; // This is another custom class
-(id) initWithName:(NSString*) name home:(NSString*) home preference:(Preference) preference;
end
#interface MyViewController()
#property (nonatomic, strong) NSArray *rowArray;
#end
#implementation MyViewController
...
...
...
- (void) initializeArray
{
self.rowArray = #{
[[myClass alloc] initWithName:#"Harry" home:#"New York" preference :Acura],
[[myClass alloc] initWithName:#"Win" home:#"Seattle" preference :Toyota];
};
}
Can someone tell me just where I am messing up and why I'm getting this error?
The Objective-C literal for an array is with square brackets,
NSArray *anArray = #[obj1, obj2].
In the code you posted it is trying to make a Dictionary,
NSDictionary *aDict = #{"key1" : obj1, #"key2" : obj2}
so this is why it is saying it expects a :.
The line should read,
self.rowArray = #[
[[myClass alloc] initWithName:#"Harry" home:"New York" preference :Acura],
[[myClass alloc] initWithName:#"Win" home:"Seattle" preference :Toyota];
];
As others have pointed out the there are a few other errors with the code and those city names are not NSString's, but I guess this is just an example snippet.

How to store data in class in iOS programming?

The goal, to create a class which contains an array of data to be used throughout the application by other classes.
I have this GlobalObject.h
It declares the array to be used to store the data.
#import <Foundation/Foundation.h>
#interface GlobalObjects : NSObject
#property (retain) NSMutableArray *animals;
-(id)init;
#end
I have this GlobalObject.m.
It contains the NSDictionary data and stores in to the array.
#import <Foundation/Foundation.h>
#interface GlobalObjects : NSObject
#property (retain) NSMutableArray *animals;
-(id)init;
#end
#import "GlobalObjects.h"
#implementation GlobalObjects
#synthesize animals;
-(id)init{
self = [super init];
if (self) {
// Define the data
NSArray *imagesValue = [[[NSArray alloc] initWithObjects:#"dog.wav",#"cat.png",#"bird.png",nil] autorelease];
NSArray *audioValue =[[[NSArray alloc] initWithObjects:#"dog.wav",#"cat.wav",#"bird.wav",nil] autorelease];
NSArray *descriptionValue = [[[NSArray alloc] initWithObjects:#"Dog",#"Cat",#"Bird",nil] autorelease];
// Store to array
for (int i=0; i<8; i++) {
NSDictionary *tempArr = [NSDictionary dictionaryWithObjectsAndKeys:[imagesValue objectAtIndex:i],#"image", [audioValue objectAtIndex:i],#"audio", [descriptionValue objectAtIndex:i], #"description", nil];
[self.animals addObject:tempArr];
}
}
return self;
}
#end
Here's how I call it.
// someOtherClass.h
#import "GlobalObjects.h"
#property (nonatomic, retain) GlobalObjects *animalsData;
// someOtherClass.m
#synthesize animalsData;
self.animalsData = [[[GlobalObjects alloc] init] autorelease];
NSLog(#"Global Object %# ",self.animalsData.animals);
Now the problem is, when I call this array in another class, it always returns null.
I'm new to iOS programming. So probably my method is wrong?
You forgot to allocate the animals array in the init method of "GlobalObjects":
self.animals = [[NSMutableArray alloc] init];
If you don't do this, self.animals is nil and addObject has no effect.
Since you do not use ARC, remember to release the array in dealloc.
EDIT: As #H2CO3 and #Bastian have noticed, I forgot my pre-ARC lessons. So the correct way to allocate self.animals in your init method is
self.animals = [[[NSMutableArray alloc] init] autorelease];
and in dealloc you have to add
self.animals = nil;
before calling [super dealloc]. I hope that I got it right now!
Yes, it's wrong - an instance variable isn't tied to a class itself, but to a particular instance of the class. The Cocoa-standard solution to this problem is creating a shared instance of the class - instead of
elf.animalsData = [[[GlobalObjects alloc] init] autorelease];
write
elf.animalsData = [GlobalObjects sharedInstance];
and implement the + sharedInstance method like this:
+ (id)sharedInstance
{
static shared = nil;
if (shared == nil)
shared = [[self alloc] init];
return shared;
}
As #MartinR pointed out, you make another mistake: you don't create the array you're adding objects to - then it remains nil, cancelling out the effect of all method calls on itself. You have to alloc-init a mutable array for it in the - init method.

ios NSDictionary always shows up empty

h
#import <UIKit/UIKit.h>
#interface LoginViewController : UIViewController <UITextFieldDelegate>
#property (nonatomic, retain) NSDictionary *_data;
#end
m
#import "LoginViewController.h"
#import "XMLReader.h"
#implementation LoginViewController
static NSDictionary *_raceInformation;
#synthesize _data, bibInput, lastNameInput, error;
- (id)initWithCoder:(NSCoder *)aDecoder
{
self = [super initWithCoder:aDecoder];
if (self) {
NSError *e = [NSError alloc];
NSString *xml = [NSString stringWithContentsOfFile:[[NSBundle mainBundle] pathForResource:#"testhalfmarathon" ofType:#"xml"] encoding:NSUTF8StringEncoding error:&e];
NSDictionary *asdf = [XMLReader dictionaryForXMLString:xml error:nil];
self._data = [XMLReader dictionaryForXMLString:xml error:nil];
//[xml release];
//[e release];
// !! BREAKPOINT HERE
}
return self;
}
When I hit the breakpoint, the value for self._data is nil. However, the value for asdf is the correct dictionary value I would expect in self._data. What gives?
backstory: I'm a n00b when it comes to MRC as I usually use ARC/GC languages.
What line of code did you put the breakpoint against? If it was just a blank line it will actually break at the previous valid line of code, which may have been before self._data was set.
Try putting NSLog(#"data %#", self._data); instead of your breakpoint and see what gets logged.
BTW, I see you had [xml release], which you commented out, presumably because it wasn't working. The reason this line is wrong is that [XMLReader dictionaryForXMLString...] returns an autoreleased object that shouldn't be released again.
In general, in Objective-C if a method name doesn't begin with "new", "alloc" or "copy" then it returns an autoreleased object that you don't need to release yourself.

Resources