coerced to Any' but property is of type UIColor
This has nothing to do with .foregroundColor
. It has everything to do with .tintColor
and setTitleTextAttributes
.
This parameter is of type [NSAttributedString.Key : Any]
. It is not in any way considering the documentation for each key. It doesn't know or care that this should be a UIColor
. If you passed "squid", this would compile without warning (it wouldn't work, but it would compile):
UIBarButtonItem.appearance().setTitleTextAttributes(
[
.font: UIFont.systemFont(ofSize: 40),
.foregroundColor: "squid",
], for: .normal)
All it's looking at is that you're assigning view.tintColor
to a value of type Any
.
The problem is that view.tintColor
is not UIColor
, it's UIColor!
. It's not actually possible for .tintColor
to be nil, but it's possible to set it to nil:
view.tintColor // r 0.0 g 0.478 b 1.0 a 1.0
view.tintColor = .red
view.tintColor // r 1.0 g 0.0 b 0.0 a 1.0
view.tintColor = nil
view.tintColor // r 0.0 g 0.478 b 1.0 a 1.0
That makes sense in ObjC, but the only way to express it in Swift is to use a !
type. When you assign !
types to other things, they become ?
types. And that means that you're using UIColor?
in a place that accepts Any
(the value of the dictionary).
Using an optional as Any
can be dangerous because it creates a lot of weird corner cases. For example, you can't round-trip an optional through Any; it gets squashed into its base type:
let x: Any = Optional(1)
x as? Int? // Cannot downcast from 'Any' to a more optional type 'Int?'
x as? Int // 1
There are a lot of these kinds of little sharp-edges when working with Any.
Of course you didn't mean to work with Any. It's not your fault. But this is why Swift is complaining.
There are several solutions, depending on what you like. You can use a !
:
.foregroundColor: view.tintColor!
You can add as Any
to silence the warning:
.foregroundColor: view.tintColor as Any
Personally I'd use as Any
.
Or you can be elaborate and unload the value earlier (I don't recommend this):
let tintColor = view.tintColor ?? .blue
UIBarButtonItem.appearance().setTitleTextAttributes(
[
.font: UIFont.systemFont(ofSize: 40),
.foregroundColor: tintColor,
], for: .normal)
Implicitly unwrapped property warning?
Since Swift 4, ImplicitlyUnwrappedOptional
or !
as we knew it, became Optional
.
Check:
let a: ImplicitlyUnwrappedOptional<Int> = 1
will spit out the error:
'ImplicitlyUnwrappedOptional' has been renamed to 'Optional'
So instead if we do:
let a: Int! = 1
print(type(of: a)) //will print "Optional<Int>"
It's still Optional<Int>
but indicates to the compiler that it can be implicitly unwrapped.
Implicit Unwrapping is Part of a Declaration.
...
consider
!
to be a synonym for?
with the addition that it adds a flag on the declaration letting the compiler know that the declared value can be implicitly unwrapped.
Ref: Reimplementation of Implicitly Unwrapped Optionals
Now getting to the main question:
If you do:
let a: Int! = 1
let b: Any = a
print(type(of: b)) //prints "Optional<Int>"
It will give the following warning:
Expression implicitly coerced from 'Int?' to 'Any'
or as per Xcode 11
Coercion of implicitly unwrappable value of type 'Int?' to 'Any' does not unwrap optional
Note here that we tried to get a non-optional Any
out of an Int?
which means we were basically expecting an Int
but just by specifying Any
it won't also unwrap the Optional
.
It will remain an Optional
, and this is the meaning behind that warning.
Solutions:
To handle this warning gracefully, we can do any of the following:
let a: Int! = 1
let b: Any? = a
type(of: b) //Optional<Any>.Type
let c: Any! = a
type(of: c) //Optional<Any>.Type
let d: Any = a!
type(of: d) //Int.Type
EDIT: (based on comment)
!
instead of?
have any practical difference for the programmer?
!
tells the compiler that it can be implicitly unwrapped so it can help ease in the need for optional chaining.
Example:
With
?
class A {
var n: Int? = 1
}
class B {
var a: A? = A()
}
let b: B? = B()
print(b?.a?.n)
/*
but the following won't compile as compiler
will not implicitly unwrap optionals
print(b.a.n)
*/With
!
class A {
var n: Int! = 1
}
class B {
var a: A! = A()
}
let b: B! = B()
print(b.a.n) //compiler will implicitly unwrap `!` similar to print(b!.a!.n)
//also... you can still safely unwrap if you want
print(b?.a?.n)b.a.n
andb?.a?.n
will both give anOptional<Int>
at the end- Ofcourse if
b
ora
isnil
thenb.a.n
will crash because it's implicitly unwrappingb
anda
to get ton
which isOptional<Int>
- To get
Int
instead ofOptional<Int>
, you would dob.a.n!
and so in your case you would do:print(residenceId!)
to getInt
I hope I made sense
Crashing while passing UIColor as argument
This line declares the color property, which will retain the color when assigned.
@property (nonatomic, retain) UIColor *color;
This line bypasses the property setter and assigns an autoreleased object directly to the member.
color = [UIColor colorWith...
You can fix it with either:
self.color = [UIColor colorWith...
or
[color retain];
or
color = [[UIColor alloc] initWith...
Cannot subscript a value of type '[Int : UIColor]' with an index of type 'NSNumber'
Hello If you're programming in swift 4, use:
closestBeacon.major.intValue
instead of
closestBeacon.major.integerValue
Casting from AnyObject to CGColor? without errors or warnings
xcode also gives me the following hint:
Add parentheses around the cast to silence this warning
well... when xcode says so...
layer.borderColor = (borderColor as! CGColor)
Swift - Adding UserDefaults to NotificationCenter
You can set color in UserDefaults
when you notification method called. So, updated your code as follow in ViewController1:
@objc func testNotifcation(notification: NSNotification) {
table.backgroundColor = UIColor.systemPink
let colorData = NSKeyedArchiver.archivedData(withRootObject: UIColor.systemPink)
UserDefaults.standard.set(colorData, forKey: "savedColor")
UserDefaults.standard.synchronize()
print("This is a message to say it is working")
}
Then, In view did load, you need to add code to fetch saved color and set it as background. So update code in viewDidLoad
in ViewController1.
override func viewDidLoad() {
super.viewDidLoad()
NotificationCenter.default.addObserver(self, selector: #selector(BrandTableViewController.testNotifcation(notification:)), name:NSNotification.Name(rawValue: "refresh"), object: nil);
if let colorData = UserDefaults.standard.value(forKey: "savedColor") as? Data,
let savedColor = NSKeyedUnarchiver.unarchiveObject(with: colorData) as? UIColor
{
table.backgroundColor = savedColor
}
}
I hope this will help you.
EXC_BAD_ACCESS when setting properties of an option view property
You haven't actually created the UIProgressView before you call self.progressView!.tintColor
thus, progressView is nil at this point but you're trying to force unwrap it.
Move the progressView = UIProgressView(...)
line up to the top of addControls()
and that should solve the problem.
How do I expose a private class method of an Objective-C object using protocols in Swift?
One way to achieve what you want via protocols is to use a separate protocol for the static method. Static methods in Objective-C
are actually instance methods on the metaclass of the class, so you can safely take an approach like below:
@objc protocol UIColorPrivateStatic {
func _systemDestructiveTintColor() -> UIColor
}
let privateClass = UIColor.self as! UIColorPrivateStatic
privateClass._systemDestructiveTintColor() // UIDeviceRGBColorSpace 1 0.231373 0.188235 1
This will give you both exposure of the private method and usage of protocols, and you get rid of the ugly unsafeBitCast
(not that a forced cast would be more beautiful).
Just note that as always if you are working with private API's your code can break at any time if Apple decides to change some of the internals of the class.
How to pass variable reference between viewcontrollers?
Classes are reference types:
Unlike value types, reference types are not copied when they are assigned to a variable or constant, or when they are passed to a function. Rather than a copy, a reference to the same existing instance is used instead.
In the case above I think you would be best setting detailVC.setting to setting and then accessing/modifying the object properties on the object directly instead of passing the value of a class property, Does this help?
See Classes are Reference Types in the documentation
EDIT:
I believe you are using the colorsVC to set a color on the themeVC, so you segue to the colorsVC, select a color and this is returned to the themeVC table cell, correct?
If so there are a couple of ways to achieve this, I think the best way would be to pass the cell's row to the colorsVC so that it can update it as needed.
Related Topics
[_Nscftimer Copywithzone:]: Unrecognized Selector Sent to Instance
How to Call a Method on a Uiview from Outside the Uiviewrepresentable in Swiftui
Update Nstouchbar on the Fly to Add/Remove Items Programmatically
Accessing Global Variable in Swift
How to Use Unsafemutablepointer<Opaquepointer> in Swift
Setting Medium and Long Measurement Symbols in Swift 3
Cast to Different C Struct Unsafe Pointer in Swift
Value of Type 'Tags' Has No Member 'Lastused'
How to Place Uisearchcontroller to the Navigationtitle and How to Enable and Disable It by Button
Getting Twitter Profile Image with Parse in Swift
Sending Firebase Push Notifications to Logged-In Users Only
Self' Is Only Available in a Protocol or as the Result of a Class Method