I used path to documents to link external file in app. But when I want to run the project on real iPhone, I replaced the path with NSBundle. Now I'm getting error because of NSBundle(I think) or something else. How can I debug it?
error in console: fatal error: unexpectedly found nil while unwrapping an Optional value
the whole code:
import UIKit
func assign() -> [String]{
let bundle = NSBundle.mainBundle()
let path = bundle.pathForResource("words", ofType: "txt")
let content = String(contentsOfFile: path!, encoding: NSUTF8StringEncoding, error: nil)//xcode marked that line with green
let newArray = content!.componentsSeparatedByString("\n")
return newArray
}
class ViewController: UIViewController, UITextFieldDelegate {
let newArray: [String] = assign()
#IBOutlet weak var textBox: UITextView!
#IBOutlet weak var firstInput: UITextField!
#IBOutlet weak var resultLabel: UILabel!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
firstInput.returnKeyType = .Search
firstInput.delegate = self
textBox.text = ""
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func getFromPath() {
//getFromPath() func used to be in assign func.
var letters = firstInput.text
var res = search(set: newArray, letters: letters)
textBox.text! = ""
for element in res {
textBox.text = (textBox.text ?? "") + "\n" + "\(element)"
}
}
func textFieldShouldReturn(textField: UITextField) -> Bool {
if firstInput.text == "" {
}
else {
getFromPath()
}
self.view.endEditing(true)
return false
}
func search(#set: [String], letters: String) -> [String] {
let result = filter(set) { item in
for char in letters {
if !contains(item, char) {
return false
}
}
return true
}
return result
}
}
It seems like you dont have that file in your bundle.
Make sure the file has been added to the target, check in the inspector.
Wrap critical initialization in
if let someObject = source as? someType
{
}
Drag your file to your project and place it together with your projects files. Make sure you select copy items if needed:
class ViewController: UIViewController {
let wordsUrl = NSBundle.mainBundle().URLForResource("words", withExtension: "txt")!
override func viewDidLoad() {
super.viewDidLoad()
var error: NSError?
if wordsUrl.checkResourceIsReachableAndReturnError(&error) {
println(true)
if let myString = String(contentsOfURL: wordsUrl, encoding: NSUTF8StringEncoding, error: &error) {
let myArray = myString.componentsSeparatedByString("\n")
println(myArray)
} else if let error = error {
println(error.description)
}
} else if let error = error {
println(error.description)
}
// 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.
}
}
Related
I have this app that I made with Swift, for fun and because I'm a beginner. Basically what it does is you can enter an artist name and song name and it fetches lyrics from AZLyrics.com based on the artist and song name you entered. For some reason most of the time when I try and load lyrics the first time when I open the app it doesn't load (it loads the 2nd, 3rd, 4th etc time). Here is my code could someone please tell me how I could fix this?
First View controller
import UIKit
var lyricsWithQuotes = ""
var urlError = false
class ViewController: UIViewController, UITextFieldDelegate {
#IBOutlet var songName: UITextField!
#IBOutlet var artistName: UITextField!
#IBAction func search(sender: AnyObject) {
var url = NSURL(string: "http://www.azlyrics.com/lyrics/" + artistName.text.stringByReplacingOccurrencesOfString(" ", withString: "").stringByReplacingOccurrencesOfString("'", withString: "").stringByReplacingOccurrencesOfString(",", withString: "").stringByReplacingOccurrencesOfString(".", withString: "").lowercaseString + "/" + songName.text.stringByReplacingOccurrencesOfString(" ", withString: "").stringByReplacingOccurrencesOfString("'", withString: "").stringByReplacingOccurrencesOfString(",", withString: "").stringByReplacingOccurrencesOfString(".", withString: "").lowercaseString + ".html")
if url != nil {
let task = NSURLSession.sharedSession().dataTaskWithURL(url!, completionHandler: { (data, response, error) -> Void in
if error == nil {
var urlContent = NSString(data: data, encoding: NSUTF8StringEncoding) as NSString!
var urlContentArray = urlContent.componentsSeparatedByString("<!-- Usage of azlyrics.com content by any third-party lyrics provider is prohibited by our licensing agreement. Sorry about that. -->")
if urlContent.containsString("It's a place where all searches end!") {
urlError = true
} else {
var lyricsArray = urlContentArray[1].componentsSeparatedByString("<br><br>")
var lyrics = lyricsArray[0] as! String
var lyricsWithoutBR = lyrics.stringByReplacingOccurrencesOfString("<br>", withString: "")
var lyricsWithoutSlashDiv = lyricsWithoutBR.stringByReplacingOccurrencesOfString("</div>", withString: "")
var lyricsWithoutI = lyricsWithoutSlashDiv.stringByReplacingOccurrencesOfString("<i>", withString: "")
var lyricsWithoutSlashI = lyricsWithoutI.stringByReplacingOccurrencesOfString("</i>", withString: "")
lyricsWithQuotes = lyricsWithoutSlashI.stringByReplacingOccurrencesOfString(""", withString: "\"")
}
} else {
urlError = true
}
})
task.resume()
} else {
urlError = true
}
}
override func touchesBegan(touches: Set<NSObject>, withEvent event: UIEvent) {
view.endEditing(true)
}
func textFieldShouldReturn(textField: UITextField) -> Bool {
textField.resignFirstResponder()
return true
}
override func viewDidLoad() {
super.viewDidLoad()
artistName.delegate = self
songName.delegate = self
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
Second View Controller
import UIKit
var lyricsComplete = ""
class ViewController2: UIViewController {
#IBOutlet var lyricsDisplay: UITextView!
override func viewDidAppear(animated: Bool) {
if urlError == true {
urlError = false
lyricsDisplay.text = "Couldn't find that song!"
} else {
lyricsComplete = lyricsWithQuotes
lyricsDisplay.text = lyricsComplete
}
}
override func viewDidLoad() {
super.viewDidLoad()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
After your NSURLSession has completed - basically this line:
lyricsWithQuotes = lyricsWithoutSlashI.stringByReplacingOccurrencesOfString(""", withString: "\"")
You have two options:
Option One - Programatically launch the view:
let storyboard = UIStoryboard(name: "STORYBOARD NAME HERE", bundle: nil)
let newVC = storyboard.instantiateViewControllerWithIdentifier("VIEW CONTROLLER IDENTIFIER HERE") as! ViewController2
newVC.lyricsComplete = lyricsWithQuotes
If you have a navigation controller:
self.navigationController?.pushViewController(newVC, animated: true)
If you don't have a navigation controller:
self.showViewController(newVC, sender: self)
Options 2 - Trigger the Segue:
performSegueWithIdentifier("SEGUE NAME HERE", sender: nil)
Then intercept the Segue
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
// Get the new view controller using segue.destinationViewController.
// Pass the selected object to the new view controller.
if(segue.identifier == "SEGUE NAME HERE"){
let newVC = segue.destinationViewController as! ViewController2
newVC.lyricsComplete = lyricsWithQuotes
}
}
If you use option 2, make sure the Segue is between the View Controllers and not attached to your button:
Like this:
Not like this:
I want to randomize the image background of weather depending on the weather information. I want to make them work one after the other;
the first function will make a string and the second function use the string produced by the first one.
import UIKit
class ViewController: UIViewController, UITextFieldDelegate {
#IBOutlet weak var cityNameTextField: UITextField!
#IBOutlet weak var weatherFact: UILabel!
#IBOutlet weak var weatherImage: UIImageView!
var weather = ""
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
self.cityNameTextField.delegate = self
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
#IBAction func weatherButton(sender: UIButton) {
weatherInformation()
randomWeatherImage()
}
func showError() {
self.weatherFact.text = "we can't load the weather of \(cityNameTextField.text). please try again"
}
override func touchesBegan(touches: Set<NSObject>, withEvent event: UIEvent) {
self.view.endEditing(true)
}
func textFieldShouldReturn(textField: UITextField) -> Bool {
self.view.endEditing(true)
return true
}
func randomWeatherImage() {
if weatherFact.text != nil {
let string = weather
let regex = NSRegularExpression(pattern: "-?[0-9]{1,3}", options: NSRegularExpressionOptions(), error: nil)
if let matches = regex?.matchesInString(string, options: NSMatchingOptions(), range: NSRange(location: 0, length: count(string))){
let degrees = matches.map { return(string as NSString).substringWithRange($0.range) }
var maxDegree = degrees[0].toInt()
var minDegree = degrees[1].toInt()
var averageWeather:Int = (maxDegree! + minDegree!) / 2
if averageWeather < 0 {
self.weatherImage.image = UIImage(named: "Cold.jpg")
}
else if averageWeather > 20 {
self.weatherImage.image = UIImage(named: "Warm.jpg")
}
else {
self.weatherImage.image = UIImage(named: "Mild.jpg")
}
}
}
}
func weatherInformation() {
let url = NSURL(string: "http://www.weather-forecast.com/locations/" + cityNameTextField.text.stringByReplacingOccurrencesOfString(" ", withString: "-") + "/forecasts/latest")
if url != nil {
let task = NSURLSession.sharedSession().dataTaskWithURL(url!){ (data, response, error) in
var urlError = false
if error == nil {
var urlContent = NSString(data: data, encoding: NSUTF8StringEncoding)
var urlContentArray = urlContent!.componentsSeparatedByString("<span class=\"phrase\">")
if urlContentArray.count > 0 {
var weatherArray = urlContentArray[1].componentsSeparatedByString("</span>")
self.weather = weatherArray[0] as! String
self.weather = self.weather.stringByReplacingOccurrencesOfString("°", withString: "º")
}
else {
urlError = true
}
}
else {
urlError = true
}
dispatch_async(dispatch_get_main_queue()) {
if urlError == true {
self.showError()
}
else {
self.weatherFact.text = self.weather
}
}
}
task.resume()
}
else {
showError()
}
}
}
Just call randomWeatherImage after you set weatherFact.text:
dispatch_async(dispatch_get_main_queue()) {
if urlError == true {
self.showError()
}
else {
self.weatherFact.text = self.weather
self.randomWeatherImage()
}
}
When I run this code it does not update the alertLabel to the message I have set on parse. Iim not getting any errors, and the label is correctly linked to my ViewController class.
I'm very new to coding so I would appreciate you help. Thanks in advance.
class ViewController: UIViewController {
#IBOutlet weak var alertLabel: UILabel!
var output : PFObject!
let theObjectID = "M0qEFWMxYI"
let theClass = "bobcatStatus"
override func viewDidLoad() {
super.viewDidLoad()
}
func displayData() {
var thisQuery = PFQuery(className: theClass)
thisQuery.getObjectWithId(theObjectID)
if let alertOutput = output["alertMessage"] as? String {
alertLabel.text = alertOutput
}
else {
alertLabel.text = "Error loading data."
}
}
// 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.
}
Xcode 6.2.3
#brianprsly i am assuming you are trying to get a record from parse class using object id, try to implement below code in your project. Let me know if it helps you.
Ref : https://www.parse.com/docs/ios/guide#objects-retrieving-objects
var query = PFQuery(className: theClass)
query.getObjectInBackgroundWithId(theObjectID) {
(theClassObj: PFObject?, error: NSError?) -> Void in
if error == nil && theClassObj != nil {
println(theClassObj)
if let alertOutput = theClassObj["alertMessage"] as? String {
alertLabel.text = alertOutput
}else {
alertLabel.text = "Error loading data."
}
} else {
println(error)
}
}
import UIKit
class ViewController: UIViewController {
#IBOutlet weak var yourScore: UITextField!
#IBOutlet weak var totalScore: UITextField!
#IBOutlet weak var labelText: UILabel!
#IBAction func buttonPressed(sender: AnyObject) {
let score1: Int = yourScore.text.toInt()!
let score2: Int = totalScore.text.toInt()!
let mistakes = score2 - score1
let scoreFinal = ((((score2 / 2) - mistakes)*23)/score2)+75
labelText.text = "\(scoreFinal)"
}
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.
}
}
Something is wrong with my code. Is it because of data types or something? When I load the application, it just opens fine but when the button is pressed, the app crashes.
http://i.stack.imgur.com/B2i5Z.png
You could safely unwrap the values with if let:
if let score1 = yourScore.text.toInt() {
if let score2 = totalScore.text.toInt() {
let mistakes = score2 - score1
let scoreFinal = ((((score2 / 2) - mistakes)*23)/score2)+75
labelText.text = "\(scoreFinal)"
} else {
// no valid score2
}
} else {
// no valid score1
}
While unwrapping, you can't just willy nilly use the values. Before unwrapping you have to check if the current value is nil. If it's not nil, then you can safely unwrap the text.
I am getting a compiler error in the code below. I have imported the required Foundation library so I am not sure exactly what is wrong, please could someone suggest what I might be doing incorrectly or what I might do in order to fix this?
Thanks
import UIKit
import Foundation
class ViewController: UIViewController {
#IBOutlet var areaTxt: UITextField!
#IBOutlet var resultLbl: UILabel!
#IBAction func goBtn(sender: AnyObject) {
if(countElements(areaTxt.text) > 0){
var removedSpaces = areaTxt.text.stringByReplacingOccurrencesOfString(" ", withString: "");
var url = "http://weather-forecast.com/locations/" + removedSpaces + "/forecasts/latest";
self.getWeatherReportForArea(url);
}else{
let alert = UIAlertView()
alert.title = "Alert"
alert.message = "The user location is empty"
alert.addButtonWithTitle("Ok")
alert.show()
}
}
func getWeatherReportForArea(area: String){
var url = NSURL(string: area);
let task = NSURLSession.sharedSession().dataTaskWithURL(url) { (data, response, error) in
var urlContent = NSString(data: data, encoding: NSUTF8StringEncoding);
if(urlContent.bridgeToObjectiveC().containsString("<span class=\"phrase\">")){
var contentArray = urlContent.componentsSeparatedByString("<span class=\"phrase\">");
var newContentArray = contentArray[1].componentsSeparatedByString("</span>");
var value = newContentArray[0].stringByReplacingOccurrencesOfString("°", withString: "º");
dispatch_async(dispatch_get_main_queue()){
self.resultLbl.text = value;
}
}else{
}
}
task.resume();
}
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.
}
}
bridgeToObjectiveC() was removed in Xcode 6 Beta 5. Now bridging is transparent, simply use
if urlContent.containsString("<span class=\"phrase\">") {
...
}