いよいよ電卓画面を実装します。
ViiewControllerからキーボードの値だけをNumberQueueオブジェクトに入れ込めば済むように作ってある(ハズな)ので、本当に画面を作るだけで済むはずです。
で、できあがった画面は次のものになります。
なかなか真っ暗でしょ(ww)
まぁ色合いはさておき、下のボタン類をNumberQueueに受け渡すところは簡単にできました。単にイベントを受け取ったら所定の値を渡すだけです。
問題は、結果を表示するところです。
NumberQueueオブジェクト自身は計算結果を返してくれません。値を返してもいいのですが、そうするとボタンごとに結果を表示するという、変な話になってしまいますので、それではNGです。
ということで、delegateを実装していくことにしました。前にも作っていましたが、objective-cでもあり、もう忘れているのもあり、調べながら作っていきました。
まずはプロトコロル(空の関数)の実装からです。
この空の関数を定義するのは、ViewControllerですので、このDelegateを採用しますよ、というのをViewControllerで宣言してあげます。
print(s)は単にデバック用の表示です。
ViewConroller側はこれでOK(ではありません。あとで問題になります)。
NumberQueue側では、このデリゲート使いますよ、というのを宣言します。
この!は、デリゲートができていない場合nilになるので、!を書くようですが、これ自身に問題がありませんが、あとで問題に。
で、このデリゲートオブジェクトの関数を直接使ってもいいのですが、使うための関数を作ってあげます。
これで実装は完了(のはずでしたが・・)ですので、これまでデバッグ用に実装していた結果の表示のprintをdispに置き換えてあげると表示されるはずでした。
しかし、実行時にエラーが。
unexpectedly found nil while implicity unwrapping an optional value
なんじゃこれ、というので調べてみると!を?にして関数にも?をつければいいという、デマ回答が乗っていてさらに混乱しました。
いろいろとググっていくと、質問者の質問に「何かを実装していないけれども、実装していると仮定して」とかいう前提付きで回答している人がいました。
これは意地悪な回答だわ、と思いつつ、そういえばViewConroller側ではNumberQueueから呼び出されるのがわからないし、このdisplayというオブジェクトが生成されていないということなんだよなぁ、ということでこんなコードを入れてみました。
はい、ビンゴです。
numberQueueのdisplayというオブジェクトは、自分が実装してますよ、と言ってあげているんですね。これで上のエラーがでなくなりましたので、無事displayのオブジェクトができてViewControllerで受け取ることができました。
しかし、delegateの解説が少なすぎて、あっても複雑に書かれすぎでよくわからんわ。まぁ解決したのでOK牧場ですね。
あとは、この電卓をつかいながらデバッグしていきます。
ViiewControllerからキーボードの値だけをNumberQueueオブジェクトに入れ込めば済むように作ってある(ハズな)ので、本当に画面を作るだけで済むはずです。
で、できあがった画面は次のものになります。
なかなか真っ暗でしょ(ww)
まぁ色合いはさておき、下のボタン類をNumberQueueに受け渡すところは簡単にできました。単にイベントを受け取ったら所定の値を渡すだけです。
@IBAction func AC(_ sender: Any) {
numberQueue.calc("c")
}
@IBAction func c(_ sender: Any) {
numberQueue.pop()
}
@IBAction func nine(_ sender: Any) {
numberQueue.push("9")
}
@IBAction func eight(_ sender: Any) {
numberQueue.push("8")
}
@IBAction func seven(_ sender: Any) {
numberQueue.push("7")
}
@IBAction func six(_ sender: Any) {
numberQueue.push("6")
}
@IBAction func five(_ sender: Any) {
numberQueue.push("5")
}
@IBAction func four(_ sender: Any) {
numberQueue.push("4")
}
@IBAction func three(_ sender: Any) {
numberQueue.push("3")
}
@IBAction func two(_ sender: Any) {
numberQueue.push("2")
}
@IBAction func one(_ sender: Any) {
numberQueue.push("1")
}
@IBAction func zero(_ sender: Any) {
numberQueue.push("0")
}
@IBAction func zerozero(_ sender: Any) {
numberQueue.push("0")
numberQueue.push("0")
}
@IBAction func dot(_ sender: Any) {
numberQueue.push(".")
}
@IBAction func plus(_ sender: Any) {
numberQueue.calc("+")
}
@IBAction func minus(_ sender: Any) {
numberQueue.calc("-")
}
@IBAction func x(_ sender: Any) {
numberQueue.calc("*")
}
@IBAction func dev(_ sender: Any) {
numberQueue.calc("/")
}
@IBAction func equal(_ sender: Any) {
numberQueue.calc("=")
}
問題は、結果を表示するところです。
NumberQueueオブジェクト自身は計算結果を返してくれません。値を返してもいいのですが、そうするとボタンごとに結果を表示するという、変な話になってしまいますので、それではNGです。
ということで、delegateを実装していくことにしました。前にも作っていましたが、objective-cでもあり、もう忘れているのもあり、調べながら作っていきました。
まずはプロトコロル(空の関数)の実装からです。
protocol DisplayDelegate{
func disp(_ s:String)
}
この空の関数を定義するのは、ViewControllerですので、このDelegateを採用しますよ、というのをViewControllerで宣言してあげます。
class ViewController: UIViewController ,DisplayDelegate{
そうすると、「ViewControllerにこの関数を実装していませんよ」と怒られますので、実装してあげます。
func disp(_ s: String) {
print(s)
mainDisplay.text = s
}
ViewConroller側はこれでOK(ではありません。あとで問題になります)。
NumberQueue側では、このデリゲート使いますよ、というのを宣言します。
var display: DisplayDelegate!
で、このデリゲートオブジェクトの関数を直接使ってもいいのですが、使うための関数を作ってあげます。
func disp(_ s:String){
self.display.disp(s)
}
これで実装は完了(のはずでしたが・・)ですので、これまでデバッグ用に実装していた結果の表示のprintをdispに置き換えてあげると表示されるはずでした。
しかし、実行時にエラーが。
unexpectedly found nil while implicity unwrapping an optional value
なんじゃこれ、というので調べてみると!を?にして関数にも?をつければいいという、デマ回答が乗っていてさらに混乱しました。
いろいろとググっていくと、質問者の質問に「何かを実装していないけれども、実装していると仮定して」とかいう前提付きで回答している人がいました。
これは意地悪な回答だわ、と思いつつ、そういえばViewConroller側ではNumberQueueから呼び出されるのがわからないし、このdisplayというオブジェクトが生成されていないということなんだよなぁ、ということでこんなコードを入れてみました。
override func viewDidLoad() {
super.viewDidLoad()
numberQueue.display = self
// Do any additional setup after loading the view.
}
はい、ビンゴです。
numberQueueのdisplayというオブジェクトは、自分が実装してますよ、と言ってあげているんですね。これで上のエラーがでなくなりましたので、無事displayのオブジェクトができてViewControllerで受け取ることができました。
しかし、delegateの解説が少なすぎて、あっても複雑に書かれすぎでよくわからんわ。まぁ解決したのでOK牧場ですね。
あとは、この電卓をつかいながらデバッグしていきます。
0 件のコメント:
コメントを投稿