2016-12-26 142 views
2

我有一个警报视图,我正试图在照片视图中呈现。试图在已经呈现的视图控制器上呈现UIAlertController(空)[Swift]

照片显示在列表中,可以推送到全屏视图。

以编程方式显示照片视图。我认为这就是导致问题的原因,因为警报视图试图在已经呈现的(照片)视图的顶部呈现另一个视图。

警报视图试图显示,但得到这个错误:

Warning: Attempt to present <UIAlertController: 0x147d2c6b0> on <LiveDeadApp.ListViewController: 0x147d614c0> which is already presenting (null) 

,可能是有问题的线,这是一个:

self.present(textPrompt, animated: true, completion: nil) 

这是主列表视图 This is the main list view

这是拍摄屏幕截图时的主要列表视图 This is the main list view when a screenshot is taken

这是主要的照片视图 This is the main photo view

这是在主照片视图的酥料饼(通过 “i” 按钮访问) This is the popover in the main photo view (accessed via the "i" button)

当屏幕截图在主照片视图中被采用,不会发生警报视图。但是,当设备的方向发生变化时,照片视图会回到列表并显示警报。 When a screenshot is taken on the main photo view, no alert view occurs. However, when the device's orientation is changed, the photo view goes back to the list and shows the alert.

这就是我要做的: enter image description here

斯威夫特3 iOS的10

谢谢!

这里是列表视图和图片浏览的代码:

import UIKit 
import Kingfisher 
import SKPhotoBrowser 

class ListViewCell: UITableViewCell { 

@IBOutlet weak var Cellimage: UIImageView! 

@IBOutlet weak var cellVenue: UILabel! 

@IBOutlet weak var cellLocation: UILabel! 

@IBOutlet weak var cellDate: UILabel! 
@IBOutlet weak var aiView: UIActivityIndicatorView! 
} 

class ListViewController: UITableViewController { 

var subcategory:Subcategory! 

var objects:[[String:String]] = [[String:String]]() 

var images = [SKPhotoProtocol]() 



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


} 

override func viewDidLoad() { 
    super.viewDidLoad() 


    self.tableView.separatorStyle = .none 

    self.view.backgroundColor = UIColor.black 

    self.navigationController?.navigationBar.titleTextAttributes = [NSForegroundColorAttributeName: UIColor.white] 

    navigationController!.navigationBar.barTintColor = UIColor.black 

    let requireTextInput = "require text input" 
    // add observer for screen shot 
    NotificationCenter.default.addObserver(forName: NSNotification.Name.UIApplicationUserDidTakeScreenshot, object: nil, queue: OperationQueue.main, using: 
     { notification in 

      self.definesPresentationContext = true 

      var inputTextField = UITextField() 

      let textPrompt = UIAlertController(title: "Test!", message: "Testing!", preferredStyle: .alert) 

      textPrompt.addAction(UIAlertAction(title: "Continue", style: .default, handler: { 
       (action) -> Void in 
       // if the input match the required text 

       let str = inputTextField.text 
       if str == requireTextInput { 
        print("right") 
       } else { 
        print("wrong") 
       } 

      })) 

      textPrompt.addTextField(configurationHandler: {(textField: UITextField!) in 
       textField.placeholder = "" 
       inputTextField = textField 

      }) 

      self.present(textPrompt, animated: true, completion: nil) 

    }) 

    if subcategory != nil { 
     self.title = subcategory.title 
     self.objects = subcategory.photos 

     createLocalPhotos() 

     self.tableView.reloadData() 
    } 


} 

func createLocalPhotos() { 

    for item in objects { 
     let photo = SKPhoto.photoWithImageURL(item["url"]!) 
     photo.shouldCachePhotoURLImage = true 
     images.append(photo) 
    } 

} 

override func didReceiveMemoryWarning() { 
    super.didReceiveMemoryWarning() 
} 

override func numberOfSections(in tableView: UITableView) -> Int { 
    return 1 
} 

override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { 
    return objects.count 
} 

