Ada*_*ach 2 iphone model-view-controller interface-builder
我开始尝试使用以前使用过代码的IB.我已经为iPad/iPhone Portrait/Landscape创建了笔尖,所以我有四种可能的视图.所有文件所有者都设置为UIViewController,都有一个对象从调色板集添加到我的NSObject子类"TargetObject".设置IBActions/IBOutlets没问题,只需按住Ctrl键拖动即可在一个笔尖中创建代码,然后右键单击该对象并将操作/出口拖动到其他笔尖中的右控件,以便所有连接都存在碎粒.我们的想法是,app委托启动当前设备的相应视图控制器,然后该视图控制器根据方向加载正确的视图.
(也许有自动掌握这种方法是没有必要的 - 我想知道是否有可能这样做,因为让布局重新排列自己恰到好处的那些IB控件是非常非常令人沮丧的.)
这些一对多视图和目标对象背后的想法是我可以在应用程序的任何地方使用它们.例如,我显示的内容是核心数据中的对象,我希望允许在应用程序的多个位置进行详细查看/编辑.这似乎是一种非常MVC的做事方式.
当我这样做时,问题出现在视图控制器的loadView中:
NSArray *portraitViewArray = [[NSBundle mainBundle] loadNibNamed:@"Weekview_iPad_Portrait" owner:self options:nil];
portraitWeekView = [portraitViewArray objectAtIndex:0];
NSArray *landscapeViewArray = [[NSBundle mainBundle] loadNibNamed:@"Weekview_iPad_Landscape" owner:self options:nil];
landscapeWeekView = [landscapeViewArray objectAtIndex:0];
// this object is intended to be a common target for portrait and landscape arrays.
weekViewTarget = [portraitViewArray objectAtIndex:1];
UIInterfaceOrientation interfaceOrientation = self.interfaceOrientation;
if(interfaceOrientation == UIInterfaceOrientationPortrait || interfaceOrientation == UIInterfaceOrientationPortraitUpsideDown)
self.view = portraitWeekView;
else
self.view = landscapeWeekView;
Run Code Online (Sandbox Code Playgroud)
正如您猜测的那样,纵向方向的一切都很好,但在景观中,与目标对象的任何交互都会崩溃.weekViewTarget对象引用使用纵向视图创建的对象,因此横向视图正在查找未使用引用保留的其他实例.在横向视图中_viewDelegate是nil - 它是私有的,所以我无法在代码中修复它.
我也可以使用引用来保持横向目标对象,但是每当方向改变时都会出现问题 - 在任何有状态控件(如UITableView)的情况下,数据源/委托将发生更改,从而导致旋转时的奇怪用户体验.除非我确保目标对象仅实现简单操作,并使用单独的共享对象为任何表视图或所需的文本视图实现数据源/委托对象.
我想到的一件事是让目标成为单身人士.看起来像一个黑客,这将是无法工作的时间.
使用公共目标对象创建作为nib实现的多个视图的正确方法是什么?
进展 - 如果我给每个目标一个指向它自己类型的指针,事情就会开始起作用:
WeekViewTarget *forwardTarget;
Run Code Online (Sandbox Code Playgroud)并让真正的处理程序forwardTarget = nil在未使用的处理程序的forwardTarget设置如下:
weekViewTarget = [portraitViewArray objectAtIndex:1];
forwardedWeekViewTarget = [landscapeViewArray objectAtIndex:1];
forwardedWeekViewTarget.forwardTarget = weekViewTarget;
Run Code Online (Sandbox Code Playgroud)
然后在每个IBAction中执行以下操作:
- (IBAction)timeBlockTapped:(id)sender {
if(forwardTarget != nil) {
[forwardTarget performSelector:@selector(timeBlockTapped:) withObject:sender];
} else {
NSLog(@"Got a tap event with sender %@", [sender description]);
}
}
Run Code Online (Sandbox Code Playgroud)
尽管如此仍然感觉不对劲.
orj*_*orj 17
亚当,听起来你想要一个代理(也就是外部)对象.
在从NIB实例化对象图时,NSBundle和UINib返回自动释放的数组.在事件循环结束时释放数组时,将释放您未专门保留的任何对象.显然,只要保留其所有者,就会保留笔尖内相互引用的对象.
因此,您正在释放动作目标对象的第二个实例,因为您没有依赖它.
你真正想要的只是两个NIB都可以引用的目标对象的单个实例.因此,您无法让NIB实例化该对象的实例.但是你的NIB需要能够引用该对象实例!
哦,亲爱的,该怎么办?!
基本上,外部对象是您放置在NIB中的代理.然后,您在实例化实例化NIB的对象图时输入.NIB加载程序将NIB中的代理替换为您提供的外部实例,并在Interface Builder中配置您分配给代理的任何目标或出口.
id owner = self; // or whatever
id targetObject = self.targetObject; // or whatever...
// Construct a dictionary of objects with strings identifying them.
// These strings should match the Identifiers you specified in IB's
// Attribute Inspector.
NSDictionary *externalObjects = [NSDictionary dictionaryWithObjectsAndKeys:
targetObject, @"TargetObject",
nil];
// Load the NIBs ready for instantiation.
UINib *portraitViewNib = [UINib nibWithNibName:@"Weekview_iPad_Portrait" bundle:nil];
UINib *landscapeViewNib = [UINib nibWithNibName:@"Weekview_iPad_Landscape" bundle:nil];
// Set up the NIB options pointing to your external objects dictionary.
NSDictionary *nibOptions = [NSDictionary dictionaryWithObjectsAndKeys:
externalObjects, UINibExternalObjects,
nil];
// Instantiate the objects in the nib passing in the owner
// (coincidentally also a proxy in the NIB) and your options dictionary.
NSArray *portraitViewArray = [portraitViewNib instantiateWithOwner:owner
options:nibOptions];
NSArray *landscapeViewArray = [landscapeViewNib instantiateWithOwner:owner
options:nibOptions];
self.view = [(UIInterfaceOrientationIsPortrait(interfaceOrientation)) ? portraitViewArray : landscapeViewArray) objectAtIndex:0];
Run Code Online (Sandbox Code Playgroud)
您正在使用NSBundle加载NIB.你应该使用UINib.读取NIB文件要快得多.此外,它将NIB加载与对象实例化分开.这意味着您可以在init,awakeFromNib或viewDidLoad中加载NIB,而不是实例化NIB的内容.然后,在您需要NIB中的实际对象的最后一刻,您可以调用instantiateWithOwner.
假设在使用UITableViewController的情况下,您将在viewDidLoad中加载表单元格nib,但实际上不实例化它们,直到在-tableView:cellForRowAtIndexPath:中需要该类型的单元格为止.
| 归档时间: |
|
| 查看次数: |
1542 次 |
| 最近记录: |