iOS 滑出菜单导致应用程序崩溃。怎么修?

Posted

技术标签:

【中文标题】iOS 滑出菜单导致应用程序崩溃。怎么修?【英文标题】:iOS Slide out menu is causing app to crash. How to fix? 【发布时间】:2014-04-06 00:28:36 【问题描述】:

我正在创建一个带有滑出导航栏的 RSS 提要应用程序,如图所示 (http://www.appcoda.com/ios-programming-sidebar-navigation-menu/)。 该应用程序将加载,RSS 提要将解析并出现在我的主屏幕上。您可以单击一个提要,它将导致一个 webView 显示相应的网站。我还将在左上角有一个导航栏按钮来切换滑出菜单。我无法继续处理我的应用程序,因为它一直在崩溃。顺便说一句,我正在使用名为 SWRevealViewController 的第三方库。这是我的 MasterViewController:

//
//  JSSMasterViewController.m
//  News App
//
//  Created by Steve on 4/5/14.
//  Copyright (c) 2014 self.edu.steve. All rights reserved.
//

#import "JSSMasterViewController.h"
#import "JSSDetailViewController.h"
#import "SWRevealViewController.h"

@interface JSSMasterViewController () 
    NSXMLParser *parser;
    NSMutableArray *feeds;
    NSMutableDictionary *item;
    NSMutableString *title;
    NSMutableString *link;
    NSString *element;

@end

@implementation JSSMasterViewController

- (void)awakeFromNib

    [super awakeFromNib];


- (void)viewDidLoad

    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.
    feeds = [[NSMutableArray alloc] init];
    NSURL *url = [NSURL URLWithString:@"http://images.apple.com/main/rss/hotnews/hotnews.rss"];
    parser = [[NSXMLParser alloc] initWithContentsOfURL:url];
    [parser setDelegate:self];
    [parser setShouldResolveExternalEntities:NO];
    [parser parse];

    // Change button color
    _sidebarButton.tintColor = [UIColor colorWithWhite:0.96f alpha:0.2f];

    // Set the side bar button action. When it's tapped, it'll show up the sidebar.
    _sidebarButton.target = self.revealViewController;
    _sidebarButton.action = @selector(revealToggle:);

    // Set the gesture
    [self.view addGestureRecognizer:self.revealViewController.panGestureRecognizer];




- (void)didReceiveMemoryWarning

    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.


#pragma mark - Table View

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView 
    return 1;


- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section 
    return feeds.count;


- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath 
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"Cell" forIndexPath:indexPath];
    cell.textLabel.text = [[feeds objectAtIndex:indexPath.row] objectForKey: @"title"];
    return cell;


