Как извлечь и просмотреть элементы из NSMutableArray

#objective-c #nsmutablearray

#objective-c #nsmutablearray

Вопрос:

Я пробую несколько примеров из книги «Objective C для чайников». Я пытался извлечь элементы с помощью приведенного ниже кода, но тщетно. Все они рассматриваются как объекты в NSMutableArray. Но я не знаю, как извлечь элементы, используя объекты.

main.m

 #import <Foundation/Foundation.h>
#import "BudObj.h"
#import "Transaction.h"
int main(int argc, char *argv[]) {
        Budget* europeBudget=[Budget new];
        NSMutableArray *transactions=[[NSMutableArray alloc] initWithCapacity:10];
        [europeBudget createBudget:1000.00 withExchangeRate:1.2500];
        Transaction* aTransaction;
        aTransaction = [Transaction new];
        for(int n=1;n<2;n  ){
                aTransaction = [[Transaction alloc] init];
                [aTransaction createTransaction:n*100 ofType:cash];
                [transactions addObject:aTransaction];
                [aTransaction release];
        }

        int n=1;
        while (n<3) {
                aTransaction = [[Transaction alloc]init];
                [aTransaction createTransaction:n*100 ofType:credit];
                [transactions addObject:aTransaction];
                [aTransaction release];
                n  ;
        }

        do{
                aTransaction = [[Transaction alloc]init];
                [aTransaction createTransaction:n*100 ofType:cash];
                [transactions addObject:aTransaction];
                [aTransaction release];
                n  ;
        }while (n<=3);

        NSLog(@"nNumber of elements in an array:%i",[transactions count]);
        int c;
        c=[transactions count];
        NSLog(@"nThe Elements are:n");
        for(int i=0;i<c;i  ){
                NSLog(@"%@",[transactions objectAtIndex:i]);
        }

        for(Transaction *aaTransaction in transactions){
         switch ([aTransaction returnType]) {
                case cash:
                        [europeBudget spendDollars:[aaTransaction returnAmount]];
                        break;
                case credit:
                        [europeBudget changeForeignCurrency:[aaTransaction returnAmount]];
                        break;
                default:
                        break;
         }
        }
        [transactions release];
        [europeBudget release];

        return 0;
}
  

BudObj.h

 #import <Foundation/Foundation.h>

@interface 
Budget : NSObject {

        float  exchangeRate;
        double budget;
        double exchangeTransaction;

}

- (void) createBudget: (double) aBudget withExchangeRate: (float) anExchangeRate;
- (void) spendDollars: (double) dollars;
- (void) changeForeignCurrency: (double) foreignCurrency;

@end
  

BudObj.m

 #import <Foundation/Foundation.h>
#import "BudObj.h"
#import "Transaction.h"

@implementation Budget

- (void) createBudget: (double) aBudget withExchangeRate: (float) anExchangeRate{
        budget = aBudget;
        exchangeRate = anExchangeRate;
}


- (void) spendDollars:(double)dollars{
    budget = budget - dollars;
        NSLog(@"Converting %0.2f US Dollars into Foreign Currency leaves $%0.2f",dollars,budget);
}

- (void) changeForeignCurrency:(double)foreignCurrency{
    exchangeTransaction = foreignCurrency * exchangeRate;
        budget = budget - exchangeTransaction;
        NSLog(@"Charging %0.2f in Foreign Currency leaves $%0.2f",foreignCurrency,budget);
}

@end
  

Transaction.h

 #import <Cocoa/Cocoa.h>

typedef enum{cash,credit} transactionType;

@interface Transaction : NSObject {

        transactionType type;
        double amount;

}

-(void)createTransaction:(double)theAmount ofType:(transactionType)theType;
-(double)returnAmount;
-(transactionType)returnType;

@end
  

Transaction.m

 #import "Transaction.h"

@implementation Transaction

