3 Replies
      Latest reply on Jul 13, 2018 5:26 PM by PBK
      Odyth Level 1 Level 1 (0 points)

        When using named colors in your interface builder files their values get set AFTER viewDidLoad() and awakeFromNib() get called. Making it difficult to change the values at run time. Is this by design? is their some other method i need to override so I can change the colors at run time? Should I just stop using named colors?

         

        In my test project I have a view and I set the background to a named color then try and set that background to somthing else in viewDidLoad(). If I don't use a named color things work as you would expect. This app only supports iOS 11+

         

        I made a custom view called MyView and log the back trace when the background is set. you see it first set when the control is being created in initWithCoder

         

        (lldb) bt
        * thread #1, queue = 'com.apple.main-thread', stop reason = breakpoint 1.1
          * frame #0: 0x000000010eba36b2 ***`MyView.backgroundColor.didset(oldValue=nil, self=0x00007fb97e707eb0) at MyView.swift:17
            frame #1: 0x000000010eba3674 ***`MyView.backgroundColor.setter(newValue=0x000060000006f640, self=0x00007fb97e707eb0) at MyView.swift:0
            frame #2: 0x000000010eba35ac ***`@objc MyView.backgroundColor.setter at MyView.swift:0
            frame #3: 0x000000010fde7ecc UIKit`-[UIView initWithCoder:] + 1242
            frame #4: 0x000000010eba3a1a ***`MyView.init(aDecoder=0x00007fb98000a600) at MyView.swift:0
            frame #5: 0x000000010eba3abf ***`@objc MyView.init(coder:) at MyView.swift:0
            frame #6: 0x00000001101d4725 UIKit`-[UIClassSwapper initWithCoder:] + 246
            frame #7: 0x000000011042688c UIKit`UINibDecoderDecodeObjectForValue + 704
            frame #8: 0x00000001104265bf UIKit`-[UINibDecoder decodeObjectForKey:] + 246
            frame #9: 0x00000001101d43f1 UIKit`-[UIRuntimeConnection initWithCoder:] + 178
            frame #10: 0x000000011042688c UIKit`UINibDecoderDecodeObjectForValue + 704
            frame #11: 0x0000000110426a2a UIKit`UINibDecoderDecodeObjectForValue + 1118
            frame #12: 0x00000001104265bf UIKit`-[UINibDecoder decodeObjectForKey:] + 246
            frame #13: 0x00000001101d35e2 UIKit`-[UINib instantiateWithOwner:options:] + 1262
            frame #14: 0x000000010feee0d7 UIKit`-[UIViewController _loadViewFromNibNamed:bundle:] + 383
            frame #15: 0x000000010feeea04 UIKit`-[UIViewController loadView] + 177
            frame #16: 0x000000010feeed21 UIKit`-[UIViewController loadViewIfRequired] + 175
            frame #17: 0x000000010feef574 UIKit`-[UIViewController view] + 27
            frame #18: 0x000000010fdbd123 UIKit`-[UIWindow addRootViewControllerViewIfPossible] + 122
            frame #19: 0x000000010fdbd834 UIKit`-[UIWindow _setHidden:forced:] + 294
            frame #20: 0x000000010fdd05cc UIKit`-[UIWindow makeKeyAndVisible] + 42
            frame #21: 0x000000010fd443da UIKit`-[UIApplication _callInitializationDelegatesForMainScene:transitionContext:] + 4739
            frame #22: 0x000000010fd495cb UIKit`-[UIApplication _runWithMainScene:transitionContext:completion:] + 1677
            frame #23: 0x000000011010bf7e UIKit`__111-[__UICanvasLifecycleMonitor_Compatability _scheduleFirstCommitForScene:transition:firstActivation:completion:]_block_invoke + 866
            frame #24: 0x00000001104dea39 UIKit`+[_UICanvas _enqueuePostSettingUpdateTransactionBlock:] + 153
            frame #25: 0x000000011010bbba UIKit`-[__UICanvasLifecycleMonitor_Compatability _scheduleFirstCommitForScene:transition:firstActivation:completion:] + 236
            frame #26: 0x000000011010c3db UIKit`-[__UICanvasLifecycleMonitor_Compatability activateEventsOnly:withContext:completion:] + 675
            frame #27: 0x0000000110a7d614 UIKit`__82-[_UIApplicationCanvas _transitionLifecycleStateWithTransitionContext:completion:]_block_invoke + 299
            frame #28: 0x0000000110a7d4ae UIKit`-[_UIApplicationCanvas _transitionLifecycleStateWithTransitionContext:completion:] + 433
            frame #29: 0x000000011076175d UIKit`__125-[_UICanvasLifecycleSettingsDiffAction performActionsForCanvas:withUpdatedScene:settingsDiff:fromSettings:transitionContext:]_block_invoke + 221
            frame #30: 0x000000011095c4b7 UIKit`_performActionsWithDelayForTransitionContext + 100
            frame #31: 0x0000000110761627 UIKit`-[_UICanvasLifecycleSettingsDiffAction performActionsForCanvas:withUpdatedScene:settingsDiff:fromSettings:transitionContext:] + 223
            frame #32: 0x00000001104de0e0 UIKit`-[_UICanvas scene:didUpdateWithDiff:transitionContext:completion:] + 392
            frame #33: 0x000000010fd47eac UIKit`-[UIApplication workspace:didCreateScene:withTransitionContext:completion:] + 515
            frame #34: 0x000000011031abcb UIKit`-[UIApplicationSceneClientAgent scene:didInitializeWithEvent:completion:] + 361
            frame #35: 0x00000001150d72f3 FrontBoardServices`-[FBSSceneImpl _didCreateWithTransitionContext:completion:] + 331
            frame #36: 0x00000001150dfcfa FrontBoardServices`__56-[FBSWorkspace client:handleCreateScene:withCompletion:]_block_invoke_2 + 225
            frame #37: 0x000000011420c7ec libdispatch.dylib`_dispatch_client_callout + 8
            frame #38: 0x0000000114211db8 libdispatch.dylib`_dispatch_block_invoke_direct + 592
            frame #39: 0x000000011510b470 FrontBoardServices`__FBSSERIALQUEUE_IS_CALLING_OUT_TO_A_BLOCK__ + 24
            frame #40: 0x000000011510b12e FrontBoardServices`-[FBSSerialQueue _performNext] + 439
            frame #41: 0x000000011510b68e FrontBoardServices`-[FBSSerialQueue _performNextFromRunLoopSource] + 45
            frame #42: 0x000000011304abb1 CoreFoundation`__CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION__ + 17
            frame #43: 0x000000011302f4af CoreFoundation`__CFRunLoopDoSources0 + 271
            frame #44: 0x000000011302ea6f CoreFoundation`__CFRunLoopRun + 1263
            frame #45: 0x000000011302e30b CoreFoundation`CFRunLoopRunSpecific + 635
            frame #46: 0x00000001159a0a73 GraphicsServices`GSEventRunModal + 62
            frame #47: 0x000000010fd4b057 UIKit`UIApplicationMain + 159
            frame #48: 0x000000010eba5a67 ***`main at AppDelegate.swift:12
            frame #49: 0x0000000114289955 libdyld.dylib`start + 1
            frame #50: 0x0000000114289955 libdyld.dylib`start + 1
        (lldb) 
        

         

        Then in my viewDidLoad() method I set it

         

        (lldb) bt
        * thread #1, queue = 'com.apple.main-thread', stop reason = breakpoint 1.1
          * frame #0: 0x000000010eba36b2 ***`MyView.backgroundColor.didset(oldValue=0x0000608000271d40, self=0x00007fb97e707eb0) at MyView.swift:17
            frame #1: 0x000000010eba3674 ***`MyView.backgroundColor.setter(newValue=0x0000608000272000, self=0x00007fb97e707eb0) at MyView.swift:0
            frame #2: 0x000000010eba35ac ***`@objc MyView.backgroundColor.setter at MyView.swift:0
            frame #3: 0x000000010eba42b7 ***`ViewController.viewDidLoad(self=0x00007fb981504fa0) at ViewController.swift:20
            frame #4: 0x000000010eba4484 ***`@objc ViewController.viewDidLoad() at ViewController.swift:0
            frame #5: 0x000000010feef131 UIKit`-[UIViewController loadViewIfRequired] + 1215
            frame #6: 0x000000010feef574 UIKit`-[UIViewController view] + 27
            frame #7: 0x000000010fdbd123 UIKit`-[UIWindow addRootViewControllerViewIfPossible] + 122
            frame #8: 0x000000010fdbd834 UIKit`-[UIWindow _setHidden:forced:] + 294
            frame #9: 0x000000010fdd05cc UIKit`-[UIWindow makeKeyAndVisible] + 42
            frame #10: 0x000000010fd443da UIKit`-[UIApplication _callInitializationDelegatesForMainScene:transitionContext:] + 4739
            frame #11: 0x000000010fd495cb UIKit`-[UIApplication _runWithMainScene:transitionContext:completion:] + 1677
            frame #12: 0x000000011010bf7e UIKit`__111-[__UICanvasLifecycleMonitor_Compatability _scheduleFirstCommitForScene:transition:firstActivation:completion:]_block_invoke + 866
            frame #13: 0x00000001104dea39 UIKit`+[_UICanvas _enqueuePostSettingUpdateTransactionBlock:] + 153
            frame #14: 0x000000011010bbba UIKit`-[__UICanvasLifecycleMonitor_Compatability _scheduleFirstCommitForScene:transition:firstActivation:completion:] + 236
            frame #15: 0x000000011010c3db UIKit`-[__UICanvasLifecycleMonitor_Compatability activateEventsOnly:withContext:completion:] + 675
            frame #16: 0x0000000110a7d614 UIKit`__82-[_UIApplicationCanvas _transitionLifecycleStateWithTransitionContext:completion:]_block_invoke + 299
            frame #17: 0x0000000110a7d4ae UIKit`-[_UIApplicationCanvas _transitionLifecycleStateWithTransitionContext:completion:] + 433
            frame #18: 0x000000011076175d UIKit`__125-[_UICanvasLifecycleSettingsDiffAction performActionsForCanvas:withUpdatedScene:settingsDiff:fromSettings:transitionContext:]_block_invoke + 221
            frame #19: 0x000000011095c4b7 UIKit`_performActionsWithDelayForTransitionContext + 100
            frame #20: 0x0000000110761627 UIKit`-[_UICanvasLifecycleSettingsDiffAction performActionsForCanvas:withUpdatedScene:settingsDiff:fromSettings:transitionContext:] + 223
            frame #21: 0x00000001104de0e0 UIKit`-[_UICanvas scene:didUpdateWithDiff:transitionContext:completion:] + 392
            frame #22: 0x000000010fd47eac UIKit`-[UIApplication workspace:didCreateScene:withTransitionContext:completion:] + 515
            frame #23: 0x000000011031abcb UIKit`-[UIApplicationSceneClientAgent scene:didInitializeWithEvent:completion:] + 361
            frame #24: 0x00000001150d72f3 FrontBoardServices`-[FBSSceneImpl _didCreateWithTransitionContext:completion:] + 331
            frame #25: 0x00000001150dfcfa FrontBoardServices`__56-[FBSWorkspace client:handleCreateScene:withCompletion:]_block_invoke_2 + 225
            frame #26: 0x000000011420c7ec libdispatch.dylib`_dispatch_client_callout + 8
            frame #27: 0x0000000114211db8 libdispatch.dylib`_dispatch_block_invoke_direct + 592
            frame #28: 0x000000011510b470 FrontBoardServices`__FBSSERIALQUEUE_IS_CALLING_OUT_TO_A_BLOCK__ + 24
            frame #29: 0x000000011510b12e FrontBoardServices`-[FBSSerialQueue _performNext] + 439
            frame #30: 0x000000011510b68e FrontBoardServices`-[FBSSerialQueue _performNextFromRunLoopSource] + 45
            frame #31: 0x000000011304abb1 CoreFoundation`__CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION__ + 17
            frame #32: 0x000000011302f4af CoreFoundation`__CFRunLoopDoSources0 + 271
            frame #33: 0x000000011302ea6f CoreFoundation`__CFRunLoopRun + 1263
            frame #34: 0x000000011302e30b CoreFoundation`CFRunLoopRunSpecific + 635
            frame #35: 0x00000001159a0a73 GraphicsServices`GSEventRunModal + 62
            frame #36: 0x000000010fd4b057 UIKit`UIApplicationMain + 159
            frame #37: 0x000000010eba5a67 ***`main at AppDelegate.swift:12
            frame #38: 0x0000000114289955 libdyld.dylib`start + 1
            frame #39: 0x0000000114289955 libdyld.dylib`start + 1
        (lldb) 
        

         

        Then it is set by _UIColorAttributeTraitStorage applyRecordsMatchingTraitCollection after that.

         

        (lldb) bt
        * thread #1, queue = 'com.apple.main-thread', stop reason = breakpoint 1.1
          * frame #0: 0x000000010eba36b2 ***`MyView.backgroundColor.didset(oldValue=0x0000608000272000, self=0x00007fb97e707eb0) at MyView.swift:17
            frame #1: 0x000000010eba3674 ***`MyView.backgroundColor.setter(newValue=0x0000608000036240, self=0x00007fb97e707eb0) at MyView.swift:0
            frame #2: 0x000000010eba35ac ***`@objc MyView.backgroundColor.setter at MyView.swift:0
            frame #3: 0x000000010eed0b47 Foundation`-[NSObject(NSKeyValueCoding) setValue:forKey:] + 292
            frame #4: 0x000000010fe19f77 UIKit`-[UIView(CALayerDelegate) setValue:forKey:] + 172
            frame #5: 0x00000001100dcac3 UIKit`-[NSObject(UIIBPrivate) _uikit_applyValueFromTraitStorage:forKeyPath:] + 50
            frame #6: 0x00000001100de12d UIKit`-[_UIColorAttributeTraitStorage applyRecordsMatchingTraitCollection:] + 160
            frame #7: 0x00000001100dd38f UIKit`-[NSObject(_UITraitStorageAccessors) _applyTraitStorageRecordsForTraitCollection:] + 261
            frame #8: 0x000000010fdeecf0 UIKit`-[UIView _traitCollectionDidChangeInternal:] + 77
            frame #9: 0x000000010fdeef1d UIKit`-[UIView _wrappedProcessTraitCollectionDidChange:forceNotification:] + 163
            frame #10: 0x000000010fdef21f UIKit`-[UIView _processDidChangeRecursivelyFromOldTraits:toCurrentTraits:forceNotification:] + 129
            frame #11: 0x000000010fe1a740 UIKit`-[UIView(CALayerDelegate) layoutSublayersOfLayer:] + 1411
            frame #12: 0x0000000116817456 QuartzCore`-[CALayer layoutSublayers] + 177
            frame #13: 0x000000011681b667 QuartzCore`CA::Layer::layout_if_needed(CA::Transaction*) + 395
            frame #14: 0x00000001167a20fb QuartzCore`CA::Context::commit_transaction(CA::Transaction*) + 343
            frame #15: 0x00000001167cf79c QuartzCore`CA::Transaction::commit() + 568
            frame #16: 0x000000010fd65269 UIKit`__34-[UIApplication _firstCommitBlock]_block_invoke_2 + 141
            frame #17: 0x000000011304ab0c CoreFoundation`__CFRUNLOOP_IS_CALLING_OUT_TO_A_BLOCK__ + 12
            frame #18: 0x000000011302f2db CoreFoundation`__CFRunLoopDoBlocks + 331
            frame #19: 0x000000011302ea84 CoreFoundation`__CFRunLoopRun + 1284
            frame #20: 0x000000011302e30b CoreFoundation`CFRunLoopRunSpecific + 635
            frame #21: 0x00000001159a0a73 GraphicsServices`GSEventRunModal + 62
            frame #22: 0x000000010fd4b057 UIKit`UIApplicationMain + 159
            frame #23: 0x000000010eba5a67 ***`main at AppDelegate.swift:12
            frame #24: 0x0000000114289955 libdyld.dylib`start + 1
            frame #25: 0x0000000114289955 libdyld.dylib`start + 1
        (lldb) 
        
        • Re: named colors get set after viewDidLoad() WHY?!
          QuinceyMorris Level 8 Level 8 (5,700 points)

          It doesn't seem impossible that colors might be adjusted when the view is added to a window view hierarchy, without being documented anywhere.

           

          I'd suggest you try setting your overriding colors in viewWillAppear or (if that's still too early) in viewDidAppear.

           

          Might be worth a bug report, too.

          • Re: named colors get set after viewDidLoad() WHY?!
            PBK Level 6 Level 6 (2,735 points)

            viewDidLoad refers to your viewController’s code. After the viewController is loaded the nib file is loaded along with all your instructions in the interface builder and all those colors and frame positioning. Then viewWillAppear is executed. So you can override the nib file there. Note that if you don’t want to repeatedly execute that viewWillAppear code each time the view will appear you can set a variable like firstTime to YES in viewDidLoad and set it to NO at the end of viewWillAppear.