1

化学反応のクイズアプリを作っています。アプリはユーザーに質問を与え、ユーザーは2つの別々のテキストフィールドに反応物と生成物を入力します。

考えられるすべてのクイズの質問を含むデータクラスがあります。次に、特定のパラメーターに基づいて、データクラスは、可能な質問のプールから特定の量の質問を選択し、それらを配列にシャッフルしますquizQuestions

ビューコントローラもありますquizController。質問ごとに、の新しいインスタンスquizControllerが読み込まれます。vcには、表示する質問、正解などを知るためのデータが必要です。

これは、データとVCの間で通信するための私のオリジナルのソリューションです。

データクラスのインスタンスを作成しますdatavc1最初の質問用に作成しdata、のプロパティとしてvc1設定し、そのタグを1に設定して、データから最初の質問をロードします。

ユーザーが最初の質問に答えた後、新しいビューコントローラーを作成します。vc2メソッドでvc1、タグ1を最後のvcよりも大きくして、2番目の質問が読み込まれるようにし、'sプロパティdataから'sに渡します。vc1vc2

そして、他の質問についても繰り返します。

ただし、これはあまり良い設計ではなく、より良い解決策を探しています。dataにはランダムな質問のセットが含まれているはずなので、クラスメソッドを使用できるとは思いません。以下に、データクラスのコードを示します。

// the data class as it is now, designed for instance methods

- (id)init {
self = [super init];
if (self) {

    //Questions of the same type belong to a "ROW" (Reaction of Week)
    //individual questions
    // Items in array: (1)Question, (2)Reactants, (3)Products, (4)Elements for keyboard

    NSArray *R1Q1 = [[NSArray alloc] initWithObjects:@"Methanol is burned completely in air", @"2CH₃OH(l) + 3O₂(g)", @"2CO₂(g) + 4H₂O", @"C,H,O", nil];
    NSArray *R1Q2 = [[NSArray alloc] initWithObjects:@"Ammonia is burned in excess oxygen gas", @"4NH₃(g) + 7H₂O(l)", @"4NO₂(g) + 6H₂O(l)", @"N,H,O", nil];
    NSArray *R1Q3 = [[NSArray alloc] initWithObjects:@"Hydrogen sulfide gas is burned in excess oxygen gas", @"2H₂S(g) + 3O₂(g)", @"CO₂(g) + 2SO₂(g)", @"H,S,O", nil];

    NSArray *R2Q1 = [[NSArray alloc] initWithObjects:@"Solid potassium is added to a flask of oxygen gas", @"K(s) + O₂(g)", @"KO₂(s)", @"K,O", nil];
    NSArray *R2Q2 = [[NSArray alloc] initWithObjects:@"Sodium metal is dropped into a flask of pure water", @"2Na(s) + H₂O(l)", @"2Na⁺(aq) + 2OH⁻(aq) + H₂(g)", @"Na,H,O", nil];
    NSArray *R2Q3 = [[NSArray alloc] initWithObjects:@"A piece of lithium is heated strongly in oxygen", @"4Li(s) + O₂(g)", @"2Li₂O(s)", @"Li,O", nil];

    NSArray *R3Q1 = [[NSArray alloc] initWithObjects:@"Solutions of potassium chloride and silver nitrate are mixed", @"Ag⁺(aq) + Cl⁻(aq)", @"AgCl(s)", @"K,Cl,Ag,N,O", nil];
    NSArray *R3Q2 = [[NSArray alloc] initWithObjects:@"Solutions of iron(III) nitrate and sodium hydroxide are mixed", @"Fe³⁺(aq) + 3OH⁻(aq)", @"Fe(OH)₃(s)", @"Fe,N,O,Na,H", nil];
    NSArray *R3Q3 = [[NSArray alloc] initWithObjects:@"Solutions of nickel iodide and barium hydroxide are mixed", @"Ni²⁺(aq) + 2OH⁻(aq)", @"Ni(OH)₂(s)", @"Ni,I,Ba,OH", nil];
    // add rest

    //organize questions into groups
    row1 = [[NSArray alloc] initWithObjects:R1Q1, R1Q2, R1Q3, nil];
    row2 = [[NSArray alloc] initWithObjects:R2Q1, R2Q2, R2Q3, nil];
    row3 = [[NSArray alloc] initWithObjects:R3Q1, R3Q2, R3Q3, nil];
    //add rest

    // array containing all questions
    allRows = [[NSMutableArray alloc] initWithObjects:row1, row2, row3, nil];

    //in a real situation, needs to be given to class dynamically 
    self.maxRowNumber = 3;
    self.questionsPerRow = 2;
}

return self;
}

