getting an error in Objective C - objective-c

I am getting an error in the following code. I could not guess what mistake i have done for such error to come up.
remote.h
struct RMH_REQUEST_SESSION_MSG //Message Data
{
int uDeviceID;
int uProtocolVersion;
int uReserved[5];
};
RS232MsgRequestSession.m
#implementation RS232MsgRequestSession
-(id)init
{
if (self = [super init]) {
struct RMH_REQUEST_SESSION_MSG st;
}
return self;
}
#end
xyz.h
#import "RS232MsgRequestSession.h"
#implementation xyz
-(void)Open{
RS232MsgRequestSession* pMsg = [[RS232MsgRequestSession alloc]init];
pMsg->st.uProtocolVersion = RS232_VERSION; //error
pMsg->st.uDeviceID = RS232_PROTOCOL_DEVICE_ID; //error
memset(pMsg->st.uReserved,0x00,sizeof(pMsg->st.uReserved)); //error
}
#end
Error:'struct RS232MsgRequestSession' has no member named 'st'

Put iVar declaration in class's #interface block. In your code st is just a local variable in init method:
#interface RS232MsgRequestSession : NSObject{
...
#public
struct RMH_REQUEST_SESSION_MSG st;
}
...
#end

You are defining st as a local variable in the init function.
Move struct RMH_REQUEST_SESSION_MSG st; to the class definition in RS232MsgRequestSession.h

What you forgot to do was include the struct in your #interface as a public instance variable:
#interface RMH2532MsgRequestSession : NSObject {
#public
struct RMH_REQUEST_SESSION_MSG st;
}
- (void) Open;
#end
And your #implementation should be empty:
#implementation RS232MsgRequestSession
#end
PS - The reason why you must use #public here is because in xyz, you were doing a direct dereference of the object using the member operator ->. This is not allowed by default when working with Objective-C objects. However, if the instance variables are under a #public attribute, then you will not have any problems doing this.
As you might have guessed by now, using #public is a Very Bad Idea -- usually. It breaks encapsulation and opens a pandora's box of potential problems that you wouldn't have otherwise had if you had used proper encapsulation.

Related

Invoking function getting stuck in a recursive loop and never comes

