2012-06-22 60 views
3

背景應用的UITextView滾動

我的應用程序需要的數據從一個網絡流中,並改變在屏幕上的用戶界面元素的值之後崩潰。一個元素是UITextView,它用作傳入數據的一種日誌。當應用程序收到一個「HasBytesAvailable」NSStreamEvent時,它應該會隨着數據傳入的性質而更新。 (例如,如果進入的數據與蛋糕有關,textview會更新爲類似「6/22/12 8:00 - 得到蛋糕」)。下面顯示了它如何更新的示例。

[logString insertString:@"This is an update\n" atIndex:0]; 
//logstring is a MutableString I use to hold my UITextView's text 
[logString insertString:timeString atIndex:0]; //timestring is current time 
logView.text = logString; //logView is my UITextView 
[logView flashScrollIndicators]; 

//logstring and logview declaration and implementation 
@property (nonatomic,retain) IBOutlet UITextView *logView; 
@property (nonatomic,retain) NSMutableString *logString; 

logString = [[NSMutableString alloc] initWithString:@"-logging started\n"]; 

的問題

的更新工程,我想它,只要我不試圖滾動TextView的。但是,如果我滾動瀏覽文本並按住它,推測足夠長,以便我的更新代碼被調用,那麼當我停止滾動時,應用程序會崩潰。我可以輕鬆瀏覽文本,只是在它必須處理傳入數據包時,我仍然在滾動,它會崩潰。此外,當我滾動時,沒有其他更新。應該由收到的數據更新的所有標籤保持不變。

我的思想

這是因爲如果該應用程序不能同時處理滾動,並在同一時間輸入數據的工作。我不確定這是因爲我在內存管理上做了什麼錯誤,或者我需要覆蓋一些滾動功能,或者完全是其他的東西。任何幫助或想法表示讚賞。

解決方案

正如trumpetlicks說,我需要實現多線程對我的網絡任務 做到這一點,我做了以下內容:

在初始化

NSOperationQueue *networkQueue = [NSOperationQueue new]; 
NSInvocationOperation *operation = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(initNetworkCommunication) object:nil]; 
[networkQueue addOperation:operation]; 
[operation release]; 
在initNetworkCommunication

:初始化CFSocketpair和流後
+0

對我來說,當你正在主動滾動時,UI線程很忙,而且不會執行其他更新。 (我假設你的網絡正在其他線程中發生。)崩潰是什麼樣子(異常和堆棧)? –

+0

你的網絡流量有多高?它看起來像一個輕的網絡負載應該導致你所看到的,如果它是一個沉重的負載,那麼這是另一個問題! – trumpetlicks

+0

@trumpetlicks它不應該成爲流量負載,我們正在談論每條消息64字節,每秒約一次。 –

回答

0

從這裏開始。

developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/...您可以

也希望增加你的網絡設置和使用的代碼,以便大家都看到你在做什麼有! !

0

我可以建議3個想法,可以幫助你:

1)DONT調用後臺線程中的UI元素,總是在主線程,因此,例如使用:

dispatch_async(dispatch_get_main_queue(), ^{ 

     self.textview.text = ..... 

    }); 

2)使用一些線程之間的同步類型(稍後更多..)

3)的NSOperation是這個任務太複雜,簡單地使用NSURLSession回調並在完成所謂的「中心」的方法,你必須序列(如2))

說,假設在每個網絡回撥:

... 
    // create Session and request... 
    NSURLSessionDataTask *task = [session dataTaskWithRequest:request 
              completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) { 
               NSString * s = [[NSString alloc]initWithData:data encoding: NSUTF8StringEncoding]; 
               [self serializer:s]; 
              } 
            ]; 
    [task resume]; 
... 

4)現在,讓我們嘗試同步(在 「初始化」 進入主線程UI ..)

/viewDidLoad中創建一個

self.queue = dispatch_queue_create("com.acme.myQueue", DISPATCH_QUEUE_CONCURRENT); 

5)用它,在串行方法:

-(void) serializer:(NSString*)s 
{ 
    dispatch_barrier_async(self.queue, ^{ 
     [self updateUI:s]; 
    }); 
} 

6)更新UI:

-(void) updateUI:(NSString*)s 
{ 
    dispatch_async(dispatch_get_main_queue(), ^{ 
     NSString * currText = self.textView.text; 
     self.textView.text = [NSString stringWithFormat:@"%@\n%@", currText, s]; 

    }); 
} 

所以回顧一下我所有的控制器可以是(一些細節留給你..)

@interface ViewController() 

@property dispatch_queue_t queue; 
@property UITextView * textView; 

@end 

@implementation ViewController 

- (void)viewDidLoad { 
    [super viewDidLoad]; 
    self.queue = dispatch_queue_create("com.acme.myQueue", DISPATCH_QUEUE_CONCURRENT); 

    [self startDownloadFromURL:@"https://www.apple.com"]; 
    [self startDownloadFromURL:@"https://www.google.com"]; 
} 


-(void)startDownloadFromURL:(NSString*)urlString{ 

    NSURLSession * session; 
    NSURLRequest * request; 

    // create Session and request... 
    NSURLSessionDataTask *task = [session dataTaskWithRequest:request 
              completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) { 
               NSString * s = [[NSString alloc]initWithData:data encoding: NSUTF8StringEncoding]; 
               [self serializer:s]; 
              } 
            ]; 
    [task resume]; 
} 

-(void) serializer:(NSString*)s 
{ 
    dispatch_barrier_async(self.queue, ^{ 
     [self updateUI:s]; 
    }); 
} 


-(void) updateUI:(NSString*)s 
{ 
    dispatch_async(dispatch_get_main_queue(), ^{ 
     NSString * currText = self.textView.text; 
     self.textView.text = [NSString stringWithFormat:@"%@\n%@", currText, s]; 

    }); 
} 





@end