2012-02-09 19 views
7

Tôi biết cách khắc phục sự cố mà tôi sắp phác thảo, tuy nhiên, tôi hơi bối rối về lý do mã kịch bản hoạt động trong trình mô phỏng iOS nhưng không phải trên iPad của tôi.Chỉ định thuộc tính CGColor hiện có cho thuộc tính CGColor hoạt động trong Trình mô phỏng iOS, không phải thiết bị iOS. Tại sao?

Tôi có phương pháp kiểm tra các thuộc tính khác nhau và sau đó đặt màu nền của CALayer tùy thuộc vào trạng thái của thuộc tính. Đoạn mã sau tương tự như phương pháp gán màu của tôi:

//This will be the CALayer BGColor... 
CGColor c = UIColor.blueColor.CGColor; //Blue is the default 
switch (myState) 
{ 
    case state_one: 
     c = UIColor.greenColor.CGColor; 
     //... more code ... 
     break; 
    case state_two: 
     c = UIColor.redColor.CGColor; 
     //... more code ... 
     break; 
    case state_three: //multiple cases are like the state_three case. 
     //Other code, but I don't need to assign the color. Blue works... 
} 

myCALayer.backgroundColor = c; //Oh-noes!!! Here we get the dreaded EXC_BAD_ACCESS on iPad 
//...more code dealing with the layer. 

Đoạn mã trên hoạt động không có sự cố trong Trình mô phỏng. Tuy nhiên, khi tôi chạy ứng dụng trên iPad của tôi, nó bị treo tại nhiệm vụ backgroundColor.

Tôi có thể sửa lỗi này bằng cách loại bỏ biến số CGColor và gán màu nền từ trực tiếp trong chuyển đổi/trường hợp của tôi và đó là những gì tôi định làm.

Tuy nhiên, tôi tò mò. Tại sao điều này sẽ làm việc trong một môi trường chứ không phải môi trường khác?

CẬP NHẬT

Couple thứ. Trước tiên, điều đáng nói là đây là một dự án ARC, sử dụng Xcode 4.2, nhắm mục tiêu thiết bị iOS 5. Ngoài ra, mã phân chia màu của tôi không hoàn toàn giống như tôi có một loạt các định nghĩa mà tôi sử dụng để thiết lập các màu này vì chúng được tham chiếu trong toàn bộ ứng dụng của tôi.

Đây là những gì một vài trong số các #define báo cáo trông giống như:

#define BLUE [UIColor colorWithRed:8.0/255.0 green:80.0/255.0 blue:150.0/255.0 alpha:1.0].CGColor 
#define GREEN (UIColor.blueColor.CGColor) 
//...and there are about 6 other colors 

tôi đã cố gắng để đơn giản hóa mã của tôi bởi vì trình biên dịch nên thay thế các refs để refs của tôi để định nghĩa của tôi. Tuy nhiên, nó chỉ đáng nhắc đến trong trường hợp.

+0

Bạn có chắc chắn để bao gồm các khuôn khổ QuartzCore trong từng xây dựng? –

+1

Mỏ của tôi thậm chí sẽ không được xây dựng với 'CGColor' của bạn có thể là' CGColorRef' –

+0

Tôi đã thêm khung công tác và tham chiếu các tiêu đề từ bên trong tệp mã đang thực hiện nhiệm vụ này. – RLH

Trả lời

8

Đây là linh cảm của tôi: Có thể UIColor đã tạo nó (và giữ tham chiếu duy nhất) đã bị hủy trước khi bạn vượt qua CGColor. Vì số đếm tham chiếu của CGColorRef không được xử lý cho bạn theo ARC, màu sẽ là tham chiếu treo nếu UIColor giữ nó đã bị hủy trước khi bạn sử dụng CGColor.

ARC có tối ưu hóa nơi các đối tượng "tự động" không bao giờ có thể được thêm vào các nhóm tự động phát hành và thay vào đó, released sau khi đối tượng objc không còn được tham chiếu. Đây là sự kết hợp của ba yếu tố:

  1. Phiên bản trình biên dịch và các tùy chọn bạn sử dụng. Không có gì ngạc nhiên, trình biên dịch thêm số đếm tham chiếu và có các biến thể cho việc này.
  2. Thời gian chạy ObjC. Thời gian chạy có thể sử dụng dữ liệu cục bộ luồng. Đương nhiên, điều này có thể bao gồm ngăn xếp của bạn.Nếu bạn đọc các chi tiết về cách một đối tượng có thể bỏ qua một nhóm autorelease, điều này sẽ rõ ràng hơn.
  3. Các thư viện bạn sử dụng (bao gồm thư viện hệ thống và khung công tác). Khi trình biên dịch và thời gian chạy được cập nhật, các thư viện có thể sử dụng ARC hoặc họ có thể sử dụng các cuộc gọi thời gian chạy khác nhau để thực thi chương trình.

Biết rằng, tôi nghi ngờ chương trình này sẽ khắc phục vấn đề:

