Возможные местоположения для вызова addObserver и removeObserver методов

Простой скрипт

Вот пример в Common Lisp, предполагая, что ваш ввод находится в файле "/tmp/ex.cad" (его также можно получить, прочитав поток вывода процесса).

Основной цикл обработки состоит в открытии файла для получения входного потока in (который автоматически закрывается в конце with-open-file), циклического перебора всех форм в файле, их обработки и, возможно, вывода их на стандартный вывод. Вы можете усложнить процесс сколько угодно, но достаточно хорошо следующее:

(with-open-file (in #"/tmp/ex.cad")
  (let ((*read-eval* nil))
     (ignore-errors
       (loop (process-form (read in))))))

Предположим, вы хотите увеличить ширину fp_line записей, игнорировать fp_text и в противном случае распечатать форму без изменений. Вы можете определить process-form следующим образом:

(defun process-form (form)
  (destructuring-bind (header . args) form
    (print
     (case header
       (fp_line (let ((width (assoc 'width args)))
                  (when width (incf (second width) 3)))
                form)
       (fp_text (return-from process-form))
       (t form)))))

Выполнение предыдущего цикла выдаст:

(FP_LINE (START -27.04996 -3.986) (END -27.24996 -3.786) (LAYER F.FAB) (WIDTH 3.1)) 
(PAD "" NP_THRU_HOLE CIRCLE (AT 35.56 0) (SIZE 3.175 3.175) (DRILL 3.175) (LAYERS *.CU *.MASK) (CLEARANCE 1.5875)) 
(PAD 96 SMD RECT (AT 1.25 3.08473) (SIZE 0.29972 1.45034) (LAYERS F.CU F.PASTE F.MASK) (CLEARANCE 0.09906)) 

Больше безопасности

Оттуда вы можете построить более сложные конвейеры, с помощью сопоставления с образцом или макросов, если хотите. Вы должны принять во внимание некоторые меры безопасности, такие как привязка *read-eval* к nil, использование with-standard-io-syntax и привязка *print-circte* к T, как предложено в tfb , запрещение полностью определенных символов (имея #\: сигнализировать об ошибке) и т. д. В конечном счете, как и в случае однострочных сценариев оболочки Shell, количество мер предосторожности, которые вы добавляете, зависит от того, насколько вы доверяете своим данным:

;; Load libraries
(ql:quickload '(:alexandria :optima))

;; Import symbols in current package
(use-package :optima)
(use-package :alexandria)

;; Transform source into a stream
(defgeneric ensure-stream (source)
  (:method ((source pathname)) (open source))
  (:method ((source string)) (make-string-input-stream source))
  (:method ((source stream)) source))

;; make reader stop on illegal characters    
(defun abort-reader (&rest values)
  (error "Aborting reader: ~s" values))

Специальный пакет для символов KiCad (экспорт необязателен). ):

(defpackage :kicad
  (:use)
  (:export #:fp_text
           #:fp_line
           #:pad
           #:size))

Циклические формы:

(defmacro do-forms ((form source &optional result) &body body)
  "Loop over forms from source, eventually return result"
  (with-gensyms (in form%)
    `(with-open-stream (,in (ensure-stream ,source))
       (with-standard-io-syntax
         (let ((*read-eval* nil)
               (*print-circle* t)
               (*package* (find-package :kicad))
               (*readtable* (copy-readtable)))
           (set-macro-character #\: #'abort-reader nil)
           (loop
              :for ,form% := (read ,in nil ,in)
              :until (eq ,form% ,in)
              :do (let ((,form ,form%)) ,@body)
              :finally (return ,result)))))))

Пример:

;; Print lines at which there is a size parameter, and its value
(let ((line 0))
  (labels ((size (alist) (second (assoc 'kicad:size alist)))
           (emit (size) (when size (print `(:line ,line :size ,size))))
           (process (options) (emit (size options))))
    (do-forms (form #P"/tmp/ex.cad")
      (match form
        ((list* 'kicad:fp_text _ _ options) (process options))
        ((list* 'kicad:fp_line options) (process options))
        ((list* 'kicad:pad _ _ _ options) (process options)))
      (incf line))))

Выход

(:LINE 2 :SIZE 3.175) 
(:LINE 3 :SIZE 0.29972)
8
задан Mustafa 5 September 2012 в 14:23
поделиться

2 ответа

На самом деле это - плохая идея. Когда память понижается, Ваш контроллер представления может быть отправлен предупреждение памяти. Поведение по умолчанию в этом экземпляре состоит в том, чтобы убрать Ваше представление (если Вы в настоящее время не находитесь на экране). В этом случае Вы могли добраться, сообщение viewDidLoad отправило во второй раз (после того, как событие памяти, когда Ваше представление возвращено на экране его контроллером навигации.) Таким образом у Вас будет две регистрации того же объекта, но только одно удаление (в его dealloc)

Лучшее решение состоит в том, чтобы или установить флаг, говоря, что Вы зарегистрировались, или зарегистрироваться в Вашем init методе.

5
ответ дан 5 December 2019 в 22:21
поделиться

Я предполагаю, что правильные положения для регистрации для уведомления viewDidLoad метод и правильное положение для нерегистрации для тех же уведомлений dealloc метод.

1
ответ дан 5 December 2019 в 22:21
поделиться
Другие вопросы по тегам:

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