I am learning Objective-C inheritance and my program is getting lost in a recursive loop and won't come out. It gets hung up when calling a getter function.
I am using XCode version: Version 6.2 (6C101)
My program is given below
Vehicle.h
#ifndef exercise_2_Vehicle_h
#define exercise_2_Vehicle_h
#import <Foundation/Foundation.h>
#interface Vehicle : NSObject
#property float speed;
-(void) start;
-(void) stop;
-(void) park;
#end
#endif
Vehicle.m
#import "Vehicle.h"
#implementation Vehicle
-(void) setSpeed:(float)speed {
self.speed = speed;
}
-(float) speed {
return self.speed;
}
-(void) start {
NSLog(#"Starting the vehicle");
}
-(void) stop {
NSLog(#"Stopping the vehicle");
}
-(void) park {
NSLog(#"Parking the vehicle");
}
#end
Car.h
#ifndef exercise_2_Car_h
#define exercise_2_Car_h
#import "Vehicle.h"
#interface Car : Vehicle
#property (nonatomic) NSString* make;
-(Car*) initMake: (NSString*) make;
-(NSString*) make;
#end
#endif
Car.m
#import "Car.h"
#implementation Car
-(Car*) initMake:(NSString *)make {
self = [super init];
if (self) {
self.make = make;
}
return self;
}
-(NSString*) make {
return self.make;
}
#end
main.m
#import <Foundation/Foundation.h>
#import "Car.h"
#import "Vehicle.h"
int main(int argc, const char * argv[]) {
#autoreleasepool {
// insert code here...
Car* car = [[[Car alloc] init] initMake: #"Camry"];
//[car setSpeed:45];
NSLog(#"The model initialized is ");
[car make];
// [car speed];
}
return 0;
}
The issue you have is caused by creating the property for speed:
#property float speed;
and overriding setSpeed: method.
When you create #property compiler adds two methods for you, in your example setSpeed and speed.
This command:
self.speed = speed;
is equal to:
[self setSpeed: speed];
and inside setSpeed you have this command again which cause the loop. In your example you can remove both methods (setSpeed and speed) because compiler will add it for you. If you need it because you want to do some customisation you should use _speed instead self.speed.
_speed is backed variable added by compiler when using #property.
Change your method to:
-(void) setSpeed:(float)speed {
_speed = speed;
}
to remove the infinite loop.
In the
- (NSString*)make;
use
return _make
instead. The same with the speed.
If you return "self.x" in a getter method, then it's going to try and call the method again because you're requesting it on self. XCode will automatically convert the properties into variables that can be accessed with an '_' character, so you don't need to do any extra work.
You could also ignore our advice and remove both the "speed" and "make" getter methods you have made, because XCode automagically creates them for you.

Property doesn't match type of instance variable?

I took some sample code from Apple's SimpleFTPSample
Which looks like this:
#interface PutController () <UITextFieldDelegate, NSStreamDelegate>
...
#property (nonatomic, assign, readonly) uint8_t *buffer;
...
#end
#implementation PutController
{
uint8_t _buffer[kSendBufferSize];
}
...
#end
But when I copy it to my code I get an error:
Type of property 'buffer' ('uint8_t *' (aka 'unsigned char *')) does not match type of instance variable '_buffer' ('unsigned char [32768]')
My code is exactly the same as their sample, and yet it won't compile. What's going on here?
Unfortunately, while arrays can decay to pointers, with clang, at least, it doesn't auto-decay into a readonly pointer when used in a property.
The simplest way to fix this is by having a second instance variable which is simply a pointer to the first element into the array, and have your property synthesize to that, like this:
#interface MyObj : NSObject
#property (readonly) uint8_t *buffer;
#end
#implementation MyObj {
uint8_t *_bufferPtr;
uint8_t _buffer[1024];
}
#synthesize buffer = _bufferPtr;
-(id) init {
if (self = [super init]) {
_bufferPtr = &_buffer[0];
}
return self;
}
#end
Alternativey, simply implement your own getter implementation to simply return the pointer to the first element of buffer. It's your call, really.
It isn't optimal, but it does appear to work the way you want.

Declaring instance variables in iOS - Objective-C

Ok, I've read a lot around these days about this topic and I alwyas get confused because the answers is different every search I make.
I need to know the best way to declare instance variables in iOS. So far I know I should only declare them inside .m file and leave .h clean. But I can't do it: the compiler gives me compilation erros.
Here is some code from .m only.
#interface UIDesign ()
// .m file
{
NSString *test2 = #"test2";
}
#property (nonatomic, assign) int privateInt;
#end
#implementation UIDesign
{
NSString *test1 = #"test1";
}
Both strings are declared incorrectly and I don't know why. The compiler says: expected ';' at end of declaration list.
So the question is: how can I declare instance variables? I will only need them inside the class.
You cannot initialize instance variables. They are all initialized to nil or zeroes. So compiler expect a semicolon when you are writing an equal sign.
You can initialize them in init method.
You are attempting to add an instance variable to a class extension or category which is unsupported. [EDIT 2013-05-12 06-11-08: ivars in class extension are supported, but not in categories.] As an alternative:
#interface UIDesign : NSObject
#end
#interface UIDesign ()
#property (nonatomic, assign) int privateInt;
#end
#implementation UIDesign
#synthesize privateInt = _privateInt;
- (void)someMethod {
self.privateInt = 42;
}
#end
On the other hand, if you just want to declare an instance variable inside the implementation, just do it there:
#implementation UIDesign {
int _privateInt;
}
#end
EDIT: just noticed that you're also attempting to initialize instance variables in the declaration which is also unsupported. So:
#interface UIDesign : NSObject
#end
#implementation UIDesign {
NSString *_test;
}
- (id)init {
self = [super init];
if( !self ) return nil;
_test = #"Foo";
return self;
}
#end

Hide instance variable from header file in Objective C

I came across a library written in Objective C (I only have the header file and the .a binary).
In the header file, it is like this:
#interface MyClass : MySuperClass
{
//nothing here
}
#property (nonatomic, retain) MyObject anObject;
- (void)someMethod;
How can I achieve the same thing? If I try to declare a property without its corresponding ivar inside the interface's {}, the compiler will give me an error. Ultimately, I want to hide the internal structure of my class inside the .a, and just expose the necessary methods to the header file. How do I declare instance variables inside the .m? Categories don't allow me to add ivar, just methods.
For 64 bit applications and iPhone applications (though not in the simulator), property synthesis is also capable of synthesizing the storage for an instance variable.
I.e. this works:
#interface MyClass : MySuperClass
{
//nothing here
}
#property (nonatomic, retain) MyObject *anObject;
#end
#implementation MyClass
#synthesize anObject;
#end
If you compile for 32 bit Mac OS X or the iPhone Simulator, the compiler will give an error.
You may use of the same idiom used in Cocoa classes. If you have a look to NSString class interface in NSString.h you'll see that there is no instance variable declared. Going deeper in GNUstep source code you'll find the trick.
Consider the following code.
MyClass.h
#interface MyClass : NSObject
// Your methods here
- (void) doSomething;
#end
MyClass.m
#interface MyClassImpl : MyClass {
// Your private and hidden instance variables here
}
#end
#implementation MyClass
+ (id) allocWithZone:(NSZone *)zone
{
return NSAllocateObject([MyClassImpl class], 0, zone);
}
// Your methods here
- (void) doSomething {
// This method is considered as pure virtual and cannot be invoked
[self doesNotRecognizeSelector: _cmd];
}
#end
#implementation MyClassImpl
// Your methods here
- (void) doSomething {
// A real implementation of doSomething
}
#end
As you can see, the trick consist in overloading allocWithZone: in your class. This code is invoked by default alloc provided by NSObject, so you don't have to worry about which allocating method should be used (both are valid). In such allocWithZone:, you may use the Foundation function NSAllocateObject() to allocate memory and initialize isa for a MyClassImpl object instead of MyClass. After that, the user is dealing with a MyClassImpl object transparently.
Of course, the real implementation of your class shall be provided by MyClassImpl. The methods for MyClass shall be implemented in a way that considers a message receiving as an error.
You can use a class extension. A class extension is similar as category but without any name. On the Apple documentation they just define private methods but in fact you can also declare your internal variables.
MyClass.h
#class PublicClass;
// Public interface
#interface MyClass : NSObject
#property (nonatomic, retain) PublicClass *publicVar;
#property (nonatomic, retain) PublicClass *publicVarDiffInternal;
- (void)publicMethod;
#end
MyClass.m
#import "PublicClass.h"
#import "InternalClass.h"
// Private interface
#interface MyClass ( /* class extension */ )
{
#private
// Internal variable only used internally
NSInteger defaultSize;
// Internal variable only used internally as private property
InternalClass *internalVar;
#private
// Internal variable exposed as public property
PublicClass *publicVar;
// Internal variable exposed as public property with an other name
PublicClass *myFooVar;
}
#property (nonatomic, retain) InternalClass *internalVar;
- (void)privateMethod;
#end
// Full implementation of MyClass
#implementation MyClass
#synthesize internalVar;
#synthesize publicVar;
#synthesize publicVarDiffInternal = myFooVar
- (void)privateMethod
{
}
- (void)publicMethod
{
}
- (id)init
{
if ((self = [super init]))
{
defaultSize = 512;
self.internalVar = nil;
self.publicVar = nil;
self.publicVarDiffInternal = nil; // initialize myFooVar
}
return self;
}
#end
You can give MyClass.h to anyone with just your public API and public properties. On MyClass.m you declare your member variable private and public, and your private methods, on your class extension.
Like this it's easy to expose public interfaces and hide detail implementation. I used on my project without any troubles.
According to the documentation I've been looking at there is no problem. All you have to do to hide instance variables is to declare them at the start of the #implementation section, inside { ... }. However, I'm a relative newcomer to Objective C and there's a chance I have misunderstood something - I suspect that the language has changed. I have actually tried this system, using XCode 4.2, building code for the iPad, and it seems to work fine.
One of my sources for this idea is the Apple developer documentation at http://developer.apple.com/library/ios/#documentation/cocoa/conceptual/objectivec/Chapters/ocDefiningClasses.html, which gives this pattern:
#implementation ClassName
{
// Instance variable declarations.
}
// Method definitions.
#end
Two possibilities:
It could be taking advantage of the modern runtime's ability to synthesize instance variables, as bbum suggested.
The property might not have an underlying instance variable in that class. Properties do not necessarily have a one-to-one mapping with instance variables.
No you can't. But you can do this if you're not using #property:
.h
#interface X : Y {
struct X_Impl* impl;
}
-(int)getValue;
#end
.m
struct X_Impl {
int value;
};
...
#implementation X
-(void)getValue {
return impl->value * impl->value;
}
#end
How about a macro trick?
Have tested code below
have tested with dylibs - worked fine
have tested subclassing - Warning! will break, I agree this makes the trick not that useful, but still I think it tells some about how ObjC works...
MyClass.h
#interface MyClass : NSObject {
#ifdef MYCLASS_CONTENT
MYCLASS_CONTENT // Nothing revealed here
#endif
}
#property (nonatomic, retain) NSString *name;
#property (nonatomic, assign) int extra;
- (id)initWithString:(NSString*)str;
#end
MyClass.m
// Define the required Class content here before the #import "MyClass.h"
#define MYCLASS_CONTENT \
NSString *_name; \
int _extra; \
int _hiddenThing;
#import "MyClass.h"
#implementation MyClass
#synthesize name=_name;
#synthesize extra=_extra;
- (id)initWithString:(NSString*)str
{
self = [super init];
if (self) {
self.name = str;
self.extra = 17;
_hiddenThing = 19;
}
return self;
}
- (void)dealloc
{
[_name release];
[super dealloc];
}
#end
DON'T do this, but I feel it should be noted that the runtime has the ability to add ivars whenever you want with class_addIvar
I was able to do the following in my library:
myLib.h:
#interface MyClass : SomeSuperClass <SomeProtocol> {
// Nothing in here
}
- (void)someMethods;
#end
myLib.m
#interface MyClass ()
SomeClass *someVars;
#property (nonatomic, retain) SomeClass *someVars;
#end
#implementation MyClass
#synthesize someVar;
- (void)someMethods {
}
#end
The protocol is optional of course. I believe this also makes all your instance variables private though I'm not 100% certain. For me it's just an interface to my static library so it doesn't really matter.
Anyway, I hope this helps you out. To anyone else reading this, do let me know if this is bad in general or has any unforeseen consequences. I'm pretty new to Obj-C myself so I could always use the advice of the experienced.
I don't think the following code written in another answer is working as expected.
The "SomeClass *someVars" defined in the extension class is not an instance variable of MyClass. I think it is a C global variable. If you synthesize someVars, you will get compile error. And self.someVars won't work either.
myLib.h
#interface MyClass : SomeSuperClass <SomeProtocol> {
// Nothing in here
}
- (void)someMethods;
#end
myLib.m
#interface MyClass ()
SomeClass *someVars;
#property (nonatomic, retain) SomeClass *someVars;
#end
#implementation MyClass
#synthesize someVar;
- (void)someMethods {
}
#end

