Swift 4.2 странное поведение - PullRequest
0 голосов
/ 13 января 2019

У меня возникли проблемы с использованием .map в коллекции в Swift 4.2. Вот что происходит:

У меня есть свойство, объявленное так:

var cbPerifList:[CBPeripheral]!

Позже в коде, когда я пишу:

_ = cbPerifList.map { (perif) -> Void in
    print(perif.identifier)
}

Компилятор выглядит счастливым и не жалуется.

Но когда я пишу:

_ = cbPerifList.map { (perif) -> Void in
    print(perif.identifier)
    print("HELLO")
}

Компилятор жалуется, отображая это сообщение.

Value of type '[CBPeripheral]' has no member 'identifier'

в строке кода: печать (perif.identifier) ​​

Может кто-нибудь объяснить, что здесь происходит?

  1. Я не понимаю, почему добавление этой строки кода имеет значение.

    печать ( "HELLO")

  2. Я ожидаю, что perif будет иметь тип CBPeripheral, а не [CBPeripheral], как говорится в сообщении об ошибке.

Ответы [ 2 ]

0 голосов
/ 13 января 2019

Как упоминалось в другом ответе и в комментариях, использование forEach или for ... in будет правильным способом обхода массива.

Но чтобы ответить на ваш вопрос и объяснить, почему эти, казалось бы, идентичные фрагменты кода ведут себя по-разному: это вызвано сочетанием нескольких фактов:

В закрытии с одним утверждением

_ = cbPerifList.map { (perif) -> Void in
    print(perif.identifier)
}

компилятор пытается определить тип замыкания из выражения print, и для проверки типа perif.identifier IUO cbPerifList должен быть развернут в массив.

В закрытии с несколькими утверждениями

_ = cbPerifList.map { (perif) -> Void in
    print(perif.identifier)
    print("HELLO")
}

компилятор не пытается определить тип замыкания из контекста. Поэтому cbPerifList рассматривается как обычный необязательный параметр, а map() является вышеупомянутым Optional.map методом. Внутри крышки perif имеет развернутый тип [CBPeripheral]. Вот почему perif.identifier не компилируется с сообщением об ошибке

Значение типа '[CBPeripheral]' не имеет члена 'идентификатор'

Вы можете «помочь» компилятору с явной аннотацией типа

_ = cbPerifList.map { (perif: CBPeripheral) -> Void in
    print(perif.identifier)
    print("HELLO")
}

но - как уже говорилось - в данном конкретном случае есть лучшие решения.

0 голосов
/ 13 января 2019

Способ работы map в Swift (и в других местах) заключается в том, что он может отображать (изменять) входные данные от одного типа к другому. Так что в вашем случае вы будете вызывать map на вашем [CBPeripheral], и для каждого элемента функция map будет возвращать другое значение. Итак, если identifier - это String, вы получите массив строк.

Вот как это должно работать.

Однако:)

В вашем случае вы определили свою функцию отображения следующим образом:

(perif) -> Void

Это означает, что вы будете пробегать свой массив и вызывать карту с функцией, которая ничего не возвращает. Это означает, что результатом будет массив, заполненный значениями Void.

Поэтому, как предлагают другие в комментариях, если вы просто хотите просмотреть содержимое вашего cbPerifList, вам лучше использовать цикл for in, например

for cbPerif in cbPerifList {
    print(cbPerif.identifier)
}

Если, однако, вы заинтересованы в получении массива имен ваших CBPeripherals, вы можете сделать что-то вроде этого

let names = cbPerifList.map { $0.identifier }

Комментарий к вышесказанному: Чтобы узнать больше о том, как мы можем в итоге просто написать { $0.name }, взгляните на главу о Closures в документации Swift или этот ответ

Надеюсь, это поможет вам.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...