Данные пропадают при передаче между потоками с использованием Singleton

Изменить:

Спасибо @BlackFrog. Я думаю, что я уже ближе, но значения все еще не доходят...

Значения устанавливаются, как показано в журналах в [progressController updateProgressSummary:...], но равны нулю, когда я регистрирую их в progressUpdate initWithProgressUpdate:.... как показано ниже.

Я немного запутался в том, какое свойство используется: один набор для progressUpdate или те, которые установлены для каждого из трех компонентов progressUpdate. Я изменил 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 и передает ему сведения о текущем прогрессе. Это, в свою очередь, выполняет действие SelectorOnMainThread для делегата ProgressController (контроллера представления) для отображения деталей.

Все работало нормально, когда я проходил через одну NSString, но мне нужно передать две строки и число, а так как PerformSelectorOnMainThread может передать только один объект, я инкапсулировал их в пользовательский объект — ProgressUpdate.

Данные проходят через ProgressController правильно, но к тому времени, когда они появляются в контроллере представления, становятся нулевыми. Я знаю это, так как размещал 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];
}

person Chris    schedule 19.04.2011    source источник


Ответы (2)


В методе init вы только назначаете ivars и не сохраняете их в новом объекте. Повторите свой метод инициализации следующим образом:

-(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;
}

Пара моментов:

  • Вы не должны использовать метод доступа в методе инициализации
  • Переименуйте свой метод инициализации, чтобы было понятно
  • В @property измените назначение, чтобы сохранить
person Black Frog    schedule 19.04.2011

Попробуйте удалить оператор '[выпуск progressUpdateForIssue];' в методе

'-(void) updateProgressSummary: (NSString *) краткая информация: (NSString *) детализация процента завершения: (NSNumber *) полная '.

Также измените атрибут свойства с «назначить» на «сохранить» в вашем классе ProgressUpdate. Вы можете освободить эти свойства в методе Dealloc.

Удачи.

person Sreehari.S    schedule 19.04.2011
comment
Спасибо Шрихари, но это не имеет значения. - person Chris; 19.04.2011