如何防止UIViewController被弹出?

时间:2017-11-15 04:34:29

标签: ios swift uiviewcontroller

我有一个从parentViewController推送的childViewController。在childViewController中,我想阻止特定条件下的弹出动作。

我在viewWillDisappear中编写了这段代码:但我想在其他地方需要这样做。

override func viewWillDisappear(_ animated: Bool) {
    super.viewWillDisappear(animated)

    if changesMade {
        let alertController = UIAlertController(title: "Alert", message: "Changes made are not saved. Do you wish to save changes made?", preferredStyle: .alert)

        let cancelOption = UIAlertAction(title: "Cancel", style: .cancel)
        let saveOption = UIAlertAction(title: "Save", style: .default, handler: { (action) in
            self.saveSession()
        })

        alertController.addAction(saveOption)
        alertController.addAction(cancelOption)
        present(alertController, animated: true)
    }
}

4 个答案:

答案 0 :(得分:0)

阻止弹出操作,直到您的更改未像此一样保存

null

更新 - 在父视图控制器中推送的子视图控制器中添加以下自定义按钮及其操作 所以,如果不满足您的条件,用户不能再次从孩子搬到父母那里

要自定义导航backButton的动作,你需要使用下面的行手动添加一个后退按钮,你可以在DidLoad中添加自定义barButton

@echo off
setlocal

@echo off

set JAVA_SERVICE_EXE=libertyserver.exe
...
....
set SERVICE_DISPLAY_NAME="%LIBERTY_SERVICE_NAME%"
set SERVICE_DESCRIPTION="%LIBERTY_SERVICE_NAME%"

echo Stopping and Deleting existing services

for /F "tokens=3 delims=: " %%H in ('sc query %SERVICE_NAME% ^| findstr "STATE" ') do (
  if /I "%%H" EQU "RUNNING" (
   sc stop %SERVICE_NAME% >nul 2>&1
   timeout /t 30 /nobreak >nul 2>&1
  )

sc delete %SERVICE_NAME% >nul 2>&1
  timeout /t 30 /nobreak >nul 2>&1
)

for /f "tokens=2" %%a in ('tasklist^|find /i "libertyserver.exe"') do (taskkill.exe /f /pid %%a >nul 2>&1)

echo Installing liberty profile %SERVICE_NAME%

set INSTALL_SERVICE_COMMAND=%DAEMON_EXEC% //IS//%SERVICE_NAME% --Startup=manual --DisplayName=%SERVICE_DISPLAY_NAME% --Description=%SERVICE_DESCRIPTION% ++DependsOn=Tcpip --LogPath=%LOG_PATH% --StdOutput=auto --StdError=auto --StartMode=exe --StartPath=%SERVER_START_COMMAND_PATH% --StartImage=%SERVER_START_COMMAND% --StartParams=start#SIServer --StopMode=exe --StopPath=%SERVER_STOP_COMMAND_PATH% --StopImage=%SERVER_STOP_COMMAND% --StopParams=stop#SIServer
%INSTALL_SERVICE_COMMAND%

echo Installed liberty profile %SERVICE_NAME%

它将执行所需的操作

if changesMade {
        let alertController = UIAlertController(title: "Alert", message: "Changes made are not saved. Do you wish to save changes made?", preferredStyle: .alert)

        let cancelOption = UIAlertAction(title: "Cancel", style: .cancel)
        let saveOption = UIAlertAction(title: "Save", style: .default, handler: { (action) in
            self.saveSession()
            self.navigationController?.popViewController(animated: true)
        })

        alertController.addAction(saveOption)
        alertController.addAction(cancelOption)
        present(alertController, animated: true)
    }

我不认为你可以停止导航控制器的默认后退按钮动作任务,因为它的设计方式是执行它

但是,您可以在ViewWillDisappear中将其作为:

进行管理
 self.navigationItem.leftBarButtonItem = UIBarButtonItem(title: "Back", style: UIBarButtonItemStyle.plain, target: self, action: #selector(self.backToInitial(sender:)))

-----------------重新更新---------------

在swift中我使用了一个Objective-C类来获得预期的输出,childViewController pop动作是一个使用我们从导航控制器获得的默认后退按钮的警报控制器

您可以自定义要执行的弹出操作,直到您的条件不满意为止 Github Link - https://github.com/RockinGarg/NavigationBackButton.git

答案 1 :(得分:0)

这里有两种情况:

  1. 用户可以使用后退按钮弹出。
  2. 用户可以使用导航控制器的交互式弹出手势弹出。
  3. 我认为您应该使用自定义后退按钮并将其命名为完成,并在按下此按钮时编写显示警报的逻辑。 使用自定义后退按钮将默认禁用交互式弹出手势,您将免于在导航控制器上播放启用/禁用interactivePopGesture的舞蹈。

答案 2 :(得分:0)

实际上,有一个非常简单的解决方案:navigationItem.hidesBackButton = true-这将隐藏“ BACK”按钮,并禁用“轻扫”功能。

答案 3 :(得分:-1)

(我认为)我找到了一个更为优雅的解决方案。

无论用户如何触发弹出窗口(可访问性转义,向后轻扫手势,向后轻击),它都有效,因为它会覆盖系统使用的内置弹出方法。

雨燕5

public class DiscardSafeNavigationController:UINavigationController {
    /// Should the pop be prevented? Set this to `true` when you have changes which need to be protected
    public var hasUnsavedChanges:Bool = false

    /// Show a prompt on the top most screen asking the user if they wish to proceed with the pop
    /// - Parameter discardCallback: The callback to use if the user opts to discard
    private func confirmDiscardChanges(discardCallback:@escaping (()->())) {
        let alertController = UIAlertController.init(title: "Discard changes", message: "Are you sure you want to discard any unsaved changes?", preferredStyle: UIAlertController.Style.alert)
        alertController.addAction(UIAlertAction.init(title: "Discard", style: UIAlertAction.Style.destructive, handler: { (_) in
            discardCallback()
            //User elected to discard and so, at this point, they no longer have changes to save
            self.hasUnsavedChanges = false
        }))
        alertController.addAction(UIAlertAction.init(title: "Cancel", style: UIAlertAction.Style.cancel, handler: nil))
        self.topViewController?.present(alertController, animated: true, completion: nil)
    }

    override func popViewController(animated: Bool) -> UIViewController? {
        //If there aren't unsaved changes, popping is safe
        if !hasUnsavedChanges {
            return super.popViewController(animated: animated)
        }else {
            //Changes have been made. Block the pop and first check with the user before continuing
            confirmDiscardChanges {
                super.popViewController(animated: animated)
            }
            return nil
        }
    }


}

,当您想从任何子视图控制器启用丢弃保护时,只需使用:

(self.navigationController as? DiscardSafeNavigationController)?.hasUnsavedChanges = true

,然后每当要求导航控制器弹出它时,导航控制器都会首先询问用户。