8.22 Draw 畫圖板

面向接口編程勺卢,多個類的共同點(diǎn)提出來伙判,當(dāng)做接口,充分利用多態(tài)的特性減少判斷值漫,利用封裝澳腹,繼承织盼,能使得代碼更加清晰易讀,添加功能也不需要改太多東西酱塔×ち冢可擴(kuò)展性高

將需要畫的線,矩形羊娃,橢圓等都寫成類

import UIKit

class ViewController: UIViewController {
    
    @IBAction func didClicked(sender: UIButton) {
        let cv = self.view as! CustomView
//        let array = cv.array
        
        let path = NSHomeDirectory() + "/Documents/1.jpg"
        //
        //        NSKeyedArchiver.archiveRootObject(array, toFile: path)
        
        //1. 開始一個image上下文唐全,繪制在內(nèi)存的一個區(qū)域,保存為JPG
        UIGraphicsBeginImageContext(self.view.bounds.size)
        //2. 獲取image context
        
        //a.
        //        let context = UIGraphicsGetCurrentContext()
        //
        //        for line in array {
        //            line.draw(context!)
        //        }
        //
        //        CGContextDrawPath(context, .Stroke)
        
        //b. 將視圖上的所有內(nèi)容繪制到當(dāng)前的context中
        //截屏
        cv.drawViewHierarchyInRect(cv.bounds, afterScreenUpdates: true)
        
        //3. 從當(dāng)前上下文中獲取圖片(UIImage)
        let image = UIGraphicsGetImageFromCurrentImageContext()
        //        let data = UIImagePNGRepresentation(image) //UIImage -> NSData
        let data = UIImageJPEGRepresentation(image, 0.4)
        try! data?.writeToFile(path, options: .AtomicWrite)
        
        //4. 結(jié)束圖形上下文
        UIGraphicsEndImageContext()
        
        
        
        //1. 可以自動轉(zhuǎn)換
        //Int/Float... <-> NSNumber
        //String <-> NSString
        //2. 容器的轉(zhuǎn)換有條件蕊玷,元素必須能夠自動轉(zhuǎn)換
        //Dictionary <-> NSDictionary
        //Array <-> NSArray
        //        var strArray = Array<String>()
        //        for point in array {
        //            //CGPoint -> NSString
        //            strArray.append(NSStringFromCGPoint(point))
        //        }
        //        //NSArray是一個不可變類型
        //        (strArray as NSArray).writeToFile(path, atomically: true)
    }
    
    func changeShape(type: Shape.Type) {
        let cv = self.view as! CustomView
        cv.type = type
    }
    
    //meta programming
    //meta type: 元類型
    @IBAction func didLineClicked(sender: UIButton) {
        changeShape(Line.self)
    }
    
    @IBAction func didRectClicked(sender: UIButton) {
        changeShape(Rectangle.self)
    }
    
    @IBAction func didCurveClicked(sender: UIButton) {
        changeShape(Curve.self)
    }
    
    @IBAction func didCircleClicked(sender: AnyObject) {
        changeShape(Circle.self)
    }
    @IBAction func RedColor(sender: UIButton) {
        let cv = self.view as! CustomView
        cv.color = UIColor.redColor().self
    }
    
    @IBAction func BlueColor(sender: UIButton) {
        let cv = self.view as! CustomView
        cv.color = UIColor.blueColor().self

    }
    override func viewDidLoad() {
        super.viewDidLoad()
        
        let cv = self.view as! CustomView
        
        let path = NSHomeDirectory() + "/Documents/array.plist"
        let array = NSKeyedUnarchiver.unarchiveObjectWithFile(path)
        
        if let a = array as? Array<Line> {
            
            cv.array = a
        }
        
        //        let strArray = NSArray(contentsOfFile: path)!
        //        for str in strArray {
        //            //NSString -> CGPoint
        //            let point = CGPointFromString(str as! String)
        //            cv.array.append(point)
        //        }
    }
    
    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }
}

import UIKit

class CustomView: UIView {
    var array = Array<Shape>()
    var type: Shape.Type = Line.self //默認(rèn)為Line類型
    var color: UIColor?
    // Only override drawRect: if you perform custom drawing.
    // An empty implementation adversely affects performance during animation.
    //1. 視圖顯示
    //2. 大小邮利、位置改變
    override func drawRect(rect: CGRect) {
        let context = UIGraphicsGetCurrentContext()
        
        for shape in array {
            
            CGContextSetLineWidth(context, 3)
            CGContextSaveGState(context)
            
            CGContextSetStrokeColorWithColor(context,shape.color?.CGColor)
            //多態(tài)
            shape.draw(context!)
            
            CGContextStrokePath(context)
        }
        
        CGContextDrawPath(context, .Stroke)
    }
    
    func pointForTouches(touches: Set<UITouch>) -> CGPoint {
        
        let touch = touches.first! //UITouch
        let point = touch.locationInView(self)
        
        return point
    }

