How do you do pointers to pointers in Swift? In Objective-C I had a function which I would call recursively so that I could keep track of the number of recursions, but I'm stumped as to how to achieve this in Swift.
NSNumber *recursionCount = [NSNumber numberWithInteger:-1];
[self doRecursion:&recursionCount];
- (void)doRecursion:(NSNumber **)recursionCount {
// I'm sure this is a terrible way to increment, but I have limited Objective-C experience
// and this worked, so I moved on after failing to find a decent var++ equivalent :-(
int addThis = (int)i + 1;
*recursionCount = [NSNumber numberWithInt:[*recursionCount intValue] + addThis];
[self doRecursion:recursionCount];
}
In the process of cutting this sample down for this post, I've ended up creating a never-ending loop, but you get the idea on how I'm remembering the value with each recursion.
Does anybody know how to do this in Swift? Thanks.
Usage of pointers in swift is highly discouraged.
To change a variable passed as argument to a function, you have to pass it by reference (similar to passing its pointer) using the inout modifier. I've changed the logic of your function to stop after 10 iterations:
func doRecursion(inout recursionCount: Int) -> Int {
if (recursionCount < 10) {
++recursionCount
doRecursion(&recursionCount)
}
return recursionCount
}
Then you can call using:
var counter: Int = -1
let x = doRecursion(&counter) // Prints 10 in playground
Suggested reading: In-Out Parameters
Related
I used a framework Objective-C in my Project (Swift). But in the code have a Block, i cannot convert to swift (i'm newbie in swift)
So the code is
[self.datePicker setDateHasItemsCallback:^BOOL(NSDate *date) {
int tmp = (arc4random() % 30)+1;
return (tmp % 5 == 0);
}];
Please help me.
Thank you ,
Where you would use a block in Objective-C, you use a function in Swift. In Objective-C, the argument is a block that takes an NSDate and returns a BOOL:
[self.datePicker setDateHasItemsCallback:^BOOL(NSDate *date) {
So, in Swift the argument is a function that takes an NSDate and returns a Bool:
self.datePicker.setDateHasItemsCallback {
(date:NSDate) -> Bool in
return true // fix this up as desired
}
Merry Christmas everybody :)
I have a pointer problem. Although I´m familiar with pointer concepts I haven´t used pointers in Objective-C so far the way it´s described here.
I modified it like this:
int countSInteger = 10;
[self setHMSValues:countSInteger];
- (void) setHMSValues: (int*) timeCat {
*timeCat = *timeCat - 1;
}
But now I´receiving a EXC_BAD_ACCESS:
Any Santa hints?
Greetings from Switzerland, Ronald Hofmann
It looks like you want setHMSValues: to calculate and return a value for the integer parameter. However, the parameter is a pointer to an int (int *), and you're passing a plain int with the value of 10. Because pointers are just integer values themselves (with the integer value representing a memory address), the code is trying to set the value at memory location 10; hence, you get a "bad access" error because your program cannot access or change values at memory location 10.
What you should do is pass the address of countSInteger to the method:
[self setHMSValues:&countSInteger];
However, there's a better way to do this. Since you're returning only one value from the method, there's no need for an out parameter. You can change your method to this:
- (int) setHMSValues: (int) timeCat {
return timeCat - 1;
}
and call it like this:
int countSInteger = 10;
countSInteger = [self setHMSValues:countSInteger];
Try:
- (void) setHMSValues: (int*) timeCat {
*timeCat = *timeCat - 1;
}
"countInteger" is declared as an "int *" while the method you're calling into is expecting an "int".
Don't you think you might have better luck if you declare "countInteger" as a plain "int"?
Why use int pointers? Just remove the *
Does Objective-C support pass by reference using & like C++? I haven't checked Objective-C specifically, (never had the need) but in C++ the following is used to tell the compiler to use pass-by-reference:
void count(int &var);
Is there any way to do the following at compile-time?
int anInteger = 0;
__if_object(anInteger) {
// send object some messages
}
__if_primitive(anInteger) {
// do something else
}
An dummy situation where this could be used is to define the __add_macro below.
#define __add_macro(var, val) __something_goes_here__
int i = 1;
MyInteger* num = [[MyNumber alloc] initWithValue:1]
__add_macro(i, 4);
__add_macro(num, 4);
// both should now hold 5
Clarification/Simplification
I guess there is no way to do this with one macro. But I still need it to warn if the macro is being used on the wrong datatype. Those two types are: object and non-object).
To check if it is an object, this works:
#define __warn_if_not_object(var) if(0){[(var) class];}
What I need:
#define _warn_if_object(var) if(0){__something_here__}
Again, I need this to happen at compile-time. And it can either throw an error or warning.
Thanks
When you declare an int variable you can really only put an int value in it.
While this is Objective-C, and hence C, so you can bypass just about every type protection mechanism that exists, this is not to be advised. Indeed there is no guarantee whatsoever that a, say, NSNumber reference will even fit into an int variable - and more than enough chance that if you try, and bypass any warnings, some bits will just get tossed making the reference invalid.
So, no, while you can tell what class an object reference refers to, you cannot in general tell whether a variable has an integer value or an object reference in it - you shouldn't even try to put these two very different things into the same variable.
Answer 2
Patrick, your comments and clarification seem to suggest you are not trying to do what the question starts out by asking (how do you determine if the value in an int is an object - answered above, you don't), but something rather different...
I think what you're after is function overloading, and as you seem to be trying to use macros, maybe inline functions as well. Clang supports function overloading, here is program fragment which may show you how to solve your problem:
// Clang likes prototypes so let's give it some
// The following declares two overloaded inline functions:
NS_INLINE void __attribute__((overloadable)) byType(int x);
NS_INLINE void __attribute__((overloadable)) byType(NSNumber *x);
// now some simple definitions:
NS_INLINE void __attribute__((overloadable)) byType(int x)
{
NSLog(#"int version called: %d", x);
}
NS_INLINE void __attribute__((overloadable)) byType(NSNumber *x)
{
NSLog(#"NSNumber version called: %#", x);
}
// now call them, automatically selecting the right function
// based on the argument type
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification
{
int x = 5;
NSNumber *y = [NSNumber numberWithInt:42];
byType(x);
byType(y);
}
The above code when run outputs:
int version called: 5
NSNumber version called: 42
Clang 3 compiles the above code inlining the two calls, so you get the same code as using macros.
please don't mix between scalar values and pointers to objects... it will not end well.
if you insist you can do something with Objective-C++
something like
int sum(int,int);
NSNumber * sum(NSNumber *, NSNumber *);
I've started using blocks, and one of the first things I encountered is an inability to set values which are captured by the closure. This is fine, I've been using C/C++ a long time. I'll just use pointers!
MyObject* bestObj = nil;
float bestDist= 10000.f;
MyObject **pBestObj = &bestObj;
float* pBestDist = &bestDist;
[self testObjects:class block:^(MyObject* obj){
CGRect r = [obj boundingBox];
// position is captured from outside this code sample
if( CGRectContainsPoint( r, position ) )
{
float dist = GetDistance( obj, position );
if(dist < bestDist)
{
*pBestDist = dist;
*pBestObj = obj;
}
}
}];
return bestObj;
My question is, is this safe? I assume that as long as my pointer points to something that hasn't gone out of scope and that still exists, that it should work. But I'm also assuming that things that take blocks don't ever, say, run them in parallel. I know my code doesn't, but I don't know about, say, using a block with an NSArray enumerateObjectsUsingBlock call.
The 'right' way to do this would be to mark those original variables as block mutable, __block
- (void) swapController:(MyViewController*)controller1
with:(MyViewController*)controller2
{
MyViewController *swap = controller2;
controller2 = controller1;
controller1 = swap;
}
Looks like this doesn't work because I'm not passing references. How to do it anyway?
You can do this by passing in pointers to the pointers you want to change:
- (void)swapController:(MyViewController**)controller1 with:(MyViewController**)controller2
{
MyViewController* swap = *controller2;
*controller2 = *controller1;
*controller1 = swap;
}
Not looking for this as an opposing answer here, but rather to complement #Huw's answer.
On implementing his swapController:with: method above, I noticed some issues with ARC and with primitives. ARC will take issue if you're passing a strong id* to an id* ( which it will designate as autoreleased id and other fun warnings).
If you're anything like me, well, one fine day you'll be swapping pointers back and forth in objc and one of those values will be a primitive data type.
If you do end up doing something like that, here's a little helper (like I said earlier) to complement the above answer:
void swapObjcPointerWithC ( void** ptrA, void** ptrB ) {
void *temp = *ptrA;
*ptrA = *ptrB;
*ptrB = temp;
}
...
// Later on
id objA;
int anInt = 10;
swapObjcPointerWithC ( (void*)&objA, (void*)&anInt );
There you go. My two cents.
Note: also works will nil pointers apparently.