I just started learning objective c. I have this little problems and questions, hope you guys could help me.
I have a ViewController, I called it: GameViewController.
This GameViewController, will call a model class, "PlayerModel"(NSObject) and this PlayerModel contains "PlayerProfile" object (its a NSObject).
The viewDidLoad in GameViewController will call and initiate model class:
playerModel = [[PlayerModel alloc] initWithInt:playerID];
Then, in my PlayerModel initWithInt method, I populate PlayerProfile data by fetching the data from online database. I manage to populate the data, but when I want to call it in gameViewController
// This is gameViewController.m
....
playerModel.playerProfile.name;
But i got this error message: "Property name not found on object of type PlayerProfile"
I NSLog the playerProfile in gameViewController, its "(null)", whereas when I NSLog in the playerModel, it has some values. How do I pass this values and make it universal, so that others classes can make use (set the value) of it?
Regarding the "Property name not found," I assume that's a compile error. You probably have failed to #import PlayerProfile.h in GameViewController.
If gameViewController is nil in GameViewController then either you have not actually initialized it, or playerModel is nil. Are you sure that you're checking it after viewDidLoad actually runs? This can be later than you think.
Related
Sorry if this is a stupid question, but I have come across a problem when setting the delegate property of an AVAudioPlayer instance.
In my program, I create 4 AVAudioPlayer instances. These are all in a class called ShapeView, derived from NSObject. I am not sure exactly what I am supposed to set the delegate to, and when I set it to 'self' it gives me the warning: "Sending 'ShapeView *const_strong to parameter of incompatible type 'id'"
I am a relatively inexperienced programmer playing around with sounds, so any help would be aprreciated.
Thanks!
Two ways to fix this:
1: conform to the protocol in the .h like so:
#interface MyExampleClass : NSObject <AVAudioPlayerDelegate> ...
Then set the delegate for each one of the players.
2: If the compiler still complains, for some reason casting the self class to id makes it go away. So:
[self.audioplayer setDelegate:(id)self];
In my app I do a lot of network loading. My data model consists of "Loader" objects that do this loading and call their delegate when finished/failed. The delegates all conform to a "LoaderDelegate" protocol.
The issue I'm having is that sometimes seemingly random objects, not the delegate, are getting the delegate messages. This of course causes a crash because of an unrecognized selector.
Only one set of crash logs tell me which one of my loaders is having the issue, the others don't have that information, just the random object that got the message.
I'm stuck at how to determine the real cause of this issue.
One set of crash logs has a loader trying to call it's delegate but reaching _UIImageViewExtendedStorage. Another has a loader is reaching __NSCFInputStream. Another __NSBlockVariable__. And yet another, CALayer.
And that's just in my latest beta from 3 days ago.
It would be one thing if it was the same object each time, but it seems almost random. Is it possible that memory is getting overritten with a new object somehow?
My delegate property for all of my loaders is an assign property, but the delegate is always alive when the loader finishes (delegates are my view controllers calling the loaders).
Please post some code, cause it is hard to troubleshoot. Remember to nil your delegate in the dealloc.
- (void) dealloc {
objectOfWhichIAmTheDelegate.delegate = nil;
}
What is more you the delegate should be an assign property not retain - but that's not a problem in your situation.
#property (assign) id<TheMightyDelegate> delegate;
Another thing you should do is to guarantee that the delegate responds to the selector you want to send to him before you fire the method.
if ([delegate respondsToSelector:#selector(yourMethod)]) {
[delegate performSelector:#selector(yourMethod)];
}
Hope this will put some light on your problem. If not please provide some code.
Turns out I was getting this error randomly all over the place, just not in this particular class and not just with delegate methods.
In my case, the problem turned out to be that I was accessing properties of various classes in multiple threads and those properties were nonatomic. Since I fixed that (removed nonatomic attribute of the properties), I haven't seen this happen anymore.
In my quest to be the grandmaster of Objective C, I keep running into it's subtleties, which I want to share with ya'll and gain an understanding why
1) I have two init methods, the one that is inherited by NSObject for my Objective C class and one is a custom method that I create off my own, let's say
initCustomMethod:(int)par1 argument2:(int)par2;
My Aim is to call initCustomMethod through the provided init method, essentially
-(id)init{
return [self initCustomMethod:1 argument2:3];
}
Naturally, maintaining the order, I have init appearing before initCustomMethod in the .m file. Xcode warns me telling me that the initCustomMethod is not found, I go ahead and shuffle the order and have init appearing after initCustomMethod is declared and there is no such warning message anymore and everything is fine.
I concur that the order is important since it's essentially derived from C, however I am not sure of this. Because, i shuffled the order of some properties and their custom methods, with the properties #synthesize being declared after the custom setter method for a given property, but there was no such error replica.
Can anyone point out the malice here?
Thanks guys!!!
Very cool guys, thanks for helping me out with this. Also, since I have a custom init method, I am initializing the super in this method and using the original init method to call the custom init method.
Anything wrong with this?
Before you reference it anywhere, you should declare initCustomMethod:argument2 in your interface, which would usually be in your header file.
For example, you would usually have a .h file that looks like:
#interface MyClass
{
//instance variables
int anInstanceVariable;
}
// properties
#property (nonatomic, assign) int aProperty;
// methods
-(id)initCustomMethod:(int)par1 argument2:(int)par2;
#end
And if you did this, the order in which you define init and initCustomMethod:argument2: won't matter. This is because the declaration tells the compiler that you are going to define the method, and what it will look like, so it isn't confused when you use it later.
It's a bad idea in Objective-C to use a function or a method before it is either declared or defined. Putting initCustomMethod:argument2: before init means that the former is already defined in the latter. But if you'd just declare it in the header, it wouldn't matter which order they went in.
Add your custom method name in your header file - the compiler just goes through things in order. If you don't have a forward declaration, the compiler won't know what to do with that call. You're going to need to put it in the header if you want other parts of your program to be able to call it anyway.
Stuck on what I figure is simple thing here. Basically I need to pass a pointer to an object as an argument into an instance method of another class. Said differently: I have a class that creates "Things" and I have an instance of another class that I want to receive the "Things."
Working with Cocos2D frameworks. The Things are a custom subclass of CCSprite, and the instance that receives them is a CCLayer.
I figure I'm misunderstanding something basic about ivars or maybe properties here. Any pointers in the right direction would be appreciated.
Here's the interface for ThingLayer, which should receive the "thing":
#interface ThingLayer: CCLayer {
CCTextureAtlas *textureAtlas;
ThingLayer *thingLayer;
NSMutableArray *ThingsArray;
}
- moveThingtoLayer:(Thing*)athing;
#end
And here's how I'm trying to message to the instance, from outside the class:
[ThingLayer moveThingtoLayer:thing];
I realize I'm asking the class here, not the instance... which is giving me "may not respond to..." errors. But this isn't working either (asking name of instance)...
[thingLayer moveThingtoLayer:thing];
Any obvious answers?
Looks like you should have
ThingLayer *thingLayer = [[ThingLayer alloc] init];
[thingLayer moveThingtoLayer: thing];
As a side thought, you most likely want to init a new thing in thingLayer so that instance owns the Thing, and release thing after calling moveThingToLayer.
I have written a UITabBarController subclass (called MainViewController) and added a few instance variables, specifically a venue of type Venue. Each tab of the MainViewController needs to access the venue variable of the MainViewController. In the first tab, a UIViewController subclass named HomeViewController, I wrote my viewDidLoad method and tried to output to NSLog with both...
NSLog(#"%#", self.parentViewController.venue.name);
and
NSLog(#"%#", self.tabBarController.venue.name);
But XCode gives the error
error: request for member 'venue' in something not a structure or union
I can access the venue property from within MainViewController just fine so have ruled out an error there. The iPhone simulator does see both self.parentViewController and self.tabBarController as an instance of MainViewController. The line...
NSLog(#"%#", self.tabBarController);
outputs...
2009-06-05 17:54:46.502 Venue[29729:20b] <MainViewController: 0x536600>
Since it's seen as a MainViewController instance, I doubt using casting would help. Is my only other option to initialize the HomeViewController with a copy of the venue or am I just doing something completely wrong with 'self.parentViewController.venue.name'? Thanks, Rob
You're doing something completely wrong. parentViewController is declared as a UIViewController. NSLoging it outputs its real type due to the wonders of polymorphism.
UIViewController doesn't have a Venue member. Your MainViewController does. Casting it is, in fact, the right answer. Make sure to import MainViewController.h as well.
#import "MainViewController.h"
[...]
NSString *name = ((MainViewController *)self.parentViewController)).venue.name;
Also make sure, of course, that venue is declared as a #property of MainViewController, and name is a #property of Venue.
int currentVCIndex = [self.navigationController.viewControllers indexOfObject:self.navigationController.topViewController];
//previous view controller
AccountViewController *account = (AccountViewController *)[self.navigationController.viewControllers objectAtIndex:currentVCIndex - 1];
account.property = object;
[account doSmthng];
Your NSLog() statement is "seeing" it as a MainViewController because that's what the object actually is. The problem you're having though, is that the compiler doesn't actually realize this because the parentViewController property is declared as a plain old UIViewController. Even though you're actually returning a subclass of it, as far as the compiler knows you're trying to call that method on a UIViewController, and it's going to complain. Casting it to a MainViewController will solve the issue.