Objective-C - Position Object with CGPoint from another Method - objective-c

Hello i have got a question. I hope anybody could help me. I do not understand… I have a method returnPointFromArray where i have an array with values (e.g. 50.0, 100.0). Than i want to random it and then i want to use the CGPoint p in the Method drawObjectWithPoint to position my Object (object from another class) with the random value.
But the drawObjectWithPoint Method says always that the CGPoint p ist 0.0, 0,0 or he says "Use of undeclared identifier p or "instance variable hides…" .
I tried the same principle to test with int and this works.
I don´t know what i´m doing wrong.
It would be great if anybody could help me and explain what i´m doing wrong.
Thanks a lot.
.h
-(void)returnPointFromArray;
-(void)drawObjectWithPoint;
.m
-(void)returnPointFromArray
{
NSArray *points = [];
//Random for points
NSUInteger *randomIndex = arc4random() % [points count];
NSValue *val = [points objectAtIndex:randomIndex];
CGPoint p = [val CGPointValue];
}
-(void)drawObjectWithPoint
{
Object *myObject [[Object alloc]init];
CGPoint pNew = p;
myObject.position =
[self addChild:myObject];
}

You can do this: Edited: (This is how yo declare in .h file)
in .h file
#import <UIKit/UIKit.h>
#interface MyClass : UIViewController {
CGPoint p;
}
-(void)returnPointFromArray;
-(void)drawObjectWithPoint;
#end
in .m file
-(void)returnPointFromArray {
NSArray *points = [];
//Random for points
NSUInteger *randomIndex = arc4random() % [points count];
NSValue *val = [points objectAtIndex:randomIndex];
p = [val CGPointValue]; // change here
}
-(void)drawObjectWithPoint {
Object *myObject [[Object alloc]init];
CGPoint pNew = p;
myObject.position =
[self addChild:myObject];
}

assign value directly by method call
-(void)drawObjectWithPoint
{
Object *myObject [[Object alloc]init];
myObject.position = [self returnPointFromArray];
[self addChild:myObject];
}
-(CGPoint)returnPointFromArray {
NSArray *points = [];
//Random for points
NSUInteger *randomIndex = arc4random() % [points count];
NSValue *val = [points objectAtIndex:randomIndex];
return [val CGPointValue];
}

Just declared CGPoint p; in .h file. You declared it as locally(returnPointFromArray function) means its scope is local for that function only. check here
for reference.

Your returnPointFromArray method returns void - just modify it -
-(CGPoint)returnPointFromArray
{
// your code
return p;
}
Then where you want to use p, just write
CGPoint pNew = [self returnPointFromArray];
obviously you'll have to add code which actually uses this value - your code doesn't do this at all -
myObject.position = pNew;

Related

Objective C - Get argument types of a method?

