(作业)纯代码版HelloWorld,斯坦福iOS10教学视频

这次作业不止上一篇哦,还有第二个和第三个,第三个作业是按照斯坦福老爷子的视频做一个计算器,那个很简单,博主会在文章末尾附上链接,这次主要完成第二个作业。照常,要求先上
这里写图片描述
第一个作业就用的工程里自带的视图控制器来做的,这次需要将storyboard删除并自己创建自定义的视图控制器。我们需要删除的是工程创建完成之后的Main.storyboard和ViewController.swift,然后需要更该一下工程的配置,不然程序会崩溃。更改工程配置步骤如下:
这里写图片描述

然后就是创建一个继承自UIViewController的MyViewController的类了。
最后就是要求中的ICON和图片了,添加ICON很简单,先自己创建一个大小为180x180像素的icon(可以为png或者jpg格式),然后拖入资源文件夹中即可。具体步骤如下:
这里写图片描述
因为博主用的模拟器是iPhone8 plus,所以它在界面显示的icon大小为180x180像素的,博主还做了一个120x120像素的,那是可以显示在多任务界面中。就这儿:
这里写图片描述
顺便附上博主自己做的图标吧(虽然略丑,但请不要嫌弃)
120x120
180x180
然后是添加图片了,这个很简单,自己找一张图片,然后在工程文件夹下右击,选择add files to… 最后找到你的图片就可以了(不要直接拖进去,有时候会找不到该文件,亲测的坑)
这里写图片描述

以上就是这次作业需要的准备工作了,现在就开始写代码吧。首先是
AppDelegate.swift

import UIKit

@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {

    var window: UIWindow?


    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
        // Override point for customization after application launch.

        //创建UIWindow对象
        window = UIWindow(frame: UIScreen.main.bounds)
        //设置window的根视图控制器为MyViewController
        window?.rootViewController = MyViewController()
        //显示window
        window?.makeKeyAndVisible()

        return true
    }

    func applicationWillResignActive(_ application: UIApplication) {
        // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.
        // Use this method to pause ongoing tasks, disable timers, and invalidate graphics rendering callbacks. Games should use this method to pause the game.
    }

    func applicationDidEnterBackground(_ application: UIApplication) {
        // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later.
        // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
    }

    func applicationWillEnterForeground(_ application: UIApplication) {
        // Called as part of the transition from the background to the active state; here you can undo many of the changes made on entering the background.
    }

    func applicationDidBecomeActive(_ application: UIApplication) {
        // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
    }

    func applicationWillTerminate(_ application: UIApplication) {
        // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
    }


}

在AppDelegate.swift中需要添加的代码也不多,就application(application:didFinishLaunchingWithOptions:)函数中的三行代码,这里贴全了。其他方法是在特定情况下有用的,各位看着不爽可以删掉。

然后是
MyView.swift

import UIKit

class MyView: UIView {

    private var function: ((CGFloat) -> CGFloat)? //一元函数

    override func draw(_ rect: CGRect) {
        //调用父类的draw方法
        super.draw(rect)

        //创建一个UIBezierPath变量,UIBezierPath可创建基于矢量的路径,常用来绘图
        let rectPath = UIBezierPath(rect: rect)
        //设置白色填充
        UIColor.white.setFill()
        //先将MyView填充一层白色
        rectPath.fill()

        //再创建一个UIBezierPath变量,用于绘制坐标系
        let path = UIBezierPath()
        //坐标系用红色描边
        UIColor.black.setStroke()
        //坐标系以MyView中心为原点,向右为x正方向,向上为y正方向
        //先将path移动到左边线中点处
        path.move(to: CGPoint(x: 0, y: rect.height / 2))
        //然后添加一条到右边线中点处的直线
        path.addLine(to: CGPoint(x: rect.width, y: rect.height / 2))
        //绘制这条直线
        path.stroke()
        //这样就完成了x轴的绘制

        //绘制y轴原理同上
        path.move(to: CGPoint(x: rect.width / 2, y: 0))
        path.addLine(to: CGPoint(x: rect.width / 2, y: rect.height))
        path.stroke()

        //判断函数是否为空,方便后面会再次调用draw函数
        if function != nil {
            let path = curve(rect: rect, color: UIColor.red, function: function!)
            path.stroke()
        }
    }


    /// 绘制图形的函数
    ///
    /// - Parameter function: 需要绘制的一元函数
    func drawCurve(function: @escaping (CGFloat) -> CGFloat) {
        self.function = function
        self.draw(self.frame)
    }


