Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <p>Use <code>@synchronized(logBuffer)</code>:</p> <pre><code>- (void) addToLog:(NSString*)str { @synchronized(logBuffer) { [logBuffer addObject:s]; } if ([logBuffer count] &gt;= kBufferSize) { [self writeLogOnFile]; } } - (void) writeLogOnFile { @synchronized(logBuffer) { NSString *multiline = [logBuffer componentsJoinedByString:@"\r\n"]; multiline = [NSString stringWithFormat:@"%@\n", multiline]; NSData *data = [multiline dataUsingEncoding:NSUTF8StringEncoding]; NSFileHandle *outputFileHandle = [NSFileHandle fileHandleForWritingAtPath:logFilePath]; [outputFileHandle seekToEndOfFile]; [outputFileHandle writeData:data]; [outputFileHandle closeFile]; [logBuffer removeAllObjects]; // This is where the exception is thrown } } </code></pre> <p>Edit: Since I'm using <code>@synchronized</code>, we can get rid of the buffer copy and just synch.</p> <p>In continuation, considering the comments and edited question:</p> <p>If you only call <code>writeLogOnFile</code> from <code>addToLog</code>, then I would do one of two things:</p> <ol> <li><p>Merge the <code>writeLogOnFile</code> code into <code>addToLog</code>, since it's 1-to-1 anyway. This ensures that nothing will ever directly call <code>writeLogOnFile</code>. In this case, wrap <code>addToLog</code> completely within <code>@synchronized(logBuffer) {}</code></p></li> <li><p>If you want to keep <code>writeLogOnFile</code> separate for whatever reason, then make this method private to the class. In this case, you can get rid of <code>@synchronized(logBuffer)</code> within <code>writeLogOnFile</code> since in theory you know what you are doing within the class, but you should also wrap <code>addToLog</code> completely within <code>@synchronized(logBuffer) {}</code></p></li> </ol> <p>As you can see, in both cases you should absolutely make <code>addToLog</code> completely single-threaded through <code>@synchronized</code> (or keep the original answer). It's very simple, keeps your code clean, and gets rid of all the threading issues that your edited question is trying to work around. The <code>@synchronized</code> pattern was created specifically to avoid writing all the wrapper code that you wrote to solve your problem, namely forcing everything through the main thread (or a specific thread).</p> <p>For completeness, here's the complete code that I would write:</p> <pre><code>- (void) addToLog:(NSString*)str { @synchronized(logBuffer) { [logBuffer addObject:s]; if ([logBuffer count] &gt;= kBufferSize) { // write log to file NSString *multiline = [logBuffer componentsJoinedByString:@"\r\n"]; multiline = [NSString stringWithFormat:@"%@\n", multiline]; NSData *data = [multiline dataUsingEncoding:NSUTF8StringEncoding]; NSFileHandle *outputFileHandle = [NSFileHandle fileHandleForWritingAtPath:logFilePath]; [outputFileHandle seekToEndOfFile]; [outputFileHandle writeData:data]; [outputFileHandle closeFile]; [logBuffer removeAllObjects]; } } } </code></pre>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. VO
      singulars
      1. This table or related slice is empty.
    2. VO
      singulars
      1. This table or related slice is empty.
    3. VO
      singulars
      1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload