I have built a fully functioning flappy bird game but when I try to add a sound I can't even run the project because an error pops up before I can play the game. the error is:
thread 1 exc_bad_instruction (code=exc_i386_invop subcode=0x0)
import SpriteKit
import AVFoundation
class GameScene: SKScene {
var bird = SKSpriteNode()
var pipeUpTexture = SKTexture()
var pipeDownTexture = SKTexture()
var PipesMoveAndRemove = SKAction()
var sound = try? AVAudioPlayer(contentsOfURL: NSURL(fileURLWithPath: NSBundle.mainBundle().pathForResource("wingsSound", ofType: "waw")!))
let pipeGap = 150.0
override func didMoveToView(view: SKView) {
/* Setup your scene here */
sound!.play()
Related
I'm working on a webservice based app and I've come to a crashing hault due to sending requests too quickly to the webservice. I simply can not getting GCD working in Swift 3 and I'm scratching my head. I've decided to dumb it down and just try loading 4 web images to a web view in order. Based on everything I'm seeing online the following code should work, but it is still freezing the UI until all four images load. What am I doing wrong?
import UIKit
let imageURLs = ["http://www.planetware.com/photos-large/F/france-paris-eiffel-tower.jpg", "http://adriatic-lines.com/wp-content/uploads/2015/04/canal-of-Venice.jpg", "http://hd-wall-papers.com/images/wallpapers/hi-resolution-pictures/hi-resolution-pictures-5.jpg", "http://hd-wall-papers.com/images/wallpapers/hi-resolution-pictures/hi-resolution-pictures-1.jpg"]
class Downloader {
class func downloadImageWithURL(_ url:String) -> UIImage! {
let data = try? Data(contentsOf: URL(string: url)!)
return UIImage(data: data!)
}
}
class ViewController: UIViewController {
#IBOutlet weak var imageView1: UIImageView!
#IBOutlet weak var imageView2: UIImageView!
#IBOutlet weak var imageView3: UIImageView!
#IBOutlet weak var imageView4: UIImageView!
#IBOutlet weak var sliderValueLabel: UILabel!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
#IBAction func didClickOnStart(_ sender: AnyObject) {
let serialQueue = DispatchQueue(label: "syncQueue")
serialQueue.sync{
let img1 = Downloader.downloadImageWithURL(imageURLs[0])
DispatchQueue.main.async(execute: {
self.imageView1.image = img1
})
}
serialQueue.sync{
let img2 = Downloader.downloadImageWithURL(imageURLs[1])
DispatchQueue.main.async(execute: {
self.imageView2.image = img2
})
}
serialQueue.sync{
let img3 = Downloader.downloadImageWithURL(imageURLs[2])
DispatchQueue.main.async(execute: {
self.imageView3.image = img3
})
}
serialQueue.sync{
let img4 = Downloader.downloadImageWithURL(imageURLs[3])
DispatchQueue.main.async(execute: {
self.imageView4.image = img4
})
}
}
#IBAction func sliderValueChanged(_ sender: UISlider) {
self.sliderValueLabel.text = "\(sender.value * 100.0)"
}
}
freezing the UI
Because you are calling serialQueue.sync. You almost never want to call sync, and in this case you certainly don't. Use async instead.
this is the code :
import Foundation
import UIKit
import AVFoundation
class MP3PLAYER {
var player = AVPlayer()
func PLAY (){
player.play()
}
init ( url_ : String , autoplay_ : String , player_ : AVPlayer) {
player = player_
let url = url_
let playerItem = AVPlayerItem( url:URL( string:url )! )
player = AVPlayer(playerItem:playerItem)
player.rate = 1.0;
if autoplay_ == "YES" {
player.play()
print("autoplay is on")
}
}
}
In this code there is no error even warning.
Simply player wont play . If i put code direct in viewController than player working ...
I use class on this way in viewController:
<code>
import UIKit
import AVFoundation
class Mp3Stream_example: UIViewController {
var player = AVPlayer()
override func viewDidLoad() {
super.viewDidLoad()
let STREAM1 = MP3PLAYER(url_: "http://listen.181fm.com:181-soul_128k.mp3" , autoplay_: "YES" , player_ : player )
STREAM1.player.play()
//player.play()
.....
</code>
Your player, STREAM1, is going out of scope and is being deallocated, hence no sound. Make it a class member variable instead of a local variable. e.g.
class Mp3Stream_example: UIViewController {
let STREAM1 = MP3PLAYER(url_: "http://listen.181fm.com:181-soul_128k.mp3" , autoplay_: "YES" , player_ : AVPlayer() )
....
P.S. you've got extra AVPlayers that you don't need.
While Strings appears to be fine I'm having some trouble storing Integers into Core Data. Following tutorials and reading available information out there doesn't seem to be helping me who has no Objective-C background. (Swift seemed like a straight forward language like the languages I'm fluent with PHP/OOPHP/JavaScript/VBScript/... thus I started playing with it and so far have been able to do everything I wanted, almost)
What I want to do now is, to receive the JSON data and store it into Core Data
Here's my Core Data
Entity name: Category
Its Attributes:
id Int16
title String
description String
My Swift model? file: Category.swift
import CoreData
class Category: NSManagedObject {
#NSManaged var id: Int //should I declare this as Int16?
#NSManaged var title: String
#NSManaged var description: String
}
I'm using SwiftyJASON extension? and NSURLSession protocol? to get the data and to parse it as follow:
import UIKit
import CoreData
class ViewController: UIViewController {
let managedObjectContext = (UIApplication.sharedApplication().delegate as AppDelegate).managedObjectContext
override func viewDidLoad() {
super.viewDidLoad()
fetchData()
}
func fetchData() {
var url = NSURL.URLWithString("http://domain.com/index.php?r=appsync/read&id=category")
var session = NSURLSession.sharedSession()
session.dataTaskWithURL(url, completionHandler: {(data, response, error) in
// parse data into json
let json = JSONValue(data)
let entityDescription = NSEntityDescription.entityForName("Category", inManagedObjectContext: self.managedObjectContext)
let category = Category(entity: entityDescription, insertIntoManagedObjectContext: self.managedObjectContext)
for item in json.array! {
category.id = item["id"].string!.toInt()! //goes KABOOM!
category.title = item["title"].string!
category.description = item["description"].string!
managedObjectContext?.save(nil)
}
dispatch_async(dispatch_get_main_queue()) {
// do something
}
}).resume()
}
}
Let's assume the JASON data is:
[{"id":"1","title":"cat1","description":"blabala one"},{"id":"2","title":"cat2","description":"blabala two"}]
At line where it says category.id = item["id"].string!.toInt()! xCode goes KABOOM, what am I doing wrong here?
Notes/More questions:
I tried changing id type within Core Data to Int32 and then declaring it as just Int
in the model (and not Int16 or Int32) which reduced some errors but
xCode still crashes
Probably the way I'm looping stuff is not the best way to do this,
what's the better way of storing array of data into core data at
once?
Most of the tutorials I've seen there's no id's for Entities(tables), am I missing something here?
References:
SiftyJSON: https://github.com/lingoer/SwiftyJSON
Core Data tutorial:
http://rshankar.com/coredata-tutoiral-in-swift-using-nsfetchedresultcontroller/
EDIT > Working code:
Category.swift model file which can be auto generated using File>New>File>iOS>Core Data>NSManagedObject subclass [swift, no need for bridging header but you need to manually add #objc line as below]
import CoreData
#objc(Category) //Wouldn't work without this
class Category: NSManagedObject {
#NSManaged var id: NSNumber //has to be NSNumber
#NSManaged var title: String
#NSManaged var mydescription: String //"description" is reserved so is "class"
}
ViewController.swift
import UIKit
import CoreData
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
fetchData()
}
func fetchData() {
var url = NSURL.URLWithString("http://domain.com/index.php?r=appsync/read&id=category")
var session = NSURLSession.sharedSession()
session.dataTaskWithURL(url, completionHandler: {(data, response, error) in
let json = JSONValue(data)
let managedObjectContext = (UIApplication.sharedApplication().delegate as AppDelegate).managedObjectContext //this line had to be moved here
let entityDescription = NSEntityDescription.entityForName("Category", inManagedObjectContext: managedObjectContext)
for item in json.array! {
let category = Category(entity: entityDescription, insertIntoManagedObjectContext: managedObjectContext) //this line has to be in inside for loop
category.id = item["id"].string!.toInt()!
category.title = item["title"].string!
category.mydescription = item["description"].string!
managedObjectContext?.save(nil)
}
dispatch_async(dispatch_get_main_queue()) {
// do something
}
}).resume()
}
}
Sample fetching data code:
func requestData() {
let appDel:AppDelegate = UIApplication.sharedApplication().delegate as AppDelegate
let context:NSManagedObjectContext = appDel.managedObjectContext!
var request = NSFetchRequest(entityName: "Category")
request.returnsObjectsAsFaults = false
var results:NSArray = context.executeFetchRequest(request, error: nil)
//println(results)
for category in results {
var cat = category as Category
println("\(cat.id),\(cat.title),\(cat.mydescription)")
}
}
P.S. Make sure to Clean your project and delete the app from simulator after changing Model
Scalar types (integers, floats, booleans) in core data are broken in the current Swift beta (5). Use NSNumber for the properties, and file a radar.
object.intProperty = NSNumber(int:Int(item["id"] as String))
(Typed on the phone, so sorry if that's wrong, and I know it's disgusting code - hence, file a radar!)
Or, in your specific case, looking at the JSON, use String. Those IDs are coming in as strings anyway.
Updated for Swift 2
If your JSON data is really of type [[String:String]], you can use the following code in order to set category.id:
if let unwrappedString = item["id"], unwrappedInt = Int(unwrappedString) {
category.id = unwrappedInt
}
This is the code i'm using:
var aSound = NSURL(fileURLWithPath: NSBundle.mainBundle().pathForResource("abc", ofType: "mp3"))
var audioPlayer = AVAudioPlayer()
println(aSound)
audioPlayer = AVAudioPlayer(contentsOfURL: aSound, error: nil)
audioPlayer.prepareToPlay()
audioPlayer.play()
I'm trying to print the path of the file and this is what I see in the console.
file:///Users/<username>/Library/Developer/CoreSimulator/Devices/<some GUID>/data/Containers/Bundle/Application/<some different GUID>/HelloWorld.app/abc.mp3
I have added the mp3 to my project by doing an "Add Files to project" from the menu.
Does it get added to the location above automatically when I run the simulator?
import UIKit
import AVFoundation
class ViewController: UIViewController {
var audioPlayer = AVAudioPlayer()
override func viewDidLoad() {
super.viewDidLoad()
var alertSound = NSURL(fileURLWithPath: NSBundle.mainBundle().pathForResource("fileName", ofType: "extension"))
println(alertSound)
AVAudioSession.sharedInstance().setCategory(AVAudioSessionCategoryPlayback, error: nil)
AVAudioSession.sharedInstance().setActive(true, error: nil)
var error:NSError?
audioPlayer = AVAudioPlayer(contentsOfURL: alertSound, error: &error)
audioPlayer.prepareToPlay()
audioPlayer.play()
}
}
var audio: AVAudioPlayer = AVAudioPlayer()
#IBAction func playaudio(sender: AnyObject) //method for playing audio {
var audioPath = NSString(string: NSBundle.mainBundle().pathForResource("bus", ofType: "mp3")!)
var error: NSError? = nil
//instantiate the player
audio = AVAudioPlayer(contentsOfURL: NSURL(string: audioPath as String), error: &error)
audio.prepareToPlay()
audio.play()
}
override func viewDidLoad()
{
super.viewDidLoad()
// Do any additional setup after loading the view.
}
And don't forget to import AVFoundation Framework.
Use This Function to make sound in Swift (You can use this function where you want to make sound.)
First Add SpriteKit Framework.
import SpriteKit
func playEffectSound(filename: String){
runAction(SKAction.playSoundFileNamed("\(filename)", waitForCompletion: false))
}
// use this function to play sound
playEffectSound("Sound File Name With Extension")
// Example :- playEffectSound("BS_SpiderWeb_CollectEgg_SFX.mp3")
Ok so the problem actually occurs once the code bit var context: NSManagedObjectContext = appDel.managedObjectContext is run I commented it out to confirm that it was that line and it was please note this is my first time learning iOS programming so please try to be as specific as possible in your answer thank you :)
import UIKit
import CoreData
class SecondViewController: UIViewController, UITextFieldDelegate {
#IBOutlet var txtName : UITextField
#IBOutlet var txtDesc : UITextField
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
override func touchesBegan(touches: NSSet!, withEvent event: UIEvent!) {
self.view.endEditing(true)
}
#IBAction func hitAdd(sender : UIButton) {
glTask.newTask(txtName.text, desc: txtDesc.text)
txtName.text = ""
txtDesc.text = ""
self.view.endEditing(true)
self.tabBarController.selectedIndex = 0
var appDel: AppDelegate = (UIApplication.sharedApplication().delegate as AppDelegate)
Right here V
var context: NSManagedObjectContext = appDel.managedObjectContext
This crashes the app once button is pressed ^
The code error message is fatal error Cant unwrap Optional.None
var newTask = NSEntityDescription.insertNewObjectForEntityForName("Tasks", inManagedObjectContext: context) as NSManagedObject
newTask.setValue("test task", forKey: "myTask")
newTask.setValue("test Description", forKey: "myDesc")
context.save(nil)
//println(newTask)
println("Task was saved.")
}
// UITextField Delegate
func textFieldShouldReturn(textField: UITextField!) -> Bool {
textField.resignFirstResponder()
return true
}
}
Looking at the Core Data stack in Swift, managedObjectContext is implemented like this:
var managedObjectContext: NSManagedObjectContext {
if !_managedObjectContext {
let coordinator = self.persistentStoreCoordinator
if coordinator != nil {
_managedObjectContext = NSManagedObjectContext()
_managedObjectContext!.persistentStoreCoordinator = coordinator
}
}
return _managedObjectContext!
}
var _managedObjectContext: NSManagedObjectContext? = nil
As you can see it is backed by an Optional.
The place where this can go wrong is here:
_managedObjectContext = NSManagedObjectContext()
_managedObjectContext!.persistentStoreCoordinator = coordinator
if NSManagedObjectContext() returns a nil, then the backing _managedObjectContext will be nil and you will get this crash at the line where you unwrap it return _managedObjectContext!
To debug this, dig deeper down the stack, its most likely failing to initialize the object model or persistant store, and thus returning nil to you.
Edit:
In the definiton of the getter for var persistentStoreCoordinator: NSPersistentStoreCoordinator
They provide a location (the wall of comments) where you should debug this exact type of issue.
Not sure if OP ever figured this out, but I had a similar issue and realized that the code I copied from another app's AppDelegate was using the project name of that app and that I had forgot to change this line: let modelURL = NSBundle.mainBundle().URLForResource("CoreData", withExtension: "momd") to use "CoreData" instead of the "test" it had from another project.