How to deal with double composition and inheritance?

I found this related question: How do I use composition with inheritance?
I would like to do the same with Objective-C, that is to say that a GenericView knows that its property obj is a GenericObject, and that a SpecializedView knows that the very same obj property is a SpecializedObject.
Here is an example that will be clearer:
//
// Example.m
#import <UIKit/UIKit.h>
/* HEADER */
// Electrical Machine
#interface ElectricalMachine : NSObject {
}
- (void)plugIn;
#end
// Toaster
#interface Toaster : ElectricalMachine {
}
- (float)getThermostat;
#end
// GenericView
#interface GenericView : NSObject {
ElectricalMachine *machine;
}
- (void)doSomethingGeneric;
#property (nonatomic, retain) ElectricalMachine *machine;
#end
//SpecializedView
#interface SpecializedView : GenericView {
}
- (void)doSomethingSpecialized;
#end
/* IMPLEMENTATION */
// GenericView
#implementation GenericView
#synthesize machine;
- (void)doSomethingGeneric {
Toaster *toaster = [[Toaster alloc] init];
[toaster plugIn];
self.machine = toaster;
[toaster release];
}
#end
// SpecializedView
#implementation SpecializedView
- (void)doSomethingSpecialized {
/* ERROR HERE
* Incompatible types in initialization
* 'ElectricalMachine' may not respond to '-getThermostat'
*/
float r = [machine getThermostat];
r = r;
// ...
}
#end
As you see, I get an error at the end, because for SpecializedView the machine property is an ElectricalMachine, not a Toaster.
Thank you very much for your help!
Old Question
Here is the first version of my question, which was maybe too cryptic:
I have the following generic view:
#interface GenericView {
GenericObject obj;
}
- (id)doSomething;
I also have the following specialized view:
#interface SpecializedView : GenericView {
}
- (id)doSomethingElse;
I have the following object:
#interface GenericObject {
}
- (id)plugIn;
and the following specialized object:
#interface SpecializedObject : GenericObject {
}
- (float)toastTime;
Let's say I want GenericView to handle GenericObject, and SpecializedView to handle the same object, knowing that it is SpecializedObject.
Let me explain by showing implementations:
GenericView doSomething
- (id)doSomething {
[obj plugIn];
}
SpecializedView doSomethingElse
- (id)doSomethingElse {
// ERROR here
float time = [obj toastTime];
}
I will get the following warning:
'GenericObject' may not respond to '-toastBread'
and the following error:
Incompatible types in assignement
Which is logical, since I have defined the type of obj as GenericObject. I want to be able to use methods from GenericObject in GenericView, and methods from SpecializedObject in SpecializedView. Is there a way to precise that obj has to be a GenericObject in GenericView to be handled, and has to be a SpecializedObject to be dealt with in SpecializedView, without adding a property? How would you do that?
Objective-C is a dynamically-typed language and methods are resolved at runtime, not compile time. If in SpecializedView, obj is in fact of an object of type SpecializedObject (even though it's declared as GenericObject), it will in fact respond to a toastBread message. The compiler will generate a warning but you can ignore it.
If SpecializedView may have both GenericObjects and SpecializedObjects, you can make sure that obj responds to toastBread using the respondsToSelector: message (inherited from NSObject):
if ([obj respondsToSelector:#selector(toastBread)]) {
[obj toastBread];
}