【问题标题】:PickerView Delegate Causing CrashPickerView 委托导致崩溃
【发布时间】:2014-04-02 08:08:03
【问题描述】:

我正在解雇一个模态视图控制器,它是 delegateUIPickerView

当我使用

关闭视图时
    [self dismissViewControllerAnimated:YES completion:NULL];

我的应用程序崩溃了,但只有在 UIPickerView 显示并且当前是第一响应者时才会崩溃。

我发现崩溃的原因是僵尸,这种方法,[UIPicker _updateSelectedRows] 在我的仪器中显示为问题。

我可以通过在关闭视图控制器之前将 UIPicker 委托和数据源设置为 nil 来解决此问题。

我以前从来不需要这样做,是不是我遗漏了什么?

这里是呈现视图的基本框架,以模态segue 呈现。当您使用 IBAction 关闭它时,它会导致崩溃

@interface VTSecViewController () <UIPickerViewDataSource, UIPickerViewDelegate>

@property (strong, nonatomic) UIPickerView *catPicker;
@property (strong, nonatomic) NSArray *catItems;
@property (weak, nonatomic) IBOutlet UITextField *pickerTF;

@end

@implementation VTSecViewController

- (IBAction)dismpress:(id)sender
{
    [self dismissViewControllerAnimated:YES completion:NULL];
}

- (void)viewDidLoad
{
    [super viewDidLoad];
    self.catItems = @[@"one", @"two"];
    self.catPicker = [[UIPickerView alloc] init];
    self.pickerTF.inputView = self.catPicker;
    self.catPicker.delegate = self;
    self.catPicker.dataSource = self;
    [self.pickerTF becomeFirstResponder];
    // Do any additional setup after loading the view.
}

#pragma mark PickerView DataSource

- (NSInteger)numberOfComponentsInPickerView: (UIPickerView *)pickerView
{
    return 1;
}

- (NSInteger)pickerView:(UIPickerView *)pickerView numberOfRowsInComponent:(NSInteger)component
{
    return [self.catItems count];
}

- (void)pickerView:(UIPickerView *)pickerView didSelectRow:(NSInteger)row inComponent:(NSInteger)component
{
    self.pickerTF.text = self.catItems[row];
}

- (NSString *)pickerView:(UIPickerView *)pickerView titleForRow:(NSInteger)row forComponent:(NSInteger)component
{
    return self.catItems[row];
}


@end

这个post 有助于澄清一些事情

【问题讨论】:

  • 你如何展示 UIPickerview?在操作表或其他视图控制器中?
  • 作为 UITextField 的 inputView
  • 您应该使用[ self.categoryTF resignFirstResponder]; 来关闭pickerview。
  • 是的,我正在使用 [self.view endEditing:YES];在解雇之前,但仍然有五分之一的崩溃,唯一确保没有崩溃的方法是将代表设置为零。
  • 您是否多次执行 setUpCatPicker?只是想知道你是否应该只设置self.catPicker 如果它为零? (虽然抓着稻草)

标签: ios delegates crash uipickerview modalviewcontroller


【解决方案1】:

委托(在这种情况下是您的视图控制器)应该在您点击时向 pickerview 提供有关标题/行数/whattodo 等内容的信息。当您在选择器仍在视图上时关闭控制器时。 pickerview 不知道你的控制器已经死了,它会不断地向委托询问这些信息,因此 -> 崩溃。

当您将委托和数据源设置为 nil 时。它会让pickerview知道你的委托不再存在,这样你就不会崩溃。

旁注:转到它显示的文档中的委托和数据源属性

@protocol UIPickerViewDataSource, UIPickerViewDelegate;

NS_CLASS_AVAILABLE_IOS(2_0) @interface UIPickerView : UIView <NSCoding, UITableViewDataSource>

@property(nonatomic,assign) id<UIPickerViewDataSource> dataSource;                // default is nil. weak reference
@property(nonatomic,assign) id<UIPickerViewDelegate>   delegate;                  // default is nil. weak reference

您可以看到属性是“分配”(弱)而不是“保留”(强)。因此,当您解除委托和数据源时,uipickerview 不会对委托的引用计数产生任何影响,并且它会解除分配。如果这是保留/强,那将是一个不同的情况。您可能应该查看苹果文档上的内存管理主题,了解这些是如何工作的。 https://developer.apple.com/library/mac/documentation/general/conceptual/devpedia-cocoacore/MemoryManagement.html。委托几乎一直都是弱引用。

【讨论】:

  • 但这并不总是发生。我在一个项目中遇到了这个问题,我试图将其隔离并在从头创建的应用程序中重现,但无济于事。
  • 此外,我无法理解弱属性如何导致僵尸状态 - 它应该安全地自行失效。
  • 我试图解释为什么委托/数据源必须保持弱/分配属性而不是强属性。我想你误会了。
  • 那我很糟糕。实际上,我认为问题的真正原因是这些属性是assign(即unsafe_unretained),而不是weak。再加上 iOS 经常保持对已释放视图控制器视图的子视图的 +1 引用(无论出于何种原因) - ...
  • 我认为你最好多阅读一些关于 uiviewcontroller 和 uiview 关系的内容。 UIViewController 具有强大的属性 UIView(因此控制器无法在没有视图的情况下生存),另一方面,UIView 只有对 UiViewController 的弱/委托引用。 (意味着 uiview 可以在没有控制器类的情况下很好地生存)。当您将视图 A 添加到另一个视图 B 时,该视图 B 的控制器/类将 +1 视图 A 的引用计数,但这不会影响控制器的引用计数。这就是为什么最初您可以在 UI 中看到选择器视图,但控制器/委托已死。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2023-03-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-09-02
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多