Swift / ObjC import from NSData in updated SDK (21.67.00)

Former Member
Former Member

Thanks heaps for the latest updates in the recent SDK version. Having an SPM package for use in both Swift and ObjC based apps is really nice. In the FITDecoder implementation, it expects to take in the filename to a string. Is there a way to decode from an instance of NSData instead of saving the data out to a temporary file?

  • Under the hood, the Obj-C SDK is using the C++ SDK. The C++ SDK encoder and decoder classes both operate on instances of a std::iostream. That gives us two standard options std:fstream and std:stringstream. There is not an efficient path between NSData and std::stringstream, especially when the memory is allocated from Swift. So we opt'd not to support it as part of the initial release.

  • Former Member
    0 Former Member in reply to Ben FIT

    From the swift code, I'm currently saving out a file to the caches directory that can then be read by the FITDecoder. Unfortunately this is constantly throwing C++ runtime exceptions. Do you know what could be causing the problem with the file that gets written and the FITDecoder expecting? 

    The way that I'm saving the data out to a file is via the following swift code

        let sha256 = SHA256.hash(data: data).compactMap { String(format: "%02x", $0) }.joined()
        let filename = "\(sha256).fit"
        guard let url = try? FileManager.default.url(
          for: .cachesDirectory,
          in: .userDomainMask,
          appropriateFor: nil,
          create: true
        ) else {
          return nil
        }
        let fileURL = url.appendingPathComponent(filename)
        try data.write(to: fileURL)
    
        let decoder = FITDecoder()
        let listener = FITListener()
        decoder.mesgDelegate = listener
    
        guard decoder.isFIT(fileURL.path) else {
          throw Errors.invalidFile
        }
    
        guard decoder.checkIntegrity(fileURL.path) else {
          throw Errors.integrityCheckFailed
        }
    
        decoder.decodeFile(url.path)
    

    The exception that gets thrown is from Decode:Resume where there is an unexpected end of input stream.

    "FIT decode error: Unexpected end of input stream at byte: "

  • "Unexpected end of input stream at byte" means that there is an issue with the file. The file is shorter than expected. I would first make sure that the file is actually written to the temp folder, and that the file is valid. Either way, the issue is upstream of the decoder, and the decoder is just reporting the error. Try opening your file in another app. If it does not load there either, then it is an issue with the file.  When encoding the file, make sure that you are calling encoder.close(). See line ~426 in the ActivityEncodeTests example. IT may be that the file is missing the checksum at the end.

  • Note that the Swift Package https://github.com/roznet/FitFileParser that uses the c SDK under the hood instead of the c++ SDK operate on memory, so it has a constructor from data/NSData and file url if that help. it only lets you read and decode though, not encode and write out files.