override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { 

    let cell: ListViewCell = tableView.dequeueReusableCell(withIdentifier: "Cell") as! ListViewCell 

    let item = objects[indexPath.row] 

    let title = item["title"] 
    let location = item["location"] 
    let date = item["date"] 
    let urlSrt = item["url"] 


    cell.cellVenue.text = title 
    cell.cellLocation.text = location 
    cell.cellDate.text = date 

    if let url = URL(string: urlSrt!) { 
     cell.aiView.startAnimating() 
     cell.Cellimage.kf.setImage(with: url, placeholder: nil, options: nil, progressBlock: nil, completionHandler: { (image, error, cacheType, url) in 
      cell.aiView.stopAnimating() 
     }) 
    } 

    return cell 

} 

override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { 
    let cell = tableView.cellForRow(at: indexPath) as! ListViewCell 

    if(cell.Cellimage.image != nil) { 
     SKPhotoBrowserOptions.displayToolbar = false 
     SKPhotoBrowserOptions.displayCounterLabel = false 
     SKPhotoBrowserOptions.displayBackAndForwardButton = false 
     SKPhotoBrowserOptions.displayAction = false 
     SKPhotoBrowserOptions.displayDeleteButton = true 
     SKPhotoBrowserOptions.displayHorizontalScrollIndicator = false 
     SKPhotoBrowserOptions.displayVerticalScrollIndicator = false 
     SKPhotoBrowserOptions.displayStatusbar = false 
     SKPhotoBrowserOptions.disableVerticalSwipe = true 
     SKPhotoBrowserOptions.bounceAnimation = false 
     let browser = ExtendedSKPhotoBrowser(originImage: cell.Cellimage.image!, photos: images, animatedFromView: cell) 

     let btnSize = 80//24 * UIScreen.main.scale 

     browser.updateCloseButton(UIImage(named: "ic_close_white")!, size: CGSize(width: btnSize, height: btnSize)) 
     browser.updateDeleteButton(UIImage(named: "ic_info_white")!, size: CGSize(width: btnSize, height: btnSize)) 
     browser.initializePageIndex(indexPath.row) 
     browser.delegate = self 
     present(browser, animated: true, completion: {}) 
     browser.toggleControls() 
    } 
} 

override var prefersStatusBarHidden: Bool { 
    get { 
     return true 
    } 
} 


var popOverVC:PopUpViewController! 
} 

extension ListViewController: SKPhotoBrowserDelegate { 
func didShowPhotoAtIndex(_ index: Int) { 






} 

func willDismissAtPageIndex(_ index: Int) { 

} 

private func willShowActionSheet(photoIndex: Int) { 
    // do some handle if you need 
} 

func didDismissAtPageIndex(_ index: Int) { 
} 

func didDismissActionSheetWithButtonIndex(_ buttonIndex: Int, photoIndex: Int) { 
    // handle dismissing custom actions 
} 

func removePhoto(_ browser: SKPhotoBrowser, index: Int, reload: (() -> Void)) { 
    popOverVC = self.storyboard?.instantiateViewController(withIdentifier: "sbPopUpID") as! PopUpViewController 
    popOverVC.photoData = objects[index] 

} 

func viewForPhoto(_ browser: SKPhotoBrowser, index: Int) -> UIView? { 
    return tableView.cellForRow(at: IndexPath(row: index, section: 0)) 
} 
} 


open class ExtendedSKPhotoBrowser: SKPhotoBrowser { 

open override var preferredStatusBarStyle: UIStatusBarStyle { 
    return .lightContent // white statusbar, .default is black 
} 

open override var prefersStatusBarHidden: Bool { 
    return true 
} 
} 
+0

只有当您尝试呈现已经呈现的控制器(或呈现任何其他控制器)时才会出现此错误。检查你是否在你的代码中出现过两次“UIAlertController”。 –

+0

@KrishnaDattShukla这是我提出警报控制器的唯一地方。虽然,我也展示了一个popover控制器。 – Miles

+0

我认为你同时提出了popover和alert。这就是产生这个错误的原因。解除弹出窗口后显示警报控制器。 –

回答

2

问题非常简单,你显示在当前呈现的UIAlertController上另一个UIAlertController