UIColor * c = UIColor.blueColor; //Blue is the default 
switch (myState) { 
    case state_one: 
     c = UIColor.greenColor; 
     //... more code ... 
     break; 
    case state_two: 
     c = UIColor.redColor; 
     //... more code ... 
     break; 
    case state_three: //multiple cases are like the state_three case. 
     //Other code, but I don't need to assign the color. Blue works... 
} 

myCGLayer.backgroundColor = c.CGColor; 
//...more code dealing with the layer. 

Cụ thể hơn, có nhiều cách trình biên dịch và runtime objc có thể hiểu và thực hiện chương trình của bạn. Điều này có nghĩa rằng vấn đề này có thể ảnh hưởng đến bạn khi bạn thay đổi phiên bản trình biên dịch hoặc khi thời gian chạy (OS) được cập nhật. Nó cũng có thể xảy ra khi các thư viện bạn sử dụng được cập nhật hoặc được xây dựng với các phiên bản hoặc cài đặt trình biên dịch khác nhau. Ví dụ: Nếu thư viện chuyển sang ARC trên đường đi, nó có thể sử dụng một cuộc gọi thời gian chạy khác hoặc cuộc gọi có thể sử dụng dữ liệu cục bộ luồng khác nhau nếu trình biên dịch được thực hiện cuộc gọi được cập nhật.

tin chi tiết về spec ARC vì nó liên quan đến thời gian chạy có thể được tìm thấy ở đây: http://clang.llvm.org/docs/AutomaticReferenceCounting.html#runtime


Một vấn đề tương tự đã được nhìn thấy ở đây:

EXC_BAD_ACCES drawing shadow

+0

Bỏ qua thư tôi vừa xóa. Ma thuật! Điều này đã khắc phục được sự cố. Có sự khác biệt đáng kể trong cách QuartzCore quản lý bộ nhớ trên OSX từ iOS? Đây không phải là lần đầu tiên tôi nhìn thấy những điều kỳ quặc về quản lý bộ nhớ giữa hai người, nhưng điều này chắc chắn là kỳ quặc nhất. – RLH

+0

@RLH Nó không phải là Quartz - nó liên quan đến ARC và trình biên dịch (đó là linh cảm của tôi - tôi không sử dụng ARC trong các dự án thực sự, và chưa đọc triển khai mới nhất của runtime objc để xác nhận điều này @ 100%) . Thời gian chạy sử dụng lưu trữ cục bộ luồng trong một số trường hợp; các đối tượng mà * sẽ * được tự động phát hành trong MRC có thể không bao giờ được thêm vào một nhóm autorelease. Thay vào đó, trình biên dịch sẽ thêm những gì sẽ dẫn đến một thông điệp phát hành theo một số runtimes (tự nhiên, điều này sẽ xảy ra sau khi bạn đã hoàn thành việc sử dụng nó).Tôi đã thêm một liên kết đến câu trả lời của tôi để biết thêm chi tiết về việc triển khai nó. – justin

+0

Cảm ơn bạn đã liên kết và tôi đã đánh dấu câu trả lời này vì tôi nghi ngờ có một câu trả lời trực tiếp (rõ ràng), trừ khi ai đó ở đây làm việc với mã độc quyền của Apple cho các khung công tác hoặc trình biên dịch này. Bài viết của bạn trông khá sâu-- Tôi sẽ kiểm tra nó ra vào cuối tuần này. – RLH

0

Bạn không nói ví dụ của bạn là gì myCGLayer chúng tôi bắt nguồn từ, nhưng tôi sẽ chụp và nói rằng nó không có nguồn gốc từ CGLayer, vì CGLayer không có thuộc tính backgroundColor. Vì vậy, tôi đoán (một lần nữa), các tham số thông qua nên được loại UIColor và không CGColor. CGColor có nguồn gốc từ lớp CFType. UIColor có nguồn gốc từ NSObject. Họ không nên hoán đổi cho nhau. Nếu đoán của tôi là đúng, tôi ngạc nhiên khi nó hoạt động trong trình mô phỏng.

Đừng tát tôi quá khó nếu dự đoán của tôi sai.

+0

Chúng có thể có nghĩa là CALayer. Họ thực sự đã nói CALayer trong phần mô tả. – Chuck

+0

Cảm ơn vì nỗ lực, nhưng đó là lỗi của tôi. Tôi đã nhập vào tất cả các mã mẫu đó, vì vậy, không cắt và dán. Chuck đúng - đây là một 'CALayer'. Tôi đã cập nhật biến của tôi trong mẫu để phản ánh điều này. – RLH

+0

Điều đó sẽ tạo sự khác biệt (nếu mã thực không có loại lỗi đánh máy đó). – Jim

4

Do ARC màu được phát hành quá sớm vào cuối phương thức.

tôi sử dụng: CGColorRetain

CGColorRef whiteColor = CGColorRetain([UIColor colorWithRed:1.0 green:1.0 
             blue:1.0 alpha:1.0].CGColor);