NSAssert thực sự là gì?


155

Tôi phải hỏi điều này, bởi vì: Điều duy nhất tôi nhận ra là, nếu xác nhận thất bại, ứng dụng gặp sự cố. Đó có phải là lý do tại sao sử dụng NSAssert? Hoặc những gì khác là lợi ích của nó? Và có đúng không khi đặt NSAssert ngay trên bất kỳ giả định nào tôi đưa ra trong mã, giống như một hàm không bao giờ nên nhận -1 dưới dạng param nhưng có thể là -0.9 hoặc -1.1?

Câu trả lời:


300

Khẳng định là đảm bảo một giá trị là giá trị của nó. Nếu một xác nhận thất bại có nghĩa là đã xảy ra sự cố và vì vậy ứng dụng sẽ thoát. Một lý do để sử dụng khẳng định là nếu bạn có một số chức năng sẽ không hoạt động hoặc sẽ tạo ra các hiệu ứng phụ rất xấu nếu một trong các tham số được truyền cho nó không chính xác là một giá trị (hoặc một phạm vi giá trị) bạn có thể đặt một xác nhận để thực hiện chắc chắn rằng giá trị đó là những gì bạn mong đợi, và nếu không thì điều gì đó thực sự sai, và vì vậy ứng dụng thoát ra. Khẳng định có thể rất hữu ích cho việc gỡ lỗi / kiểm tra đơn vị và cả khi bạn cung cấp các khung để ngăn người dùng thực hiện những việc "xấu xa".


9
Bạn nên lấy ra NSAssert để phát hành. Có một cờ thời gian biên dịch để làm điều đó.
Barry Wark

127
> Bạn nên lấy NSAssert ra để phát hành. Đây là tranh cãi. Tôi luôn phát hành các ứng dụng của mình với các xác nhận được kích hoạt và đây là thông lệ tiêu chuẩn cho rất nhiều phần mềm, ví dụ như Apple làm điều này. Ngay khi chương trình của bạn phát hiện trạng thái bất thường, bạn sẽ gặp sự cố. Bạn có thể nhận được một dấu vết ngăn xếp về nơi xảy ra lỗi, trong khi nếu bạn tắt xác nhận, bạn có thể làm hỏng bộ nhớ và / hoặc dữ liệu người dùng và vấn đề sẽ rất khó gỡ lỗi.
Mike Weller

18
Lưu ý rằng XCode 4 có NS_BLOCK_ASSERTION được xác định theo mặc định trong các cấu hình phát hành. Tôi đoán nếu bạn không thay đổi rằng mã được phát hành của bạn sẽ không chứa NSAssert: s.
Jonny

16
Nếu tôi hiểu chính xác, điểm để lại chúng (trên phiên bản phát hành) là gì? Tại sao không thay thế NSAssert bằng câu lệnh if và nếu (điều gì đó khủng khiếp xảy ra), sau đó thông báo cho người dùng (hoặc làm điều gì đó nằm dưới sự kiểm soát của bạn ), và không chỉ thoát / sụp đổ và khiến người dùng tự hỏi điều gì đã xảy ra ... Hoặc tui bỏ lỡ điều gì vậy?
Gik

11
Thật lãng phí thời gian của nhà phát triển để đi vào con đường của mọi trường hợp ngoại lệ không được phép xảy ra trong mọi trường hợp thông thường. Điều này liên quan đến việc nghĩ ra những cách thích hợp để thông báo cho người dùng cho từng người trong số họ và / hoặc làm cho ứng dụng đủ mạnh để tiếp tục theo cách dự kiến ​​sau khi xảy ra. Cách tiếp cận thực tế hơn là đánh sập ứng dụng và sửa lỗi tìm thấy từ báo cáo sự cố và phát hành phiên bản mới. Đã nói rằng, điều quan trọng là đảm bảo rằng không có mất dữ liệu trong bất kỳ tình huống như vậy. Điều này phải được đảm bảo tuy nhiên nó là công việc ít hơn nhiều.
trss

20

Tôi thực sự không thể nói chuyện với NSAssert, nhưng tôi tưởng tượng rằng nó hoạt động tương tự như khẳng định của C ().

assert () được sử dụng để thực thi hợp đồng ngữ nghĩa trong mã của bạn. Điều đó có nghĩa là gì, bạn yêu cầu?

Vâng, giống như bạn đã nói: nếu bạn có một hàm không bao giờ nhận được -1, bạn có thể xác nhận () thực thi rằng:

void gimme_poseitive_ints (int i) {
  khẳng định (i> 0);
}

Và bây giờ bạn sẽ thấy một cái gì đó như thế này trong nhật ký lỗi (hoặc STDERR):

Xác nhận i> 0 không thành công: tệp example.c, dòng 2

