Making pointer from integer in Objective C - objective-c

After programming with C# and Java for many years I finally decided to learn Objective-C in order to start programming iOS Devices as well as Mac OS X, and I have to admit it is very different then most modern c-based programming languages. I am getting the following warning in my code:
warning: passing argument 1 of 'SetAge' makes pointer from integer without a cast
Here is my code:
Dog.h
#import <Cocoa/Cocoa.h>
#interface Dog : NSObject {
int ciAge;
NSString * csName;
}
- (void) Bark;
- (void) SetAge: (int *) liAge;
- (void) SetName: (NSString *) lsName;
#end
Dog.m
#import "Dog.h"
#implementation Dog
- (void) Bark
{
NSLog(#"The dog %# barks with age %d", csName, ciAge);
}
- (void) SetAge: (int *) liAge {
ciAge = (int)liAge;
}
- (void) SetName: (NSString *) lsName {
csName = lsName;
}
#end
HelloWorld.m
#import <Foundation/Foundation.h>
#import "Dog.h"
int main (int argc, const char * argv[]) {
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
int liTemp = 75;
NSString * lsCity = #"Chicago";
NSDate * loDate = [NSDate date];
// insert code here...
NSLog(#"The temperature is %d currently in %#, on %#", liTemp, lsCity, loDate);
int liAge = 10;
// Call Dog class
Dog * Dog1 = [Dog new];
[Dog1 SetAge:(int)liAge]; // The Warning happens here
[Dog1 SetName:#"Fido"];
[Dog1 Bark];
[pool drain];
return 0;
}
My Questions Are:
How do I get rid of the warning above?
Instead of creating methods in the Dog Class for setting Age and Name, how could I have make Age and Name public class level variables that I could directly assign to?
Any help would be much appreciated!
Thanks,
Pete

Don't declare an int as a pointer. Change your code from:
- (void) SetAge: (int *) liAge
to
- (void) SetAge: (int) liAge
and
- (void) SetAge: (int *) liAge {
ciAge = (int)liAge;
}
to
- (void) SetAge: (int) liAge {
ciAge = liAge;
}
Consider making age and name a property. Change:
- (void) SetAge: (int *) liAge;
- (void) SetName: (NSString *) lsName;
to
#property (nonatomic, readwrite) NSInteger age; //Don't declare as pointer
#property (nonatomic, retain) NSString *name; //DO declare as pointer
Also, don't forget to synthesize them in your implementation file:
#synthesize age, name;

int is a C primitive scalar type so you don't need pointers. Don't use *.
Warning here
int * represents a pointer variable, a thing you're not used to see in C# or in Java.
int *p is a variable that will point to a memory address. To put data at this address you have to dereference the variable p before using it ex:*p = 3.
Objective-C is based on the C language and this is a C language problem. You should (must ?) read about C and pointers if you want to code in Objective-C.
And read also how Objective-C simplifies your life with pointers to objects particularly the fact that you don't have do explicitly dereference them to use them.

Related

How to input new instance of Object with multiple arguments into NSMutablearray

I'm very new to Obj-C, been learning more Java and C++ lately.
I have two objects Friend and Foe which inherit the Character Object. Friend and Foe have slightly different attributes. I want all Friends and Foes to be in the same NSMutablearray. Can't figure out how to put these into the array. I get an error saying too many arguments, expected 1 have 4. For Foe its the same, but expected 1, have 5.
The Character Object
#import <foundation/foundation.h>
#interface Character : NSObject
#property NSString *name;
#property NSInteger strength;
#property NSInteger iff;
- (void) printDetails;
#end
#import <Foundation/Foundation.h>
#import "game_character.h"
#implementation Character
- (void) printDetails
{
NSLog (#"%# has strength %ld\n", self.name, self.strength);
}
#end
The Friend Object (The Foe object is similar with without intelligence and spell but has an alternate NSInteger attribute.
#interface Friend : Character
#property NSInteger intelligence;
#property NSString *spell;
- (void)printDetails;
#end
#import <Foundation/Foundation.h>
#import "game_character.h"
#import "friend.h"
#implementation Friend
-(void)printDetails
{
NSLog (#"%# has strength %ld\n", self.name, self.strength);
NSLog (#" ,Intelligence %ld, Spell %#\n", self.intelligence, self.spell);
}
#end
The Friend Input Method (I will have a similar method to input a Foe)
void input_friend()
{
#autoreleasepool
{
char str[30] = {0};
NSInteger strength;
NSInteger iff=1;
NSInteger intelligence;
NSLog(#"Enter character name\n");
scanf("%s", str);
NSString *name = [NSString stringWithUTF8String:str];
NSLog(#"Enter character strength\n");
scanf("%ld", &strength);
NSLog(#"Enter character intelligence");
scanf("%ld", &intelligence);
NSLog(#"Enter character spell\n");
scanf("%s", str);
NSString *spell = [NSString stringWithUTF8String:str];
My Error is here when I try to add the object to the array.
[characters addObject:name, strength, iff, intelligence, spell];
}
}
The Main so far. I intend to add a menu with option to add Friend or Foe to the array.
int main(int argc, const char * argv[])
{
#autoreleasepool
{
characters = [[NSMutableArray alloc] init];
void input_friend();
void input_foe();
}
return 0;
}
In this line, you are passing multiple arguments to add to your list of characters. However, this doesn't work since you want to add objects, which is why you got your error:
[characters addObject:name, strength, iff, intelligence, spell];
So you need to initialize a new Friend or Foe first, set its properties, and then add it to your array.
Friend *newFriend = [[Friend alloc] init];
newFriend.name = name;
newFriend.strength = strength;
// etc.
[characters addObject: newFriend];

How to store the returning value of an NSArray.objectAtIndex to an NSString variable

I'm new to programming using objective c, I've only used java in the past. I'm trying to code a quick hangman game and I've come across errors that for the life of me I can't find a solution to.
So in this method, I'm trying to pick a random word from an NSArray and setting it equal to the instance variable word.
#import <Foundation/Foundation.h>
#interface Hangman : NSObject
{
NSString *word;
}
-(void) randomWord;
-(void) guessLettter: (char) g;
-(void) guessWord: (NSString*) guess;
-(void) displayLetters: (char) x;
#end
#import "Hangman.h"
#implementation Hangman
-(void) randomWord;
{
NSArray *array = [NSArray arrayWithObjects:#"Mercedes", #"Banana", #"Porsche",
#"Dinosaur", #"Blue", #"owls", #"chicken", #"Lollipop", #"Table",
#"Hello", #"Corn", #"Uniform",nil];
int num = 11;
NSUInteger r = arc4random_uniform(11);
word = *[array objectAtIndex:(NSUInteger)r];
}
But trying to set word equal to whatever object is returned is giving me an error about assigning NSString Strong to type 'id' and I don't know what 'id' is.
You have a simple typo. This line:
word = *[array objectAtIndex:(NSUInteger)r];
should be:
word = [array objectAtIndex:r];
or even better:
word = array[r];
Side note: Don't put the ivar in the .h file. Put it in the .m file. The public doesn't need to know about private details.
.h:
#interface Hangman : NSObject
-(void) randomWord;
-(void) guessLettter: (char) g;
-(void) guessWord: (NSString*) guess;
-(void) displayLetters: (char) x;
#end
.m:
#import "Hangman.h"
#implementation Hangman {
NSString *word;
}
-(void)randomWord
{
NSArray *array = #[#"Mercedes", #"Banana", #"Porsche",
#"Dinosaur", #"Blue", #"owls", #"chicken", #"Lollipop", #"Table",
#"Hello", #"Corn", #"Uniform"];
NSUInteger r = arc4random_uniform(11);
word = array[r];
}
Also get rid of the semicolon after the name of the randomWord method in the .m file.
And notice the use of modern array syntax.

accessing inherited array in Objective C

I'm currently working on a project that's split in two classes, the class 'Array' and the class 'PPCalcVals'. Because other classes, that will be added, will also have to have access the array, I thought it would be the best to write the array class, containing an NSMutableArray and Subclass all the others (beginning with the PPCalcVals class.
So the 'PPCalcVals' class needs to access the elements of the array in the superclass 'Array'.
(Please correct me if this is the wrong approach).
As mentioned the whole program is written and well working in C but to create a GUI and eventually an OSX or IOS application I started to learn OOProgramming with Objecitve C.
Anyways, when I reference the objects in the array of the superclass the only value that gets printed is "null" which is not really what I want.
Here is the code:
main routine:
#import <Foundation/Foundation.h>
#import "Array.h"
#import "PPCalcVals.h"
int main(int argc, const char * argv[])
{
#autoreleasepool
{
Array *prices = [[Array alloc]initWithName:#0];
PPCalcVals *myVals = [[PPCalcVals alloc]init];
[prices addValue:#12];
[prices addValue:#13];
[prices addValue:#14];
[prices addValue:#15];
[prices addValue:#15];
[prices print];
[myVals print];
}
return 0;
}
array.h file:
#import <Foundation/Foundation.h>
#interface Array : NSObject
{
NSMutableArray *prices;
}
-(id) initWithName: (NSNumber *) values;
-(void) addValue: (NSNumber *) value;
-(void) print;
-(NSMutableArray *) prices;
#end
array.m
#import "Array.h"
#implementation Array
-(id) initWithName:(NSNumber *)values
{
self = [super init];
if(self)
{
prices = [NSMutableArray array];
}
return self;
}
-(void) addValue: (NSNumber *) value
{
[prices addObject:value];
}
-(void) print
{
NSLog(#"%#",prices);
}
-(NSMutableArray *)prices
{
return prices;
}
#end
PPCalcVals.h:
#import "Array.h"
#interface PPCalcVals : Array
#property id high,low,open,close;
-(void) setHigh:(NSMutableArray *)h setLow:(NSMutableArray *)l; //set high and low
-(void) setOpen:(NSMutableArray *)o setClose:(NSMutableArray *)c; //set open and close
-(void) sort; //sort array
-(void) print; //debugging tool
#end
PPCalcVals.m:
#import "PPCalcVals.h"
#implementation PPCalcVals
#synthesize high,low,open,close;
-(void) setOpen:(NSMutableArray *)o setClose:(NSMutableArray *)c
{
o = prices[0];
c = prices[2];
open = o;
close = c;
}
-(void) sort;
{
[prices sortedArrayUsingComparator:^(NSString *str1, NSString *str2) {
return [str1 compare:str2 options:NSNumericSearch];
}];
}
-(void) setHigh:(NSMutableArray *)h setLow:(NSMutableArray *)
{
h = prices[0];
l = prices[2];
high = h;
low = l;
}
-(void) print
{
NSLog(#"open: %#",open);
NSLog(#"close: %#",close);
NSLog(#"high: %#",high);
NSLog(#"low: %#",low);
}
#end
The running program outputs only:
2013-08-05 10:21:08.546 prog1[1314:303] (
12,
13,
14,
15,
15
)
open: (null)
close: (null)
high: (null)
low: (null)
I realize that this is probably a really basic question but I would appreciate your help a lot and I already thank you if you read until this point ;)
You have created two distinct, completely unrelated objects prices and myVals:
Array *prices = [[Array alloc]initWithName:#0];
PPCalcVals *myVals = [[PPCalcVals alloc]init];
What you probably meant is to create a PPCalcVals object (which inherits
all methods from the superclass Array):
PPCalcVals *prices = [[PPCalcVals alloc]init];
[prices addValue:#12]; // invokes `addValue` method from superclass "Array"
// ...
[prices print]; // invokes `print` method from "PPCalcVals"
You also have to implement init in the PPCalcVals class in such a way
that it calls the "designated initializer" initWithName in the superclass.
I have one question. Where did you make calls for the functions
-(void) setHigh:(NSMutableArray *)h setLow:(NSMutableArray *)l;
-(void) setOpen:(NSMutableArray *)o setClose:(NSMutableArray *)c;
Because all I can see is that these functions are not called. So the properties high, low, open & close are not yet assigned and thus they return Null.
Also may I know the reason why are you overriding the parameters inside above mentioned functions?
o = prices[0];
c = prices[2];
and
h = prices[0];
l = prices[2];

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.

Request for member 'pData' with BOOL value TRUE is not a structure or union-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];