Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/iphone/42.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ios 从包含的对象内调用UIViewController方法_Ios_Iphone_Objective C_Model View Controller_Uiviewcontroller - Fatal编程技术网

Ios 从包含的对象内调用UIViewController方法

Ios 从包含的对象内调用UIViewController方法,ios,iphone,objective-c,model-view-controller,uiviewcontroller,Ios,Iphone,Objective C,Model View Controller,Uiviewcontroller,假设我有几个属于UIViewController的对象(模型)。当其中一个模型发生更改或执行某些操作时,我希望它通知UIViewController,以便视图可以立即更新,或者执行一些动画作为响应 我该怎么做?具体来说, (1.)单个对象如何知道ViewController?如果我在每个对象中存储一个指向ViewController的指针,那么我将引入一个循环引用,其中ViewController引用引用ViewController的子对象 (2.)即使使用弱指针,模型对象本身也不知道ViewC

假设我有几个属于UIViewController的对象(模型)。当其中一个模型发生更改或执行某些操作时,我希望它通知UIViewController,以便视图可以立即更新,或者执行一些动画作为响应

我该怎么做?具体来说,

(1.)单个对象如何知道ViewController?如果我在每个对象中存储一个指向ViewController的指针,那么我将引入一个循环引用,其中ViewController引用引用ViewController的子对象

(2.)即使使用弱指针,模型对象本身也不知道ViewController中的哪个视图与其自身相对应。例如,假设有10个视图和10个模型。模型与视图不耦合(即,每个模型都有一个以10为一组表示它的视图,但索引并不总是相同的,因为用户不断地切换它们,因此,虽然模型有一个稳定的索引0…9,但表示模型0的视图可能位于索引1,或更高的索引2,3,…,9),因此,当模型更新时,它需要以某种方式告诉ViewController 10个视图中的哪一个代表它,除非它不知道。因此,ViewController无法知道更新哪个视图

我应该补充的是,我当前的代码只给每个模型对象一个指向其相应视图的指针,这样它就不需要通过ViewController来访问正确的视图并更新其内容。但这似乎违反了MVC,所以我试图更正我的代码,并意识到在这种特殊情况下我不知道如何更正

抱歉,这让人困惑。如果有什么不清楚的地方,我会更新这个问题。 编辑:更新了更具体的示例代码

@interface ViewController : UIViewController<ProfileViewControllerDelegate>
{
    BattleModel* battle;
}

@property (nonatomic, strong) BattleModel* battle;

@property (nonatomic, weak) NSArray* heroPersons; // Person objects
@property (nonatomic, weak) NSArray* villainPersons; // Person objects

@property (nonatomic, strong) IBOutletCollection(PersonImageView) NSArray* villainImages;
@property (nonatomic, strong) IBOutletCollection(HealthBarView) NSArray* villainHealthBars;

@property (nonatomic, strong) IBOutletCollection(PersonImageView) NSArray* heroImages;
@property (nonatomic, strong) IBOutletCollection(HealthBarView) NSArray* heroHealthBars;

@property (weak, nonatomic) IBOutlet UITextView* reporter;
正如您所看到的,我目前违反了MVC,因为报告者被传递给了模型人,还有一个指向拟人的指针,VC应该处理这个指针。无论如何,当战斗发生时,反应*会在各种有针对性的命中例程中被查询,这就是修改发生的地方,并且会通知记者。请注意,此人完全不知道其对应的PersonView在grand scheme UIViewController中占用了哪个索引,因此当currentReaction在某个深层例程中触发并传递数据时,ViewController不知道要更新哪个UIView。它知道在某一点上(当这个人被创建时),但是英雄和恶棍的数组会发生很多变化(如果一个人从英雄变为恶棍,甚至会改变阵营),所以它在出生时的索引不是它在触发反应时必须拥有的索引,需要更新PersonImageView。这有点麻烦,所以我可能需要将数据传回UIViewController,告诉它哪个PersonImageView刚刚发生了反应(我该如何做?)

