My app always crash when I trying to assign an enum to a value of[String: Any]
only on iOS14.6, tested on iOS15, iOS16, iOS17, never saw this issue.
The function would pass an ConnectState
enum and a serial number string to a userInfo of notification, received class may perform some UI updates when connect state changed.
func post(state: ConnectState, serial: Int) {
var userInfo: [String: Any] = [:]
userInfo["state"] = state
userInfo["serial"] = serial
print(userInfo)
NotificationCenter.default.post(name: NSNotification.Name("PostName"), object: nil, userInfo: userInfo)
}
@objc enum ConnectState: UInt8 {
case connected = 0x00
case disConnected = 0x01
var description: String {
switch self {
case .connected:
return "connected"
case .disConnected:
return "disConnected"
}
}
}
Classes received this notification, may perform some task based on connect state changed.
class AClass {
init() {
NotificationCenter.default.addObserver(self, selector: #selector(handleNotification(_:)), name: NSNotification.Name("PostName"), object: nil)
}
@objc func handleNotification(_ notification :Notification) {
let state = notification.userInfo?["state"] as! ConnectState
print("AClass handleNotification: \(state.description)")
}
}
let a = AClass()
post(state: .disConnected, serial: 123456)
post(state: .connected, serial: 123456)
//["serial": 123456, "state": __lldb_expr_3.ConnectState]
//AClass handleNotification: disConnected
//["serial": 123456, "state": __lldb_expr_3.ConnectState]
//AClass handleNotification: connected
The crashes always happened in the line that assigning the ConnectState
enum to dictionary [String: Any]
value, both connect state and serialNumber are not nil or optional.
I'm not sure why would this related to a allocate issue, is my code wrong?
AppName(645,0x16f61f000) malloc: can't allocate region
:*** mach_vm_map(size=1152921504606863360, flags: 100) failed (error code=3)
AppName(645,0x16f61f000) malloc: *** set a breakpoint in malloc_error_break to debug
```Since we only have one iOS14.6 device, it will be a challenge to test on other same iOS version device, nor test on simulator.
So I dusted off (literally) an iOS 14 test device and tried this out. Specifically, using Xcode 15.3 I added code to post and receive a notification like so:
final class MainViewController: UIViewController {
@objc enum ConnectState: UInt8 {
case connected = 0x00
case disConnected = 0x01
}
let testNoteName = Notification.Name("com.example.Test750235.test")
override func viewDidLoad() {
super.viewDidLoad()
NotificationCenter.default.addObserver(
self,
selector: #selector(didReceiveTest(note:)),
name: testNoteName,
object: nil
)
}
@objc func didReceiveTest(note: Notification) {
print("did receive test, note: \(note)")
}
func post() {
let state = ConnectState.connected
var userInfo: [String: Any] = [:]
userInfo["state"] = state
NotificationCenter.default.post(name: testNoteName, object: nil, userInfo: userInfo)
}
… rest of the view controller …
}
This didn’t crash. When I tap a button that calls post()
, the didReceiveTest(note:)
method runs and prints:
did receive test, note: name = com.example.Test750235.test, object = nil, userInfo = Optional([AnyHashable("state"): Test750235.MainViewController.ConnectState])
This is on iOS 14.8.
Please create a new test project, add this code, and try it on your iOS 14 test device. That’ll tell us whether my code is replicating the problem properly, or whether this is tied to your environment somehow. For example, I doubt that the difference between iOS 14.6 and 14.8 matters here, but it’s always possible.
Share and Enjoy
—
Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"