首先,当你app运行起来时,会有个UIWindowScene的类,他的_windowSceneDelegate会返回一个类似AppDelegate的类的对象(是这个类->SceneDelegate),调用它的window方法,判断当前window是否存在,不存在,就会根据UIWindowScene类下的screen的大小创建一个window.存在就会调用_resizeWindowToFullScreenIfNecessary,在init初期就是纠正道正确尺寸,所以window的大小永远是正确的屏幕尺寸大小。这里和AppDelegate很像。
当你的window 设置了rootController,并且调用了makeKeyAndVisible时,rootController 会调用自己的view方法,然后开始回事loadview 从xib或者SB中加载view了,这是你的xib 或者SB 决定着 你的Controller执行到viewdidload 方法时的self.view 的大小。xib或者SB你选择的屏幕的大小,就是到viewdidload 时view的大小,所以显然你不能在不同手机尺寸,来根据你的self.view的frame 来布局你的subViews是错误的,所以现在所有使用frame的人都会使用UIscreen的bounds来获取当前屏幕尺寸。
此时只要删除xib或者SB就可以了。
其实self.view纠正貌似来自viewcontorller 的'-[UIViewController _window]的大小纠正,底层来自CALayer::这个C++类的纠正
一切viewcontroller.view 的subviews 开始布局在viewcontroller调完viewWillLayoutSubviews这个方法之后。但是有人就想问的更深一些,经过研究发现,是在view.layer 的代理方法开始布局的,layoutSublayersOfLayer:,这个代理方法默认指向view自己的.
/* Called by the default -layoutSublayers implementation before the layout
* manager is checked. Note that if the delegate method is invoked, the
* layout manager will be ignored. */
- (void)layoutSublayersOfLayer:(CALayer *)layer;
另一处是:
/* Called when the layer requires layout. The default implementation
* calls the layout manager if one exists and it implements the
* -layoutSublayersOfLayer: method. Subclasses can override this to
* provide their own layout algorithm, which should set the frame of
* each sublayer. */
- (void)layoutSublayers;
由此可见只要你默认不实现这个代理方法他会用他自己的layout algorithm(layout 算法),只要你自己实现了,你要写一套布局算法,或者手动设置frame布局也可。
这个算法经过调试就是View自己的私有方法的算法-[view _layoutEngine]
,这是个私有类->NSISEngine.
我获取了NSISEngine所有的属性和方法
in NSISEngine:
Class Methods:
+ (BOOL) _dbg_anyEngineContainsVariable:(id)arg1; (0x7fff59a25c40)
+ (void) setEnableEngineTrace:(BOOL)arg1; (0x7fff59a285ee)
+ (BOOL) enableEngineTrace; (0x7fff59a285fa)
+ (id) traceFileSuffix; (0x7fff59a28604)
+ (void) setTraceFileSuffix:(id)arg1; (0x7fff59a2860c)
+ (void) setLogOnInvalidUseFromBGThread:(BOOL)arg1; (0x7fff59a2861a)
Properties:
@property (retain) NSMutableArray* variablesWithValueRestrictionViolations; (@synthesize variablesWithValueRestrictionViolations = _variablesWithValueRestrictionViolations;)
@property (retain) NSISVariable* artificialRowHead; (@synthesize artificialRowHead = _artificialRowHead;)
@property (retain) NSISVariable* artificialObjectiveRowHead; (@synthesize artificialObjectiveRowHead = _artificialObjectiveRowHead;)
@property (retain) NSISObjectiveLinearExpression* artificialObjectiveRowBody; (@synthesize artificialObjectiveRowBody = _artificialObjectiveRowBody;)
@property <NSISEngineDelegate>* delegate; (@synthesize delegate = _delegate;)
@property BOOL shouldIntegralize;
@property BOOL revertsAfterUnsatisfiabilityHandler; (@synthesize revertsAfterUnsatisfiabilityHandler = _revertsAfterUnsatisfiabilityHandler;)
@property (readonly) unsigned long variableChangeCount;
@property (readonly, getter=isOptimizationInProgress) BOOL optimizationInProgress;
@property (nonatomic) struct CGSize engineScalingCoefficients; (@synthesize engineScalingCoefficients = _engineScalingCoefficients;)
@property (readonly) unsigned long hash;
@property (readonly) Class superclass;
@property (readonly, copy) NSString* description;
@property (readonly, copy) NSString* debugDescription;
Instance Methods:
- (id) debugQuickLookObject; (0x7fff24ae85b2)
- (void) _UIKitPerformPendingChangeNotifications; (0x7fff24af0442)
- (BOOL) _UIKitEngineTrackingOn; (0x7fff24af042a)
- (void) _setUIKitEngineTrackingOn:(BOOL)arg1; (0x7fff24af03dc)
- (unsigned long) _UIKitRowCount; (0x7fff24af0497)
- (void) dealloc; (0x7fff59a23bc5)
- (id) description; (0x7fff59a288c6)
- (id) init; (0x7fff59a238ff)
- (id) delegate; (0x7fff59a2bc5a)
- (void) setDelegate:(id)arg1; (0x7fff59a2bc64)
- (unsigned long) rowCount; (0x7fff59a28801)
- (id) constraints; (0x7fff59a2877e)
- (void) setShouldIntegralize:(BOOL)arg1; (0x7fff59a1f2a8)
- (void) setEngineScalingCoefficients:(struct CGSize)arg1; (0x7fff59a2bc98)
- (void) withAutomaticOptimizationDisabled:(^block)arg1; (0x7fff59a2511d)
- (struct ?*) traceState; (0x7fff59a28612)
- (struct CGSize) engineScalingCoefficients; (0x7fff59a2bc88)
- (double) valueForVariable:(id)arg1; (0x7fff59a2516b)
- (BOOL) hasValue:(double*)arg1 forVariable:(id)arg2; (0x7fff59a25282)
- (BOOL) isObservingChangesForVariable:(id)arg1; (0x7fff59a285ce)
- (void) performPendingChangeNotifications; (0x7fff59a1f872)
- (id) candidateRedundantConstraints; (0x7fff59a2ab6d)
- (id) constraintsAffectingValueOfVariable:(id)arg1; (0x7fff59a2a9bf)
- (BOOL) exerciseAmbiguityInVariable:(id)arg1; (0x7fff59a2ba71)
- (void) stopObservingChangesForVariable:(id)arg1; (0x7fff59a28536)
- (void) removeObservableForVariable:(id)arg1; (0x7fff59a28413)
- (void) nsis_valueOfVariable:(id)arg1 didChangeInEngine:(id)arg2; (0x7fff59a1f1fc)
- (id) nsis_descriptionOfVariable:(id)arg1; (0x7fff59a1f20a)
- (int) nsis_orientationHintForVariable:(id)arg1; (0x7fff59a1f28f)
- (BOOL) nsis_valueOfVariableIsUserObservable:(id)arg1; (0x7fff59a1f202)
- (BOOL) valueOfVariableIsAmbiguous:(id)arg1; (0x7fff59a2b998)
- (unsigned long) variableChangeCount; (0x7fff59a288b0)
- (void) startObservingChangesForVariable:(id)arg1; (0x7fff59a2847b)
- (id) observableForVariable:(id)arg1; (0x7fff59a28376)
- (unsigned long) optimize; (0x7fff59a243fd)
- (void) beginRecording; (0x7fff59a241f6)
- (unsigned long) colCount; (0x7fff59a28855)
- (void) endBookkeepingForVariableIfUnused:(id)arg1; (0x7fff59a25b6e)
- (id) variableChangeTransactionSignal; (0x7fff59a285a5)
- (double) valueForExpression:(id)arg1; (0x7fff59a25607)
- (id) variableForEngineVarIndex:(struct ?)arg1; (0x7fff59a241a3)
- (int) valueRestrictionForEngineVarIndex:(struct ?)arg1; (0x7fff59a241cc)
- (void) verifyInternalIntegrity; (0x7fff59a29076)
- (id) _brokenConstraintPositiveErrorsIfAvailable; (0x7fff59a1eaae)
- (id) _brokenConstraintNegativeErrorsIfAvailable; (0x7fff59a1edf1)
- (void) enumerateRows:(^block)arg1; (0x7fff59a2592e)
- (void) removeConstraintWithMarker:(id)arg1; (0x7fff59a27734)
- (void) setVariablesWithValueRestrictionViolations:(id)arg1; (0x7fff59a2bc4b)
- (void) withoutOptimizingAtEndRunBlockWithAutomaticOptimizationDisabled:(^block)arg1; (0x7fff59a25137)
- (unsigned long) _optimizeWithoutRebuilding; (0x7fff59a248f0)
- (void) withBehaviors:(unsigned long)arg1 performModifications:(^block)arg2; (0x7fff59a24efc)
- (BOOL) tryToAddConstraintWithMarker:(id)arg1 expression:(id)arg2 mutuallyExclusiveConstraints:(id*)arg3; (0x7fff59a25c86)
- (BOOL) containsVariable:(id)arg1; (0x7fff59a25876)
- (void) constraintDidChangeSuchThatMarker:(id)arg1 shouldBeReplacedByMarkerPlusDelta:(double)arg2; (0x7fff59a28094)
- (double) integralizationAdjustmentForMarker:(id)arg1; (0x7fff59a1f297)
- (BOOL) shouldIntegralize; (0x7fff59a1f2a0)
- (BOOL) isTrackingVariableChanges; (0x7fff59a1f868)
- (void) performPendingChangeNotificationsForItem:(id)arg1; (0x7fff59a1fcd7)
- (void) performModifications:(^block)arg1 withUnsatisfiableConstraintsHandler:(^block)arg2; (0x7fff59a21bbb)
- (struct ?) engineVarIndexForVariable:(id)arg1; (0x7fff59a24192)
- (id) recordedCommandsData; (0x7fff59a2421d)
- (unsigned long) replayCommandsData:(id)arg1 verifyingIntegrity:(BOOL)arg2; (0x7fff59a2424e)
- (void) withDelegateCallsDisabled:(^block)arg1; (0x7fff59a25151)
- (BOOL) hasValueForPossiblyDeallocatedVariable:(id)arg1; (0x7fff59a25473)
- (BOOL) hasValue:(double*)arg1 forExpression:(id)arg2; (0x7fff59a25726)
- (void) beginBookkeepingForVariableIfNeeded:(id)arg1; (0x7fff59a25b61)
- (BOOL) tryToAddConstraintWithMarker:(id)arg1 expression:(id)arg2 integralizationAdjustment:(double)arg3 mutuallyExclusiveConstraints:(id*)arg4; (0x7fff59a25c74)
- (void) addVariableToBeOptimized:(id)arg1 priority:(double)arg2; (0x7fff59a265ba)
- (void) removeVariableToBeOptimized:(id)arg1 priority:(double)arg2; (0x7fff59a2678d)
- (void) changeVariableToBeOptimized:(id)arg1 fromPriority:(double)arg2 toPriority:(double)arg3; (0x7fff59a26ab3)
- (BOOL) containsConstraintWithMarker:(id)arg1; (0x7fff59a27722)
- (BOOL) tryToChangeConstraintSuchThatMarker:(id)arg1 isReplacedByMarkerPlusDelta:(double)arg2 undoHandler:(^block)arg3; (0x7fff59a281ca)
- (BOOL) hasObservableForVariable:(id)arg1; (0x7fff59a2845e)
- (unsigned long) pivotCount; (0x7fff59a288a6)
- (BOOL) isOptimizationInProgress; (0x7fff59a288ba)
- (id) allVariableValues; (0x7fff59a2bb65)
- (id) variablesWithValueRestrictionViolations; (0x7fff59a2bc37)
- (BOOL) revertsAfterUnsatisfiabilityHandler; (0x7fff59a2bc6e)
- (void) setRevertsAfterUnsatisfiabilityHandler:(BOOL)arg1; (0x7fff59a2bc7c)
- (id) artificialRowHead; (0x7fff59a2bca8)
- (void) setArtificialRowHead:(id)arg1; (0x7fff59a2bcbc)
- (id) artificialObjectiveRowHead; (0x7fff59a2bccb)
- (void) setArtificialObjectiveRowHead:(id)arg1; (0x7fff59a2bcdf)
- (id) artificialObjectiveRowBody; (0x7fff59a2bcee)
- (void) setArtificialObjectiveRowBody:(id)arg1; (0x7fff59a2bd02)
NSISEngine 的@property <NSISEngineDelegate>* delegate;
是指向view自己的。
听说这个算法是个先行方程,这里不做研究了。少研究算法,保护好自己的头发。不感兴趣,作为无谓的自我伤害不值得。
-[CALayer layoutSublayers]:
↓
-[UIView(CALayerDelegate) layoutSublayersOfLayer:]
↓
-[UIView _updateConstraintsAsNecessaryAndApplyLayoutFromEngine]
↓
-[UIView(AdditionalLayoutSupport) _is_layout]
↓
-[UIView resizeSubviewsWithOldSize:]
其中上图第二步至关重要,他来自UIKitCore(UIKitCore``-[UIView(CALayerDelegate) layoutSublayersOfLayer:]
),如果你不实现layoutSublayersOfLayer:代理方法,他就选择走UIView的CALayerDelegate分类。然后用_layoutEngine去布局。
下面我们既使用系统的布局引擎,同时又可拦截布局的方法:
ex:
-(void)layoutSublayersOfLayer:(CALayer *)layer {
[super layoutSublayersOfLayer:layer];
// 可以布局一些未布局的view 或者CALayer
}
自己只会布局subview 布局。自己的布局要看自己所添加的上层view 对自己的布局.自己没有对上层view添加自己的布局约束,就会走frame。不会影响subview 的布局。frame和autolayout 可以共存。