2012-07-28 17 views
17

Tôi thấy trong nhiều video của WWDC cho biết bạn muốn đạt được 60.0 FPS càng gần càng tốt để có trải nghiệm cuộn mượt mà hơn. Tôi có một UIScrolLView tải lên hình ảnh và một vài lần xem bảng cùng một lúc. Hiện tại tôi đang nhận được 30 FPS. Đây là một nửa số FPS được đề xuất. Chỉ cần tự hỏi FPS những gì bạn guys thường nhận được cho một cái nhìn xem bảng/cuộn mà tải lên hình ảnh và các công cụ nặng/rendering khác.FPS có thể chấp nhận được khi cuộn và mẹo nào để cải thiện hiệu suất?

Bất kỳ mẹo nào khác để chọn lọc FPS? Tôi đã dành cả tuần qua cho đến bây giờ bắn lên dụng cụ bằng cách sử dụng thời gian profiler, phân bổ, và công cụ hoạt hình cốt lõi để tối ưu hóa nhiều nhất có thể.

Chỉ cần làm rõ một chút về những gì tôi có. Tôi có bố trí kiểu nề/thác/kiểu sở thích trên iPad. Vì vậy, nó không chỉ là một UITableView thông thường. Đó là một UIScrollView lấp đầy toàn bộ màn hình, và được lấp đầy với một vài của UIView. Mỗi khung nhìn này có một UIImageView 150x150 và một UITableView và nó cũng có một số nhãn được phân bổ, được vẽ bằng cách sử dụng Core Text. Vì vậy, trong nháy mắt khi bạn nhìn thấy màn hình, bạn có thể thấy 5-8 xem bảng tại một lần chụp, mỗi ô lại có UIImageView và sau đó mỗi ô sẽ hiển thị nhãn được phân bổ được vẽ bằng văn bản lõi.

Vì vậy, bạn chỉ có thể hình ảnh sâu sắc và phức tạp như thế nào. Đây không chỉ là chế độ xem bảng thông thường với UIImageView. Tôi biết làm thế nào để có được 60 FPS chỉ với một UITableView trong một chiếc iPhone với một UIImage. Khái niệm này là tải hình ảnh một cách đồng bộ và không chặn chủ đề chính càng nhiều càng tốt.

EDIT:

Dường như vấn đề ở đây là UITableView mà tôi có trong quan điểm của tôi .. khi tôi loại bỏ từ UIView tôi nhận được di chuyển thực sự trơn tru ..

Tôi đã tải lên một dự án mẫu là một phiên bản đơn giản của những gì tôi có, nhưng nó cho thấy rõ ràng vấn đề. Liên kết là here

+0

có lẽ đây: http: //www.cocoacontrols .com/platforms/ios/controls/gmgridview (nếu nó giống như Pinterest?) – sridvijay

+1

Có vẻ như bạn cũng cần PSCollectionView để biên dịch: https://github.com/ptshih/PSCollectionView – Eoin

Trả lời

19