以下是一个示例反应,仅为了完整性和帮助您理解系统:

-(void) wasHitByMove:(SelectedMove*)selMove log:(UITextView*)reporter
{
    [self.currentReaction personWasHitByMove:selMove inBattle:self.currentBattle log:reporter];
}
根据反应是否相关(有几个反应的子类做不同的事情),通过Person属性设置器调用“loseLife:(int)life”这样的修改,这时我需要将报告/动画向VC提交。现在,错误的代码(糟糕的设计)只是直接发送给动画的拟人,然后是文本通知的报告者。我意识到这是一个糟糕的设计,这就是我来这里的原因,但这并不像通过回调告诉VC那样简单,“(BOOL)嘿,我出了什么事。”因为哪个PersonImageView是“我”?ViewController如何在自己的方法中执行战斗的逻辑,知道立即回应回调?回调是如何进行的?(关于:代理。那么将代理协议附加到Person、PersonImageView和UIViewController?因为它们都遵循协议,那么它们可以通过协议方法解释公共消息?)

我也查看了NSNotification,但发现对于这个目的来说太复杂了;它似乎更像是一种被动观察者类型的东西,在我的应用程序中,当反应触发时,我需要UIViewController立即用UITextView文本+PersonImageView动画更新屏幕。在反应再次触发之前,动画需要立即发生,因为它可能涉及PersonImageView的后退、摔倒或改变外观。这不是一个实时游戏,但下一次攻击将已经排队,并且将在前一次攻击触发当前反应后立即发生,因此任何形式的延迟或被动观察都可能是不好的。

代理

假设您有一个带有按钮的视图。给它一个协议:

@protocol MyButtonViewDelegate
@required
- (void)buttonPressed;
@end
- (void)someMethod:(id)sender {
    // sender is a reference to the view which called this method on delegate
}
现在,带有按钮的视图具有如下属性:

@property (nonatomic, weak) NSObject<MyButtonViewDelegate> *delegate;
[[NSNotificationCenter defaultCenter] postNotificationName:@"somethingInModel3" object:self];
视图控件符合
MyButtonViewDelegate
协议,并将自身设置为视图的委托。然后,它实现方法
按钮按下

- (void)buttonPressed {
    // do whatever you want to do when that button was pressed
}

如果需要在此方法中传递对视图的引用,也可以这样做:

@protocol MyViewDelegate
@required
- (void)someMethod:(id)sender;
@end
然后:

然后,委托实现协议中的方法:

@protocol MyButtonViewDelegate
@required
- (void)buttonPressed;
@end
- (void)someMethod:(id)sender {
    // sender is a reference to the view which called this method on delegate
}

您可以编写一个协议方法来发送任意数量的参数。您甚至可以让这些方法返回您使用的值:

@protocol MyResizableViewProtocol
@required
- (CGRect)newSizeForResizableView:(MyResizableView*)resizableView;
@end
视图类中的某些内容触发对委托调用此方法并请求新大小。委托实现此方法:

- (CGRect)newSizeForResizableView:(MyResizableView*)resizableView {
    return CGRectMake(0.0f, 0.0f, 100.0f, 400.0f);
}
可调整大小的视图使用的方法如下:

- (void)timeToResize {
    self.frame = [self.delegate newSizeForResizableView:self];
}

就我而言,理解协议和委托是iOS开发中更重要的方面之一。

委托

假设您有一个带有按钮的视图。给它一个协议:

@protocol MyButtonViewDelegate
@required
- (void)buttonPressed;
@end
- (void)someMethod:(id)sender {
    // sender is a reference to the view which called this method on delegate
}
现在,带有按钮的视图具有如下属性:

@property (nonatomic, weak) NSObject<MyButtonViewDelegate> *delegate;
[[NSNotificationCenter defaultCenter] postNotificationName:@"somethingInModel3" object:self];
视图控件符合
MyButtonViewDelegate
协议,并将自身设置为