[Fatal error: Unexpectedly found nil while implicitly unwrapping an Optional value]

Hello! I am a beginner in MetaWear iOS development.

I am building the accelerometer logging button by referring to "https://mbientlab.com/iosdocs/latest/logger.html". Below are part of my codes.

class DeviceViewController: UIViewController {
    @State var loggers: [String : OpaquePointer]! 
...
    func accelerometerBMI160StartLog(device: MetaWear) {
        let signal = mbl_mw_acc_bosch_get_acceleration_data_signal(device.board)!
        mbl_mw_datasignal_log(signal, bridge(obj: self)) { (context, logger) in
                    let _self: DeviceViewController = bridge(ptr: context!)
                    let cString = mbl_mw_logger_generate_identifier(logger)!
                    let identifier = String(cString: cString)
                    _self.loggers[identifier] = logger!
                }
        mbl_mw_logging_start(device.board, 0)
            mbl_mw_acc_enable_acceleration_sampling(device.board)
            mbl_mw_acc_start(device.board)
            device.flashLED(color: .blue, intensity: 1.0, _repeat: 3)
    }
...
}

However, I got a runtime error: [Fatal error: Unexpectedly found nil while implicitly unwrapping an Optional value] in line "_self.loggers[identifier] = logger!". I checked other forced unwrapping parts such as "let signal = mbl_mw_acc_bosch_get_acceleration_data_signal(device.board)!" but there is no problem. I guess the possible solution could be modifying something inside the closure or changing the type of "var loggers: [String : OpaquePointer]".
Please give me some advice.

Comments

  • edited August 2021

    @Laura

    Thank you!
    However, the problem is that the functions inside the closure did not work. I putted in three print functions for debugging but nothing printed out. Also the line print("self.log: (self.log)") only prints out "self.log: ".

      mbl_mw_datasignal_log(signal, bridge(obj: self)) { (context, logger) in
            let _self: DeviceViewController = bridge(ptr: context!)
            let cString = mbl_mw_logger_generate_identifier(logger)!
            let identifier = String(cString: cString)
            _self.loggers[identifier] = logger
    
            _self.log = "cString: \(identifier), logger: \(logger)" // for debugging
            print("identifier: \(identifier)")  // for debugging
            print("logger: \(logger)")      // for debugging
            print("logger dict: \(_self.loggers)")  // for debugging
            }
        print("self.log: \(self.log)")
    

    I think this is the cause of my problem. Do I misunderstand anything about this function?

  • Maybe I should specify my question. In the MetaWear document [https://mbientlab.com/iosdocs/latest/logger.html], there is the following code.

    let signal = mbl_mw_gyro_bmi160_get_rotation_data_signal(device.board)!
    mbl_mw_datasignal_log(signal, bridge(obj: self)) { (context, logger) in
        let cString = mbl_mw_logger_generate_identifier(logger)!
        let identifier = String(cString: cString)
        loggers[identifier] = logger! //logger is saved in loggers array
    }
    
    // TIME PASSES //
    
    guard let logger = loggers.removeValue(forKey: "angular-velocity") else { //get logger from loggers array
        return
    }
    mbl_mw_logger_subscribe(logger, bridge(obj: self)) { (context, obj) in
        let acceleration: MblMwCartesianFloat = obj!.pointee.valueAs()
        print(Double(acceleration.x * 0.008), Double(acceleration.y * 0.008), Double(acceleration.z * 0.008),obj!.pointee.epoch)
    }
    

    Which part should I define the dictionary "loggers"? I think the line "bridge(prt: context!)" should be added in order to use the "loggers" property inside the closure.

  • @aleph00 said:
    @Laura

    Thank you!
    However, the problem is that the functions inside the closure did not work. I putted in three print functions for debugging but nothing printed out. Also the line print("self.log: (self.log)") only prints out "self.log: ".

      mbl_mw_datasignal_log(signal, bridge(obj: self)) { (context, logger) in
            let _self: DeviceViewController = bridge(ptr: context!)
            let cString = mbl_mw_logger_generate_identifier(logger)!
            let identifier = String(cString: cString)
          _self.loggers[identifier] = logger
        
            _self.log = "cString: \(identifier), logger: \(logger)"   // for debugging
            print("identifier: \(identifier)")    // for debugging
            print("logger: \(logger)")        // for debugging
            print("logger dict: \(_self.loggers)")    // for debugging
            }
        print("self.log: \(self.log)")
    

    I think this is the cause of my problem. Do I misunderstand anything about this function?

    I tested several things, and I reconfirmed that the closure does not work. I set a breakpoint inside it, but there was no response. I want to know what is going on there.

  • Do you get any print statements at all? Can you share the output?

  • edited August 2021

    Thank you for replying.

    @Laura said:
    Do you get any print statements at all? Can you share the output?

    The print functions inside the closure did not work. The only output is:
    self.log:

    Also, the streaming task works well. The code below prints out real-time accelerometer data.

    mbl_mw_datasignal_subscribe(signal, bridge(obj: self)) { (context, data) in
                let contBridge: DeviceViewController = bridge(ptr: context!)
                let obj: MblMwCartesianFloat = data!.pointee.valueAs()
    
                if (obj.x>0.2||obj.y>0.2){
                    contBridge.log = "\(obj.x), \(obj.y), \(obj.z)"
                    print(contBridge.log)
                    }
                }
    
  • edited August 2021

    I can't comment much without seeing all of your code but there must be an issue with your bridge ptr, is the high level controller in your code even a "DeviceViewController"? Can you try to use some of the code from our examples in github?

Sign In or Register to comment.