    override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {
        //獲取起點(diǎn)
        let point = pointForTouches(touches)
        
        let shape = type.init() //必須有required的構(gòu)造函數(shù)
        if color != nil {
            shape.color = color!
        }
        shape.addPoint(point)
        array.append(shape)
    }
    
    override func touchesMoved(touches: Set<UITouch>, withEvent event: UIEvent?) {
        //獲取動態(tài)點(diǎn)
        let point = pointForTouches(touches)
        
        let shape = array.last
        shape?.addPoint(point)
        
        self.setNeedsDisplay() //強(qiáng)制刷新(重繪)
    }
    
    override func touchesEnded(touches: Set<UITouch>, withEvent event: UIEvent?) {
        //獲取終點(diǎn)
        let point = pointForTouches(touches)
        
        let shape = array.last
        shape?.addPoint(point)
        
        self.setNeedsDisplay() //強(qiáng)制刷新(重繪)
    }
}

import UIKit

//enum ShapeType {
//    case Line
//    case Rect
//    case Ellipse
//}

//定義接口協(xié)議,方便其他類調(diào)用
protocol ShapeProtocol {
    func draw(context: CGContextRef)
    func addPoint(point: CGPoint)
}

class Shape: NSObject, NSCoding, ShapeProtocol {
    
//    var begin: CGPoint!
//    var end: CGPoint!
//    var cgcolor: CGColor!
    
    
    //NSArray中只能存放對象
    var points = Array<Point>()
    var color:UIColor!
    required override init() {
        super.init()
        
    }
    
    required init?(coder aDecoder: NSCoder) {
//        begin = aDecoder.decodeCGPointForKey("begin")
//        end = aDecoder.decodeCGPointForKey("end")
        
//        取數(shù)據(jù)
        if let array = aDecoder.decodeObjectForKey("points") as? Array<Point> {
            points = array
        }
        if let m = aDecoder.decodeObjectForKey("color") as?  UIColor{
            color = m
        }
    }
//    存數(shù)據(jù)
    func encodeWithCoder(aCoder: NSCoder) {
//        aCoder.encodeCGPoint(begin, forKey: "begin")
//        aCoder.encodeCGPoint(end, forKey: "end")
        
        aCoder.encodeObject(points, forKey: "points")
        aCoder.encodeObject(color, forKey: "color")

    }
    
    func draw(context: CGContextRef) {
    }
    
    func addPoint(point: CGPoint) {  
    }
}

import UIKit
//兩個點(diǎn)之間的畫圖垃帅,如線延届,矩形,定義為SimpleShape簡單圖形類贸诚,繼承Shape圖形類
class SimpleShape: Shape {
    override func addPoint(point: CGPoint) {
        let p = Point(point: point)
        
        if points.count < 2 {
            points.append(p)
        }
        else {
            points[1] = p
        }
    }
}

import UIKit
//線
class Line: SimpleShape  {
 
    override func draw(context: CGContextRef) {
//        安全檢查方庭,如果少于兩個點(diǎn),就不畫了
        if points.count < 2 {
            return
        }
        
        CGContextMoveToPoint(context, points[0].x, points[0].y)
        CGContextAddLineToPoint(context, points[1].x, points[1].y)
    }
}

import UIKit
//矩形
class Rectangle: SimpleShape {
    override func draw(context: CGContextRef) {
//        安全檢查酱固,必須大于等于兩個點(diǎn)才畫
        guard points.count >= 2 else {
            return
        }
        
        CGContextAddRect(context, CGRect(x: points[0].x, y: points[0].y, width: points[1].x - points[0].x, height: points[1].y - points[0].y))
    }
}

---------------------------

