2015-12-06 4 views
3

У меня есть следующая структура.Использование карты в Swift для изменения свойств настраиваемого объекта

struct Person { 

    var firstName :String 
    var lastName :String 
    var active :Bool 
} 

Я создал коллекцию Person, как показано ниже:

var persons :[Person] = [] 

for var i = 1; i<=10; i++ { 

    var person = Person(firstName: "John \(i)", lastName: "Doe \(i)", active: true) 
    persons.append(person) 
} 

и теперь я пытаюсь изменить активное свойство ложно, используя код ниже:

let inActionPersons = persons.map { (var p) in 

    p.active = false 
    return p 
} 

Но Я получаю следующую ошибку:

Cannot invoke map with an argument list of type @noescape (Person) throws 

Любые идеи?

РЕШЕНИЕ:

Похоже, Свифт не может выводить типы иногда который является своего рода хромой! Вот решение:

let a = persons.map { (var p) -> Person in 

     p.active = false 
     return p 
} 

ЭТО НЕ РАБОТАЕТ:

let a = persons.map { p in 

     var p1 = p 
     p1.active = false 
     return p1 
} 

ответ

5

При использовании скобок для аргументов, так что var работы, вы должны поставить возвращение типа, а также:

let inActionPersons = persons.map { (var p) -> Person in 

    p.active = false 
    return p 
} 
+0

Даже если вы не используете скобки и переместите p в новую переменную p1, для этого требуется явно указать тип возврата. Проверьте обновление в исходном сообщении. –

+0

@johndoe Да, я понял это только сейчас, я думаю, что это ошибка, потому что 'people.map {return $ 0}' работает, но 'persons.map {print (" "); return $ 0} 'is not – Kametrixom

+0

Возможно, ошибка на этом языке! Надеюсь, это может быть исправлено в последующих выпусках! –

6

Существует ровно два случая, когда компилятор Swift автоматически возвращает тип замыкания:

  • В «закрытие одного выражения,» в то есть корпуса укупорочного состоит из одного выражения только (с или без явных параметров замыкания).
  • Если тип может быть выведен из контекста вызова .

Все это не относится

let inActionPersons = persons.map { (var p) in 
    p.active = false 
    return p 
} 

или

let a = persons.map { p in 
     var p1 = p 
     p1.active = false 
     return p1 
} 

и поэтому вы должны указать тип возвращаемого значения в явном виде в Kametrixom's answer.

Пример закрытия с одним выражением:

let inActionPersons = persons.map { p in 
    Person(firstName: p.firstName, lastName: p.lastName, active: false) 
} 

и он будет компилировать с (var p) in или (p : Person) in, так что это не имеет ничего общего с ли аргументы закрытия даны явно в скобках или нет.

А вот пример, когда тип выводится из вызывающего контекста:

let a : [Person] = persons.map { p in 
    var p1 = p 
    p1.active = false 
    return p1 
} 

Результата map() должен быть [Person] массивом, поэтому карта необходим замыкания типа Person -> Person, и компилятор информация возвращение type Person автоматически.

Для получения дополнительной информации см. Раздел «Вывод типа из контекста» и «Неявные возвращения из закрытий с одним выражением» в главе "Closures" в книге Swift.

+0

У вас есть ссылка на эти неявные правила вывода типов? – Kametrixom

+0

@Kametrixom: В https://developer.apple.com/library/ios/documentation/Swift/Conceptual/Swift_Programming_Language/Closures.html есть разделы «Вывод типа из контекста» и «Неявные возвращения из закрытий с одним выражением». В нем явно не указано, что это * только * случаи, когда тип выводится, но это то, что я выяснил при попытке и ошибке. - Но, как вы можете видеть из примеров, это не зависит от * "... с помощью скобок для аргументов ..." * –

+0

Да, это кажется действительно странным, но это работает: 'persons.map {return $ 0}' , но 'persons.map {print (" "); return $ 0} 'does not. Я думаю, это либо ошибка, либо просто еще не поддерживается, потому что это должно обязательно работать – Kametrixom

Смежные вопросы