2

ファイルの読み込み状況を示す進行状況バーを作成したいと思います。 変数_progressを含むC++クラスのリーダーを使用してファイルを読みました。ココアの進行状況バーでファイルを読む

どのようにReaderクラスにObjCコードを書き込まずに、progress.barの値をプログレスバーに更新するようにCocoaに指示できますか?

ご協力いただければ幸いです。

ProgressController *pc = [[ProgressController alloc] init]; 
[pc showWindow:sender]; 


// Create the block that we wish to run on a different thread 
void (^progressBlock)(void); 
progressBlock = ^{ 
    [pc.pi setDoubleValue:0.0]; 
    [pc.pi startAnimation:sender]; 

    Reader reader("/path/to/myfile.txt"); 
    reader.read(); 

    while (reader._progress < 100.) 
    { 
     dispatch_async(dispatch_get_main_queue(), ^{ 
      [pc.pi setDoubleValue:reader._progress]; 
      [pc.pi setNeedsDisplay:YES]; 
     }); 
    } 
}; // end of progressBlock 

// Finally, run the block on a different thread 
dispatch_queue_t queue = dispatch_get_global_queue(0, 0); 
dispatch_async(queue, progressBlock); 

だからここに私の2回目の試行です。

リーダーコード:

class PDBReader 
{ 
public: 
Reader(const char *filename); 
Reader(string filename); 
~Reader(); 

int read(); 

string _filename; 
float _progress; 

void setCallback(void (^cb)(double)) 
{ 
    if (_cb) 
    { 
     Block_release(_cb); 
     _cb = Block_copy(cb); 
    } 
} 
void (^_cb)(double); 

protected: 
private: 
}; 



int Reader::read() 
{ 
string buffer; 
unsigned atomid = 0; 
ifstream file; 
file.open(_filename.c_str(), ifstream::in); 

if (!file.is_open()) 
{ 
    return IOERROR; 
} 

file.seekg(0, ios_base::end); 
float eof = (float) file.tellg(); 
file.seekg(0, ios_base::beg); 

while (getline(file, buffer)) 
{ 
    _progress = (float) file.tellg()/eof * 100.; 
    if (_cb) 
    { 
     _cb(_progress); 
    } 
     // some more parsing here... 
    } 
file.close(); 
return SUCCESS; 
} 

PDBReader::~PDBReader() 
{ 
if (_cb) 
{ 
    Block_release(_cb); 
} 
} 

とココアの一部:あなたの助けのための

-(IBAction) test:(id) sender 
{ 
ProgressController *pc = [[ProgressController alloc] init]; 
[pc showWindow:sender]; 

Reader reader("test.txt"); 

reader.setCallback(^(double progress) 
{ 
    dispatch_async(dispatch_get_main_queue(), ^{ 
     [pc.pi setDoubleValue:progress]; 
     [pc.pi setNeedsDisplay:YES]; 
    }); 
}); 

reader.read(); 
} 

感謝。

+0

投稿したコードを使用する際にどのような問題が発生していますか? –

+0

主な問題は動作しないということです!まったく意味があります!基本的には無限ループのようです。 – blaurent

答えて

0

最後に!!!!!

キューに入れないとうまくいきます。

ProgressController *pc = [[ProgressController alloc] init]; 
[pc showWindow:sender]; 
[pc.pi setUsesThreadedAnimation:YES]; 

Reader reader("test.txt"); 
reader.setCallback(^(double progress) 
{ 
    [pc.pi setDoubleValue:progress]; 
    [pc.pi setNeedsDisplay:YES]; 
}); 

reader.read(); 

しかし、なぜ「これはメインスレッドをブロックするので、これは悪いです」と言いますか? 基本的に私のプログラムは何か他のことをする前にファイルを読み込むのを待つ必要があるからです。 ここに欠けている基本的な最適化はありますか?

ご協力いただきありがとうございます。

+0

なぜあなた自身の回答を投稿して、それを私のものよりも受け入れたのですか? –

7

読者にObjective-Cコードを含めさせたくないという理由だけで、外部からしか見ることができないということではありません。渡された関数ポインタを介してC関数を呼び出すことができます。それは、より一般的なファンクタ(関数オブジェクト)メカニズムを使用することができます。ブロックすることもできます。

あなたは間違いなくそのループをwhile (reader._progress < 100.)したくありません。それはビジーなループです。可能な限り速やかに進行状況を更新することをスピンします。 CPUコアを100%利用でペグします。実際には、タスクは主ディスパッチキューにタスクが実行できるよりも速くキューイングされます。

Readerが_progressのメンバーを更新したときに進行状況インジケータを更新したい場合は、Readerクラスから何らかの協力が必要です。

+0

あなたの答えをありがとう。私はこの結論に至りましたが、私はそれをどうやって行うのか分かりません。提案するサンプルコードはありますか? – blaurent

+0

たとえば、 'Reader'クラスに' setCallback(void(^ cb)(double)) 'メンバ関数を作成します。 'void(^ _cb)(double)'メンバ変数も作成してください。設定者は 'if(_cb)Block_release(_cb);を実行します。 _cb =ブロックコピー(cb); '。 'Reader'が' _progress'を更新するたびに、 'if(_cb)_cb(_progress);'も行うべきです。デストラクタは 'if(_cb)Block_release(_cb);'も行うべきです。 –

+0

ありがとうございます。私はそれを試してみましょう。 – blaurent

関連する問題