Overriding a setter method, and getting info out - objective-c

I have a setter method (setMinimumNumberOfSides) that I want to override after using synthesize. In it, I'm putting in a constraint on the instance variable to make sure the int is within certain bounds.
Later in a custom init method, I'm setting another instance variable (numberOfSides), but I need to make sure minimumNumberOfSides and maximumNumberOfSides was set properly within bounds. I tried changing the return value on the setter to a BOOL, so I could pass back a YES or NO if it succeeded/failed, but that created a conflicting method, I'm guessing because I'm using synthesize and overriding the setter.
How can I get the info out easily to check to see if the setter was called and returned successfully?
-(void)setNumberOfSides:(int)sides
{
if ((sides < maximumNumberOfSides) && (sides > minimumNumberOfSides))
{
numberOfSides = sides;
}
else
NSLog (#"Invalid number of sides: %d is outside the constraints allowed", sides);
}
-(void)setMinimumNumberOfSides:(int)minimum
{
if (minimum > 2)
minimumNumberOfSides = minimum;
}
-(void)setMaximumNumberOfSides:(int)maximum
{
if (maximum <= 12)
maximumNumberOfSides = maximum;
}
-(id)initWithNumberOfSides:(int)sides minimumNumberOfSides:(int)min maximumNumberOfSides:(int)max
{
if (self = [super init])
{
self.minimumNumberOfSides = min;
self.maximumNumberOfSides = max;
self.numberOfSides = sides;
}
return self;
}

You don't have to synthesize numberOfSides if you're planning on implementing the getter and setter. Without #synthesize numberOfSides you can return a BOOL if you choose. You'll need to declare the getter/setter in your interface accordingly.
BTW, another approach would be to use the synthesized getter/setter and add a separate method -(BOOL)isNumberOfSidesValid which performs this check.

In a situation like this, you may be better off using a simple call to assert(), or throwing an exception.
The choice will depend on how you see this class being used. If it will be part of a library, and you expect other developers to frequently supply incorrect values for minimumNumberOfSides or maximumNumberOfSides, you should probably throw a proper exception.
A word of warning, though. If you expect the users of your application to frequently supply incorrect values, then an exception is a bad idea. Exception handling in Objective-C is an expensive operation. If these checks are in place for the sake of the user, you should perform input validation, and report errors to the user in a much more friendly manner.
edit: Here is some quick sample code:
-(void)setMinimumNumberOfSides:(int)minimum
{
if (minimum <= 2)
{
[NSException raise:#"invalid minimumNumberOfSides value"
format:#"value of %d is too low (must be > 2)", minimum];
}
minimumNumberOfSides = minimum;
}
edit: Here is another SO question that goes into detail about exception handling in Objective-C.

Related

Is the return statement and the end if the method required if the method return value is void?

If I have for example this piece of code:
- (void)doSomething
{
// do whatever the method has to do
return;
}
I know that the return is not required for the app to keep running. It seems to be smart enough to know that the method has finished. My question is: Does the absence of the return have negative side effects? (e.g. a memory leak)
Of course not, return has no meaning in void methods except if you wanna return early based on condition or failure to stop execution rest of method.

When to 'return' in an Objective-C method

Just a quick question. I was just wandering whether or not, I still have to "return;" even in a void function?
At the moment, even in methods which are not returning a variable/etc... I still have "return" at the end of the method.
So do I still need this? Because I swear without it, it does NOT return to where it was called from.
EG:
-(void)viewDidLoad {
[super viewDidLoad];
// Run other setup code....
// Run method 1.
[self method_01];
// Run next bit of code....
}
-(void)method_01 {
// Run code....
return;
}
Do I still have to do it like the above example?
Thanks for your time, Dan.
If the return is at the end of the method, it doesn't make any difference.
-(void) doSomethingWithX:(int) X
{
..........................
........some Code.........
..........................
return ;
}
The control would reach the caller one the method execution completes. Marking a return does the same.
However in a condition like below,
-(void) doSomethingWithX:(int) X
{
if(X>10)
{
return;
}
..........................
........some Code.........
..........................
}
The some code will not be executed if your X value is greater than 10. So, by default control return to the caller at the end of method. Use return if you want to force a return to caller in between the method execution.
You do not. The method will return to its previous point of execution once it reaches the end of the current scope.
You do not need to call return in methods that are defined with void and thus do not return a value.
There are times when you would want to call return in such methods, such as if you want to exit out of the method without executing the remaining code, if a particular condition is met:
if (iHaveDeterminedIAmFinished) {
return;
}
... // code that would otherwise execute.
Other than this, it would be bad practice to routinely include return at the end of every method. Every Objective-C method returns without exception, if it reaches the end of the method without a previous return. Therefore, this practice would not be more clear to a reader who has any familiarity with Objective-C. Indeed, it would likely confuse other developers reading your code who would be left wondering what the intention was. It would be likely to appear like something had been omitted from the end of the method, since there would be no reason for including this return otherwise. In short, I suggest it would be bad practice to include unnecessary return calls at the end of methods.
Because I swear without it, it does NOT return to where it was called from.
Something else is going on here. You may well need to figure out what it is, but it is not correct that the absence of return calls would prevent a return to the point of execution. Either it is returning, and you're not realising it for some reason, or something else is happening in your code.
You can do it either way. It should return automatically without an explicit return.

How to enforce parameters of anonymous blocks to be unused in Objective-C?

I've run into a situation while using a library called TransitionKit (helps you write state machines) where I am want to supply entry and exit actions in the form of a callback.
Sadly, the callbacks include two completely useless parameters. A typical block has to look like this:
^void (TKState *state, TKStateMachine *stateMachine) {
// I TOTALLY don't want parameters `state` or `stateMachine` used here
};
(this is an anonymous code block. Read up on blocks here if you're unclear)
As I've noted in the comment, I really don't want those parameters even mentioned in the body there. I've tried simply removing the parameter names like suggested in this question like so:
^void (TKState *, TKStateMachine *) {
// I foobar all I like here
};
but sadly the code won't compile then :(.
How can I enforce this non-usage of parameters in code?
This is what I could come up with. Quite a hack and relies on the GCC poison pragma, which is not standard but a GNU extension - although, given that you are probably compiling this with clang anyway, it should not be a problem.
#define _state state
#define _stateMachine stateMachine
#pragma GCC poison state stateMachine
Then this compiles:
^(TKState *_state, TKStateMachine *_stateMachine) {
do_something();
}
But this doesn't:
^(TKState *_state, TKStateMachine *_stateMachine) {
do_something(state, stateMachine);
}
You could just have a function that took one kind of block, and returned another, like this:
#class TKState, TKStateMachine; // here so this will compile
typedef void (^LongStateBlock)(TKState *state, TKStateMachine *stateMachine);
static inline LongStateBlock Adapter(void(^block)()) {
void(^heapBlock)() = [block copy]; // forces block to be on heap rather than stack, a one-time expense
LongStateBlock longBlock = ^(TKState *s __unused, TKStateMachine *sm __unused) {
heapBlock();
};
// this is the non-ARC, MRR version; I'll leave ARC for the interested observer
[heapBlock release];
return [[longBlock copy] autorelease];
}
And in practice:
// this represents a library method
- (void)takesLongStateBlock:(LongStateBlock)longBlock
{
// which hopefully wouldn't look exactly like this
if (longBlock) longBlock(nil, nil);
}
- (void)yourRandomMethod
{
[self takesLongStateBlock:^(TKState *state, TKStateMachine *stateMachine) {
NSLog(#"Gratuitous parameters, AAAAHHHH!");
}];
[self takesLongStateBlock:Adapter(^{
NSLog(#"So, so clean.");
})];
}
The whole thing is gisted, and should compile inside any class. It does what you expect when you call -yourRandomMethod.
AFAIK there is no way to do what you want when you are creating a block, you can only miss the parameter names when you are declaring a block variable(a reference to a block, to avoid misunderstandings)
So here you can miss the param names:
void (^myBlock)(SomeClass *);
But not when you create a block:
myBlock = ^(SomeClass *o)
{
};
I'd write
^void (TKState *unused_state, TKStateMachine *unused_stateMachine) {
// Anyone using unused_state or unused_stateMachine gets what they deserve.
};
Of course someone can use the parameters. But then whatever you do, they can change the code. If someone is intent on shooting themselves in the foot, there is no stopping them.

Objective-C Blocks, Recursion Fails

Sup guys,
I'm trying to do a function that calls itself but by putting everything on one block,
As you can see, the following function is intended to be called an indefinite amount of times (until arcrandom returns a number lower than 50) and you should expect as an output a variable number of "RUNNING" messages, depending on chance.
void (^_test_closure)(void) = ^ {
NSLog(#"RUNNING");
if(arc4random() % 100 > 50) {
_test_closure();
}
};
_test_closure();
However, when running it, I get an EXC_BAD_ACCESS error and the reason I've found is that when the code tries to calls _test_closure inside of the closure it basically points to nowhere.
Does anyone know how to make the above code work?
You have to declare your block itself as a block variable:
__block void (^_test_closure)();
_test_closure = ^{
NSLog(#"Running...");
if ((arc4random() % 100) > 50) {
_test_closure();
}
}
_test_closure();
Recursion and blocks is tricky. Because a block captures all variables passed in, the variable _test_closure is not initialized yet (and clang should give you a warning:
Block pointer variable '_test_closure' is uninitialized when captured by block
).
There are several ways you can get around this, but the most obvious & simplest is to just make the block itself a __block variable (what #H2CO3 said). This allows the block to be weak-linked almost, so that when you call it again, it is properly initialized.
Another option you have is making the block a global or static, like this:
// outside of 'main', thus being a global variable
void (^blockRecurse)(int) = ^(int level) {
if (level < 0)
return;
NSLog(#"Level: %i", level);
blockRecurse(--level);
};
int main()
{
#autoreleasepool {
blockRecurse(10);
}
}
This means it's not being captured by the block, but instead it's referencing the global / static variable, which can be changed by all code equally.
It works with XCode 5 - no warnings, no retain cycles:
typedef void(^blockT)();
blockT block1;
blockT __block block1recursive;
block1recursive = block1 = ^(){
block1recursive();
};
block1();

Binary Tree in Objective-C

I am learning algorithms and data structures and to train I am trying to design and implement a binary tree using objective-c.
So far I have the following Classes:
main - for testing
Node - node of tree
BinaryTree - for all methods related to the tree
One of the first methods in BinaryTree class I implemented is insertNode:forRoot:.
- (void)insertNodeByRef:(Node **)node forRoot:(Node **)root{
if (head == NULL) {
head = *node;
}
// Case 2 root is null so can assign the value of the node to it
if (root == NULL) {
root = node;
} else {
if (node.data > root.data) { // to the right
[self insertNode:node forRoot:root.right];
} else if (node.data < root.data) { //or to the left
[self insertNode:node forRoot:root.left];
}
}
}
Where the interface of Node class looks like:
#interface Node : NSObject
#property(nonatomic, assign) int data;
#property(nonatomic, strong) Node * right;
#property(nonatomic, strong) Node * left;
#end
My problem is that I don't know how to access the Node class member variables if I am passing Node as a reference. Whenever I try to access the node properties (like data, left or right) I am getting the following error message:
Member reference base type 'Node *__autoreleasing *' is not a structure or union
So my questions is:
how can I access those properties (data, left or right) and use them to store either int data or reference to another Node?
Hope it makes sense. Thanks!
Your code is mixing two common approaches to the task, hence the problem. You are also using an abstract data type (ADT) type approach, rather than an object-oriented one, so there are three approaches to consider.
In both ADT approaches your tree is represented by a reference to its root, in Objective-C this is probably stored in an instance variable:
Node *TreeRoot;
Note also that both of these algorithms use field references, a->b, rather than property references, a.b - this is because the former references a variable and the second algorithm requires passing a reference to a variable.
Functional ADT: Pass-by-value and assign result
In this approach a node is inserted into a tree and a modified tree is returned which is assigned back, e.g. the top-level call to insert a Node nodeToInsert would be:
TreeRoot = insertNode(nodeToInsert, TreeRoot);
and the insertNode function looks like:
Node *insertNode(Node *node, Node *root)
{
if(root == nil)
{ // empty tree - return the insert node
return node;
}
else
{ // non-empty tree, insert into left or right subtree
if(node->data > root->data) // to the right
{
root->right = insertNode(node, root->right);
}
else if(node->data < root->data)//or to the left
{
root->left = insertNode(node, root->left);
}
// tree modified if needed, return the root
return root;
}
}
Note that in this approach in the case of a non-empty (sub)tree the algorithm performs a redundant assignment into a variable - the assigned value is what is already in the variable... Because of this some people prefer:
Procedural ADT: Pass-by-reference
In this approach the variable holding the root of the (sub)tree is passed-by-reference, rather than its value being passed, and is modified by the called procedure as needed. E.g. the top-level call would be:
insertNode(nodeToInsert, &TreeRoot); // & -> pass the variable, not its value
and the insertNode procedure looks like:
void insertNode(Node *node, Node **root)
{
if(*root == nil)
{ // empty tree - insert node
*root = node;
}
else
{ // non-empty tree, insert into left or right subtree
Node *rootNode = *root;
if(node->data > rootNode->data) // to the right
{
insertNode(node, &rootNode->right);
}
else if(node->data < rootNode->data)//or to the left
{
insertNode(node, &root->left);
}
}
}
You can now see that your method is a mixture of the above two approaches. Both are valid, but as you are using Objective-C it might be better to take the third approach:
Object-Oriented ADT
This is a variation of the procedural ADT - rather than pass a variable to a procedure the variable, now called an object, owns a method which updates itself. Doing it this way means you must test for an empty (sub)tree before you make a call to insert a node, while the previous two approaches test in the call. So now we have the method in Node:
- (void) insert:(Node *)node
{
if(node.data > self.data) // using properties, could also use fields ->
{
if(self.right != nil)
[self.right insert:node];
else
self.right = node;
}
else if(node.data < rootNode.data)
{
if(self.left != nil)
[self.left insert:node];
else
self.left = node;
}
}
You also need to change the top level call to do the same test for an empty tree:
if(TreeRoot != nil)
[TreeRoot insert:nodeToInsert];
else
TreeRoot = nodeToInsert;
And a final note - if you are using MRC, rather than ARC or GC, for memory management you'll need to insert the appropriate retain/release calls.
Hope that helps you sort things out.
First of all, don't write your methods to take Node **. It's just confusing.
Second, think about how it should work. Describe to yourself how it should work at a pretty abstract level. Translate that description directly into code, inventing new (not-yet-written!) messages where necessary. If there are steps you don't know how to do yet, just punt those off to new messages you'll write later. I'll walk you through it.
Presumably you want the public API of BinaryTree to include this message:
#interface BinaryTree
- (void)insertValue:(int)value;
So how do you implement insertValue:? Pretend you're the BinaryTree object. What's your high-level description of what you need to do to insert a value? You want to create a new Node. Then you want to insert that new Node into yourself. Translate that description directly into code:
#implementation BinaryTree {
Node *root_; // root node, or nil for an empty tree
}
- (void)insertValue:(int)value {
Node *node = [[Node alloc] initWithData:value];
[self insertNode:node];
}
Now think about how you do the inserting. Well, if you are an empty tree, your root_ is nil and you can just set it to the new node. Otherwise, you can just ask your root node to insert the new node under himself. Translate that description directly into code:
- (void)insertNode:(Node *)node {
if (root_ == nil) {
root_ = node;
} else {
[root_ insertNode:node];
}
}
Now pretend you're a Node. You've been asked to insert a new Node under yourself. How do you do it? You have to compare the new node's value to your value. If the new node's value is less than your value, you want to insert the new node on your left side. Otherwise, you want to insert it on your right side. Translate that description directly into code:
#implementation Node
- (void)insertNode:(Node *)node {
if (node.data < self.data) {
[self insertNodeOnLeftSide:node];
} else {
[self insertNodeOnRightSide:node];
}
}
Now you're still a Node, and you've been asked to insert a new node on your left side. How do you do it? Well, if you don't have a child on your left side yet, just use the new node as your left child. Otherwise, you ask your left child to insert the new node under himself. Translate that description directly into code:
- (void)insertNodeOnLeftSide:(Node *)node {
if (self.left == nil) {
self.left = node;
} else {
[self.left insertNode:node];
}
}
I'll leave the implementation of insertNodeOnRightSide: as an exercise for the reader. ;^)
Your code, in my opinion, has a lot of logic errors. Maybe consider reviewing what a pointer-to-pointer is to insure you're designing the desired effect. Likewise, you need to dereference node/root to access them in normal state. Otherwise, the error is valid, Node** is not type of structure or union.
(Node **)node is a pointer to an object pointer so node.something is invalid because you are a reference to far away from the object.
But (*node).something will work.
Addition for comments :
When you originally call this method : -(void)insertNodeByRef:(Node **)node forRoot:(Node **)root how do you call it?
From the error you've post in your comment it look to me that you are doing :
Node *n = [[Node alloc] init];
[aNode insertNodeByRef:n forRoot:aRoot];
when your method signature state that you need to call it like this :
[aNode insertNodeByRef:&n forRoot:&aRoot];
To pass the address of the pointer to the object.
I'm saying this because your error is now stating that your are sending Node * instead of Node ** which are 2 different thing. (( Incompatible pointer types sending 'Node *' to parameter of type 'Node **' ) I've remove the __autoreleasing between the 2 *, it was obscuring the error message.)
So in other word you are passing a pointer to an object when your method is asking for a pointer TO A pointer to an object.