0

I'm developing a react native application on a M1 Pro Macbook, and I'm having this error when calling a NativeModule.

Fatal error: Unexpectedly found nil while unwrapping an Optional value

The NativeModule method that I'm calling is like a "middleware" to make request to backend services that don't accept requests coming directly from JS.

This is my NativeModule Swift file:

import Foundation

@objc(Request)
class Request: NSObject {
  
  @objc
  func makeRequest(_ requestUrl: String, requestQuery: String, token: String, resolve: @escaping RCTPromiseResolveBlock,  reject: @escaping RCTPromiseRejectBlock) -> Void {
    let url = URL(string: requestUrl+requestQuery)!
    var request = URLRequest(url: url)
    
    if(!token.isEmpty) {
      request.setValue("Bearer "+token, forHTTPHeaderField: "Authorization")
    }
    
    let task = URLSession.shared.dataTask(with: request) { data, response, error in
      if let data = data {
        resolve(String(data: data, encoding: .utf8) )
      } else if let error = error {
        reject("500", "error", error)
      }
    }
    task.resume()
  }
  
  @objc static func requiresMainQueueSetup() -> Bool {
      return true
  }
  
}

The Obj-C file to expose it to the bridge:

#import <Foundation/Foundation.h>
#import "React/RCTBridgeModule.h"

@interface RCT_EXTERN_MODULE(Request, NSObject)

RCT_EXTERN_METHOD(makeRequest: (NSString)requestUrl requestQuery: (NSString)requestQuery token: (NSString)token resolve:(RCTPromiseResolveBlock)resolve reject:(RCTPromiseRejectBlock)reject)

@end

And that's my call to the NativeModule on React Native side:

import AsyncStorage from '@react-native-async-storage/async-storage';
import {NativeModules} from 'react-native';
import {INSTANCE_URL} from '../config/salesforce';
import {STORAGE_ITEMS} from '../constants/async-storage.constants';

export const executeQuery = async (query: string): Promise<any> => {
  const token = await AsyncStorage.getItem(STORAGE_ITEMS.TOKEN);

  if (!token) {
    //throw unauthorized and go back to login page
  }

  const response = await NativeModules.Request.makeRequest(
    `${INSTANCE_URL}/services/data/v54.0/query/?q=`,
    query,
    token,
  );
  return JSON.parse(response);
};

This same NativeModule call is working on Android, so it seems to be a problem with the communication between React < - > iOS, or on the params definition.

Can you guys help me please?

1 Answer 1

1

Just found the solution for the ones that may be having the same problem.

That's the reason: https://developer.apple.com/documentation/foundation/nsurlrequest#1776617

Authorization is a Reserved HTTP Header, so I had to set him through the URLSessionConfiguration, like that:

let sessionConfiguration = URLSessionConfiguration.default
sessionConfiguration.httpAdditionalHeaders = [
    "Authorization": token
]
let session = URLSession(configuration: sessionConfiguration)

This solved the problem for me. My final code for the swift file looks like that:

import Foundation

@objc(Request)
class Request: NSObject {
  
  @objc
  func makeRequest(_ requestUrl: String, requestQuery: String, token: String, resolve: @escaping RCTPromiseResolveBlock,  reject: @escaping RCTPromiseRejectBlock) -> Void {
    let stringUrl: String = requestUrl + requestQuery
    let url = URL(string: stringUrl.addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed)!)!
    let request = URLRequest(url: url)

    let sessionConfiguration = URLSessionConfiguration.default
    sessionConfiguration.httpAdditionalHeaders = [
        "Authorization": token
    ]
    let session = URLSession(configuration: sessionConfiguration)

    
    let task = session.dataTask(with: request) { data, response, error in
      if let data = data {
        resolve(String(data: data, encoding: .utf8) )
      } else if let error = error {
        reject("500", "error", error)
      }
    }
    task.resume()
  }
  
  @objc static func requiresMainQueueSetup() -> Bool {
      return true
  }
  
}
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.