So, how do we solve such case?

  1. 你需要得到总UIAlertController的列表,您在当前视图控制器会使用。

  2. 如果您正在进行异步请求,您必须检查如何在当前视图控制器或其他视图控制器中显示警报的逻辑。

  3. 当您想要显示另一个警报时,您的代码必须与此类似。

假设loadingAlert是当前一个将其显示在屏幕上。

self.loadingAlert.dismiss(animated: true, completion: { 
    let anotherAlert = UIAlertController(title: "New One", message: "The Previous one is dismissed", preferredStyle: .alert) 
    let okAction = UIAlertAction(title: "OK", style: .default, handler: nil) 
    anotherAlert.addAction(okAction) 
    self.present(anotherAlert, animated: true, completion: nil) 
}) 

您必须在另一个出现之前关闭第一个。我做出了这个回答,因为没有按钮就关闭了警报。所以,加载警报的按钮更少。

So, how about the alert with action buttons?

It will dismiss automatically when you clicked one of the action buttons on UIAlertController that you created.

但是,如果您显示两个同时包含UIButton的UIAlertController,那么问题仍然会发生。所以,你需要检查每个逻辑回来,否则你可以在每个动作的处理程序办理:

self.connectionErrorAlert.dismiss(animated: true, completion: { 
    let anotherAlert = UIAlertController(title: "New One", message: "The Previous one is dismissed", preferredStyle: .alert) 
    let okAction = UIAlertAction(title: "OK", style: .default, handler: {action in 
      let nextAlert = UIAlertController(title: "New One", message: "The Previous one is dismissed", preferredStyle: .alert) 
      self.present(nextAlert, animated: true, completion: nil) 
    }) 
    anotherAlert.addAction(okAction) 
    self.present(anotherAlert, animated: true, completion: nil) 
}) 

麦克回答

DispatchQueue.main.async(execute: { 

     if self.presentedViewController == nil { 
      print("Alert comes up with the intended ViewController") 
      var inputTextField = UITextField() 

      let textPrompt = UIAlertController(title: "Test", message: "Testing", preferredStyle: .alert) 

      textPrompt.addAction(UIAlertAction(title: "Continue", style: .default, handler: { 
       (action) -> Void in 
       // if the input match the required text 

       let str = inputTextField.text 
       if str == requireTextInput { 
        print("right") 
       } else { 
        print("wrong") 
       } 

      })) 

      textPrompt.addTextField(configurationHandler: {(textField: UITextField!) in 
       textField.placeholder = "" 
       inputTextField = textField 

      }) 
      weakSelf?.present(textPrompt, animated: true, completion: nil) 
     } else { 
      // either the Alert is already presented, or any other view controller 
      // is active (e.g. a PopOver) 
      // ... 
      let thePresentedVC : UIViewController? = self.presentedViewController as UIViewController? 
      if thePresentedVC != nil { 
       if let _ : UIAlertController = thePresentedVC as? UIAlertController { 
         print("Alert not necessary, already on the screen !") 

       } else { 

         print("Alert comes up via another presented VC, e.g. a PopOver") 
       } 
      } 
     } 
}) 

感谢@Luke答:https://stackoverflow.com/a/30741496/3378606

+0

谢谢你的彻底回应。我仍然不确定如何去做这件事。我已将照片添加到我的问题中以供澄清。谢谢! – Miles

+0

你目前的问题有多少个控制器?只有一个listViewController? –

+0

只有一个:ListViewController。 – Miles

0
在viewDidLoad中


weak变量,像weak var weakSelf = self在通知中心


目前textPropmt

weak var weakSelf = self 
NotificationCenter.default.addObserver(forName: NSNotification.Name.UIApplicationUserDidTakeScreenshot, object: nil, queue: OperationQueue.main, using: 
     { notification in 
DispatchQueue.main.async(execute: { 
    //create textPrompt here in Main Thread 
    weakSelf.present(textPrompt, animated: true, completion: nil) 
}) 
}) 
+0

我应该将所有警报视图的代码放在“//在主线程中创建textPrompt”吗?感谢您的回应! – Miles

+0

这就是为什么我把这个评论代码。 **;)** , 前进。 – Vats

+0

,并且在主线程上使用UI控件是一种很好的做法.. – Vats

相关问题