Alright, this is my first post and am still rather new at objective-c, but here it goes:
I am currently creating a project that will create a second queue to generate a bunch of NSTimers and set them off. Since I don't want to halt the main queue, I figured Grand Central Station was the best route.
Currently, I have a UIButton that performs the following action:
- (IBAction)runTest:(id)sender {
if (!timerQueue) {
timerQueue = dispatch_queue_create("com.myApp.timerQueue", DISPATCH_QUEUE_SERIAL);
}
dispatch_async(timerQueue, ^{[self initiateTest];});
and then...
- (void) initiateTest {
// code to generate timers and execute
}
The header file associated with the viewController where this all happens looks like this:
#interface ViewController : UIViewController <SomeOtherMgrDelegate> {
dispatch_block_t timerQueue;
}
...
- (IBAction)runTest:(id)sender;
- (void) initiateTest;
The issue seems to be with regards to the line
timerQueue = dispatch_queue_create("com.myApp.timerQueue", DISPATCH_QUEUE_SERIAL);
Which generates a rather long-winded semantic issue that reads:
Assigning to '__strong dispatch_block_t' (aka 'void (^__strong)(void)') from incompatible type 'dispatch_queue_t' (aka 'NSObject *')
Any idea why this error might be generating? It seemed in the documentation that this was the correct way to go about it.
Thanks; and let me know if there is anything else in my code that might be useful to see!
EDIT: So this was a rather dumb mistake, but for others: make sure the types match up (blocks /= queues!). The .h file associated with the viewController SHOULD look like this:
#interface ViewController : UIViewController <SomeOtherMgrDelegate> {
dispatch_queue_t timerQueue; // This is where the problem was.
}
...
- (IBAction)runTest:(id)sender;
- (void) initiateTest;
You declared timerQueue as an instance of dispatch_block_t, when it should be dispatch_queue_t, the return type of dispatch_queue_create()
Read the error. Look at the docs for the return value of dispatch_queue_create. And finally look at how you declared timerQueue. It's the wrong type.
You need:
#interface ViewController : UIViewController <SomeOtherMgrDelegate> {
dispatch_queue_t timerQueue;
}
Related
What does self mean in Objective-C? When and where should I use it?
Is it similar to this in Java?
self refers to the instance of the current class that you are working in, and yes, it is analagous to this in Java.
You use it if you want to perform an operation on the current instance of that class. For example, if you are writing an instance method on a class, and you want to call a method on that same instance to do something or retrieve some data, you would use self:
int value = [self returnSomeInteger];
This is also often used for accessor methods on an instance (i.e. setters and getters) especially with setter methods, if they implement extra functionality rather than just setting the value of an instance variable, so that you do not have to repeat that code over and over when you want to set the value of that variable, for example:
[self setSomeVariable:newValue];
One of the most common uses of self is during initialization of a class. Sample code might look like:
- (id)init
{
self = [super init];
if(self!=nil) {
//Do stuff, such as initializing instance variables
}
return self;
}
This invokes the superclass's (via super) initializer, which is how chained initialization occurs up the class hierarchy. The returned value is then set to self, however, because the superclass's initializer could return a different object than the superclass.
self is an implied argument to all Obj-C methods that contains a pointer to the current object in instance methods, and a pointer to the current class in class methods.
Another implied argument is _cmd, which is the selector that was sent to the method.
Please be aware that you only get self and _cmd in Obj-C methods. If you declare a C(++) method, for instance as a callback from some C library, you won't get self or cmd.
For more information, see the Using Hidden Arguments section of the Objective-C Runtime Programming guide.
Yes, it's exactly the same as "this" in Java - it points to the "current" object.
Two important notes:
The class itself, e.g. UIView (I'm NOT talking about a UIView object) is itself an object, and there is a self associated with it. So for example, you can reference self in a class method like this:
// This works
+(void) showYourself { [self performSelector: #selector(makeTheMostOfYourself)]; }
// Class method!
+(void) makeTheMostOfYourself { }
Note that the compiler does NOT raise any warnings or errors, even if the self you mean to reference is an object and not a class. It is VERY easy to cause crashes this way, for example:
// This will crash!
+(void) showYourself { [self performSelector: #selector(makeTheMostOfYourself)]; }
// Object method!
-(void) makeTheMostOfYourself { }
// This will crash too!
-(void) showYourself2 { [self performSelector: #selector(makeTheMostOfYourself2)]; }
// Class method!
+(void) makeTheMostOfYourself2 { }
Sadly, this makes class methods a bit harder to use, which is unfortunate because they are a valuable tool for encapsulation through information hiding. Just be careful.
Wow, that many half-correct answers and misleading hints. This let me answer the Q even there is a accepted answer for years:
First of all: It is really hard to compare a concept of messaging/calling in the context of an early binding, static typing language as Java with a late binding, dynamically typing languages as Objective-C. At one point this will break. I would say: No, this is not similiar, since the typing and dispatching concepts of both language are fundamental different so nothing can be similar to the other one. However, …
Then we should differ between the "two sides" of self.
A. Using self
When you use it in a message, it is simply an object reference as any other:
[self doSomething];
[anotherObject doSomething];
Technically both lines works identically (accept of having a different receiver, of course). This especially means, that the first line does not lead to an execution of a method inside the class of self, because self does not necessarily refer to "that class". As every message inside Objective-C (single exception: messages to super)this can lead to the execution of a method in a subclass:
#interface A : NSObject
- (void)doSomething;
- (void)doAnotherThing;
#end
#implementation
- (void)doSomething
{
[self doAntoherThing];
}
- (void)doAnotherThing
{
NSLog( #"A" );
}
#interface B : A
- (void)doSomething; // Not necessary, simply as a marker
#end
#implementation B
- (void)doAnotherThing
{
NSLog( #"B" );
}
In a code like this
B *b = [B new;]
[b doSomething];
The line
[self doAnotherThing];
in class A will lead to the execution of -doAnotherThing (B), because messages to self are late bound as every other message. The result on the console will b "B", not "A". Using self as a receiver you should not think of a single special rule. There is completely none.
(And the above example is a very good example for using self in class methods, because the same situation can occur on class methods. Using the class itself breaks polymorphism, what is one of the worst idea at all in OOP. DO use self in class methods, too.)
B. Getting self
What is self pointing to? It points to the object to whom the message is sent that caused the execution of the current method.
Having …
…[someObject doSomething]… // some object is a reference to an instance object
… as a message, a method is called, in the most simple case …
- (void)doSomething
{ … }
In such a case, self can point to an instance of the class, the method belongs to. And it can point to an instance of a subclass, the method belongs to, too. You don't know. (And this information is preserved using self to send a message as explained above.)
If the message is sent to a class object, self points to the class object, that was the receiver of the message. This is completely analogous. Therefore it is possible that self points to a subclass object:
#interface A : NSObject
+ (void)doSomething;
+ (void)doAnotherThing;
#end
#implementation
+ (void)doSomething
{
[self doAntoherThing];
}
+ (void)doAnotherThing
{
NSLog( #"A" );
}
#interface B : A
- (void)doSomething; // Not necessary, simply as a marker
#end
#implementation B
+ (void)doAnotherThing
{
NSLog( #"B" );
}
Having this classes
…[A doSomething]…
self inside -doSomething (A) points to the class object of B. Therefore [self doAnotherThing] of B(!) is executed. This is clearly different from
+ (void)doSomething
{
[A doAntoherThing];
}
The latter version causes relevant harm to the principles of OOP.
As a side note it is possible that self inside a class method of a root class points to an instance object of the root class or any subclass. You have to keep this in mind, when writing categories on NSObject.
self is an object pointer to the current instances dispatch table. It is an implicit first argument to every member function of an object, and is assigned when that function is called.
In functions like init, you need to be careful that when you call the super class init you reassign self to be the return value as the super class init may redefine what self points to.
super is similar to self except it points to the superclass dispatch table.
Can someone please explain to me (in simple terms) why an instancetype is used in Objective-C?
- (instancetype) init {
self = [super init];
if (self) {
// Custom initialization
}
return self;
}
It's to increase type safety.
Back in the old days, initialisers just returned an object of type id (any object).
With normal initialisers (those that begin with "init", "alloc" or "new"), this wasn't usually a problem. The compiler would automatically infer the type that it returned and therefore restrict any method calls on the object to the instance methods of that class.
However, this was a problem with static convenience initialisers or "factory methods" that didn't necessarily follow the same naming convention - therefore it was unable to apply the same type safety.
This means that with a class like this:
#interface Foo : NSObject
+(id) aConvenienceInit;
#end
The compiler would accept code like this:
NSArray* subviews = [Foo aConvenienceInit].subviews;
Why? Because the returned object could be any object, so if you try and access a UIView property - there's no type safety to stop you.
However, now with instancetype, the result you get back is of type of your given instance. Now with this code:
#interface Foo : NSObject
+(instancetype) aConvenienceInit;
#end
...
NSArray* subviews = [Foo aConvenienceInit].subviews;
You'll get a compiler warning saying that the property subviews is not a member of Foo*:
Although it's worth noting that the compiler will automatically convert the return type from id to instancetype if your method begins with "alloc", "init" or "new" - but nonetheless using instancetype wherever you can is a good habit to get into.
See the Apple docs on instancetype for more info.
Imagine two classes:
#interface A : NSObject
- (instancetype)init;
#end
#interface B : A
#end
The init method from A is inherited to B. However, in both classes the method has a different return type. In A the return type is A and in B the return type is B.
There is no other way to declare the return type for initializers correctly. Note that most programming languages with classes don't even have return types for constructors, therefore they completely avoid the issue.
This is the reason why Obj-C needs instancetype but of course it can be used outside initializers, too.
It is important to use instancetype instead of id in Objective-C if you are also using this code in Swift. Consider the following class declaration:
#interface MyObject : NSObject
+ (id)createMyObject;
- (void)f;
#end
If you want to create a MyObject instance in Swift 5.3 with createMyObject and then call f for this object, you will have to do the following:
let a = MyObject.createMyObject()
(a as? MyObject)?.f()
Now replace id with instancetype in MyObject to have the following Swift code:
let a = MyObject.create()
a?.f()
As you can see now, you can use MyObject.create() instead of MyObject.createMyObject(). And you don't need to use (a as? MyObject) since a is defined as MyObject? and not as Any.
Background:
I have an object (let's call it BackendClient) that represents connection with server. Its methods are generated to single #protocol and they are all synchronous, so I want to create proxy object that will call them in background. The main problem is return value, which I obviously can't return from async method, so I need to pass a callback. The "easy" way will be copy all BackendClient's methods and add callback argument. But that's not very dynamic way of solving that problem, while ObjectiveC nature is dynamic. That's where performSelector: appears. It solves problem entirely, but it almost kills proxy object transparency.
Problem:
I want to be able to send not declared selector to proxy (subclass of NSProxy) object as if it was already declared.
For example, I have method:
-(AuthResponse)authByRequest:(AuthRequest*)request
in BackendClient protocol. And I want proxy call look like this:
[proxyClient authByRequest:myRequest withCallback:myCallback];
But this wouldn't compile because
No visible #interface for 'BackendClientProxy' declares the selector 'authByRequest:withCallBack:'
OK. Let's calm down compiler a bit:
[(id)proxyClient authByRequest:myRequest withCallback:myCallback];
Awww. Another error:
No known instance method for selector 'authByRequest:withCallBack:'
The only thing that comes to my mind and this point is somehow construct new #protocol with needed methods at runtime, but I have no idea how to do that.
Conclusion: I need to suppress this compilation error. Any idea how to do that?
If I understand it, you have a synchronous, non-threaded, API that you want to be asynchronous for purposes of not blocking, say, the main event loop, etc...
I would add a serial queue to BackgroundClient:
#property(strong) dispatch_queue_t serialQueue;
... somewhere in your -init ...
_serialQueue = dispatch_queue_create(..., serial constant);
Then:
- (void)dispatchOperation:(dispatch_block_t)anOperation
{
dispatch_async(_serialQueue, anOperation);
}
That can be used like:
[myClient dispatchOperation:^{
[myClient doSynchronousA];
id result = [myClient doSynchronousB];
dispatch_async(dispatch_get_main_queue(), ^{
[someone updateUIWithResult:result];
}
}];
That is the easiest way to move the BackgroundClient to an asynchronous model without rewriting it or heavily refactoring it.
If you want to harden the API, then create a class wrapper for BackendClient that holds an instance of the client and the serial queue. Make it such that said class instantiates the client and the rest of your code only retrieves instances from that wrapper. That'll allow you to still have the same dispatchOperation: model, but not require mirroring all the methods.
typedef void(^ AsyncBackendBlock(BackendClient* bc);
#interface AsyncBackend
+(instancetype)asyncBackendWithBackend:(BackendClient*)bc;
#property .... serialQueue;
- (void) dispatchAsync:(AsyncBackendBlock) backBlock;
#end
.m:
#interface AsyncBackend()
#property... BackendClient *client;
#end
#implementation AsyncBackend
- (void) dispatchAsync:(AsyncBackendBlock) backBlock
{
dispatch_async(_serialQueue, ^{
backBlock(_client);
});
}
#end
Caller:
AsyncBackend *b = [AsyncBackend asyncBackendWithBackend:[BackendClient new]];
[b dispatchAsync:^(BackendClient *bc) {
[bc doSomething];
id result = [bc retrieveSomething];
dispatch_async(dispatch_get_main_queue(), ^{
[uiThingy updateWithResult:result];
}
}];
....
To look up a selector at runtime, you can use NSSelectorFromString(), but in this case you should just go ahead and import whatever header you need to get the declaration of -authByRequest:
I get the above message in XCode 4.6. I've done a pretty thorough search and but nothing seems to match the exact circumstances surrounding my issue. Admittedly, I'm relatively new to iOS dev, and memory-management has never been my strong suit, but this just has me completely miffed.
I have an instance variable theLink which is defined in the class Game as follows:
#interface Game : NSObject
// Class objects
#property(nonatomic,retain) NSMutableArray *queryItems;
#property(nonatomic,retain) NSMutableArray *theArray;
#property(nonatomic,retain) NSString *theLink;
#property(nonatomic,retain) NSString *thePath;
theLink is set in the makeGame method which is called in the method initialiseGame in my view controller:
- (void) initialiseGame
{
bool gameCreated = FALSE;
while (!gameCreated)
{
gameCreated = [theGame makeGame:#"ptl"];
}
[loadingIndicator stopAnimating];
[loading setText:#"Tap to Start"];
[self performSelector:#selector(setLabels) withObject:nil afterDelay:0.0];
}
(Note: the performSelector afterDelay is used to allow the view to update before continuing. Bit of a hack but I couldn't work out a better way!)
The app then loads the game, and when the user taps the screen to start, the next method which is called from the view controller is:
- (void) setupLink
{
...
for(int i=0; i<[theGame.theLink length]; i++) {
...
}
}
It is on this reference to theGame.theLink where I'm am getting the crash.
What has me most confused is that if I call theGame.theLink from inside the initialiseGame method, it is displays correctly, and also calling any other variable from the Game class (such as thePath or theArray works perfectly, so theGame object has not been deallocated in it's entirety, only the variable theLink.
It seems to me that the variable is being deallocated somewhere as the view controller is being updated. I haven't released the variable, and can't work out why only this variable is being deallocated. As I said at the start, memory-management is not my strength!
Any help/ideas would be hugely appreciated. Let me know if you require any more details.
Thanks heaps,
Andrew
EDIT: Setting of theLink within makeGame
- (bool) makeGame:(NSString*)gameType
{
...
[self getLink];
}
- (void) getLink
{
...
if (... && ((arc4random() % 10) > 8))
{
theLink = #"Animals";
}
}
There are many different ways theLink may be set, depending on random numbers and other factors. This is the most basic form which simply sets it to a static string. It doesn't matter how theLink is set or what it is set to, the program always crashes at the same point.
If theLink is being set to the parameter being passed to it ,#"ptl" or some similar temporary string, it will give you a problem, because it is just a pointer pointing at the current location that is holding #"ptl". After the makeGame method is completed, your system will assume that it is all done with #"ptl" and just free it up.
When you make an #"stringwhatever" in your code, it is supposed to be the equivalent of making an NSObject that is an immutable literal instance of #"stringwhataver". It should, in theory handle all the reference counting in a nice way, but when you are doing your own memory management, there are so many ways to lose count of your references.
There's a pretty simple rule to follow. If you've declared properties, access them via the property. To do otherwise (as you are doing above, with theLink = ...) bypasses all of the memory management built into the property accessors.
self.theLink = ...
Would have solved this problem under MRC. Switching to ARC has "solved" your problem without you understanding the root cause.
I'm stuck trying to combine openGL-es (xcode openGL game template with the ogles2tools library from powervr 3.0 sdk. My problem is the line of code where I load the effect file:
/*
Load the effect.
We pass 'this' as an argument as we wish to receive callbacks as the PFX is loaded.
This is optional and supplying NULL implies that the developer will take care
of all texture loading and binding to to the Effect instead.
*/
if(m_pEffect->Load(*m_pEffectParser, "Effect", c_szPfxFile, NULL, uiUnknownUniforms, &error) != PVR_SUCCESS)
{
NSLog(#"%s",error.c_str());
return;
}
I'm supposed to pass a "this" pointer so I can receive the callbacks. The delegate method I need to implement is:
EPVRTError OGLES2IntroducingPFX::PVRTPFXOnLoadTexture(const CPVRTStringHash& TextureName, GLuint& uiHandle, unsigned int& uiFlags)
{
/*
This is an optional callback function for PVRTPFXEffect and can be used to automate
the texture loading process.
If multiple effects are to be loaded and they share textures it would be
prudent to have a caching system in place so texture memory is not wasted.
Please see OGLES2MagicLantern for an example of this.
*/
if(PVRTTextureLoadFromPVR(TextureName.String().c_str(), &uiHandle) != PVR_SUCCESS)
return PVR_FAIL;
return PVR_SUCCESS;
}
I guess the big issue for me is how do I go about providing a cpp delegate method in objective-c? I did some reading on this issue, but it seemed what I was reading was going the other way. That is, an objective-c delegate in cpp. It's pretty confusing, but here's my thought...
I create a cpp class the implements the method I need. I add that to my viewController class and pass the pointer to this cpp class in the m_pEffect->Load call. Does this seem correct?
Thanks.
P.S. Sorry if my code formatting is bad. I'm still learning.
Edit: Here's the example I found regarding mixing the objective-c and cpp. It seems really similar to what I want to do.
Update: Here's some additional info (requested by user1118321)
The CPP class which needs a delegate is CPVRTPFXEffect (PVRTPFXParserAPI.h - from powerVR SDK 3.0). I would add a link, but I'm not sure if this is allowed. Here's a link to the class header, but this version (and others on the web) did not include the pDelegate attribute for the load method. I'm assuming they are examples of a previous version. Let me know if it's okay to post this class file and I will do so.
I found a good example of what I think I'm supposed to do from reading this thread. So here's what I have so far:
My CPP delegate class...
class myCppDelegate : public PVRTPFXEffectDelegate {
public:
myCppDelegate() {};
EPVRTError PVRTPFXOnLoadTexture(const CPVRTStringHash& TextureName, GLuint& uiHandle, unsigned int& uiFlags) {
return PVR_FAIL;
};
};
My Obj-C wrapper class (just modified from the example link above)...
struct RNWrapOpaque;
#interface RNWrap : NSObject {
struct RNWrapOpaque *_cpp;
}
- (id)init;
#end
implementation...
#import "RNWrap.h"
#import "Wrap.h"
#interface RNWrap ()
#property (nonatomic, readwrite, assign) RNWrapOpaque *cpp;
#end
#implementation RNWrap
#synthesize cpp = _cpp;
struct RNWrapOpaque
{
public:
RNWrapOpaque() : wrap() {};
myCppDelegate wrap;
};
- (id)init
{
self = [super init];
if (self != nil)
{
self.cpp = new RNWrapOpaque();
}
return self;
}
- (void)dealloc
{
delete _cpp;
_cpp = NULL;
// [super dealloc];
}
#end
Basically I am able to compile the code and debug, but when the the CPVRTPFEffect class makes this call:
if(pDelegate->PVRTPFXOnLoadTexture(pTexDesc->FileName, uiHandle, uiFlags) != PVR_SUCCESS)
I get EXC_BAD_ACCESS. I'm assuming it's not finding my callback method, because I set a breakpoint and the line never gets called.
Here's my updated code which calls CPVRTPFXEffect::Load using a bridge command for the delegate parameter.
if(m_pEffect->Load(*m_pEffectParser, "Effect", c_szPfxFile,(__bridge myCppDelegate*)opaqueCppWrap, uiUnknownUniforms, &error) != PVR_SUCCESS)
Thanks for your help!
Update 2: The project uses ARC. Here's what my viewController interface looks like:
#interface ViewController : GLKViewController {
...
RNWrap* opaqueCppWrap;
...
}
#property (strong) RNWrap *opaqueCppWrap;
Adding the #property didn't help with the EXC_BAD_ACCESS. I'm not sure how to "see" the value of pDelegate when I'm tracing the CPP code. Xcode doesn't reveal anything when I hover over the variable.
I added the following line of code to the CPVRTPFXEffect::Load method (just prior to the line where it crashes):
*pReturnError += PVRTStringFromFormattedStr("Here is your class typeid: %s.\n", typeid(pDelegate).name());
return PVR_FAIL;
This is what displayed in the debug output window:
Here is your class typeid: P21PVRTPFXEffectDelegate.
I'm not sure what the "P21" means (if anything), but it looks like I'm close to getting this working. I dunno, maybe this is as close as it gets. Still crashing and not finding my method.
First, you may want to look at the last article in the series on wrapping C++. Most of it has gotten much simpler in the latest versions of clang. You probably don't need half this code anymore. ObjC++ objects can now have private C++ properties without any tricks, while maintaining a pure-ObjC interface.
Here is how you want to think about this problem:
Build a C++ object that is the delegate. Write all the code involved in setting up the delegation, etc, in C++. So when it says "pass a this pointer" you should really be passing a this pointer (because you should be doing this in the C++ code). The fact that you're doing a _bridge cast in a C++ call is a real hint something is going wrong.
Let an ObjC own the C++ object as a property.
Write the delegate callbacks in C++ inside the C++ object. If useful, you can let the C++ object then make calls into the ObjC object as needed, but it may be easier if the C++ object does all the delegate work.
I finally got this working, but had to remove the obj-c wrapper class from my viewController in order to do so. Here's what the code looks like:
ViewController.h
struct Opaque;
#interface ViewController : GLKViewController {
...
//RNWrap* opaqueCppWrap; // this didn't work
struct Opaque *opaqueCpp; // try this
...
}
ViewController.mm
// declare the Opaque structure
struct Opaque {
public:
Opaque() : cppobject() {};
myCppDelegate cppobject;
};
viewDidLoad
// ... create opaque member on initialization
opaqueCpp = new Opaque();
//opaqueCppWrap = [[RNWrap alloc] init]; // old way of doing things using wrapper
pass the delegate to the Load method
// old way using bridge cast and wrapper
//if(m_pEffect->Load(*m_pEffectParser, "Effect", c_szPfxFile,(__bridge myCppDelegate*)opaqueCppWrap, uiUnknownUniforms, &error) != PVR_SUCCESS)
// this works...
if(m_pEffect->Load(*m_pEffectParser, "Effect", c_szPfxFile, (myCppDelegate*)opaqueCpp, uiUnknownUniforms, &error) != PVR_SUCCESS)
Not sure why the wrapper class doesn't work, but I'm happy that my callback is working (appy no crashy!)
Phew, that was rough. Any thoughts/comments?