UIWebBrowserView的声明如下:(代码好长,点此跳过)
@interface UIWebBrowserView : UIWebDocumentView <UIWebFormAccessoryDelegate, UIBrowserDocumentController, _UIWebRotationDelegate> { UIWebFormAccessory *_accessory; NSObject<UIFormPeripheral> *_input; DOMNode *_currentAssistedNode; DOMNode *_assistedNodeStartingFocusRedirects; struct CGRect _inputViewBounds; struct CGRect _addressViewBounds; float _lastAdjustmentForScroller; unsigned int _audioSessionCategoryOverride; unsigned int _accessoryEnabled:1; unsigned int _forceInputView:1; unsigned int _formIsAutoFilling:1; unsigned int _inputViewObeysDOMFocus:1; unsigned int _allowDOMFocusRedirects:1; unsigned int _hasEditedTextField:1; unsigned int _alwaysDispatchesScrollEvents:1; UIWebTouchEventsGestureRecognizer *_webTouchEventsGestureRecognizer; UIWebFormDelegate *_formDelegate; UIResponder *_editingDelegateForEverythingExceptForms; unsigned int _dispatchedTouchEvents; NSMutableArray *_deferredTouchEvents; struct { NSMutableArray *all; NSMutableArray *html; NSMutableArray *javascript; NSMutableArray *css; NSMutableArray *error; NSMutableArray *warning; NSMutableArray *tip; NSMutableArray *log; } _messages; CDStruct_d58a15aa _pdf; } + (id)_PDFPageNumberLabel:(BOOL)arg1; + (BOOL)isAutoFillAllowed; + (id)getUIWebBrowserViewForWebFrame:(id)arg1; + (float)preferredScrollDecelerationFactor; @property(readonly, nonatomic) BOOL hasEditedTextField; // @synthesize hasEditedTextField=_hasEditedTextField; @property(nonatomic) BOOL allowDOMFocusRedirects; // @synthesize allowDOMFocusRedirects=_allowDOMFocusRedirects; @property(nonatomic) BOOL inputViewObeysDOMFocus; // @synthesize inputViewObeysDOMFocus=_inputViewObeysDOMFocus; @property(nonatomic, getter=isAccessoryEnabled) BOOL accessoryEnabled; // @synthesize accessoryEnabled=_accessoryEnabled; @property(nonatomic) UIResponder *_editingDelegateForEverythingExceptForms; // @synthesize _editingDelegateForEverythingExceptForms; @property(retain, nonatomic) DOMNode *_currentAssistedNode; // @synthesize _currentAssistedNode; @property(retain, nonatomic) NSObject<UIFormPeripheral> *_input; // @synthesize _input; @property(retain, nonatomic) UIWebFormAccessory *_accessory; // @synthesize _accessory; - (BOOL)considerHeightOfRectOfInterestForRotation; - (struct CGSize)contentSizeForScrollView:(id)arg1; - (float)scaleForProposedNewScale:(float)arg1 andOldScale:(float)arg2; - (struct CGRect)activeRectForRectOfInterest:(struct CGRect)arg1; - (float)heightToKeepVisible; - (float)minimumVerticalContentOffset; - (struct CGRect)rectOfInterestForRotation; - (void)updateBoundariesOfScrollView:(id)arg1 withScales:(CDStruct_869f9c67)arg2; - (CDStruct_869f9c67)scalesForContainerSize:(struct CGSize)arg1; @property(nonatomic) BOOL alwaysDispatchesScrollEvents; - (void)webView:(id)arg1 didFirstVisuallyNonEmptyLayoutInFrame:(id)arg2; - (id)_absoluteUrlRelativeToDocumentURL:(id)arg1; - (void)_startURLificationIfNeededCoalesce:(BOOL)arg1; - (void)_setSelectedDOMRangeAndUpdateUI:(id)arg1; - (void)_clearSelectionAndUI; - (BOOL)_dumpWebArchiveAtPath:(id)arg1; - (void)_updatePDFPageNumberLabelWithUserScrolling:(BOOL)arg1 animated:(BOOL)arg2; - (struct CGPoint)_originForPDFPageLabelInSuperview:(id)arg1; - (unsigned int)_firstVisiblePDFPageNumber; - (void)_clearAllConsoleMessages; - (void)clearMessagesMatchingMask:(int)arg1; - (id)messagesMatchingMask:(int)arg1; - (void)webView:(id)arg1 addMessageToConsole:(id)arg2 withSource:(id)arg3; - (void)_setAddressViewFrame:(struct CGRect)arg1; - (void)rotateEnclosingScrollViewToFrame:(struct CGRect)arg1; - (struct CGSize)_defaultScrollViewContentSize; - (void)_zoomToRect:(struct CGRect)arg1 withScale:(float)arg2; - (void)_zoomToRect:(struct CGRect)arg1 ensuringVisibilityOfRect:(struct CGRect)arg2 withScale:(float)arg3 forceScroll:(BOOL)arg4 formAssistantFrame:(struct CGRect)arg5 animationDuration:(double)arg6; - (void)_zoomToRect:(struct CGRect)arg1 ensuringVisibilityOfRect:(struct CGRect)arg2 withScale:(float)arg3 forceScroll:(BOOL)arg4; - (void)_zoomToNode:(id)arg1 forceScroll:(BOOL)arg2; - (void)_centerRect:(struct CGRect)arg1 forSizeChange:(BOOL)arg2 withVisibleHeight:(float)arg3 pinningEdge:(int)arg4; - (void)_centerRect:(struct CGRect)arg1 forSizeChange:(BOOL)arg2 withVisibleHeight:(float)arg3 pinningEdge:(int)arg4 toValue:(float)arg5; - (struct CGRect)_activeRectForRectToCenter:(struct CGRect)arg1; - (void)webViewDidPreventDefaultForEvent:(id)arg1; - (struct CGPoint)_convertWindowPointToViewport:(struct CGPoint)arg1; @property(readonly, nonatomic) BOOL isDispatchingTouchEvents; - (void)_webTouchEventsRecognized:(id)arg1; - (void)_handleDeferredEvents; - (void)_deferWebEvent:(id)arg1; - (void)_endDeferringEvents; - (void)_startDeferringEvents; - (void)_dispatchWebEvent:(id)arg1; - (BOOL)_shouldDeferEvents; - (void)webView:(id)arg1 elementDidBlurNode:(id)arg2; - (void)webView:(id)arg1 elementDidFocusNode:(id)arg2; - (void)webViewFormEditedStatusHasChanged:(id)arg1; - (BOOL)isAutoFilling; - (BOOL)isAutoFillMode; - (void)autoFillWithElementValue; - (void)acceptedAutoFillWord:(id)arg1; - (void)webView:(id)arg1 didFirstLayoutInFrame:(id)arg2; - (void)webView:(id)arg1 didFailLoadWithError:(id)arg2 forFrame:(id)arg3; - (void)webView:(id)arg1 didFinishLoadForFrame:(id)arg2; - (void)webView:(id)arg1 didStartProvisionalLoadForFrame:(id)arg2; - (void)webView:(id)arg1 willCloseFrame:(id)arg2; - (void)_autoFillFrame:(id)arg1; - (void)_resetFormDataForFrame:(id)arg1; - (id)textFormElement; - (id)formElement; - (BOOL)canAutoFill; - (void)formDelegateHandleTextChangeWithAutoFillSuggestions:(BOOL)arg1; - (void)_scrollCaretToVisible:(id)arg1; - (void)accessoryClear; - (void)accessoryAutoFill; - (void)accessoryTab:(BOOL)arg1; - (void)accessoryDone; @property(nonatomic) unsigned int audioSessionCategoryOverride; @property(nonatomic) BOOL mediaPlaybackRequiresUserAction; @property(nonatomic) BOOL allowsInlineMediaPlayback; - (void)assistFormNode:(id)arg1; - (void)_endAllowingFocusRedirects; - (void)_beginAllowingFocusRedirects; - (void)_updateAccessory; - (void)_displayFormNodeInputView; - (void)_stopAssistingFormNode; - (void)setBounds:(struct CGRect)arg1; - (void)setFrame:(struct CGRect)arg1; - (void)_didScroll; - (void)_updateScrollerViewForInputView:(id)arg1; - (void)_updateFixedPositioningObjectsLayoutSoon; - (void)_updateFixedPositionContent; - (void)_updateFixedPositioningObjectsLayoutAfterVisibleGeometryChange; - (void)_updateFixedPositioningObjectsLayoutAfterScroll; - (void)_keyboardWillHide:(id)arg1; - (void)_keyboardWillShow:(id)arg1; - (void)_keyboardDidChangeFrame:(id)arg1; - (void)_keyboardWillChangeFrame:(id)arg1; - (void)_setInputViewBoundsForAutomaticKeyboardInfo:(id)arg1 adjustScrollView:(BOOL)arg2; - (void)_stopAssistingNode:(id)arg1; - (void)_startAssistingNode:(id)arg1; - (void)_stopAssistingKeyboard; - (void)_startAssistingKeyboard; - (void)_promptForReplace:(id)arg1; - (BOOL)playsNicelyWithGestures; - (id)_editingDelegate; - (void)copy:(id)arg1; - (BOOL)canPerformAction:(SEL)arg1 withSender:(id)arg2; - (id)inputView; - (id)inputAccessoryView; - (void)_handleKeyEvent:(struct __GSEvent *)arg1; - (BOOL)resignFirstResponder; - (id)textDocument; - (id)_keyboardResponder; - (BOOL)_requiresKeyboardResetOnReload; - (BOOL)_requiresKeyboardWhenFirstResponder; - (BOOL)_keepKeyboardVisibleDuringFocusRedirects; - (BOOL)isEditable; - (void)installGestureRecognizers; - (void)dealloc; - (id)initWithFrame:(struct CGRect)arg1; - (id)initWithWebView:(id)arg1 frame:(struct CGRect)arg2; @end
UIWebBrowserView并不算复杂,主要负责这些工作:
下面想探讨一下UIWebBrowserView->UIWebDocumentView->UIWebTiledView这样的设计。
从已掌握的信息看,他们的成员变量都是使用private继承,即子类无法直接访问父类的成员变量。他们之间的关系是子类操控父类,基类的职责不会牵涉和考虑到子类,分工非常明确。由于UIWebDocumentView直接管理WebView,它的职责是有部分属于Controller的行为,例如手势事件。但是UIWebBrowserView的JavaScript手势却完全不干涉UIWebDocumentView的手势,通过别的途径来获取更高优先级的处理权。
总之,通过继承来拆分一个大类,必须做到这样才是可行的,值得借鉴。要拆分大类通常会用组合,但这里就是不用组合的优秀例子。当然,这也要求继承链里不能有分支,即基类不会有多个子类。