Реализация класса Swift 5.0 в Unity версии 2019 - PullRequest
1 голос
/ 09 июля 2020

Я создал класс в Swift 5.0, который будет использовать сетевой модуль и определять тип интерфейса, используемый в настоящее время пользователем.

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()
    }
}

Меня попросили создать плагин Unity iOS, где этот код можно использовать в Unity, вызвав NetworkStrength.startMonitor () или NetworkStrength.interfaceType. Класс называется NetworkStrength, поскольку у него есть специальный тест скорости, который я не могу включить, потому что код станет слишком большим.

У меня нет опыта использования Objective C. Но я пробовал следующие решения.

Блог 1 Блог 2

Используя их, я создал проект фреймворка iOS, который имеет files

NetworkStrength.swift // который показан выше

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;
}

и

NetworkStrength.h, как указано в этой ссылке документация Apple , которая содержит

@class NetworkStrength;

и для параметра Defines Module значение Yes. Я построил проект, и ошибок не было.

Итак, я пошел дальше и создал новый проект единства, в котором все указанные файлы находятся внутри Assets / Plugins / iOS / NetworkStrength / Source. Как сказано в блоге, я создал файл NetworkStrength.cs, содержащий следующий код.

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
}


и добавил SwiftPostProcessor.cs в Assets / Plugins / iOS / NetworkStrength / Editor, содержащий следующий код.

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);
        }
    }

}

Сделав это, я построил проект, чтобы посмотреть, нет ли ошибок. Первая ошибка, которую я получил, была

Файл NetworkStrength / NetworkStrength-Swift.h не найден. Я пробовал разные решения, но каждый раз получал одну и ту же ошибку. Кажется, я не могу решить эту проблему. Помогите, пожалуйста, решить эту проблему.

PS. Я попробовал NetworkStrength-Bridging-Header.h, как и в блоге, но продолжал получать ошибку: использование заголовков моста с целями фреймворка не поддерживается. Я последовал тому, что было предложено в этом решении .

...