Coerced to Any' But Property Is of Type Uicolor

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 and b?.a?.n will both give an Optional<Int> at the end
    • Ofcourse if b or a is nil then b.a.n will crash because it's implicitly unwrapping b and a to get to n which is Optional<Int>
    • To get Int instead of Optional<Int>, you would do b.a.n! and so in your case you would do: print(residenceId!) to get Int

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



Leave a reply



Submit