Instance class or method without an interface? - iphone

Got this code:
#import <Foundation/Foundation.h>
#interface CalculatorBrain : NSObject
- (void)pushOperand:(double)operand;
- (double)performOperation:(NSString *)op;
#property (nonatomic, readonly) id program;
+ (NSString *)descriptionOfProgram:(id)program;
+ (double)runProgram:(id)program;
#end
And this one:
#import "CalculatorBrain.h"
#interface CalculatorBrain()
#property (nonatomic, strong) NSMutableArray *programStack;
#end
#implementation CalculatorBrain
#synthesize programStack = _programStack;
- (NSMutableArray *)programStack
{
if (_programStack == nil) _programStack = [[NSMutableArray alloc] init];
return _programStack;
}
- (id)program
{
return [self.programStack copy];
}
+ (NSString *)descriptionOfProgram:(id)program
{
return #"blablabla";
}
- (void)pushOperand:(double)operand
{
[self.programStack addObject:[NSNumber numberWithDouble:operand]];
}
- (double)performOperation:(NSString *)operation
{
[self.programStack addObject:operation];
return [[self class] runProgram:self.program];
}
+ (double)popOperandOffProgramStack:(NSMutableArray *)stack
{
double result = 0;
return result;
}
+ (double)runProgram:(id)program
{
NSMutableArray *stack;
if ([program isKindOfClass:[NSArray class]]) {
stack = [program mutableCopy];
}
return [self popOperandOffProgramStack:stack];
}
#end
The code is fine an it runs, so the question is, Where is declared popOperandOffProgramStack in the interface? why it compiles and it's okay? it should crash but I can not find an explanation to this....
Thank you!

You only need to declare methods in the #interface in the .h file if you're exposing them to the world. Otherwise, no declaration needed.
And nowadays, the order that they appear in the implementation doesn't matter, either. Historically, if the method was implemented later in the #implementation than where it was invoked, you needed to have the method declared above (generally in the #interface). Now the compiler doesn't care whether the implementation is earlier or later in the .m file.

the compiler can sees its definition:
+ (double)popOperandOffProgramStack:(NSMutableArray *)stack
{
double result = 0;
return result;
}
so it is able to confirm it has been declared, the parameter types, and return type.
also - in older compilers, it would need to precede usage, but not anymore if used in the #implementation scope.
even if it were not declared, objc is weak enough that it would not be a compiler error (warning, perhaps). exception: the method must be visible if you're using ARC. the compiler needs to know the reference counting semantics and parameter types when ARC is enabled.

Related

Making an Integer Array in Objective-C

I want to have an internal int array for my class, but I can't seem to get XCode to let me. The array size needs to be set on initialization so I can't put the size directly into the interface.
At the moment I've been trying:
#interface TestClass : NSObject {
int test[];
}
But it tells me that I'm not allowed. How to I refer to it in my interface, and then how do I allocate it when I create the implementation?
Sorry for a somewhat standard sounding question, but I can't seem to find the answer I need from searching.
edit: I want to use an array because it's apparently much faster than using an NSArray
You can use a number of methods to overcome this problem, but the easiest is to simply make the instance variable a pointer, like this:
#interface TestClass : NSObject {
int *test;
}
#property int *test;
#end
Synthesizing the property will give it getter and setter methods which you can use to set its contents:
#implementation TestClass
#synthesize test;
//contents of class
#end
You can then use it like this:
TestClass *pointerTest = [[TestClass alloc] init];
int *array = (int *)malloc(sizeof(int) * count);
//set values
[pointerTest setTest:array];
[pointerTest doSomething];
However, using objects like NSNumber in an NSArray is a better way to go, perhaps you could do something like this:
#interface TestClass : NSObject {
NSArray *objectArray;
}
#property (nonatomic, strong) NSArray *objectArray;
#end
#implementation TestClass
#synthesize objectArray;
//contents of class
#end
You can then set its contents with a pointer to an NSArray object:
NSArray *items = [NSArray arrayWithObjects:[NSNumber numberWithInt:1], [NSNumber numberWithInt:2], nil];
TestClass *arrayClass = [[TestClass alloc] init];
[arrayClass setItems:items];
[arrayClass doSomething];
When retaining objects upon setting them (like the previous example), always make sure you deallocate the object in the classes dealloc method.
A C array is just a sufficiently sized raw memory buffer. Foundation has a nice wrapper around raw memory that frees you from all the manual memory management: NSMutableData
The following approach gives you automatic memory management plus proper encapsulation.
#interface TestClass : NSObject
#property (nonatomic, readonly) int *testArray;
#property (nonatomic, readonly) NSUInteger testArraySize;
#end
#implementation TestClass
{
NSMutableData *_testData;
}
- (id)initWithSize:(NSUInteger)size
{
self = [self init];
if (self != nil) {
_testData = [NSMutableData dataWithLength:size];
}
}
- (int *)testArray
{
return [_testData mutableBytes];
}
- (NSUInteger)testArraySize
{
return [_testData length];
}
#end
As you see, the ivar does not have to be declared in the #interface.
Try something like this:
#interface TestClass : NSObject
{
int *_test;
}
#property (assign) int *test;
#end
#implementation TestClass
- (instancetype)init
{
if (self = [super init])
{
_test = malloc(sizeof(int) * 20);
}
return self;
}
- (int *)test
{
return _test;
}
- (void)setTest:(int*)test
{
memcpy(&_test, &test, sizeof(_test));
}
- (void)dealloc
{
free(_test);
}
#end