```bash
import UIKit
任意線
class Curve: Shape {
    override func addPoint(point: CGPoint) {
        let p = Point(point: point)
        
        points.append(p)
    }
    
    override func draw(context: CGContextRef) {
        if points.count < 2 {
            return
        }
        
        CGContextMoveToPoint(context, points[0].x, points[0].y)
        for p in points {
            CGContextAddLineToPoint(context, p.x, p.y)
        }
    }
}

import UIKit
//橢圓
class Circle: SimpleShape {
    override func draw(context: CGContextRef) {
        let begin = points[0] //圓心
        let end = points[1]
        
//        求半徑
        //r = ((x1-x0)**2 + (y1-y0)**2)^2
        let radius = sqrt(pow((end.x - begin.x), 2) + pow((end.y - begin.y), 2))
        
        CGContextAddEllipseInRect(context, CGRect(x: begin.x - radius, y: begin.y - radius, width: radius + radius, height: radius + radius))
    }
}

import UIKit

class Point: NSObject, NSCoding {
    var x: CGFloat = 0
    var y: CGFloat = 0
    
    init(point: CGPoint) {
        super.init()
        
        x = point.x
        y = point.y
    }
//    取數(shù)據(jù)
    required init?(coder aDecoder: NSCoder) {
        x = CGFloat(aDecoder.decodeDoubleForKey("x"))
        y = CGFloat(aDecoder.decodeDoubleForKey("y"))
    }
//    存數(shù)據(jù)
    func encodeWithCoder(aCoder: NSCoder) {
        aCoder.encodeDouble(Double(x), forKey: "x")
        aCoder.encodeDouble(Double(y), forKey: "y")
    }
}

編譯運(yùn)行結(jié)果如下:

Paste_Image.png

真彩色械念,類似取色工具 pod search colorpick

協(xié)議和擴(kuò)展都要實(shí)現(xiàn)屬性,實(shí)際上是計算屬性 {set get}

為防止重構(gòu)运悲,寫程序前要留后路

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末龄减,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子班眯,更是在濱河造成了極大的恐慌希停,老刑警劉巖,帶你破解...
    沈念sama閱讀 221,820評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件鳖敷,死亡現(xiàn)場離奇詭異脖苏,居然都是意外死亡程拭,警方通過查閱死者的電腦和手機(jī)定踱,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,648評論 3 399
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來恃鞋,“玉大人崖媚,你說我怎么就攤上這事⌒衾耍” “怎么了畅哑?”我有些...
    開封第一講書人閱讀 168,324評論 0 360
  • 文/不壞的土叔 我叫張陵,是天一觀的道長水由。 經(jīng)常有香客問我荠呐,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 59,714評論 1 297
  • 正文 為了忘掉前任泥张,我火速辦了婚禮呵恢,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘媚创。我一直安慰自己渗钉,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,724評論 6 397
  • 文/花漫 我一把揭開白布钞钙。 她就那樣靜靜地躺著鳄橘,像睡著了一般。 火紅的嫁衣襯著肌膚如雪芒炼。 梳的紋絲不亂的頭發(fā)上瘫怜,一...
    開封第一講書人閱讀 52,328評論 1 310
  • 那天,我揣著相機(jī)與錄音本刽,去河邊找鬼宝磨。 笑死,一個胖子當(dāng)著我的面吹牛盅安,可吹牛的內(nèi)容都是我干的唤锉。 我是一名探鬼主播,決...
    沈念sama閱讀 40,897評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼别瞭,長吁一口氣:“原來是場噩夢啊……” “哼窿祥!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起蝙寨,我...
    開封第一講書人閱讀 39,804評論 0 276
  • 序言:老撾萬榮一對情侶失蹤晒衩,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后墙歪,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體听系,經(jīng)...
    沈念sama閱讀 46,345評論 1 318
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,431評論 3 340
  • 正文 我和宋清朗相戀三年虹菲,在試婚紗的時候發(fā)現(xiàn)自己被綠了靠胜。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,561評論 1 352
  • 序言:一個原本活蹦亂跳的男人離奇死亡毕源,死狀恐怖浪漠,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情霎褐,我是刑警寧澤址愿,帶...
    沈念sama閱讀 36,238評論 5 350
  • 正文 年R本政府宣布,位于F島的核電站冻璃,受9級特大地震影響响谓,放射性物質(zhì)發(fā)生泄漏损合。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,928評論 3 334
  • 文/蒙蒙 一娘纷、第九天 我趴在偏房一處隱蔽的房頂上張望塌忽。 院中可真熱鬧,春花似錦失驶、人聲如沸土居。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,417評論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽擦耀。三九已至,卻和暖如春涩堤,著一層夾襖步出監(jiān)牢的瞬間眷蜓,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,528評論 1 272
  • 我被黑心中介騙來泰國打工胎围, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留吁系,地道東北人。 一個月前我還...
    沈念sama閱讀 48,983評論 3 376
  • 正文 我出身青樓白魂,卻偏偏與公主長得像汽纤,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子福荸,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,573評論 2 359

推薦閱讀更多精彩內(nèi)容

  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 172,297評論 25 707
  • 發(fā)現(xiàn) 關(guān)注 消息 iOS 第三方庫蕴坪、插件、知名博客總結(jié) 作者大灰狼的小綿羊哥哥關(guān)注 2017.06.26 09:4...
    肇東周閱讀 12,120評論 4 61
  • *面試心聲:其實(shí)這些題本人都沒怎么背,但是在上海 兩周半 面了大約10家 收到差不多3個offer,總結(jié)起來就是把...
    Dove_iOS閱讀 27,163評論 30 470
  • 她來了 又要走了 短暫而美麗 圖/文:敬頤
    敬頤閱讀 254評論 0 0
  • 對待生命要有感恩的心。 俗語說:滴水之恩台夺,當(dāng)涌泉相報径玖。感恩是一種生活態(tài)度,是一種善于發(fā)現(xiàn)生活中的感動并能享受這一感...
    映卿閱讀 948評論 0 0