1

I have made a class in Swift 5.0 that will use the Network module and identify the interface type currently used by the user.

import UIKit
import Network

@objc public class NetworkStrength: NSObject {

    let shared = NetworkStrength()
    var startTime = CFAbsoluteTime()
    var stopTime = CFAbsoluteTime()
    let monitor = NWPathMonitor()

    @objc public var interfaceType = "No Interface connected"
    
    
    @objc public func startMonitoring() {
        
        let queue = DispatchQueue.global(qos: .background)
        monitor.start(queue: queue)
        
        monitor.pathUpdateHandler = { path in
            if path.status == .satisfied {
                print("Connected...")
                let isCellular: Bool = path.usesInterfaceType(.cellular)
                let isWifi: Bool = path.usesInterfaceType(.wifi)
                let isEthernet: Bool = path.usesInterfaceType(.wiredEthernet)
                let isOther: Bool = path.usesInterfaceType(.other)
                let isLoopback: Bool = path.usesInterfaceType(.loopback)
                
                if isCellular {
                    self.interfaceType = "Cellular"
                }else if isWifi {
                    self.interfaceType = "Wifi"
                }else if isEthernet {
                    self.interfaceType = "Wired Ethernet"
                }else if isLoopback {
                    self.interfaceType = "Loopback"
                }else if isOther{
                    self.interfaceType = "Other (Virtual or other undermined network)"
                }else {
                    self.interfaceType = "No interface connected"
                }
                
                print("Interface Type => \(self.interfaceType)")

            }
            else if path.status == .requiresConnection || path.status == .unsatisfied {
                print("Connection not available. Please connect to the internet.")
            }
        }
    }
    
    @objc public func stopMonitoring() {
        monitor.cancel()
    }
}

I have been asked to make a Unity iOS plugin where this code can be used in Unity by calling NetworkStrength.startMonitor() or NetworkStrength.interfaceType. The class is called NetworkStrength as it does have a custom speed test which I can't include because the code will become too big.

I do not have any experience using Objective C. But I have tried the following solutions.

Blog 1 Blog 2

Using these I have created an iOS framework project which has the files

NetworkStrength.swift // which is shown above

NetworkStrength.mm

#import <UIKit/UIKit.h>
#import <NetworkStrength/NetworkStrength-Swift.h>

#pragma mark - C interface
extern "C" {
    
    void _startMonitoring() {
        [[NetworkStrength shared] startMonitoring];
    }
    
    void _stopMonitoring() {
        [[NetworkStrength shared] stopMonitoring];
    }
    
    char* _returnInterfaceType() {
         NSString *returnString = [[NetworkStrength shared] interfaceType];
         char* cStringCopy(const char* string);
         return cStringCopy([returnString UTF8String]);
    }
}

char* cStringCopy(const char* string){
     if (string == NULL){
          return NULL;
     }
     char* res = (char*)malloc(strlen(string)+1);
     strcpy(res, string);
     return res;
}

and

NetworkStrength.h as suggested in this link apple documentation which contains

@class NetworkStrength;

and setting Defines Module to Yes. I built the project and there were no errors.

So, I went ahead and created a new unity project housing all the above files inside Assets/Plugins/iOS/NetworkStrength/Source. Just like the blog said I created a NetworkStrength.cs file containing the following code.

using System;
using System.Runtime.InteropServices;
using UnityEngine;

public class NetworkStrength : MonoBehaviour {

    #region Declare external C interface
   
    #if UNITY_IOS && !UNITY_EDITOR
        
    [DllImport("__Internal")]
    private static extern void _startMonitoring();

    [DllImport("__Internal")]
    private static extern void _stopMonitoring();


    [DllImport("__Internal")]
    private static extern void _returnInterfaceType();
    
    #endif
   
    #endregion
   
    #region Wrapped methods and properties
    public static void StartMonitoring() {
        #if UNITY_IOS && !UNITY_EDITOR
        _startMonitoring();
        #endif
    }

    public static void StopMonitoring() {
        #if UNITY_IOS && !UNITY_EDITOR
        _stopMonitoring();
        #endif
    }

    public static void ReturnInterfaceType() {
        #if UNITY_IOS && !UNITY_EDITOR
        _returnInterfaceType();
        #endif
    }

   #endregion
   
   #region Singleton implementation

   private static NetworkStrength _instance;
    
   public static NetworkStrength Instance
   {
    get
        {
            if (_instance == null)
            {
                var obj = new GameObject("NetworkStrength");
                _instance = obj.AddComponent<NetworkStrength>();
            }

            return _instance;
        }
    }

    private void Awake()
    {
        if (_instance != null)
        {
            Destroy(gameObject);
            return;
        }
        
        DontDestroyOnLoad(gameObject);
    }

    #endregion
}


and added SwiftPostProcessor.cs to Assets/Plugins/iOS/NetworkStrength/Editor containing the following code.

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEditor;
using UnityEditor.Callbacks;
using UnityEditor.iOS.Xcode;
using System.Diagnostics;

using System.IO;
using System.Linq;

public static class SwiftPostProcess {

    [PostProcessBuild]
    public static void OnPostProcessBuild(BuildTarget buildTarget, string buildPath)
    {
        if (buildTarget == BuildTarget.iOS)
        {
            var projPath = buildPath + "/Unity-Iphone.xcodeproj/project.pbxproj";
            var proj = new PBXProject();
            proj.ReadFromFile(projPath);

            var targetGuid = proj.GetUnityFrameworkTargetGuid() ;
            //// Configure build settings
            proj.SetBuildProperty(targetGuid, "ENABLE_BITCODE", "NO");
            proj.SetBuildProperty(targetGuid, "SWIFT_OBJC_BRIDGING_HEADER", "Libraries/Plugins/iOS/NetworkStrength/Source/NetworkStrength.h");
            proj.SetBuildProperty(targetGuid, "SWIFT_OBJC_INTERFACE_HEADER_NAME", "NetworkStrength-Swift.h");
            proj.AddBuildProperty(targetGuid, "LD_RUNPATH_SEARCH_PATHS", "@executable_path/Frameworks");

            proj.WriteToFile(projPath);
        }
    }

}

Having made this I built the project to see if there are any errors. The first error I got was

'NetworkStrength/NetworkStrength-Swift.h' file not found. I tried various solutions but I kept getting the same error every time. I can't seem to solve this issue. Please help me solve this issue.

PS. I tried NetworkStrength-Bridging-Header.h just like what the blog said but I kept getting the error: using bridging headers with framework targets is unsupported. I followed what was suggested in this solution.

Dávid Pásztor
  • 51,403
  • 9
  • 85
  • 116
Aneesh Prabu
  • 165
  • 1
  • 8

0 Answers0