2012-09-01 2 views
0

Objective C 및 Cocoa로 그립을 잡으려고하고 있으므로 여기에서 잘못된 용어를 사용하고있을 수 있습니다.Array 객체에서 objectAtIndex를 사용하는 방법

내 주요 AppDelegate.h 두 가지 방법, deckOfCards & pickACard을 가지고 & AppDelegate.m, 읽 한 벌의 카드에 대한 목표 C 클래스를했습니다. deckOfCards 그냥있는 NSMutableArray는 다음 pickACard에서이 같은 새로운 배열을 만들 문자열 형태로 기록 된 모든 카드 유형입니다 :

-(void)pickACard 
{ 
    DeckOfCards *newDeck = [[DeckOfCards alloc] init]; 
    int r = arc4random() % 52; 
    NSLog (@"The card you picked is: %@, and there are %i cards left", [newDeck  objectAtIndex:r], [newDeck count]); 
    [newDeck removeObjectAtIndex:r]; 
} 

그러나 엑스 코드 나는이 새로운 배열에 objectAtIndex & removeObjectAtIndex을 사용할 수 없다는 것을 말하고있다 때문에, 나는 무작위로 카드를 선택한 다음 배열의 해당 부분을 제거하여 "팩에서 제거"할 수 없습니다.

이것은 모두 deckOfCards에있을 때 작동했지만 AppDelegate.m에 의해 호출되었을 때 새로운 배열을 작성하므로 다른 카드를 가져올 수 있지만 팩에서 둘 이상을 제거하지 마십시오.

나는이 새로운 배열을 제대로 만들지 않을 것이라고 추측 할 것입니다. 있는 NSMutableArray의 서브 클래스

@implementation DeckOfCards 
-(void)deckOfCards 
{ 
NSMutableArray *deckOfCards = [NSMutableArray arrayWithObjects: 
    @"One of Hearts", @"Two of Hearts"..., nil]; 
} 
-(void)pickACard 
{ 
    DeckOfCards *newDeck = [[DeckOfCards alloc] init]; 
    int r = arc4random() % 52; 
    NSLog (@"The card you picked is: %@, and there are %i cards left",[newDeck  objectAtIndex:r], [newDeck count]); 
    [newDeck removeObjectAtIndex:r]; 
} 

@end 
+0

'DeckOfCards *'란 무엇입니까? – kennytm

+0

은 NSArray 하위 클래스 인 DeckOfCards입니까? 또는 그것의 구현에 NSArray를 사용합니까? – wattson12

+1

실제 오류 메시지는 무엇입니까? – rdelmar

답변

3

그러나 엑스 코드는

없음

, 당신이 배열에 그것을 사용하려고하지 않는 것을 말하는 ... 나는이 새로운 배열에 objectAtIndex & removeObjectAtIndex을 사용할 수 없다는 것을 말하고있다.

은 당신이 그것을 사용하려고하는 것은 DeckOfCards입니다 :

DeckOfCards *newDeck = [[DeckOfCards alloc] init]; 
int r = arc4random() % 52; 
NSLog (@"The card you picked is: %@, and there are %i cards left", [newDeck  objectAtIndex:r], [newDeck count]); 
[newDeck removeObjectAtIndex:r]; 

newDeck는 당신이 첫 번째 줄에 만든 DeckOfCards 서비스를 제공합니다.

@interface DeckOfCards : NSObject 

DeckOfCards 단순히 목적 :

DeckOfCards 배열 아니다. 단지 어떤 대상도 아닙니다. 당신은 그것을 추가했습니다 (deckOfCardspickACard 방법). 그러나 배열이 아니므로 objectAtIndex:에 응답하지 않으며 가변 배열이 아니므로 removeObjectAtIndex:에도 응답하지 않습니다.

그럼 을 수행 하시겠습니까? 배열이 있습니까?

-(void)deckOfCards 
{ 
NSMutableArray *deckOfCards = [NSMutableArray arrayWithObjects: 
    @"One of Hearts", @"Two of Hearts"..., nil]; 
} 

그러나 그 배열에 발생 : 글쎄, 당신은 당신의 deckOfCards 방법 중 하나 만들?

아무것도 아니요. 당신이 그것을 만들고 바닥에 놓습니다. 당신은 그것을 당신에게 불리는 것에 돌려 보내지 않습니다. 이 메서드는 void을 반환하기 때문에 실제로는 할 수 없습니다.