Vì vậy, nó không chỉ bảo vệ an toàn trước các đầu vào xấu mà còn ghi lại chúng theo cách tiêu chuẩn, hữu ích.

Ồ, và ít nhất trong C assert () là một macro, vì vậy bạn có thể xác định lại assert () là không có trong mã phát hành của bạn. Tôi không biết đó có phải là trường hợp của NSAssert (hoặc thậm chí khẳng định () nữa không), nhưng nó khá hữu ích để biên dịch các kiểm tra đó.


2
Vâng, NSAssert cũng là một macro.
Martin Wickman

18

NSAssertcung cấp cho bạn nhiều hơn là chỉ làm hỏng ứng dụng. Nó cho bạn biết lớp, phương thức và dòng nơi xác nhận xảy ra. Tất cả các xác nhận cũng có thể dễ dàng hủy kích hoạt bằng NS_BLOCK_ASSERTIONS. Do đó làm cho nó phù hợp hơn để gỡ lỗi. Mặt khác, ném một NSExceptionứng dụng duy nhất làm hỏng ứng dụng. Nó cũng không nói về vị trí của ngoại lệ, cũng không thể bị vô hiệu hóa một cách đơn giản. Xem sự khác biệt trong các hình ảnh dưới đây.

Ứng dụng gặp sự cố vì một xác nhận cũng đưa ra một ngoại lệ, như tài liệu NSAssert nêu:

Khi được gọi, một trình xử lý xác nhận sẽ in một thông báo lỗi bao gồm tên phương thức và tên lớp (hoặc tên hàm). Sau đó, nó sẽ đưa ra một ngoại lệ NSIternalInconsistencyException.

NSAssert:

Nhật ký sau khi xác nhận

NSException:

Nhật ký sau một ngoại lệ


An NSExceptioncung cấp nhiều cơ hội để tùy chỉnh đầu ra mà nó trả về thông qua reasonuserInfocác tham số. Không có lý do gì bạn không thể thêm tên lớp, bộ chọn, thông tin dòng và bất cứ thứ gì bạn quan tâm để thêm vào để hỗ trợ gỡ lỗi. IMHO, bạn sử dụng một NSAssertmục đích để gỡ lỗi trong quá trình phát triển nhưng vô hiệu hóa chúng để vận chuyển; bạn ném một NSExceptionnếu bạn muốn để lại một xác nhận trong mã vận chuyển.
markeissler

17

Ngoài những gì mọi người đã nói ở trên, hành vi mặc định của NSAssert()(không giống như C assert()) là đưa ra một ngoại lệ, mà bạn có thể nắm bắt và xử lý. Ví dụ, Xcode thực hiện điều này.


Có nhiều hơn về cách chúng ta có thể bắt và xử lý ngoại lệ?
Gon

1
Các ngoại lệ trong ca cao KHÔNG phải là "bắt được và có thể bắt được" trên thực tế. Nếu điều khiển đi qua một hàm apple ở mọi nơi trong cây cuộc gọi, hành vi không được xác định. Các ngoại lệ hoàn toàn dành cho báo cáo lỗi (hay còn gọi là crittercism, v.v.), không sử dụng chung như trong Java.
Michael

9

Chỉ cần làm rõ, như ai đó đã đề cập nhưng không giải thích đầy đủ, lý do có và sử dụng các xác nhận thay vì chỉ tạo mã tùy chỉnh (ví dụ: thực hiện một ngoại lệ cho dữ liệu xấu) là khẳng định NÊN bị vô hiệu hóa cho các ứng dụng sản xuất.

Trong khi phát triển và gỡ lỗi, các xác nhận được kích hoạt để bạn bắt lỗi. Chương trình sẽ tạm dừng khi một xác nhận được đánh giá là sai. Nhưng, khi biên dịch để sản xuất, trình biên dịch sẽ bỏ qua mã xác nhận và thực sự KIẾM CHƯƠNG TRÌNH CHẠY CỦA BẠN. Đến lúc đó, hy vọng, bạn đã sửa tất cả các lỗi. Trong trường hợp chương trình của bạn vẫn có lỗi trong khi sản xuất (khi các xác nhận bị vô hiệu hóa và chương trình "bỏ qua" các xác nhận), chương trình của bạn có thể sẽ bị sập ở một số điểm khác.

Từ trợ giúp của NSAssert: "Các xác nhận bị vô hiệu hóa nếu macro tiền xử lý NS_BLOCK_ASSERTIONS được xác định." Vì vậy, chỉ cần đặt macro trong mục tiêu phân phối của bạn [chỉ].


6

