Objective-c refer variable outside of block - objective-c

I'd like to refer variable which I define inside of if block at outside of if else block. How can I? If it can't be, do I have to write same long code (they can't be function or method) inside if block and else block?
if (aTrack.compilation)
{
NSString *artistName = NSLocalizedString(#"compilations", #"");
}
else
{
NSString *artistName = aTrack.artist
}
NSLog(#"%#",artistName);

What #nickfalk and #CRD posted is good but you can also (for such easy statements) use a ternary operator which in this case will look like this:
NSString *artistName = aTrack.compilation ? NSLocalizedString(#"compilations", #""): aTrack.artist;
NSLog(#"%#",artistName);
It is a matter of style but I would go this way for this simple example as my code is in one line

The lifetime of an ordinary (non static) variable declared in a block is just that block, any nested blocks, etc. This is part of the standard lifetime and visibility rules of (Objective-)C(++).
Just declare the variable before the if/else and assign values to it in each block.

This will do what you want:
NSString *artistName;
if (aTrack.compilation){
artistName = NSLocalizedString(#"compilations", #"");
} else {
artistName = aTrack.artist;
}
NSLog(#"%#",artistName);
Also have a look at CRD's reply as this is really basic knowledge and you really need to understand this. (Also, as viperking noticed in my example, there was a terminating semicolon missing in your original code...)
Viperking has a nice example using the the ternary operator. It might be a bit alien at first but is rather nice when you wrap your head around it. a third solution would be
NSString *artistName = aTrack.artist;
if (aTrack.compilation){
artistName = NSLocalizedString(#"compilations", #"");
}
NSLog(#"%#",artistName);
For more complex scenarios I would advice against it, but for an example with two possible cases and one single string it would be quite legible. I'd also advice using nil rather than an empty-string for the localizedString comment.

Related

How to assign the value inside the if condition in vue?

I don't know if vue recognize the syntax below:
if(var error = errors.description){
location.href = "/redirect?topic="+error;
}
The code above returns a compilation error:
ERROR in ./resources/js/forms/Signup.vue?vue&type=script&lang=js& (./node_modules/babel-loader/lib??ref--4-0!./node_modules/vue-loader/lib??vue-loader-options!./resources/js/forms/Signup.vue?vue&type=script&lang=js&)
Someone knows how to assign a variable inside the if else condition?
This is rather a JavaScript syntax issue than Vue. While I highly recommend not assigning within a conditional, you can do so only by either declaring the variable earlier or not explicitly declaring it at all, i.e. by removing the var above.
Here's an example with your above code:
if(error = errors.description){
location.href = "/redirect?topic="+error;
}
To be clear, it is highly recommended not to do the above, or at the very least declare var error earlier so that you don't accidentally modify a global variable, like so:
let error;
if(error = errors.description){
location.href = "/redirect?topic="+error;
}
Of course the most explicit and safe solution to avoid confusion about the assignment is to simply do it earlier:
let error = errors.description;
if (error) {
location.href = "/redirect?topic="+error;
}
There has been some discussion about whether assignment within conditionals is good practice. However, on a completely separate note it is widely agreed that assigning variables that haven't been declared with var, let, or const is dangerous as you could accidentally modify variables of higher scope.

How to Implement a Decision Table in Objective-C

I am a novice programmer, and I've just started reading about decision tables. I have read Chapter 18 in Code Complete and it was very enlightening. I looked around the web to try to find any kind of example of decision tables in Objective-C and I was unable to find any boilerplate or real world examples of how to implement this.
I am programming a game in Objective-C in my spare time, and I have been dealing with increasing complexity for the rules of the game. There are a handful of somewhat deeply nested if-else statements, as well as a few switch statements that already have 10 or more cases to deal with. I think it would be easier to work with decision tables, but I have no idea how to implement this in Objective-C for something non-trivial like the logic of a game.
For example, I need different methods to execute for different combinations of states. How would I implement a decision table in Objective-C that could take different combinations of states as keys, and run specific logic based on the combination of them?
Well I thought about decision tables in Objective-C some more and came up with a solution to implement a basic one. I will not post the entire code here, just the snippets that make the decision table work and their basic purpose. I posted this over at Code Review SE if you want to see the full code and some great suggestions for how to improve it. I'm posting this now because someone posted a comment requesting that I do so, but I will definitely end up improving this and integrating the suggestions from the review. Anyway, here is the code.
First before the initialization method I establish a number of NSString constants that will be used as the keys in an NSDictionary.
//Two options for the decision table, either access the dictionary directly with 0-x, the enum values, or make strings for their names
//the advantage of strings is that it is more extensible, and the position in the enum doesnt matter
NSString* const kEnemyMovementStateJustSpawned = #"enemyMovementStateJustSpawned";
NSString* const kEnemyMovementStateIdle = #"enemyMovementStateIdle";
NSString* const kEnemyMovementStateNeedsMoving = #"enemyMovementStateNeedsMoving";
NSString* const kEnemyMovementStateToFloor = #"enemyMovementStateToFloor";
NSString *const kEnemyMovementStateAtDestinationFloor = #"enemyMovementStateAtDestinationFloor";
NSString* const kEnemyMovementStateToFloorExit = #"enemyMovementStateToFloorExit";
NSString* const kEnemyMovementStateToAttackWalls = #"enemyMovementStateToAttackWalls";
NSString* const kEnemyMovementStateToAttackFloor = #"enemyMovementStateToAttackFloor";
NSString* const kEnemyMovementStateToAttackRoom = #"enemyMovementStateToAttackRoom";
Then I use these constants along with the names of methods in the class to build the NSDictionary:
-(void) setupDecisionTable {
//the string objects are the names of methods in the class
_decisionTable = #{kEnemyMovementStateJustSpawned: #"doEnemyJustSpawned",
kEnemyMovementStateIdle: #"doEnemyIdle",
kEnemyMovementStateNeedsMoving: #"doEnemyNeedsMoving",
kEnemyMovementStateToFloorExit: #"doFloorMovement",
kEnemyMovementStateToFloor: #"doVerticalMovement",
kEnemyMovementStateAtDestinationFloor: #"doEnemyAtDestinationFloor",
kEnemyMovementStateToAttackWalls: #"doFloorMovement",
kEnemyMovementStateToAttackFloor: #"doFloorMovement",
kEnemyMovementStateToAttackRoom: #"doFloorMovement"
};
}
Then every tick I call this method, which executes the method with the name of the object pulled from the dictionary:
-(void) doMovement {
//the selector is formed from a string inside the decision table dictionary
SEL methodToCallName = NSSelectorFromString([_decisionTable objectForKey:[self stringForState:self.state]]);
if (methodToCallName) {
IMP functionPointer = [self methodForSelector:methodToCallName];
void (*methodToCall)(id, SEL) = (void *)functionPointer;
methodToCall(self, methodToCallName);
}
}
-(NSString *) stringForState:(EnemyMovementState)state {
switch (state) {
case EnemyMovementStateJustSpawned:
return kEnemyMovementStateJustSpawned;
case EnemyMovementStateIdle:
return kEnemyMovementStateIdle;
case EnemyMovementStateNeedsMoving:
return kEnemyMovementStateNeedsMoving;
case EnemyMovementStateToFloor:
return kEnemyMovementStateToFloor;
case EnemyMovementStateAtDestinationFloor:
return kEnemyMovementStateAtDestinationFloor;
case EnemyMovementStateToFloorExit:
return kEnemyMovementStateToFloorExit;
case EnemyMovementStateToAttackWalls:
return kEnemyMovementStateToAttackWalls;
case EnemyMovementStateToAttackFloor:
return kEnemyMovementStateToAttackFloor;
case EnemyMovementStateToAttackRoom:
return kEnemyMovementStateToAttackRoom;
default:
return nil;
}
}
Finally here are a couple of the methods that execute, just for a complete example:
-(void) doEnemyIdle {
if ([self checkFloorsForJobs]) {
self.state = EnemyMovementStateNeedsMoving;
} else {
[self doIdleMovement];
}
}
-(void) doEnemyNeedsMoving {
[self calculateFloorExitPositionByFloor];
self.state = EnemyMovementStateToFloorExit;
}
This is a pretty simple implementation. Currently it can only deal with one input, and a better decision table would be able to evaluate multiple inputs and provide the proper output. I think it could be extended by having an intermediate method that took the state combined with other variables to choose the proper object from the dictionary.
After doing all this, I'm not sure that decision tables are worth the effort in Objective-C. I do not know if the code is easier to understand than a switch statement. In order to add new logic to the code, it has to be modified in more places than a switch statement would seem to require. I provide this code as an example, and it would be cool to see other versions of decision tables in Objective-C if anyone has one.

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.

Passing and recieving multi-dimensional primitive (int) arrays in objective-c

I have two objective c methods. One needs to return an int[][] and the other which needs to take int[][] as a parameter. I was originally using an NSMutableArray with NSMutableArrays as values however I was told to redo it like this in order to be compatible with some current code. I can't figure out how to make this work. I'm not sure I'm even googling the right thing. Anyway here is what I have now.
+(int [][consantValue]) getCoefficients
{
int coefficiennts [constantValue2][constantValue1] = { {0,1,2}, {3,4,5}, {6,7,8} };
return coefficients;
}
At the return statement I get the Error "Array initilizer must be an initializer list'
I also have to take the int[][] and rebuild it into an NSMutableArray of NSMutableArrays in another method but I'm hoping if someone can give me a hint on the first part I can work the second part out myself although if anyone has any advice on that I would appreciate it as well. Thanks.
The easy way to do this for fixed size array(s) is to use a struct for storage:
typedef struct {
int at[constantValue2][constantValue1];
} t_mon_coefficients;
And then you'd declare the method which returns by value:
+ (t_mon_coefficients)coefficients;
And passes by value as a parameter:
- (void)setCoefficients:(const t_mon_coefficients)pCoefficients;
If the struct is large, you should pass by reference:
// you'd use this like:
// t_mon_coefficients coef;
// [SomeClass getCoefficients:&coef];
+ (void)getCoefficients:(t_mon_coefficients* const)pOutCoefficients;
- (void)setCoefficients:(const t_mon_coefficients*)pCoefficients;
But there are multiple ways one could accomplish this.

indexOfObject does not match correctly

I've been stuck with this problem from a couple of days and I can't get myself out of it.
I've searched all over the net, but I couldn't find anything useful to solve my issue.
this is the scenario.
I've got an array of strings containing a bunch of ids fetched from a coredata sqlite db and
I'd like to know the index of a certain element into this array.
My first solution would have been as easy as using indexOfObject
-(NSInteger) getPageId:(NSString *)symbol_id {
NSInteger refId = [myIds indexOfObject:symbol_id];
// .. stuff ..
return refId;
}
now, I don't know why, but the returning value of the function is always NSNotFound.
If I print out the values via NSLog
NSLog(#"%#\n%#", myIds, symbol_id);
I can clearly see that the value I'm searching for figures out into the elements of the array.
I've even tried a dumbest solution, like probing the match via isEqual function into a for loop:
int idx = 0;
for(NSString *tok in myIds) {
if([tok isEqual:synmbol_id])
{
NSLog(#"yay, a match was encountered!!");
return idx;
}
idx++;
}
but the execution never gets into the NSLog.
I dunno where to knock my head.
hope that some of you already figured this out and could explain this to me.
thx in advance
k
Try printing all the elements on the array like this:
for(NSString *tok in myIds) {
NSLog(#"On the array [%#]", tok);
}
Maybe there is a TAB \t, an ENTER \n or something weird in your NSString preventing isEqual message to run as expected. Usually these characters are hard to find on a regular debugger. That's why I'am suggesting to enclose the string in [].