- (void)selectQuestions {

self.quizQuestions = [[NSMutableArray alloc] init];

for (int j = 0; j<self.maxRowNumber; j++) {
   //shuffle each row
    NSMutableArray *row = [NSMutableArray arrayWithArray:[allRows objectAtIndex:j]];
    [row shuffle];

    //add questions from each row
    for (int k = 0; k<self.questionsPerRow; k++)       
       [quizQuestions addObject:[row objectAtIndex:k]];

}

[quizQuestions shuffle];

}

コントローラコードの抜粋を表示

    # pragma mark Cell Setup
    //1st cell in tableview
    - (void) setUpEquationCell: (UITableView *) tableView  {

    equationCell = (EquationCell *) [tableView dequeueReusableCellWithIdentifier:@"equationCell"];

    if (equationCell == nil) {   
        NSArray *nib =   [[NSBundle mainBundle] loadNibNamed:@"EquationCell" owner:self options:nil];
        equationCell = (EquationCell*) [nib objectAtIndex:0];
        [equationCell.leftButton addTarget:self action:@selector(addDissociateCell) forControlEvents:UIControlEventTouchUpInside];
        [equationCell.rightButton addTarget:self action:@selector(addBalanceCell) forControlEvents:UIControlEventTouchUpInside];
    }

}

    - (void) setUpBalanceCell: (UITableView *) tableView  {
            //2nd cell in tableview

    balanceCell = (BalanceCell *) [tableView dequeueReusableCellWithIdentifier:@"balanceCell"];

    if (balanceCell == nil) {   
        NSArray *nib =   [[NSBundle mainBundle] loadNibNamed:@"BalanceCell" owner:self options:nil];
        balanceCell = (BalanceCell*) [nib objectAtIndex:0];

        // stores data from equation cell into model
        for (FormulaLabel *label in equationCell.leftView.equationOrder) 
            [leftData.equation addObject:label.text];                                                 

        for (FormulaLabel *label in equationCell.rightView.equationOrder)  
            [rightData.equation addObject:label.text];

        [leftData setUpBalancedEquation];
        [rightData setUpBalancedEquation];
        [self setUpView:balanceCell.leftView fromArray:leftData.equation toArray:leftBalanceItems];
        [self setUpView:balanceCell.rightView fromArray:rightData.equation toArray:rightBalanceItems];
        [self addBalanceTapMethodInArray:leftBalanceItems Data:leftData];
        [self addBalanceTapMethodInArray:rightBalanceItems Data:rightData];
    }

}
    - (void) setUpDissociateCell: (UITableView *) tableView  {
    dissCell = (DissociateCell *) [tableView dequeueReusableCellWithIdentifier:@"dissCell"];

    if (dissCell == nil) {   
        NSArray *nib =   [[NSBundle mainBundle] loadNibNamed:@"DissociateCell" owner:self options:nil];
        dissCell = (DissociateCell*) [nib objectAtIndex:0];

        leftData.disEquation = [[NSMutableArray alloc] init];
        rightData.disEquation = [[NSMutableArray alloc] init];

        // stores data from equation cell into model
        for (FormulaLabel *label in equationCell.leftView.equationOrder) 
            [leftData.disEquation addObject:label.text];                                                 

        for (FormulaLabel *label in equationCell.rightView.equationOrder)  
            [rightData.disEquation addObject:label.text];

        [self setUpView:dissCell.leftView fromArray:leftData.disEquation toArray:leftDisItems];
        [self setUpView:dissCell.rightView fromArray:rightData.disEquation toArray:rightDisItems];
        [self addDissTapToArray:leftDisItems fromData:leftData inView:dissCell.leftView];
        [self addDissTapToArray:rightDisItems fromData:rightData inView:dissCell.rightView];
        [dissCell.dissociateButton addTarget:self action:@selector(dissociate) forControlEvents:UIControlEventTouchUpInside];
        }
    [dissCell.rightButton addTarget:self action:@selector(addBalanceCell) forControlEvents:UIControlEventTouchUpInside];

}




    - (void)addDissociateCell {

    [cellOrder addObject:@"dissociateCell"];
    [table reloadData];
    NSIndexPath *myIndexPath = [NSIndexPath indexPathForRow:0 inSection:([cellOrder count]-1)];
    [table scrollToRowAtIndexPath:myIndexPath atScrollPosition:UITableViewScrollPositionTop animated:YES];
}


