When I try to read data in HealthKit I get an error telling me that the application crashed because of
fatal error: unexpectedly found nil while unwrapping an Optional value
I understand that I am trying to unwrap an optional that is nil, but when I try to use optionals I get an error telling me to force unwrap it.
Here is some of the code that I am using:
import Foundation
import HealthKit
import UIKit
class HealthManager {
let healthKitStore = HKHealthStore()
func authorizeHealthKit(completion: ((success: Bool, error: NSError) -> Void)!) {
// Set the Data to be read from the HealthKit Store
let healthKitTypesToRead: Set<HKObjectType> = [(HKObjectType.quantityTypeForIdentifier(HKQuantityTypeIdentifierActiveEnergyBurned))!, HKObjectType.quantityTypeForIdentifier(HKQuantityTypeIdentifierFlightsClimbed)!, HKObjectType.quantityTypeForIdentifier(HKQuantityTypeIdentifierNikeFuel)!, HKObjectType.quantityTypeForIdentifier(HKQuantityTypeIdentifierStepCount)!, HKObjectType.quantityTypeForIdentifier(HKQuantityTypeIdentifierDistanceWalkingRunning)!]
// Check if HealthKit is available
if !HKHealthStore.isHealthDataAvailable() {
let error = NSError(domain: "com.MyCompany.appName", code: 2, userInfo: [NSLocalizedDescriptionKey: "HealthKit is not available on this device"])
if completion != nil {
completion?(success: false, error: error)
}
return;
}
// Request HealthKit Access
self.healthKitStore.requestAuthorizationToShareTypes(nil, readTypes: healthKitTypesToRead) {
(success, error) -> Void in
if completion != nil {
completion?(success: true, error: error!)
}
}
}
}
Also, if I try to remove the bang operator(!) I get an error saying that:
Value of optional type 'HKQuantityType?' not unwrapped; did you mean to use '!'?
Since quantityTypeForIdentifier returns HKQuantityType?, then force unwrapping it can result in unwrapping a nil value, as you know. You have to check for nil, for example in the form:
if let objectType = HKObjectType.quantityTypeForIdentifier(HKQuantityTypeIdentifierFlightsClimbed) {
// Add objectType to set
}
I realized that when I was requesting HealthKit access this piece of code was returning nil:
if completion != nil {
completion?(success: true, error: error!)
}
It turns out that the error was actually nil and I was force unwrapping the nil. As a result, I changed the code to:
if error != nil && completion != nil {
completion?(success: true, error: error!)
}
Related
I am trying to build a text recognizer app in iOS with the Firebase ML Kit. I have tried following some tutorials, but no luck. I keep getting the following error at the line indicated (return self.result):
Thread 1: Fatal error: Unexpectedly found nil while implicitly unwrapping an Optional value
I am still very new to Swift/xcode and firebase so any help would be greatly appreciated!
var result: VisionText!
var textRecognizer: VisionTextRecognizer!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
let vision = Vision.vision()
textRecognizer = vision.cloudTextRecognizer()
imageResult.image = UIImage(named: "sampletext")
print(textRecognition(image: imageResult.image!))
textResult.text += scantext
}
func textRecognition(image: UIImage) -> VisionText{
let visionImage = VisionImage(image: image)
textRecognizer.process(visionImage) { (result, error) in guard error == nil, case self.result = result else {
print("oops")
return
}
print("oops")
}
return self.result \\ ERROR
}
EDIT
I made sure to implement a correct way to unwrap an optional. My problem is that the Firebase MLVision process does not return anything, the result is nil. Not sure if I am going about the method incorrectly. Here is my updated code with some small changes.
var scannedresult: VisionText!
var textRecognizer: VisionTextRecognizer!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
let vision = Vision.vision()
textRecognizer = vision.cloudTextRecognizer()
imageResult.image = UIImage(named: "sampletext")
print("oops")
print(textRecognition(image: imageResult.image!))
// textResult.text += scannedresult.text
}
func textRecognition(image: UIImage) {
let visionImage = VisionImage(image: image)
textRecognizer.process(visionImage) { (result, error) in guard error == nil, let result = result else { print("oops")
return }
self.scannedresult = result
}
}
"Fatal error: Unexpectedly found nil while implicitly unwrapping an Optional value"
^This error occurs when you are trying to access a value for an option variable, and the value is nil. You have to unwrap it safely. There are five ways to unwrap an optional. This is my preferred way:
guard let result = self.result else { return }
return result
the guard statement will cause your code to skip over the next lines in the block if there is no value, or NIL, in the result.
Here is a quick read on all the ways to unwwrap your optionals w/ examples
So I'm new to core data, starting doing some tutorials and got a very basic setup where a 10 scores are saved from the AppDelegate and that works fine (am able to fetch and print from the console).
Then when I want to use a fetchrequest in another VC to retrieve the data which has been saved successfully, I get the following error:
fatal error: unexpectedly found nil while unwrapping an Optional value.
Here's the code to retrieve the data:
import Foundation
import CoreData
import UIKit
class testVC: UIViewController {
var managedObjectContext: NSManagedObjectContext!
var scores = [Scores]()
#IBOutlet weak var retrieveDataLabel: UIButton!
#IBOutlet weak var saveLabel: UIButton!
override func viewDidLoad() {
super.viewDidLoad()
}
#IBAction func retrieveData(sender: AnyObject) {
let fetchRequest = NSFetchRequest(entityName: "Scores")
do {
if let results = try managedObjectContext.executeFetchRequest(fetchRequest) as? [Scores]{
scores = results
for result in results {
if let gameScore = result.valueForKey("gameScore") as? Int{
print("Your score is \(gameScore)")
}
}
}
}catch{
print("Error fetching data")
}}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
Since I'm using if let .. shouldn't I be getting "Error fetching data"? instead of getting the fatal error? How come I can retrieve the data when loading the app but not when I try to retrieve the data in a different VC using the same code?
I've looked at other questions relating to fatal error found nil while unwrapping an optional value:
What does "fatal error: unexpectedly found nil while unwrapping an Optional value" mean?
fatal error: unexpectedly found nil while unwrapping an Optional value
and it seems that I'm basically trying to retrieve something which isn't there, but the data is saved indeed and I can retrieve it in the console when starting the app. Using the same fetch request I'd expect to get identical results when I load the app and retrieve the data but that's not the case.
What am I missing here? It feels like it should be very basic but for some reason just cannot get it to work after trying for 2 days.
app delegate code to save and retrieve data:
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
// Override point for customization after application launch.
//addTestData()
let fetchRequest = NSFetchRequest(entityName: "Scores")
do {
if let results = try managedObjectContext.executeFetchRequest(fetchRequest) as? [NSManagedObject]{
for result in results {
if let gameScore = result.valueForKey("gameScore") as? Int{
print("Your score is \(gameScore)")
}
}
}
}catch{
print("Error fetching data")
}
return true
}
func addTestData(){
guard let entity = NSEntityDescription.entityForName("Scores", inManagedObjectContext: managedObjectContext) else{
fatalError("Could not find entity description")
}
for i in 1...10{
let score = Scores(entity: entity, insertIntoManagedObjectContext: managedObjectContext)
score.gameScore = i
}
do {
try managedObjectContext.save()
} catch {
// Replace this implementation with code to handle the error appropriately.
// abort() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development.
let nserror = error as NSError
NSLog("Unresolved error \(nserror), \(nserror.userInfo)")
abort()
}
}
Any help would be greatly appreciated!
When you use if let, you are checking to see if it is possible to make the result as an Int. You want to see if that result exists first. Try this:
for result in results {
if let gameScore = result.valueForKey("gameScore") {
print("Your score is \(gameScore as! Int)")
}
}
The issue is the nil NSManagedObjectContext (declared but no value)
By definition executeFetchRequest returns a non-optional array on success and since you are supposed to know from the Core Data model that the entity Scores returns always Scores objects you can safely write
do {
scores = try managedObjectContext.executeFetchRequest(fetchRequest) as! [Scores]
And obviously using a NSManagedObject subclass use the property directly to avoid the type casting. You need the optional binding only if the property gameScore is declared as optional.
for result in results {
if let gameScore = result.gameScore {
print("Your score is \(gameScore)")
}
However for a Int value like a score a non-optional is more reasonable, than you can reduce the code to
for result in results {
print("Your score is \(result.gameScore)")
}
So I did manage to get it working, using the following for managedObjectContext:
let managedContext = AppDelegate().managedObjectContext
I'm still puzzled why I didn't get the error which was specified in the catch but at least it's working now.
Thanks for your answers!
This is my code here found the fatal error.,and it shows the
EXC_BAD_INSTRUCTION(code=EXC_i386_INVOP,subcode=0*0)
let email: NSString = NSUserDefaults.standardUserDefaults().objectForKey("fb_email")! as NSString
It seems like NSUserDefaults.standardUserDefaults().objectForKey("fb_email") is nil. When you try to unwrap it with !, a fatal error occurs.
Try this:
if let object = NSUserDefaults.standardUserDefaults().objectForKey("fb_email") {
// do sth. with object
} else {
// error
}
Trying to implement this raywenderlich tutiorial in swift , but unfortunately I am
fatal error: unexpectedly found nil while unwrapping an Optional value
on line
let acceleration :CMAcceleration = self.motionManager!.accelerometerData.acceleration
Can any body please help why its occuring
please down scene file from here
self.motionManager is nil and you try to unwrap a nil value.Always unwrap optional values by checking for nil with optional binding or use optional chaining.
if let motionManager = self.motionManager {
if let accelerometerData = motionManager.accelerometerData {
let acceleration :CMAcceleration = accelerometerData.acceleration
}
}
else {
print("motion manager is nil")
}
You should check your code if you have intialized motionManager or not.
EDIT
I have checked documentation
Returns the latest sample of accelerometer data, or nil if none is
available.
*/
var accelerometerData: CMAccelerometerData! { get }
So you need to also check nil for accelerometerData.It can be nil and it is Implicitly wrapped optional so it will crash when data not available.
Everything was fine in Xcode beta 5 but now in full fledged Xcode I'm getting 2 similar errors in my App Delegate:
"cannot invoke '!=' with argument list of type '(NSManagedObjectContext, NilLiteralConvertible')"
"cannot invoke '!=' with argument list of type '(NSPersistentStoreCoordinator, NilLiteralConvertible')"
I tried replacing the != with !== and I get a different error. I don't see what the problem is with !=.
The code:
func saveContext () {
var error: NSError? = nil
let managedObjectContext = self.managedObjectContext
if managedObjectContext != nil { //THIS LINE
if managedObjectContext.hasChanges && !managedObjectContext.save(&error) {
// Replace this implementation with code to handle the error appropriately.
// abort() causes the application to generate a crash log and terminate.
//println("Unresolved error \(error), \(error.userInfo)")
abort()
}
}
}
// #pragma mark - Core Data stack
// Returns the managed object context for the application.
// If the context doesn't already exist, it is created and bound to the persistent store coordinator for the application.
var managedObjectContext: NSManagedObjectContext {
if _managedObjectContext !== nil {
let coordinator = self.persistentStoreCoordinator
if coordinator != nil { //THIS LINE
_managedObjectContext = NSManagedObjectContext()
_managedObjectContext!.persistentStoreCoordinator = coordinator
}
}
return _managedObjectContext!
}
var _managedObjectContext: NSManagedObjectContext? = nil
I have a new error: "'NSManagedObjectContext?' does not have a member named 'hasChanges'"
In this code:
func saveContext () {
var error: NSError? = nil
let managedObjectContext = self.managedObjectContext
if managedObjectContext != nil {
if managedObjectContext.hasChanges && !managedObjectContext.save(&error) { //This line
// Replace this implementation with code to handle the error appropriately.
// abort() causes the application to generate a crash log and terminate.
//println("Unresolved error \(error), \(error.userInfo)")
abort()
}
}
}
The reason for this is because NSManagedObjectContext, and probably NSPersistentStoreCoordinator, do not conform to the Equatable protocol. In order to use == and !=, an object needs to conform to this protocol.
=== and !== do not check equality in that sense. These check to see if two objects are in fact the *same object`. Not with similar values. They both point to the same object in memory.
You are able to check this on the two noted types because they are objects. This should work fine for your situation.
About your second issue, your code should look like this:
func saveContext () {
var error: NSError? = nil
let managedObjectContext = self.managedObjectContext
if let moc = managedObjectContext {
if moc.hasChanges && !moc.save(&error) { //This line
// Replace this implementation with code to handle the error appropriately.
// abort() causes the application to generate a crash log and terminate.
//println("Unresolved error \(error), \(error.userInfo)")
abort()
}
}
}
The difference here is if let moc = managedObjectContext: if managedObjectContext is not nil, the value is stored in the constant moc. Otherwise, whatever is inside does not get executed. You can read more about optionals here.
self.managedObjectContext is here typed as an NSManagedObjectContext, not an NSManagedObjectContext?.
You can't compare a var to nil unless it's of type Optional<>, implements Equatable, or is nil itself.