Adding integer values as contents of an array,iphone - iphone

I need to store some integer values as the contents of an array. But when i try to do so, it throws a warning,
passing argument 1 of 'addObject' makes pointer from integer without a cast.
And obviously the value is not stored in the array.
Here's thecode.
NSUInteger i;
for (i=0;i<5;i++){
[array addObject:i];}

NSArray-s cannot store non-id objects. You have to box it into an NSNumber:
NSUInteger i;
for (i=0;i<5;i++) {
[array addObject:[NSNumber numberWithUnsignedInteger:i]];
}
or use a CFArray with custom callbacks (but you sacrifice readability for performance), or use std::vector<NSUInteger> (but you need to use Objective-C++).

Related

What type of arguments does [NSString stringWithFormat] take?

I know that the method stringWithFormat is usually used as follows:
[NSString stringWithFormat: #"%# %#", arg1, arg2];
My question is, what exactly is the type of the last argument of this method (the one with ... in the specs).
I want to be able to do something like the following:
NSArray *array = [NSArray arrayWithObjects: #"Hi", #"Bob"];
[NSString stringWithFormat: #"%# %#", array]
As you can see one datastructure array is holding all of the arguments. Unfortunately, this doesn't work. Is there a way to do this so that I don't have to explicitly list out all of my arguments in the stringWithFormat method?
What type of arguments does [NSString stringWithFormat] take?
Whatever type you tell it to do so using its format string.
My question is, what exactly is the type of the last argument of this method
That's not the last argument. This is a concept called a "variadic function" (or method, in this case). The ... indicates that the function can take any number of arguments. This is a feature of C, and you can use it by using the types, macros and functions from the C standard library header <stdarg.h>. Example: this creates an array with the objects given.
- (NSArray *)arrayWithCountAndObjects:(int)count, ...
{
NSMutableArray *arr = [NSMutableArray array];
va_list args;
va_start(args, count);
for (int i = 0; i < count; i++) {
[arr addObject:va_arg(args, id)];
}
va_end(args);
return arr;
}
However, what you should do here is simply joining the items in the array instead of hacking with variadic arguments, because that's unnecessary:
NSArray *arr = #[#"Hello", #" ", #"world!"];
NSString *s = [arr componentsJoinedByString:#""];
You don't want to use string with format, if the array holds strings, then you want to use the array method, componentsJoinedByString:. Just pass #" " as the string if you want a space between the strings.
It takes variable arguments. If you want to look up the type of function, it's called "variadic".
In this specific case, those arguments are determined by the formatting string you specify. %# means any cocoa object (inheriting from NSObject). %s means a c string (null-terminated char array). %d means an int, %f means a float or double, and so on. There's quite a lot of them (all except %# are borrowed from C's printf function). You can find full details here: http://www.cplusplus.com/reference/cstdio/printf/ and here https://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/Strings/Articles/FormatStrings.html#//apple_ref/doc/uid/20000943
As for your attempt, that's not how it works. You'll just have to split the array up into separate parameters, or use componentsJoinedByString, or loop through manually if you need more control. But you could use a single %# to display the array in its own format, probably something like [First Value; Second Value].

How to reverse a string without allocating memory

I was asked this question on how to reverse a string without allocating memory. Any takers?
You cannot reverse an NSString, with or without allocating memory, because an NSString is immutable.
You cannot reverse an NSMutableString in place without allocating memory, because the only methods that NSMutableString provides to replace its contents require the new characters to be specified in an NSString, which you would have to allocate.
CFMutableString has the same “problem”.
void reverseStringBetter(char* str)
{
int i, j;
i=j=0;
j=strlen(str)1;
for (i=0; i<j; i++, j-)
{
str[i] ^= str[j] ;
str[j] ^= str[i] ;
str[i] ^= str[j] ;
}
}
It is not possible with NSString since they are immutable and the only way is to create a new string.
Though this might not be what you are looking for, you can convert the NSString to a normal c-string, and edit that in-place. You are still allocating memory, but you'll at least get half of what you want by being able to modify the string in place.
I'm not sure what your use case is for not wanting to allocate memory, or if this is simply a hypothetical.

How to Assign a single value to whole NSMutableArray?

I have an mutable array of say 20 objects. And it has values like #"TRUE",#"FALSE",#"TRUE"...
Now I want to reset the all values of array to #"FALSE". Means array having all values as #"FALSE" (20 times).
I know how to add, insert at index... But I want to know that How can I set whole array value to #"FALSE" in a sing line ??? `without using loop and replace object at index... ?
For example : is it possible
thArray = [[NSMutableArray alloc] initWithCapacity:20];
theArray = #"FALSE" ;
Thanks...
Can you use a C array? If so, you can use {0, 1} as C-equivalents of {FALSE, TRUE}, initializing a C array with:
unsigned short int cArray[20] = {0};
or:
static unsigned short int cArray[20]; /* all values are zeroes, or FALSEs */
This might be more efficient, instead of using an array of static NSString * const elements like you're doing now. Testing whether two integers are equivalent is usually faster than testing lexicographical equivalence of two strings, where your program will have to compare each string character by character.
To reset the contents of the array, you can use the C function memset():
memset(cArray, 0, 20*sizeof(unsigned short int)); /* set all values of cArray to 0 */
If you need a dynamically-sized array, use a pointer with calloc() and reset it with memset() as previously described. Just remember to free() the pointer afterwards, so that you don't get a memory leak:
unsigned short int *cArray = NULL;
size_t cArrayLength = 20; /* can be passed in as a value from another method, etc. */
cArray = calloc(cArrayLength, sizeof(unsigned short int)); /* values are initialized to 0 */
if (cArray) {
/* use cArray... */
*(cArray + 8) = 1; /* e.g., set ninth element with the value of 1 */
/* we don't need cArray any longer, so we free it */
free(cArray);
}
else
/* error */
If you must use Objective-C with NSString * or NSNumber * instances in an NSArray or NSMutableArray, there is no ready-made method for initialization and you'll need to use a loop or copy a pre-existing array, as described in Justin's answer. He is also correct that a method for creating and populating the array is a good idea, if you want to go in this direction.
If those were mutable strings inside the array you could do this in just one line:
[theArray makeObjectsPerformSelector:#selector(setString:) withObject:#"FALSE"];
Here's one way:
NSArray * initialized = ...array with fifty #"FALSE" values...;
NSMutableArray * a = [initialized mutableCopy];
... mutate a ...
[a setArray:initialized];
If you are actually dealing with bool values, C scalars will be faster (see Alex's answer).
Another alternative would be a CFMutableBitVector.
Finally, this would also be a good case for creating a function.
1) Either this
2) Or this
Otherwise without a loop there is no way.
only way i know is
for(int i = 0;i<[theArray count];i++)
{[theArray replaceObjectAtIndex:i withObject:#"FALSE"];}

Objective-C syntax

I've been studying objective-c for a few days now. I keep coming across these two structures:
NSString * somestring
(NSString *) somestring
I understand the first simply sets a pointer to an NSString object, but what does the second construct do, and when should I use it?
What's the deal with the asterix marks?
Sorry if this question doesn't make any sense, I am completely new to this language, and haven't even reached the level of asking proper questions.
Main purpose -- I'm trying to decipher this method:
-(NSString *)pickerView:(UIPickerView *)pickerView titleForRow:(NSInteger) row forComponent: (NSInteger)component
**Also, the classes I chose don't matter. **
What you want to understand is the method declaration syntax. In Objective-C, a method has a name which looks like this doSomethingWith:andAlso:inMode:. Each colon precedes an argument. When you declare or define a method, you also specify the types of the variables and their names; the type is given in parentheses. You also prepend things with a - for instance methods and a + for static methods, as well as the (parenthesized) return type. Now, you have
- (NSString*) pickerView:(UIPickerView*)pickerView
titleForRow:(NSInteger)row
forComponent:(NSInteger)component
{
...
}
When we decipher this, we find that:
-: It's an instance method.
(NSString*): The return type, NSString*.
pickerView:: The first part of the method name.
(UIPickerView*)pickerView: The first argument; its name is pickerView and it has type UIPickerView*.
titleForRow:: The second part of the method name.
(NSInteger)row: The second argument; its name is row and its type is NSInteger.
forComponent:: The third part of the method name.
(NSInteger)component: The third argument; its name is component and its type is NSInteger.
Thus, putting it all together, this defines the instance method pickerView:titleForRow:forComponent:; it returns an NSString*, and the three arguments it takes are of type UIPickerView*, NSInteger, and NSInteger, respectively. This method would be called as [obj pickerView:myPV titleForRow:myRow forComponent:myComponent].
And just for further reference: in isolation, if you have NSString* str, it declares a variable of type NSString*; and if you have (NSString*)obj, it (forcefully) converts that object to have type NSString*. This has no connection to the method declaration syntax.
Edit 1: I also saw that you were asking about the asterisks. In (Objective-)C, this represents a pointer. If you have an int x, say, then when you write int y = x and then y = 3, the original value of x is unchanged. If, however, you have an int* px, then you can write px = &x. (Note that ints, declared as int, are a completely different data type than int pointers declared as int*. Writing int y = &x is garbage, as is int* py = x, and so on.) This & is the "address of" operator; it finds where x is in memory and returns it. Now, if you write int* py = px and then py = &y, this won't change px. But if you write *px, you access the value currently stored in x, and you can change it: *px = 42 sets x to 42. For various reasons, when working with objects, people tend to like to work with references to them instead of their actual values; thus, in Objective-C, you only handle objects through pointers. What this means is that you will never see NSMutableArray x, only NSMutableArray* x; and that if you have NSMutableArray* y = x, then x and y are, roughly speaking, the same, and calling [x addObject:obj] affects y as well. There are more comprehensive tutorials out there—it's worth checking them out if you don't understand pointers—but this should suffice as an overview.
Edit 2: In another comment, you say you're coming from Ruby and Python. In Ruby (and I think Python, but I've used it less), every variable is a reference. This means that the basic use of pointers for object types should be familiar; as long as you never use & or *, they'll function in pretty much the same way. The difference between pointers and references is that you can take references to objects and create pointers to pointers. For instance, many methods end in ...error:(NSDictionary**)error. This effectively provides an extra return value; in the method, if something goes wrong, they can write *error = myErrorInfo. Since function arguments are copied, error = myErrorInfo wouldn't be visible; however, the pointer's referent is still the same, and so it can be assigned to. If you then write code such as:
NSDictionary* errorDict = nil;
[obj unsafeOperation:#"http://stackoverflow.com" error:&errorDict];
You pass in a pointer to errorDict so that the unsafeOperation:error: method can write to errorDict and you can see it.
mebFace - an asterisk represents a pointer. So whenever you see (eg) "NSString *" then it means you're dealing with a pointer to a NSString object. The method you're trying to decipher returns a pointer to a string as the result. It takes three parameters: a pointer to a UIPickerView, followed by a couple of integers. The reason that you don't use an asterisk in conjunction with the integers is because they are simple integers - not objects.
You should probably start off by reading a book on the C programming language. This is what Objective-C is built on top of.
Dave
The first one is variable declaration while second is type-casting. I.e. somestring is not of type NSString* so you type-cast it into being NSString*. I believe that the latter case is mostly (if not always) seen on the right side of assignment statement.
In ObjectiveC this comes from C and is also used in many other strictly-typed languages like Java, C# and so on.
In the updated question, your method signature defines that method returns pointer to NSString - (NSString *). And it accepts 3 parameters:
Pointer to UIPickerView object;
number of row;
number of column;
Confusingly, in Objective-c, both of your examples mean different things in different contexts.
When declaring a variable (and other places, but not everywhere else) the asterisk means 'pointer to', ie…
int foo; // An int variable
int *bar; // A pointer to an int
When it comes to objective-c objects we mostly deal with pointers to them, ie.. you will not see this..
NSString myString;
you will always see this
NSString *myString;
The reason why is quite involved, but is to do with where the memory for the object is allocated (the heap) and what happens when you pass a variable to a function or method. A value passed as an argument to a method is copied. It turns out that copying our string when we pass it to a method is probably not what we intended, so we pass a pointer to the string instead, and that is copied. Imagine a string that contains the complete works of Shakesphere, roughly 5 million bytes. It is inefficient to copy it every time we pass it to a method, but a pointer to it is only 4 bytes, and a pointer gives us just as good access to the data because it, well, points to it. This approach wouldn't get us anything for the int argument tho, as the int and the pointer to the int are going to be the same size (or ballpark, at least).
Your second example is a method or a method declaration. It might help to compare it to function definition in something like javascript:
function pickerViewTitleForRowForComponent( pickerView, row, component ) {
...do something here
return result;
}
Objective-c does things slightly better, sorry, i mean differently. The above would basically look like
- pickerView: pickerView titleForRow: row forComponent: component {
...do something here
return result;
}
The arguments are the same: pickerView, row and component. However, the above isn't a valid method because it is missing type info. ie. We must explicitly say what type each argument is and also the type of the object returned from the method.
- (return type)pickerView:(argument type)pickerView titleForRow:(argument type)row forComponent:(argument type)component {
...do something here
return result;
}
As you can probably see, in your example:
return type > a pointer to an NSString object -- (NSString *)
argument1 type > a pointer to a UIPickerView object -- (UIPickerView *)
argument2 type > an NSInteger -- (NSInteger)
argument3 type > an NSInteger -- (NSInteger)

NS String comparison fails with stringWithFormat

I have two NSStrings with the same value
this failed for me:
if (button.controlName == controlName) {
return button;
}
this worked:
if ([button.controlName compare: controlName] == NSOrderedSame) {
return button;
}
Is this just how strings are compared in objective c? Or should the first statement have worked as well? Why might the first statement have failed? I know it worked for other strings.
The strings it does not work for are initialized like this:
button.controlName = [NSString stringWithFormat:#"controlName%d", i]
With NSString you should use isEqualToString: instead of compare.
[button.controlName isEqualToString:controlName]
Read more the why (and also why it worked for some other strings)
Objective-C is a fairly thin layer on top of standard C. As a result obj-c, just as in normal c, doesn't have operator overloading.
NSString *controlName = #"bobDole";
The above code creates a pointer to the string #"bobDole", controlName is not the value itself, but instead is really just a long integer that says the memory address of an object.
When using pointers and comparing them using the == operator like (mutableCopy is being used to prevent the compiler from optimizing out the validity of this example.)
NSString *string1 = #"bobDole";
NSString *string2 = [string1 mutableCopy];
NSLog(#"%d", string1 == string2);
The above code will always print false (or zero in this case), even though both objects are NSStrings, and both contain the value of #"bobDole". This is because the value of string1 is actually a hex number like 0x0123456 and string2 could be something like 0x0987654. So really the above comparison looks like this to the computer:
NSLog(#"%d", 0x0123456 == 0x0987654);
So when comparing strings (or any other object), always use one of the isEqual methods, never use the == operator.
Now as to why it worked for some other strings:
As mentioned above when using the == operator you're actually doing pointer comparison. You'll also notice in my above example I used mutableCopy instead of the following:
NSString *string1 = #"bobDole";
NSString *string2 = #"bobDole";
The reason I did such was that the compiler will look at those two statements know they share the same immutable value and optimize them so they point at the same value in memory. Thus making the pointer values of the two identical.
The compiler also makes the same optimizations for these methods of string initialization.
NSString *string3 = [NSString stringWithString:#"bobDole"];
NSString *string4 = [NSString stringWithString:string1];
NSString *string5 = [string1 copy];
Because of this optimization by the compiler and runtime all 5 pointers point to the same memory location and are thus equal to each other when compared via ==.
This may be kinda long, but I tried to make it accessible and understandable. Hope it helps.
1st statement just compares pointers, but not string values, so to compare strings you should use -isEqualToString as Bryan points.
There's a method called isEqualToString to compare two NSStrings.
if([button.controlName isEqualToString:controlName])
...