    /// 计算函数绘制的路径
    ///
    /// - Parameters:
    ///   - rect: 绘制区域
    ///   - color: 绘制函数的颜色
    ///   - function: 需要绘制的函数
    /// - Returns: 返回最终绘制的路径
    private func curve(rect: CGRect, color: UIColor, function: (CGFloat) -> CGFloat) -> UIBezierPath {
        let path = UIBezierPath()

        //该绘制区域的宽度的一半
        let center = rect.width / 2
        //y轴的高度的一半
        let height = rect.height / 2
        //需要计算多少个x值对应的y值(x轴正半轴)
        let rate: CGFloat = 100
        color.setStroke()

        //从原点开始,先计算x轴正半轴的所有y值
        path.move(to: CGPoint(x: center, y: height - function(0) / rate))
        //stride为步进函数,设置起始值、结尾值和步进值
        for item in stride(from: center / rate, through: center, by: center / rate) {
            path.addLine(to: CGPoint(x: center + item, y: height - function(item) / rate))
        }
        //因为自己建立的简易坐标系与UIView视图默认的坐标系不同(UIView默认视图坐标系原点在左上角,并向右为x轴正方向,向下为y轴正方向)。所以需要用到类似仿射变换的方式转换坐标系,将当前坐标系中的点转换成UIView坐标系中的值。UIView中x值为当前值加上x轴宽度的一半,y值为y轴高度的一半减去在当前坐标系中的y值

        //绘制x轴负半轴的所有y值,原理类似
        path.move(to: CGPoint(x: center, y: height - function(0) / rate))
        for item in stride(from: center / rate, through: center, by: center / rate) {
            path.addLine(to: CGPoint(x: center - item, y: height - function(-item) / rate))
        }

        return path
    }

}

这个是在作业1中需要的自定义UIView类,博主这里就偷下懒,不再重新说明了,各位想要详细了解一下的话,可以点击这里去看看博主的上一篇文章。

最后是
MyViewController.swift

import UIKit

class MyViewController: UIViewController {

    //声明UILabel对象
    var label: UILabel!

    override func viewDidLoad() {
        super.viewDidLoad()

        //设置根视图视图背景色
        self.view.backgroundColor = UIColor.white

        let myView = MyView(frame: CGRect(x: 0, y: 20, width: self.view.frame.width, height: self.view.frame.height - 20))
        myView.drawCurve { (x) -> CGFloat in
            return x * x
        }
        self.view.addSubview(myView)

        //创建UILabel对象
        label = UILabel(frame: CGRect(x: 100, y: 100, width: 100, height: 40))
        //设置label显示文字
        label.text = "hello world"
        //将label加入到视图控制器中
        self.view.addSubview(label)

        //创建UIButton对象
        let btn = UIButton(frame: CGRect(x: 100, y: 250, width: 100, height: 40))
        //设置正常状态下按钮的标题
        btn.setTitle("点我", for: .normal)
        //设置按钮边框宽度
        btn.layer.borderWidth = 1
        //设置正常状态下标题的颜色
        btn.setTitleColor(UIColor.black, for: .normal)
        //设置高亮状态下(被点击且未释放鼠标)标题的颜色
        btn.setTitleColor(UIColor.brown, for: .highlighted)
        //给按钮添加target-action
        btn.addTarget(self, action: #selector(clicked), for: .touchUpInside)
        self.view.addSubview(btn)

        //创建UIImageView对象
        let imageView = UIImageView(frame: CGRect(x: 10, y: 400, width: self.view.frame.width - 20, height: (self.view.frame.width - 20) * 0.618))
        //获取图片资源路径
        let path = Bundle.main.path(forResource: "Coffee", ofType: "png")
        //以该路径创建图片
        let image = UIImage(contentsOfFile: path!)
        //将图片加入到imageView中
        imageView.image = image
        //将imageView加入到控制器中
        self.view.addSubview(imageView)
    }


    /// 按钮点击事件,改变label显示的文字
    @objc func clicked() {
        if label.text == "hello world" {
            label.text = "I'm clicked"
        } else {
            label.text = "hello world"
        }
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }
}

这就是这次作业2的重点了,注释应该写得蛮清楚了,如果还有不懂的话,可以留言询问。

来看看最终的效果图吧。
这里写图片描述
这里写图片描述

最后附上斯坦福老爷子的视频链接,有iPhone的同学可以直接在iTunes U中搜索

英文字幕版:https://apollozhu.github.io/Developing-iOS-10-Apps-with-Swift/tools/download.html
B站牛人中文翻译版: https://space.bilibili.com/14767902#!/channel/detail?cid=9243

再来分享一下博主这次作业的工程吧:
纯代码版HelloWorld
iOS版计算器
MacOS版计算器

发布了45 篇原创文章 · 获赞 20 · 访问量 5万+

猜你喜欢

转载自blog.csdn.net/average17/article/details/78277352