At runtime I need to be able to get the argument types of a method. The following is what gets printed:
I have read on other threads that at run-time time objective c treats all objects passed to a method as arguments as id. If this approach doesn't work any other suggestions on a way to read argument types?
Log
2014-02-07 15:47:08.962 OCInjection[55727:70b] #
2014-02-07 15:47:08.964 OCInjection[55727:70b] :
Code
Class class = NSClassFromString(injectionBinding);
unsigned int methodCount;
Method *methodList = class_copyMethodList(class, &methodCount);
for (int i = 0; i < methodCount; i++)
{
Method method = methodList[i];
SEL selector = method_getName(method);
NSMethodSignature *signature = [class instanceMethodSignatureForSelector:selector];
NSUInteger numberOfArguments = [signature numberOfArguments];
for (int i=0 ; i<numberOfArguments ; i++)
{
NSString *type = [NSString stringWithUTF8String:[signature getArgumentTypeAtIndex:i]];
NSLog(type);
}
}
According to
-getArgumentTypeAtIndex:
and
Decode Class from #encoded type string
I think there is no method to get the "real" argument type.
Doesn't seem like it's possible to do this. I ended up using a proxy object to send the message to, and capture it. Probably not the ideal way, but I haven't found a better solution.
#interface DIContructorInjectorProxy()
#property (nonatomic, strong) id realObject;
#end
#implementation DIContructorInjectorProxy
#define Inject(x) [DIContructorInjectorProxy _injectMacro:x]
- (id)initWithClass:(Class)class
{
self.realObject = [[class alloc] init];
}
+ (id)_injectMacro:(id)x
{
if ([x isKindOfClass:NSClassFromString(#"Protocol")])
return NSStringFromProtocol(x);
else
return NSStringFromClass(x);
}
- (id)withConstructor
{
// Just making the method call for defining a constructor more readable by a call to this method first
return self;
}
- (void)forwardInvocation:(NSInvocation *)anInvocation
{
NSMutableString *selectorName = [NSStringFromSelector(anInvocation.selector) mutableCopy];
NSUInteger numberOfColonsInMethodName = [selectorName replaceOccurrencesOfString:#":"
withString:#":"
options:NSLiteralSearch
range:NSMakeRange(0, selectorName.length)];
[anInvocation retainArguments];
NSMutableArray *argumentsPassedToSelector = [NSMutableArray array];
for (int i=2 ; i<numberOfColonsInMethodName+2 ; i++)
{
NSString *argument;
[anInvocation getArgument:&argument atIndex:i];
[argumentsPassedToSelector addObject:[NSString stringWithFormat:#"%#", argument]];
}
// Store arguments somewhere
return;
}
- (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector
{
return [self.realObject methodSignatureForSelector:aSelector];
}
#end
How the user uses this to define method arguments
[self bindProtocol:#protocol(DataStorage) toClass:[InMemoryDataStorage class]];
// withConstructor returns an appropriate proxy object
// Then when the init method is called, it calls forwardInvocation,
// and from there I save all the info I need about the method and arguments
(void)[[[self bindProtocol:#protocol(GoogleClient) toClass:[GoogleClientEngine class]] withConstructor]
initWithDataStorage:Inject(#protocol(DataStorage))];

NSMutableArray not working at all

I'm trying to add sprites to a NSMutableArray but it's not adding them. This is what I have:
NSMutableArray *tail;
CCSprite *block;
int j;
-(void)handleTail:(CCSprite*)pos{
CGPoint point= pos.position;
block = [CCSprite spriteWithFile:#"Icon-Small-50.png"];
//Adding the tail blocks
block.scale = .8;
block.color = ccGREEN;
block.position = point;
NSLog(#"Block Pos (%f,%f)",block.position.x,block.position.y);
//CGPoint playerPos = piece.position;
originalPos = point;
if ([tail count] < maxLength) {
[tileMap addChild:block];
[tail addObject:block];
NSLog(#"Tail length:%i",tail.count);
j+=1;
}
if (j == 3) {
NSLog(#"J called");
[tail removeObjectAtIndex:0];
}
}
I don't understand why this isn't working?
You have not alloc+inited the tail.
In awakeFromNib or init or viewDidLoad ( which ever is applicable for your class) use
tail=[[NSMutableArray alloc] init];
Suggestion NOTE : Try to follow naming convention.
As tail is an array (plural) you should use tails.
You forget to alloc init NSMuttableArray
tail = [[NSMuttableArray alloc]init];
without alloc and init your array you cannot add object to it
when you try to access its member it returns nil
try NSLog (#"%#",tail); it returns
You need to instantiate your NSMutableArray.
tail = [NSMutableArray array];
You need to allocate and initialize the array.
Something like:
tail = [NSMutableArray array];

CGRectIntersection requires scalar type?

I am trying to check collisions of objects from a NSMutableArray against another object (using a CGRect) but it keeps saying the method requires a scalar type?!
Here is the method throwing the error:
-(void) checkSquareToCircleCollisions{
NSMutableArray *array = [squares getSquares];
for(int i = 0; i < [squares getCount]; i++){
Square *s = [array objectAtIndex: i];
CGRect rect1 = [player getRect];
CGRect rect2 = [s getRect];
//if(CGRectIntersection(rect1, rect2)){
//[player setAlive: NO];
// }
}
}
Use CGRectIntersectsRect, not CGRectIntersection.
CGRectIntersectsRect returns a boolean: YES if the rectangles intersect. CGRectIntersection returns the CGRect that is the overlap (if any) between the two rectangles.
if (CGRectIntersectsRect(playerRect, squareRect)) {
player.alive = NO;
}

Something is wrong with singleton...unable adding a child because it is nil

I use a singleton the first time and I don't really know how to implement it...
Ok I need to explain some things:
In Hexagon.h (which inherits from CCNode) I want to create multiple sprites (here referred to as "hexagons"). However, they are not added to the scene yet. They are being added in the HelloWorldLayer.m class by calling Hexagon *nHex = [[Hexagon alloc]init]; . Is that correct ? Is it then iterating through the for loop and creating all hexagons or only one ?
Well anyways, I have a singleton class which has to handle all the public game state information but retrieving is not possible yet.For instance I cannot retrieve the value of existingHexagons, because it returns (null) objects. Either I set the objects wrongly or I am falsely retrieving data from the singleton. Actually, I would even appreciate an answer for one of these questions. Please help me. If something is not clear, please add a comment and I'll try to clarify it.
What I have right now is the following:
GameStateSingleton.h
#import <Foundation/Foundation.h>
#interface GameStateSingleton : NSObject{
NSMutableDictionary *existingHexagons;
}
+(GameStateSingleton*)sharedMySingleton;
-(NSMutableDictionary*)getExistingHexagons;
#property (nonatomic,retain) NSMutableDictionary *existingHexagons;
#end
GameStateSingleton.m
#import "GameStateSingleton.h"
#implementation GameStateSingleton
#synthesize existingHexagons;
static GameStateSingleton* _sharedMySingleton = nil;
+(GameStateSingleton*)sharedMySingleton
{
#synchronized([GameStateSingleton class])
{
if (!_sharedMySingleton)
[[self alloc] init];
return _sharedMySingleton;
}
return nil;
}
+(id)alloc
{
#synchronized([GameStateSingleton class])
{
NSAssert(_sharedMySingleton == nil, #"Attempted to allocate a second instance of a singleton.");
_sharedMySingleton = [super alloc];
return _sharedMySingleton;
}
return nil;
}
-(id)init {
self = [super init];
if (self != nil) {
}
return self;
}
#end
Hexagon.m
-(CCSprite *)init{
if( (self=[super init])) {
NSString *mainPath = [[NSBundle mainBundle] bundlePath];
NSString *levelConfigPlistLocation = [mainPath stringByAppendingPathComponent:#"levelconfig.plist"];
NSDictionary *levelConfig = [[NSDictionary alloc] initWithContentsOfFile:levelConfigPlistLocation];
NSString *currentLevelAsString = [NSString stringWithFormat:#"level%d", 1];
NSArray *hexPositions;
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad){
hexPositions = [[levelConfig valueForKey:currentLevelAsString] valueForKey:#"hexpositionIpad"];
}
else{
hexPositions = [[levelConfig valueForKey:currentLevelAsString] valueForKey:#"hexpositionIphone"];
}
NSString *whichType = [NSString stringWithFormat:#"glass"];
CGSize screenSize = [CCDirector sharedDirector].winSize;
if ([whichType isEqualToString:#"stone"]){
hexagon = [CCSprite spriteWithFile:#"octagonstone.png"];
}else if([whichType isEqualToString: #"glass"]){
hexagon = [CCSprite spriteWithFile:#"octagoncolored1.png"];
}else if([whichType isEqualToString: #"metal"]){
hexagon = [CCSprite spriteWithFile:#"octagonmetal.png"];
}
NSMutableDictionary *eHexagons =[[GameStateSingleton sharedMySingleton] getExistingHexagons];
for (int i=0;i < [hexPositions count];i++){
CGPoint location = CGPointFromString([hexPositions objectAtIndex:i]);
CGPoint nLocation= ccp(screenSize.width/2 + 68 * location.x,screenSize.height/2 + 39 * location.y);
NSString *aKey = [NSString stringWithFormat:#"hexagon%d",i];
hexagon =[CCSprite spriteWithFile:#"octagoncolored1.png"];
hexagon.position = nLocation;
[eHexagons setObject:hexagon forKey:aKey];
[self addChild:[eHexagons valueForKey:aKey] z:3];
[[GameStateSingleton sharedMySingleton]setExistingHexagons:eHexagons];
}
NSLog(#"these are the existinghexagons %#", existingHexagons);
//This returns a dictionary with one (null) object
}
return hexagon;
}
HelloWorldLayer.m -> -(id)init method
Hexagon *nHex = [[Hexagon alloc]init];
First of all, it returns null because the existingHexagons array has never been initialized in the first place. Go to the init function of your singleton and add:
existingHexagons = [[NSMutableArray alloc]init];
As for your For Loop question, I did not get it. I recommend making one StackOverflow question per query instead of putting two in one.

iOS - Storing groups of UILabels into a NSMutableArray

I'm creating UILabels dynamically in a for each loop. Every loop that is run creates 1-4 UILabels.
What I want is that I put these UILabels into my NSMutableArray and being able later to easy retrieve the data.
My original thought was to put these UILabels into a NSDictionary and use [dictGroupLabels setValue:uiLabel1 forKey:#"uiLabel1"] and then [dictGroupLabels setValue:uiLabel2 forKey:#"uiLabel2"] and so on. And then put this dictionary into my NSMutableArray for each loop. Later on I could access the values like UILabel *label = [[myArray objectAtIndex:0] valueForKey:#"uiLabel1"] BUT that unfortunately doesn't work since UILabels don't conform to the NSCopying protocol.
So with this in mind how would you solve this?
this question provided more information on what you are trying to accomplish. Since you know for a fact, the possible set of labels you are trying to create in each case, I would highly recommend using mutable dictionaries instead of arrays.
To illustrate, given the following hypothetical class definition:
#interface MyClass: NSObject {
NSMutableDictionary * _labelDict;
}
#property (nonatomic, retain) NSMutableDictionary * labelDict;
- ( void )methodA;
- ( void )methodB;
- (NSMutableDictionary *) labelsForRunLoop: (NSUInteger) loopIdx;
#end
You would have the following, hypothetical, class implementation:
#implementation MyClass
#synthesize labelDict = _labelDict;
- ( id ) init {
if( ( self = [ super init ] ) ) {
[self setLabelDict: [NSMutableDictionary dictionaryWithCapacity: 8]];
}
}
- ( void ) dealloc {
[ self.labelDict release ];
[ super dealloc ];
}
- ( void ) methodA {
for(NSUInteger i = 0; i < some index; i++) {
[self.labelDict setObject: [self labelsForRunLoop: i] forKey: [NSString stringWithFormat: #"%d", i]];
}
}
- ( void ) methodB {
// Locate the label you need to work with. Example based on this crude pseudo code
NSMutableDictionary * subDict = (NSMutableDictionary *) [self.labelDict objectForKey: #"0"];
UILabel * theLabel = (UILabel * ) [subDict objectForKey: #"UILabel.Z"];
theLabel.text = #"Label 1";
}
- (NSMutableDictionary *) labelsForRunLoop: (NSUInteger) loopIdx {
NSMutableDictionary * dictionary = [NSMutableDictionary dictionaryWithCapacity: 4] ;
[dictionary setObject: create-w-label forKey: #"UILabel.W"];
[dictionary setObject: create-x-label forKey: #"UILabel.X"];
[dictionary setObject: create-y-label forKey: #"UILabel.Y"];
[dictionary setObject: create-z-label forKey: #"UILabel.Z"];
return [dictionary retain];
}
#end
This is basically pseudo code and will not successfully compile. However it will serve as a good starting point. You probably want to store each label dictionary under some key that makes sense, instead of just using the loop's index. Hope this helps.
They don’t need to adhere to NSCopying to be added to an array. It sounds like you just need to do something like this:
NSMutableArray *mainArray = [NSMutableArray array];
for(int i = 0; i < 5; i++)
{
NSMutableArray *subArray = [[NSMutableArray alloc] initWithCapacity:5];
for(int j = 0; j < 4; j++)
{
UILabel *label = [[UILabel alloc] init];
// etc.
[subArray addObject:label];
[label release];
}
[mainArray addObject:subArray];
[subArray release];
}
// then, to get one of the labels:
UILabel *someSpecificLabel = [[mainArray objectAtIndex:2] objectAtIndex:1];