Well I was experiencing same Issue , It sounds like this was not supported before or not doable to play custom sound for local notification that is not included in App Bundle. But later this is supported and you can assign custom sounds from App container specifically in Library/Sounds directory . And it worked with me . you can either download sounds from server to this directory or test it by copying a .caf(Apple said other extensions may work) file from bundle to Library/sounds directory and then remove reference for the file from bundle so that you can make sure that if sounds played it is from directory out of bundle . This all works very well , the main issue with me if user force quoted the app it stops working for local notification while it still works with push kit notifications , Im scheduling local one though when push kit push arrives.
Here is the code for testing playing sound from directory :
func copyFileToDirectoryFromBundle()
{
// get reference to library directory
let LibraryDirectoryPaths = NSSearchPathForDirectoriesInDomains(NSSearchPathDirectory.LibraryDirectory, NSSearchPathDomainMask.UserDomainMask, true)
// see what is in there
for path in LibraryDirectoryPaths
{
print("di=\(path)")
}
// prepare for sound directory
let libraryDirectoryPath: AnyObject = LibraryDirectoryPaths[0]
let soundsDirectoryPath = libraryDirectoryPath.stringByAppendingPathComponent("Sounds")
// create sounds directory under library if not there already
if !NSFileManager.defaultManager().fileExistsAtPath(soundsDirectoryPath)
{
do {
try NSFileManager.defaultManager().createDirectoryAtPath(soundsDirectoryPath, withIntermediateDirectories: false, attributes: nil)
print("sounds library created,,,")
} catch let error as NSError {
print("creating sounds directory error = \(error.localizedDescription)");
}
}
else
{
print("Sounds directory is there already under Library")
}
do {
// sounds directory should have been added under library
let directoryContents = try NSFileManager.defaultManager().contentsOfDirectoryAtURL( NSURL(string: libraryDirectoryPath as! String)!, includingPropertiesForKeys: nil, options: [])
print("Library directs=\(directoryContents)")
// prepare for adding subdirectory with file name from bundle
// here is where you should save files if downloaded from server
// here im just moving one from bundle
let subDirectoryPath = directoryContents.last!
if let pathFromBundle = NSBundle.mainBundle().pathForResource("notification", ofType:"caf") {
let myFilePathUnderSounds = "\(subDirectoryPath.path!)\("/notification.caf")"
if !NSFileManager.defaultManager().fileExistsAtPath(myFilePathUnderSounds)
{
do {
print("bundle path=\(pathFromBundle)and datacontainer path=\(subDirectoryPath.path!)")
try NSFileManager.defaultManager().copyItemAtPath(pathFromBundle, toPath:myFilePathUnderSounds )
print("item copied")
} catch let error as NSError {
print(error.localizedDescription);
}
}
else
{
print("Your file from bundle path = \(pathFromBundle) is already there under Sounds")
}
}
else
{
print("Item not found in bundle")
}
// see item there after you add it
let subDirectories = try NSFileManager.defaultManager().contentsOfDirectoryAtURL( subDirectoryPath, includingPropertiesForKeys: nil, options: [])
print("files under sounds")
for fileDirectory in subDirectories
{
print(fileDirectory)
}
} catch let error as NSError {
print(error.localizedDescription)
}
}
After making sure .caf file is under Library/Sounds directory . All you have to do is merely assigning file name with extension to local notification soundName property like if the file is in bundle.