Setting The Delegate of an AVAudioPlayer Instance - objective-c

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];

Related

Objective-C : Accessing fields in implementation

Is it possible to fields defined only in implementation but not in interface definition ?
#interface MyInterface .... #end --> dict not defined here!!!
#implementation MyInterface
...
NSDictionary *dict;
...
#end
In this case if somewhere I somehow accessed to this class, can I access to the dict or should I create a getter just like in Java ?
Edit after #Rob's answer
Thanks for the answer Rob, I wish I have the implementation of these interface and classes. Instead I am trying to bind two different libraries ( I know it is reallllly bad as architectural point of view but this is where I end up).
Basically, I am in react-native world. And we are using react-native-video as our player layer. But since AVPlayer does not support some subtitle types our head company sent us a library that needs a player instance and a view instance to draw subtitle on the view. I believe they will bind to events of the player and draw sub titles based on player states.
So react-native-video is in this github repo with the interface and implementation.
I find the UIView that includes the properties and casted it to the object itself RTCVideo in this case). But now I am stuck. I can go and change some stuff as per your suggestion in the "Development Pods" to be able to access but this is my last bullet :) I prefer to convince these two libraries in a friendly way :)
Yes, but the above syntax isn't what you want. The modern way to do this is with a class extension.
Your header file is the same:
#interface MyInterface
#end
But in your .m file, you create an extension by appending ():
#interface MyInterface ()
#property (nonatomic, readwrite) NSDictionary *dict;
#end
Now, inside your .m file, you can access self.dict normally, but outside of your .m file it won't appear available.
For full details, see Programming with Objective-C: Class Extensions Extend the Internal Implementation.
The syntax you've written actually creates a static (global) variable called dict that isn't tied to any instance.
It is possible to create raw instance variables using a {...} syntax, either on the extension or on the implementation, but this isn't used that often today, except for managing raw buffers that you don't want accessors for. The syntax is either:
#interface MyInterface () {
NSDictionary *_dict;
}
...
#end
or on the implementation:
#implementation MyInterface {
NSDictionary *_dict;
}
...
#end
But I recommend simple extensions with properties any time you can. And if you are considering creating an accessor for it, you definitely want to use #property and let the system do it for you.
If I understand your edits correctly, you're trying to read the internal ivars of an object that doesn't expose them with an accessor, correct? I believe specifically you want to access _player.
There's several common ways to do that. The key feature you want is Key-Value Coding.
The simplest approach for this problem is -valueForKey:
AVPlayer *player = [view valueForKey:#"player"];
The first thing -valueForKey: looks for is _<key>, and if it's just an object pointer (as in this case), it just returns it.
(This can be broken if a class return false for +accessInstanceVariablesDirectly, but the default is true, and it's unusual to override this.)
Another very common approach is to just declare any methods you know exist as a category. (This won't work for _player, since it's not a method, but in case you need similar things.) Imagine you wanted to call the "private" method -removePlayerTimeObserver. In your .m file, just say you know about it using a category:
#interface RCTVideo (PrivateMethods)
- (void)removePlayerTimeObserver;
#end
And since you know about it, you can call it:
[video removePlayerTimeObserver];
If you're wrong, and that method doesn't really exist, then the program will crash. In Objective-C, almost all rules are advisory. You can break them if you want to. ObjC programmers tend to be big rule-followers because otherwise the program crashes and ObjC has very clear rules that are pretty easy to follow. It's not because the system forces us to.

XCode4 Base class in property gives compiler warning when set to subclass

I have a base class, say BaseClass, which provides a common interface for several subClasses, defined by, for example #interface SubA:BaseClass.
The interface of the base class includes a method, say -(void)method1:arg;
In my view, I want to send message to different subClass instances, depending on circumstances. View has a property something like
#property (strong) BaseClass *currentInstance
When I use, in a controller object,
[self.myView setCurrentInstance:instanceOfSubA]
I get a compiler warning.
Then in the view at some point I have
[self.currentInstance method1:thisArg]
and everything works right; that is:
Checking the class in the view, gives the class as SubA.
And all the overridden functions give the right results.
Can I get rid of the warnings? Or is this a signal that I'll get in trouble somewhere down the line.
I seem to have found the answer in Cocoa With Love
In his description of why not to say "polymorphic" Matt Gallagher gives this example of overriding:
MyBaseClass *newObject = [[[MySubClass alloc] init] autorelease];
[newObject instanceMethodDeclaredInMyBaseClass];
Tried it, and it works. Simple and straight forward, but I wouldn't have thought of it if I hadn't seen this example.
By the way, I've benefited from Cocoa With Love many times.

Shared object with others classes?

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.

In objective-c , How to make variable accessible from more than one class

in cocos2d for iphone i have two classes:
1- GameScene.h class
2- Player.h class
GameScene.h has this label scoreLabel2 declared as follows
#interface GameScene : CCLayer {
Player* player;
CCLabel* scoreLabel2;
and the player.h class has the following method
-(void)updateScore{
NSLog(#"%#",scoreLabel2);
}
I am getting this error
error: 'scoreLabel2' undeclared (first use in this function)
what is the best solution to that problem since I will need to use many objects and variables between my classes?
Many Thanks
Ahmed,
You need to have an updateScore method on your scene and then call this method from your player class. I would recommend something like this:
#interface GameScene : CCLayer {
Player* player;
CCLabel* scoreLabel2;
NSInteger score;
...
}
...
- (void) updateScoreByAmount:(NSInteger)scoreModifier;
andin the .m you would have something like:
- (void) updateScoreByAmount:(NSInteger)scoreModifier
{
score += scoreModifier; // scoreModifier can be positive or negative
}
then in your player class you would call this method on your scene when you want to change the score.
[myScene updateScoreByAmount:5];
This will need to be modified to suit your situation, but something like that is what you are looking for.
You can do it with [scene valueForKey:#"scoreLabel2"] but that points to a nasty problem with the design of your classes. You haven't properly declared the interface to the GameScene and there's no reference to the GameScene in the Player's updateScore method. Maybe it's just a typo, but you shouldn't be declaring whole methods in the .h file. (Not sure if this is a getter or a setter either. Normally, I'd infer that it's a getter because it doesn't have a parameter, but I don't think it's safe to assume anything about this code.) I mean this in the nicest way, but it sounds like you have a lot of fundamental work to do to understand OOP better.
The answer to your question is using Singletons.
Hi have recently answered a similar question here
How to share data between separate classes in Java
you can do the same thing in Objective-C actually there should be an example int he wiki page I provide in the answer.
Bye
Andrea

How to pass message to instance from a different class in objective c?

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.