- (void) addDissTapToArray:(NSMutableArray*)viewOrder fromData:(EquationData*)data inView:(UIView*)view {

    NSString *leftOrRight;

    if (view == dissCell.leftView) 
        leftOrRight = @"left";    
    else 
        leftOrRight = @"right";

    for (int j=0; j < [viewOrder count]; j++) {


        if (j%2==0) {
            UIView *formulaView = [viewOrder objectAtIndex:j];
            //dissociate method
            FalseTarget *target = [[FalseTarget alloc] initWithVC:self leftOrRightView:leftOrRight];
            UITapGestureRecognizer* tap = [[UITapGestureRecognizer alloc] initWithTarget:target action:@selector(dissTap:)]; 
            [formulaView addGestureRecognizer:tap];

            // cancelling method
            FalseTarget *target2 = [[FalseTarget alloc] initWithVC:self Data:data ViewList:viewOrder view:view];
            UILongPressGestureRecognizer *longPress = [[UILongPressGestureRecognizer alloc] initWithTarget:target2 action:@selector(dissLongTap:)];
            [formulaView addGestureRecognizer:longPress];
                  }

    }
}
- (void)addCompoundToLabel:(UIGestureRecognizer *)recognizer leftOrRight:(NSString*)leftRight{
    if( [recognizer state] == UIGestureRecognizerStateEnded ) {
        FormulaLabel* label = (FormulaLabel*)[recognizer view];  
        dissIndex = label.tag;
        dissCell.unDissociated.text = label.text;
        currentDissCellView = leftRight;
    }
}

- (void)dissociate {

    EquationData *data;
    NSMutableArray *viewOrder;
    UIView *view;

    if ([currentDissCellView isEqualToString:@"left"]) {
        data = leftData;
        viewOrder = leftDisItems;
        view = dissCell.leftView;
    }

    else {
        data = rightData;
        viewOrder = rightDisItems;
        view = dissCell.rightView;
    }

    FormulaLabel *c1 = [dissCell.leftTextField.equationOrder objectAtIndex:0];
    FormulaLabel *c2 = [dissCell.rightTextField.equationOrder objectAtIndex:0];
    [data updateDisEquationAtIndex:dissIndex withCompound1:c1.text Compound2:c2.text];

    for (UIView *view in viewOrder) 
        [view removeFromSuperview];

    [viewOrder removeAllObjects];
    [self setUpView:view fromArray:data.disEquation toArray:viewOrder];
    [self addDissTapToArray:viewOrder fromData:data inView:view];

}

- (void) cancelIons:(id)sender fromData:(EquationData *)data inView:(UIView *)view withViewList:(NSMutableArray *)viewlist {
    if( [sender state] == UIGestureRecognizerStateEnded ) {

        FormulaLabel* label = (FormulaLabel*)[sender view];  
        int index = label.tag;
        [data.disEquation removeObjectAtIndex:index];

        for (UIView *formulaView in viewlist) 
            [formulaView removeFromSuperview];

        [viewlist removeAllObjects];
        [self setUpView:view fromArray:data.disEquation toArray:viewlist];
        [self addDissTapToArray:viewlist fromData:data inView:view];


    }
}

    - (void)addBalanceCell {

    [cellOrder addObject:@"balanceCell"];
    [table reloadData];
    NSIndexPath *myIndexPath = [NSIndexPath indexPathForRow:0 inSection:([cellOrder count]-1)];
    [table scrollToRowAtIndexPath:myIndexPath atScrollPosition:UITableViewScrollPositionTop animated:YES];

    leftBalanceItems = [[NSMutableArray alloc] init];
    rightBalanceItems = [[NSMutableArray alloc] init];
}

    - (void) addBalanceTapMethodInArray:(NSMutableArray *)balanceItems Data:(EquationData *)data {

    FalseTarget *target = [[FalseTarget alloc] initWithVC:self Data:data ViewList:balanceItems view:nil];

    for (UIView *view in balanceItems) {
        UITapGestureRecognizer* tap = [[UITapGestureRecognizer alloc] initWithTarget:target action:@selector(tap:)];
        [view addGestureRecognizer:tap];
    }

}


    - (void)updateBalanceLabelofSender:(UIGestureRecognizer*)sender fromData:(EquationData *)data inArray:(NSMutableArray *)balanceItems {

    FormulaLabel* label = (FormulaLabel*)[sender view];
    int oldWidth = label.frame.size.width;
    label.text = [data updateBalancedatIndex:label.tag];
    [label sizeToFit];
    int newWidth = label.frame.size.width;
    int difference = newWidth - oldWidth;
    int labelIndex = label.tag * 2;

    for (int j = 0; j<[balanceItems count]; j++) {
        // adjusts coordinate of  all views to the right of tapped item

        if (j > labelIndex){
            UIView *item = [balanceItems objectAtIndex:j];
            item.frame = CGRectMake(item.frame.origin.x + difference, item.frame.origin.y, item.frame.size.width, item.frame.size.height);
        }
    }
}


    - (void)setUpView:(UIView *)view fromArray:(NSMutableArray *)equationData toArray:(NSMutableArray *)balanceItems {

    int labelCount = 0; //label #
    int startingPoint = 5; //x vaiue where first label starts

    for (NSString *equationText in equationData) {

        //add text
        FormulaLabel *tempLabel = [[FormulaLabel alloc] initWithFrame:CGRectMake(startingPoint, 2, 10, 22)];
        tempLabel.text = equationText;
        [tempLabel sizeToFit];
        [view addSubview:tempLabel];
        tempLabel.tag = labelCount;
        [balanceItems addObject:tempLabel];
        //set location of '+'
        startingPoint = tempLabel.frame.origin.x + tempLabel.frame.size.width + 3;

        if (labelCount != [equationData count]-1) { //not the last label

            UILabel *plus = [[[UILabel alloc] initWithFrame:CGRectMake(startingPoint, 5, 10, 10)]autorelease];
            plus.text = @"+";
            plus.font = [UIFont systemFontOfSize:13];
            [plus sizeToFit];
            [view addSubview:plus];
            startingPoint = plus.frame.origin.x + plus.frame.size.width + 3;
            [balanceItems addObject:plus];
        }

        labelCount ++;
        [tempLabel release];
    }

}
4

