草庐IT

ios App 在解除分配 UIView 子类实例时崩溃

coder 2023-09-29 原文

我使用 CocoaTouch 和 ARC native 构建的应用程序在取消分配 UIView 子类实例时崩溃。

这是崩溃日志。

OS Version:      iOS 6.1.3 (10B329)

Exception Type:  EXC_BAD_ACCESS (SIGSEGV)
Exception Codes: KERN_INVALID_ADDRESS at 0x00000008
Crashed Thread:  0

0: 0x39de65b0 libobjc.A.dylib objc_msgSend + 16
1: 0x31edb694 CoreFoundation -[NSArray makeObjectsPerformSelector:] + 300
2: 0x33d8c57a UIKit -[UIView(UIViewGestures) removeAllGestureRecognizers] + 146
3: 0x33d8c144 UIKit -[UIView dealloc] + 440
4: 0x00240b36 MyApp -[StandardPanelView .cxx_destruct](self=0x20acba30, _cmd=0x00240985) + 434 at StandardPanelView.m:139
5: 0x39deaf3c libobjc.A.dylib object_cxxDestructFromClass(objc_object*, objc_class*) + 56
6: 0x39de80d2 libobjc.A.dylib objc_destructInstance + 34
7: 0x39de83a6 libobjc.A.dylib object_dispose + 14
8: 0x33d8c26a UIKit -[UIView dealloc] + 734
9: 0x0022aa14 MyApp -[StandardPanelView dealloc](self=0x20acba30, _cmd=0x379f1a66) + 156 at StandardPanelView.m:205
10: 0x39de8488 libobjc.A.dylib (anonymous namespace)::AutoreleasePoolPage::pop(void*) + 168
11: 0x31e98440 CoreFoundation _CFAutoreleasePoolPop + 16
12: 0x31f28f40 CoreFoundation __CFRunLoopRun + 1296
13: 0x31e9bebc CoreFoundation CFRunLoopRunSpecific + 356
14: 0x31e9bd48 CoreFoundation CFRunLoopRunInMode + 104
15: 0x35a502ea GraphicsServices GSEventRunModal + 74
16: 0x33db1300 UIKit UIApplicationMain + 1120
17: 0x00113c50 MyApp main(argc=1, argv=0x2fd3ed30) + 140 at main.m:23

问题是:

  1. 可能设置错误导致对 [UIView(UIViewGestures) removeAllGestureRecognizers] 的内部调用崩溃。一种理论认为手势数组中的某些手势已经在其他地方释放。
  2. 当 UIView 包含 subview 时,释放过程的顺序如何?

一些额外的背景信息:

  1. 崩溃发生了,但没有准确的方法来重现它。
  2. StandardPanelView 实例作为属于其 subview 的手势的委托(delegate)。
  3. 我们在 StandardPanelView 实例上使用 flyweight,即缓存和回收。

提前感谢您提供有关此崩溃如何发生的任何提示。

最佳答案

我的第一印象是您可能正在尝试访问刚刚解除分配的 StandardPanelView。

  • What could be set wrong that makes the internal call to [UIView(UIViewGestures) removeAllGestureRecognizers] crash. One theory is that some gesture in the gestures array is deallocated already somewhere else.

这不会是因为 UIGestureRecognizer 被释放了。 UIView 强烈地将 UIGestureRecognizers 保存在 NSArray 中。当它们仍在数组中时,它们不会被释放。

但是,UIGestureRecognizer 的委托(delegate) 可能已被释放。这只是一个(分配)属性,意味着它不是强持有的,如果委托(delegate)被释放,它将成为一个悬空指针。因此,如果在 [NSArray makeObjectsPerformSelector:] 中使用了委托(delegate),则可能会发生这种情况。

  • When a UIView contains subviews, how is the sequence of deallocation process?

对象从“ parent ”释放到“ child ”,即。 super View 被释放,然后是 subview ,然后是手势识别器。 (虽然 subview 是否在手势识别器之前被释放是一个实现细节,所以你可能不应该依赖它)。

我们可以在一个简单的示例 Controller 中看到这一点:

// The UIView that will be used as the main view
// This is the superview
@interface MyView : UIView
@end

@implementation MyView
- (void)dealloc {
    NSLog(@"Dealloc MyView");
}
@end


