I get NSIndexPath array from UITableViewController and NSIndexPath of a specific file. I get mp3 files from the document folder in NSIndexPath array and I get a specific file from the selected row from UITableViewCell in a NSIndexPath file.
I want to switch mp3 files for it need change NSIndexPath in UIViewController is which plays music. Or is there different methods are which switching mp3 files from document folder?
The UITableViewController code
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
var playerVC = (segue.destinationViewController as! UINavigationController).topViewController as! PlayMusicViewController
var indexPath = tableView.indexPathForSelectedRow()
var nameOfObjectForPass = listOfMP3Files![indexPath!.row] // default it's name and
var fileManager = NSFileManager.defaultManager()
var wayToFile = fileManager.URLsForDirectory(NSSearchPathDirectory.DocumentDirectory, inDomains: NSSearchPathDomainMask.UserDomainMask)
var passMusicFileURL: NSURL? // for pass mp3
if let documentPath: NSURL = wayToFile.first as? NSURL {
let musicFile = documentPath.URLByAppendingPathComponent(nameOfObjectForPass)
println(musicFile)
passMusicFileURL = musicFile
}
var currentTrackIndex = tableView.indexPathForSelectedRow()!
var allIndexTable = tableView.indexPathsForVisibleRows()! as! [NSIndexPath]
if segue.identifier == "listenMusic" {
playerVC.nameMusicFile = nameOfObjectForPass // name
playerVC.mp3URL = passMusicFileURL
// test
playerVC.currentIndex = currentTrackIndex
playerVC.allIndex = allIndexTable
}
}
The UIViewController code
var currentIndex: NSIndexPath!
var allIndex = [AnyObject]() as! [NSIndexPath]
func playNextSound() {
println("index \(currentIndex)")
println("all object \(allIndex)")
var indextFound = find(allIndex, currentIndex)
println("index found \(indextFound)")
}
The code is which plays music
func playMusic() {
AVAudioSession.sharedInstance().setCategory(AVAudioSessionCategoryPlayback, error: nil) // == true
AVAudioSession.sharedInstance().setActive(true, error: nil)
var error: NSError?
audioPlayer = AVAudioPlayer(contentsOfURL: mp3URL, error: &error)
// audioPlayer.prepareToPlay()
if currentPause == nil {
} else {
audioPlayer.currentTime = currentPause
}
//
audioPlayer.volume = 0.5
audioPlayer.play()
}
I get following results in the console
index {length = 2, path = 0 - 0} it is current object
it is all object from document folder
all object [ {length = 2, path = 0 - 0}, {length = 2, path = 0 - 1}]
var newURL: NSURL!
#IBAction func nextTrack(sender: UIButton) {
println("touched next")
var nowRow: Int = self.currentRow
var maxCount = self.arrayOfMP3.count-1 // -1
if nowRow < maxCount {
nowRow = self.currentRow++
println("plus")
} else if nowRow == arrayOfMP3.endIndex {
nowRow = maxCount
println("equals")
}
// for play/pause button setting
currentPause = nil
//println("current pause\(currentPause)")
next = false
//
println("current row \(currentRow)")
println("end index \(arrayOfMP3.endIndex)")
var nextTrack = arrayOfMP3![nowRow]
var nextDirectory = fileManager.URLsForDirectory(NSSearchPathDirectory.DocumentDirectory, inDomains: NSSearchPathDomainMask.UserDomainMask)
if var nextURL: NSURL = nextDirectory.first as? NSURL {
newURL = nextURL.URLByAppendingPathComponent(nextTrack)
}
var nameArtist: String!
var nameSong: String!
var imageString: NSData!
var itemPlayer = AVPlayerItem(URL: newURL)
var listMetaData = itemPlayer.asset.commonMetadata as! [AVMetadataItem]
for item in listMetaData {
if item.commonKey == "title" {
nameSong = item.stringValue
}
if item.commonKey == "artist" {
nameArtist = item.stringValue
}
if item.commonKey == "album" {
item.stringValue
}
if item.commonKey == "artwork" {
imageString = item.dataValue
}
}
nameLabel?.text = "\(nameArtist) \(nameSong)"
if imageString != nil {
imageView?.image = UIImage(data: imageString)
} else {
imageView?.image = nil
}
tapButtonPlay = false
playMusic()
}
Related
The application uses iCloud to store the objects conformed to Codable protocol using NSKeyedArchiver/NSKeyedUnarchiver.
Synchronization between devices is OK, except when the application is reinstalled on the device (or installed on a new device) and the file with data exists – in this case
NSKeyedUnarchiver.unarchiveObject(withFile: filePathe) return nil.
How to get data from an existing file from the iCloud when I install the application on a new device (reinstall on the same device)?
class ViewController: UIViewController {
#IBOutlet weak var nameLabel: UILabel!
#IBOutlet weak var weightLabel: UILabel!
#IBOutlet weak var nameTextField: UITextField!
#IBOutlet weak var weightTextField: UITextField!
var iCloudContainer: URL? {
return FileManager().url(forUbiquityContainerIdentifier: nil)
}
func getFilePath(container: URL, fileName: String) -> String {
let filePath = container.appendingPathComponent(fileName).path
return filePath
}
override func viewDidLoad() {
super.viewDidLoad()
}
#IBAction func fetchButtonPressed(_ sender: UIButton) {
let container = self.iCloudContainer
let filePathe = getFilePath(container: container!, fileName: "Person")
if let jsonData = NSKeyedUnarchiver.unarchiveObject(withFile: filePathe) as? Data {
if let person = try? JSONDecoder().decode(Person.self, from: jsonData) {
nameLabel.text = person.name
weightLabel.text = String(person.weight)
} else {
nameLabel.text = "No data loaded"
weightLabel.text = "No data loaded"
}
} else {
nameLabel.text = "No data loaded"
weightLabel.text = "No data loaded"
}
}
#IBAction func saveButtonPressed(_ sender: UIButton) {
let container = self.iCloudContainer
let filePathe = getFilePath(container: container!, fileName: "Person")
let person = Person(name: nameTextField.text!, weight: Double(weightTextField.text!)!)
let jsonData = try? JSONEncoder().encode(person)
NSKeyedArchiver.archiveRootObject(jsonData!, toFile: filePathe)
}
To get data from iCloud container to your local UbiquityContainer you should use NSMetadata to find and download items from iCloud to device.
lazy var metadataQuery : NSMetadataQuery = {
let query = NSMetadataQuery()
query.searchScopes = [NSMetadataQueryUbiquitousDocumentsScope]
query.predicate = NSPredicate(format: "%K CONTAINS %#", NSMetadataItemFSNameKey, "List")
NotificationCenter.default.addObserver(self, selector: #selector(didFinishGathering), name: NSNotification.Name.NSMetadataQueryDidUpdate, object: query)
NotificationCenter.default.addObserver(self, selector: #selector(didFinishGathering), name: NSNotification.Name.NSMetadataQueryDidFinishGathering, object: query)
return query
}()
override func viewDidLoad() {
super.viewDidLoad()
self.metadataQuery.start()
}
deinit {
NotificationCenter.default.removeObserver(self)
}
#objc func didFinishGathering(notification: Notification?) {
let query = notification?.object as? NSMetadataQuery
query?.enumerateResults { (item: Any, index: Int, stop: UnsafeMutablePointer<ObjCBool>) in
let metadataItem = item as! NSMetadataItem
if isMetadataItemDownloaded(item: metadataItem) == false {
let url = metadataItem.value(forAttribute: NSMetadataItemURLKey) as! URL
try? FileManager.default.startDownloadingUbiquitousItem(at: url)
}
}
guard let queryresultsCount = query?.resultCount else { return }
for index in 0..<queryresultsCount {
let item = query?.result(at: index) as? NSMetadataItem
let itemName = item?.value(forAttribute: NSMetadataItemFSNameKey) as! String
let container = filesCoordinator.iCloudContainer
let filePath = filesCoordinator.getFilePath(container: container!, fileName: "TaskList")
let addressPath = filesCoordinator.getFilePath(container: container!, fileName: "CategoryList")
if itemName == "TaskList" {
if let jsonData = NSKeyedUnarchiver.unarchiveObject(withFile: filePath) as? Data {
if let person = try? JSONDecoder().decode(Person.self, from: jsonData) {
nameLabel.text = person.name
weightLabel.text = String(person.weight)
} else {
nameLabel.text = "NOT decoded"
weightLabel.text = "NOT decoded"
}
} else {
nameLabel.text = "NOT unarchived"
weightLabel.text = "NOT unarchived"
}
} else if itemName == "CategoryList" {
if let jsonData = NSKeyedUnarchiver.unarchiveObject(withFile: addressPath) as? Data {
if let address = try? JSONDecoder().decode(Address.self, from: jsonData) {
streetLabel.text = address.street
houseLabel.text = String(address.house)
} else {
streetLabel.text = "NOT decoded"
houseLabel.text = "NOT decoded"
}
} else {
streetLabel.text = "NOT unarchived"
houseLabel.text = "NOT unarchived"
}
}
}
}
func isMetadataItemDownloaded(item : NSMetadataItem) -> Bool {
if item.value(forAttribute: NSMetadataUbiquitousItemDownloadingStatusKey) as? String == NSMetadataUbiquitousItemDownloadingStatusCurrent {
return true
} else {
return false
}
}
#IBAction func saveButtonPressed(_ sender: UIButton) {
let container = filesCoordinator.iCloudContainer
let personPath = filesCoordinator.getFilePath(container: container!, fileName: "TaskList")
let addressPath = filesCoordinator.getFilePath(container: container!, fileName: "CategoryList")
let person = Person(name: nameTextField.text!, weight: Double(weightTextField.text!)!)
let jsonPersonData = try? JSONEncoder().encode(person)
NSKeyedArchiver.archiveRootObject(jsonPersonData!, toFile: personPath)
let address = Address(street: streetTextField.text!, house: Int(houseTextField.text!)!)
let jsonAddressData = try? JSONEncoder().encode(address)
NSKeyedArchiver.archiveRootObject(jsonAddressData!, toFile: addressPath)
}
}// end of the class
I was doing the weather app, everything was fine until I add the CAGradientLayer transition to UIView. It still worked but the transition took so long, around 10-15 seconds. I'm using the Apixu API for the weather. One thing to notice is the audio was perfectly playing, right away. I have checked the duration and there was nothing wrong with animation:
import UIKit
import AVFoundation
class ViewController: UIViewController, UISearchBarDelegate {
#IBOutlet weak var searchBar: UISearchBar!
#IBOutlet weak var cityLbl: UILabel!
#IBOutlet weak var conditionLbl: UILabel!
#IBOutlet weak var degreeLbl: UILabel!
#IBOutlet weak var imgView: UIImageView!
#IBOutlet weak var gradientView: UIView!
let gradientLayer = CAGradientLayer()
let gradientLayer2 = CAGradientLayer()
let gradientLayer3 = CAGradientLayer()
var degree: Int!
var condition: String!
var imgURL: String!
var city: String!
var exists: Bool = true
var audioPlayer1 = AVAudioPlayer()
var audioPlayer2 = AVAudioPlayer()
var audioPlayer3 = AVAudioPlayer()
var audioPlayerSunny = AVAudioPlayer()
var audioPlayerSnow = AVAudioPlayer()
var audioPlayerThunder = AVAudioPlayer()
// Audio part.
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
gradientLayer.frame = gradientView.bounds
gradientLayer.colors = [UIColor.blue.cgColor, UIColor.black.cgColor]
gradientView.layer.insertSublayer(gradientLayer, at: 0)
//gradient color view
gradientLayer2.colors = [UIColor.red.cgColor, UIColor.purple.cgColor]
//gradient color view 2
gradientLayer3.colors = [UIColor.orange.cgColor, UIColor.green.cgColor]
//gradient color view 3
searchBar.delegate = self
// Audio Code starts.
do {
audioPlayer1 = try AVAudioPlayer(contentsOf: URL.init(fileURLWithPath: Bundle.main.path(forResource: "ambiance", ofType: "mp3")!))
audioPlayer1.prepareToPlay()
audioPlayer2 = try AVAudioPlayer(contentsOf: URL.init(fileURLWithPath: Bundle.main.path(forResource: "guitar", ofType: "mp3")!))
audioPlayer2.prepareToPlay()
audioPlayer3 = try AVAudioPlayer(contentsOf: URL.init(fileURLWithPath: Bundle.main.path(forResource: "rain", ofType: "mp3")!))
audioPlayer3.prepareToPlay()
audioPlayerSunny = try AVAudioPlayer(contentsOf: URL.init(fileURLWithPath: Bundle.main.path(forResource: "sunny", ofType: "mp3")!))
audioPlayerSunny.prepareToPlay()
audioPlayerSnow = try AVAudioPlayer(contentsOf: URL.init(fileURLWithPath: Bundle.main.path(forResource: "snow", ofType: "mp3")!))
audioPlayerSnow.prepareToPlay()
audioPlayerThunder = try AVAudioPlayer(contentsOf: URL.init(fileURLWithPath: Bundle.main.path(forResource: "thunder", ofType: "mp3")!))
audioPlayerThunder.prepareToPlay()
}
catch {
print(error)
} // Audio Code ends.
}
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
searchBar.resignFirstResponder()
}
func searchBarSearchButtonClicked(_ searchBar: UISearchBar) {
searchBar.resignFirstResponder()
let urlRequest = URLRequest(url: URL(string: "http://api.apixu.com/v1/current.json?key=494942fa74444eabb6973325170510&q=\(searchBar.text!.replacingOccurrences(of: " ", with: "%20"))")!)
let task = URLSession.shared.dataTask(with: urlRequest) { (data, response, error) in
if error == nil {
do {
let json = try JSONSerialization.jsonObject(with: data!, options: .mutableContainers) as! [String : AnyObject]
if let current = json["current"] as? [String : AnyObject] {
if let temp = current["temp_c"] as? Float {
self.degree = Int(temp.rounded())
}
if let condition = current["condition"] as? [String : AnyObject] {
self.condition = condition["text"] as! String
let icon = condition["icon"] as! String
self.imgURL = "http:\(icon)"
}
}
if let location = json["location"] as? [String : AnyObject] {
self.city = location["name"] as! String
}
if let _ = json["error"] {
self.exists = false
}
if self.condition == "Sunny" || self.condition == "Clear" {
self.audioPlayerSunny.currentTime = 0
self.audioPlayerSunny.play()
self.audioPlayer1.stop()
self.audioPlayer3.stop()
self.audioPlayer2.stop()
self.audioPlayerSnow.stop()
self.audioPlayerThunder.stop()
// Audio Code.
let colorChangeAnimation = CABasicAnimation(keyPath: "colors")
colorChangeAnimation.duration = 1.0
colorChangeAnimation.toValue = self.gradientLayer3.colors
colorChangeAnimation.fillMode = kCAFillModeForwards
colorChangeAnimation.isRemovedOnCompletion = false
self.gradientLayer.add(colorChangeAnimation, forKey: "colorChange")
//effects
} else if self.condition.lowercased().range(of:"cloudy") != nil || self.condition.lowercased().range(of:"overcast") != nil {
self.audioPlayer1.currentTime = 0
self.audioPlayer1.play()
self.audioPlayer2.stop()
self.audioPlayer3.stop()
self.audioPlayerSnow.stop()
self.audioPlayerSunny.stop()
self.audioPlayerThunder.stop()
// Audio Code.
let colorChangeAnimation = CABasicAnimation(keyPath: "colors")
colorChangeAnimation.duration = 1.0
colorChangeAnimation.toValue = self.gradientLayer2.colors
colorChangeAnimation.fillMode = kCAFillModeForwards
colorChangeAnimation.isRemovedOnCompletion = false
self.gradientLayer.add(colorChangeAnimation, forKey: "colorChange")
//effects
} else if self.condition.lowercased().range(of:"snow") != nil || self.condition.lowercased().range(of:"snowy") != nil || self.condition.lowercased().range(of:"sleet") != nil
{
self.audioPlayerSnow.currentTime = 0
self.audioPlayerSnow.play()
self.audioPlayer2.stop()
self.audioPlayer3.stop()
self.audioPlayer1.stop()
self.audioPlayerSunny.stop()
self.audioPlayerThunder.stop()
// Audio Code.
} else if self.condition.lowercased().range(of:"rain") != nil || self.condition.lowercased().range(of:"rainy") != nil || self.condition.lowercased().range(of:"drizzle") != nil
{
self.audioPlayer3.currentTime = 0
self.audioPlayer3.play()
self.audioPlayer2.stop()
self.audioPlayer1.stop()
self.audioPlayerSnow.stop()
self.audioPlayerSunny.stop()
self.audioPlayerThunder.stop()
// Audio Code.
} else if self.condition.lowercased().range(of:"thunder") != nil || self.condition.lowercased().range(of:"thundery") != nil {
self.audioPlayerThunder.currentTime = 0
self.audioPlayerThunder.play()
self.audioPlayer2.stop()
self.audioPlayer3.stop()
self.audioPlayerSnow.stop()
self.audioPlayerSunny.stop()
self.audioPlayer1.stop()
// Audio Code.
} else {
self.audioPlayer2.currentTime = 0
self.audioPlayer2.play()
self.audioPlayer1.stop()
self.audioPlayer3.stop()
self.audioPlayerSnow.stop()
self.audioPlayerSunny.stop()
self.audioPlayerThunder.stop()
// Audio Code.
}
DispatchQueue.main.async {
if self.exists{
self.degreeLbl.isHidden = false
self.conditionLbl.isHidden = false
self.imgView.isHidden = false
self.degreeLbl.text = "\(self.degree.description)°"
self.cityLbl.text = self.city
self.conditionLbl.text = self.condition
self.imgView.downloadImage(from: self.imgURL!)
}
else {
self.degreeLbl.isHidden = true
self.conditionLbl.isHidden = true
self.imgView.isHidden = true
self.cityLbl.text = "No matching city found"
self.exists = true
}
}
} catch let jsonError {
print(jsonError.localizedDescription)
}
}
}
task.resume()
}
}
extension UIImageView {
func downloadImage(from url: String) {
let urlRequest = URLRequest(url: URL(string: url)!)
let task = URLSession.shared.dataTask(with: urlRequest) { (data, response, error) in
if error == nil {
DispatchQueue.main.async {
self.image = UIImage(data: data!)
}
}
}
task.resume()
}
}
How do I used a string value from a function in a another class to update an UILabel on my ViewController?
Here is my code:
View controller:
import UIKit
class ViewController: UIViewController, dataEnterdDelegate {
#IBOutlet weak var auaTempLabel: UILabel!
override func viewDidLoad() {
super.viewDidLoad()
let weather2 = WeatherService2()
weather2.getWeatherData("Oranjestad,AW")
}
**func userDidEnterInformation(info: NSString)
{
testLabel!.text = info as String
}**
func setLabel2(information: String)
{
auaTempLabel.text = information
}
The other class named WeatherService2 contain the following codes:
**protocol dataEnterdDelegate{
func userDidEnterInformation(info:NSString)
}**
Class WeatherService2{
var currentTempeture:String?
let targetVC = ViewController()
**var delegate: dataEnterdDelegate?**
func getWeatherData(urlString:String)
{
let url = NSURL(string: urlString)!
let sqlQuery = "select * from weather.forecast where woeid in (select woeid from geo.places(1) where text=\"\(url)\")"
let endpoint = "https://query.yahooapis.com/v1/public/yql?q=\(sqlQuery)&format=json"
let testString = (String(endpoint))
getData(testString)
}
func getData(request_data: String)
{
let requestString:NSString = request_data.stringByAddingPercentEncodingWithAllowedCharacters(NSCharacterSet.URLQueryAllowedCharacterSet())!
let url_with_data = NSURL(string: requestString as String)!
let task = NSURLSession.sharedSession().dataTaskWithURL(url_with_data){
(data, response, error) in dispatch_async(dispatch_get_main_queue(), {
if data == nil
{
print("Failed loading HTTP link")
}else{
self.setLabel(data!)
}
})
}
task.resume()
}
func setLabel(weatherData:NSData)
{
enum JSONErrors: ErrorType
{
case UserError
case jsonError
}
do{
let jsonResults = try NSJSONSerialization.JSONObjectWithData(weatherData, options: .AllowFragments)
if let city = jsonResults["query"] as? NSDictionary
{
if let name = city["results"] as? NSDictionary
{
if let channel = name["channel"] as? NSDictionary
{
if let item = channel["item"] as? NSDictionary
{
if let condition = item["condition"] as? NSDictionary
{
if let temp = condition["temp"] as? String
{
setTemp(temp)
**delegate!.userDidEnterInformation(temp)**
}
}
}
}
}
}
}
catch {
print("Failed to load JSON Object")
}
}
func setTemp(tempeture:String)
{
self.currentTempeture = tempeture
}
func getTemp() ->String
{
return self.currentTempeture!
}
}
The code runs fine and everything but I get an error "Fatal error: unexpectedly found nil while unwrapping an Optional value" when I try to update the UILabel in my ViewController.
When I used the print("The return value is: "+information) in the view controller class it print the return value correctly.
This is the reason I'm confused right now because I don't know why I still getting the "Fatal error: unexpectedly found nil while unwrapping an Optional value" when trying to use this value to update my UILabel.
Can anyone help me with this problem?
Thanks in advance
For that you have to create delegate method.
In viewController you create delegate method and call it from where you get response and set viewController.delegate = self
I could not explain more you have to search for that and it will works 100% .
All the best.
I manage to fix this issue by doing the following:
I create the following class
- Item
- Condition
- Channel
These classes implement the JSONPopulator protocol.
The JSONPopulator protocol:
protocol JSONPopulator
{
func populate(data:AnyObject)
}
Item class:
class Item: JSONPopulator
{
var condition:Condition?
func getCondition() ->Condition
{
return condition!
}
func populate(data: AnyObject)
{
condition = Condition()
condition?.populate(data)
}
}
Condition class:
class Condition:JSONPopulator
{
var arubaTemp:String?
var channel:NSDictionary!
func getArubaTemp()->String
{
return arubaTemp!
}
func getBonaireTemp() ->String
{
return bonaireTemp!
}
func getCuracaoTemp()->String
{
return curacaoTemp!
}
func populate(data: AnyObject)
{
if let query = data["query"] as? NSDictionary
{
if let results = query["results"] as? NSDictionary
{
if let channel = results["channel"] as? NSDictionary
{
self.channel = channel
if let location = channel["location"] as? NSDictionary
{
if let city = location["city"] as? String
{
if city.containsString("Oranjestad")
{
switch city
{
case "Oranjestad":
arubaTemp = getTemp()
print(arubaTemp)
default:
break
}
}
}
}
}
}
}
}
func getTemp() ->String
{
var temp:String?
if let item = self.channel["item"] as? NSDictionary
{
if let condition = item["condition"] as? NSDictionary
{
if let tempeture = condition["temp"] as? String
{
print(tempeture)
temp = tempeture
}
}
}
print(temp)
return temp!
}
}
Channel class:
class Channel: JSONPopulator
{
var item:Item?
var unit:Unit?
var request_city:String?
func setRequestCity(request_city:String)
{
self.request_city = request_city
}
func getRequestCity() ->String
{
return request_city!
}
func getItem() -> Item
{
return item!
}
func getUnit() -> Unit
{
return unit!
}
func populate(data: AnyObject)
{
item = Item()
item?.populate(data)
}
}
The WeatherService class that handles the function of parsing the JSON object. This class implement a WeatherServiceCallBack protocol.
The WeatherServiceCallBack protocol:
protocol WeatherServiceCallBack
{
func arubaWeatherServiceService( channel:Channel)
func arubaWeatherServiceFailure()
}
WeatherService class:
class WeatherService
{
var weatherServiceCallBack:WeatherServiceCallBack
var requestCity:String?
init(weatherServiceCallBack: WeatherServiceCallBack)
{
self.weatherServiceCallBack = weatherServiceCallBack
}
internal func checkCity(city:String)
{
switch (city)
{
case "Oranjestad,AW":
requestCity = city
getWeatherData(requestCity!)
default:
break
}
}
func getWeatherData(urlString:String)
{
let url = NSURL(string: urlString)!
let sqlQuery = "select * from weather.forecast where woeid in (select woeid from geo.places(1) where text=\"\(url)\")"
let endpoint = "https://query.yahooapis.com/v1/public/yql?q=\(sqlQuery)&format=json"
let testString = (String(endpoint)
executeTask(testString)
}
func executeTask(request_data: String)
{
let requestString:NSString = request_data.stringByAddingPercentEncodingWithAllowedCharacters(NSCharacterSet.URLQueryAllowedCharacterSet())!
let url_with_data = NSURL(string: requestString as String)!
let task = NSURLSession.sharedSession().dataTaskWithURL(url_with_data){
(data, response, error) in dispatch_async(dispatch_get_main_queue(), {
if data == nil
{
print("Failed loading HTTP link")
}else{
self.onPost(data!)
}
})
}
task.resume()
}
func onPost(data:NSData)
{
enum JSONErrors: ErrorType
{
case UserError
case jsonError
}
do{
let jsonResults = try NSJSONSerialization.JSONObjectWithData(data, options: .AllowFragments)
print(jsonResults)
if let city = jsonResults["query"] as? NSDictionary
{
if let name = city["count"] as? Int
{
if name == 0
{
weatherServiceCallBack.arubaWeatherServiceFailure()
}
}
}
if let requestCity_check = jsonResults["query"] as? NSDictionary
{
if let results = requestCity_check["results"] as? NSDictionary
{
if let channel = results["channel"] as? NSDictionary
{
if let location = channel["location"] as? NSDictionary
{
if let city = location["city"] as? String
{
requestCity = city
let channel = Channel()
channel.setRequestCity(requestCity!)
channel.populate(jsonResults)
weatherServiceCallBack.arubaWeatherServiceService(channel)
}
}
}
}
}
}catch {
print("Failed to load JSON Object")
}
}
}
In the ViewController class (I add some animation to the UILabel so it can flip from Fahrenheit to Celsius):
class ViewController: UIViewController, WeatherServiceCallBack
{
var weather:WeatherService?
var aua_Tempeture_in_F:String?
var aua_Tempeture_in_C:String?
var timer = NSTimer()
#IBOutlet var aua_Temp_Label: UILabel!
let animationDuration: NSTimeInterval = 0.35
let switchingInterval: NSTimeInterval = 5 //10
override func viewDidLoad() {
super.viewDidLoad()
weather = WeatherService(weatherServiceCallBack: self)
weather?.checkCity("Oranjestad,AW")
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func animateTemptext()
{
self.timer = NSTimer.scheduledTimerWithTimeInterval(7.0, target: self, selector: Selector("tempConvertionTextSwitch"), userInfo: nil, repeats: true)
}
func setTempinCelsius(temp_string:String)
{
aua_Tempeture_in_F = "\(temp_string)°F"
let convertedString = convertFahrenheittoCelsius(temp_string)
aua_Tempeture_in_C = "\(convertedString)°C"
aua_Temp_Label.text = aua_Tempeture_in_C
animateTemptext()
}
func convertFahrenheittoCelsius(currentTemp:String) ->String
{
let tempTocelsius = (String(((Int(currentTemp)! - 32) * 5)/9))
return tempTocelsius
}
#objc func tempConvertionTextSwitch()
{
CATransaction.begin()
CATransaction.setAnimationDuration(animationDuration)
CATransaction.setCompletionBlock{
let delay = dispatch_time(DISPATCH_TIME_NOW,Int64(self.switchingInterval * NSTimeInterval(NSEC_PER_SEC)))
dispatch_after(delay, dispatch_get_main_queue())
{
}
}
let transition = CATransition()
transition.type = kCATransitionFade
if aua_Temp_Label.text == aua_Tempeture_in_F
{
aua_Temp_Label.text = aua_Tempeture_in_C
}else if aua_Temp_Label.text == aua_Tempeture_in_C
{
aua_Temp_Label.text = aua_Tempeture_in_F
}else if aua_Temp_Label == ""
{
aua_Temp_Label.text = aua_Tempeture_in_C
}
aua_Temp_Label.layer.addAnimation(transition, forKey: kCATransition)
CATransaction.commit()
}
func arubaWeatherServiceFailure() {
}
func arubaWeatherServiceService(channel: Channel)
{
let requested_city = channel.getRequestCity()
let items = channel.getItem()
let aua_Temp = items.getCondition().getArubaTemp()
setTempinCelsius(aua_Temp)
}
}
Reference:
iOS 8 Swift Programming Cookbook Solutions Examples for iOS Apps book
iOS 8 Programming Fundamentals with Swift Swift, Xcode, and Cocoa Basics book
Hope it help the once that had the same problem
I make a simple media player. I have a UITableViewController with mp3 files from Document Directory and UIViewController which plays mp3 files. I pass NSURL of a mp3 file from UITableViewController to UIViewController and I can play it. I want to make buttons are which will be turn track to next or previous. How can I make it?
The code is passing NSURL on a specific file.
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
var playerVC = (segue.destinationViewController as! UINavigationController).topViewController as! PlayMusicViewController
var indexPath = tableView.indexPathForSelectedRow()
var nameOfObjectForPass = listOfMP3Files![indexPath!.row] // default it's name and
var fileManager = NSFileManager.defaultManager()
var wayToFile = fileManager.URLsForDirectory(NSSearchPathDirectory.DocumentDirectory, inDomains: NSSearchPathDomainMask.UserDomainMask)
var passMusicFileURL: NSURL? // for pass mp3
if let documentPath: NSURL = wayToFile.first as? NSURL {
let musicFile = documentPath.URLByAppendingPathComponent(nameOfObjectForPass)
println(musicFile)
passMusicFileURL = musicFile
}
if segue.identifier == "listenMusic" {
playerVC.nameMusicFile = nameOfObjectForPass // name
playerVC.mp3URL = passMusicFileURL
// test
playerVC.allUrlsVC = allURLS
}
The code is playing mp3 file
func playMusic() {
AVAudioSession.sharedInstance().setCategory(AVAudioSessionCategoryPlayback, error: nil) // == true
AVAudioSession.sharedInstance().setActive(true, error: nil)
var error: NSError?
audioPlayer = AVAudioPlayer(contentsOfURL: mp3URL, error: &error)
// audioPlayer.prepareToPlay()
if currentPause == nil {
} else {
audioPlayer.currentTime = currentPause
}
//
audioPlayer.volume = 0.5
audioPlayer.play()
}
UPDATE
I made following
var arrayMP3url: Array<AnyObject>!
func playNextSound() {
var queue = AVQueuePlayer(URL: mp3URL)
var current = queue.currentItem
var arrayForSearch = arrayMP3url as! [NSURL]
var arrNS = arrayForSearch as NSArray
var index = arrNS.indexOfObject(mp3URL!)
println("index \(index)")
println("array for search \(arrayForSearch)")
println("current song \(current)")
}
But I always get the same index from NSArray
Use your array of mp3 files, and determine current playing index using indexPath, increase or, decrease the current playing index on button click as Next, or, Prev, and change the mp3 file by the index.
Replay the music.
Simple.
Ping if you need more help.
Update
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
var playerVC = (segue.destinationViewController as! UINavigationController).topViewController as! PlayMusicViewController
var indexPath = tableView.indexPathForSelectedRow();
//We only need to pass current index, and array of mp3 urls
playerVC.curIndex=indexPath.row;
playerVC.mp3s= listOfMP3Files;
}
So as described above, just declare two properties in your playerVC, ie
curIndex as int and mp3s as NSArray.
In the function
func playMusic() {
var nameOfObjectForPass = mp3s![curIndex]; // default it's name and
var fileManager = NSFileManager.defaultManager()
var wayToFile = fileManager.URLsForDirectory(NSSearchPathDirectory.DocumentDirectory, inDomains: NSSearchPathDomainMask.UserDomainMask)
var passMusicFileURL: NSURL? // for pass mp3
if let documentPath: NSURL = wayToFile.first as? NSURL {
let musicFile = documentPath.URLByAppendingPathComponent(nameOfObjectForPass)
println(musicFile)
passMusicFileURL = musicFile
}
self.nameMusicFile = nameOfObjectForPass // name
self.mp3URL = passMusicFileURL
// test
self.allUrlsVC = allURLS
AVAudioSession.sharedInstance().setCategory(AVAudioSessionCategoryPlayback, error: nil) // == true
AVAudioSession.sharedInstance().setActive(true, error: nil)
var error: NSError?
audioPlayer = AVAudioPlayer(contentsOfURL: mp3URL, error: &error)
// audioPlayer.prepareToPlay()
if currentPause == nil {
} else {
audioPlayer.currentTime = currentPause
}
//
audioPlayer.volume = 0.5
audioPlayer.play()
}
Then simply define your next and previous index calculations like
func playNextSound(){
self.curIndex++;
var maxCount=self.mp3s.count-1;
if(self.curIndex>maxCount){
self.curIndex=maxCount;
}
playMusic();
}
func playPrevSound(){
self.curIndex--;
if(self.curIndex<0){
self.curIndex=0;
}
playMusic();
}
Hope it helps. Cheers.
While reloading a tableView the app crashes and I am getting error
malloc:
error for object 0x7f8c7b99be80: pointer being freed was not allocated
set a breakpoint in malloc_error_break to debug
I have set the Symbolic breakpoint for
malloc_error_break
Also try to find memory leakage with "Instruments" but it just showing same error in console but here is no any memory leakage.
How to solve this issue.
(I am using 8.3 SDK and 6.3.1 Xcode)
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
var ResultCellIdentifier = "placementID"
var LoadCellIdentifier = "LoadingCell"
var count = self.arrayOfAllData.count as NSInteger
if count == 0 && indexPath.row == 0 {
let cell = tableView.dequeueReusableCellWithIdentifier("LoadingCell") as! UITableViewCell
return cell
}
else {
let cell = tableView.dequeueReusableCellWithIdentifier("placementID") as! PlacementsTableViewCell
indexPATH = indexPath
var tweet = self.arrayOfAllData.objectAtIndex(indexPath.row) as! NSDictionary
let created_at = tweet.valueForKey("created_at") as? NSString
var dateArray : NSArray = created_at!.componentsSeparatedByString(" ")
if dateArray.count != 0 {
let month = dateArray.objectAtIndex(1) as! String
let date = dateArray.objectAtIndex(2) as! String
cell.timeLabel.text = String(format: "%# %#", date,month)
}
///////////any url present in tweet text
var entities = NSDictionary()
entities = tweet.valueForKey("entities") as! NSDictionary
var urlsArray = entities.valueForKey("urls") as! NSArray
if urlsArray.count == 0 {
}else {
for item in urlsArray as! [NSDictionary] {
let expanded_url = item.valueForKey("expanded_url") as? String
}
}
///////////
var tweet_id_str = NSString()
var user_id_str = NSString()
var data = NSData()
// var name = NSString()
///////////count of retweets
var retweet_count = tweet.valueForKey("retweet_count") as! NSInteger
var retweeted_status = tweet.valueForKey("retweeted_status") as! NSDictionary
var favorite_count = retweeted_status.valueForKey("favorite_count") as! NSInteger
///////////tweet id
tweet_id_str = retweeted_status.valueForKey("id_str") as! NSString
if retweeted_status.isEqual(nil) {
}
else {
var user = retweeted_status.valueForKey("user") as! NSDictionary
///////////last update
let created_at = retweeted_status.valueForKey("created_at") as! NSString
///////////
///////////user name who added this tweet
cell.titleLabel.text = user.valueForKey("name") as? String
///////////user id who added this tweet
user_id_str = user.valueForKey("id_str") as! NSString
///////////screen name
let screen_name = user.valueForKey("screen_name") as! NSString
var followers_count = user.valueForKey("followers_count") as! NSInteger
///////////profile image of the tweet
cell.avatarImageView.image = UIImage(named: "Twitter Avatar.jpg")
let profile_image_url = user.valueForKey("profile_image_url") as! NSString
var imageUrl = NSURL(string: profile_image_url as String)
let request: NSURLRequest = NSURLRequest(URL: imageUrl!)
NSURLConnection.sendAsynchronousRequest(request, queue: NSOperationQueue.mainQueue(), completionHandler: {(response: NSURLResponse!,data: NSData!,error: NSError!) -> Void in
if error == nil {
if data != nil {
var image = UIImage(data: data)
cell.avatarImageView.image = image
}
}
})
if retweet_count >= 5 || favorite_count >= 15 || followers_count >= 30000 {
cell.featuredImageView.hidden = false
cell.featuredImageView.image = UIImage(named: "new feature star")
}
else {
cell.featuredImageView.hidden = true
}
}
cell.mailLabel.text = ""
let tweetText = tweet.valueForKey("text") as? NSString
cell.beattypeLabel.text = tweetText as? String
if tweetText?.containsString("#gmail") == true{
NSLog("Mail id is present at index : %d", indexPath.row)
var words = NSArray()
words = NSArray(array: tweetText!.componentsSeparatedByString(" "))
var mailAddress = NSString()
for var i = 0; i < words.count; i++ {
var mailAdd = words.objectAtIndex(i) as! NSString
if mailAdd.rangeOfString("#gmail").location != NSNotFound {
NSLog("mail Address : %#", mailAdd)
if mailAdd.rangeOfString(".com").location == NSNotFound {
var lastChar = mailAdd.characterAtIndex(mailAdd.length-1)
var lastCharStr:NSString = NSString(format: "%ch", lastChar)
mailAddress = mailAdd.stringByAppendingString(".com")
}
}
}
}
return cell
}
}
at the same time Thread 1 showing this
http://i.stack.imgur.com/2YoQp.jpg
(please go through this image)
use
var cell = tableView.dequeueReusableCellWithIdentifier("placementID") as! PlacementsTableViewCell
if cell.isEqual(nil) {
cell = PlacementsTableViewCell(style: UITableViewCellStyle.Default, reuseIdentifier: "placementID")
}
instead of
let cell = tableView.dequeueReusableCellWithIdentifier("placementID") as! PlacementsTableViewCell
and change downloading image in other thread like follow
let qualityOfServiceClass = QOS_CLASS_BACKGROUND
let backgroundQueue = dispatch_get_global_queue(qualityOfServiceClass, 0)
dispatch_async(backgroundQueue, {
println("This is run on the background queue")
var imageData = NSData(contentsOfURL: imageUrl!)
var image = UIImage(data: imageData!)
dispatch_async(dispatch_get_main_queue(), { () -> Void in
println("This is run on the main queue, after the previous code in outer block")
cell.avatarImageView.image = image
})
})