菜鸟教程小白 发表于 2022-12-11 20:22:33

objective-c - 两个 UIViewController 的故事


                                            <p><p>所以我觉得我快疯了。</p>

<p>我已经更新到 XCode 4.2,所以我有 IOS 5 SDK。</p>

<p>我的应用在升级之前一直运行良好。现在,我有一个奇怪的问题。它不适用于我的 IOS 5 iPad 2,也不适用于 IOS 5 模拟器。在 4.3 模拟器中运行良好。</p>

<p>出于这个问题的目的,我有两个基于 UIViewController 的类。他们不使用 NIB 文件。一种叫做 HistoryBrowser,效果很好。另一个,NoteBrowseViewController,按照同样的思路构造,没有。</p>

<p>来自 NoteBrowseView.Controller.h:</p>

<pre><code>@interface NoteBrowseViewController : UIViewController &lt;UITableViewDelegate, UITableViewDataSource, NSFetchedResultsControllerDelegate, UIActionSheetDelegate,      UISearchDisplayDelegate, UITabBarDelegate, MKMapViewDelegate&gt; {
UITableView* tableView;
... buncha other vars ...
}
@property (retain, nonatomic) UITableView* tableView;
... buncha other properties ...
</code></pre>

<p>来自 NoteBrowseViewController.m:</p>

<pre><code>@synthesize tableView

- (id)initWithEditing:(BOOL)inEditingMode inserting:(BOOL)inserting {
self=;
if (self) {
    self.isInserting=inserting;
    self.isEditing=inEditingMode;
    self.viewIsMap=NO;
    self.insertType=defInsertTypeLink;

    NSUserDefaults *defaults = ;
    NSDictionary *appDefaults = ,@&#34;viewSortOrder&#34;,
                                 ,@&#34;priorityView&#34;,
                                 ,@&#34;simpleView&#34;,
                                 nil];

    ;

    self.viewIsSimple=[boolForKey:@&#34;simpleView&#34;];
}
return self;
}

