NSLog tên phương thức với Objective-C trong iPhone


153

Hiện tại, chúng tôi đang xác định cho mình một cơ chế nhật ký mở rộng để in ra tên lớp và số dòng nguồn của nhật ký.

#define NCLog(s, ...) NSLog(@"<%@:%d> %@", [[NSString stringWithUTF8String:__FILE__] lastPathComponent], \
    __LINE__, [NSString stringWithFormat:(s), ##__VA_ARGS__])

Ví dụ: khi tôi gọi NCLog (@ "Xin chào thế giới"); Đầu ra sẽ là:

<ApplicationDelegate:10>Hello world

Bây giờ tôi cũng muốn đăng xuất tên phương thức như:

<ApplicationDelegate:applicationDidFinishLaunching:10>Hello world

Vì vậy, điều này sẽ làm cho việc gỡ lỗi của chúng ta trở nên dễ dàng hơn khi chúng ta có thể biết phương thức nào đang được gọi. Tôi biết rằng chúng tôi cũng có trình gỡ lỗi Xcode nhưng đôi khi, tôi cũng muốn thực hiện gỡ lỗi bằng cách đăng xuất.


Trong iPhonedự án cuối cùng của tôi , tôi thực sự đã làm điều này bằng tay. Rất thích xem câu trả lời cho điều này.
Jacob Relkin

Câu trả lời:


261
print(__FUNCTION__) // Swift
NSLog(@"%@", NSStringFromSelector(_cmd)); // Objective-C

Swift 3 trở lên

print(#function)

120
Bạn thực sự nên sử dụng NSLog(@"%@", NSStringFromSelector(_cmd)), nếu bạn sẽ sử dụng _cmd, vì AFAIK Apple tuyên bố _cmdlà loại SELchứ không phải chuỗi C. Chỉ vì nó được triển khai dưới dạng chuỗi C (như các phiên bản hiện tại của Mac OS X và iPhone OS) không có nghĩa là bạn nên sử dụng nó theo cách đó, vì Apple có thể thay đổi nó trong bản cập nhật hệ điều hành.
Nick Forge

5
Có, NSStringFromSelector là câu trả lời đúng hơn. Tôi không bao giờ sử dụng _cmd làm chuỗi c cho bất cứ điều gì ngoại trừ mã gỡ lỗi.
rút ra vào

Wow, trình biên dịch phàn nàn về tính không tương thích của con trỏ, nhưng nó hoạt động ... Vậy _cmd (loại: SEL) thực sự là một char *!?
Nicolas Miari

3
Phương pháp gọi như [self doSomething:arg1 somethingElse:arg2]get chuyển thành cuộc gọi chức năng C objc_msgSend(self, "doSomething:somethingElse:, arg1, arg2);. Tham số thứ hai của objc_msgSend()mất a char*. Hãy nhớ rằng vì thời gian chạy Objective-C là động, nên thực tế nó đang sử dụng bảng tra cứu để tìm ra phương thức nào để gọi lớp đó để char * thuận tiện vì các phương thức được biểu diễn dưới dạng chuỗi trong bảng tra cứu.
Jack Lawrence

1
Đối với Swift 2.2 nên sử dụngprint("\(#function)")
Jake Lin

161

Để trả lời kỹ thuật câu hỏi của bạn, bạn muốn:

NSLog(@"<%@:%@:%d>", NSStringFromClass([self class]), NSStringFromSelector(_cmd), __LINE__);

Hoặc bạn cũng có thể làm:

NSLog(@"%s", __PRETTY_FUNCTION__);

2
Với __FUNCTION__và tương đương khá của nó cũng có sẵn trong các chức năng C.
Georg Fritzsche

NB __FUNCTION__cũng bao gồm tên lớp
OrangeDog

1
có sự khác biệt nào khi sử dụng NSLog (@ "% s", _func_ ); HOẶC NSLog (@ "% s", _PRETTY_FUNCTION_ ) ???
Ravi

82

tl; dr

NSLog( @"ERROR %@ METHOD %s:%d ", @"DescriptionGoesHere", __func__, __LINE__ );

Chi tiết

Apple có trang Hỏi & Đáp về Kỹ thuật: QA1669 - Làm cách nào tôi có thể thêm thông tin ngữ cảnh - chẳng hạn như phương thức hiện tại hoặc số dòng - vào báo cáo đăng nhập của tôi?

Để hỗ trợ đăng nhập:

  • Bộ tiền xử lý C cung cấp một vài macro .
  • Objective-C cung cấp các biểu thức (phương thức).
    • Vượt qua tranh luận ngầm cho selector phương pháp hiện tại của:_cmd

Như các câu trả lời khác đã chỉ ra, để chỉ nhận được tên của phương thức hiện tại, hãy gọi:

NSStringFromSelector(_cmd)

Để có được tên phương thức hiện tại số dòng hiện tại, hãy sử dụng hai macro này __func____LINE__như được thấy ở đây:

NSLog(@"%s:%d someObject=%@", __func__, __LINE__, someObject);

Một ví dụ khác về Đoạn mã tôi giữ trong Thư viện Đoạn mã của Xcode:

NSLog( @"ERROR %@ METHOD %s:%d ", @"DescriptionGoesHere", __func__, __LINE__ );

Thay thế và TRACE thay vì ERROR

NSLog( @"TRACE %@ METHOD %s:%d ", @"DescriptionGoesHere", __func__, __LINE__ );

Cách và một cái dài hơn bằng cách sử dụng một mô tả được mã hóa mềm đi qua một giá trị ( [rows count])

NSLog( @"TRACE %@ METHOD %s:%d.", [NSString stringWithFormat:@"'Table of Contents.txt' file's count of Linefeed-delimited rows: %u.", [rows count]] , __func__, __LINE__ );

Macro tiền xử lý để đăng nhập

Lưu ý việc sử dụng một cặp ký tự gạch dưới xung quanh cả hai mặt của macro.

| Vĩ mô | Định dạng | Sự miêu tả
  __func__% s Chữ ký hàm hiện tại
  __LINE__% d Số dòng hiện tại
  __FILE__% s Đường dẫn đầy đủ đến tệp nguồn
  __PRETTY_FUNCTION__% s Thích __func__, nhưng bao gồm dài dòng
                                    nhập thông tin trong mã C ++. 

Biểu thức để đăng nhập

| Biểu hiện | Định dạng | Sự miêu tả
  NSStringFromSelector (_cmd)% @ Tên của bộ chọn hiện tại
  NSStringFromClass ([self class])% @ Tên lớp của đối tượng hiện tại
  [[NSString% @ Tên tệp mã nguồn
    chuỗiWithUTF8String: __ FILE__]   
    LastPathComponent] 
  [NSThread callStackSymbols]% @ NSArray của dấu vết ngăn xếp

Khung đăng nhập

Một số khung đăng nhập cũng có thể giúp nhận được phương thức hoặc số dòng hiện tại. Tôi không chắc chắn, vì tôi đã sử dụng một khung ghi nhật ký tuyệt vời trong Java ( SLF4J + LogBack ) nhưng không phải là Ca cao.

Xem câu hỏi này cho các liên kết đến các khung đăng nhập ca cao khác nhau.

Tên của người chọn

Nếu bạn có biến Selector (một SEL ), bạn có thể in tên phương thức của nó ("message") theo một trong hai cách như được mô tả bởi bài đăng trên blog Codec này :

  • Sử dụng lệnh gọi Objective-C đến NSStringFromSelector :
    NSLog(@"%@", NSStringFromSelector(selector) );
  • Sử dụng thẳng C:
    NSLog(@"%s", selector );

Thông tin này được rút ra từ trang tài liệu Apple được liên kết kể từ 2013-07-19. Trang đó đã được cập nhật lần cuối 2011-10-04.


1
Đối với C, sử dụng sel_getName(SEL)vì SEL là loại mờ đục và có thể không phải lúc nào cũng làchar *
Ethan Reesor

8
NSLog(@"%@", NSStringFromSelector(_cmd)); // Objective-C
print(__FUNCTION__) // Swift

4
Đối với bất kỳ ai gặp câu trả lời này trong tương lai: nó tương đương với câu trả lời được chấp nhận, nhưng câu trả lời được chấp nhận là khác nhau, khi câu trả lời này được đăng (câu trả lời được chấp nhận đã được chỉnh sửa vào năm 2014). Tôi chuẩn bị bỏ phiếu, nhưng sau một cuộc điều tra nhỏ đã bỏ phiếu thay vào đó :)
FreeNickname

0

Nó thực sự chỉ đơn giản như:

printf(_cmd);

Vì một số lý do, iOS cho phép _cmd được thông qua dưới dạng char theo nghĩa đen mà thậm chí không có cảnh báo biên dịch. Ai biết


0

Trong Swift 4:

kiểm tra func () {

print(#function)

}

test () // in giá trị "test ()"

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.