- (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName attributes:(NSDictionary *)attributeDict 

    element = elementName;

    if ([element isEqualToString:@"item"]) 

        item    = [[NSMutableDictionary alloc] init];
        title   = [[NSMutableString alloc] init];
        link    = [[NSMutableString alloc] init];

    



- (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName 

    if ([elementName isEqualToString:@"item"]) 

        [item setObject:title forKey:@"title"];
        [item setObject:link forKey:@"link"];

        [feeds addObject:[item copy]];

    



- (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string 

    if ([element isEqualToString:@"title"]) 
        [title appendString:string];
     else if ([element isEqualToString:@"link"]) 
        [link appendString:string];
    



- (void)parserDidEndDocument:(NSXMLParser *)parser 

    [self.tableView reloadData];



- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender 
    if ([[segue identifier] isEqualToString:@"showDetail"]) 

        NSIndexPath *indexPath = [self.tableView indexPathForSelectedRow];
        NSString *string = [feeds[indexPath.row] objectForKey: @"link"];
        [[segue destinationViewController] setUrl:string];

    

@end

这是管理滑出菜单的 SideBar View 控制器:

    //
//  JSSSidebarViewController.m
//  News App
//
//  Created by Steve on 4/5/14.
//  Copyright (c) 2014 self.edu.steve. All rights reserved.
//

#import "JSSSidebarViewController.h"
#import "SWRevealViewController.h"

@interface JSSSidebarViewController ()

@end

@implementation JSSSidebarViewController

    NSArray *menuItems;


- (id)initWithStyle:(UITableViewStyle)style

    self = [super initWithStyle:style];
    if (self) 
        // Custom initialization
    
    return self;


- (void)viewDidLoad

    [super viewDidLoad];

     menuItems = @[@"title", @"news", @"comments", @"map", @"calendar", @"wishlist", @"bookmark", @"tag"];

    // Uncomment the following line to preserve selection between presentations.
    // self.clearsSelectionOnViewWillAppear = NO;

    // Uncomment the following line to display an Edit button in the navigation bar for this view controller.
    // self.navigationItem.rightBarButtonItem = self.editButtonItem;


- (void)didReceiveMemoryWarning

    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.


#pragma mark - Table view data source

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView

    // Return the number of sections.
    return 1;


- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section

    // Return the number of rows in the section.
    return [menuItems count];



- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath

    NSString *CellIdentifier = [menuItems objectAtIndex:indexPath.row];
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];

    return cell;

- (void) prepareForSegue: (UIStoryboardSegue *) segue sender: (id) sender

    // Set the title of navigation bar by using the menu items
    NSIndexPath *indexPath = [self.tableView indexPathForSelectedRow];
    UINavigationController *destViewController = (UINavigationController*)segue.destinationViewController;
    destViewController.title = [[menuItems objectAtIndex:indexPath.row] capitalizedString];

    // Set the photo if it navigates to the PhotoView

    if ( [segue isKindOfClass: [SWRevealViewControllerSegue class]] ) 
        SWRevealViewControllerSegue *swSegue = (SWRevealViewControllerSegue*) segue;

        swSegue.performBlock = ^(SWRevealViewControllerSegue* rvc_segue, UIViewController* svc, UIViewController* dvc) 

            UINavigationController* navController = (UINavigationController*)self.revealViewController.frontViewController;
            [navController setViewControllers: @[dvc] animated: NO ];
            [self.revealViewController setFrontViewPosition: FrontViewPositionLeft animated: YES];
        ;

    



@end

我无法找到解决方案。这是我的日志:

2014-04-05 20:17:43.843 News App[4496:60b] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '*** -[__NSArrayM insertObject:atIndex:]: object cannot be nil'
*** First throw call stack:
(
    0   CoreFoundation                      0x0000000101968495 __exceptionPreprocess + 165
    1   libobjc.A.dylib                     0x00000001016c799e objc_exception_throw + 43
    2   CoreFoundation                      0x000000010191f374 -[__NSArrayM insertObject:atIndex:] + 820
    3   UIKit                               0x00000001002d40da -[UIView(UIViewGestures) addGestureRecognizer:] + 199
    4   News App                            0x0000000100001ecf -[JSSMasterViewController viewDidLoad] + 719
    5   UIKit                               0x000000010036a59e -[UIViewController loadViewIfRequired] + 562
    6   UIKit                               0x000000010036a777 -[UIViewController view] + 29
    7   UIKit                               0x00000001006752e2 -[UIClientRotationContext initWithClient:toOrientation:duration:andWindow:] + 390
    8   UIKit                               0x00000001002b0ffa -[UIWindow _setRotatableClient:toOrientation:updateStatusBar:duration:force:isRotating:] + 1109
    9   UIKit                               0x00000001002b0b9f -[UIWindow _setRotatableClient:toOrientation:updateStatusBar:duration:force:] + 36
    10  UIKit                               0x00000001002b0aef -[UIWindow _setRotatableViewOrientation:updateStatusBar:duration:force:] + 101
    11  UIKit                               0x00000001002afdfe -[UIWindow _updateToInterfaceOrientation:duration:force:] + 377
    12  UIKit                               0x000000010036e70a -[UIViewController _tryBecomeRootViewControllerInWindow:] + 147
    13  UIKit                               0x00000001002aab1b -[UIWindow addRootViewControllerViewIfPossible] + 490
    14  UIKit                               0x00000001002aac70 -[UIWindow _setHidden:forced:] + 282
    15  UIKit                               0x00000001002b3ffa -[UIWindow makeKeyAndVisible] + 51
    16  UIKit                               0x000000010026fc98 -[UIApplication _callInitializationDelegatesForURL:payload:suspended:] + 1788
    17  UIKit                               0x0000000100273a0c -[UIApplication _runWithURL:payload:launchOrientation:statusBarStyle:statusBarHidden:] + 660
    18  UIKit                               0x0000000100284d4c -[UIApplication handleEvent:withNewEvent:] + 3189
    19  UIKit                               0x0000000100285216 -[UIApplication sendEvent:] + 79
    20  UIKit                               0x0000000100275086 _UIApplicationHandleEvent + 578
    21  GraphicsServices                    0x0000000103ae171a _PurpleEventCallback + 762
    22  GraphicsServices                    0x0000000103ae11e1 PurpleEventCallback + 35
    23  CoreFoundation                      0x00000001018ea679 __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE1_PERFORM_FUNCTION__ + 41
    24  CoreFoundation                      0x00000001018ea44e __CFRunLoopDoSource1 + 478
    25  CoreFoundation                      0x0000000101913903 __CFRunLoopRun + 1939
    26  CoreFoundation                      0x0000000101912d83 CFRunLoopRunSpecific + 467
    27  UIKit                               0x00000001002732e1 -[UIApplication _run] + 609
    28  UIKit                               0x0000000100274e33 UIApplicationMain + 1010
    29  News App                            0x0000000100002c23 main + 115
    30  libdyld.dylib                       0x00000001020005fd start + 1
    31  ???                                 0x0000000000000001 0x0 + 1
)
libc++abi.dylib: terminating with uncaught exception of type NSException
(lldb) 

感谢您的帮助!

【问题讨论】:

【参考方案1】:

错误正是您的错误日志所说的:

'*** -[__NSArrayM insertObject:atIndex:]: object cannot be nil'

您正试图将一个对象插入到一个数组中,而该对象为 nil。在这种特殊情况下,正是这一行导致了问题:

[self.view addGestureRecognizer:self.revealViewController.panGestureRecognizer];

您需要先分配self.revealViewController.panGestureRecognizer,然后再将其添加为视图的手势识别器。

一种分配手势识别器的方法:

UIPanGestureRecognizer *gesture = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(someMethod:)];
[self.view addGestureRecognizer:gestureRecognizer];

【讨论】:

您对错误是正确的。你能告诉我如何分配 self.revealViewController.panGestureRecognizer 以及在哪里分配它。我不知道语法。谢谢,我是 iOS 新手。 @Enrico Susatyo 非常感谢!我不再收到该错误,但不断出现新错误。这显示在我的日志 '2014-04-08 20:07:31.101 News App[10272:60b] -[JSSMasterViewControllerrevealToggle:]: unrecognized selector sent to instance 0x1093766b0' 我不明白为什么它不能识别手势。我应该从以前的代码中删除吗?如果是这样,请告诉我。谢谢! @Enrico Susatyo 这听起来像是一个完全不同的问题,它告诉你没有revealToggle这样的方法。您可能希望将此答案标记为有用/正确,然后如果您仍然不确定,请提出另一个问题。 好的!非常感谢您的参与! @Enrico Susatyo

以上是关于iOS 滑出菜单导致应用程序崩溃。怎么修?的主要内容,如果未能解决你的问题,请参考以下文章

iOS添加菜单在不是第一次查看时会导致崩溃

如何在 iOS 中使用委派来滑出菜单?

在 iOS14 上释放 wkwebview 时,发送手势事件导致崩溃

如何以编程方式在 ios 的滑出式侧边栏菜单中添加按钮

使用 SWRevealViewController 时应用程序崩溃

通过点击带有协议的滑出菜单过滤 UITableView 提要