Swift:将参数用作同一函数中其他参数的默认值

时间:2018-12-05 11:09:19

标签: ios swift

我正在尝试定义一个函数来展示邮件编写器。它使用委托人和演示者UIViewController作为参数(并不总是相同),但是对于演示者和委托人相同的UIViewController,我将不提供默认值。那可能吗?

internal func showMailComposer(presenterController: UIViewController, delegate: UIViewController = presenterController, recipient: String = "", subject: String = "", body: BodyMessage = BodyMessage(string: "", isHTML: false)) {

    guard let delegate = delegate as? MFMailComposeViewControllerDelegate else { return }

    // ...
}

3 个答案:

答案 0 :(得分:1)

使用默认的delegatenil设为 Optional ,然后使用??对其进行拆包,或者如果没有提供presenterController,则将其替换为internal func showMailComposer(presenterController: UIViewController, delegate: UIViewController? = nil, recipient: String = "", subject: String = "", body: BodyMessage = BodyMessage(string: "", isHTML: false)) { guard let delegate = (delegate ?? presenterController) as? MFMailComposeViewControllerDelegate else { return } // ... }

module Service

open Microsoft.ServiceFabric.Services.Runtime
open Microsoft.ServiceFabric.Services.Communication.Runtime
open Microsoft.ServiceFabric.Services.Communication.AspNetCore
open Microsoft.AspNetCore.Hosting
open Microsoft.Extensions.Configuration
open System.Fabric

let setBasePath path config =
    FileConfigurationExtensions.SetBasePath (config, path)

let addJson path optional reloadOnChange config =
    JsonConfigurationExtensions.AddJsonFile(config, path, optional, reloadOnChange)

type Service(context) =
    inherit StatelessService(context)

    let configureAppConfiguration (builder : IWebHostBuilder) =
        builder.ConfigureAppConfiguration(fun builderContext config ->
            let envAppsettings = sprintf "appsettings.%s.json" builderContext.HostingEnvironment.EnvironmentName

            config
                |> setBasePath builderContext.HostingEnvironment.ContentRootPath
                |> addJson "appsettings.json" false false
                |> addJson envAppsettings true false
                |> addJson "PackageRoot/Config/eventFlowConfig.json" true true
                |> EnvironmentVariablesExtensions.AddEnvironmentVariables
                |> ignore
        )

    let configureServices (ctx:ServiceContext) (builder : IWebHostBuilder) =
        builder.ConfigureServices(fun s -> s.AddSingleton<StatelessServiceContext>(ctx))

    let useStartup (builder: IWebHostBuilder) =
        builder.UseStartup<Startup>()

    let useServiceFabricIntegration listener (builder: IWebHostBuilder) =
        builder.UseServiceFabricIntegration(listener, ServiceFabricIntegrationOptions.None)

    let useUrl url (builder: IWebHostBuilder) =
        builder.UseUrls([|url|])

    let build (builder: IWebHostBuilder) =
        builder.Build()    

    let builder (ctx:ServiceContext) = fun (url:string) (listener:AspNetCoreCommunicationListener) ->  

            Microsoft.AspNetCore.WebHost.CreateDefaultBuilder()
                |> configureAppConfiguration
                |> configureServices ctx
                |> useStartup
                |> useServiceFabricIntegration listener
                |> useUrl url
                |> build


    let kestrelCommunicationListener (ctx:ServiceContext) =
        let build  = builder ctx
        let f = new System.Func<string, AspNetCoreCommunicationListener, IWebHost>(build)

        new KestrelCommunicationListener(ctx, "ServiceEndPoint", f) :> ICommunicationListener

    let serviceInstanceListener () =  new ServiceInstanceListener(fun ctx -> kestrelCommunicationListener ctx)    

    override __.CreateServiceInstanceListeners() = 

        seq {
                yield serviceInstanceListener()
            }

答案 1 :(得分:1)

就像0xa6a一样,我认为这是不可能的,因为默认值应该在编译时可用。实现类似行为的另一种方法是将参数转换为对象并在其中实现逻辑。这只是个人喜好和风格的问题。这是一个建议:

struct Mail{
   let recipient: String = ""
   let subject: String = ""
   let body: BodyMessage = BodyMessage(string: "", isHTML: false)
}

struct MailPresenter{

   weak var presenter : UIViewController?
   weak var delegate : MFMailComposeViewControllerDelegate?

   init(using presenter: UIViewController?, mailDelegate: MFMailComposeViewControllerDelegate? = nil){

      self.presenter = presenter

      if let mailDelegate = mailDelegate{
        self.delegate = mailDelegate
      }else{
        self.delegate = presenter as? MFMailComposeViewControllerDelegate
      }
    }
 }
internal func showMailComposer(from presenter: MailPresenter , for mail: Mail = Mail() ) {

}

您可以像这样使用它:

showMailComposer(from: MailPresenter(using: yourViewController))

答案 2 :(得分:0)

我认为您无法在Swift中做到这一点。即使有可能,这看起来也很奇怪。

ps:

为什么不将参数presenterController定义为MFMailComposeViewControllerDelegate。这样会更明确:

internal func showMailComposer(presenterController: UIViewController, delegate: MFMailComposeViewControllerDelegate, recipient: String = "", subject: String = "", body: BodyMessage = BodyMessage(string: "", isHTML: false)) {

    // ...
}