일시적으로 프로그래밍에 아주 새로운 가정 용서받을 수있는 구조적 문제를 제쳐두고, 당신은 몇 가지 수행해야합니다

  1. 변경 deckOfCards 메소드의 선언이이 반환됩니다 선언하기를 NSMutableArray *이 아니라 void입니다.

    return deckOfCards; 
    

    을 (그리고 deckOfCards 여기에 배열 *을 말한다 있습니다.)

  2. 변경 pickACarddeckOfCards 전화 :

  3. 즉시 배열을 반환 배열의 생성 후 라인을 추가합니다. 그러면 배열이 만들어지고 (# 2 번 변경하면) 반환됩니다. deckOfCards에서 선언 한 변수와 비슷한 pickACard의 변수를 선언하고 그 결과를 deckOfCards에 할당하십시오.

  4. pickACard에 배열이 있으므로 항목 중 하나를 검색하여 기록하고 제거 할 수 있습니다. objectAtIndex:removeObjectAtIndex: 메시지를 배열이 아닌 개체가 아닌 배열로 보내면됩니다.
  5. 여기에있는 동안 r의 유형을 수정하십시오. NSArray 인덱스의 유형은 NSUInteger이며 int이 아닙니다.

이제 프로그램을 컴파일하고 실행하고 거의 작동해야합니다.

거의? 음, 할 일이 하나 더 있습니다.

deckOfCards은 매번 새로운 데크를 생성합니다. 당신은 그 덱에서 하나의 카드를 제거하지만 그 덱에 관한 모든 것을 잊어 버리고 다음에 새로운 덱을 사용할 것입니다.

이것은 다음 도전 과제입니다. 프로그램을 초기화 할 때 덱을 만들고 변경하고 추첨 할 때마다 그 덱을 기억하고 재사용하십시오. 그 순간에 신선한 갑판을 만들어서 갑판이 고갈 된 경우 (더 이상의 카드가없는 경우)를 올바르게 처리하십시오.

(첫 번째 본능은 첫 번째 초안으로 만 사용하십시오.) 그런 다음 데크 생성 코드가 한 곳에만 있고 그 목적을위한 방법이 있고 그 방법을 호출하도록 변경하십시오 신선한 갑판을 만들어야하는 두 곳에서.)

나는 당신에게 힌트를 줄 것이다 : 인스턴스 변수. 그 방법, 당신은 그 안에 선언 배열 : 당신의 deckOfCards 방법에서


*

, 당신은 두 deckOfCards라는 것을 볼 수 있습니다. 같은 이름의 두 가지.컴파일러는 상관하지 않습니다. 메소드와 변수는 별도의 네임 스페이스에 존재하기 때문에 어떤 순간에 어떤 것이 있는지 알지 못한다. 하지만 다른 사람들이 무엇을 바꿀지에 대한 제안은 말할 것도없이 자신의 이해를 돕기 위해 하나 또는 다른 것을 바꿔야 할 것입니다 (" deckOfCards와 함께하십시오."라고 말할 수는 있겠지만 어떤 의미입니까?).

배열 변수의 이름을 바꾸는 것이 좋습니다. 그냥 array으로 이름을 짓기 만하면됩니다. (단, 해당 메소드 내에서 선언 된 로컬 변수 인 한)

인스턴스 변수로 만들 때 이름을 더 구체적인 것으로 변경하십시오. _deckOfCards은 일반적으로 일반적인 명명 규칙입니다.이 밑줄은이 이름이 인스턴스 변수의 이름이라는 것을 알려줍니다 (다시 컴파일러는 신경 쓰지 않습니다).

1

DeckOfCards되지 않고는 - objectAtIndex:를 구현하지 않습니다

#import <Foundation/Foundation.h> 

@interface DeckOfCards : NSObject 
{ 
@private 
} 
-(void) deckOfCards; 
-(void) pickACard; 

@end 

DeckOfCards.m이 있습니다 :

그냥 더 명확하게하기 위해, DeckOfCards.h이있다 그리고 - removeObjectAtIndex: 방법 중 하나를 사용하십시오. 따라서이 방법을 사용할 수 없으므로 좋습니다.

4

여기에 몇 가지 문제가 있습니다. 컴파일러 문제의 직접적인 원인은 DeckOfCards의 인스턴스에서 NSMutableArray 메서드를 호출하려고한다는 것입니다. 대신, 메서드에서 반환 된 NSMutableArray에서 이러한 메서드를 호출 할 수 있습니다. 그것은 다음과 같이 보일 것입니다 :

DeckOfCards *newDeck = [[DeckOfCards alloc] init]; 
NSMutableArray *deckArray = [newDeck deckOfCards]; 
int r = arc4random() % 52; 
NSLog (@"The card you picked is: %@, and there are %i cards left",[deckArray objectAtIndex:r], [deckArray count]); 
[deckArray removeObjectAtIndex:r]; 

그러나 이것은 우리의 다음 문제로 우리를 인도 - 그것의 반환 형식이 void으로 정의된다 - 실제로는 아무 것도 반환하지 않습니다 -deckOfCards. 따라서 NSMutableArray 인스턴스를 나머지 프로그램으로 다시 가져 오려면 return이 있어야하며 적절한 반환 유형으로 메소드를 정의하십시오. 우리가이 문제를 해결한다면, 우리는 다음처럼 -deckOfCards 방법을 변경 것 :

-(NSMutableArray *)deckOfCards 
{ 
    NSMutableArray *deckOfCards = [NSMutableArray arrayWithObjects: 
     @"One of Hearts", @"Two of Hearts"..., nil]; 

    return deckOfCards; 
} 

