我对代码设计有几个问题。这可能很长。我会尽可能地缩短它。
创建一个类并添加所需的功能,以便允许对象更改自己的状态与状态由控制器(也称为viewcontroller)更改
我发现代码示例在尝试沟通时最好: 注意:我减少了一些代码行。来自http://www.techotopia.com/index.php/An_Overview_of_Objective-C_Object_Oriented_Programming的原始代码。
无论如何,如果我必须为帐户设置帐户余额,建议我这样做:
@interface BankAccount: NSObject
{
double accountBalance;
long accountNumber;
}
-(double) getAccountBalance;
-(void) setAccountBalance: (double) x;
@end
// Implementation Section Starts Here
@implementation BankAccount
-(void) setAccountBalance: (double) x
{
accountBalance = x;
}
-(double) getAccountBalance
{
return accountBalance;
}
@end
//usage
BankAccount *account1 = [BankAccount alloc] init];
[account1 setAccountBalance: 1500.53];
----但是我相信我会把它写在这样的控制器中:------
@interface BankAccount: NSObject
{
double accountBalance;
long accountNumber;
}
import "BankAccount.h"
@interface MeViewController : UIViewController
-(void)setAccountBalance:(double)x toAccount:(BankAccount *)tempBankAcc;
@end
@implementation myViewController
-(void) setAccountBalance:(double)x toAccount:(BankAccount *)tempBankAcc
{
tempBankAcc.accountBalance = x;
}
//USAGE
BankAccount *account1 = [BankAccount alloc] init];
[self setAccountBalance(Account1,1500.53)]
@end
因为我认为是我(meViewController)设置AccountBalance,而不是帐户本身,因为帐户只是一个帐户。 这是一个非常糟糕的主意吗?我可以通过他们的例子看到该对象可以自我管理(独立)意味着改变自己的状态,而我的方法说BankAccount只能通过/与控制器(依赖)修改 ???
我还在某处读过控制器内部写的代码应仅用于:
响应用户互动&更新视图
这意味着我不应该在控制器中执行以下操作:
与NSUserDefaults进行读取或写入。由于它是一个单例,我认为无论哪个控制器当前处于活动状态,写入它都会更容易?馊主意? 我知道我应该在applicationDidEnterBackground和applicationWillTerminate中保存数据(包括NSUserDefaults),所以这是一个不好的想法,以保存在其他地方(例如在另一个控制器中)。
单身: 我的理解是[UIApplication sharedApplication],[NSNotification defaultCenter]和其他单例可以通过所有控制器访问,NSObject子类怎么样?或UIView子类?
显然,当模型更新时,您可以使用NSNotification通知其他控制器。 有人可以告诉我何时使用以及如何使用它的示例? 也许当您导入一些具有与最初预期不同的属性的数据时,可以向观察者通知升级的数据模型,这是您在数据模型中何时通知控制器的示例?
现在有足够的问题。
很抱歉,但我不得不把它们全部搞定: - )
本
答案 0 :(得分:2)
首先要做的事情:不要使用这个
@interface BankAccount: NSObject
{
double accountBalance;
long accountNumber;
}
-(double) getAccountBalance;
-(void) setAccountBalance: (double) x;
@end
在这里,accountBalance
ivar是公开的,而它应该是私有的。
相反,请使用@property
:
@interface BankAccount: NSObject
@property (assign, nonatomic) double accountBalance;
@end
那将定义一个setter:
- (void)setAccountBalance:(double)accountBalance { ... }
和一个吸气者:
- (double)accountBalance { ... }
以及名为_accountBalance
的私有实例变量(ivar)。
然后,您可以在实施中使用:
@synthesize accountBalance;
会自动创建这样的setter / getter:
- (void)setAccountBalance:(double)accountBalance {
_accountBalance = accountBalance;
}
- (double)accountBalance {
return _accountBalance;
}
答案 1 :(得分:1)
Q1)模型层对象,特别是那些将与之交互和变异的对象,应该对自己的内部表示负责,并代表交互规则的知识。对于银行账户,我认为您提出的两种方法都是错误的。第二个特别是因为它实际上甚至负责更新状态远离帐户。但第一个也是因为它只提供setBalance
方法,这在现实世界中没有意义。使用该账户的人现在必须处理转账,取款,存款,利息等所有逻辑。实际上,银行帐户应该有方法deposit
withdraw
balance
等等,这样它就可以代表这些互动发生的规则和逻辑。在这种情况下,借鉴它在现实生活中的运作方式可能会有所帮助。
Q2)很多这取决于你的应用程序的设置方式。一个简单的应用程序模型层可能只是一个plist或NSUserDefaults
和一些NSDictionary
实例。在这种情况下,您可能不希望视图控制器与之交互,但可能是数据控制器对象。但是你可以让视图控制器与那种模型交谈。当事情变得更复杂时,你肯定需要分离关注点,让控制器对象更接近数据模型,或者拥有更复杂的模型来提供交互规则。就个人而言,我要避免让所有的视图控制器加载NSUserDefaults,你可以只创建一个可以处理它的数据控制器类并根据需要实例化它。
Q3)我在这里看到两个问题。不确定“所有控制器都可访问”的含义。但是当正确使用时,NSNotification非常有用。假设您有3个视图控制器,所有视图控制器都协调银行帐户的不同视图 - 一个是分类帐,一个是饼图,一个是预算计算器。当应用程序请求从互联网刷新银行帐户的信息时,当该请求返回时,它可以立即通知所有这三个视图控制器,并且他们可以相应地刷新他们的视图。只要你有多个对象有兴趣知道发生了什么事情,它就会被用到。
希望这有帮助,如果您有任何问题,请与我联系。
答案 2 :(得分:1)
<强> Q1 强> 如果从对象本身中删除所有业务逻辑,它只不过是一个浅容器对象。此外,您需要在您使用的每个控制器中复制该逻辑。业务逻辑进入业务对象。
对于您的具体示例,控制器的方法什么也不做,只是将调用委托给对象本身(事实上,如果您在此处使用属性,则调用相同的方法)。所以你一无所获。在控制器中使用该方法可能没什么问题,如果控制器做的不仅仅是调用对象,可能会更新更多的数据。这里的一个好提示是控制器不使用任何自己的实例变量。它很容易成为一种类方法。这是代码味道。
<强> Q2 强> 基本上,您有三种选择来访问NSUserDefaults:应用程序级别,视图控制器级别或视图级别。
最糟糕的情况是视图级别 - 视图应该在任何上下文中工作,并且应该以您喜欢的任何方式进行配置,并且它当然不应该依赖于某些神奇的外部事物。这将使可重用性(不仅对于其他应用程序,而且在同一个应用程序中)成为一种痛苦。
访问视图控制器级别的默认值通常是可以的,特别是如果他们采取一些单例角色。即如果您只有一个播放屏幕和一个设置屏幕,则每个屏幕都可以轻松与默认值对话。如果你可能有不同配置的同一个类的几个实例,那么就会产生一种痛苦和难闻的工作来“个性化”这些实例。
这是您希望在视图控制器之外放置默认访问权限的地方,这是最优雅和最灵活的方法,但有时并非必要。
可重用性可能比预期更早,即打开第二个文本编辑器窗口(可能显示或不显示不同的字体),第二个设置屏幕(即弹出框),第二个用于棋盘游戏的播放屏幕等。
<强> Q3 强> 我认为单身人士本身并不好。不过,它们确实带有高昂的价格。它们在早期阶段很方便,就像全局变量一样。
很快就会变得非常昂贵。没有所有权,一切都是共享的,没有机会改变一个位而不影响该对象的其他用户。依赖于单身的物体的可重用性很差,因为你总是需要那些单身人士。我倾向于在大多数时候避开它们。每当我在我的代码中使用其中一个时,摆脱它们是一个很好的决定。
至于通知:它们实际上是为在系统级别进行通信而设计的。它们不应该被滥用于正常的应用逻辑和通信。这是系统级事件的广播。如果你用它们作为对象通信的替代品,这是一个可靠的地狱方式。这会将的每个逻辑从代码中删除,并且无法构建负责任的代码。
答案 3 :(得分:0)
阅读斯坦福关于MVC的讲座。我想你会在那里找到很多答案http://www.stanford.edu/class/cs193p/cgi-bin/drupal/node/205