Исключение нулевого указателя - это индикатор того, что вы используете объект, не инициализируя его.
Например, ниже - класс ученика, который будет использовать его в нашем коде.
public class Student {
private int id;
public int getId() {
return this.id;
}
public setId(int newId) {
this.id = newId;
}
}
Приведенный ниже код дает вам исключение с нулевым указателем.
public class School {
Student obj_Student;
public School() {
try {
obj_Student.getId();
}
catch(Exception e) {
System.out.println("Null Pointer ");
}
}
}
Поскольку вы используете Obj_Student
, но вы забыли инициализировать его, как в правильном коде, показанном ниже:
public class School {
Student obj_Student;
public School() {
try {
obj_Student = new Student();
obj_Student.setId(12);
obj_Student.getId();
}
catch(Exception e) {
System.out.println("Null Pointer ");
}
}
}
У меня была похожая проблема. вот что я сделал.
Затем использовал Self. в #selector.
@objc public protocol UpdatableUserInterfaceType {
optional func startUpdateUITimer()
optional var updateInterval: NSTimeInterval { get }
func updateUI(notif: NSTimer)
}
public extension UpdatableUserInterfaceType where Self: ViewController {
var updateUITimer: NSTimer {
return NSTimer.scheduledTimerWithTimeInterval(updateInterval, target: self, selector: #selector(Self.updateUI(_:)), userInfo: nil, repeats: true)
}
func startUpdateUITimer() {
print(updateUITimer)
}
var updateInterval: NSTimeInterval {
return 60.0
}
}
Этот ответ очень похож на Bruno Hecktheuers, но вместо того, чтобы каждый, кто хочет соответствовать протоколу «Tappable», реализовал переменную «селектор», мы решили передать его в качестве параметра функции addTapGestureRecognizer:
protocol Tappable {
func addTapGestureRecognizer(selector selector: Selector)
func tapGestureDetected(gesture:UITapGestureRecognizer)
}
extension Tappable where Self: UIView {
func addTapGestureRecognizer(selector selector: Selector)
let gesture = UITapGestureRecognizer(target: self, action: selector)
addGestureRecognizer(gesture)
}
}
class TapView: UIView, Tappable {
func tapGestureDetected(gesture:UITapGestureRecognizer) {
print("Tapped")
}
}
, а затем просто передавайте селектор везде, где он используется:
addTapGestureRecognizer(selector: #selector(self.tapGestureDetected(_:)))
Таким образом, мы избегаем того, чтобы те, кто реализует этот протокол, должны были реализовывать переменную селектора, и мы также избегали отмечать всех используя этот протокол с "@objc". Чувствуется, что этот подход менее раздутый.
Я случайно увидел это на боковой панели, у меня недавно была такая же проблема. К сожалению, из-за ограничений времени выполнения Objective C вы не можете использовать @objc для расширений протокола, я думаю, что эта проблема была закрыта в начале этого года.
Проблема возникает из-за того, что расширение добавляется после соответствия протокола, поэтому нет способа гарантировать, что соответствие протоколу будет выполнено. Тем не менее, можно вызывать метод как селектор из всего, что подклассов NSObject и соответствует протоколу. Чаще всего это делается с делегированием.
Это означает, что вы можете создать пустой подкласс обертки, соответствующий протоколу, и использовать обертку для вызова его методов из протокола, определенного в обертке, любые другие неопределенные методы из протокола могут быть переданы в делегировать. Существуют другие аналогичные решения, которые используют частное расширение конкретного класса, например UIViewController, и определяют метод, который вызывает метод протокола, но они также связаны с конкретным классом, а не реализацией по умолчанию конкретного класса, который происходит с соответствуют протоколу .
Поймите, что вы пытаетесь реализовать реализацию протокола по умолчанию, которая использует другую из своих собственных функций протокола, чтобы определить значение для своей собственной реализации. гмм!
Протокол:
public protocol CustomViewDelegate {
func update()
func nonDelegatedMethod()
}
Представление:
Использование делегата и определение метода обертки для безопасного развертывания метод делегата.
class CustomView: UIView {
let updateButton: UIButton = {
let button = UIButton(frame: CGRect(origin: CGPoint(x: 50, y: 50), size: CGSize(width: 150, height: 50)))
button.backgroundColor = UIColor.lightGray
button.addTarget(self, action: #selector(doDelegateMethod), for: .touchUpInside)
return button
}()
var delegate:CustomViewDelegate?
required init?(coder aDecoder: NSCoder) {
fatalError("Pew pew, Aghh!")
}
override init(frame: CGRect) {
super.init(frame: frame)
addSubview(updateButton)
}
@objc func doDelegateMethod() {
if delegate != nil {
delegate!.update()
} else {
print("Gottfried: I wanted to be a brain surgeon, but I had a bad habit of dropping things")
}
}
}
ViewController:
Согласуйте контроллер представления с представителем представления: и реализуйте метод протокола.
class ViewController: UIViewController, CustomViewDelegate {
let customView = CustomView(frame: CGRect(origin: CGPoint(x: 100, y: 100), size: CGSize(width: 200, height: 200)))
override func viewDidLoad() {
super.viewDidLoad()
customView.backgroundColor = UIColor.red
customView.delegate = self //if delegate is not set, the app will not crash
self.view.addSubview(customView)
}
// Protocol -> UIView Button Action -> View Controller's Method
func update() {
print("Delegating work from View that Conforms to CustomViewDelegate to View Controller")
}
//Protocol > View Controller's Required Implementation
func nonDelegatedMethod() {
//Do something else
}
}
Обратите внимание, что контроллер представления должен был соответствовать только делегату и не устанавливал селектор какого-либо свойства представления, это отделяет представление (и его протокол) от контроллера представления.
У вас уже есть UIView с именем TapView, который наследует от UIView и Tappable, поэтому ваша реализация может быть:
Протокол:
protocol TappableViewDelegate {
func tapGestureDetected(gesture:UITapGestureRecognizer)
}
TappableView:
class TappableView: UIView {
var delegate:TappableViewDelegate?
required init?(coder aDecoder: NSCoder) {
fatalError("Pew pew, Aghh!")
}
override init(frame: CGRect) {
super.init(frame: frame)
let gesture = UITapGestureRecognizer(target: self, action: #selector(doDelegateMethod(gesture:)))
addGestureRecognizer(gesture)
}
@objc func doDelegateMethod(gesture:UITapGestureRecognizer) {
if delegate != nil {
delegate!.tapGestureDetected(gesture: gesture)
} else {
print("Gottfried: I wanted to be a brain surgeon, but I had a bad habit of dropping things")
}
}
}
ViewController:
class ViewController: UIViewController, TappableViewDelegate {
let tapView = TappableView(frame: CGRect(origin: CGPoint(x: 100, y: 100), size: CGSize(width: 200, height: 200)))
override func viewDidLoad() {
super.viewDidLoad()
tapView.backgroundColor = UIColor.red
tapView.delegate = self
self.view.addSubview(tapView)
}
func tapGestureDetected(gesture: UITapGestureRecognizer) {
print("User did tap")
}
}