if let result = brain.pushOperand(displayValue){
displayValue = result
} else {
displayValue = 0
}
Замечание. Если вы запускаете на реальном устройстве, в котором Регион установлен так, что там не применяется "." для десятичных чисел, приложение закончится аварийно. Но на симуляторе оно работает.
Решение смотрите на сайте - в разделе Задание 1
@IBAction func appendDigit(sender: UIButton) {
let digit = sender.currentTitle!
if userIsInTheMiddleOfTypingANumber {
display.text! += display.text!.rangeOfString(".") != nil && digit == "." ? "" : digit
}
else {
display.text = digit
userIsInTheMiddleOfTypingANumber = true
}
}
@IBAction func decimalPoint(sender: UIButton) {
if !userAlreadyEnteredADecimalPoint {
appendDigit(sender)
userAlreadyEnteredADecimalPoint = true
}
}
@IBAction func appendDigit(sender: UIButton) {
let digit = sender.currentTitle!
// println("digit = \(digit)");
if userIsInTheMiddleOfTypingANumber {
//----- Уничтожаем лидирующие нули ---------------
if (digit == "0") && (display.text == "0") { return }
if (digit != ".") && (display.text == "0") { display.text = digit ; return }
//--------------------------------------------------
display.text = display.text! + digit
} else {
display.text = digit
userIsInTheMiddleOfTypingANumber = true
}
}
@IBAction func decimalPoint(sender: UIButton) {
if !userAlreadyEnteredADecimalPoint {
appendDigit(sender)
userAlreadyEnteredADecimalPoint = true
}
}
userAlreadyEnteredADecimalPoint: Bool {
return display.text?.rangeOfString(".") != nil
}@IBAction func decimalPoint(sender: UIButton) {
let noPointOnDisplay = display.text?.rangeOfString(".") == nil
if (noPointOnDisplay) || !(noPointOnDisplay || userIsInTheMiddleOfTypingANumber) {
appendDigit(sender)
}
}
Введите код...import UIKit
class ViewController: UIViewController {
@IBOutlet weak var display: UILabel!
@IBOutlet weak var historyLabel: UILabel!
var userWriteANumber: Bool = false
var userWriteAPoint: Bool = false
@IBAction func digit(sender: UIButton) {
let number = sender.currentTitle!
if userWriteANumber {
display.text = display.text! + number
} else {
display.text = number
userWriteANumber = true
}
}
@IBAction func points(sender: UIButton) {
if userWriteANumber{
digit(sender)
userWriteANumber = true
}
}
var arrayDigit = Array<Double>()
@IBAction func returnDigit() {
userWriteANumber = false
arrayDigit.append(displayValue!)
historyLabel.text = historyLabel.text! + "\(arrayDigit.description)"
println("return digit = \(arrayDigit)")
}
var displayValue: Double! {
get {
return NSNumberFormatter().numberFromString(display.text!)!.doubleValue
}
set {
display.text = "\(newValue)"
userWriteANumber = false
}
}
@IBAction func operand(sender: UIButton) {
let operation = sender.currentTitle!
if userWriteANumber {
returnDigit()
}
switch operation {
case "×": action { $0 * $1 }
case "÷": action { $1 / $0 }
case "−": action { $1 - $0 }
case "+": action { $0 + $1 }
case "√": action { sqrt($0) }
case "sin": action { sin($0) }
case "cos": action { cos($0) }
default: break
}
}
func action(operation: (Double, Double) -> Double) {
if arrayDigit.count >= 2 {
displayValue = operation(arrayDigit.removeLast(), arrayDigit.removeLast())
returnDigit()
}
}
func action(operation: (Double) -> Double) {
if arrayDigit.count >= 1 {
displayValue = operation(arrayDigit.removeLast())
returnDigit()
}
}
@IBAction func PI() {
let pi = M_PI
userWriteANumber = true
if userWriteANumber {
displayValue = pi
}
}
/* func action(operation: (Double, Double) -> Double) {
if arrayDigit.count >= 2 {
displayValue = operation(arrayDigit.removeLast(), arrayDigit.removeLast())
returnDigit()
}
}
func action(operation: Double -> Double){
if arrayDigit.count >= 1 {
displayValue = operation(arrayDigit.removeLast())
returnDigit()
}
}
*/
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
/* var story: String! {
get {
return NSNumberFormatter().stringFromNumber(displayValue)!
}
set {
historyLabel.text = "\(newValue)"
userWriteANumber = false
}
}
func history() {
if userWriteANumber {
historyLabel.text = historyLabel.text!
} else {
historyLabel.text = historyLabel.text! + story
userWriteANumber = true
}
}
*/
}
override func viewDidLoad() {
super.viewDidLoad()
|
@IBOutlet weak var tochka: UIButton!
let decimalSeparator = NSNumberFormatter().decimalSeparator ?? "."
override func viewDidLoad() {
super.viewDidLoad()
tochka.setTitle(decimalSeparator, forState: UIControlState.Normal)
}
@IBAction func appendDigit(sender: UIButton) {
let digit = sender.currentTitle!
// println("digit = \(digit)");
if userIsInTheMiddleOfTypingANumber {
//----- Уничтожаем лидирующие нули ---------------
if (digit == "0") && (display.text == "0") { return }
if (digit != decimalSeparator) && (display.text == "0") { display.text = digit ; return }
//--------------------------------------------------
display.text = display.text! + digit
} else {
if digit == decimalSeparator {
display.text = "0" + decimalSeparator
} else {
display.text = digit
}
userIsInTheMiddleOfTypingANumber = true
}
}
@IBAction func decimalPoint(sender: UIButton) {
let noPointOnDisplay = display.text?.rangeOfString(decimalSeparator) == nil
if (noPointOnDisplay) || !noPointOnDisplay && !userIsInTheMiddleOfTypingANumber {
appendDigit(sender)
}
}
Помешайте сюда свои решения Домашнего задания 1. Можно видео, но лучше ссылку на код для обсуждения вариантов решения.
@IBAction func addPoint(sender: UIButton) {
if pointButton.enabled {
appendDigit(sender)
pointButton.enabled = false
}
}
pointButton.enabled = true
@IBAction func addPoint(sender: UIButton) {
if display.text!.rangeOfString(decimalSeparator) == nil {
appendDigit(sender)
}
}
@IBAction func enterPi(sender: UIButton) {
if userIsInTheMiddleOfTypingANumber {
enter()
AddPiIntoDisplayAndStack()
} else {
AddPiIntoDisplayAndStack()
}
}
func AddPiIntoDisplayAndStack (){
display.text = "\(M_PI)"
enter()
}
Явно программирование не в одну строчку, но пока ничего не приходит другого.
Вопрос про 4 пункт основных заданий, поле UILabel достаточно добавить? реализация остальной логики будет в следующих заданиях?
просто с этим как-то не понятно.
Продолжу выполнять доп-ные задания 1-го ассесмента, если никто не против, буду делиться для оценки. на данный момент только 3-й день знакомства с SWIFT :)
Да, ваше последнее решение и есть решение в одну строку. Но дело даже не в количестве строк, а в том, что вы на этой очень маленькой задачке представили два подхода: один - императивный, то есть вы фиксируете некоторые состояния (в нашем случае наличие точки) и используете это состояние для изменения UI ; второй - можно назвать функциональным, то есть знать ничего не знаю, что было раньше, все буду вычислять сначала. Во втором случае не нужно хранить никакие состояния и переустанавливать их, он считается более безопасным с точки зрения возможных ошибок. Современная тенденция программирования склоняется в эту сторону. Если вам интересно, дискуссия на эту тему уже была на этом форуме: посмотрите ответ Алексея Макеева и мой пост "Задание 2. Решение - начало..."
display.text = "\(newValue)" ?? " "
if let new = newValue {
display.text = "\(new)"
} else {
display.text = " "
}
Да, я уже дошел до этого, но тогда суть задания нарушается.
Тимур, у вас задан Autolayout для метки display, но совсем нет настроек Autolayout для кнопок с цифрами и операциями. Вам нужно закончить изучать Лекцию 2 - ее 3-ая часть посвящена тому, как нужно настроить механизм Autolayout для "сетки" (grid) кнопок. У меня есть перевод этой третьей части Лекции 2, полностью посвященной Autolayout. Кроме того есть готовое Задание 1 - его можно посмотреть на Github. Если в этом Задании вы выделите любую кнопку с цифрами и перейдете в Инспектор Размера, где можно посмотреть какие "ограничения" система Autolayout создала для вас, то увидите следующую картину.
У Вас ничего подобного нет.
В моей версии работоспособность на iPhone 4s и iPhone 5 обеспечивается другим значением ( 749 ) Content Compression Resistance Priority для метки display.
этот материал представлен на Лекции 8.
performOperation {$1/$0}, performOperation (sin). case "sin": isRadian ? performOperation (sin) : performOperation {sin ($0 * M_PI /180.0)}Но формула работает правильно. Видите в конце три точки? Это значит, что число не уместилось в текстовом поле. Вот мой результат эксперимента на Playground
Здесь негативно работают сразу два фактора. Один - это то, что мы используем String interpolation, то есть код в set {} displayValue выглядит так
var displayValue: Double? {
get {
if let displayText = display.text {
return numberFormatter().numberFromString(displayText)?.doubleValue
}
return nil
}
set {
if (newValue != nil) {
display.text = "\(newValue!)"
// display.text = numberFormatter().stringFromNumber(newValue!)
} else {
display.text = " "
addHistory( "= Error")
}
userIsInTheMiddleOfTypingANumber = false
}
}
String interpolation для числа Double упорно старается представить все 15 цифр после точки, даже если они незначащие. Поэтому лучше использовать при выводе числа NSNumberFormatter(), но об этом позже.
Второй фактор - нам не хватило места в метке на iPhone 5, чтобы увидеть правильное число. Для того, чтобы это исправить, нужно правильно настроить метку display.
Сейчас у вас стоит, что если понадобится сжать текст в метке, то все равно будет использоваться фиксированный фонт
а вам нужно , чтобы он уменьшался в случае, если понадобится сжатие
Внизу указан размер минимального фонта.
Это исправит вывод результата следующим образом
Ну а для того, чтобы избавиться от такого некрасивого представления 0, используем форматирование.
var displayValue: Double? {
get {
if let displayText = display.text {
return numberFormatter().numberFromString(displayText)?.doubleValue
}
return nil
}
set {
if (newValue != nil) {
// display.text = "\(newValue!)"
display.text = numberFormatter().stringFromNumber(newValue!)
} else {
display.text = " "
addHistory( "= Error")
}
userIsInTheMiddleOfTypingANumber = false
}
}
func numberFormatter () -> NSNumberFormatter{
let numberFormatterLoc = NSNumberFormatter()
numberFormatterLoc.numberStyle = .DecimalStyle
numberFormatterLoc.maximumFractionDigits = 10
numberFormatterLoc.notANumberSymbol = "Error"
numberFormatterLoc.groupingSeparator = " "
return numberFormatterLoc
}
Тогда вы получите правильный результат
Вы молодец! Действительно, что называется "не верь глазам своим"
Но формула работает правильно. Видите в конце три точки? Это значит, что число не уместилось в текстовом поле. Вот мой результат эксперимента на Playground
Здесь негативно работают сразу два фактора. Один - это то, что мы используем String interpolation, то есть код в set {} displayValue выглядит так
var displayValue: Double? {
get {
if let displayText = display.text {
return numberFormatter().numberFromString(displayText)?.doubleValue
}
return nil
}
set {
if (newValue != nil) {
display.text = "\(newValue!)"
// display.text = numberFormatter().stringFromNumber(newValue!)
} else {
display.text = " "
addHistory( "= Error")
}
userIsInTheMiddleOfTypingANumber = false
}
}
String interpolation для числа Double упорно старается представить все 15 цифр после точки, даже если они незначащие. Поэтому лучше использовать при выводе числа NSNumberFormatter(), но об этом позже.
Второй фактор - нам не хватило места в метке на iPhone 5, чтобы увидеть правильное число. Для того, чтобы это исправить, нужно правильно настроить метку display.
Сейчас у вас стоит, что если понадобится сжать текст в метке, то все равно будет использоваться фиксированный фонт
а вам нужно , чтобы он уменьшался в случае, если понадобится сжатие
Внизу указан размер минимального фонта.
Это исправит вывод результата следующим образом
Ну а для того, чтобы избавиться от такого некрасивого представления 0, используем форматирование.
var displayValue: Double? {
get {
if let displayText = display.text {
return numberFormatter().numberFromString(displayText)?.doubleValue
}
return nil
}
set {
if (newValue != nil) {
// display.text = "\(newValue!)"
display.text = numberFormatter().stringFromNumber(newValue!)
} else {
display.text = " "
addHistory( "= Error")
}
userIsInTheMiddleOfTypingANumber = false
}
}
func numberFormatter () -> NSNumberFormatter{
let numberFormatterLoc = NSNumberFormatter()
numberFormatterLoc.numberStyle = .DecimalStyle
numberFormatterLoc.maximumFractionDigits = 10
numberFormatterLoc.notANumberSymbol = "Error"
numberFormatterLoc.groupingSeparator = " "
return numberFormatterLoc
}
Тогда вы получите правильный результат