I'm trying to convert my Swift 1 code into Swift 2.1.1 code.
So I am trying to add a fetchRequest.
In Swift 1 I did this:
if let results = context.executeFetchRequest(fetchRequest, error:&error),
let managedObject = results.first as? NSManagedObject {
context.deleteObject(managedObject)
}
let saveError: NSError?
context.save(nil)
and
var error: NSError?
let fetchedResults = managedContext.executeFetchRequest(fetchRequest) as! [NSManagedObject]?
if let results = fetchedResults {
people = results
}
else {
print("Could not fetch \(error), \(error!.userInfo)")
}
Swift 2.1 (2nd request -> doesn't work):
do {
let fetchedResults = try managedContext.executeFetchRequest(fetchRequest) as! [NSManagedObject]
// success if it gets here
if let results = fetchedResults {
people = results
}
} catch let error as NSError {
// failed so print error
print("Error: \(error.localizedDescription)")
}
Errors in line (if let results... & let fetchedResults...):
Initializer for conditional binding must have Optional type, not '[AnyObject]'
Call can throw, but is not marked with 'try' and the error is not handled
Errors in line (let fetchedResults...):
Call can throw, but is not marked with 'try' and the error is not handled
Cannot downcast from '[AnyObject]' to a more optional type '[NSManagedObject]?'
Could you please help me to translate this into Swift 2.1.1?
Thanks for your help!
You can wrap it in a do catch block. It will print an error if the let results line fails.
do {
let results = try context.executeFetchRequest(fetchRequest)
// success if it gets here
if let managedObject = results.first as? NSManagedObject {
context.deleteObject(managedObject)
}
} catch let error as NSError {
// failed so print error
print("Error: \(error.localizedDescription)")
}
EDIT
Second request:
do {
let fetchedResults = try managedContext.executeFetchRequest(fetchRequest)
// success if it gets here
if let results = fetchedResults as? [NSManagedObject]{
people = results
}
} catch let error as NSError {
// failed so print error
print("Error: \(error.localizedDescription)")
}
Related
For some reason whenever I try to update my label with the current temperature using self.infoLabel.text = String(temp!) inside of the DispatchQueue code block, I get the following fatal error message:
unexpectedly found nil while unwrapping an Optional value.
I'd appreciate if someone could help me figure out why the code below isn't working. Thanks.
func getCurrentTemp(city: String){
let weatherRequestURL = URL(string: "\(openWeatherMapBaseURL)?APPID=\(openWeatherMapAPIKey)&q=\(city)")!
// The data task retrieves the data.
URLSession.shared.dataTask(with: weatherRequestURL) { (data, response, error) in
if let error = error {
// Case 1: Error
print("Error:\n\(error)")
}
else {
//print("Raw data:\n\(data!)\n")
//let dataString = String(data: data!, encoding: String.Encoding.utf8)
//print("Human-readable data:\n\(dataString!)")
do {
// Try to convert that data into a Swift dictionary
let weather = try JSONSerialization.jsonObject(with: data!, options:.allowFragments) as! [String:AnyObject]
if let main = weather["main"] as? [String: Any] {
let temp = main["temp"] as? Double
print("temp\(temp!)")
DispatchQueue.main.sync(execute: {
self.infoLabel.text = String(temp!)
})
//return temp as? String
//let temp_max = main["temp_max"] as? Double
//print("temp\(temp_max!)")
//let temp_min = main["temp_min"] as? Double
//print("temp\(temp_min!)")
}
}
catch let jsonError as NSError {
// An error occurred while trying to convert the data into a Swift dictionary.
print("JSON error description: \(jsonError.description)")
}
}
}
.resume()
}
There are two possibilities here: 1) either temp is nil (and it shouldn't be because you already force unwrap it in the print statement above) 2) or infoLabel is nil which happens if you broke your outlet connection.
Its easy to check; make a breakpoint above your assignment and in the debug console you can type:
po self.infoLabel
to see if its nil. For good measure you an also check temp.
You can also add a print statement to check self.infoLabel or an assert.
Alright, so I found a makeshift solution to this issue (See Below). Rather than placing the code inside of the function I made, I placed it in the viewDidLoad() function. For whatever reason, self.infoLabel? would be nil anywhere inside of the function I made.
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
print("Sucessful launched weather page.")
let weatherRequestURL = URL(string: "\(openWeatherMapBaseURL)?APPID=\(openWeatherMapAPIKey)&q=\(city)")!
// The data task retrieves the data.
URLSession.shared.dataTask(with: weatherRequestURL) { (data, response, error) in
if let error = error {
// Case 1: Error
print("Error:\n\(error)")
}
else {
//print("Raw data:\n\(data!)\n")
//let dataString = String(data: data!, encoding: String.Encoding.utf8)
//print("Human-readable data:\n\(dataString!)")
do {
// Try to convert that data into a Swift dictionary
let weather = try JSONSerialization.jsonObject(with: data!, options:.allowFragments) as! [String:AnyObject]
if let main = weather["main"] as? [String: Any] {
let temp = main["temp"] as? Double
print("temp\(temp!)")
var tempInFarenheit = ((9/5)*((temp!)-273) + 32).rounded()
DispatchQueue.main.sync(execute: {
self.infoLabel.text = "\(tempInFarenheit) + °"
})
}
}
catch let jsonError as NSError {
// An error occurred while trying to convert the data into a Swift dictionary.
print("JSON error description: \(jsonError.description)")
}
}
}
.resume()
}
Although this isn't the most effective way of doing things, hopefully it can help others who are having the same problem. If I find a more effective way of doing this, I'll be sure to edit this post and include it.
Hello I am currently following a Swift tutorial which uses the old version of Swift and I am not able to follow this as I believe the syntax has changed in the newer version of Swift.
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
var appDel:AppDelegate = UIApplication.sharedApplication().delegate as! AppDelegate
var context:NSManagedObjectContext = appDel.managedObjectContext
var newUser = NSEntityDescription.insertNewObjectForEntityForName("users", inManagedObjectContext: context) as NSManagedObject
newUser.setValue("Joe", forKey: "username")
newUser.setValue("pass", forKey: "password")
do {
try context.save()
} catch let error {
print("Couldn't save user data")
print(error)
}
let request = NSFetchRequest(entityName: "Users")
request.returnsObjectsAsFaults = false
// var results = context.executeFetchRequest(request)
do {
var results =
try context.executeFetchRequest(request)
results = results as! [NSManagedObject]
} catch let error as NSError {
print(error)
}
for result: AnyObject in results {
print(results)
}
}
The error I am receiving is to do with the results on the line for result: AnyObject in results and the error is unresolved identifier 'results' which is giving me the impression that this should be declared somewhere as a variable as it is currently unresolved but I cannot figure out how to fix this, any help would be greatly appreciated, thanks!
do {
var results = try context.executeFetchRequest(request)
results = results as! [NSManagedObject]
} catch let error as NSError {
print(error)
}
for result: AnyObject in results {
print(results)
}
results only has scope inside the do block there. You need to move the processing of the array inside the do:
do {
var results = try context.executeFetchRequest(request)
results = results as! [NSManagedObject]
for result in results {
print(results)
}
} catch let error as NSError {
print(error)
}
Also there's no need to lose information by casting as AnyObject.
With the new API's against CoreData (in Swift 3.0) you should do:
let request = NSFetchRequest<Users>(entityName: "Users")
request.returnsObjectsAsFaults = false
do {
var results =
try context.fetch(request)
// `results` will here be [Users]
} catch let error as NSError {
print(error)
}
The new signature of fetch is fetch<T : NSFetchRequestResult>(_ request: NSFetchRequest<T>) throws -> [T] where T is the same as provided in <HERE> (ex. NSFetchRequest<Users>)
I'm trying to load data and save it into the database but I get a warning and an error in func preloadData():
Cast from 'NSManagedObject' to unrelated type 'LeadItem' always fails
And in func removData():
cannot convert value of type 'LeadItem' to expected argument type 'NSManagedObject'
Similar solutions for an older version of Xcode aren't working for me.
func preloadData ()
{
if let contentsOfURL = NSBundle.mainBundle().URLForResource("leads_Data", withExtension: "csv")
{
removeData()
var error:NSError?
if let leads = parseCSV(contentsOfURL, encoding: NSUTF8StringEncoding, error: &error)
{
for lead in leads
{
let leadItem = NSEntityDescription.insertNewObjectForEntityForName("LeadItem", inManagedObjectContext: self.managedObjectContext) as! LeadItem
}
}
}
}
func removeData ()
{
let fetchRequest = NSFetchRequest(entityName: "LeadItem")
do
{
let leadItems = try self.managedObjectContext.executeFetchRequest(fetchRequest) as! [LeadItem]
for leadItem in leadItems
{
self.managedObjectContext.deleteObject(leadItem)
}
}
catch let error as NSError
{
print("Failed to retrieve record: \(error.localizedDescription) \n")
}
}
}
I'm currently developing my first iOS app using Swift 2.0 and Xcode Beta 2. It reads an external JSON and generates a list in a table view with the data. However, I'm getting a strange little error that I can't seem to fix:
Extra argument 'error' in call
Here is a snippet of my code:
let task = session.dataTaskWithURL(url!, completionHandler: {data, response, error -> Void in
print("Task completed")
if(error != nil){
print(error!.localizedDescription)
}
var err: NSError?
if let jsonResult = NSJSONSerialization.JSONObjectWithData(data, options: NSJSONReadingOptions.MutableContainers, error: &err) as? NSDictionary{
if(err != nil){
print("JSON Error \(err!.localizedDescription)")
}
if let results: NSArray = jsonResult["results"] as? NSArray{
dispatch_async(dispatch_get_main_queue(), {
self.tableData = results
self.appsTableView!.reloadData()
})
}
}
})
The error is thrown at this line:
if let jsonResult = NSJSONSerialization.JSONObjectWithData(data, options: NSJSONReadingOptions.MutableContainers, error: &err) as? NSDictionary{
Can someone please tell me what I'm doing wrong here?
With Swift 2, the signature for NSJSONSerialization has changed, to conform to the new error handling system.
Here's an example of how to use it:
do {
if let jsonResult = try NSJSONSerialization.JSONObjectWithData(data, options: []) as? NSDictionary {
print(jsonResult)
}
} catch let error as NSError {
print(error.localizedDescription)
}
With Swift 3, the name of NSJSONSerialization and its methods have changed, according to the Swift API Design Guidelines.
Here's the same example:
do {
if let jsonResult = try JSONSerialization.jsonObject(with: data, options: []) as? [String:AnyObject] {
print(jsonResult)
}
} catch let error as NSError {
print(error.localizedDescription)
}
Things have changed in Swift 2, methods that accepted an error parameter were transformed into methods that throw that error instead of returning it via an inout parameter. By looking at the Apple documentation:
HANDLING ERRORS IN SWIFT:
In Swift, this method returns a nonoptional result and is marked with the throws keyword to indicate that it throws an error in cases of failure.
You call this method in a try expression and handle any errors in the catch clauses of a do statement, as described in Error Handling in The Swift Programming Language (Swift 2.1) and Error Handling in Using Swift with Cocoa and Objective-C (Swift 2.1).
The shortest solution would be to use try? which returns nil if an error occurs:
let message = try? NSJSONSerialization.JSONObjectWithData(receivedData, options:.AllowFragments)
if let dict = message as? NSDictionary {
// ... process the data
}
If you're also interested into the error, you can use a do/catch:
do {
let message = try NSJSONSerialization.JSONObjectWithData(receivedData, options:.AllowFragments)
if let dict = message as? NSDictionary {
// ... process the data
}
} catch let error as NSError {
print("An error occurred: \(error)")
}
This has been changed in Swift 3.0.
do{
if let responseObj = try JSONSerialization.jsonObject(with: results, options: .allowFragments) as? NSDictionary{
if JSONSerialization.isValidJSONObject(responseObj){
//Do your stuff here
}
else{
//Handle error
}
}
else{
//Do your stuff here
}
}
catch let error as NSError {
print("An error occurred: \(error)") }
I got some issue with the code that I can't figure out. After I installed Xcode 7 beta and convert my swift code to Swift 2
Code:
override func viewDidAppear(animated: Bool) {
let appDelegate: AppDelegate = UIApplication.sharedApplication().delegate as! AppDelegate
let context: NSManagedObjectContext = AppDel.managedObjectContext
let request = NSFetchRequest(entityName: "PlayerList")
list = Context.executeFetchRequest(request)
tableView.reloadData()
}
ScreenShot:
As of Swift 2, Cocoa methods that produce errors are translated to Swift functions that throw an error.
Instead of an optional return value and an error parameter as in Swift 1.x:
var error : NSError?
if let result = context.executeFetchRequest(request, error: &error) {
// success ...
list = result
} else {
// failure
println("Fetch failed: \(error!.localizedDescription)")
}
in Swift 2 the method now returns a non-optional and throws an error
in the error case, which must be handled with try-catch:
do {
list = try context.executeFetchRequest(request)
// success ...
} catch let error as NSError {
// failure
print("Fetch failed: \(error.localizedDescription)")
}
For more information, see "Error Handling" in "Adopting Cocoa Design Patterns"
in the "Using Swift with Cocoa and Objective-C" documentation.
You could try this code:
let result = (try! self.manageContext.executeFetchRequest(FetchRequest)) as! [NSManageObjectClass]
Swift 3.0
In this example PlayerList is NSManagedObject entity/class name (auto created by Xcode)
let request: NSFetchRequest<PlayerList> = PlayerList.fetchRequest()
var result:[PlayerList]?
do{
//Succes
result = try context.fetch(request)
}catch let error as NSError {
//Error
print("Error \(error)")
}
print("result: \(result)")
var results = [YourEntity]?
results = try! self.managedObjectContext!.executeFetchRequest(fetchRequest) as! [YourEntity]
Try the code below
override func viewWillAppear(animated: Bool) {
let appDel:AppDelegate = (UIApplication.sharedApplication().delegate as! AppDelegate)
let context = appDel.managedObjectContext
let request = NSFetchRequest(entityName:"Users")
do {
let results = try context.executeFetchRequest(request)
itemList = results as! [NSManagedObject]
} catch let error as NSError {
print("Could not fetch \(error), \(error.userInfo)")
}
}