Swift 2.2 # выбор в ошибке компилятора расширения протокола

Исключение нулевого указателя - это индикатор того, что вы используете объект, не инициализируя его.

Например, ниже - класс ученика, который будет использовать его в нашем коде.

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 ");
        }
    }
}
25
задан Andrea 23 March 2016 в 18:55
поделиться

3 ответа

У меня была похожая проблема. вот что я сделал.

  1. Помечен протокол как @objc.
  2. Помечал все методы, которые я расширил, с поведением по умолчанию как необязательное.
  3. Затем использовал 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
      }
    }
    
24
ответ дан Jim Bergman 23 March 2016 в 18:55
поделиться

Этот ответ очень похож на 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". Чувствуется, что этот подход менее раздутый.

7
ответ дан Peep 23 March 2016 в 18:55
поделиться

Я случайно увидел это на боковой панели, у меня недавно была такая же проблема. К сожалению, из-за ограничений времени выполнения 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")
   }

}
0
ответ дан RLoniello 23 March 2016 в 18:55
поделиться
Другие вопросы по тегам:

Похожие вопросы: