iOS 5 自定义标签栏取消分配表视图?

Posted

技术标签:

【中文标题】iOS 5 自定义标签栏取消分配表视图?【英文标题】:iOS 5 Custom tab bar deallocating table view? 【发布时间】:2013-04-22 19:20:23 【问题描述】:

按照 Scott Sherwood (http://www.scott-sherwood.com/ios-5-creating-a-custom-side-tabbar-using-storyboards-and-custom-segues/) 的教程,我创建了一个自定义标签栏,它使用子视图加载到其他视图中。一切都很顺利,我对结果非常满意。但是,当我将表格视图添加到“标签页”之一并将其连接到数据源时,应用程序崩溃了。

我正在使用 ARC 并打开了僵尸程序,因此我的控制台告诉我一条消息已发送到我的表视图的已释放实例。我不知道如何保留表格视图,以便显示我的数据。这只是我的第二个应用程序,我对故事板和高级视图控制器还不太熟悉。我错过了什么?

这是我的自定义标签视图控制器:

CustomTabBarViewController.h

@interface CustomTabBarViewController : UIViewController <UITableViewDataSource, UITableViewDelegate>



@property(weak,nonatomic)UIViewController *currentViewController;
@property(weak,nonatomic)IBOutlet UIView *placeholder;
@property (weak, nonatomic) IBOutlet UIImageView *tabIndicator;
@property (weak, nonatomic) IBOutlet UIImageView *headerBacker1;
@property (weak, nonatomic) IBOutlet UIImageView *headerBacker2;



@end

CustomTabBarViewController.m

#import "CustomTabBarViewController.h"

@interface CustomTabBarViewController ()

@property (weak, nonatomic) IBOutlet UIView *buttons;

@end

@implementation CustomTabBarViewController

@synthesize currentViewController;
@synthesize placeholder;
@synthesize buttons;
@synthesize tabIndicator;
@synthesize headerBacker1;
@synthesize headerBacker2;


- (void)viewDidLoad

    [super viewDidLoad];
    [self performSegueWithIdentifier:@"ProductSegue" sender:[self.buttons.subviews objectAtIndex:0]];
    // Do any additional setup after loading the view, typically from a nib.


- (void)viewDidUnload

    [self setTabIndicator:nil];
    [self setHeaderBacker1:nil];
    [self setHeaderBacker2:nil];
    [super viewDidUnload];
    // Release any retained subviews of the main view.


-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
    if([segue.identifier isEqualToString:@"ProductSegue"]
       || [segue.identifier isEqualToString:@"ContactSegue"]
       || [segue.identifier isEqualToString:@"CategoryPage"])


        if([segue.identifier isEqualToString:@"ContactSegue"])

            [UIView animateWithDuration:0.25f delay:0.0f options:UIViewAnimationOptionCurveEaseOut animations:^
                [tabIndicator setCenter:CGPointMake(614, 108)];
                [headerBacker1 setCenter:CGPointMake(1024, 48)];
                [headerBacker2 setCenter:CGPointMake(1024, 789)];
             completion:nil];

        else
            [UIView animateWithDuration:0.25f delay:0.0f options:UIViewAnimationOptionCurveEaseOut animations:^
                [tabIndicator setCenter:CGPointMake(499, 108)];
                [headerBacker1 setCenter:CGPointMake(341, 48)];
                [headerBacker2 setCenter:CGPointMake(341, 789)];
                 completion:nil];

        
    


- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation

    return UIInterfaceOrientationIsLandscape(interfaceOrientation);


@end

以及加载到选项卡中的页面,其中包含表格视图: (注*:此页面在storyboard中作为tableview数据源和table view delegate链接)

ProductListViewController.h

#import <UIKit/UIKit.h>

@interface ProductListViewController : UIViewController <UITableViewDataSource, UITableViewDelegate>


@property (strong, nonatomic) NSMutableArray *maTheData;


@end

ProductListViewController.m

#import "ProductListViewController.h"

@interface ProductListViewController ()

@end

@implementation ProductListViewController


@synthesize maTheData;

- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil 
    if (self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil]) 
        //
    
    return self;



- (void)viewDidLoad

    [super viewDidLoad];
    NSLog(@"viewDidLoad");
    if (!maTheData) 
        maTheData = [[NSMutableArray alloc] initWithObjects:@"Comets", @"Asteroids", @"Moons", nil];
    


- (void)didReceiveMemoryWarning

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



- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView

    return 1;



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

    return [maTheData count];


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

    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"categoryTableCell"];
    UILabel *lblName = (UILabel *)[cell viewWithTag:100];
    [lblName setText:[maTheData objectAtIndex:[indexPath row]]];

    return cell;



- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath

    // Navigation logic may go here. Create and push another view controller.
    /*
     <#DetailViewController#> *detailViewController = [[<#DetailViewController#> alloc] initWithNibName:@"<#Nib name#>" bundle:nil];
     // ...
     // Pass the selected object to the new view controller.
     [self.navigationController pushViewController:detailViewController animated:YES];
     */



- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation

    //return UIInterfaceOrientationIsLandscape(interfaceOrientation);
    return interfaceOrientation == UIInterfaceOrientationLandscapeRight;



@end

感谢您的意见。

【问题讨论】:

也许我遗漏了什么,但你的 UITableView 属性在哪里? 您的崩溃是否收到错误消息? @ate50eggs:我没有专门加一个。我在故事板中添加了表格视图。但是,在您发表评论后,我确实在 ProductListViewController.h 中添加了一个属性并在实现文件中对其进行了综合,但结果是相同的。 @rdelmar:因为我启用了僵尸,我收到的唯一错误消息是:-[ProductListViewController numberOfSectionsInTableView:]: message sent to deallocated instance 0x18d400 那个错误是说释放的对象是 ProductListViewController,而不是表视图。你在做什么样的转场去那个控制器? 【参考方案1】:

据我所知,您提供的链接应该是 currentViewController 指向的控制器。所以,问题在于这个声明:

@property(weak,nonatomic)UIViewController *currentViewController;

这需要强大,而不是弱。 IBOutlets 弱是可以的,因为指向的对象是另一个视图的子视图,该视图持有对它们的强引用。但是, currentViewController 应该很强大,以防止您的控制器被释放(没有其他东西对它有很强的引用)。我从链接中看到他在 perform 方法中将 currentViewController 设置为 segue 的目标控制器——如果你这样做,并且你将声明更改为 strong,你应该没问题。

【讨论】:

当然是这样。谢谢你。我错误地认为释放的对象是 tableView,而不是父视图。感谢您对强/弱引用进行更深入的解释,这很有意义。【参考方案2】:

我猜您遇到的问题是由于您的属性较弱而不是强属性,尤其是对于您的 currentViewController。尝试将它们全部更改为强,看看您是否仍然有问题。

取自:Weak and strong property setter attributes in Objective-C

弱(iOS4 = unsafe_unretained)

它说“只要其他人强烈指向它,就保留它” 与分配相同,没有保留或释放 “弱”引用是您不保留的引用。 我们通常对 IBOutlets(UIViewController 的 Childs)使用weak。这是因为子对象只需要与父对象一样存在。 弱引用是不保护被引用对象不被垃圾收集器收集的引用。 Weak 本质上是赋值,是一个未保留的属性。除了对象被释放时,弱指针会自动设置 为零

【讨论】:

【参考方案3】:
@property (nonatomic, strong) IBOutlet UITableView *tableView;

将此属性与情节提要中的 tableview 连接起来。这应该会阻止 tableview 处理,因为视图控制器有一个强指针。从调试点开始在您认为导致错误的区域放置断点以定位代码中断的行。然后您可以更深入地调查错误。我希望这有帮助。

【讨论】:

IBOutlets 通常很弱,因为它们指向的对象是其他视图(在本例中为 self.view)的子视图,并且该视图拥有指向该对象的强指针。 是的,但是当您需要时,您的表格视图会被处理掉,所以说strong 是一种表示您将决定何时处理它的方式。这是一种将其保存在内存中以便您可以使用它的方法。 不,错误是说控制器 ProductListViewController 正在被释放,而不是表视图。即使使用弱指针,表视图也会与它的子视图一样存在。 OP 的问题不在于表格视图,而在于控制器。

以上是关于iOS 5 自定义标签栏取消分配表视图?的主要内容,如果未能解决你的问题,请参考以下文章

使用自定义标签栏自动调整视图的内容插入

使用 iOS 5 自定义应用程序中的所有表格视图

自定义标签栏项目

自定义更多视图控制器

iOS 自定义标签栏项目比标签栏高

Xamarin iOS 自定义视图