2013-06-27 32 views
7

Trong ứng dụng của tôi, tôi có một UITableViewController.Tải lại dữ liệu của UITableView ở chế độ nền

Bảng của nó được chia thành 3 phần.

Tôi tải xuống dữ liệu cho từng phần đó từ máy chủ của tôi. Để làm điều này, tôi có 3 chức năng (ví dụ f1 f2 và f3). Mỗi cập nhật một NSArray tương ứng, được sử dụng làm nguồn dữ liệu cho bảng của tôi.

Bây giờ những gì tôi muốn là tải lại dữ liệu bằng cách sử dụng chức năng này và làm mới tableView của tôi sau khi 3 chức năng này được thực hiện, nhưng không làm phiền người dùng.

Tôi không được sử dụng với yêu cầu, khối, chuỗi, v.v. không đồng bộ và tôi đang tìm kiếm các mẹo.

Trên thực tế, đây là những gì tôi làm:

-(void)viewDidLoad 
{ 
    //some settings 

    [NSTimer scheduledTimerWithTimeInterval:15.0 target:self selector:@selector(reloadDatas) userInfo:nil repeats:YES]; 

    dispatch_queue_t queue = dispatch_get_main_queue(); 
    dispatch_async(queue, ^{ 
     [self reloadDatas]; 
    }); 
} 

-(void)reloadDatas 
{ 
    dispatch_queue_t concurrentQueue = dispatch_get_main_queue(); 
    dispatch_async(concurrentQueue, ^{ 
     [self f1]; 
     [self f2]; 
     [self f3]; 
     [myDisplayedTable reloadData]; 
    }); 
} 

-(void)f1 
{ 
    //load datas with a url request and update array1 
} 
-(void)f2 
{ 
    //load datas with a url request and update array2 
} 
-(void)f3 
{ 
    //load datas with a url request and update array3 
} 

Nhưng ở đây, tableView của tôi là "đóng băng" cho đến khi nó được làm mới.

Tôi không quan tâm đến thứ tự thực hiện f1 f2 và f3, nhưng tôi cần phải đợi 3 hàm này được thực hiện trước khi làm mới tableView của tôi.

Cảm ơn sự giúp đỡ của bạn.

EDIT

Cảm ơn tất cả những câu trả lời của bạn.

Dưới đây là giải pháp làm việc:

Như mros suggets, tôi loại bỏ các hàng đợi công văn từ viewDidLoad, và thay thế trong reloadDatas:

dispatch_queue_t concurrentQueue = dispatch_get_main_queue(); 

với

dispatch_queue_t mainThreadQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); 

Và cuối cùng, Tôi tải lại bảng của mình trong một chủ đề chính

dispatch_async(dispatch_get_main_queue(), ^{ [myDisplayedTable reloadData]; }); 

Trả lời

4

Vì vậy, "chuỗi nền" thực sự là chủ đề chính của bạn. Bạn phải sử dụng dispatch_get_global_queue và chỉ định mức độ ưu tiên để thực sự nhận được một chuỗi khác. Ngoài ra, công văn async trong viewDidLoad là vô ích vì tất cả các phương thức vòng đời của bộ điều khiển khung nhìn được gọi trong luồng chính. Tôi khuyên bạn nên làm điều gì đó như sau trong các phương thức f1, f2 và f3:

Bắt đầu bằng cách khởi chạy yêu cầu url không đồng bộ, sau đó trong khối hoàn thành, cập nhật mảngX và tải lại một phần cụ thể trong chế độ xem bảng của bạn. Bằng cách này, cả ba yêu cầu có thể xảy ra đồng thời và bảng chỉ cập nhật dữ liệu cần thiết khi mỗi lần kết thúc.Ngoài ra, nếu bạn chỉ muốn tải lại một lần, chỉ cần thay thế biến concurrentQueue mà bạn có bằng chuỗi nền và sau đó thực hiện [tableView reloadData] trên chuỗi chính.

2

Trong reloadDatas phương pháp bạn nên thay đổi dòng này:

dispatch_queue_t concurrentQueue = dispatch_get_main_queue(); 