// This view will be put inside MyView to be used as a subview
@interface MySubview : UIView
@end

@implementation MySubview
- (void)dealloc {
    NSLog(@"Dealloc MySubview");
}
@end


// This is the gesture recognizer that we will use
// We will give one to each view, and see when it is deallocated
@interface MyGestureRecognizer : UIGestureRecognizer
@property (nonatomic, copy) NSString *tag;
@end

@implementation MyGestureRecognizer
@synthesize tag;
-(void)dealloc {
    NSLog(@"Dealloc MyGestureRecognizer tag: %@", tag);
}
@end


// Just a test view controller that we will push on/pop off the screen to take a look at the deallocations
@interface TestViewController : UIViewController 
@end

@implementation TestViewController
- (void)loadView {
    self.view = [[MyView alloc] init];
    MyGestureRecognizer *recognizer = [[MyGestureRecognizer alloc] initWithTarget:self action:@selector(doStuff)];
    recognizer.tag = @"MyViewGestureRecognizer";
    recognizer.delegate = self;
    [self.view addGestureRecognizer:recognizer];

}

- (void)viewDidLoad {
    [super viewDidLoad];

    MySubview *subview = [[MySubview alloc] init];
    MyGestureRecognizer *recognizer = [[MyGestureRecognizer alloc] initWithTarget:self action:@selector(doStuff)];
    recognizer.tag = @"MySubviewGestureRecognizer";
    recognizer.delegate = self;
    [subview addGestureRecognizer:recognizer];
    [self.view addSubview:subview];
}

- (void)doStuff {
  // we don't actually care what it does
}
@end

我们所做的就是添加 MyView 作为 TestViewController 的主视图,然后在 MyView 中添加一个 MySubview。我们还将 MyGestureRecognizer 附加到每个 View 。

当我们将它推离屏幕时,我们的日志输出显示:

Dealloc TestViewController
Dealloc MyView
Dealloc MySubview
Dealloc MyGestureRecognizer tag: MySubviewGestureRecognizer
Dealloc MyGestureRecognizer tag: MyViewGestureRecognizer

很抱歉,回答太长了...您发布它已经大约 3 个月了,所以也许您已经解决了这个问题,但如果其他人偶然发现了这个答案,我希望它能有所帮助。

关于ios App 在解除分配 UIView 子类实例时崩溃,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18398069/