-(void)loadView {
self.view=[initWithFrame:[ applicationFrame]];

UIButton* aButton;
UIImage* buttonImage;
UIBarButtonItem* spacer=[initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace target:nil action:nil];

UISegmentedControl* sc=[initWithItems:];
;
;
;
;
sc.selectedSegmentIndex=[ integerForKey:@&#34;viewSortOrder&#34;];
sc.segmentedControlStyle=UISegmentedControlStyleBar;

UISegmentedControl* prisc=[initWithItems:];
;
;
;
prisc.selectedSegmentIndex=[ integerForKey:@&#34;priorityView&#34;];
prisc.segmentedControlStyle=UISegmentedControlStyleBar;

UIBarButtonItem* segmentedButton=[initWithCustomView:sc];
UIBarButtonItem* prioritySegmentedButton=[initWithCustomView:prisc];

buttonImage=;
aButton=;
;
aButton.frame=CGRectMake(0.0, 0.0, buttonImage.size.width, buttonImage.size.height);
UIBarButtonItem* addButton=[initWithCustomView:aButton];
;

buttonImage=;
aButton=;
;
aButton.frame=CGRectMake(0.0, 0.0, buttonImage.size.width, buttonImage.size.height);
UIBarButtonItem* editButton=[initWithCustomView:aButton];
;

buttonImage=;
aButton=;
;
aButton.frame=CGRectMake(0.0, 0.0, buttonImage.size.width, buttonImage.size.height);
UIBarButtonItem* simplify=[initWithCustomView:aButton];
;

buttonImage=;
aButton=;
;
aButton.frame=CGRectMake(0.0, 0.0, buttonImage.size.width, buttonImage.size.height);
UIBarButtonItem* complexify=[initWithCustomView:aButton];
;

buttonImage=;
aButton=;
;
aButton.frame=CGRectMake(0.0, 0.0, buttonImage.size.width, buttonImage.size.height);
UIBarButtonItem* map=[initWithCustomView:aButton];
;

buttonImage=;
aButton=;
;
aButton.frame=CGRectMake(0.0, 0.0, buttonImage.size.width, buttonImage.size.height);
UIBarButtonItem* notes=[initWithCustomView:aButton];
;

UIBarButtonItem* cancelButton=[initWithBarButtonSystemItem:UIBarButtonSystemItemDone target:self action:@selector(cancelButtonPressed:)];
self.doneToolbar=;

self.toolbar=[[init]autorelease];

if(self.isEditing) {
    self.complexToolbar=;
    self.simpleToolbar=;
}
else {
    self.complexToolbar=;
    self.simpleToolbar=;
}
self.mapToolbar=;

if (self.viewIsSimple) {
    ;
}
else {
    ;
}

self.toolbar.autoresizingMask=UIViewAutoresizingFlexibleWidth;      
;

CGFloat toolbarHeight = .size.height;
CGRect rootViewBounds=self.view.bounds;
CGFloat rootViewHeight = CGRectGetHeight(rootViewBounds);
CGFloat rootViewWidth = CGRectGetWidth(rootViewBounds);
;

self.mapView=[[initWithFrame:CGRectMake(0, toolbarHeight, rootViewWidth, rootViewHeight-(self.isInserting?49:0)-toolbarHeight)]autorelease];
self.mapView.delegate=self;
self.mapView.zoomEnabled=YES;
self.mapView.scrollEnabled=YES;
self.mapView.autoresizingMask=UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleBottomMargin;

self.tableView=[initWithFrame:CGRectMake(0, toolbarHeight, rootViewWidth, rootViewHeight-(self.isInserting?49:0)-toolbarHeight)
                                           style:UITableViewStylePlain];
self.tableView.delegate=self;
self.tableView.dataSource=self;
self.tableView.autoresizingMask=UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleBottomMargin;

self.view.autoresizesSubviews = YES;
self.view.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;

UISearchBar* searchBar = [ initWithFrame:CGRectMake(0, 44, rootViewWidth, 44.0)];
searchBar.autoresizingMask = UIViewAutoresizingFlexibleWidth;
searchBar.autocorrectionType = UITextAutocorrectionTypeNo;
self.tableView.tableHeaderView = searchBar;

self.searchDisplayController = [ initWithSearchBar:searchBar contentsController:self];
self.searchDisplayController.delegate = self;
self.searchDisplayController.searchResultsDataSource = self;
self.searchDisplayController.searchResultsDelegate = self;

;
;

if (self.isInserting) {
    UITabBarItem* item1=[[initWithTitle:@&#34;Link&#34; image:nil tag:defInsertTypeLink]autorelease];
    UITabBarItem* item2=[[initWithTitle:@&#34;Contents Later&#34; image:nil tag:defInsertTypeContentsLater]autorelease];
    UITabBarItem* item3=[[initWithTitle:@&#34;Contents Now&#34; image:nil tag:defInsertTypeContentsNow]autorelease];
    UITabBar* tabbar=[initWithFrame:CGRectMake(0, rootViewHeight-49, rootViewWidth, 49)];
    tabbar.autoresizingMask=UIViewAutoresizingFlexibleWidth|UIViewAutoresizingFlexibleHeight|UIViewAutoresizingFlexibleTopMargin|UIViewAutoresizingFlexibleBottomMargin;
    ;
    animated:YES];
    ;
    ;
}

if(self.viewIsSimple) {
    self.contentSizeForViewInPopover = CGSizeMake(200.0, 625.0);         
}
else {
    self.contentSizeForViewInPopover = CGSizeMake(450.0, 625.0);
}
self.view.autoresizesSubviews = YES;
self.view.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
self.note=nil;

;
;
;
;
;
;
;
;
;
;
;
}
</code></pre>

<p>最后,NoteBrowseViewController 从另一个 ViewController 实例化:</p>

<pre><code>self.noteBrowseViewController=[initWithEditing:NO inserting:NO];
self.noteBrowseViewController.delegate=self;
self.popoverController = [initWithContentViewController:self.noteBrowseViewController];
self.popoverController.delegate = self;
;
</code></pre>

<p>所以这就是发生的事情。如果我在调试中运行它并继续执行,只要执行到这一行:</p>

<pre><code>CGRect rootViewBounds=self.view.bounds;
</code></pre>

<p>程序崩溃并出现以下错误:</p>

<pre><code>2011-10-20 11:42:02.703 ActionNote3 *** Terminating app due to uncaught exception &#39;NSInvalidArgumentException&#39;, reason: &#39;*** -:object cannot be nil&#39;
*** First throw call stack:
(0x1eb0052 0x2a60d0a 0x1e9d36e 0x1e9e220 0x1968cb6 0x5153b 0x50e11 0x50879 0x52e4a 0xdcc64e 0x4bcb3 0x72d1 0x1eb1ec9 0xd095c2 0xd0955a 0xdaeb76 0xdaf03f 0xdae2fe 0xd2ea30 0xd2ec56 0xd15384 0xd08aa9 0x20c7fa9 0x1e841c5 0x1de9022 0x1de790a 0x1de6db4 0x1de6ccb 0x20c6879 0x20c693e 0xd06a9b 0x2dbd 0x2d35)
terminate called throwing an exception
</code></pre>

<p>通过在调试过程中观察,我知道 self.view 设置正确,并且 loadView 在应该调用的时候被调用。导致它失败的不是这条线——而是任何与 self.view 相关的东西!什么???</p>

<p>真正让我抓狂的是,我还有另一个子类 ViewControllerHistoryBrowser,它以完全相同的方式加载......而且它工作正常。</p>

<p>所以,除了对我无法弄清楚这一点感到沮丧之外,我想了解一下:</p>

<ol>
<li>XCode 4.2(从 4.1 开始)中会导致这种情况发生的变化,或者是
这是IOS 5的问题? </li>
<li>这个错误是什么意思,我该怎么办
关于它?</li>
</ol>

<p><strong>编辑:</strong></p>

<p>因此,根据 Abberant 以下回答的建议,我:</p>

<ol>
<li>将 initwithnib 更改为 init</li>
<li>删除了 loadView 方法</li>
<li>添加了完整的错误消息</li>
<li>在 init 方法中添加了更多相关代码</li>
</ol>

<p>现在,引用 self.view 可以正常工作。但事情变得陌生了。 </p>

<p>执行使其通过对 self.view 的第一次引用而没有错误。但是,它现在停止在:</p>

<pre><code>self.tableView.tableHeaderView = searchBar;
</code></pre>

<p>在 init 方法中。</p>

<p>收到的错误消息与我之前收到的错误消息非常相似:</p>

<pre><code>2011-10-20 12:34:04.818 ActionNote3 *** Terminating app due to uncaught exception &#39;NSInvalidArgumentException&#39;, reason: &#39;*** -: object cannot be nil&#39;
*** First throw call stack:
(0x1eaf052 0x2a5fd0a 0x1e9c36e 0x1e9d220 0x1967cb6 0x50b4b 0x50421 0x4fe89 0x4d757 0x6641 0x1eb0ec9 0xd085c2 0xd0855a 0xdadb76 0xdae03f 0xdad2fe 0xd2da30 0xd2dc56 0xd14384 0xd07aa9 0x20c6fa9 0x1e831c5 0x1de8022 0x1de690a 0x1de5db4 0x1de5ccb 0x20c5879 0x20c593e 0xd05a9b 0x212d 0x20a5)
terminate called throwing an exception
</code></pre>

<p>因此,如果我注释掉该行,执行将继续进行,直到它到达这组行,当它尝试执行 performFetch 时它会失败。</p>

<pre><code>    NSError *error = nil;
    if (![ performFetch:&amp;error]) {
      NSLog(@&#34;Unresolved error %@, %@&#34;, error, );
      abort();
    }
</code></pre>

<p>调试 的代码表明获取的结果 Controller 设置正确且没有问题。</p>

<p>这里收到的错误和上面一样。第一次 throw 调用堆栈中的数字发生变化,否则错误相同。</p>

<p>所以我想我这里有一个更大的问题。我只是不知道如何追踪它。正如我在某处所说的那样,我有另一个 View ,以相同的方式构建,加载良好。</p>

<p><strong>编辑:</strong></p>

<p>因此,NJones 在下面的回答中建议遵循 Apple 的指导方针,将适当的代码放在 loadView 和 viewDidLoad 中。所以我做了。我将所有 View 构造从 init 移到 loadView 中,并在 viewDidLoad 中启动了 fetchedResultsController。</p>

<p>应用仍然在同一个地方崩溃:</p>

<pre><code>self.tableView.tableHeaderView = searchBar
</code></pre>

<p>出现与上述相同的错误。</p>

<p>谢谢!</p></p>
                                    <br><hr><h1><strong>Best Answer-推荐答案</ strong></h1><br>
                                            <p><p>我会说你应该使用苹果建议的加载模型。这是创建新 UIViewController 子类时在 xCode 中生成的一些代码(为适应而删节):</p>

<pre><code>/*
// Implement loadView to create a view hierarchy programmatically, without using a nib.
-(void)loadView{
}
*/

/*
// Implement viewDidLoad to do additional setup after loading the view, typically from a nib.
-(void)viewDidLoad{
    ;
}
*/
</code></pre>

<p>基于此,由于您是以编程方式创建 View ,我想说您的 init 方法中的大部分内容都属于 loadView 方法。</p></p>
                                   
                                                <p style="font-size: 20px;">关于objective-c - 两个 UIViewController 的故事,我们在Stack Overflow上找到一个类似的问题:
                                                        <a href="https://stackoverflow.com/questions/7830502/" rel="noreferrer noopener nofollow" style="color: red;">
                                                                https://stackoverflow.com/questions/7830502/
                                                        </a>
                                                </p>
                                       
页: [1]
查看完整版本: objective-c - 两个 UIViewController 的故事