【问题标题】:Data going missing when passed between threads using a Singleton使用单例在线程之间传递时数据丢失
【发布时间】:2011-04-19 08:52:39
【问题描述】:

编辑:

感谢@BlackFrog。我想我现在更接近了,但价值观仍然没有得到通过......

这些值的设置如 [progressController updateProgressSummary:...] 中的日志所示,但当我将它们记录在 progressUpdate initWithProgressUpdate:.... 中时为 nil,如下所示。

对于哪个属性用于progressUpdate 的设置或progressUpdate 的3 个组件中的每一个设置的属性,我有点困惑。我已按照建议将 3 个单独的属性从分配更改为保留,并且也尝试对整体 progressUpdate 属性执行相同操作(此处未显示)。

progressController.h

......

    @property (nonatomic, assign)   ProgressUpdate  *progressUpdate;

progressController.m

// Ask delegate to update and display Progress text
-(void) updateProgressSummary:(NSString *)summary detail:(NSString *)detail percentComplete:(NSNumber *)complete {
// These report the proper values
    DLog(@"Reporting Summary - %s", [summary UTF8String]);
    DLog(@"Reporting Detail -  %s", [detail UTF8String]);
    DLog(@"Reporting Complete -  %i", [complete intValue]); 

    if (summary != nil)
        self.progressUpdate.summaryText = summary;
    self.progressUpdate.detailText = detail;
    self.progressUpdate.percentComplete = complete;

    ProgressUpdate *progressUpdateForIssue = [[ProgressUpdate alloc] initWithProgressUpdate:progressUpdate];    
    [self.delegate performSelectorOnMainThread:@selector(displayProgress:) withObject:progressUpdateForIssue waitUntilDone:NO]; 

    [progressUpdateForIssue release];

}

但是几毫秒后....,在对象内部....它们为零。

progressUpdate.h

.....

@property (nonatomic, retain) NSString  *summaryText;
@property (nonatomic, retain) NSString  *detailText;
@property (nonatomic, retain) NSNumber  *percentComplete;

progressUpdate.m

-(id) initWithProgressUpdate:(ProgressUpdate *)update {
    if ((self = [super init])) {
        summaryText = [update.summaryText copy];
        detailText = [update.detailText copy];
        percentComplete = [[NSNumber alloc] initWithFloat:[update.percentComplete floatValue]];
    }
    // These report nil values
    DLog(@"Reporting in progUpdate summaryText - %s", [summaryText UTF8String]);
    DLog(@"Reporting in progUpdate detailText -  %s", [detailText UTF8String]);
    DLog(@"Reporting in progUpdate percentComplete -  %i", [percentComplete intValue]);
return self;
}

更新结束

在将自定义类中的数据从一个线程传递到另一个线程时,我需要一些帮助。它在通行证之前就在那里,但在到达时就消失了。我已经尝试了我所知道的一切,但无济于事。

我的后台线程调用 ProgressController 并将当前进度的详细信息传递给它。这反过来会在 ProgressController 的委托(视图控制器)上执行 SelectorOnMainThread 以显示详细信息。

当我通过单个 NSString 时一切正常,但我需要传递两个字符串和一个数字,并且由于 performSelectorOnMainThread 只能传递一个对象,我已将它们封装在一个自定义对象中 - ProgressUpdate。

数据正确地传递到 ProgressController,但在它出现在 View Controller 中时为空。我知道这一点,因为我已将 NSLogs 放在不同的地方。

我想知道它是否与:

  • 多线程和自定义对象

  • ProgressController 是一个单例的事实,这就是为什么我每次调用它时都分配一个新的 ProgressUpdate,但这没有帮助。

欢迎任何想法。为清楚起见,代码如下。

ProgressUpdate.h

#import <Foundation/Foundation.h>


@interface ProgressUpdate : NSObject {
    NSString    *summaryText;    
    NSString    *detailText;
    NSNumber    *percentComplete;
}
@property (nonatomic, assign) NSString  *summaryText;
@property (nonatomic, assign) NSString  *detailText;
@property (nonatomic, assign) NSNumber  *percentComplete;

-(id) initWith:(ProgressUpdate *)update;

@end

ProgressUpdate.m

#import "ProgressUpdate.h"

@implementation ProgressUpdate

@synthesize summaryText, detailText, percentComplete;

-(id) initWith:(ProgressUpdate *)update {
    self = [super init];

    self.summaryText = update.summaryText;
    self.detailText = update.detailText;
    self.percentComplete = update.percentComplete;
    return self;
}

@end

ProgressController.m

static ProgressController *sharedInstance;

+ (ProgressController *)sharedInstance {
    @synchronized(self) {
        if (!sharedInstance)
            [[ProgressController alloc] init];              
    }
    return sharedInstance;
}

+(id)alloc {
    @synchronized(self) {
        NSAssert(sharedInstance == nil, NSLocalizedString(@"Attempted to allocate a second instance of a singleton ProgressController.", @"Attempted to allocate a second instance of a singleton ProgressController."));
        sharedInstance = [super alloc];
    }
    return sharedInstance;
}
-(id) init {
    if (self = [super init]) {
        [self open];
    }
    return self;
}

.........

// Ask delegate to update and display Progress text
-(void) updateProgressSummary:(NSString *)summary detail:(NSString *)detail percentComplete:(NSNumber *)complete {

    if (summary != nil)
        self.progressUpdate.summaryText = summary;
    self.progressUpdate.detailText = detail;
    self.progressUpdate.percentComplete = complete;
    ProgressUpdate *progressUpdateForIssue = [[ProgressUpdate alloc] initWith:progressUpdate];  
    [self.delegate performSelectorOnMainThread:@selector(displayProgress:) withObject:progressUpdateForIssue waitUntilDone:NO]; 
    [progressUpdateForIssue release];

}

RootViewController.m

// Delegate method to display specific text in Progress label
- (void) displayProgress:(ProgressUpdate *)update {
    [progressSummaryLabel setText:update.summaryText];
    [progressDetailLabel setText:update.detailText];
    [progressBar setProgress:[update.percentComplete intValue]];
    [progressView setNeedsDisplay];
}

【问题讨论】:

    标签: iphone objective-c multithreading singleton alloc


    【解决方案1】:

    在 init 方法中,您只是分配 ivars 而不是将它们保留在新对象中。 重做您的 init 方法,如下所示:

    -(id) initWithProgressUpdate:(ProgressUpdate *)update {
        if ((self = [super init])) {
            summaryText = [update.summaryText copy];
            detailText = [update.detailText copy];
            percentComplete = [[NSNumber alloc] initWithFloat:[update.percentComplete floatValue];
        }
        return self;
    }
    

    几点:

    • 不应在 init 方法中使用访问器
    • 重命名您的 init 方法以更清晰
    • 在@property 中,将assign 更改为retain

    【讨论】:

      【解决方案2】:

      尝试删除语句“[progressUpdateForIssue release];”在方法中

      '-(void) updateProgressSummary:(NSString *)summary detail:(NSString *)detail percentComplete:(NSNumber *)complete '.

      还要在您的 ProgressUpdate 类中将属性属性从“分配”更改为“保留”。 您可以在 dealloc 方法中释放这些属性。

      祝你好运。

      【讨论】:

      • 谢谢 Sreehari,但这没什么区别。
      猜你喜欢
      • 1970-01-01
      • 2011-08-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-10-12
      • 1970-01-01
      • 1970-01-01
      • 2014-02-22
      相关资源
      最近更新 更多