Try explicitly setting "content-available" to 1 (integer) (as noted by many others), leave out the alert key, AND the sound entry to an empty string. That made the difference for me, after a rather exhaustive diagnostic session. I was omitting the sound entry and it never worked. I tried setting a sound file name and it never worked. Setting it to an empty string ( "" ) worked fine when accompanied by content-available and omitting the alert key.
Printing what I receive (as seen below with my various diagnostic print statements) showed: ["sound": , "content-available": 1, "badge": 0]
guard let aps = userInfo["aps"] as? [String: AnyObject] else {
print( "Incoming failed" )
completionHandler(.failed)
return
}
print( aps )
print( "INCOMING" )