[英]Passing closure/ blocks in array as parameter iOS
我正在嘗試將數組中的警報操作傳遞給一個函數,該函數用於將UIAlertController配置簡化為一行。 能夠成功傳遞按鈕標題,但不能傳遞警報動作。 這是我在做什么。
+(void)showAlertWithTitle:(NSString*)title
message:(NSString*)alertmessage
buttonTitles:(NSArray*)buttonTitles
buttonActions:(NSArray*)buttonActions
inViewController:(UIViewController*)viewController {
UIAlertController *alert = [UIAlertController alertControllerWithTitle:title message:alertmessage preferredStyle:UIAlertControllerStyleAlert];
[buttonTitles enumerateObjectsUsingBlock:^(NSString* buttonTitle,NSUInteger idx,BOOL *stop){
UIAlertAction *action = [UIAlertAction actionWithTitle:buttonTitle style:UIAlertActionStyleDefault handler: [[buttonActions objectAtIndex:idx] copy]]; //blocks should always be copied to heap from stack else they will crash
[alert addAction:action];
}];
[viewController presentViewController:alert animated:YES completion:nil];
}
上面的代碼文件是很久以前寫的,因此它在目標c中。 我已經編寫了一些新文件,它們正在迅速運行,我正在如下快速調用上述方法。
CommonManager.showAlert(withTitle: "", message: "Feedback Sent",
buttonTitles: ["Ok"], buttonActions: [ { (action: UIAlertAction) in
print("you pressed Ok alert button");
// call method whatever u need
}], in: self)
如果我不通過閉包,它工作正常,如果在單擊“確定”時通過閉包,它將崩潰。 我還發現,當一個塊作為一個集合傳遞時,我們需要復制一個塊,但是我做到了,但是仍然有些不對勁,無法弄清楚。 你能告訴我我在這里需要做什么。
謝謝
問題在於,Swift閉包是與Objective-C塊不同的對象,因此嘗試在塊崩潰時運行它。
通常,如果Swift編譯器看到您正在將閉包傳遞給帶有塊類型參數的Objective-C方法,它將把Swift閉包轉換為Objective-C塊,但是在這種情況下,它只是看到您將其放入一個數組,而不是關於該方法將在數組內部執行的操作,因此它不會進行任何轉換。
我想出讓它正常工作的唯一方法是這樣的:
CommonManager.showAlert(withTitle: "", message: "Feedback Sent",
buttonTitles: ["Ok"], buttonActions: [ { (action: UIAlertAction) in
print("you pressed Ok alert button");
// call method whatever u need
} as (@convention(block) (UIAlertAction) -> Void)!], in: self)
與其處理轉換的怪異性,不如制作原生的swift版本?
這是我相同功能的版本:
extension UIViewController {
func presentAlert(title: String, message: String, actions: [UIAlertAction] = [UIAlertAction(title: "OK", style: .cancel, handler: nil)], iPadOrigin: CGRect? = nil, style: UIAlertControllerStyle = .alert, animated: Bool = true, completion: (() -> ())? = nil) {
let alert = UIAlertController(title: title, message: message, preferredStyle: style)
actions.forEach(alert.addAction)
alert.popoverPresentationController?.sourceView = self.view
if let iPadOrigin = iPadOrigin {
alert.popoverPresentationController?.sourceRect = iPadOrigin
}
present(alert, animated: animated, completion: completion)
}
func presentAlert(title: String, message: String, actions: [UIAlertAction] = [UIAlertAction(title: "OK", style: .cancel, handler: nil)], iPadButtonOrigin: UIBarButtonItem? = nil, style: UIAlertControllerStyle = .alert, animated: Bool = true, completion: (() -> ())? = nil) {
let alert = UIAlertController(title: title, message: message, preferredStyle: style)
actions.forEach(alert.addAction)
alert.view.tintColor = Color.BlueDarker
alert.popoverPresentationController?.barButtonItem = iPadButtonOrigin
present(alert, animated: animated, completion: completion)
}
}
它還可以處理iPad的差異和一些不錯的默認設置,因此viewController.presentAlert(title: "Error", message: "Something broke")
如果要在iPhone上發出簡單的警報,可以執行viewController.presentAlert(title: "Error", message: "Something broke")
。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.