How to send values to Ivar in method - objective-c

new to Objective-C and keeping it very very simple I'm looking to understand one thing at a time... I set up a very simple class called student all it does is add two numbers trying to see how things pass into and back from methods) **I rewrote the code ==>> look at end to see the version that works **
If I have a method that has
#property (nonatomic) int firstNum;
#property (nonatomic) int secondNum;
and I have an instance of my class called student I assign a value to firstNum like student.firstNum = 100; student.secondNum = 77; that is easy and the method adds them and sends the sum in a return
But in main I tried assigning it from an array and it did not work I tried
student.firstNum = [myIntegers objectAtIndex:0];
and
student.firstNum = [myIntegers objectAtIndex:i]; //using a for loop with i index
it says incompatible pointer to integer conversion
Here is the snippet from main I tried it's not complete it just is trying to set firstNum eventually I will also set up secondNum and send each pair to the method to get added together but for now I am stuck trying to get the firstNum assigned the value in myIntegers[i] to start
NSMutableArray *myIntegers = [NSMutableArray array];
for (NSInteger i= 0; i <= 10; i++) {
[myIntegers addObject:[NSNumber numberWithInteger:i]]; // this works up to here
student.firstNum = [myIntegers objectAtIndex:i]; // this does not work
}
I also tried [i].
Here is my method:
- (int)addNumbers {
int sum = self.firstNum + self.secondNum;
return sum;
}
HERE IS WHAT WORKS : assuming I have a student object
.m
(long)addNumbers:(NSNumber *)x :(NSNumber *)y {
long sum;
sum = [x integerValue] + [y integerValue];
return sum;
}
main
NSMutableArray *myIntegers1 = [NSMutableArray array];
NSMutableArray *myIntegers2 = [NSMutableArray array];
for (NSInteger i= 0; i <40; i++) {
[myIntegers1 addObject:[NSNumber numberWithInteger:i]];
[myIntegers2 addObject:[NSNumber numberWithInteger:i]];
long sum = [student addNumbers:[myIntegers1 objectAtIndex:i] :[myIntegers2 objectAtIndex:i]];
NSLog(#" The sum is %ld", sum);
}

You are creating a properties of type int, but in your for loop, you are trying to assign them an NSNumber.
NSNumber is a simple container for a c data item and can hold int, float, char, bool, etc.
Change your loop to be like that:
for (NSInteger i= 0; i <= 10; i++) {
[myIntegers addObject:[NSNumber numberWithInteger:i]];
student.firstNum = [[myIntegers objectAtIndex:i] intValue]; // this 'extracts' the int value from the NSNumber
}

Related

Printing a string object from an NSMutableArray

I stored some strings in objects and added the objects to an NSMutableArray. Now I want to print the strings in each element of the array. Clearly, I'm doing something wrong. I'm going to back and review these basics, but I was hoping someone could explain how I can print the string instead of the what looks to be the element address.
/** interface **/
#property (nonatomic, copy) NSString*myNumber;
-(void)setNumber: (NSString*) randomNumber;
/** implementation **/
#synthesize myNumber;
-(void) setNumber:(NSString *)randomNumber
{
myNumber = randomNumber;
}
/**main**/
Fraction * aFrac = [[Fraction alloc] init];
[aFrac setNumber:#"5/6"];
Fraction * bFrac = [[Fraction alloc] init];
[bFrac setNumber:#"2/3"];
NSMutableArray * myArray = [[NSMutableArray alloc] init];
[myArray addObject:aFrac];
[myArray addObject:bFrac];
int i;
for(i = 0; i<2; ++i)
{
id myArrayElement = [myArray objectAtIndex:i];
NSLog(#"%#", myArrayElement);
}
for(i = 0; i<2; ++i)
{
NSLog(#"%#", myArray[i]);
}
Both for loops print the same thing.
When you pass a custom object to NSLog you have to override the -(NSString)description method in that object.
So in your Fraction class if you simply override this function like so
- (NSString*)description
{
return self.myNumber;
}
that should log out what you want.
I would probably think about renaming that property from number as you are storing a string.
Hope that helps
I'm guessing the Fraction type you created has a NSString property or method named number (to match the -setNumber: method), in which case you would use the following code to print it:
NSLog("%#", [myArrayElement number]);
Or, for the second loop:
NSLog("%#", [myArray[i] number]);
In your code both for loop meaning has same only, try below
for(i = 0; i<2; ++i)
{
id myArrayElement = [myArray objectAtIndex:i];
NSLog(#"%#", myArrayElement.number);
}
for(i = 0; i<2; ++i)
{
NSLog(#"%#", myArray[i].number);
}
Now here two array value you are extracting
[myArray objectAtIndex:i] which is equivalent to myArray[i]

How can I create array of numbers in Objective-C?

i trying to create my firsy iphone program and i realize that making an array or matrix of 2 dims is difficult for me... :-(
*how and where i declarer somthing like this (take from java) so all the function can see it:
int[] myArray = new int[6];
*how can i trnslete this function:
public int[] sortArray (int[] myArray){
int tmp;
for (int x = 0; x < myArray.length; x++) {
for (int y = x+1; y < 6; y++) {
if (myArray[y] < myArray[x]) {
tmp = myArray[x];
myArray[x] = myArray[y];
myArray[y] = tmp;
}
}
}
return myArray;
}
*and how i call this function?
sortArray(myArray);
thanks for everyone!!!
sharon
You can do it with one line of code:
NSArray *array = #[#[#1, #2, #3],
#[#4, #5, #6],
#[#7, #8, #9]];
Learn about Objective-C literals here.
As in C,
int twoDArray[3][3];
In objective-C
NSArray *a=#[#"apple",#"axe",#"ant"];
NSArray *b=#[#"ball",#"book",#"baby"];
NSArray *c=#[#"cup",#"cat",#"cow"];
NSArray *twoDArray=#[a,b,c];
or in one statement:
NSArray *twoDArray=#[#[#"apple",#"axe",#"ant"],
#[#"ball",#"book",#"baby"],
#[#"cup",#"cat",#"cow"]];
EDIT:
NO need to convert that java function to obj-c method.
To sort the array :
NSArray *sortedArray = [array sortedArrayUsingComparator:^(id str1, id str2) {
return [((NSString *)str1) compare:((NSString *)str2) options:NSNumericSearch];
}];
EDIT 2: (Removed unwanted typecast of nsstring to id and back to string)
NSArray *sortedArray = [array sortedArrayUsingComparator:^(NSString *str1, NSString *str2) {
return [str1 compare:str2 options:NSNumericSearch];
}];
Declare in your respective .h file
NSMutableArray *numbers;
Then in your .m file
numbers = [[NSMutableArray alloc] init];
for (NSInteger i = 0; i < 6; i++)
[numbers addObject:[NSNumber numberWithInteger:i]];
and declare it in your .h as
-(NSMutableArray *)sortArray:(NSMutableArray *)numbers;
This is the translated method above in Objective-C:
-(NSMutableArray *)sortArray:(NSMutableArray *)numbers
{
NSInteger tmp = 0;
for(int x = 0; x < [numbers count]; x++)
for(int y = x + 1; y < 6; y++)
if([numbers objectAtIndex:y] < [numbers objectAtIndex:x])
{
tmp = [numbers objectAtIndex:x];
[numbers replaceObjectAtIndex:x withObject:[numbers objectAtIndex:y]];
[numbers replaceObjectAtIndex:y withObject:tmp];
}
return numbers;
}
Also you can call a method in objective-c as follows:
[self sortArray:numbers];
You seem to have (at least) two related-but separate questions here.
1/ how to create an array of numbers
Objective-C arrays come as immutable NSArrays (fixed contents) or mutable NSMutableArrays (you can add delete and shuffle contents around). You sort function as written is asking for a mutable array.
To create and populate an immutable array with NSNumber objects:
NSArray* array = #[#3,#5,#8,#2,#9,#1]; //"#1" is an NSNumber object literal
//access: array[3] etc
Multidimensional:
NSArray* arrayOfArrays #[#[#3,#5,#8],#[#2,#9,#1]];
//access: arrayOfArrays[1][2] etc
To create an empty variable-length mutable array
NSMutableArray* mutableArray = [[NSMutableArray alloc] init];
Create and populate a variable-length mutable array
myArray = [NSMutableArray arrayWithObjects:#3,#5,#8,#2,#9,#1, nil]; //note nil termination
To turn your immutable NSArray into a mutable NSMutableArray
NSMutableArray* mutableArray = [array mutableCopy];
(but take care, this will only render the top level as mutable, if it contains immutable subarrays they will remain immutable)
Objective-C collections (NSArray, NSDictionary, NSSet) can only hold objective-C objects. Therefore if you want to store ints or floats you need to box them into objective-C NSNumber objects before adding to a collection, and unbox them again to access the value.
int x;
float y;
NSNumber xNum = [NSNumber numberWithInt:x]; //box
NSNumber yNum = [NSNumber numberWithFloat:y]; //box
x = [xNum intValue]; //unbox
y = [yNum floatValue]; //unbox
2/ how to translate code
Here is a like-for-like translation:
To create the (mutable) myArray object:
NSMutableArray* myArray = [[NSMutableArray alloc] init];
Populate it:
[myArray addObjects:#3,#6,#8,#1,#9,nil]; //last value is nil to indicate termination
The method:
- sortArray:(NSMutableArray*)myArray
{
id tmp;
for (int x = 0; x < [myArray count]; x++) {
for (int y = x+1; y < 6; y++) {
if ([myArray[y] floatValue] < [myArray[x] floatValue]) {
tmp = myArray[x];
myArray[x] = myArray[y];
myArray[y] = tmp;
}
}
}
}
To call:
[self sortArray:myArray];
To declare with object scope, make a property in your #interface section
#interface myObject:NSObject
#property (nonatomic, strong) NSMutableArray* myArray;
#end
You will still need to create myArray before you can use it:
self.myArray = [[NSMutableArray alloc] init];
but you will be able to set and access it's values from anywhere inside the object thus:
self.myArray
And - if it is in the public header file #interface section - from outside the object thus:
myObject.myArray

How to generate non repeating random number

I am trying to randomize numbers in an array. I am able to do that using arc4random() % [indexes count]
My problem is - If an array consists of 20 items, every time the array shuffles, in a batch of 5, different number should appear. Example :
first shuffle: 1,4,2,5,6.
second shuffle: 7,12,9,15,3
-(IBAction)randomNumbers:(UIButton *)sender
{
int length = 10; // int length = [yourArray count];
NSMutableArray *indexes = [[NSMutableArray alloc] initWithCapacity:length];
for (int i=0; i<5; i++)
[indexes addObject:[NSNumber numberWithInt:i]];
NSMutableArray *shuffle = [[NSMutableArray alloc] initWithCapacity:length];
while ([indexes count])
{
int index = arc4random() % [indexes count];
[shuffle addObject:[indexes objectAtIndex:index]];
[indexes removeObjectAtIndex:index];
}
// for (int i=0; i<[shuffle count]; i++)
NSLog(#"%#", [shuffle description]);
}
As per your requirement....kindly check this code
Make this a property
#synthesize alreadyGeneratedNumbers;
Add these methods in your .m
-(int)generateRandomNumber{
int TOTAL_NUMBER=20;
int low_bound = 0;
int high_bound = TOTAL_NUMBER;
int width = high_bound - low_bound;
int randomNumber = low_bound + arc4random() % width;
return randomNumber;
}
-(IBAction)randomNumbers:(UIButton *)sender
{
NSMutableArray *shuffle = [[NSMutableArray alloc] initWithCapacity:5];
BOOL contains=YES;
while ([shuffle count]<5) {
NSNumber *generatedNumber=[NSNumber numberWithInt:[self generateRandomNumber]];
//NSLog(#"->%#",generatedNumber);
if (![alreadyGeneratedNumbers containsObject:generatedNumber]) {
[shuffle addObject:generatedNumber];
contains=NO;
[alreadyGeneratedNumbers addObject:generatedNumber];
}
}
NSLog(#"shuffle %#",shuffle);
NSLog(#"Next Batch");
if ([alreadyGeneratedNumbers count] >= TOTAL_NUMBER) {
NSLog(#"\nGame over, Want to play once again?");//or similar kind of thing.
[alreadyGeneratedNumbers removeAllObjects];
}
}
Still I feel you need to some changes like
it will give you correct value, but what if user pressed 5th time?
out of 20 numbers you already picked 4 sets of 5 number, on on 6th time it will be in loop to search for next set of numbers and will become infinite.
So what you can do is, keep the track of shuffle and once it reaches the limit i.e, 20/5=4 disable the random button.
Declare array that contains already generated number in extension or header file
#property (strong, nonatomic)NSMutableArray *existingNums;
#property (assign, nonatomic)NSInteger maxLimit;
#property (assign, nonatomic)NSInteger minLimit;
Then implement given code in implementation file
#synthesize existingNums;
#synthesize maxLimit;
#synthesize minLimit;
- (NSInteger)randomNumber {
if(!existingNums)
existingNums = [NSMutableArray array];
while (YES) {
NSNumber *randonNum = [NSNumber numberWithInteger:minLimit+arc4random()%maxLimit];
if([existingNums containsObject:randonNum]) {
if([existingNums count] == (maxLimit - minLimit))
return -1; // All possible numbers generated in the given range
continue;
}
[existingNums addObject:randonNum];
return [randonNum integerValue];
}
return -1; // return error
}
Hope this will help you :)
This one works for me:
NSMutableArray *numbers = [NSMutableArray new];
BOOL addElement = YES;
int limit = 100; // Range from 0 to 36
int numElem = 10; // Number of elements
do
{
int ranNum = (arc4random() % limit) +1;
if ([numbers count] < numElem) {
for (NSNumber *oneNumber in numbers) {
addElement =([oneNumber intValue] != ranNum) ? YES:NO;
if (!addElement) break;
}
if (addElement) [numbers addObject:[NSNumber numberWithInt:ranNum]];
} else {
break;
}
} while (1);
NSLog(#"%#",numbers);
The problem with all these answers is that you need to review your previous generated random numbers and that takes extra time if you need a large number of random integers.
Another solution is using cryptography:
Generate a random key
Iterate between 0..n
Encrypt each integer and apply modulo the number of alternatives do you want to use to the output of the function.
There are some extra details to take into account that don't matter for your case.

Retrieve integers by looping through a NSMutableArray

Can someone show me how to retrieve values by looping through a NSMutableArray? My code, which basically adds integer numbers to the array, is below :
NSMutableArray *ptr = [[NSMutableArray alloc] init];
[ptr addObject:[NSNumber numberWithInt:1]];
[ptr addObject:[NSNumber numberWithInt:2]];
[ptr addObject:[NSNumber numberWithInt:3]];
// How to retrieve them as integers?
I'm trying to retrieve each number from the array and sum them up to a total value.
Its actually pretty simple:
int totalValue = 0;
for(NSNumber *number in myArray) // Use fast enumeration to iterate through the array
{
totalValue += [number intValue];
}
I'm also a newbie so my answer may be wrong, but try this:
int sum = 0;
for (int i = 0, i < [ptr count], i++){
int value = [[ptr objectAtIndex:i] intValue] //you get the int, integerValue is applicable for NSInteger
sum = sum + value;//you adding values
}

How to simplify my code... 2D NSArray in Objective C...?

self.myArray = [NSArray arrayWithObjects: [NSArray arrayWithObjects: [self generateMySecretObject], [self generateMySecretObject],nil], [NSArray arrayWithObjects: [self generateMySecretObject], [self generateMySecretObject],nil],nil];
for (int k=0; k<[self.myArray count]; k++) {
for(int s = 0; s<[[self.myArray objectAtIndex:k] count]; s++){
[[[self.myArray objectAtIndex:k] objectAtIndex:s] setAttribute:[self generateSecertAttribute]];
}
}
As you can see this is a simple 2*2 array, but it takes me lots of code to assign the NSArray in very first place, because I found that the NSArray can't assign the size at very beginning. Also, I want to set attribute one by one. I can't think of if my array change to 10*10. How long it could be. So, I hope you guys can give me some suggestions on shorten the code, and more readable. thz
(Some Assumptions: myArray will have a fixed size. It won't grown up or become smaller in the run time.)
Generate the array by -addObject:.
NSMutableArray* myArray = [NSMutableArray array];
for (int k = 0; k < 10; ++ k) {
NSMutableArray* subArr = [NSMutableArray array];
for (int s = 0; s < 10; ++ s) {
id item = (s == 0 && k == 0) ? [self d] : [self generateMySecretObject];
[item setAttribute:[self generateSecertAttribute]];
[subArr addObject:item];
}
[myArray addObject:subArr];
// use [myArray addObject:[[subArr copy] autorelease]] for deep immutability.
}
return [[myArray copy] autorelease];
(Don't query self.myArray many times. Each corresponds to an ObjC call and while someone calls an ObjC call is cheap, it's still not free.)
If the array is a fixed size and each row is the same length then you could uses a 1D array and an offset, EG:
int rowLength = 5;
int rowNumber = 0;
int columnNumber = 3;
[myArray objectAtIndex: (rowLength * rowNumber) + columnNumber];