확인을, 즉 지금 컴파일해야하므로. 그러나 심각한 오류가 있습니다. 지금 당장이 대답을 할 시간이별로 없지만 객체와 클래스의 차이점과 객체와 메모리 관리의 수명에 초점을 맞춘 Objective-C 입문서를 읽어 보시기 바랍니다. 본질적으로 아무 것도 지속되지 않습니다. DeckOfCards의 인스턴스에서 -pickACard을 몇 번 호출했는지에 관계없이 항상 인스턴스화 된 인스턴스가 별도로 생성되어 새로운 NSMutableArray 인스턴스가 생성됩니다. 그러나 이러한 객체 중 어느 것도 (자동 참조 카운팅을 사용한다고 가정 할 때) 유지되지 않으며 즉시 사라집니다. 따라서 항상 새로운 카드 덱을 -pickACard에서 가져와야합니다.

이 정보가 도움이되기를 바랍니다. Objective-C 및 객체 지향 프로그래밍의 기초를 읽고 배우는 데 시간을 들여 원하는대로이 프로그램을 작동시킬 수 있습니다.질문이있는 경우 알려 주시면 답변 해 드리겠습니다.

2

다른 의견 작성자의 말처럼, 앱의 구조에는 여러 가지 문제가 있습니다. 이 문제에 접근하는 방법을 보여주기 위해 예제 애플리케이션을 만들었습니다. 첫째, DeckOfCards 클래스에서 카드 덱을 보유하고있는 가변 배열을 가리키는 속성을 원합니다. 이것을 그냥 갑판이라고합니다. 그런 다음 DeckOFCards 클래스의 인스턴스를 반환 할뿐만 아니라 해당 배열을 만들고 채우는 init 메서드가 필요합니다. 여기 DeckOfCards 클래스에 넣은 것이 있습니다. .H에서

, 그냥이 :

@interface DeckOfCards : NSObject 

@property (retain,nonatomic) NSMutableArray *deck; 

@end 

그리고,하는 .m에서 :

-(id)init { 
    if (self = [super init]) { 
     NSArray *cardNames = [NSArray arrayWithObjects:@"Two",@"Three",@"Four",@"Five",@"Six",@"Seven",@"Eight",@"Nine",@"Ten",@"Jack",@"Queen",@"King",@"Ace",nil]; 
     NSArray *suits = [NSArray arrayWithObjects:@" of Hearts",@" of Diamonds",@" of Spades",@" of Clubs",nil]; 
     self.deck = [NSMutableArray array]; 
     for (NSString *aCard in cardNames) { 
      for (NSString *aSuit in suits) { 
       [self.deck addObject:[aCard stringByAppendingString:aSuit]]; 
      } 
     } 
    } 
    return self; 
} 

당신은이 클래스의 인스턴스를 생성하고 다른 클래스 내부에서 카드를 선택하려면 , DeckOfCards 클래스 자체가 아닙니다. 이 예제에서는 앱 위임 (단순함을 위해 )에서이를 수행했지만 일부 컨트롤러 클래스에서는이를 수행하는 것이 좋습니다. 그래서, 나는 그 인스턴스에 대한 참조를 유지하는 aNewDeck을 가지고있다. (컴파일러는 "new"로 시작하는 이름을 사용하지 못하게한다. 왜 그런지, 또는 그것이 사자의 새 것이라면). applicationDidFinishLoading 메서드에서 새 인스턴스를 만든 다음 IBAction을 카드를 선택하는 단추에 연결합니다. 랜덤 넘버 생성기를 52를 사용하지 않도록 변경했지만 배열의 개수를 변경했음을 주목하십시오. 그렇게하지 않으면 배열보다 작은 숫자를 선택하게됩니다. 배열에 액세스하려면 aNewDeck.deck을 사용합니다.이 메서드는 aNewDeck 인스턴스의 속성, 데크에 액세스하는 방법입니다. 여기에 .H 파일입니다 :

@class DeckOfCards; 
#import <Cocoa/Cocoa.h> 

@interface AppDelegate : NSObject <NSApplicationDelegate> 

@property (assign) IBOutlet NSWindow *window; 
@property (strong) DeckOfCards *aNewDeck; 

-(IBAction)pickACard:(id)sender ; 

@end 

여기하는 .m이다 :이 시작하는 데 도움이되기를 바랍니다

#import "AppDelegate.h" 
#import "DeckOfCards.h" 

@implementation AppDelegate 

- (void)applicationDidFinishLaunching:(NSNotification *)aNotification { 
    self.aNewDeck = [[DeckOfCards alloc] init]; 
} 

-(IBAction)pickACard:(id)sender { 
    if (self.aNewDeck.deck.count != 0) { 
     int r = arc4random() % [self.aNewDeck.deck count]; 
     NSLog (@"The card you picked is: %@, and there are %li cards left", [self.aNewDeck.deck objectAtIndex:r], [self.aNewDeck.deck count] - 1); 
     [self.aNewDeck.deck removeObjectAtIndex:r]; 
    }else{ 
     NSLog(@"Game Over!"); 
    } 
} 

.

관련 문제