I have a simple Blocks and typedef doubt.
Consider the following codes, I've some typedef and two methods, second one is commented out. My doubt is regarding the first one. Should I use this one? Any issues or something that may arise in future?
typedef void (^MySuccessBlock)(MyServiceResponse *response);
typedef void (^MyFailureBlock)(NSError *errorObject);
#property (nonatomic, copy)MySuccessBlock mySuccessBlock;
#property (nonatomic, copy)MyFailureBlock myFailureBlock;
//SHOULD I USE THIS?
- (void)myServiceWithCompletion:mySuccessBlock
failure:myFailureBlock;
//- (void)myServiceWithCompletion:(void (^)(MyServiceResponse *response))completion
// failure:(void (^)(NSError *errorObject))failure;
In Implementation file:
//If 1st one is used:
- (void)myServiceWithCompletion:aSuccessBlock
failure:aFailureBlock{
self.mySuccessBlock = aSuccessBlock;
self.myFailureBlock = aFailureBlock;
....
}
You should use this:
- (void)myServiceWithCompletion:(MySuccessBlock)successBlock
failure:(MyFailureBlock)failureBlock;
Note the capitals at the beginning of MySuccessBlockand MyFailureBlock as in your typedef.
In fact, when you declare:
- (void)myServiceWithCompletion:mySuccessBlock
failure:myFailureBlock;
the problem comes from the fact that you don't specify the type of your parameters 'mySuccessBlock' and 'myFailureBlock'. So they are treated as default type id because:
If a return or parameter type isn’t explicitly declared, it’s assumed
to be the default type for methods and messages—an id.
It is like if you write:
- (void)myServiceWithCompletion:(id)mySuccessBlock
failure:(id)myFailureBlock;
id type is a pointer, and blocks are pointers, so there is no compile problem. But you can have execution problem because of black's parameters and return value!
The typedef declaration provides a way to create an alias that can be used anywhere in place of a (possibly complex) type name. See
You should use the typedef in the following way.
- (void)myServiceWithCompletion:(MySuccessBlock)aSuccessBlock
failure:(MyFailureBlock)aFailureBlock;
Related
I want to use a c-style struct in several classes but I am struggling with its (global) access.
I define the struct in the header file of class “Utilities”:
typedef struct
{
int length;
SInt16 *someData;
} NewStruct;
+ (NewStruct *)initStructWithValue:(int)length;
In another class I initialize this struct with the class method of Utitlities:
#property (nonatomic, assign) NewStruct *newStruct;
_newStruct = [Utilities initStructWithValue: 5]
Now I want to use newStruct in other classes. However, when I put
extern NewStruct *newStruct;
at the top of the header-files it doesn’t work, it seems that I don't have access to newStruct.
I get the error: linker command failed with exit code 1 (use -v to see invocation)
What am I doing wrong and what would be the best way to do it? Or might it be better to avoid using this struct as global variable?
The extern keyword means "declare without defining". In other words, it is a way to explicitly declare a variable, or to force a declaration without a definition. But when the linker assembles your object code it needs the variable the be defined somewhere, which means you have to have a source where the variable is there without the extern keyword NewStruct *newStruct;.
With the method above, you are considering this variable as a global singleton. If you need multiple instances, you should just use the #property as you specified above.
I understand that placing the word extern before a variable declaration in a header file declares the existence of a global static variable without initialising it. I also understand that if I import the file containing the extern variables, I can reference them without a class/file name. But where does one define them and their values?
What I am trying to do is create a class of constants with global constants that I want to use throughout an iOS application's code.
Does one put them inside the interface like this?
Example.h
#import <Foundation/Foundation.h>
#interface Constraints : NSObject
{
extern NSString * const PREFS_NAME;
}
Or does one put then outside of the interface like this
Example.h
#import <Foundation/Foundation.h>
extern NSString * const PREFS_NAME;
#interface Constraints : NSObject
{
}
Then in the implementation .m file how would one initialise the extern values?
Inside the implementation area like this?
Example.m
#import "Constraints.h"
#implementation Constraints
/**PRefecences name for the application**/
const NSString * PREFS_NAME = #"MyApp_Prefs";
#end
Or do initialise them outside of the implementation area like this:
Example.m
#import "Constraints.h"
/**PRefecences name for the application**/
const NSString * PREFS_NAME = #"MyApp_Prefs";
#implementation Constraints
#end
Or do I provide them their initial values in a constructor? or some arbitrary a static style method with + in front of it i.e. +(void) setAppConstraints;
I have tried several combinations, but always run into errors, such as "Redefinition of 'xVariable' with a different type". Or a something about "extern does not have an initialise interface" (or something like that, I forget). So I want to know how to declaire and initialise them properly to form the same role as public static final variables in Java.
Also what are the limits of the extern command? I know I can extern an NSInteger or NSString, but what about NSArray?
I am asking this question because there seems to be to much misleading, or incomplete, information regarding the use of extern in Objective-C. Many of the answers seem speculatory. My hope is for this question to be a good resource not only for me, but to limit further similar questions about the basics of extern.
You define it's value in the file inside which it's declared, which in your case is Example.m; You can still re-assign this variable, so the declaration in Example.h would look like this:
extern NSString * PREFS_NAME;
This way every file that imports Example.h has access to this variable. The equivalent of public static final in Objective-C is const. If you also want it to be public you should make it be a class instance variable, but in this case you don't need it because it's already accessible everywhere. So in this case it would be:
// .m file
NSString* const PREFS_NAME = #"MyApp_Prefs";
// .h file
extern NSString* const PREFS_NAME;
Also notice that const NSString* is different from NSString* const. The latter is a const pointer to NSString. The former hasn't sense even if it's a correct syntax. In Objective-C the const qualifier doesn't affect objects, instead there are mutable and immutable classes. It would have sense in C++ meaning that you can use just const methods on the instance.
extern is used to signal the compiler that you will be using a variable or a function that is defined in another compilation unit.
When you say extern const NSString *PREFS_NAME, you're saying "Replace all references in this compilation unit to PREFS_NAME to the variable PREFS_NAME as it is defined in another file." So when you try to assign PREFS_NAME in your .m, all you're doing is trying to assign a variable that, though it has a name, it doesn't exist. Declaring a variable extern is only a declaration of a variable or function, not a definition of that variable or function. It lets the compiler know that the name is in use, and that the linker will take care of what to do with it, but even if you provide a type here, it doesn't actually set aside space for the variable, it's expecting the space to be set aside in the compilation unit that's actually defining the variable.
You compile three or four different source code files together, three of them may declare:
extern int buffer[];
And one may declare
int buffer[BUFSIZE];
In its global scope, and the linker's job is to resolve the three declared references to extern buffer to the fourth's actual definition of the buffer.
extern is to C variables and functions much as #class is to Objective-C classes, it's a forward declaration, a promise to the compiler that you don't have to freak out when you see a name that's undefined here, because the linker will answer whatever lingering questions you may have.
How to declare an array of characters so that all the functions that has been defined inside the class can use it with the updated values.
Getting errors when defining the char data[4096] in the #synthesize definition.
#interface A: NSObject
{
char data[4096];
}
#property(nonatomic,retain)char data;
#end
#implementation A
#synthesize data
#end
I am getting "No declaration of the property 'pData' found in the interface"
Not sure why you get that error, but several things are clearly wrong in your code:
data instance variable and property for it have different types. Property declaration should be
#property(nonatomic) char[4096] data;
You must use retain attribute only for obj-c types properties, for plain c-types use assign (or don't specify anything as assign is used by default)
Exposing your pointer to char directly to changes may be not a good idea - better make your property readonly and make special method to change its contents:
#property(nonatomic, readonly) char[4096] data;
- (void) changeData:...//some parameters here
P.S. May be consider using NSString* (or NSMutableString*) instead of char[]?
P.P.S. Or if you just store some random byte data consider using NSData/NSMutableData for that. (Thanks #bbum for suggesting that)
I was hoping someone could help me understand the syntax of blocks when used as members of a class. I have some code that's actually working just fine:
#class Structure;
typedef void (^StructureDeleteCallback)(Structure *);
#interface StructureListDelegate : NRFCTableDelegate
{
StructureDeleteCallback _structureDeleteCallback;
}
#property (nonatomic, copy) StructureDeleteCallback structureDeleteCallback;
#end
This works, but I would like to understand the syntax of the typedef statement; and whether or not it's actually required to use typedef.
What I've read says that using typedef in this situation is recommended because it makes the code a lot clearer; but I've been unable to get it to compile at all when trying to do this without typedef. My understanding of typedef was that the syntax was basically:
typedef [actual type] [new name for type];
Such as:
typedef double CLLocationDegrees;
But the syntax of my typedef statement doesn't match this. So my questions are:
How can the syntax of my typedef
statement be so different from other
typedef statements / what does the syntax I'm using actually mean to the compiler?
Is it possible to
have a block as a member of a class
without using typedef?
I myself have asked a question along the lines of yours here: Block references as instance vars in Objective-C
See my answers here and here.
This is just out of curiosity but when i declare an enum type, would it be better to have it within an implementation declaration or outside of it? What would be best practice? For example:
#implementation PostQuestionScene
enum popUpItems{
kExpiredBox,
kPauseBackground
};
vs..
enum popUpItems{
kExpiredBox,
};
#implementation PostQuestionScene ..
I tend to always have a typedef so it's just like another variable:
typedef enum {
kExpiredBox,
kPauseBackground
} popUpItems_t;
Then create instances of it.
popUpItems_t popUpItems;
If you will use it outside that module, put the typedef in the header so when the header is included, other modules have the typedef at their disposal (if they need to take it as an argument, for example,) otherwise put it in the implementation (think public/private variables.)
I don't think it makes any technical difference. I would place it before the #implementation (along with all other miscellaneous declarations) unless it is just used in one or a small group of methods, in which case I would place it immediately before those methods.
Of course, if it might be used by clients or subclasses it should be in your header file (where #interface is) so that the definition is visible to them.