-(void)createTransaction:(double)theAmount ofType:(transactionType)theType{

        type=theType;
        amount=theAmount;

}

    -(double)returnAmount{

            return amount;

    }

    -(transactionType)returnType{

            return type;

    }

@end
  

Вывод

 The Elements are:
2011-04-15 18:12:11.039 BudObj.m[2180:a0f] <Transaction: 0x10010c950> //Could not retreive the data from the array it's showing up some address
2011-04-15 18:12:11.039 BudObj.m[2180:a0f] <Transaction: 0x100104fe0> //
2011-04-15 18:12:11.040 BudObj.m[2180:a0f] <Transaction: 0x100106c60> //
2011-04-15 18:12:11.040 BudObj.m[2180:a0f] <Transaction: 0x100106d00> //
2011-04-15 18:12:11.041 BudObj.m[2180:a0f] Converting 100.00 US Dollars into Foreign Currency leaves $900.00
2011-04-15 18:12:11.041 BudObj.m[2180:a0f] Converting 100.00 US Dollars into Foreign Currency leaves $800.00
2011-04-15 18:12:11.041 BudObj.m[2180:a0f] Converting 200.00 US Dollars into Foreign Currency leaves $600.00
2011-04-15 18:12:11.042 BudObj.m[2180:a0f] Converting 300.00 US Dollars into Foreign Currency leaves $300.00
  

Ответ №1:

 for (Transaction* transaction in transactions) {
   //do stuff here, or just print the object with something like the code below
   NSLog(@"Transaction:  %@", transaction);
}
  

Конечно, когда у вас есть код, подобный этому:

 [aTransaction createTransaction:n*100 ofType:credit];
[transactions addObject:aTransaction];
  

…на самом деле вы не сохраняете вновь созданную транзакцию в массиве. Вы просто сохраняете переменную aTransaction несколько раз. Возможно, вам повезет больше с чем-то вроде:

 Transaction* nextTransaction = [aTransaction createTransaction:n*100 ofType:credit];
[transactions addObject:nextTransaction];
  

Редактировать:

Возможно, вам повезет больше с:

 #import <Foundation/Foundation.h>
#import "BudObj.h"
#import "Transaction.h"
int main(int argc, char *argv[]) {
        Budget* europeBudget=[[Budget alloc] init];
        NSMutableArray *transactions=[[NSMutableArray alloc] initWithCapacity:10];
        [europeBudget createBudget:1000.00 withExchangeRate:1.2500];
        Transaction* aTransaction = nil;
        for(int n=1;n<2;n  ){
                //this adds 1 transaction to the array
                aTransaction = [[[Transaction alloc] init] autorelease];
                [aTransaction createTransaction:n*100 ofType:cash];
                [transactions addObject:aTransaction];
        }

        int n=1;
        while (n<3) {
                //this adds 2 transactions to the array
                aTransaction = [[[Transaction alloc] init] autorelease];
                [aTransaction createTransaction:n*100 ofType:credit];
                [transactions addObject:aTransaction];
                n  ;
        }

        do{
                //this adds 1 transaction to the array
                aTransaction = [[[Transaction alloc] init] autorelease];
                [aTransaction createTransaction:n*100 ofType:cash];
                [transactions addObject:aTransaction];
                n  ;
        }while (n<=3);

        //there should be 4 elements in the array now
        NSLog(@"nNumber of elements in an array:%i",[transactions count]);  
        int c;
        c=[transactions count];
        NSLog(@"nThe Elements are:n");
        for(int i=0;i<c;i  ){
                Transaction* trans = [transactions objectAtIndex:i];
                NSLog(@"Transaction %d:  %@; type=%d, amount=%f", i, trans, [trans returnType], [trans returnAmount]);
        }

        for(Transaction *aaTransaction in transactions){
         switch ([aTransaction returnType]) {
                case cash:
                        [europeBudget spendDollars:[aaTransaction returnAmount]];
                        break;
                case credit:
                        [europeBudget changeForeignCurrency:[aaTransaction returnAmount]];
                        break;
                default:
                        break;
         }
        }
        [transactions release];
        [europeBudget release];

        return 0;
}
  

