【问题标题】:terminating with uncaught exception of type NSException while making custom UIButton在制作自定义 UIButton 时以 NSException 类型的未捕获异常终止
【发布时间】:2018-12-26 05:46:21
【问题描述】:

我想制作一个自定义按钮并在自定义按钮类内的选择器内提供输入,但它给了我一个错误消息。我该如何解决它

我在操场上测试它,因为当我运行模拟器时,应用程序崩溃了。这是操场上出现的错误

以 NSException 类型的未捕获异常终止

这是我在操场上的代码

class customButton: UIButton {

let titleName: String
let selectorName: String

init(titleName: String, selectorName: String) {
    self.titleName = titleName
    self.selectorName = selectorName
    super.init(frame: .zero)

    self.setTitle(titleName, for: .normal)
    self.addTarget(self, action: Selector(selectorName), for: .touchUpInside)
}

required init?(coder aDecoder: NSCoder) {
    fatalError("init(coder:) has not been implemented")
  }
}

class viewController: UIViewController {

override func loadView() {
    super.loadView()

    let testButton = customButton(titleName: "Test", selectorName: "handleButton")
    testButton.translatesAutoresizingMaskIntoConstraints = false
    view.addSubview(testButton)
    testButton.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true
    testButton.centerYAnchor.constraint(equalTo: view.centerYAnchor).isActive = true
}

func handleButton() {
    print("Pressed")
  }
}

新问题是

无法转换 (viewController) -> () 预期参数类型 UIViewController 的值类型

I make a custom UIButton with target selector as an input, when I try to add input in the custom button it show in Xcode

无法将类型 '(ProfileController) -> () -> (ProfileController)' 的值转换为预期的参数类型 'UIViewController

这是我在 ProfileController 和自定义按钮中的代码

class CustomButton: UIButton {

let imageName: UIImage
let selectorName: String
let target: UIViewController

init(imageName: UIImage, selectorName: String, target: UIViewController) {
    self.imageName = imageName
    self.selectorName = selectorName
    self.target = target
    super.init(frame: .zero)

    self.setImage(imageName.withRenderingMode(.alwaysOriginal), for: .normal)
    self.addTarget(target, action: Selector(selectorName), for: .touchUpInside)
}

required init?(coder aDecoder: NSCoder) {
    fatalError("init(coder:) has not been implemented")
  }
}

