我正在爲化學反應做一個測驗應用程序。該應用程序給用戶一個問題,用戶在兩個單獨的文本框中鍵入反應物和產品。我如何更改此代碼,使其不違反MVC原則?
我有一個數據類,其中包含所有可能的測驗問題。然後,根據具體參數,數據類從可能的問題池中選擇一定數量的問題,並將它們混合成一個數組,quizQuestions
。
我也有一個視圖控制器,quizController
。對於每個問題,加載一個新的quizController
實例。 vc需要數據來知道要顯示哪個問題,正確答案是什麼等等。
這是我原來的解決方案,用於在數據和vc之間進行通信。
我創建了一個數據類的實例,data
。 我爲第一個問題創建vc1
,並將data
設置爲vc1
的屬性,並將其標記設置爲1,以便從數據加載第一個問題。
用戶回答第一個問題後,我創建了一個新的視圖控制器,vc2
,在vc1
的方法,使標籤比去年VC的1更使第二個問題的負載,並通過data
從vc1
的財產到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];
}
}
我正在考慮這個;我唯一擔心的是在視圖控制器中有很多對象需要刪除,並在用戶移動到新問題時重新實例化。 – Mahir
例如,我有一個以1個單元格開始的tableview。用戶在文本框中輸入一些數據,並添加另一個單元格。然後用戶輸入更多數據,並添加另一個單元格。如果我這樣做,我將不得不刪除單元格2-3和其中的所有內容以及與這些單元格相關的數據對象。然後,當用戶轉到下一個問題時,這些對象將被重新創建。 – Mahir
這樣好嗎? (我已經添加了上面的vc代碼,如果有幫助的話) – Mahir