How can I create a wrapper to use blocks for a class that uses callbacks?

I'm diving into iOS programming and I'm learning how to use blocks. I have a sucky, over-engineered library that I'm using in my project and it uses a single callback method to handle all data requests...
#protocol SuckyClassDelegate <NSObject>
-(void)returnedSuckyData:(NSMutableDictionary*)data;
#end
#interface SuckyClass: NSObject
#property (nonatomic, weak) id<SuckyClassDelegate> delegate;
-(void)getSuckyData;
#end
#interface MyViewController: UIViewController <SuckyClassDelegate>
-(void)requestDataFromSuckyClass;
#end
I'd like to create a wrapper class for the SuckyClass that allows me to use blocks when I need to access data from the SuckyClass, but I don't know how to do this. I'd like to have something like this...
#interface SuckyClassWrapper
- (void)requestDataWithSuccessBlock:(void(^)((NSMutableDictionary*)data))successBlock;
#end
#implementation MyViewController
-(void)requestDataFromSuckyClass {
SuckyClassWrapper *wrapper = [[SuckyClassWrapper alloc] init];
[wrapper requestDataWithSuccessBlock:^(NSMutableDictionary *data) {
NSLog(#"%#", data);
}
}
#end
...but I can't figure out how to convert the callback process into blocks. Can anyhow give me some direction here?
Thanks in advance for your wisdom!
By the way, I just whipped up the code without testing it, so I apologize if there are any typos.
The trick is to copy the completion block to a class iVar that you can then call later.
#property (nonatomic, copy) void (^errorHandler)(NSError *);
#property (nonatomic, copy) void (^successHandler)(NSString *);
Here is a method that saves two blocks for use later and then calls another class method:
- (void)methodWithErrorHandler:(void(^)(NSError *error))errorBlock successHandler: (void(^)(NSString *data))successBlock
{
// Copy the blocks to use later
self.successHandler = successBlock;
self.errorHandler = errorBlock;
// Run code
[self doOtherThings];
}
Later - when what we want to do has completed, we have another method that we call to run the blocks. In this silly example code we check to see if a class property self.error is nil. If it is not nil, we send that error to our saved error block. If it is nil, we pass self.data to the success block.
- (void)finishThingsUp
{
// Check to see if we should call the error block or the success block
if (self.error) {
self.errorHandler(self.error);
} else {
self.successHandler(self.data);
}
// Clean up the blocks
self.errorHandler = nil;
self.successHandler = nil;
}
We could use like this:
typedef void (^SuccessDataBlock)(NSMutableDictionary *);
#interface SuckyClassWrapper : NSObject <SuckyClassDelegate>
#property (nonatomic, retain) NSData *inputData;
#property (nonatomic, copy) SuccessDataBlock completionHandler;
+ (id)requestData:(NSData *)data successBlock:(SuccessDataBlock)handler;
#end
#implementation SuckyClassWrapper
#synthesize inputData;
#synthesize completionHandler;
- (id)initWithData:(NSData *)data completionHandler:(SuccessDataBlock)handler
{
self = [super init];
if (self != nil)
{
inputData = [data retain];
self.completionHandler = handler;
}
return self;
}
+ (id)requestData:(NSData *)data successBlock:(SuccessDataBlock)handler
{
return [[[self alloc] initWithData:data completionHandler:handler] autorelease];
}
//implement SuckyClass delegate
- (void)returnedSuckyData:(NSMutableDictionary *)data
{
self.completionHandler(data);
}
#end
Usage:
SuckyClassWrapper *wrapper = [SuckyClassWrapper requestData:data successBlock:^(NSMutableDictionary *successData) {
//your code here
}];

How to hide variables for distributed code

So I've built a few apps and am now trying my hand at building a piece of iPhone code that others can drop into their applications. Question is how do I hide the data elements in an object class header file (.h) from the user?
For example, not sure if people have used the medialets iPhone analytics but their .h does not have any data elements defined. It looks like:
#import <UIKit/UIKit.h>
#class CLLocationManager;
#class CLLocation;
#interface FlurryAPI : NSObject {
}
//miscellaneous function calls
#end
With that header file, they also supply an assembly file (.a) that has some data elements in it. How do they maintain those data elements across the life span of the object without declaring them in the .h file?
I am not sure if it matters but the .h file is only used to create a singleton object, not multiple objects of the same class (FlurryAPI).
Any help would be much appreciated. Thanks
Take a look at this:
Hide instance variable from header file in Objective C
In my header file I'd have:
#interface PublicClass : NSObject
{
}
- (void)theInt;
#end
In my source file I'd have:
#interface PrivateClass : PublicClass
{
int theInt;
}
- (id)initPrivate;
#end;
#implementation PublicClass
- (int)theInt
{
return 0; // this won't get called
}
- (id)init
{
[self release];
self = [[PrivateClass alloc] initPrivate];
return self;
}
- (id)initPrivate
{
if ((self = [super init]))
{
}
return self;
}
#end
#implementation PrivateClass
- (int)theInt
{
return theInt; // this will get called
}
- (id)initPrivate
{
if ((self = [super initPrivate]))
{
theInt = 666;
}
return self;
}
#end
I'm using theInt as an example. Add other variables to suit your taste.
I recommend you to use categories to hide methods.
.h
#import <Foundation/Foundation.h>
#interface EncapsulationObject : NSObject {
#private
int value;
NSNumber *num;
}
- (void)display;
#end
.m
#import "EncapsulationObject.h"
#interface EncapsulationObject()
#property (nonatomic) int value;
#property (nonatomic, retain) NSNumber *num;
#end
#implementation EncapsulationObject
#synthesize value;
#synthesize num;
- (id)init {
if ((self == [super init])) {
value = 0;
num = [[NSNumber alloc] initWithInt:10];
}
return self;
}
- (void)display {
NSLog(#"%d, %#", value, num);
}
- (void)dealloc {
[num release];
[super dealloc];
}
#end
You can't access to the private instance variables via dot notation, but you can still get the value by using [anObject num], though the compiler will generate a warning. This is why our apps can get rejected by Apple by calling PRIVATE APIs.

Objective-C, iPhone SDK basics

OK, this is going to be a stupid question but anyway I have nowhere to ask it except here.
I have two buttons and there must be a switch-case statement performed on tapping any of them.
Of course I can put this statement in each IBAction code block but this code would look terribly.
I tried to put swith-case into a separate method and this is what I have:
.h file
#import <UIKit/UIKit.h>
#interface AppViewController : UIViewController
{
IBOutlet UILabel *someTextLabel;
NSNumber *current;
}
#property (nonatomic, retain) IBOutlet UILabel *someTextLabel;
#property (nonatomic, retain) NSNumber *current;
- (void) switchMethod;
- (IBAction) pressButtonForward;
- (IBAction) pressButtonBack;
#end
.m file
#import "AppViewController.h"
#implementation AppViewController
#synthesize someTextLabel;
#synthesize current;
current = 0;
- (void) switchMethod:current
{
switch((int)current) {
case 0:
//do something
break;
case 1 :
//do something
break;
//etc
default:
//do something
break;
}
}
- (IBAction) pressButtonBack
{
if((int)current == 0) {
current = 6;
}
else {
current--;
}
//here must be a switchMethod performed
}
- (IBAction) pressButtonForward
{
if((int)current == 6) {
current = 0;
}
else {
current++;
}
//here must be a switchMethod performed
}
//auto-generated code here
#end
Of course this code is incorrect but this is just like a blueprint of what I wanted to get.
Questions:
What is a correct way of using such switch-case statement as a separate method so that I could call it from IBAction methods?
How should I cast data types for this code to work, or would it be better to use integer type (for "current" variable) everywhere?
I haven't really got your question but maybe you should switch between forward and backward cases using a method like this :
- (IBAction)pressButton:(id) sender;
and depending on the value of sender, you can maybe switch case between Forward And Backward.
Thus, your code will be maybe more readable and you won't have to duplicate your switch.
N.B. : If your only problem is the duplication of your switch and if you don't want to use my method, I don't understand why you don't call directly your switchMethod in the two functions...
Answer to question 1:
just send a message to a self to invoke the switch method.
Answer to question 2:
NSNumber is an object that wraps a numeric value. To convert an NSNumber to an int:
int myIntValue = [number intValue];
To convert an int to a NSNumber
NSNumber* number = [NSNumber numberWithInt: myIntValue];
However, in your example, it's better to just define current as an int. So your code should look something like this:
#interface AppViewController : UIViewController
{
IBOutlet UILabel *someTextLabel;
unsigned int current;
}
#property (nonatomic, retain) IBOutlet UILabel *someTextLabel;
#property (nonatomic, assign) unsigned int current; // nonatomic might be redundant for POD types
- (void) switchMethod;
- (IBAction) pressButtonForward;
- (IBAction) pressButtonBack;
#end
#implementation AppViewController
#synthesize someTextLabel;
#synthesize current;
//current = 0; this wouldn't compile, in any case it is redundant, ivars start out as 0.
- (void) switchMethod
{
switch(current)
{
// do switchy stuff
}
}
- (IBAction) pressButtonBack
{
if(current == 0)
{
current = 6;
}
else
{
current--;
}
[self switchMethod];
}
- (IBAction) pressButtonForward
{
if(current == 6)
{
current = 0;
}
else
{
current++;
}
[self switchMethod];
}
// etc
#end
NB although I defined a property for current, I haven't used it in the code, which is a bit of a no-no. The main problem is that if anybody decides to observe current using KVO, they won't be notified of the changes. I should really have written things like
switch([self current])...
and
[self setCurrent: 6]...
etc

How to handle Objective-C protocols that contain properties?

I've seen usage of Objective-C protocols get used in a fashion such as the following:
#protocol MyProtocol <NSObject>
#required
#property (readonly) NSString *title;
#optional
- (void) someMethod;
#end
I've seen this format used instead of writing a concrete superclass that subclasses extend. The question is, if you conform to this protocol, do you need to synthesize the properties yourself? If you're extending a superclass, the answer is obviously no, you do not need to. But how does one deal with properties that a protocol requires to conform to?
To my understanding, you still need to declare the instance variables in the header file of an object that conforms to a protocol that requires these properties. In that case, can we assume that they're just a guiding principle? CLearly the same isn't the case for a required method. The compiler will slap your wrist for excluding a required method that a protocol lists. What's the story behind properties though?
Here's an example that generates a compile error (Note: I've trimmed the code which doesn't reflect upon the problem at hand):
MyProtocol.h
#protocol MyProtocol <NSObject>
#required
#property (nonatomic, retain) id anObject;
#optional
TestProtocolsViewController.h
- (void)iDoCoolStuff;
#end
#import <MyProtocol.h>
#interface TestProtocolsViewController : UIViewController <MyProtocol> {
}
#end
TestProtocolsViewController.m
#import "TestProtocolsViewController.h"
#implementation TestProtocolsViewController
#synthesize anObject; // anObject doesn't exist, even though we conform to MyProtocol.
- (void)dealloc {
[anObject release]; //anObject doesn't exist, even though we conform to MyProtocol.
[super dealloc];
}
#end
The protocol is just telling everyone that knows about your class through the protocol, that the property anObject will be there. Protocols are not real, they have no variables or methods themselves - they only describe a specific set of attributes that is true about your class so that objects holding references to them can use them in specific ways.
That means in your class that conforms to your protocol, you have to do everything to make sure anObject works.
#property and #synthesize are at heart two mechanisms that generate code for you. #property is just saying there will be a getter (and/or setter) method for that property name. These days #property alone is enough to also have methods and a storage variable created for you by the system (you used to have to add #sythesize). But you have to have something to access and store the variable.
Here's an example of mine that works perfectly, the protocol definition first of all:
#class ExampleClass;
#protocol ExampleProtocol
#required
// Properties
#property (nonatomic, retain) ExampleClass *item;
#end
Below is a working example of a class supporting this protocol:
#import <UIKit/UIKit.h>
#import "Protocols.h"
#class ExampleClass;
#interface MyObject : NSObject <ExampleProtocol> {
// Property backing store
ExampleClass *item;
}
#implementation MyObject
// Synthesize properties
#synthesize item;
#end
all you have to do really is to drop a
#synthesize title;
in your implementation and you should be all set. it works the same way as just putting the property in your class interface.
Edit:
You may want to do this more specifically:
#synthesize title = _title;
This will fall in line with how xcode's automatic synthesis creates properties and ivars if you use auto-synthesis, so that way if your class has properties from a protocol and a class, some of your ivars won't have the different format which could impact readability.
Suppose I have MyProtocol that declares a name property, and MyClass that conforms to this protocol
Things worth noted
The identifier property in MyClass declares and generates getter, setter and backing _identifier variable
The name property only declares that MyClass has a getter, setter in the header. It does not generate getter, setter implementation and backing variable.
I can’t redeclare this name property, as it already declared by the protocol. Do this will yell an error
#interface MyClass () // Class extension
#property (nonatomic, strong) NSString *name;
#end
How to use property in protocol
So to use MyClass with that name property, we have to do either
Declare the property again (AppDelegate.h does this way)
#interface MyClass : NSObject <MyProtocol>
#property (nonatomic, strong) NSString *name;
#property (nonatomic, strong) NSString *identifier;
#end
Synthesize ourself
#implementation MyClass
#synthesize name;
#end
Example: 2 classes (Person and Serial) want use service of Viewer... and must conform to ViewerProtocol. viewerTypeOfDescription is a mandatory property subscriber classes must conform.
typedef enum ViewerTypeOfDescription {
ViewerDataType_NSString,
ViewerDataType_NSNumber,
} ViewerTypeOfDescription;
#protocol ViewerProtocol
#property ViewerTypeOfDescription viewerTypeOfDescription;
- (id)initConforming;
- (NSString*)nameOfClass;
- (id)dataRepresentation;
#end
#interface Viewer : NSObject
+ (void) printLargeDescription:(id <ViewerProtocol>)object;
#end
#implementation Viewer
+ (void) printLargeDescription:(id <ViewerProtocol>)object {
NSString *data;
NSString *type;
switch ([object viewerTypeOfDescription]) {
case ViewerDataType_NSString: {
data=[object dataRepresentation];
type=#"String";
break;
}
case ViewerDataType_NSNumber: {
data=[(NSNumber*)[object dataRepresentation] stringValue];
type=#"Number";
break;
}
default: {
data=#"";
type=#"Undefined";
break;
}
}
printf("%s [%s(%s)]\n",[data cStringUsingEncoding:NSUTF8StringEncoding],
[[object nameOfClass] cStringUsingEncoding:NSUTF8StringEncoding],
[type cStringUsingEncoding:NSUTF8StringEncoding]);
}
#end
/* A Class Person */
#interface Person : NSObject <ViewerProtocol>
#property NSString *firstname;
#property NSString *lastname;
#end
#implementation Person
// >>
#synthesize viewerTypeOfDescription;
// <<
#synthesize firstname;
#synthesize lastname;
// >>
- (id)initConforming {
if (self=[super init]) {
viewerTypeOfDescription=ViewerDataType_NSString;
}
return self;
}
- (NSString*)nameOfClass {
return [self className];
}
- (NSString*) dataRepresentation {
if (firstname!=nil && lastname!=nil) {
return [NSString stringWithFormat:#"%# %#", firstname, lastname];
} else if (firstname!=nil) {
return [NSString stringWithFormat:#"%#", firstname];
}
return [NSString stringWithFormat:#"%#", lastname];
}
// <<
#end
/* A Class Serial */
#interface Serial : NSObject <ViewerProtocol>
#property NSInteger amount;
#property NSInteger factor;
#end
#implementation Serial
// >>
#synthesize viewerTypeOfDescription;
// <<
#synthesize amount;
#synthesize factor;
// >>
- (id)initConforming {
if (self=[super init]) {
amount=0; factor=0;
viewerTypeOfDescription=ViewerDataType_NSNumber;
}
return self;
}
- (NSString*)nameOfClass {
return [self className];
}
- (NSNumber*) dataRepresentation {
if (factor==0) {
return [NSNumber numberWithInteger:amount];
} else if (amount==0) {
return [NSNumber numberWithInteger:0];
}
return [NSNumber numberWithInteger:(factor*amount)];
}
// <<
#end
int main(int argc, const char * argv[])
{
#autoreleasepool {
Person *duncan=[[Person alloc]initConforming];
duncan.firstname=#"Duncan";
duncan.lastname=#"Smith";
[Viewer printLargeDescription:duncan];
Serial *x890tyu=[[Serial alloc]initConforming];
x890tyu.amount=1564;
[Viewer printLargeDescription:x890tyu];
NSObject *anobject=[[NSObject alloc]init];
//[Viewer printLargeDescription:anobject];
//<< compilator claim an issue the object does not conform to protocol
}
return 0;
}
An other Example with Protocol inheritance over subClassing
typedef enum {
LogerDataType_null,
LogerDataType_int,
LogerDataType_string,
} LogerDataType;
#protocol LogerProtocol
#property size_t numberOfDataItems;
#property LogerDataType dataType;
#property void** data;
#end
#interface Loger : NSObject
+ (void) print:(id<LogerProtocol>)object;
#end
#implementation Loger
+ (void) print:(id<LogerProtocol>)object {
if ([object numberOfDataItems]==0) return;
void **data=[object data];
for (size_t i=0; i<[object numberOfDataItems]; i++) {
switch ([object dataType]) {
case LogerDataType_int: {
printf("%d\n",(int)data[i]);
break;
}
case LogerDataType_string: {
printf("%s\n",(char*)data[i]);
break;
}
default:
break;
}
}
}
#end
// A Master Class
#interface ArrayOfItems : NSObject <LogerProtocol>
#end
#implementation ArrayOfItems
#synthesize dataType;
#synthesize numberOfDataItems;
#synthesize data;
- (id)init {
if (self=[super init]) {
dataType=LogerDataType_null;
numberOfDataItems=0;
}
return self;
}
#end
// A SubClass
#interface ArrayOfInts : ArrayOfItems
#end
#implementation ArrayOfInts
- (id)init {
if (self=[super init]) {
self.dataType=LogerDataType_int;
}
return self;
}
#end
// An other SubClass
#interface ArrayOfStrings : ArrayOfItems
#end
#implementation ArrayOfStrings
- (id)init {
if (self=[super init]) {
self.dataType=LogerDataType_string;
}
return self;
}
#end
int main(int argc, const char * argv[])
{
#autoreleasepool {
ArrayOfInts *arr=[[ArrayOfInts alloc]init];
arr.data=(void*[]){(int*)14,(int*)25,(int*)74};
arr.numberOfDataItems=3;
[Loger print:arr];
ArrayOfStrings *arrstr=[[ArrayOfStrings alloc]init];
arrstr.data=(void*[]){(char*)"string1",(char*)"string2"};
arrstr.numberOfDataItems=2;
[Loger print:arrstr];
}
return 0;
}
The variable, anObject, needs to be defined in your TestProtocolsViewController class definition, the protocol is just informing you that it should be there.
The compiler errors are telling you the truth - the variable doesn't exist. #properties are just helpers after all.