0

私は Ojective-C で 1 か月だけコーディングしていて、デッドロックに陥っています。助けが必要。これが話です:

  1. 私は単純なクラスLXPPlayingCardを持っています:

     #import <Cocoa/Cocoa.h>
     @interface LXPPlayingCard : NSObject {
     @private NSString* cardCV;
     @private int position;
     }
    
     @property (readwrite, assign) NSString* cardCV;
     @property (readwrite,assign) int position;
     @end
    
     @implementation LXPPlayingCard
     @synthesize cardCV;
     @synthesize position;
     @end
    
  2. また、より複雑なクラス LXPDeck はほとんどありません。

    #import <Cocoa/Cocoa.h>
    #import "LXPPlayingCard.h"
    @interface LXPDeck : NSObject {
    LXPPlayingCard* cards[100];
    int deckCapacity;
    }
    
    -(void) fill:(NSString *) cardlist;
    -(void) showList;
    -(int) deckCapacity;
    
    @end
    
    #import "LXPDeck.h"
    #import "LXPPlayingCard.h" 
    @implementation LXPDeck
    -(void) fill:(NSString *) cardlist {
        int l,i,j;
        l=[cardlist length];
        j=0;
        for (i=0;i<l;i+=2) {
            cards[j]=[[LXPPlayingCard alloc] init] ;        
            [cards[j] setCardCV:[cardlist substringWithRange:NSMakeRange(i,2)]];
            [cards[j] setPosition:j+1];
            NSLog(@"%@",[cards[j] cardCV]);
            j++;
        }
      deckCapacity=j;
      }
    
      -(int) deckCapacity { return deckCapacity;}
    
      -(void) showList {
      NSLog(@"deck capacity:%d",deckCapacity);
      NSString * temp;
      temp=[[NSString alloc] init];
      for (int i=0;i<deckCapacity;i++) {
        NSLog(@"card[%d]=%d, adress:%p",i,[cards[i] position],cards[i]);
        temp=[cards[i] cardCV];
        NSLog(@"%@",temp);
        }
         }
    
     @end
    

カードの配列に文字列から名前を入力し (setCardCV)、デッキの内容を出力します (showList)。さらに、クラス AppController を作成します。

@interface LXPAppController : NSObject {

}
-(IBAction) openNewDeck:(NSButton * )sender;
-(IBAction) printDeckContent:(NSButton *)sender ;

@end

#import "AppController.h"
#import "LXPDeck.h"


@implementation LXPAppController
    BOOL deckOpened=FALSE;
    LXPDeck* workDeck;

-(IBAction) openNewDeck:(NSButton *) sender{

    if (!deckOpened) {
        NSLog(@"Opening new deck...");
        workDeck=[LXPDeck alloc];
        [workDeck fill:@"pacataca"];
    }

    deckOpened=TRUE;
}
-(IBAction) printDeckContent:(NSButton *) sender {

    if (deckOpened) {
        NSLog(@"Printing deck content...");
        [workDeck showList];
    }
}
@end

私がリンクしたメインウィンドウの2つのボタンopenNewDeckprintDeckContentメソッド。問題は、アプリケーションがエラー「EXC_BAD_ACCESS」で落ち、(デバッガーを使用すると) CFString ではないiため、=3で発生することです。[card[i] cardCV]

デッキを埋めるためにさまざまな文字列を試してみましたが、プログラムが[cards[i] cardCV]. 何が起こるかはよくわかりませんが、単純なタイプのデータ(positionたとえば)には問題がなく、showListメソッドから呼び出すとメソッドが正常に動作するため、ポインターとメモリ割り当てルールに何らかの関係があると思いますfill。手を貸してください!私は気が狂うよ!プログラムはとても単純なので、将来のコーディングの問題が心配です...

4

1 に答える 1

0

問題はそれです

[cardlist substringWithRange:NSMakeRange(i,2)]]

NSString所有していない を返します。所有していないため、文字列がLXPPlayingCardオブジェクトの存続期間中有効であるという保証はありません。その文字列への有効な参照を保持したい場合は、プロパティがプロパティではなくプロパティになるLXPPlayingCardように宣言を変更する必要があります。交換:cardCVcopyassign

@property (readwrite, assign) NSString* cardCV;

と:

@property (readwrite, copy) NSString* cardCV;

これを行うことで、次-setCardCV:のように送信すると:

[cards[j] setCardCV:[cardlist substringWithRange:NSMakeRange(i,2)]];

setCardCVはその引数をコピーし[cardlist substringWithRange:NSMakeRange(i,2)]、オブジェクトはその文字列の所有権を持ちます。これは、文字列がそのオブジェクトのライフサイクルを通じて有効であることを意味します。その文字列の所有権を取得したので、それを解放する責任があることに注意してください。-deallocしたがって、メソッドを実装する必要があります。

- (void)dealloc {
    [cardCV release];
    [super dealloc];
}

これは、対応するLXPPlayingCardが解放されると、 に格納されている文字列も解放されることを意味しcardCVます。

于 2011-04-19T09:28:15.137 に答える