2016-01-09 3 views
2

Я изучаю Swift прямо сейчас, и в ходе курса у нас есть урок, чтобы сделать простое приложение. Теперь у меня проблемы с программированием текстовых полей, что он работает неправильно.Learning Swift, значение необязательного типа, не развернутого при создании объекта

Вот мой код:

class ViewController: UIViewController { 

    @IBOutlet weak var refeicaoField: UITextField? 
    @IBOutlet weak var felicidadeField: UITextField? 


    @IBAction func addRefeicao(sender: UIButton) { 

     if refeicaoField == nil || felicidadeField == nil { 
      return 
     } 

     let nomeRefeicao = refeicaoField!.text 
     let valorFelicidade = felicidadeField!.text 
     let valorFelicidadeInt = Int(valorFelicidade!) 

     let novaRefeicao = Meal(nomeAlimento: nomeRefeicao, alegriaEmComer: valorFelicidadeInt) 
    } 


} 

Проблема начинается здесь:

let novaRefeicao = Meal(nomeAlimento: nomeRefeicao, alegriaEmComer: valorFelicidadeInt) 

Где это говорит: '? Int' значение необязательного не разворачивается; вы хотели использовать '!' или '?' а также значение необязательной строки? не разворачивается; вы хотели использовать '!' или '?'

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

let novaRefeicao = Meal(nomeAlimento: nomeRefeicao, alegriaEmComer: valorFelicidadeInt!) 

И работал, но для меня нет. И если я попытаюсь поставить «!» по двум переменным, у меня есть восклицательное предупреждение, не требующее использования для novaRefeicao.

Что случилось?

EDIT:

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

class ViewController: UIViewController { 

    @IBOutlet weak var refeicaoField: UITextField! 
    @IBOutlet weak var felicidadeField: UITextField! 


    @IBAction func addRefeicao(sender: UIButton) { 

     if refeicaoField == nil || felicidadeField == nil { 
      return 
     } 

     let nomeRefeicao = refeicaoField!.text 
     let valorFelicidade = felicidadeField!.text 

     if nomeRefeicao == nil { 
      return 
     } 

     if let valorFelicidadeInt = Int(valorFelicidade!) { 
      let novaRefeicao = Meal(nomeAlimento: nomeRefeicao, alegriaEmComer: valorFelicidadeInt) 
     } else { 
      return 
     } 
    } 


} 

Теперь я получаю ошибку на развернутый снова, но теперь с «nomeRefeicao вместо этого. Пытался поставить «!» в нем, но затем он показывает, что пусть novaRefeicao является неизменным значением.

+2