NSAssert(và tương đương stdlib của nó assert) là để phát hiện lỗi lập trình trong quá trình phát triển. Bạn không bao giờ nên có một xác nhận thất bại trong một ứng dụng sản xuất (phát hành). Vì vậy, bạn có thể khẳng định rằng bạn không bao giờ chuyển số âm cho phương thức yêu cầu đối số dương. Nếu xác nhận từng thất bại trong quá trình kiểm tra, bạn có một lỗi. Tuy nhiên, nếu giá trị được chuyển qua được nhập bởi người dùng, bạn cần xác thực hợp lệ đầu vào thay vì dựa vào xác nhận trong sản xuất (bạn có thể đặt #define cho các bản dựng phát hành vô hiệu hóa NSAssert*.


2
+1 vì câu trả lời của bạn có ý nghĩa nhất đối với tôi! Sử dụng NSAssert có ý nghĩa hơn nếu sử dụng cho phát triển, không phải sau khi phát hành. Người dùng nhập một giá trị không được phép sẽ bị theo sau bởi lỗi UI, không phải NSAssert làm hỏng ứng dụng. Sương mù đã tan!
pnizzle

3

Các xác nhận thường được sử dụng để thực thi mục đích sử dụng của một phương pháp hoặc phần logic cụ thể. Giả sử bạn đang viết một phương pháp tính tổng của hai số nguyên lớn hơn 0. Để đảm bảo phương pháp luôn được sử dụng như dự định, có lẽ bạn sẽ đặt một xác nhận kiểm tra điều kiện đó.

Câu trả lời ngắn: Họ thi hành rằng mã của bạn chỉ được sử dụng như dự định.


3

Thật đáng để chỉ ra rằng ngoài việc kiểm tra thời gian chạy, khẳng định lập trình là một phương tiện quan trọng được sử dụng khi bạn thiết kế mã theo hợp đồng.

Thông tin thêm về chủ đề khẳng định và thiết kế theo hợp đồng có thể được tìm thấy dưới đây:

Khẳng định (phát triển phần mềm)

Thiết kế theo hợp đồng

Lập trình với các xác nhận

Thiết kế theo hợp đồng, bằng ví dụ [Bìa mềm]


2

Để trả lời đầy đủ câu hỏi của anh ấy, quan điểm của bất kỳ loại khẳng định nào là hỗ trợ gỡ lỗi. Sẽ có giá trị hơn khi bắt lỗi tại nguồn của họ, sau đó bắt chúng trong trình gỡ lỗi khi chúng gây ra sự cố.

Ví dụ: bạn có thể chuyển một giá trị cho hàm mong đợi các giá trị trong một phạm vi nhất định. Hàm có thể lưu trữ giá trị để sử dụng sau và sau này sử dụng ứng dụng gặp sự cố. Ngăn xếp cuộc gọi được thấy trong kịch bản này sẽ không hiển thị nguồn của giá trị xấu. Tốt hơn hết là nắm bắt giá trị xấu khi tìm ra ai là người vượt qua giá trị xấu và tại sao.


-3

NSAssertlàm cho ứng dụng sụp đổ khi nó phù hợp với điều kiện. Nếu không phù hợp với điều kiện các câu lệnh tiếp theo sẽ thực thi. Hãy tìm EX dưới đây:

Tôi chỉ tạo một ứng dụng để kiểm tra nhiệm vụ của NSAssertnó là gì:

    - (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.
    [self testingFunction:2];
}

-(void)testingFunction: (int)anNum{
    // if anNum < 2 -> the app will crash
    // and the NSLog statement will not execute
    // that mean you cannot see the string: "This statement will execute when anNum < 2"
    // into the log console window of Xcode
    NSAssert(anNum >= 2, @"number you enter less than 2");
    // If anNum >= 2 -> the app will not crash and the below 
    // statement will execute
    NSLog(@"This statement will execute when anNum < 2");
}

vào mã của tôi, ứng dụng sẽ không gặp sự cố. Và trường hợp thử nghiệm là:

  • anNum > = 2 -> Ứng dụng sẽ không gặp sự cố và bạn có thể thấy chuỗi nhật ký: "Câu lệnh này sẽ thực thi khi anNum <2" vào cửa sổ bảng điều khiển nhật ký outPut
  • anNum <2 -> Ứng dụng sẽ sập và bạn không thể thấy chuỗi nhật ký: "Câu lệnh này sẽ thực thi khi anNum <2"

1
Bạn đã có nó theo cách khác. "NSAssert làm cho ứng dụng bị sập khi phù hợp với điều kiện. Nếu không khớp với điều kiện, các câu lệnh tiếp theo sẽ thực thi". NSAssert sập ứng dụng nếu ứng dụng KHÔNG khớp với điều kiện và thực thi bình thường nếu ứng dụng đó khớp với điều kiện.
Joe Tam

Ứng dụng gặp sự cố và thông báo nhật ký khi không đáp ứng điều kiện nếu không nó sẽ thực thi thêm.
Pravin S.
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.