2011-07-16 33 views
5

Tôi đang cố gắng phân lớp một lớp nhất định và ghi đè lên một số phương thức riêng của nó. Điều này là nguy hiểm, có thể thất bại, không thể vượt qua đánh giá của Apple (Trong AppStore), có thể có hiệu ứng khủng khiếp, vv, nhưng điều này chỉ dành cho mục đích thử nghiệm/giáo dục :)Nhận kiểu đối số theo phương thức

Ví dụ, giả sử tôi muốn biết loại của đối số đầu tiên của phương pháp dụ keyboardInput:shouldInsertText:isMarkedText: của UITextView:

SEL selector = @selector(keyboardInput:shouldInsertText:isMarkedText:); 
Class class = [UITextView class]; 
Method method = class_getInstanceMethod(class, selector); 
char *arg = method_copyArgumentType(method, 0); 
printf("_%s_\n", arg); 
free(arg); 

Tuy nhiên trong giao diện điều khiển tôi chỉ nhận được [email protected]_. Tôi nghĩ rằng @ có nghĩa là đối tượng nhưng là đối tượng của lớp học nào? (Tôi nghĩ tôi sẽ lấy tên của lớp đối số) Có thể lấy lớp tham số đó bằng cách sử dụng objective-c runtime functions hoặc bất kỳ phương tiện nào khác không?

PS: Trong ví dụ tôi đã sử dụng một lớp học của Cocoa touch nhưng tôi có thể đã thử chính xác giống với một lớp Cocoa. Vì vậy, điều này không nên cụ thể cho iOS.

SOLVED:

Tôi đã thử trong trình mô phỏng những gì Dave gợi ý, nó hoạt động!

(gdb) info all-registers đã cho tôi một danh sách dài các giá trị, ...

((gdb) po *(id*)($ebp + 8) 
<MyTextView: 0x5911270; baseClass = UITextView; frame = (80 70; 240 323); text = 'Lorem ipsum dolor sit er ...'; clipsToBounds = YES; autoresize = RM+BM; layer = <CALayer: 0x5c0c7d0>; contentOffset: {0, 0}> 

(gdb) p *(SEL*)($ebp + 12) 
$5 = (SEL) 0xbd19 

(gdb) po *(id*)($ebp + 16) 
<UIWebDocumentView: 0xa02f000; frame = (0 0; 240 457); text = 'Lorem ipsum dolor sit er ...'; opaque = NO; userInteractionEnabled = NO; layer = <UIWebLayer: 0x5c35070>> 

(gdb) po *(id*)($ebp + 20) 
t 

(gdb) p *(id*)($ebp + 24) 
$6 = (id) 0x0 

nào có ý nghĩa kể từ khi chính tôi ép là một single "t" nên nó không được đánh dấu văn bản ("0x0") vì vậy tôi là OK để nghĩ rằng đối số đầu tiên phải thuộc loại UIWebDocumentView.

Chỉ một điều nhỏ (không thích hợp trong trường hợp này), làm thế nào tôi có thể lấy tên phương thức từ SEL trong gbd? ví dụ: $5?

+0

'SEL' * là * tên phương thức. Sử dụng hàm 'sel_getName' để lấy bộ chọn làm chuỗi C; xem thêm http://developer.apple.com/library/mac/documentation/Cocoa/Reference/ObjCRuntimeRef/. Ngoài ra còn có 'NSStringFromSelector', nó thực hiện chính xác những gì nó nói, và là một phần của (và được ghi trong) Foundation. –

Trả lời

6

Giả sử đây là vì lợi ích học tập chỉ ....

Một cách để bạn có thể tìm hiểu là để phá vỡ vào biểu tượng trong GDB và kiểm tra các thông số. Bạn biết những gì chung loại chúng là (ví dụ: floatobject, v.v.), vì vậy bạn có thể chỉ cần sử dụng lệnh p phù hợp để in chúng.

Để đặt breakpoint, bạn có thể làm:

  1. Trong gdb console, gõ b -[UITextView keyboardInput:shouldInsertText:isMarkedText:]
  2. Trong Xcode, thêm một breakpoint biểu tượng mới cho -[UITextView keyboardInput:shouldInsertText:isMarkedText:]

Khi bạn thực sự nhấn breakpoint, bạn sẽ không thấy bất cứ điều gì hữu ích (tất nhiên). Nhưng bạn có thể in các đối số tại thời điểm này, bởi vì bạn biết kích thước của chúng và do đó chúng sẽ nằm trong sổ đăng ký.

Để biết thêm thông tin về đăng ký của người đăng ký, hãy xem this handy blog post. Bạn cũng có thể làm điều gì đó như info all-registers để in ra tất cả các thông tin trong tất cả các thanh ghi, vv


cập nhật

Nếu bạn muốn in tên của bộ chọn, bạn có thể sử dụng một chút lừa, mà là selectors có nhiều hoặc ít hơn * char* s:

p (char*)$5 

Sẽ in:

${some number} = 0x{some address} "keyboardInput:shouldInsertText:isMarkedText:" 
+0

Cảm ơn, Nó đã hoạt động! Tôi có một nghi ngờ cuối cùng và ít, mặc dù :) (Vui lòng đọc câu trả lời cập nhật) – nacho4d

+0

@ nacho4d câu trả lời cập nhật –

+0

tuyệt vời! Câu trả lời tuyệt vời :) – nacho4d

0

@ thực sự có nghĩa là "đối tượng" nhưng bạn không thể tìm ra lớp học đó là gì. Điều này không được lưu trong phân đoạn __OBJC của tệp nhị phân và do đó không có sẵn cho bạn trừ khi bạn có tệp tiêu đề gốc.

Bạn phải đoán điều đó. :)

9

Bạn không thể cho biết lớp của đối số từ nội suy của giao diện. Tất cả id được tạo bằng nhau trong Objective-C, khi bạn đã được biên dịch. Tuy nhiên, bạn có thể yêu cầu một cá thể cụ thể là -class. Vì vậy, nếu bạn đang cố gắng đảo ngược kỹ sư một phương pháp nội bộ, bạn sẽ cần phải làm cho phương thức này trở nên phức tạp, làm cho nó được gọi, và sau đó nhìn vào các đối tượng bạn được truyền đi. "Phương thức" của Google đang lan truyền cho nhiều cuộc thảo luận về cách tiêm mã của bạn vào bất kỳ phương pháp Mục tiêu-C nào.

+0

+1 bởi vì nó đúng hơn câu trả lời của tôi. –

+0

Tôi đã nghĩ đến sự nổi loạn, nhưng trong trường hợp này nếu tôi không biết kiểu tranh luận đầu tiên sẽ không hoạt động, tôi tin. – nacho4d

+0

Bạn biết rằng đó là một 'id'. Đó là tất cả những gì bạn cần. Hãy nhớ rằng, tất cả 'id' được tạo ra bằng nhau sau khi biên dịch. Điều đó nói rằng, tôi thích giải pháp @Dave DeLong tốt hơn cho vấn đề này. –

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