Để:

dispatch_queue_t concurrentQueue = dispatch_queue_create("some queue", NULL);

Nhưng khi bạn gọi [myDisplayedTable reloadData], bạn cần phải gọi hoạt động này trong hàng đợi chính.

dispatch_async(dispatch_get_main_queue(), ^{ [myDisplayedTable reloadData]; }); 
+0

Bạn đã tạo concurrentQueue chưa? – abhi1992

3

Câu trả lời trước là hoàn toàn đúng. Tuy nhiên, việc triển khai reloadDatas của bạn & viewDidLoad hơi có vấn đề.

Chỉ cần làm rõ:

Bạn muốn hoàn thành thời gian tiêu thụ dữ liệu tải thứ trong một thread nền, sau đó cập nhật UI/Các tế bào khi dữ liệu của bạn đã sẵn sàng vào các chủ đề chính.

Giống như vậy:

-(void)viewDidLoad 
    { 
     dispatch_queue_t concurrentQueue = dispatch_queue_create("com.my.backgroundQueue", NULL); 
     dispatch_async(concurrentQueue, ^{ 
      [self reloadDatas]; 
     }); 
    } 

-(void)reloadDatas 
{ 
    // Expensive operations i.e pull data from server and add it to NSArray or NSDictionary 
     [self f1]; 
     [self f2]; 
     [self f3]; 

    // Operation done - now let's update our table cells on the main thread 

    dispatch_queue_t mainThreadQueue = dispatch_get_main_queue(); 
    dispatch_async(mainThreadQueue, ^{ 

     [myDisplayedTable reloadData]; // Update table UI 
    }); 
} 
+0

Tôi đã thử giải pháp của bạn, nhưng tương tác của người dùng và tải lại đang chặn nhau. Tôi có nghĩa là reloadDatas không được gọi vì người dùng không ngừng di chuyển bảng và người dùng không thể cuộn bảng trong khi bảng không được làm mới ... – zbMax

+0

Bạn có chắc chắn nó không được gọi vì người dùng đang cuộn bảng ? Thử thêm một vài NSLog hoặc breakpoint. – smaura777

+0

có, đó là những gì tôi có ý nghĩa bởi 'tương tác người dùng': khi cuộn bảng, NSTimer của tôi không gọi hàm của tôi cho đến khi cuộn kết thúc. – zbMax

1

Một điều khác. Việc kéo dữ liệu từ máy chủ và cập nhật các ô bảng là khá phổ biến. Không cần hàng đợi hoặc hẹn giờ ở đây. Đây là một cấu trúc thay thế.

Giả sử bạn đang kéo mp3 từ máy chủ của mình: Lớp mô hình của bạn là: Music.h/m Trình quản lý mô hình của bạn là: MusicManager.h/m (Singleton) - nó sẽ chứa một mảng đối tượng nhạc - singleton về cơ bản là nguồn dữ liệu của bạn; và cuối cùng UITableViewController của bạn: MusicTableVC.h/m

Trong MusicManager.h/m: Bạn có một NSMutableArray đó sẽ được nạp với các đối tượng Music.h mà bạn đã kéo từ máy chủ. Bạn có thể làm điều đó ngay sau khi bạn tải ứng dụng mà không cần chờ đợi cho TableViewController.

Bên trong MusicManager bạn có một vài phương thức trợ giúp để thêm hoặc xóa các mục khỏi mutableArray và cung cấp số lượng và tất nhiên các phương thức kết nối mạng của bạn.

Cuối cùng: Đăng thông báo trong mã mạng của bạn. UITableViewController của bạn nên lắng nghe/quan sát thông báo đó và "tải lại" cho phù hợp.

[[NSNotificationCenter defaultCenter] postNotificationName:@"NewMusicAdded" object:nil]; 

Bạn truy vấn dữ liệu từ máy chủ, phân tích dữ liệu vào đối tượng Âm nhạc thêm chúng vào mảng NSMutable của bạn và đăng thông báo để bản cập nhật bảng.

Công thức khá chuẩn.

Các vấn đề liên quan