我正在教自己Objective C,我正在努力推进模型 - 视图 - 控制器的想法。我的问题是:在模型类中创建数据的正确方法是什么?我有一个例子来说明我的意思,它有点长但是一个非常简单的问题。
以下代码来自我刚刚完成的记忆游戏。它工作正常,我已将数据与视图控制器分开,因此我有一个单独的类来保存卡片的图像。这是上课。顺便说一句,这一切都有效,对我的问题唯一重要的是有一个声明的数组,所以随意跳过大部分复制图像和随机化的代码。无论如何,这是:
@implementation Cards
- (NSMutableArray*) createCardImages{
NSMutableArray *Fruits = [[NSMutableArray alloc] initWithObjects:
[UIImage imageNamed:@"Apple.png"],
[UIImage imageNamed:@"Banana.png"],
[UIImage imageNamed:@"Pear.png"],
[UIImage imageNamed:@"Strawberry.png"],
[UIImage imageNamed:@"Lemon.png"],
[UIImage imageNamed:@"Orange.png"],
[UIImage imageNamed:@"Pineapple.png"],
[UIImage imageNamed:@"Kiwi.png"],
[UIImage imageNamed:@"Prune.png"],
[UIImage imageNamed:@"Peach.png"],
nil];
NSUInteger tileCount = [Fruits count];
for (NSUInteger i = 0; i < tileCount; ++i) {
NSInteger nElements = tileCount - i;
NSInteger n = (arc4random() % nElements) + i;
[FullList exchangeObjectAtIndex:i withObjectAtIndex:n];
}
NSArray *Shortlistprep1 = [Fruits subarrayWithRange:NSMakeRange(0, 10)];
NSArray *ShortListprep2=[Shortlistprep1 arrayByAddingObjectsFromArray:Shortlistprep1];
NSMutableArray *ShortList = [[NSMutableArray alloc]init];
ShortList = [NSMutableArray arrayWithArray:ShortListprep2];
return ShortList;
}
- (NSMutableArray*) shuffleCards{
NSUInteger cardCount = [self.cardImages count];
NSMutableArray *count = [[NSMutableArray alloc]init];
for (int tileID = 0; tileID < cardCount; tileID++){
[count addObject:[NSNumber
numberWithInt:tileID]];
}
return count;
}
然后我从视图控制器调用此方法,一切正常。 接下来,我想添加一个不同的图像列表,以便在玩游戏时可以选择不同的图像集。类似的东西:
NSMutableArray *Clothes = [[NSMutableArray alloc] initWithObjects:
[UIImage imageNamed:@"Hat.png"],
[UIImage imageNamed:@"Coat.png"],
[UIImage imageNamed:@"Gloves.png"],
[UIImage imageNamed:@"Trousers.png"],
[UIImage imageNamed:@"Socks.png"],
[UIImage imageNamed:@"Sweater.png"],
[UIImage imageNamed:@"T-shirt.png"],
[UIImage imageNamed:@"Shirt.png"],
[UIImage imageNamed:@"Jumper.png"],
[UIImage imageNamed:@"Underwear.png"],
nil];
我知道我可以为每个新集复制整个方法,如下所示:
- (NSMutableArray*) createCardImagesClothes{
NSMutableArray *Clothes = [[NSMutableArray alloc] initWithObjects:
[UIImage imageNamed:@"Hat.png"],
[UIImage imageNamed:@"Coat.png"],
[UIImage imageNamed:@"Gloves.png"],
[UIImage imageNamed:@"Trousers.png"],
[UIImage imageNamed:@"Socks.png"],
[UIImage imageNamed:@"Sweater.png"],
[UIImage imageNamed:@"T-shirt.png"],
[UIImage imageNamed:@"Shirt.png"],
[UIImage imageNamed:@"Jumper.png"],
[UIImage imageNamed:@"Underwear.png"],
nil];
NSUInteger tileCount = [FullList count];
for (NSUInteger i = 0; i < tileCount; ++i) {
NSInteger nElements = tileCount - i;
NSInteger n = (arc4random() % nElements) + i;
[FullList exchangeObjectAtIndex:i withObjectAtIndex:n];
}
NSArray *Shortlistprep1 = [FullList subarrayWithRange:NSMakeRange(0, 10)];
NSArray *ShortListprep2=[Shortlistprep1 arrayByAddingObjectsFromArray:Shortlistprep1];
NSMutableArray *ShortList = [[NSMutableArray alloc]init];
ShortList = [NSMutableArray arrayWithArray:ShortListprep2];
return ShortList;
}
如果这是前进的方法,我很乐意这样做,我只是想学习最佳实践。我觉得应该有办法只写一个方法,然后在h文件上声明属性如下:
#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>
@interface Cards : NSObject
// Create Cards
@property NSMutableArray *cardImages;
@property NSMutableArray *shuffledCards;
@propery NSMutableArray *Fruits;
@propery NSMutableArray *Clothes;
@propery NSMutableArray *SomeOtherSet;
@propery NSMutableArray *SomeOtherSet;
@propery NSMutableArray *SomeOtherSet;
- (NSMutableArray*) createCardImages;
- (NSMutableArray*) shuffleCards;
@end
然后我要做的就是修改我的方法以接受NSMutableArray类型的参数,如下所示:
- (NSMutableArray*) createCardImages:(NSMutableArray);
只需使用参数调用该方法,该参数将代表我想要加载的任何集合。
我的问题,这是一个相当基本的问题,我将把信息实际加载到这些数组中。 “m”文件中没有“main”或“viewDidLoad”方法来实际将数据(在这种情况下是图像)加载到数组中。
这有意义吗?
感谢阅读。
答案 0 :(得分:0)
可以说你不应该暴露可变数组,你的模型应该是数据的更好容器,并且实际上对数据进行操作。通过返回一组数字进行改组并不能实际改变数据模型,它应该。
此外,如果您的数据模型处理的是数据管理,而不是显式创建,则会更清晰。如果您有一个工厂类可以被要求生成一组图像并为您的Cards
课程提供这些图像来处理,那么您可以更好地区分您的问题。您可以将类方法添加到Cards
,或者使用枚举来确定要使用哪些图像的实例方法,但图像实际上是将这些图像作为卡管理的单独问题。
因此,视图控制器在创建用于管理游戏时,会向工厂类询问指定图像类型的Cards
实例。一旦它具有Cards
实例,它就可以将其洗牌,然后在指定的索引或网格位置请求卡。
索引和网格位置是有趣的部分,因为对于不同的游戏类型可能会有所不同。不同的游戏类型都可以使用同一组卡(虽然具有不同的Cards
实例),但以不同的方式索引这些卡。为了支持这一点,最好为卡片提供一个简单的索引,并让知道游戏逻辑的控制器决定如何使用该索引系统。
在上述所有情况中,控制器永远不会将卡作为阵列访问。界面类似,但所有交互都与Cards
进行,并且该类隐藏其内部结构。在内部,它会使用一个数组,但它可以使用其他东西,而控制器也不应该关心。