Would like NSArray valueForKey to return the array indices - objective-c

I can create an NSArray that contains all the hash values of the objects in myArray like this:
NSArray *a = [myArray valueForKey:#"hash"];
What key do I pass to valueForKey: to get an array containing myArray's indices?
Say myArray has n items. I'd like to do something like this:
NSArray *a = [myArray valueForKey:#"index"];

NSArray * arrayWithNumbersInRange( NSRange range )
{
NSMutableArray * arr = [NSMutableArray array];
NSUInteger i;
for( i = range.location; i <= range.location + range.length; i++ ){
[arr addObject:[NSNumber numberWithUnsignedInteger:i];
}
return arr;
}
NSArray * indexArray = arrayWithNumbersInRange((NSRange){0, [myArray length]-1});

You can query an NSArray for the index of an object with indexOfObject:
NSArray *a = [myArray valueForKey:#"hash"];
NSInteger index = [myArray indexOfObject:a];

Create a superclass of NSArray which returns the index:
//
// CapArrayOfIndex.h
// Created by carmin politano on 7/26/12.
// no rights reserved
//
#interface CapArrayOfIndex : NSArray {
/*! Simulated constant array containing an array of NSNumber representing the index. */
NSUInteger iCount;
//*! NSNotFound causes bybass of index bounds testing. */
}
#pragma mark create
+ (CapArrayOfIndex*) withCount: (NSUInteger) aCount;
#end
and
//
// CapArrayOfIndex.mm
// Created by carmin on 7/26/12.
// no rights reserved
//
#import "CapArrayOfIndex.h"
#implementation CapArrayOfIndex
#pragma mark NSCopying
- (id) copyWithZone: (NSZone*) aZone {
/*! New allocation required because -count is a mutable property. */
return [CapArrayOfIndex withCount: self.count];
}
#pragma mark create
+ (CapArrayOfIndex*) withCount: (NSUInteger) aCount {
CapArrayOfIndex* zArray = self.alloc;
zArray->iCount = aCount;
return zArray;
}
#pragma mark NSArray
- (NSUInteger) count {
return iCount;
}
- (void) setCount: (NSUInteger) aCount {
iCount = aCount;
}
- (id) objectAtIndex: (NSUInteger) aIndex {
/*! My code performs a bounds test using unusual macros: return [ViaUInteger RaiseIfObjectAtIndex(nil, self, aIndex, nil)]; */
return [NSNumber numberWithInteger: aIndex];
}
#end

Related

how to add objects to existing array in objective c

I am new to objective c and having some problem with nsmutableArray.I have button and two textfields on my gui and i want that when i click on button the strings from textfields should be added to my existing array. But the problem is that when i click on button it always create new array.Help anybody.
my button code in myfile.m is as follows:
NSMutableArray* myArray = [NSMutableArray array];
NSString *strr=[textf stringValue];
NSString *strr1=[textf1 stringValue];
// [myArray addObject:strr]; // same with float values
// [myArray addObject:strr1];
[myArray addObject:strr];
[myArray addObject:strr1];
int i,j=0;
int count;
for (i = 0, count = [myArray count]; i < count; ){
NSString *element = [myArray objectAtIndex:i];
NSLog(#"The element at index %d in the array is: %#", i, element);
}
Because you always create new array in this line:
NSMutableArray* myArray = [NSMutableArray array];
Make your array as property of your class object. Example:
#interface MyClass ()
#property (nonatomic, strong) NSMutableArray * array;
#end
#implementation MyClass
- (id)init {
self = [super init];
if ( self ) {
_array = [NSMutableArray array];
}
return self;
}
- (IBAction)onButtonClick {
NSString *strr = [textf stringValue];
NSString *strr1 = [textf1 stringValue];
[self.array addObject:strr];
[self.array addObject:strr1];
for ( int i = 0; i < [myArray count]; i++ ) {
NSString * element = [myArray objectAtIndex:i];
NSLog(#"The element at index %d in the array is: %#", i, element);
}
}
#end

Self and arrays problems

I am new to Objective C and I'm having trouble getting my head around a few things.
I am trying to make a big integer program, from which I read items entered in a string and put them into an individual elements in the array.
I am currently working on an add method which adds elements from both the arrays together to make a big number stored in a final array.
But I'm kind of confused about to get this array I made from the initWithString method into the array method. I have some understanding of self, but I don't really know how to use it in this sense.
#implementation MPInteger
{
}
-(id) initWithString: (NSString *) x
{
self = [super init];
if (self) {
NSMutableArray *intString = [NSMutableArray array];
for (int i = 0; i < [x length]; i++) {
NSString *ch = [x substringWithRange:NSMakeRange(i, 1)];
[intString addObject:ch];
}
}
return self;
}
-(NSString *) description
{
return self.description;
}
-(MPInteger *) add: (MPInteger *) x
{
//NSMutableArray *arr1 = [NSMutableArray arrayWithCapacity:100];
//NSMutableArray *arr2 = [NSMutableArray arrayWithCapacity:100];
//for (int i=0; i < 100; i++) {
//int r = arc4random_uniform(1000);
//NSNumber *n = [NSNumber numberWithInteger:r];
//[arr1 addObject:n];
//[arr2 addObject:n];
// }
self.array = [NSMutableArray initialize];
return x;
}
#end
int main(int argc, const char * argv[]) {
#autoreleasepool {
MPInteger *x = [[MPInteger alloc] initWithString:#"123456789"];
MPInteger *y = [[MPInteger alloc] initWithString:#"123456789"];
[x add: y];
}
}
So I want too add the x and y arrays, but I'm not sure how to get the arrays in the add method. Do I use self to represent one of the arrays and initialise it, and x to represent the other. I don't know if I'm going about it completely the wrong way. Some help to understand would be greatly appreciated.
When referring to self you're actually accessing the current instance of the class. In other languages this may be implemented as this instead. There are a couple ways of designing the approach you're going for but the simplest pattern is probably composition:
#interface MPInteger
{
NSMutableArray *digits;
}
#end
----------------------------------------------------------------------------
#implementation MPInteger
-(id) initWithString: (NSString *) x
{
// Create a new instance of this class (MPInteger) with a default
// constructor and assign it to the current instance (self).
self = [super init];
if (self) {
// Previously we initialized a string, but then threw it out!
// Instead, let's save it to our string representation:
self->digits = [NSMutableArray array];
for (int i = 0; i < [x length]; i++) {
NSString *ch = [x substringWithRange:NSMakeRange(i, 1)];
[self->digits addObject:ch];
}
return self;
}
// Depending on how you want to implement this function, it could return
// a new MPInteger class or update the current instance (self):
-(MPInteger *) add: (MPInteger *) x
{
NSArray *a = self->digits;
NSArray *b = x->digits;
// Have both strings for A + B, so use them to find C:
NSArray *c = ????;
// Return a new instance of MPInteger with the result:
return [ [ MPInteger alloc ] initWithString:c ];
}
#end
Notice that now the MPInteger class has an instance of an NSString object that will exist during the entire lifetime of the MPInteger object. To update/access this string, all you need to do is say:
self->digits

How to add a number of objects skipping nil objects to NSMutableArray?

I need a method that would add a few objects (2-10) to my array, skipping these that are nils:
NSMutableArray *arr = [[NSMutableArray alloc] init];
[arr addObjectsSkipNils:obj1, obj2, obj3];
How I can write this method in an elegant way?
This category method would work:
#interface NSMutableArray (MyAdditions)
- (void)addObjectsSkipNilsWithCount:(NSUInteger)count objects:(id)obj, ...;
#end
#implementation NSMutableArray (MyAdditions)
- (void)addObjectsSkipNilsWithCount:(NSUInteger)count objects:(id)obj, ...
{
va_list ap;
va_start(ap, obj);
// First object:
if (obj != nil)
[self addObject:obj];
// Remaining objects:
for (NSUInteger i = 1; i < count; i++) {
id myobj = va_arg(ap, id);
if (myobj != nil)
[self addObject:myobj];
}
va_end(ap);
}
#end
Example:
NSMutableArray *a = [NSMutableArray array];
[a addObjectsSkipNilsWithCount:3 objects:#"foo", nil, #"bar"];
NSLog(#"%#", a);
// Output: ( foo, bar )
You have to specify the number of objects explicitly, because nil cannot be used as terminator for the variable argument list. (And bad things can happen if the count is greater than the actual number of objects supplied !)
You can use:
[yourMainArray removeObjectIdenticalTo:[NSNull null]];
Now if you want to copy this to arr you can do quite easily.

Array of floating point values in Objective-C

How can I create array of floating point numbers in Objective-C?
Is it possible?
You can create a dynamic array (size decided at runtime, not compile time) in different ways, depending on the language you wish to use:
Objective-C
NSArray *array = [[NSArray alloc] initWithObjects:
[NSNumber numberWithFloat:1.0f],
[NSNumber numberWithFloat:2.0f],
[NSNumber numberWithFloat:3.0f],
nil];
...
[array release]; // If you aren't using ARC
or, if you want to change it after creating it, use an NSMutableArray:
NSMutableArray *array = [[NSMutableArray alloc] initWithCapacity:0];
[array addObject:[NSNumber numberWithFloat:1.0f]];
[array addObject:[NSNumber numberWithFloat:2.0f]];
[array addObject:[NSNumber numberWithFloat:3.0f]];
...
[array replaceObjectAtIndex:1 withObject:[NSNumber numberWithFloat:99.9f]];
...
[array release]; // If you aren't using ARC
Or using the new-ish Objective-C literals syntax:
NSArray *array = #[ #1.0f, #2.0f, #3.0f ];
...
[array release]; // If you aren't using ARC
C
float *array = (float *)malloc(sizeof(float) * 3);
array[0] = 1.0f;
array[1] = 2.0f;
array[2] = 3.0f;
...
free(array);
C++ / Objective-C++
std::vector<float> array;
array[0] = 1.0f;
array[1] = 2.0f;
array[2] = 3.0f;
For an dynamic approach you can use NSNumber object and add it to NSMutableArray, or if you need only static array then use suggestions from comments, or use standard C.
like:
NSMutableArray *yourArray = [NSMutableArray array];
float yourFloat = 5.55;
NSNumber *yourFloatNumber = [NSNumer numberWithFloat:yourFloat];
[yourArray addObject:yourFloatNumber];
and then to retrive:
NSNumber *yourFloatNumber = [yourArray objectAtIndex:0]
float yourFloat = [yourFloatNumber floatValue];
If you are using Xcode 4.4+, you can try this:
NSArray *a = #[ #1.1f, #2.2f, #3.3f];
Here is all new literals of LLVM Compiler 4.0.
How about something like this?
#interface DoubleArray : NSObject
#property(readonly, nonatomic) NSUInteger count;
#property(readonly, nonatomic) double *buffer;
- (instancetype)init NS_UNAVAILABLE;
- (instancetype)initWithCount:(NSUInteger)count NS_DESIGNATED_INITIALIZER;
- (double)valueAtIndex:(NSUInteger)idx;
- (void)setValue:(double)value atIndex:(NSUInteger)idx;
#end
#implementation DoubleArray
- (void)dealloc
{
if (_buffer != 0) {
free(_buffer);
}
}
- (instancetype)initWithCount:(NSUInteger)count
{
self = [super init];
if (self) {
_count = count;
_buffer = calloc(rows * columns, sizeof(double));
}
return self;
}
- (double)valueAtIndex:(NSUInteger)idx
{
return *(_buffer + idx);
}
- (void)setValue:(double)value atIndex:(NSUInteger)idx
{
*(_buffer + idx) = value;
}
#end
It's a basic array. You can extend this with more complex features like appending, indexed removal etc.

How to get indexes from NSIndexset into an NSArray in cocoa?

I'm getting the select items from a table view with:
NSIndexSet *selectedItems = [aTableView selectedRowIndexes];
what's the best way to get the indexes in a NSArray object?
Enumerate the set, make NSNumbers out of the indexes, add the NSNumbers to an array.
That's how you'd do it. I'm not sure I see the point in transforming a set of indexes into a less efficient representation, though.
To enumerate a set, you have two options. If you're targeting OS X 10.6 or iOS 4, you can use enumerateIndexesUsingBlock:. If you're targeting earlier versions, you'll have to get the firstIndex and then keep asking for indexGreaterThanIndex: on the previous result until you get NSNotFound.
NSIndexSet *selectedItems = [aTableView selectedRowIndexes];
NSMutableArray *selectedItemsArray=[NSMutableArray array];
[selectedItems enumerateIndexesUsingBlock:^(NSUInteger idx, BOOL *stop) {
[selectedItemsArray addObject:[NSNumber numberWithInteger:idx]];
}];
With swift you can do the following
extension NSIndexSet {
func toArray() -> [Int] {
var indexes:[Int] = [];
self.enumerateIndexesUsingBlock { (index:Int, _) in
indexes.append(index);
}
return indexes;
}
}
then you can do
selectedItems.toArray()
Here is the sample code:
NSIndexSet *filteredObjects = [items indexesOfObjectsPassingTest:^BOOL(id obj, NSUInteger idx, BOOL *stop) {do testing here}];
NSArray *theObjects = [theItems objectsAtIndexes:filteredObjects]
Availability
Available in iOS 2.0 and later.
I did it by creating a category on NSIndexSet. This kept it small and efficient, requiring very little code on my part.
My interface (NSIndexSet_Arrays.h):
/**
* Provides a category of NSIndexSet that allows the conversion to and from an NSDictionary
* object.
*/
#interface NSIndexSet (Arrays)
/**
* Returns an NSArray containing the contents of the NSIndexSet in a format that can be persisted.
*/
- (NSArray*) arrayRepresentation;
/**
* Returns an array of NSNumber objects representing each index in the set.
*/
- (NSArray<NSNumber*>*) arrayOfNumbersRepresentation;
/**
* Initialises self with the indexes found wtihin the specified array that has previously been
* created by the method #see arrayRepresentation.
*/
+ (NSIndexSet*) indexSetWithArrayRepresentation:(NSArray*)array;
#end
and the implementation (NSIndexSet_Arrays.m):
#import "NSIndexSet_Arrays.h"
#implementation NSIndexSet (Arrays)
/**
* Returns an NSArray containing the contents of the NSIndexSet in a format that can be persisted.
*/
- (NSArray*) arrayRepresentation {
NSMutableArray *result = [NSMutableArray array];
[self enumerateRangesUsingBlock:^(NSRange range, BOOL *stop) {
[result addObject:NSStringFromRange(range)];
}];
return [NSArray arrayWithArray:result];
}
/**
* Returns an array of NSNumber objects representing each index in the set.
*/
- (NSArray<NSNumber*>*) arrayOfNumbersRepresentation {
NSMutableArray<NSNumber*> *result = [NSMutableArray array];
[self enumerateIndexesUsingBlock:^(NSUInteger idx, BOOL * _Nonnull stop) {
[result addObject:[NSNumber numberWithInteger:idx]];
}];
return [NSArray arrayWithArray:result];
}
/**
* Initialises self with the indexes found wtihin the specified array that has previously been
* created by the method #see arrayRepresentation.
*/
+ (NSIndexSet*) indexSetWithArrayRepresentation:(NSArray*)array {
NSMutableIndexSet *result = [NSMutableIndexSet indexSet];
for (NSString *range in array) {
[result addIndexesInRange:NSRangeFromString(range)];
}
return result;
}
#end