Если предполагается, что '' '' '' '' '' '' '' '' '' '' '' ''' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' 'должны быть подключены в Interface Builder, это довольно бессмысленно объявлять их как optionals ('? '). Если ваш курс подскажет это, пойдите для лучшего курса. Способ, рекомендованный Apple, состоит в том, чтобы объявить их как неявные развернутые необязательные ('!'), Потому что они безопасно не равны нулю при подключении. Преимущество состоит в том, чтобы избавиться от всех восклицательных знаков, чтобы развернуть их в коде, и, конечно же, проверка на 'nil' при каждом вызове метода тоже не требуется. – vadian

ответ

2

text И свойство UITextField и результат Int(string:String) инициализаторе возвращают необязательное значение.

Итак, вы должны развернуть как в том случае, если метод ожидает необязательные параметры.

let novaRefeicao = Meal(nomeAlimento: nomeRefeicao!, alegriaEmComer: valorFelicidadeInt!) 

Самый компактный синтаксис

class ViewController: UIViewController { 

    @IBOutlet weak var refeicaoField: UITextField! 
    @IBOutlet weak var felicidadeField: UITextField! 


    @IBAction func addRefeicao(sender: UIButton) { 

    if let nomeRefeicao = refeicaoField.text, valorFelicidade = felicidadeField.text, valorFelicidadeInt = Int(valorFelicidade) { 
     let novaRefeicao = Meal(nomeAlimento: nomeRefeicao, alegriaEmComer: valorFelicidadeInt) 
     // do something with novaRefeicao 
    } 
    } 
} 

Meal инициализатор вызывается только если

  • refeicaoField.text не nil
  • felicidadeField.text не nil и могут быть преобразованы в Int

Нет необходимости проверять UITextField экземпляры для nil.
Если вы получили ошибку времени выполнения, одно из полей не подключено в IB.

Сообщение Initialization of immutable value ... является предупреждением, поскольку созданный экземпляр Meal, присвоенный novaRefeicao, никогда не используется. Вот почему я добавил комментарий линию сделать что-то ...

+0

Эй! Если я попытаюсь это сделать, у меня есть ошибка неизменной переменной в let novaRefeicao. –

+0

Если вам нужно использовать 'novaRefeicao' как переменную, а не константу, замените' let' на 'var' – vadian

+0

Извините, я использую ее как let, но когда я пытаюсь использовать '!' в nomeRefeicao, я получаю «Инициализацию неизменяемой ценности». если пусть valorFelicidadeInt = Int (valorFelicidade!) { let novaRefeicao = Питание (nomeAlimento: nomeRefeicao !, alegriaEmComer: valorFelicidadeInt) –

1

Вы должны понимать, что язык Swift изменил лот за последний год, и этот восклицательный знак со временем значительно изменился. Если у вас есть примеры с середины 2015 года, вы смотрите на устаревший синтаксис.

, имеющий значение с ?, означает, что этот элемент может содержать значение ... или он может не быть.

, имеющий значение с !, означает, что вы принудительно разворачиваете объект, который может быть довольно опасным, используйте его экономно и только тогда, когда вы точно знаете, что это не приведет к сбою.

Если у вас есть дополнительное значение, вы можете смело разворачивать его так:

guard let unwrapped = wrapped else { 
    return 
} 

или

if let unwrapped = wrapped { 
    print(unwrapped) 
} 

Немного больше информации, если у вас есть инициализированному необязательное значение, что вы» ve действительно получил это:

enum Optional<A> { 
    case None 
    case Some(A) 
} 

Вот почему вы не можете использовать свою ценность, не разворачивая ее. .. он «завернут» в необязательное перечисление, которое либо имеет значение, либо нет.

Ваш код с небольшой гарантией добавил:

class ViewController: UIViewController { 

    @IBOutlet weak var refeicaoField: UITextField? 
    @IBOutlet weak var felicidadeField: UITextField? 


    @IBAction func addRefeicao(sender: UIButton) { 

     guard let refeicaoField = refeicaoField!.text else { 
      return 
     } 

     guard let felicidadeField = felicidadeField!.text else { 
      return 
     } 

     let nomeRefeicao = refeicaoField ?? "error" // added protection 
     let valorFelicidade = felicidadeField ?? "error" // added protection 
     let valorFelicidadeInt = Int(valorFelicidade) ?? 123 // defaults to '123' in case of issue 
    } 
} 
+0

Почему бы не просто 0 как «значение по умолчанию»? :-) – user3441734

+0

Хм ... я не понимаю, не обращайте внимания, я собираюсь задуматься о вас. – user3441734

1

Линия:

let valorFelicidadeInt = Int(valorFelicidade!) 

преобразует String значение в качестве Int. Что должен делать ваш код, если строка не может быть преобразована в целое число? Вы должны обратиться к этому явно.

В Swift конверсия имеет тип Optional - либо преобразование выполнено, либо оно не было. Таким образом, у вас есть два случая для покрытия. Ниже приведен возможный подход:

if let valorFelicidadeInt = Int(valorFelicidade!) { 
    let novaRefeicao = Meal(nomeAlimento: nomeRefeicao, alegriaEmComer: valorFelicidadeInt) 
    // continue using `Meal` 
} 
else { 
    // User error; text not an int 
} 

if let будет успешным, если Int(...) возвращает не ноль дополнительный; вы затем создадите Meal.

Такой же подход к развертыванию при обработке двух параметров применяется к другим частям вашего кода.

+0

Извините, что поздно ответить. Я был занят. Сделал это! Но теперь я продолжаю получать ошибку с элементом nomeRefeicao внутри вашего if. Пытался поставить «!» там, но тогда переменная говорит, что это неизменная переменная. –

+0

«Инициализация неизменяемой ценности» * –

+0

Вот что я имел в виду под «тем же самым подходом к разворачиванию» - вам нужно применить решение, которое я описал, к двум вашим переменным. Сосредоточьтесь на значениях, которые являются «Необязательными» - функция '.text' возвращает« Необязательный », я считаю. Что произойдет, если текст отсутствует? Возможно, используйте '(refeicaoField !.text ??" ")' – GoZoner