Адрес, который вы видите в своих выходных данных, не означает, что программа не смогла найти Transaction в массиве. На самом деле, это означает прямо противоположное. Адрес — это адрес в памяти вашего Transaction экземпляра. Причина, по которой он печатается как адрес, заключается в том, что это поведение по умолчанию при печати NSObject экземпляра. Ваш класс не переопределяет это поведение по умолчанию, поэтому вы получаете адрес памяти при его печати.

Если вы хотите переопределить это поведение по умолчанию, вы можете сделать что-то вроде:

 #import "Transaction.h"

@implementation Transaction

    //override the 'description' method to change how your object prints
    -(NSString*)description {
        NSString* friendlyType = theType == cash ? @"cash" : @"credit";
        return [NSString stringWithFormat:@"Transaction:  type=%@, amount=%f", friendlyType, amount];
    }

    -(void)createTransaction:(double)theAmount ofType:(transactionType)theType{
        type=theType;
        amount=theAmount;
    }

    -(double)returnAmount{
            return amount;
    }

    -(transactionType)returnType{
            return type;
    }

@end
  

Комментарии:

1. Я тоже пробовал это. Я получаю некоторый адрес, распечатанный в качестве выходных данных.

2. @Beata Jane — вероятно, это адрес экземпляров вашего объекта. Если вы предоставите некоторые подробности о том, какие поля / свойства существуют в Transaction объекте, мы можем предоставить несколько лучших примеров того, как печатать их осмысленным способом.

3. @aroth-Я отредактировал код и предоставил полную программу выше. пожалуйста, ознакомьтесь с ней.

4. @Beata Jane — Извините за задержку, я обновил свой ответ. Надеюсь, это поможет прояснить ситуацию.

Ответ №2:

Вы уже извлекаете объекты из массива в последних 4 строках вашего кода.

При использовании [transactions objectAtIndex:i] этого будет возвращен i'th transaction объект в массиве.

Комментарии:

1. Я помещаю это в цикл for, поэтому должен отображаться объект с индексом 0,1,2, независимо от того, какое количество. Но я все еще не мог понять, как извлечь элементы из массива.

Ответ №3:

Проблема, с которой вы сталкиваетесь, заключается в том, что вы выводите свой объект как целое число ( i ) в вашем NSLog . Вместо этого вы должны использовать @ .

Другая проблема заключается в том, что объекты в Objective-C являются ссылочными типами. Это означает, что когда вы присваиваете объект другому объекту, скажем:

 Transaction* transA = [[Transaction alloc] init];
Transaction* transB = [[Transaction alloc] init];

transB = transA;
  

Первые две строки создают два отдельных объекта. Но третья строка присваивает transB в качестве ссылки на transA . То есть это один и тот же объект. Кроме того, это приводит к утечке памяти, поскольку transB больше не указывает на исходный объект.

Хотя я не уверен на 100%, как работает создание вашего объекта, строки, похожие на [aTransaction createTransaction:n*100 ofType:cash]; , присваивают значения одному и тому же объекту ( aTransaction ). Это означает, что, скорее всего, все объекты, содержащиеся в вашем массиве, являются указателями на один и тот же объект. Более того, это может быть утечка памяти, если они не возвращают автоматически выпущенные объекты.


Простой способ зарегистрировать элементы в NSArray or NSMutableArray (или, возможно, в любом типе коллекции) — это просто сделать:

 NSArray* someArray = [NSArray array];
// Add items here.
NSLog(@"SomeArray: %@", someArray);
  

Выходные данные будут автоматически отформатированы для вас.

Комментарии:

1. Я пытался с тем же, что вы сказали, но, похоже, он отображает какой-то адрес