3 に答える 3

0

UIViewControllerあなたはデータモデルについて知っていることを強制しているので、私はそれをしません(それをプロパティにしている間)。私がすることはクラスであり、クラスメソッド(オブジェクトメソッドではない)を使用するとデータソースが作成されます。どういうわけかデータを保持する必要がありますが、aま​​たはaで十分UIViewControllerだと思います。NSArrayNSDictionary

-(void)viewDidLoad{
  [superViewDidLoad];
  myArray = [MyModel createDataSourceForTag:myTag];
} 
于 2012-06-13T06:51:04.060 に答える
0

ここでは、モデル構造を使用する必要があると思います。

1.モデル:モデルはエンティティを表します。ここであなたの場合、私は2つのエンティティを作成できますラウンド、質問

@interface Round: NSObject {

    NSUInteger *roundId; // 1, 2 = if it is required to check then this mi
    NSArray *questions; // Array that contains objects for Question entity
}


@interface Question:NSObject {

    NSString *questionText;
    NSString *options1Text;
    NSString *options2Text;
    NSString *options3Text;
}


@interface DataManager:NSObject {

    NSArray *rounds; // Array that contains object for Round entity
}

+(void)sharedInstance;

2. DataManger:DataManagerはエンティティオブジェクトを管理します。このデータマネージャーはsharedInstanceクラスになります。そのため、マネージャーの初期化中に、エンティティが作成され、データが挿入されます。

3. ViewController: View Controllerで、次のようにsharedInstaceを直接使用できるようになりました。

[[DataManager sharedInstance] rounds]

sharedInstanceクラスを作成するためのコードを簡単に取得できます。

これで、アプリケーション全体のどこでもこのラウンドを使用できます。そのため、静かにアクセスしやすくなります。たとえば、第1ラウンド、第2質問、第3オプションが必要な場合は、同じ方法でコードを記述します。

ラウンド1

Round *r = [[[DataManager sharedInstance] rounds] objectAtIndex:0];

質問2

Question *q = [[r questions] objectAtIndex:1];

質問テキストとオプション3

NSLog(@"questionText : %@  3rd Option: %@", q.questionText, q.option3Text)

コーディングをお楽しみください:)

于 2012-06-13T18:36:17.707 に答える
0

プロパティのsetterメソッドをオーバーロードしてUIを新しいデータに更新するquestion-propertyで1つのViewControllerクラスを使用できないのはなぜですか。

QuestionViewController.hファイル内:

@property (retain, nonatomic) Question* myQuestionData;

QuestionViewController.mで

-(void) setMyQuestionData:(Question*)newData {
   [myQuestionData autorelease];
   myQuestionData = [newData retain];
   [self updateUIElements];
}
于 2012-06-29T17:44:02.747 に答える