みなさんこんにちは!
イザナギです!
さて、この記事を見ている方はおそらくSwiftで開発をしている、もしくは興味を持っている方々だと思います。
実際私も、興味を持ったのでSwiftでの開発を始めました!
初め「何作ろうかな?」って考えました。その時ちょうど買った「iPad」でお絵かきアプリ作れんじゃね?と思いました。
なので、今回はSwiftを使って、お絵かきができるIOSアプリケーションを作成していこうと思い余す!
ツールをご紹介!
初めに私が使用したツールをご紹介したいと思います。
使用したツール以下の通りです。
- Xcode:Version 10.2.1
- macOS: Mojave Version 10.14.5
- IOSシミュレーター iPad(6th)
- Swift
実装していく!
では、作成していきたいと思います!まずは変数を設定します。
今回扱う変数は以下の三つです。
//ベジェ曲線の利用
var bezier:UIBezierPath!
//画像の変数
var Image:UIImage!
//サインする場所
@IBOutlet  var canvas: UIImageView!  
3つ目の変数は、imageviewを利用していますので、ストーリーボードに設置して関連づけておいてください。
ここでなかなか聴き慣れないものが出てきましたね。
そう、「ベジェ曲線」!
ベジェ曲線とは?
「ベジェ曲線」とは、コンピューター上で滑らかな曲線を描け、形が整いやすいそうです。
ボタンの設置
今回は、画像をphotoフォルダーに保存する「saveボタン」と書いたサインをクリアする「clearボタン」を設置します。
メインストーリーボード内でボタンを設置し、右クリックを押し「touch down」を選択し関連づけてください。
//クリアボタンの動作
@IBAction func clear_button(_ sender: Any) {
     clear()
 }
//saveボタン
@IBAction func save_button(_ sender: Any) {
      saveImage(image: Image)
}
ボタンの中には、のちに定義するメソッドを入れてあります。
viewDidLoad()について
次にはじめに呼び出される「viewDidLoad()」でアプリを開いた時の処理を書いていきます。
override func viewDidLoad() {
         super.viewDidLoad()
         
   //書くところ(canvas)についての設定
         canvas = UIImageView()
         canvas.frame = CGRect(x:105,y:295,width:835,height:330)
         canvas.backgroundColor = UIColor.clear
         self.view.addSubview(canvas)
 }
画面をタッチした時のメソッド
画面をタッチした時のメソッドは以下の通りです。
//タッチイベント
override func touchesBegan(_ touches: Set, with event:UIEvent?){ 
          //タッチ時のイベントを習得
          let touchEvent = touches.first! 
          //タッチしている座標を習得
          let currentPoint:CGPoint = touchEvent.location(in: self.canvas)
          bezier = UIBezierPath()
          //ペンの太さ
          bezier.lineWidth = 10.0
          //ペンのスタイル
          bezier.lineCapStyle = .butt
          //支点に現在タッチしている位置をセット
          bezier.move(to:currentPoint)
}
 
ドラックした時の処理
次はドラックした時の処理です。
//ドラックイベント
override func touchesMoved(_ touches: Set, with event:UIEvent?) {
    //タッチ開始時bizierを初期化していない場合処理終了
    if bezier == nil {
        return
    }
    //タッチ時のイベント習得
    let touchEvent = touches.first!
    //タッチしている座標取得
    let currentPoint:CGPoint = touchEvent.location(in: self.canvas)
    //ベジェ曲線を描く
    bezier.addLine(to: currentPoint)
    //描写メソッド(後述)
    drawLine(path: bezier)
}
 
drawLine()メソッドは持ちに定義します。
離した時のメソッド
指などを離した時のメソッドです。
//指を離した時のイベント
override func touchesEnded(_ touches: Set, with event: UIEvent?) {
    if bezier == nil {
        return
    }
    let touchEvent = touches.first!
    let currentPoint:CGPoint = touchEvent.location(in: canvas)
    bezier.addLine(to: currentPoint)
    drawLine(path: bezier)
    //Imageにcanvasのimageを保存
    self.Image = canvas.image
}
 
描写の処理(drawLine()メソッド)
//描画処理
func drawLine(path:UIBezierPath){
    UIGraphicsBeginImageContext(canvas.frame.size)
    if let image = self.Image {
        image.draw(at: CGPoint.zero)
    }
    //線のカラー
    let lineColor = UIColor.black
    //線のスタイル
    lineColor.setStroke()
    path.stroke()
    //canvasに画像を表示
    self.canvas.image = UIGraphicsGetImageFromCurrentImageContext()
    UIGraphicsEndImageContext()
}
ボタンの処理を定義(save,clear)
func clear(){
    Image = nil
    canvas.image = nil
}
//画像を写真ライブラリに追加(端末内)
func saveImage (image: UIImage) {
    UIImageWriteToSavedPhotosAlbum(image,self,nil,nil)
}
clearメソッドは変数のImageとcanvas.imageにnilを入れて初期化しています。
saveメソッドは「UIImageWriteToSavedPhotosAlbum」を利用しています。
これを利用すると、「UIImageをphotoに保存する」ことができます。
これでも画像が保存できるのですが、saveボタンを押しても何も表示されません。
ですので、以下のコードを置き換えます。
UIImageWriteToSavedPhotosAlbum(image,self,nil,nil)
置き換えるコードはした気の通りです。
UIImageWriteToSavedPhotosAlbum(image,self,#selector(self.didFinishSavingImage(_:didFinishSavingWithError:contextInfo:)),nil)
保存結果を返すメソッド
保存できたら「保存完了」エラーの時は「エラー」と表示するメソッドです。
@objc func didFinishSavingImage(_ image: UIImage, didFinishSavingWithError error: NSError!, contextInfo: UnsafeMutableRawPointer) {     
    // 結果によって出すアラートを変更する
    var title = "保存完了"
    var message = "カメラロールに保存しました"
    
    if error != nil {
        title = "エラー"
        message = "保存に失敗しました"
    }
    
    let alertController = UIAlertController(title: title, message: message, preferredStyle: .alert)
    alertController.addAction(UIAlertAction(title: "OK", style: .default, handler: nil))
    self.present(alertController, animated: true, completion: nil)
}
まとめ
完成するとこんな感じになります。シミュレーターを使用しているため字が汚いのはご了承ください。www

いや〜、できましたね!
今回は、下のサイトを参考にさせてもらい、サイン(お絵かき)ができるアプリケーションを作ってみました。
二つのサイトを組み合わせて作りましたので、詳しくは下記のサイトを見た方がわかりやすいかもしれませんね。
これからは、photoに保存ではなくデータベース(今の所MySQL)に保存できるように改造していきたいと思います。
今回はここで筆を置かせていただきます。
最後までご覧いただきありがとうございました!
参考
【Swift】簡易ペイントを作成してみた。
【Swift4】UIViewをUIImageに変換し、画像としてカメラロールに保存する方法