class ProfileController: UIViewController, UIImagePickerControllerDelegate, UINavigationControllerDelegate {

let profileID = "profileID"

let profileImageView: UIImageView = {
    let iv = UIImageView()
    iv.image = #imageLiteral(resourceName: "581010.jpg-r_1280_720-f_jpg-q_x-xxyxx").withRenderingMode(.alwaysOriginal)
    iv.contentMode = .scaleAspectFill
    iv.clipsToBounds = true
    return iv
}()

let pickerImage = CustomButton(imageName: #imageLiteral(resourceName: "user-6"), selectorName: "handleImagePicker", target: self) //this is the error message show up in the target: self

【问题讨论】:

  • 你正在使用 self 所以你应该使用惰性声明作为lazy var pickerImage: CustomButton = { return CustomButton(imageName: #imageLiteral(resourceName: "user-6"), selectorName: "handleImagePicker", target: self) }()
  • @Kamran maaaann 你是神我要崇拜你哈哈哈,再次感谢你,它有效。

标签: ios swift exception uibutton


【解决方案1】:

您应该删除选择器作为初始值设定项参数。您应该在创建按钮的任何位置设置目标。您还需要将@objc 放入handleButton 以由Selector 调用。您的设置将如下所示,

class customButton: UIButton {

    let titleName: String

    init(titleName: String) {
        self.titleName = titleName
        super.init(frame: .zero)

        self.setTitle(titleName, for: .normal)
    }

    required init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
}

class viewController: UIViewController {

override func loadView() {
    super.loadView()

    let testButton = customButton(titleName: "Test")
    testButton.translatesAutoresizingMaskIntoConstraints = false
    testButton.addTarget(self, action: Selector("handleButton"), for: .touchUpInside)
    view.addSubview(testButton)
    testButton.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true
    testButton.centerYAnchor.constraint(equalTo: view.centerYAnchor).isActive = true
}

@objc func handleButton() {
    print("Pressed")
  }
}

最新的Swift,你应该把Selector("handleButton")改成#selector(handleButton)


如果你想坚持当前的实现,那么你需要在customButton初始化器中使用target参数,如下所示,

init(titleName: String, selectorName: String, target: UIViewController) {
    self.titleName = titleName
    self.selectorName = selectorName
    super.init(frame: .zero)

    self.setTitle(titleName, for: .normal)
    self.addTarget(target, action: Selector(selectorName), for: .touchUpInside)
}

现在您将传递 ViewController 引用,

let testButton = customButton(titleName: "Test", selectorName: "handleButton", target: self)

别忘了将handleButtonobjc 标记为,

@objc func handleButton() {

【讨论】:

  • 它只能使用 objc 添加,没有它应用程序崩溃谢谢
  • 现在我有新问题无法转换 viewController 预期 UIViewController 类型的值,因为我的 viewController 有 UIViewController、UIImagePickerControllerDelegate、UINavigationControllerDelegate。
  • 我提出一个新问题
【解决方案2】:

删除

self.addTarget(self, action: Selector(selectorName), for: .touchUpInside)

来自 customButton 类。并添加

testButton.addTarget(self, action: Selector(handleButton), for: .touchUpInside)

在 viewDidLoad() 方法中。 还要在 viewController 类中添加选择器方法

@objc func handleButton() {
    print("Pressed")
}

【讨论】:

  • 所以目标选择器不能在自定义类中提供输入? @Viren_Malhan
  • 可以的。那么你必须在那个类中实现你的选择器。
  • @VirenMalhan 这不是虚构的
【解决方案3】:

应用程序崩溃,因为在下面的行中,您在 customButton 类中将目标设置为 self

self.addTarget(self, action: Selector(selectorName), for: .touchUpInside)

customButton 类没有方法handleButton

handleButton 在视图控制器中,因此您必须将目标设置为视图控制器

所以你必须在你的代码中进行轻微的修改,如下所示

class customButton: UIButton {

let titleName: String
let selectorName: String
let ViewController:UIViewController

init(titleName: String, selectorName: String,ViewController:UIViewController) {
self.titleName = titleName
self.selectorName = selectorName
self.ViewController = ViewController
super.init(frame: .zero)

self.setTitle(titleName, for: .normal)
self.addTarget(ViewController, action: Selector(selectorName), for: .touchUpInside)
}

required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}

class viewController: UIViewController {

override func loadView() {
super.loadView()

let testButton = customButton(titleName: "Test", selectorName: "handleButton",ViewController:self)
testButton.translatesAutoresizingMaskIntoConstraints = false
view.addSubview(testButton)
testButton.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true
testButton.centerYAnchor.constraint(equalTo: view.centerYAnchor).isActive = true
}

func handleButton() {
print("Pressed")
 }
}

【讨论】:

  • @Devil_Decoder 它仍然错误并显示相同的消息
  • @Devil_Decoder >libc++abi.dylib:以 NSException 类型的未捕获异常终止
  • @Devil_Decoder 在操场上的错误是我给你的评论,但在应用程序中,错误是无法转换值类型 viewController 预期的参数 UIViewController。因为我的 viewController 是 UIViewController 并且有 UIImagePickerControllerDelegate、UINavigationControllerDelegate
  • @ferryawijayanto 我已经更新了答案你是否在 init 方法中初始化了视图控制器
  • @ferryawijayanto 我已经更新了答案你是否在 init 方法中初始化了视图控制器
【解决方案4】:

这行会导致崩溃:

self.addTarget(self, action: Selector(selectorName), for: .touchUpInside)

在这一行中,您是说customButton 有一个名为selectorName 的方法,但实际上该方法驻留在viewController 中。

如果你在 customButton 类中添加这个,那么

class customButton: UIButton {

let titleName: String
let selectorName: String

  init(titleName: String, selectorName: String) {
    self.titleName = titleName
    self.selectorName = selectorName
    super.init(frame: .zero)

    self.setTitle(titleName, for: .normal)
    self.addTarget(self, action: Selector("handleTap"), for: .touchUpInside)
  }

   required init?(coder aDecoder: NSCoder) {
     fatalError("init(coder:) has not been implemented")
   }
   @objc func handleButton() {
      print("Pressed")
   }
}

或者在 ViewController 类中添加目标,例如,

let testButton = customButton(titleName: "Test", selectorName: "handleButton")
testButton.addTarget(self, action: Selector("handleButton"), for: .touchUpInside)

【讨论】:

    【解决方案5】:

    Swift 4.2 中,

    请使用,

    self.addTarget(self, action: #selector(handleButton), for: .touchUpInside)
    

    对于handleButton,需要 Obj-C 运行时才能查找给定选择器的方法实现,

    @objc func handleButton() {
      print("handle button selected")
    }
    

    【讨论】:

    • #selector 中的 selectorName 是一个函数,Xcode 抱怨。因为 selectorName 是字符串的类型。有函数类型吗?
    • 你应该使用#selector(handleButton),更新答案
    猜你喜欢
    • 2016-03-25
    • 1970-01-01
    • 2017-07-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-07-20
    • 2014-07-26
    相关资源
    最近更新 更多