Nhiều việc ảnh hưởng đến hiệu suất làm, sau đây là một số mặt hàng, bạn có thể kiểm tra:

  • Hồ sơ - Bạn nói bạn đã làm điều này, công việc tuyệt vời như vậy! Thật không may hồ sơ thường bị bỏ qua, mặc dù nó có thể tiết lộ những vấn đề bất ngờ. Trong một ứng dụng tôi đã làm việc trên một lịch với các ô khác nhau đại diện cho ngày tháng. Lúc đầu di chuyển giữa các tế bào chậm, đó là bất ngờ. Tôi nghĩ có lẽ nó đang vẽ một vài tế bào quá nhiều. Sau khi profiling tôi thấy rằng [NSCalender currentCalender] đã sử dụng 85% thời gian CPU của tôi! Sau khi sửa chữa tất cả mọi thứ cuộn tuyệt vời!

  • Hình ảnh - Hình ảnh lớn đặt rất nhiều tải trong CoreGraphics. Di chuyển đặc biệt yêu cầu nhiều thao tác vẽ để di chuyển chúng xung quanh. Một mẹo là chia tỷ lệ hình ảnh trên thiết bị càng ít càng tốt, điều đó làm cho công việc của CoreGraphics dễ dàng hơn nhiều. Nếu hình ảnh lớn gấp hai lần lượt xem, hãy thay đổi kích cỡ UIImage trước khi hiển thị nó trong khung nhìn. Thiết bị iOS xử lý PNG tốt nhất. Chúng được nén bởi một công cụ (pngcrush) tại thời gian biên dịch và iOS có phần cứng đặc biệt để hiển thị chúng.

  • Vẽ tùy chỉnh - Nếu có thể, hãy cắt giảm số lượng bản vẽ CGContext tùy chỉnh mà bạn thực hiện. Rất nhiều bản vẽ tùy chỉnh có tác động tiêu cực đến tốc độ hoạt ảnh. Tôi sẽ xem xét sử dụng một hình ảnh trên bản vẽ tùy chỉnh phức tạp, nếu có thể.

  • Cull - Chỉ vẽ những thứ bạn cần. UITableView tự động tải và tải các ô khi chúng xuất hiện, vì vậy việc này được thực hiện cho bạn, nhưng mọi bản vẽ CGContext tùy chỉnh chỉ nên được thực hiện khi phần đó hiển thị. Bóng xem tự động cũng có thể rất chậm trong trải nghiệm của tôi.

  • Tái sử dụng - Sử dụng nhận dạng tái sử dụng trên UITableView, điều này sẽ cho phép UITableView để tái sử dụng đối tượng di động chứ không phải là phân bổ lại như nó cuộn - nhìn vào câu trả lời cho question này. Đồng thời sử dụng lại UIImages thay vì phân bổ nhiều cho cùng một tệp. imageNamed lưu trữ hình ảnh tự động nhưng imageFromContents của tệp thì không.

  • Tạo tài khoản của riêng bạn - Bạn có thể tạo lớp chế độ xem lưới của riêng mình, chọn chế độ xem tiểu sử ẩn màn hình và cuộn với tải nội dung lười.Bằng cách viết một giải pháp tùy chỉnh, bạn hoàn toàn có thể kiểm soát quá trình và tạo ra một thiết kế tối ưu hóa cho bối cảnh sử dụng. Đối với hầu hết các trường hợp sử dụng, bạn sẽ có một thời gian khó khăn để xây dựng một cái gì đó tốt hơn so với tiêu chuẩn của Apple, nhưng tôi đã thấy nó được thực hiện trong trường hợp cụ thể.

  • Phương sách cuối cùng - Giảm kích thước của chế độ xem vi phạm (cải thiện lọc), chia nhỏ nội dung thành nhiều trang, giảm kích thước hình ảnh, cắt các thiết bị cũ không hoạt động tốt. Tôi sẽ giải quyết cho 30 FPS trước khi hy sinh hầu hết những thứ đó. Thiết bị sẽ tiếp tục nhận được nhanh hơn, các thiết bị cũ hơn sẽ bị loại bỏ và ứng dụng của bạn sẽ dần dần trở nên nhanh hơn.

+2

Tôi muốn thêm một bullet: cố gắng không thực hiện chặn (tải xuống đồng bộ chẳng hạn)/các hoạt động nặng trên chuỗi chính để tránh chặn vòng chạy chính, xử lý các sự kiện và giao diện người dùng. – Jilouc

7

Tôi nhận được gần 60 khung hình/giây với UITableViewController nơi bảng chứa khoảng 2000 ô và mỗi ô sẽ lấy hình ảnh từ web. Bí quyết là lười tải các hình ảnh khi bạn cần chúng. Điều này sample code from Apple là khá hữu ích.

Ý tưởng chung là giữ cho giao diện người dùng phản hồi bằng cách không chặn luồng chính. Thực hiện tải xuống và các tác vụ tốn thời gian khác trên một chuỗi khác.

+0

vâng, tôi đã thực hiện điều đó. Tôi thậm chí vô hiệu hóa tất cả tải xuống/hiển thị và vẫn không nhận được 60 khung hình/giây – xonegirlz

+0

Một cách để hiểu vấn đề tốc độ khung hình của bạn là xóa mục cho đến khi tốc độ khung hình có thể chấp nhận được. Sau đó, thêm các mục một lần lượt và xem nguyên nhân khiến tốc độ khung hình giảm xuống. Sau đó, làm một cái gì đó sáng tạo với mục đó. Thật khó để nói chính xác những gì cần làm w/o biết thêm về chính xác những gì các mục chứa. – SundayMonday

+0

Tôi đã thêm một số chi tiết về dự án của tôi trên – xonegirlz