有关ios App 在解除分配 UIView 子类实例时崩溃的更多相关文章

  1. ruby-on-rails - Rails - 子类化模型的设计模式是什么? - 2

    我有一个模型:classItem项目有一个属性“商店”基于存储的值,我希望Item对象对特定方法具有不同的行为。Rails中是否有针对此的通用设计模式?如果方法中没有大的if-else语句,这是如何干净利落地完成的? 最佳答案 通常通过Single-TableInheritance. 关于ruby-on-rails-Rails-子类化模型的设计模式是什么?,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.co

  2. ruby - 检查 "command"的输出应该包含 NilClass 的意外崩溃 - 2

    为了将Cucumber用于命令行脚本,我按照提供的说明安装了arubagem。它在我的Gemfile中,我可以验证是否安装了正确的版本并且我已经包含了require'aruba/cucumber'在'features/env.rb'中为了确保它能正常工作,我写了以下场景:@announceScenario:Testingcucumber/arubaGivenablankslateThentheoutputfrom"ls-la"shouldcontain"drw"假设事情应该失败。它确实失败了,但失败的原因是错误的:@announceScenario:Testingcucumber/ar

  3. ruby-on-rails - 如何使用 instance_variable_set 正确设置实例变量? - 2

    我正在查看instance_variable_set的文档并看到给出的示例代码是这样做的:obj.instance_variable_set(:@instnc_var,"valuefortheinstancevariable")然后允许您在类的任何实例方法中以@instnc_var的形式访问该变量。我想知道为什么在@instnc_var之前需要一个冒号:。冒号有什么作用? 最佳答案 我的第一直觉是告诉你不要使用instance_variable_set除非你真的知道你用它做什么。它本质上是一种元编程工具或绕过实例变量可见性的黑客攻击

  4. ruby 正则表达式 - 如何替换字符串中匹配项的第 n 个实例 - 2

    在我的应用程序中,我需要能够找到所有数字子字符串,然后扫描每个子字符串,找到第一个匹配范围(例如5到15之间)的子字符串,并将该实例替换为另一个字符串“X”。我的测试字符串s="1foo100bar10gee1"我的初始模式是1个或多个数字的任何字符串,例如,re=Regexp.new(/\d+/)matches=s.scan(re)给出["1","100","10","1"]如果我想用“X”替换第N个匹配项,并且只替换第N个匹配项,我该怎么做?例如,如果我想替换第三个匹配项“10”(匹配项[2]),我不能只说s[matches[2]]="X"因为它做了两次替换“1fooX0barXg

  5. Ruby Koans about_array_assignment - 非平行与平行分配歧视 - 2

    通过ruby​​koans.com,我在about_array_assignment.rb中遇到了这两段代码你怎么知道第一个是非并行赋值,第二个是一个变量的并行赋值?在我看来,除了命名差异之外,代码几乎完全相同。4deftest_non_parallel_assignment5names=["John","Smith"]6assert_equal["John","Smith"],names7end45deftest_parallel_assignment_with_one_variable46first_name,=["John","Smith"]47assert_equal'John

  6. Ruby Readline 在向上箭头上使控制台崩溃 - 2

    当我在Rails控制台中按向上或向左箭头时,出现此错误:irb(main):001:0>/Users/me/.rvm/gems/ruby-2.0.0-p247/gems/rb-readline-0.4.2/lib/rbreadline.rb:4269:in`blockin_rl_dispatch_subseq':invalidbytesequenceinUTF-8(ArgumentError)我使用rvm来管理我的ruby​​安装。我正在使用=>ruby-2.0.0-p247[x86_64]我使用bundle来管理我的gem,并且我有rb-readline(0.4.2)(人们推荐的最少

  7. ruby-on-rails - Rails - 从另一个模型中创建一个模型的实例 - 2

    我有一个正在构建的应用程序,我需要一个模型来创建另一个模型的实例。我希望每辆车都有4个轮胎。汽车模型classCar轮胎模型classTire但是,在make_tires内部有一个错误,如果我为Tire尝试它,则没有用于创建或新建的activerecord方法。当我检查轮胎时,它没有这些方法。我该如何补救?错误是这样的:未定义的方法'create'forActiveRecord::AttributeMethods::Serialization::Tire::Module我测试了两个环境:测试和开发,它们都因相同的错误而失败。 最佳答案

  8. Ruby——嵌套类和子类是一回事吗? - 2

    下面例子中的Nested和Child有什么区别?是否只是同一事物的不同语法?classParentclassNested...endendclassChild 最佳答案 不,它们是不同的。嵌套:Computer之外的“Processor”类只能作为Computer::Processor访问。嵌套为内部类(namespace)提供上下文。对于ruby​​解释器Computer和Computer::Processor只是两个独立的类。classComputerclassProcessor#Tocreateanobjectforthisc

  9. ruby-on-rails - RSpec:避免使用允许接收的任何实例 - 2

    我正在处理旧代码的一部分。beforedoallow_any_instance_of(SportRateManager).toreceive(:create).and_return(true)endRubocop错误如下:Avoidstubbingusing'allow_any_instance_of'我读到了RuboCop::RSpec:AnyInstance我试着像下面那样改变它。由此beforedoallow_any_instance_of(SportRateManager).toreceive(:create).and_return(true)end对此:let(:sport_

  10. ruby - 在 Ruby 中重新分配常量时抛出异常? - 2

    我早就知道Ruby中的“常量”(即大写的变量名)不是真正常量。与其他编程语言一样,对对象的引用是唯一存储在变量/常量中的东西。(侧边栏:Ruby确实具有“卡住”引用对象不被修改的功能,据我所知,许多其他语言都没有提供这种功能。)所以这是我的问题:当您将一个值重新分配给常量时,您会收到如下警告:>>FOO='bar'=>"bar">>FOO='baz'(irb):2:warning:alreadyinitializedconstantFOO=>"baz"有没有办法强制Ruby抛出异常而不是打印警告?很难弄清楚为什么有时会发生重新分配。 最佳答案

随机推荐