2016-12-26 143 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

相關問題