Swift开发:如何检查我的本地开发api服务器是否正在运行?

时间:2016-08-18 23:05:58

标签: ios swift

开发连接到api服务器的iOS应用程序,如果本地服务器正在运行,我希望应用程序连接到http://localhost:3000的本地开发api服务器。否则,应用程序应连接到生产服务器,例如https://example.com

如何检查本地api服务器是否正在运行?

这仅在iOS模拟器中是必需的,而不是在真实的应用程序中。

2 个答案:

答案 0 :(得分:1)

如果您正在开发一个应用程序并且正在组织生产代码,那么您应该至少拥有两个不同的构建版本。理想情况下,您最多可以有3个,一个用于开发,一个用于分段,一个用于生产。

在您的XCode项目中,您可以配置多个构建目标,然后可以将这些目标与iTunes Connect中的不同应用相关联,这样您就可以始终确保您的更改以开发构建为目标。

您真的不希望您的生产应用程序检查您的开发服务器API,因为您不希望您的用户在您处理更新时遇到该服务器。

This is a good starting point要设置目标,您可以立即启动并运行。有了这些不同的目标,您就可以为每个构建配置一个新的info.plist,并且总是一个好主意,也可以有一个不同的应用程序图标,让您知道您正在测试或使用不同的目标。

然后,您可以为每个目标配置所需数量的配置文件,配置文件可能如下所示:

Config.plist(以xml格式)

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "...">
<plist version="1.0">
    <dict>
        <key>ClientId</key>
        <string>{SomeIdValue}</string>
        <key>ClientSecret</key>
        <string>{ClientSecret}</string>
        <key>ServerUrl</key>
        <string>{my.target.apiEndpoint}</string>
    </dict>
</plist>

然后,您可以拥有一个为您的应用程序提供正确的API端点配置的提供程序,如下所示(使用config.plist进行生产,使用configDebub.plist进行调试):

struct ConfigProvider {

#if DEVELOPMENT
let name: String = "configDebug"
#else
let name: String = "config"
#endif

enum ConfigError: ErrorType {
    case FileNotWritten
    case FileDoesNotExist
}

var sourcePath:String? {
    guard let path = NSBundle.mainBundle().pathForResource(name, ofType: "plist") else { return .None }
    return path
}

var destPath:String? {
    guard sourcePath != .None else { return .None }
    let dir = NSSearchPathForDirectoriesInDomains(.DocumentDirectory, .UserDomainMask, true)[0]
    return (dir as NSString).stringByAppendingPathComponent("\(name).plist")
}

init?() {
    let fileManager = NSFileManager.defaultManager()

    guard let source = sourcePath else { return nil }
    guard let destination = destPath else { return nil }
    guard fileManager.fileExistsAtPath(source) else { return nil }

    if !fileManager.fileExistsAtPath(destination) {
        do {
            try fileManager.copyItemAtPath(source, toPath: destination)
        } catch let error as NSError {
            print("Unable to copy file. ERROR: \(error.localizedDescription)")
            return nil
        }
    }
}

func getConfig() -> NSDictionary?{
    let fileManager = NSFileManager.defaultManager()
    if fileManager.fileExistsAtPath(destPath!) {
        guard let dict = NSDictionary(contentsOfFile: destPath!) else { return .None }
        return dict
    } else {
        return .None
    }
}

func getServerUrl() -> String {
    if let c = getConfig()?["ServerUrl"] {
        return c as! String
    }
    // Handle error
}

func getClientSecret() -> String {
    if let c = getConfig()?["ClientSecret"] {
        return c as! String
    }
    // Handle error
}

func getClientId() -> String {
    if let c = getConfig()?["ClientId"] {
        return c as! String
    }
    // Handle error
}

func getMutablePlistFile() -> NSMutableDictionary?{
    let fileManager = NSFileManager.defaultManager()
    if fileManager.fileExistsAtPath(destPath!) {
        guard let dict = NSMutableDictionary(contentsOfFile: destPath!)     else { return .None }
            return dict
        } else {
        return .None
        }
    }
}

然后您可以将详细信息配置为:

private static let config = ConfigProvider()!
private let clientId = config.getClientId()
private let clientSecret = config.getClientSecret()
private let serverUrl = config.getServerUrl()

希望这有帮助!

答案 1 :(得分:0)

假设,在启动过程中的某个时刻,visitEntryPointUrl()被调用。

  func visitEntryPointUrl() {
    if Device.isSimulator {
      visitLocalServerIfRunningAndProductionServerOtherwiese()
    } else {
      visit(self.productionEntryPointUrl)
    }
  }

检查它是否是模拟器

// Device.swift
import Foundation
struct Device {
  // https://stackoverflow.com/a/30284266/2066546
  static var isSimulator: Bool {
    return TARGET_OS_SIMULATOR != 0
  }
}

我从https://stackoverflow.com/a/30284266/2066546获取了这个技巧。

检查本地服务器是否正在运行

  func visitLocalServerIfRunningAndProductionServerOtherwiese() {
    let testSessionConfiguration = 
        NSURLSessionConfiguration.defaultSessionConfiguration()
    testSessionConfiguration.timeoutIntervalForRequest =
        NSTimeInterval(1) // seconds
    testSessionConfiguration.timeoutIntervalForResource =
        NSTimeInterval(1) // seconds
    let testSession = NSURLSession(configuration: testSessionConfiguration)
    let task = testSession.dataTaskWithURL(self.developmentEntryPointUrl) { 
        (data, response, error) -> Void in

      // https://stackoverflow.com/a/28321213/2066546,   
      // https://stackoverflow.com/a/33715865/2066546
      dispatch_async(dispatch_get_main_queue()) { 
        if data != nil {
          print("local server running. connecting to \(self.developmentEntryPointUrl)")
          self.visit(self.developmentEntryPointUrl)
        } else {
          print("server not running. connecting to \(self.productionEntryPointUrl)")
          self.visit(self.productionEntryPointUrl)
        }
      }
    }
    task.resume()
  }

参考