3

Điều tôi đã làm là sử dụng NSCache. Tôi đã tạo một lớp nhỏ với các thuộc tính phù hợp với giao thức dữ liệu NSCache (nó thực sự dễ thực hiện). Vì vậy, những gì tôi làm là tạo ra một mối quan hệ giữa mỗi tế bào trong bảng chính và những thứ khác nhau đáng nhớ: chuỗi NSAttributed, hình ảnh, vv - thực sự bất cứ điều gì mà có công việc để tạo ra. Tôi không tải trước nhưng bạn có thể.

Khi bạn được yêu cầu cung cấp ô theo chế độ xem bảng, hãy tìm trong bộ nhớ cache cho đối tượng chính của bạn. Nếu có, kéo tất cả các đối tượng bạn cần. Nếu bộ nhớ cache không có đối tượng, sau đó lấy dữ liệu theo cách thời trang cũ, nhưng trước khi bạn hoàn thành, lưu nó vào bộ nhớ cache quá.

Điều này thực sự đã giúp tôi giảm "nói lắp" khi cuộn ô.Ngoài ra, KHÔNG animate bất cứ điều gì trong tế bào - mà giết chết hiệu suất. Tất cả mọi thứ phải được hoàn trả đầy đủ.

Một điều khác cần nhớ - đảm bảo rằng chế độ xem bao giờ có thể được đặt thành mờ có thuộc tính được đặt thành CÓ. Đó chắc chắn sẽ giúp hệ thống làm cho tế bào

EDIT (bao gồm cả xem backgound nếu bạn sử dụng nó.):

Vì vậy, bạn cung cấp thông tin bao gồm UITableViews có thể vấn đề gốc. Vì vậy, hai đề xuất:

1) Bạn có thể quay lại và tìm hiểu cách tạo scrollView một UITableView đơn lẻ không? Với đầu trang và chân trang của bảng và phần đầu trang và chân trang, và thậm chí cả khả năng tạo ra một khung nhìn nổi bật, bạn không thể tìm ra cách để tìm kiếm lại những gì bạn có?

2) Vì vậy, bạn quyết định không đề xuất 1. Sau đó, thực hiện việc này. Hãy suy nghĩ về không gian được sử dụng bởi tableview như là một cái nhìn container. Bất cứ khi nào xem bảng được chỉnh sửa, hãy chụp nhanh ảnh của nó và giữ hình ảnh này xung quanh. Ngay khi người dùng bắt đầu cuộn, hãy hoán đổi tableViews ra cho hình ảnh. Khi scrollView ngừng trao đổi UITableView trở lại. Điều này tất nhiên sẽ mất một số điều chỉnh tốt. Trong thực tế, bạn có thể có thể che phủ một hình ảnh mờ đục trên bảng (mà sẽ ẩn nó và ngăn chặn nó được yêu cầu để vẽ chính nó) trong khi di chuyển.

+0

Tôi có một số khía cạnh của bộ nhớ đệm tại chỗ cho các ô, nhưng nó không giúp ích gì. Tôi đã tải lên một dự án mẫu trong bài đăng gốc của mình, hiển thị rõ ràng vấn đề tôi gặp phải. Tôi không quan tâm và có thời gian để nhìn vào nó, nó được đánh giá rất cao – xonegirlz

+0

Vâng, có cam kết Chủ nhật nhưng sẽ rất vui mừng để có một cái nhìn vào thứ hai –

+0

Chắc chắn .. Tôi sẽ đánh giá cao quá – xonegirlz

0

Bạn muốn 60 khung hình/giây, nhưng 30 khung hình/giây trông không quá khủng khiếp trong thực tế. Nhưng tôi sẽ cố gắng đạt 60fps cho một cái nhìn mượt mà hơn trong khi di chuyển.

Có rất nhiều khả năng cải thiện hiệu suất, mà còn được trình bày bởi các hướng dẫn khác nhau

0

mắt người nhìn thấy ở khoảng 60 FPS, vì vậy đó là lý do tại sao nó được đề nghị, nhưng 30 FPS cũng sẽ xuất hiện rất trơn tru, đặc biệt là khi thường xuyên người dùng đang xem nó, trái ngược với bạn đang cố gắng tìm càng nhiều càng tốt để sửa chữa càng tốt. Điều này rõ ràng là phụ thuộc vào tốc độ di chuyển nhanh như thế nào, nếu sự khác biệt giữa khung hình với khung là một chuyển động của một vài điểm ảnh, 30 FPS sẽ hoạt động tốt, nhưng chuyển động nhanh hơn sẽ yêu cầu FPS cao hơn xuất hiện trơn tru

