2013-08-08 23 views
5

Tôi đang xây dựng chế độ xem tùy chỉnh chứa một số phụ đề khác (NSTextField, WebView, ...). Tôi muốn chế độ xem tùy chỉnh của tôi vẽ một đường viền khác khi một trong các bản xem trước là trả lời đầu tiên và hoạt động như một mục duy nhất có thể được thực hiện cùng với các mục menu và phím tắt. Nó trông giống như sau:Có cách nào mạnh mẽ để phát hiện các thay đổi trả lời đầu tiên trong các bản xem trước không?

+-------------+ 
| NSTextField | 
+-------------+ 
| WebView  | 
+-------------+ 

Cho đến nay, tôi đã thành công subclassing NSTextField và những người khác để thông báo cho đại biểu khi - (BOOL)becomeFirstResponder- (BOOL)resignFirstResponder được gọi. Cách tiếp cận này không hoạt động với WebView mặc dù, vì chính nó chứa nhiều bản xem trước - tôi không thể phân lớp tất cả!

Có cách nào tốt hơn để phát hiện khi các bản xem trước thay đổi trạng thái trả lời đầu tiên của họ không? Hoặc cách tốt hơn để tạo chế độ xem tùy chỉnh?

+0

Chính xác cùng một sự cố ở đây, bạn đã bao giờ tìm thấy giải pháp chưa? – Kappe

Trả lời

1

Cả WebViewEditingDelegate phương pháp sẽ được gọi,

từ chức responder đầu tiên:

-(void)webViewDidEndEditing:(NSNotification *)notification 
{ 

} 

và khi trở thành responder đầu tiên:

-(BOOL)webView:(WebView *)webView shouldBeginEditingInDOMRange:(DOMRange *)range 
{ 
    return YES; 
} 
+0

Chắc chắn sẽ tốt nếu API này có sẵn cho UIWebKit :) – BadPirate

2

Cách tiếp cận khác sẽ là ghi đè phương thức -makeFirstResponder: trên NSWindow để gửi thông báo.

- (BOOL)makeFirstResponder:(NSResponder *)responder { 
    id previous = self.firstResponder ?: [NSNull null]; 
    id next = responder ?: [NSNull null]; 

    NSDictionary *userInfo = @{ 
    BrFirstResponderPreviousKey: previous, 
    BrFirstResponderNextKey: next, 
    }; 

    [[NSNotificationCenter defaultCenter] postNotificationName:BrFirstResponderWillChangeNotification object:self userInfo:userInfo]; 

    return [super makeFirstResponder:responder]; 
} 

Sau đó bạn có thể nghe thông báo trong giao diện tùy chỉnh của bạn hoặc một bộ điều khiển xem và kiểm tra xem phản ứng trước hoặc bên cạnh là subviews sử dụng -isDescendantOf: và thiết lập needsDisplay khi cần thiết.

Tuy nhiên, đây không phải là giải pháp lý tưởng vì chế độ xem tùy chỉnh không còn độc lập nữa. Nó hoạt động ngay bây giờ, nhưng hy vọng một cách tiếp cận tốt hơn sẽ được chia sẻ.

1

Tôi có vấn đề này với iOS/UIWebView, không triển khai makeFirstResponder trong UIWindow, cũng không phải webViewDidEndEditing hoặc shouldBeginEditingInDOMRange. Tuy nhiên, với việc sử dụng Swizzling tôi đã có thể tạo một danh mục trợ giúp cho phép truy xuất trả lời đầu tiên hiện tại, cũng như đăng thông báo mỗi lần thay đổi trả lời đầu tiên. Thực sự bực bội như thế nào tất cả điều này nên được API công cộng, nhưng không phải là, như sự gian lận thường không phải là một goto đầu tiên, nhưng điều này làm việc tốt đủ.

Thứ nhất, thiết lập tiêu đề mục của bạn:

@interface UIResponder (Swizzle) 
+ (UIResponder *)currentFirstResponder; 
- (BOOL)customBecomeFirstResponder; 
@end 

Sau đó, loại thực

@implementation UIResponder (Swizzle) 
// It's insanity that there is no better way to get a notification when the first responder changes, but there it is. 
static UIResponder *sCurrentFirstResponder; 
+ (UIResponder *)currentFirstResponder { 
    return sCurrentFirstResponder; 
} 

- (BOOL)customBecomeFirstResponder { 
    NSMutableDictionary *userInfo = [NSMutableDictionary dictionaryWithCapacity:2]; 
    if(sCurrentFirstResponder) { 
     [userInfo setObject:sCurrentFirstResponder forKey:NSKeyValueChangeOldKey]; 
    } 
    sCurrentFirstResponder = self; 
    if(sCurrentFirstResponder) { 
     [userInfo setObject:sCurrentFirstResponder forKey:NSKeyValueChangeNewKey]; 
    } 
    [[NSNotificationCenter defaultCenter] postNotificationName:kFirstResponderDidChangeNotification 
                 object:nil 
                 userInfo:userInfo]; 
    return [self customBecomeFirstResponder]; 
} 
@end 

Cuối cùng, sử dụng một helper như JR Swizzle, trao đổi các lớp học.

#import "JRSwizzle.h" 

- (void)applicationLoaded { 
    if(![UIResponder jr_swizzleMethod:@selector(becomeFirstResponder) withMethod:@selector(customBecomeFirstResponder) error:&error]) { 
     NSLog(@"Error swizzling - %@",error); 
    } 
} 

Nghĩ rằng tôi muốn chia sẻ. Hợp lệ trong cửa hàng ứng dụng vì nó không sử dụng API riêng tư, và trong khi Apple cảnh báo chống lại các lớp cơ sở khó khăn thì không có nguyên tắc nào chống lại việc làm như vậy.