I am developing with audioQueueService
But stop in function "CFURLCreateFromFileSystemRepresentation"
here is my code but always get nil for return.
var path = Bundle.main.path(forResource: "123", ofType: "mp3")!
var xyz = UInt8(path.utf8CString[0])
let audioFileURL = CFURLCreateFromFileSystemRepresentation(kCFAllocatorDefault,&xyz, path.characters.count, false)
print(audioFileURL)
I had try post path's point to func but not work?
can anyone help me?
let url = Bundle.main.url(forResource: "123", withExtension: "mp3")!
let audioFileURL = url as CFURL
Related
I am trying to make a morse code converter in a swift playground. I got the conversion to work, but I need to make the code "speak" with AVFoundation. How can I decode the morse code string to play the short beep for every '.' and the long beep for every '-'?
Here's my code so far:
func speakTheCode(message: String) {
var speaker = AVAudioPlayer()
let longBeep = URL(fileURLWithPath: Bundle.main.path(forResource: "beep_long", ofType: "mp3")!)
let shortBeep = URL(fileURLWithPath: Bundle.main.path(forResource: "beep_short", ofType: "mp3")!)
try! speaker = AVAudioPlayer(contentsOf: longBeep)
try! speaker = AVAudioPlayer(contentsOf: shortBeep)
speaker.prepareToPlay()
}
Just try to decode the string to the correspondingly audio.
func speakTheCode(message: String) {
var audioItems: [AVPlayerItem] = []
guard let longPath = Bundle.main.path(forResource: "beep_long", ofType: "mp3"),
let shortPath = Bundle.main.path(forResource: "beep_short", ofType: "mp3") else {
print("Path is not availabel")
return
}
let longBeep = AVPlayerItem(url: URL(fileURLWithPath: longPath))
let shortBeep = AVPlayerItem(url: URL(fileURLWithPath: shortPath))
for character in message.characters {
if character == Character("-") {
audioItems.append(longBeep)
} else if character == Character(".") {
audioItems.append(shortBeep)
}
}
let player = AVQueuePlayer(items: audioItems)
player.play()
}
speakTheCode(message: "..--..")
I'm new to swift and have a lot of repeating code. For example how would you change the following code into different functions:
Example 1
if let button = view.viewWithTag(12) as? UIButton {
// change any properties of the button as you would normally do
button.isHidden = true
}
Example 2
var oneAPlayer = AVAudioPlayer()
var oneBPlayer = AVAudioPlayer()
var oneCPlayer = AVAudioPlayer()
var oneDPlayer = AVAudioPlayer()
var twoAPlayer = AVAudioPlayer()
var threeAPlayer = AVAudioPlayer()
var fourAPlayer = AVAudioPlayer()
let oneASound = Bundle.main.path(forResource: "1-a", ofType: "mp3")
let oneBSound = Bundle.main.path(forResource: "1-b", ofType: "mp3")
let oneCSound = Bundle.main.path(forResource: "1-c", ofType: "mp3")
let oneDSound = Bundle.main.path(forResource: "1-d", ofType: "mp3")
let twoASound = Bundle.main.path(forResource: "2-a", ofType: "mp3")
let threeASound = Bundle.main.path(forResource: "3-a", ofType: "mp3")
let fourASound = Bundle.main.path(forResource: "4-a", ofType: "mp3")
I wouldn't necessarily use a new function for this. I would write it like so:
let soundNames = ["1-a", "1-b", "1-c", "1-d", "2-a", "3-a", "4-a"]
let sounds = soundNames.map{ Bundle.main.path(forResource: $0, ofType: "mp3") }
Alex answer is good, but it's pretty complicated for someone new. I would suggest learning the basics of functions before attempting functional programming (usage of .map, .filter, and other fun stuff).
Here is a simple example that you can modify in numerous ways to be more flexible if desired:
var sounds: [String:String] = [:]
func addSound(_ num: Int,_ letter: Character) {
let key = String(num) + "-" + String(letter)
sounds[key] = Bundle.main.path(forResource: key, ofType: "mp3")
}
// Usage:
addSound(1,"a")
print(sounds["1-a"])
What we are doing is using just one variable to hold the sounds in... You access your different sounds by typing in the string, as demonstrated in the usage section.
This is a dictionary, and they are very powerful. They work based on Key and Value.
So here we have key of "1-a" and the value will be the bundle that we added in the function.
The function basically just converts the input parameters, an integer and a Character, and turns it into a string that we can use with our Bundle and Dictionary.
If you want to add many sounds at one time, you can convert this to an array:
func addSounds(_ keys: [String]) {
for key in keys {
sounds[key] = Bundle.main.path(forResource: key, ofType: "mp3")
}
}
// Usage:
addSounds( ["1-a", "1-b"])
print( sounds["1-b"])
This second example is exactly what Alex did, his version used .map which is actually a function that does basically the same thing as the for loop. It's a great feature, but it focuses on what's called declarative programming --which is great--but generally difficult to learn when just starting out.
I'm trying to play a sound based on file name. I created an enum with all file names. Everything works, except this case, where I check for the soundType.click
func playSound(type: soundType) {
var soundUrl = URL.init(fileURLWithPath: Bundle.main.path(forResource: type.rawValue, ofType: "aiff")!)
if type.rawValue == soundType.click.rawValue {
soundUrl = URL.init(fileURLWithPath: Bundle.main.path(forResource: type.rawValue, ofType: "wav")!)
}
do {
audioPlayer = try AVAudioPlayer(contentsOf: soundUrl)
audioPlayer.play()
} catch _ { }
}
And here is my enum
enum soundType: String {
case selectAnswer = "answerSelected"
case correctAnswer = "correctAnswer"
case wrongAnswer = "wrongAnswer"
case click = "click"
}
The problem is here where I check for "type.rawValue == soundType.click.rawValue"
Here is the error
fatal error: unexpectedly found nil while unwrapping an Optional value
You should take a look at this line of code first.
var soundUrl = URL.init(fileURLWithPath: Bundle.main.path(forResource: type.rawValue, ofType: "aiff")!)
soundUrl = URL.init(fileURLWithPath: Bundle.main.path(forResource: type.rawValue, ofType: "wav")!)
Here, you are force unwrapping a failable initializer. You should check if Bundle.main.path(forResource: type.rawValue, ofType: "aiff")!) exists first by doing something like this...
if let soundUrl = URL.init(fileURLWithPath: Bundle.main.path(forResource: type.rawValue, ofType: "aiff")){
if type.rawValue == soundType.click.rawValue {
...
}
or you could also use a guard statement..
Check this blog post by Natashtherobot to learn more about how to unwrap stuff well. https://www.natashatherobot.com/swift-guard-better-than-if/
I have a plist running in my project which contains number of image urls.I am trying to pass the url image to my imageView which is in the same viewController.I found similar questions from github like Loading/Downloading image from URL on Swift , Swift - Read plist , Can't get plist URL in Swift I went through all those answers but no luck so far rather than fatal crash. My partial codes as follows....
Method 1:
override func viewDidLoad() {
super.viewDidLoad()
if let path = Bundle.main.path(forResource: "apps", ofType: "plist"),
let root = (NSArray(contentsOfFile: path))
{
let url = NSURL(string: path)
let data = NSData(contentsOf: url! as URL)
if let imageData = data {
imageView.image = UIImage(data: imageData as Data)
}
**// Swift Console Printinging as Follows**
print(root)
// printing all my plist url links like {icon = "https://xxxxxxxxxxx.com/image/girl_face_freckles_eyes_92358_1920x1080.jpg";}
print(url)
// (/Users/xxxxxx/Library/Developer/CoreSimulator/Devices/52DA3F73-83E0-4C29-9DE1-D8D5F0731C13/data/Containers/Bundle/Applica ... ps.plist)
print(data)
// nil
print(imageView.image)
//nil
} else {
print("Either the file does not exist or the root object is an array")
}
Method 2:
let path = Bundle.main.path(forResource: "apps", ofType: "plist")
let url = NSURL(string: path!)
let imgData = try? Data(contentsOf: url as! URL)
let img = UIImage(data: imgData!)!
print(img) // fatal crash
}
path is the path to your plist, not to your image URL.
The image URL is in the key "icon" in the "root" array.
Get the first item of the array and subscript with the key, you should get your image URL:
if let item = root[0] as? [String:Any] {
if let result = item["icon"] as? String {
print(result)
}
}
The path in (NS)Bundle is a file system path and these paths must be created with URL(fileURLWithPath:)
let path = Bundle.main.path(forResource: "apps", ofType: "plist")
let url = URL(fileURLWithPath: path!)
But why does nobody use the URL related API which is much more convenient
let url = Bundle.main.url(forResource: "apps", withExtension: "plist")
I have a code which loads some thumbnails from articles retrieved online and places them into an Article object. It looks like the following:
for article in newArticlesArray {
let url: String
if let myGroup = article["group"] as? Dictionary<NSObject, AnyObject>, let myThumbnail = myGroup["thumbnail"] as? Dictionary<NSObject, AnyObject>, let myURL = myThumbnail["url"] as? String{
url = myURL
}
else{
url = "file://no-thumbnail.png"
}
let a = Article(t: article["title"] as! String,
da: article["pubDate"] as! String,
de: newDesc,
th: NSURL(string: url)!,
l: NSURL(string: article["link"] as! String)!)
articlesArray.addObject(a)
However the issue arises when an article does not have a thumbnail and hence I have to use a local image. The local file for no thumbnail is called no-thumbnail.png, however I cannot seem to find a simple guide online on how to actually reference a local file, in this case a .png image, through the usage of an NSURL in swift.
Looking for somebody to share some insight into this.
Solution
For people interested the solution is as follows:
let th = NSBundle.mainBundle().URLForResource("no-thumbnail", withExtension: "png")
url = th!.absoluteString
You can use Bundle.main.url(forResource: "no-thumbnail", withExtension: "png")
The syntax has changed a bit for Swift 4:
let imageURL = Bundle.main.url(forResource: "imageName", withExtension: "png")