Request for member 'pData' with BOOL value TRUE is not a structure or union-Objective C - objective-c

I could not use the pData[4096] to pass it to the other function from main.
data.m
------
#implementation data
static int msgID;
static char pData[4096]="\0";
+ (void)initialize
{
//some initialisations
msgID =123;
}
-(void)SwapEndian:(uint8_t*)pData withBOOLValue:(BOOL)bIsAlreadyLittleEndian
{
NSLog("%s %s",pData,bIsAlreadyLittleEndian);
}
#end
main.m
-------
[dat SwapEndian:dat.pData withBOOLValue:TRUE];
I am getting pData undeclared. As pData is declared as static inside the Data
implementation i tried with dat.pData to pass it from main.But when i do it i am getting
Request for member 'pData' with BOOL value TRUE is not a structure or union.

It is difficult to determine what the code is supposed to do, but here is how to create an Objective-C object that holds an integer identifier and a 4096-character array. Please note that this sort of thing is usually discouraged. Unless you have a really specific reason for using int and char[], the identifier should be NSInteger and the data should be an NSData or NSString object.
I have also used some of the "standard" naming conventions. If you are writing Cocoa code, it helps to drink a lot of the Kool-Aid.
Message.h:
#interface Message : NSObject
{
int identifier;
char data[4096];
}
#property (nonatomic, assign) int indentifier;
#property (nonatomic, readonly) char * data;
- (void)swapEndian:(BOOL)flag;
#end
Message.m:
#implementation Message
#synthesize identifier;
#synthesize data;
- (id)init
{
if ((self = [super init]) == nil) { return nil; }
identifier = 0;
data[0] = '\0';
return self;
}
- (void)swapEndian:(BOOL)flag
{
NSLog(#"%s %d", data, flag);
}
#end
main.m:
#import "Message.h"
...
Message * message = [[[Message alloc] init] autorelease];
message.identifier = 123;
[message swapEndian:YES];

Related

What's happening when you synthesize a subclass' variable?

I have a superclass and a subclass. I can access the variable some_property (declared in the superclass) via self.some_property in the subclass.
However if I try to access the instance variable directly with _some_property, I'll get the error 'Use of undeclared identifier _some_property...'.
Using #synthesize some_property = _some_property silences this warning.
Whats going on when I re-synthesize the property?
You are creating another ivar named _some_property — and also overriding the getter method to return the value of this new ivar. The compiler gives you an error about this if the base class's #implementation (i.e. the implicit declaration of its _some_property ivar) is visible at the site of the #synthesize in the subclass.
(By the way, don't do this!)
You can demonstrate to yourself by inspecting the Obj-C runtime:
#import <Foundation/Foundation.h>
#import <objc/runtime.h>
#interface Base : NSObject
#property id foo;
#end
#interface Derived : Base
#end
#implementation Derived
#synthesize foo=_foo; // the compiler doesn't know about Base's _foo yet, so this is OK...
- (instancetype)init {
if ((self = [super init])) {
_foo = #"I'm derived";
}
return self;
}
#end
#implementation Base // after Derived to avoid the error
- (instancetype)init {
if ((self = [super init])) {
_foo = #"I'm base";
}
return self;
}
#end
int main(int argc, const char * argv[]) {
#autoreleasepool {
Derived *obj = [Derived new];
NSLog(#"getter returns %#", obj.foo);
unsigned int count = 0;
// Examine Base ivars
NSLog(#"Base ivars:");
Ivar *ivars = class_copyIvarList([Base class], &count);
for (unsigned int i = 0; i < count; i++) {
NSLog(#" %s = %#", ivar_getName(ivars[i]), object_getIvar(obj, ivars[i]));
}
// Examine Derived ivars
NSLog(#"Derived ivars:");
ivars = class_copyIvarList([Derived class], &count);
for (unsigned int i = 0; i < count; i++) {
NSLog(#" %s = %#", ivar_getName(ivars[i]), object_getIvar(obj, ivars[i]));
}
}
return 0;
}
Output:
getter returns I'm derived
Base ivars:
_foo = I'm base
Derived ivars:
_foo = I'm derived

Why does the object in this Objective C code not set?

I have the below code which simply read a bunch of cards and inputs their names into a Mutable Array if they are not present beforehand.
int main(int argc, const char * argv[])
{
#autoreleasepool {
NSMutableArray *allCards = [[NSMutableArray alloc] init];
char cardAvailable = '\0';
do {
Card *newCard = [[Card alloc] init];
NSLog(#"What is the Card Name ?\n");
char cName[20];
scanf("%s",cName);
NSString *nName = [NSString stringWithCString:cName encoding:1];
[newCard setName:nName];
if([newCard wasMatch:allCards]) {
NSLog(#"Card Already Present");
} else {
NSLog(#" NEW CARD NAME %# %# %s",[newCard getName],newCard.name, cName);
[newCard addGlobal:newCard toArray:allCards];
}
NSLog(#"Is there another Card to Input?");
scanf("%c",&cardAvailable);
} while(cardAvailable != 'N' || cardAvailable != 'n');
NSLog(#":::: Card Names Are ::::");
for(Card *card in allCards)
{
NSLog(#"%#",card.name);
}
}
return 0;
}
However, first - The name is simply NOT SET. I don't know why this is happening. Today was my first day ever with Objective C, so please pardon me if this is too simple.
The Card class files are -
#import <Foundation/Foundation.h>
#interface Card : NSObject
#property(nonatomic) BOOL chosen;
#property (nonatomic, getter = getName) NSString *name;
-(BOOL)wasMatch:(NSMutableArray*) allCards;
-(void)addGlobal:(Card*) aCardName toArray:(NSMutableArray*) allCards;
-(void)setName:(NSString *)name;
-(void)setChosen:(BOOL)chosen;
#end
I get the error here - in the add global line.
#import "Card.h"
#implementation Card
#synthesize chosen = _chosen;
-(BOOL)chosen
{
return _chosen;
}
-(void)setChosen:(BOOL)chosen
{
_chosen = chosen;
}
#synthesize name = _name;
-(NSString*)getName
{
return _name;
}
-(void)setName:(NSString*)name
{
name = _name;
}
-(BOOL)wasMatch:(NSMutableArray *)allCards
{
for(Card *card in allCards)
{
if([self.name isEqualToString:card.name])
{
return true;
}
}
return false;
}
-(void)addGlobal:(Card *)aCardName toArray:(NSMutableArray *)allCards
{ NSLog(#" THE NS STRING %#",aCardName.name);
[allCards addObject:aCardName.name];
}
#end
Your setter is wrong.
-(void)setName:(NSString*)name
{
name = _name;
}
You assign the current instance variable (_name) to the parameter.
This should be the other way around.
-(void)setName:(NSString*)name
{
_name = name;
}
But you don't need this at all. There are various problems with your code.
Objective-C does not use getFoo for ordinary getters.
#property (nonatomic, getter = getName) NSString *name; should be
#property (copy, nonatomic) NSString *name;
And unless you are writing code in a ancient version of Objective-C (which you shouldn't) you don't need explicit getters and setters. In recent version you don't even have to explicitly synthesize.
In newer version of Objective-C your Card class should look more like this:
#interface Card : NSObject
#property (assign, nonatomic) BOOL chosen;
#property (copy, nonatomic) NSString *name;
-(BOOL)wasMatch:(NSMutableArray*) allCards;
-(void)addGlobal:(Card*) aCardName toArray:(NSMutableArray*) allCards;
#end
#import "Card.h"
#implementation Card
-(BOOL)wasMatch:(NSMutableArray *)allCards
{
for(Card *card in allCards)
{
if([self.name isEqualToString:card.name])
{
return YES;
}
}
return NO;
}
-(void)addGlobal:(Card *)aCardName toArray:(NSMutableArray *)allCards
{ NSLog(#" THE NS STRING %#",aCardName.name);
[allCards addObject:aCardName.name];
}
#end
Way less code. You might want to look for a more up to date learning resource.
The rest of your code looks questionable as well. I honestly don't see the point in addGlobal:toArray:. But I don't want to make this answer longer than necessary. ;-)
Also, for the love of your future self, don't use 1 in NSString *nName = [NSString stringWithCString:cName encoding:1]; use the constant. In your case NSASCIIStringEncoding. But because it's no longer 1980 you most likely want to use NSUTF8StringEncoding instead of ASCII.
As I said, please get more recent and decent learning resources.
In the -setName: property accessor method, you assign the the _name instance variable value to the name parameter. It should be swapped like this:
-(void)setName:(NSString*)name
{
_name = name;
}
To learn Objective-C i reccomment the most recent Stanford lectures by Paul Hegarty. CS193p the class is called. You can find all materials, and excellent videos on iTunes U. Other then Apple resource, there is no better then this.

Objective-C and NSCoding primative data type just like the old C code

I have some old C code that looks like this:
#include <stdio.h>
#include <strings.h>
main()
{
FILE *output;
struct socket_cpacket
{
char type; /* CP_SOCKET */
char version;
char udp_version; /* was pad2 */
char pad3;
unsigned socket;
};
struct socket_cpacket sockPack;
bzero(&sockPack,sizeof(sockPack));
sockPack.type = 27;
sockPack.version = 4;
sockPack.udp_version = 10;
sockPack.pad3 = 0;
sockPack.socket = 0;
output = fopen("/tmp/sockPack.bin", "wb");
fwrite(&sockPack, sizeof(sockPack), 1, output);
}
I'd like to duplicate this functionality in obj-c and I started down the path of using NSCoding protocol.
CP_Socket.h
#import <Foundation/Foundation.h>
#interface CP_Socket : NSObject <NSCoding>
{
#private
char type;
char version;
char udp_version;
char pad3;
unsigned int socket;
}
#property (readonly) char type;
#property (readonly) char version;
#property (readonly) char udp_version;
#property (readonly) char pad3;
#property unsigned int socket;
typedef enum {
mTYPE = 27,
mVERSION = 4,
mUDP_VERSION = 10,
} cpSocketEnum;
#end
And CP_Socket.m
#import "CP_Socket.h"
#implementation CP_Socket
#pragma mark ======== properties =========
#synthesize type;
#synthesize version;
#synthesize udp_version;
#synthesize pad3;
#synthesize socket;
- (id)init {
NSLog(#"init");
if( !( self = [super init] ) )
return nil;
type = mTYPE;
version = mVERSION;
udp_version = mUDP_VERSION;
pad3 = 0;
socket = 0;
return self;
}
#pragma mark ======== Archiving and unarchiving methods =========
//
// Archives and Serializations Programming Guide for Cocoa
// http://bit.ly/PAaRsV
//
// NSCoding Protocol Reference
// http://bit.ly/PAb1Rd
//
- (void)encodeWithCoder:(NSCoder *)coder
{
NSLog(#"encodeWithCoder");
[coder encodeBytes:[self type] length:1 forKey:#"type"];
//[coder encodeBytes:[self version] length:1 forKey:#"version"];
//[coder encodeBytes:[self udp_version] length:1 forKey:#"udp_version"];
//[coder encodeBytes:[self pad3] length:1 forKey:#"pad3"];
//[coder encodeInt:[self socket] forKey:#"socket"];
}
- (id)initWithCoder:(NSCoder *)coder
{
NSLog(#"initWithCoder");
}
#end
First problem, [coder encodeBytes:[self type] length:1 forKey:#"type"]; throws a warning. Incompatible integer to pointer conversion sending 'char' to parameter of type 'const uint8_t *.
How do I encode a char?
I tried [coder encodeInt:[self type] forKey:#"type"]; but char != int.
Going with the code to further understand how it work; the file the obj-c code generates is 280 bytes and looking inside the file I see what looks like name-mangled class identifiers.
I've tried NSKeyedArchiver and NSArchiver with the same results.
I don't know where to go from here. The C-code generates a 8 byte file. I'd like the obj-c code to do the same while using some of the OO stuff like the NSCoding protocol.
I feel like I'm going to have to extend the NSCoder object to make this work.
Any help would be appreciated.
The first argument to encodeBytes:length:forKey: is expected to be a pointer to the buffer you want to encode, so take the address of your ivar:
[coder encodeBytes:&type length:1 forKey:#"type"];
Or make a temp variable, put the result of the property access in that, and take its address.
Using encodeInt:forKey: should work too (with a cast), but it'll inflate the size of your data file.
If you really wanted to, you could certainly extend NSCoder with a category:
#implementation NSCoder (BTEncodeChar)
- (void)BTencodeChar: (char)c forKey: (NSString *)key
{
[self encodeBytes:&c length:1 forKey:key];
}
#end
I dont know much about NSCoding, but obj C interops with C just fine. Take your existing code put it in a function with params and call it.

Objective C arc -- keeping a reference to a Class

I want to have an ivar of type Class, and to keep the pointer around after it is passed in. But no matter what I do, arc will not let me do that. For instance, if I declare
#property (nonatomic, strong) Class myClass;
the compiler decides that myClass should be unsafe_unretained. And if I try this:
-(id) initWithClass: (Class) passedInClass {
if ((self = [super init])) {
self.myClass = passedInClass;
}
return self;
}
what happens is that even if the class is non-nil in the calling code, it is nil within the init method.
Short of turning off arc, is there any way to get around this?
EDIT: This question is just wrong. It does work. See the accepted answer.
Works as advertised with Xcode 4.3.2 targeting 10.7 and 5.1:
#interface MOYNObject : NSObject
#property (nonatomic, strong, readwrite) Class myClass;
#end
#implementation MOYNObject
#synthesize myClass;
- (id)initWithClass:(id)pClass
{
self = [super init];
if (self != nil)
self.myClass = pClass;
assert(self.myClass);
CFShow((__bridge const void*)self.myClass);
return self;
}
#end
int main(int argc, const char* argv[]) {
#autoreleasepool {
MOYNObject * o = [[MOYNObject alloc] initWithClass:[NSString class]];
// ...
}
return 0;
}
Are you ahead of or behind 4.3.2?

Incomplete Implementation Example Help!

I am working on an example from a book that I got and it doesnt seem to be working I am getting the warning Incomplete implementation. When I run the program I get an error singal "EXC_BAD_ACCESS". The warning is in the .m file at the line return [NSString stringWithFormat:#"Name:... Does anyone know what I am doing wrong?
my .m file
#import "RadioStation.h"
#implementation RadioStation
+ (double)minAMFrequency {
return 520.0;
}
+ (double)maxAMFrequency {
return 1610.0;
}
+ (double)minFMFrequency {
return 88.3;
}
+ (double)maxFMFrequency {
return 107.9;
}
- (id)initWithName:(NSString *)newName atFrequency:(double)newFreq atBand:(char)newBand {
self = [super init];
if (self != nil) {
name = [newName retain];
frequency = newFreq;
band = newBand;
}
return self;
}
- (NSString *)description {
return [NSString stringWithFormat:#"Name: %#, Frequency: %.1f Band: %#", name, frequency, band];
}
- (void)dealloc {
[name release];
[super dealloc];
}
#end
My .h file
#import <Cocoa/Cocoa.h>
#interface RadioStation : NSObject {
NSString *name;
double frequency;
char band;
}
+ (double)minAMFrequency;
+ (double)maxAMFrequency;
+ (double)minFMFrequency;
+ (double)maxFMFrequency;
-(id)initWithName:(NSString*)name
atFrequency:(double)freq
atBand:(char)ban;
-(NSString *)name;
-(void)setName:(NSString *)newName;
-(double)frequency;
-(void)setFrequency:(double)newFrequency;
-(char)band;
-(void)setBand:(char)newBand;
#end
radiosimulation.m file:
int main (int argc, const char * argv[]) {
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
// insert code here...
NSMutableDictionary* stations = [[NSMutableDictionary alloc] init];
RadioStation* newStation;
newStation = [[RadioStation alloc] initWithName:#"Star 94"
atFrequency:94.1
atBand:'F'];
[stations setObject:newStation forKey:#"WSTR"];
[newStation release];
NSLog(#"%#", [stations objectForKey:#"WSTR"]);
newStation = [[RadioStation alloc] initWithName:#"Rocky 99"
atFrequency:94.1
atBand:'F'];
[stations setObject:newStation forKey:#"WKFR"];
[newStation release];
NSLog(#"%#", [stations objectForKey:#"WKFR"]);
[stations release];
[pool drain];
return 0;
You are declaring the following property accessor/mutators (getter/setters) but are not implementing them in your .m file.
-(NSString *)name;
-(void)setName:(NSString *)newName;
-(double)frequency;
-(void)setFrequency:(double)newFrequency;
-(char)band;
-(void)setBand:(char)newBand;
You need to implement all 6 of these methods in the .m file if you want to remove the warning about incomplete implementation.
You are effectively saying in the .h file that this is what your object is going to do, then not doing it in the .m. It won't generate an error, as objective-c messaging means that the message will be handed up to NSObject to deal with, which will also not have any matching implementation, and the messages will just be silently ignored. I don't like the way that this is only shown as a warning - but there you go.
That said, I wouldn't create the properties like this (there are neater ways of doing this in objective-c using #property), I would remove those method declarations in the .h and replace them with:
#property (nonatomic, retain) NSString *name;
#property (nonatomic, assign) double frequency;
#property (nonatomic, assign) char band;
These property declarations go in the same place as method declarations.
and then add the following to the .m file:
#synthesize name;
#synthesize frequency;
#synthesize band;
This will avoid having to write all that boilerplate accessor/mutator code that you are currently missing. Again, these go in the same region of the code as method implementations. Effectively the compiler is going to create name and setName methods automatically.
This code is untested - but should point you in the right direction for tidying up the incomplete implementation. It may fix your access error too - but that may require more detailed look at a stack trace.
Another point I'm not sure the code as written even needs to use get/set methods or properties. You might try removing the method declarations from the .h and see if it works. It seems that all the accesses to name, frequency and band are all from within the object.