2010-11-22 33 views
16

Tôi đang làm một số tài liệu điên trong một công cụ cửa sổ duy nhất với kiến ​​trúc dựa trên tài liệu và tôi hoàn thành 95%.Làm cách nào để kiểm tra chuỗi trả lời?

Tôi có kiến ​​trúc tài liệu hai tầng này, trong đó tài liệu gốc mở và định cấu hình cửa sổ, cung cấp danh sách tài liệu "con". Khi người dùng chọn một trong những đứa trẻ, tài liệu đó được mở bằng cùng một bộ điều khiển cửa sổ và nó đặt một NSTextView trong cửa sổ. Liên kết tài liệu của trình điều khiển cửa sổ được thay đổi để "dấu chấm đã chỉnh sửa" và tiêu đề cửa sổ theo dõi tài liệu hiện được chọn. Hãy nghĩ về một dự án Xcode và những gì sẽ xảy ra khi bạn chỉnh sửa các tệp khác nhau trong đó.

Để đặt mã theo dạng giả, một phương pháp như thế này được gọi trong tài liệu gốc khi mở tài liệu con.

-(void)openChildDocumentWithURL:(NSURL *)documentURL { 
    // Don't open the same document multiple times 
    NSDocument *childDocument = [documentMapTable objectForKey:documentURL]; 
    if (childDocument == nil) { 
    childDocument = [[[MyDocument alloc] init] autorelease]; 
    // Use the same window controller 
    // (not as bad as it looks, AppKit swaps the window's document association for us) 
    [childDocument addWindowController:myWindowController]; 
    [childDocument readFromURL:documentURL ofType:@"Whatever" error:NULL]; 

    // Cache the document 
    [documentMapTable setObject:childDocument forKey:documentURL]; 
    } 

    // Make sure the window controller gets the document-association swapped if the doc came from our cache 
    [myWindowController setDocument:childDocument]; 

    // Swap the text views in 
    NSTextView *currentTextView = myCurrentTextView; 
    NSTextView *newTextView = [childDocument textView]; 
    [newTextView setFrame:[currentTextView frame]]; // Don't flicker  

    [splitView replaceSubview:currentTextView with:newTextView]; 

    if (currentTextView != newTextView) { 
    [currentTextView release]; 
    currentTextView = [newTextView retain]; 
    } 
} 

Điều khiển cửa sổ có liên kết tài liệu chính xác tại bất kỳ thời điểm nào kể từ khi dấu chấm và tiêu đề theo dõi bất kỳ tài liệu nào tôi đang chỉnh sửa.

Tuy nhiên, khi tôi nhấn lưu, (CMD + S hoặc Tệp -> Lưu/Lưu dưới dạng), bạn muốn lưu tài liệu gốc, không phải tài liệu hiện tại (như được báo cáo bởi [[NSDocumentController sharedDocumentController] currentDocument] và như được chỉ ra bởi tiêu đề cửa sổ và thay đổi dấu chấm).

Từ đọc các tài liệu hướng dẫn NSResponder, nó có vẻ như chuỗi phải được điều này:

Current View -> SuperView (lặp lại) -> Window -> WindowController -> Document -> DocumentController -> Application.

Tôi không chắc chắn cách kiến ​​trúc dựa trên tài liệu đang thiết lập chuỗi trả lời (tức là cách đặt NSDocumentNSDocumentController vào chuỗi), vì vậy tôi muốn gỡ lỗi, nhưng tôi không chắc chắn nên tìm ở đâu. Làm cách nào để truy cập chuỗi trả lời vào bất kỳ thời điểm nào?

Trả lời

38

Bạn có thể lặp qua chuỗi phản hồi bằng cách sử dụng phương pháp NSResponder nextResponder. Ví dụ, bạn sẽ có thể bắt đầu với giao diện hiện tại, và sau đó liên tục in ra kết quả của gọi đó là trong một vòng lặp như thế này:

NSResponder *responder = currentView; 
while ((responder = [responder nextResponder])) { 
    NSLog(@"%@", responder); 
} 
+0

Cảm ơn, tôi không biết điều đó đã không xảy ra với tôi như thế nào, tôi đã quá tập trung vào ý tưởng tìm nạp trực tiếp toàn bộ ngăn xếp trong một lần. – d11wtq

6

Dưới đây là một phiên bản dành cho người dùng Swift:

func printResponderChain(_ responder: UIResponder?) { 
    guard let responder = responder else { return; } 

    print(responder) 
    printResponderChain(responder.next) 
} 

Đơn giản chỉ cần gọi nó với chính mình để in ra chuỗi trả lời bắt đầu từ tự.

printResponderChain(self) 
3

Bạn cũng có thể thêm danh mục vào lớp UIResponder với phương thức thích hợp có thể được sử dụng bởi bất kỳ lớp con nào của UIResponder.

@interface UIResponder (Inspect) 

- (void)inspectResponderChain; // show responder chain including self 

@end 

@implementation UIResponder (Inspect) 

- (void)inspectResponderChain 
{ 
    UIResponder *x = self; 
    do { 
     NSLog(@"%@", x); 
    }while ((x = [x nextResponder])); 
} 
@end 

hơn bạn có thể sử dụng phương pháp này ở đâu đó trong mã như ví dụ dưới đây:

- (void)viewDidLoad { 
    ... 
    UIView *myView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 100, 100)]; 
    [self.view addSubview:myView]; 
    [myView inspectResponderChain]; // UIView is a subclass of UIResponder 
    ... 
} 
2

Swift 3:

func printResponderChain(from responder: UIResponder?) { 
    var responder = responder 
    while let r = responder { 
     print(r) 
     responder = r.next 
    } 
} 


printResponderChain(from: view) 
1

tôi sẽ cải thiện một chút về câu trả lời loại Responder, bằng cách sử dụng một phương pháp lớp học mà cảm thấy nhiều hơn "có thể sử dụng" khi gỡ lỗi (bạn không cần phải phá vỡ trong một cái nhìn cụ thể hoặc bất cứ điều gì).

Mã dành cho Cocoa nhưng phải dễ dàng di chuyển đến UIKit.

@interface NSResponder (Inspect) 

+ (void)inspectResponderChain; 

@end 

@implementation NSResponder (Inspect) 

+ (void)inspectResponderChain 
{ 
    NSWindow *mainWindow = [NSApplication sharedApplication].mainWindow; 

    NSLog(@"Responder chain:"); 
    NSResponder *responder = mainWindow.firstResponder; 
    do 
    { 
    NSLog(@"\t%@", [responder debugDescription]); 
    } 
    while ((responder = [responder nextResponder])); 
} 

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