2012-06-13 74 views
1

我正在爲化學反應做一個測驗應用程序。該應用程序給用戶一個問題,用戶在兩個單獨的文本框中鍵入反應物和產品。我如何更改此代碼,使其不違反MVC原則?

我有一個數據類,其中包含所有可能的測驗問題。然後,根據具體參數,數據類從可能的問題池中選擇一定數量的問題,並將它們混合成一個數組,quizQuestions

我也有一個視圖控制器,quizController。對於每個問題,加載一個新的quizController實例。 vc需要數據來知道要顯示哪個問題,正確答案是什麼等等。

這是我原來的解決方案,用於在數據和vc之間進行通信。

我創建了一個數據類的實例,data。 我爲第一個問題創建vc1,並將data設置爲vc1的屬性,並將其標記設置爲1,以便從數據加載第一個問題。

用戶回答第一個問題後,我創建了一個新的視圖控制器,vc2,在vc1的方法,使標籤比去年VC的1更使第二個問題的負載,並通過datavc1的財產到vc2's。

然後我重複其他問題。

但是,這不是很好的設計,我正在尋找更好的解決方案。我不認爲我可以使用類方法,因爲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]; 
    } 

} 

回答

0

爲什麼你不能用一個視圖控制器類,你超載屬性的setter方法來更新UI的新數據的問題屬性:

在QuestionViewController.h文件:

@property (retain, nonatomic) Question* myQuestionData; 

在QuestionViewController.m

-(void) setMyQuestionData:(Question*)newData { 
    [myQuestionData autorelease]; 
    myQuestionData = [newData retain]; 
    [self updateUIElements]; 
} 
+0

我正在考慮這個;我唯一擔心的是在視圖控制器中有很多對象需要刪除,並在用戶移動到新問題時重新實例化。 – Mahir

+0

例如,我有一個以1個單元格開始的tableview。用戶在文本框中輸入一些數據,並添加另一個單元格。然後用戶輸入更多數據,並添加另一個單元格。如果我這樣做,我將不得不刪除單元格2-3和其中的所有內容以及與這些單元格相關的數據對象。然後,當用戶轉到下一個問題時,這些對象將被重新創建。 – Mahir

+0

這樣好嗎? (我已經添加了上面的vc代碼,如果有幫助的話) – Mahir

0

我不會做這樣的,因爲你是迫使UIViewController瞭解數據模型(同時也使它的屬性)。我會做什麼,會是一個類,使用類方法(而不是對象方法)會創建數據源。你仍然要保持在UIViewController莫名其妙的數據,但我認爲一個NSArrayNSDictionary就足夠好:

-(void)viewDidLoad{ 
    [superViewDidLoad]; 
    myArray = [MyModel createDataSourceForTag:myTag]; 
} 
+0

我仍然有問題是數據的情況下,洗牌的問題順序,所以我不能每次都實例化一個新的對象... – Mahir

+0

的順序並不重要。您需要根據標籤計算數據源。如果計算量很大,實際數據不大,可以將其存儲在Singleton中,以便隨時訪問它。 – Peres

+0

我很猶豫要做單身人士,因爲我想不出讓所有視圖控制器都能訪問它的好方法。 – Mahir

0

我想在這裏你應該與模型結構去。

1.型號:型號代表實體。在這裏,你的情況下,我可以創建回合兩個實體,問題

@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。視圖控制器:現在,在視圖控制器,你可以直接使用sharedInstace,像這樣:

[[DataManager sharedInstance] rounds] 

您可以輕鬆地獲取代碼創建sharedInstance類。

現在,您可以在整個應用程序的任何位置使用此循環。 因此,它很容易訪問。例如,如果你需要第一輪第二個問題第三選項,然後,編寫代碼同樣的方式

回合1

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

問題2

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

問題文本,並選擇3

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

享受編碼:)

+0

現在進行洗牌也可以根據您的要求直接洗牌,或者輪流或問題或選項。 – Mrunal

相關問題