0

Trong khi 60 FPS là lý tưởng, trò chơi như Halo chạy rất đẹp trong 30 FPS. Sự hỗn loạn chiến trường trong Halo có thể liên quan đến sự chuyển động nhanh, đáng ngạc nhiên hơn so với hầu hết các danh sách, thậm chí cả những danh sách phức tạp như của bạn!

1

Có một vài điều bạn có thể làm nói chung để có được hiệu suất tốt hơn xem bảng:

1) Chuyển sang phương pháp vẽ UITableViewCell của (vì thiếu một liên kết tốt hơn Loren Brichter của: http://www.therefinedgeek.com.au/index.php/2010/12/21/fast-scrolling-uitableview-updates-for-ios-4-2/)

Về cơ bản , tất cả các mã của mình làm là hiển thị tất cả nội dung ô của bạn dưới dạng UIView mờ đục, UITableView (và CoreGraphics) có thể nhanh chóng tấn công lên UITableViewCell

Nếu bạn không muốn làm tất cả thiết kế ô trong drawRect :, bạn vẫn có thể sử dụng ngòi, nhưng:

  • Hãy chắc chắn rằng mỗi subview được đánh dấu đục
  • Đừng có bất kỳ/subviews bán trong suốt trong suốt
  • Không có bất kỳ hình ảnh với một kênh alpha! = 1.0f.

2) Đừng để UIImageView làm bất cứ rộng để hiển thị hình ảnh của bạn, cung cấp cho nó một UIImage đúng cỡ

3) Nếu bạn đang sử dụng iOS 5 trở lên, bạn có thể đăng ký một ngòi cho một số nhận dạng ô cụ thể. Bằng cách đó, khi bạn gọi [tableView dequeueReusableCellWithIdentifier:], bạn sẽ được bảo đảm nhận một ô.phân bổ di động nhanh hơn (theo Apple), và bạn có thể viết mã ít:

- (void)viewDidLoad { 
    UINib *nib = [UINib nibWithNibName:@"MyCell" bundle:nil]; 
    [self.tableView registerNib:nib forCellReuseIdentifier:@"MyCellIdentifier"]; 
} 

// ... 

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { 
    static NSString *cellIdentifier = @"MyCellIdentifier"; 
    MyCell *cell = (MyCell *)[tableView dequeueReusableCellWithIdentifier:cellIdentifier]; 

    // Commented out code is no longer needed 
    //if (cell == nil) { 
    // cell = [[MyCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellIdentifier]; 
    //} 

    // setup cell 

    return cell; 
} 

4) Hiển thị hình ảnh tải về từ web

  • hiển thị một hình ảnh mặc định (cái gì để nhìn vào trong khi hình ảnh thực tế được tải xuống)
  • Bắt đầu tải trên một sợi riêng biệt (gợi ý: sử dụng dispatch_async GCD của())
  • Khi hình ảnh đi kèm trong, bộ nhớ cache nó (gợi ý: NSCache), và hiển thị nó trên tế bào
    • Làm tất cả tải xuống hình ảnh/lưu vào bộ nhớ đệm khỏi chủ đề chính; điều duy nhất bạn nên làm vào các chủ đề chính là thiết lập các hình ảnh (nhớ mã UI HAS để được vào các chủ đề chính!)

Bạn có lẽ sẽ muốn viết một UIImageView async có khả năng (hoặc sử dụng thư viện hiện có).

Tránh xa EGOImageView, mặc dù nó có tải xuống không đồng bộ, nó tra cứu bộ nhớ cache (điều này xảy ra trên đĩa, do đó có nghĩa là tốn kém đĩa IO) trên luồng chính trước khi gửi đến chuỗi nền để tải xuống. Tôi đã từng sử dụng nó, nhưng cuối cùng tôi đã viết một tập các lớp riêng để xử lý nó, và nó nhanh hơn đáng kể.

-

Chỉ cần làm theo những, và các công cụ ppl khác đã viết ở đây, và bạn sẽ có tầm nhìn bảng mà di chuyển như kính trong thời gian không :)