iOS Programming: The Big Nerd Ranch Guide 5th Edition

1- Introduction

作为iOS开发者,必须掌握:

  • swift 语言
  • 重要概念 - 代理,归档等
  • 框架

MVC pattern

iOS Programming: The Big Nerd Ranch Guide 5th Edition_第1张图片
MVC.png

Interface Builder

  • document outline
  • canvas
iOS Programming: The Big Nerd Ranch Guide 5th Edition_第2张图片
IB.png

Xcode utility area

iOS Programming: The Big Nerd Ranch Guide 5th Edition_第3张图片
utility area.png

scheme

iOS Programming: The Big Nerd Ranch Guide 5th Edition_第4张图片
scheme.png

Auto Layout

iOS Programming: The Big Nerd Ranch Guide 5th Edition_第5张图片
autolayout.png
  • 技巧:多选添加多个约束
iOS Programming: The Big Nerd Ranch Guide 5th Edition_第6张图片
multiple.png

Application Icons

  • size

Launch Screen

iOS Programming: The Big Nerd Ranch Guide 5th Edition_第7张图片
launch.png

2 - The Swift Language

Types

  • structures
  • classes
  • enumerations
iOS Programming: The Big Nerd Ranch Guide 5th Edition_第8张图片
types.png
  1. 字典的key必须是hashable,保证key唯一,Int, Float, Character, String都是hashable
  2. 集合的元素唯一并且是hashable
  3. literal values 是 instance。
  4. 初始化器:
  • 空值
l​e​t​ ​e​m​p​t​y​S​t​r​i​n​g​ ​=​ ​S​t​r​i​n​g​(​)​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​// "​"​
l​e​t​ ​e​m​p​t​y​A​r​r​a​y​O​f​I​n​t​s​ ​=​ ​[​I​n​t​]​(​)​ ​ ​ ​ ​ ​ ​ ​// 0​ ​e​l​e​m​e​n​t​s​
l​e​t​ ​e​m​p​t​y​S​e​t​O​f​F​l​o​a​t​s​ ​=​ ​S​e​t​<​F​l​o​a​t​>​(​)​ ​ ​// 0​ ​e​l​e​m​e​n​t​s​”
  • 默认值
l​e​t​ ​d​e​f​a​u​l​t​N​u​m​b​e​r​ ​=​ ​I​n​t​(​)​ ​ // 0​
l​e​t​ ​d​e​f​a​u​l​t​B​o​o​l​ ​=​ ​B​o​o​l​(​)​ ​ ​   // f​a​l​s​e​
le​t​ ​d​e​f​a​u​l​t​F​l​o​a​t​ ​=​ ​F​l​o​a​t​(​)​   // 0.0
  1. 文档资料
  • The Swift Programming Language
  • The Swift Standard Library Reference

3 - Views and the View Hierarchy

  1. View Hierarchy
iOS Programming: The Big Nerd Ranch Guide 5th Edition_第9张图片
view hierarchy.png
  1. 一旦层级关系确定,就开始绘制到屏幕上:
  • 绘制自己到layer
  • 所以的layer在屏幕上组合起来
iOS Programming: The Big Nerd Ranch Guide 5th Edition_第10张图片
render.png
  1. 一个 framework 是相关的类和资源的集合。

  2. 一个视图的frame是相对其父视图的。

  3. Baseline :大部分是和bottom相同的,但是UITextField和UILabel是在其内容的底部。

  4. Frame 和 Alignment rectangle

  • Alignment rectangle 大部分和 Frame相同,但它是通过约束计算出来的。
iOS Programming: The Big Nerd Ranch Guide 5th Edition_第11张图片
alignment.png

4 - Text Input and Delegation

  1. 使用N​S​N​u​m​b​e​r​F​o​r​m​a​t​t​e​r 输出格式化数字的字符串
    参考 iOS中数字的格式化 NSNumberFormatter
l​e​t​ ​n​u​m​b​e​r​F​o​r​m​a​t​t​e​r​:​ ​N​S​N​u​m​b​e​r​F​o​r​m​a​t​t​e​r​ ​=​ ​{​
 ​ ​ ​ ​l​e​t​ ​n​f​ ​=​ ​N​S​N​u​m​b​e​r​F​o​r​m​a​t​t​e​r​(​)​
 ​ ​ ​ ​n​f​.​n​u​m​b​e​r​S​t​y​l​e​ ​=​ ​.​D​e​c​i​m​a​l​S​t​y​l​e​
 ​ ​ ​ ​n​f​.​m​i​n​i​m​u​m​F​r​a​c​t​i​o​n​D​i​g​i​t​s​ ​=​ ​0​
 ​ ​ ​ ​n​f​.​m​a​x​i​m​u​m​F​r​a​c​t​i​o​n​D​i​g​i​t​s​ ​=​ ​1​
 ​ ​ ​ ​r​e​t​u​r​n​ ​n​f​
}​(​)​

  c​e​l​s​i​u​s​L​a​b​e​l​.​t​e​x​t​ ​=​ ​n​u​m​b​e​r​F​o​r​m​a​t​t​e​r​.​s​t​r​i​n​g​F​r​o​m​N​u​m​b​e​r​(​v​a​l​u​e​)​
  1. 代理:处理多个callback。

  2. 代理协议的命名:类名+Delegate

  3. 避免输入两个.

    func textField(textField: UITextField, shouldChangeCharactersInRange range: NSRange, replacementString string: String) -> Bool {
        
        let existingTextHasDecimalSeparator = textField.text?.rangeOfString(".")
        let replacementTextHasDecimalSeparator = string.rangeOfString(".")
        
        if existingTextHasDecimalSeparator != nil && replacementTextHasDecimalSeparator != nil {
            return false
        }
        else {
            return true
        }
    }
  1. 限制只能输入特定的字符 ???

5 - View Controllers

  1. 当一个View controller 被设置为window的 rootViewController ,它的view 被添加到window的视图层级中。

  2. A UITabBarController’s view is a UIView with two subviews: the tab bar and the view of the selected view controller

  3. 生命周期

  • init(coder:) :用 storyboard 创建 或 init(nibName:bundle:):用代码创建
  • loadView()
  • viewDidLoad()
  • viewWillAppear(_: )
  • viewDidAppear(_:)
  • viewWillDisappear(_:)
  • viewDidDisappear(_:)

6 - Programmatic Views

  1. Constraints Common ancestor
  • 约束需要加到最近的共同祖先上。
  • active属性的作用:先找共同祖先,然后调用addConstraint(:) 或 removeConstraint(:)
  1. layoutGuide
  • 使用topLayoutGuide:让内容不遮挡status bar 或 navigation bar
  • 使用bottomLayoutGuide: 让内容不遮挡 tab bar
  • 可以使用的约束:topAnchor, bottomAnchor, heightAnchor
  1. layoutMarginsGuide
  • 每个视图都有这个属性

7 - Localization

国际化

  1. NSNumberFormatter
  • 有一个local属性,被设置为设备的当前local,使用NSNumberFormatter时,它会首先检查它的local属性,然后格式化设置内容。
  • NSLocal 知道不同地区使用的symbols, dates, decimals and whether use metric system。
@IBAction func fahrenheitFieldEditingChanges(textField: UITextField) {
        if let text = textField.text, let number = numberFormatter.numberFromString(text) {
            fahrenheitValue = number.doubleValue
        }
        else {
            fahrenheitValue = nil
        }
    }
  • NSLocal.currentLocal() 代表用户设置的地区。
 func textField(textField: UITextField, shouldChangeCharactersInRange range: NSRange, replacementString string: String) -> Bool {
        
        let currentLocale = NSLocale.currentLocale()
        let decimalSeparator =
        currentLocale.objectForKey(NSLocaleDecimalSeparator) as! String
        
        let existingTextHasDecimalSeparator = textField.text?.rangeOfString(decimalSeparator)
        let replacementTextHasDecimalSeparator = string.rangeOfString(decimalSeparator)
        
        if existingTextHasDecimalSeparator != nil && replacementTextHasDecimalSeparator != nil {
            return false
        }
        else {
            return true
        }
    }

本地化

NSLocal 没有的,只有本地化。

  1. 调试技巧:
  • Edit Scheme... -> Run -> Options -> Application Region
  • Show Assistant Editor -> Preview -> 右下角可以选择语言
  • 添加本地化后 -> 删除应用 -> 重启xcode -> Clean -> Run
  1. 本地化的原理:main bundle 里放了所有的资源文件,本地化资源文件就是复制一份放在 bundle 的具体语言的目录下(目录名为语言和地区的简写,后缀为iproj)。当需要资源的时候,先查找bundle的最顶层,如果找到,返回文件的URL,如果没有找到,则根据地区和语言设置找到相应的iproj目录,查找需要的资源,如果找到,返回URL,如果没有找到,则查找Base.iproj目录,如果没有找到,则返回nil。(为什么使用调试技巧3)
  • storyboard 怎么办?Xcode 创建了 Base.iproj 目录将storyboard 放在里面,如需本地化只需创建 Localizable.strings 文件(只本地化字符串)。
  • 界面可以通过Autolayout本地化。
  1. storyboard 本地化步骤

  2. 选中右侧Localization -> 选中English


    iOS Programming: The Big Nerd Ranch Guide 5th Edition_第12张图片
    check.png
  3. Project -> Info -> + -> 添加其他语言

  4. 翻译对应语言

  5. 使用调试技巧2,选择Application Language

  6. 代码中的字符串本地化步骤

  7. 在代码中使用NSLocalizedString函数

let str = NSLocalizedString("hello world", comment: "xxxxddd")
  1. 用终端进入代码文件目录

  2. 输入命令:genstrings ViewController.swift

  3. 将生成的文件Localizable.strings拖入项目

  4. 选中右侧Localization -> 点击Localize... -> Base

  5. 勾选其他语言

  6. 翻译对应语言

  7. 使用调试技巧2,选择Application Language

  8. 使用XLIFF文件

  9. 导出:Project -> Editor -> Export For Localization...

  10. 翻译

  11. 导入:Project -> Editor -> Import For Localization...

8 - Controlling Animations

  1. 约束动画:layoutIfNeeded -> 修改动画 -> layoutIfNeeded
    技巧:使用swap(_:)函数。

     view.layoutIfNeeded()
     
     let screenWidth = view.frame.width
     self.nextQuestionLabelCenterXConstraint.constant = 0
     self.currentQuestionLabelCenterXConstraint.constant += screenWidth
     
     UIView.animateWithDuration(0.5,
         delay: 0,
         options: [.CurveLinear],
         animations: {
             self.currentQuestionLabel.alpha = 0
             self.nextQuestionLabel.alpha = 1
             
             self.view.layoutIfNeeded()
         },
         completion: { _ in
             swap(&self.currentQuestionLabel, &self.nextQuestionLabel)
             swap(&self.currentQuestionLabelCenterXConstraint, &self.nextQuestionLabelCenterXConstraint)
             
             self.updateOffScreenLabel()
     })
    

9 - TableViewControllers

  1. UITableViewController
  • view controller
  • data source
  • delegate


    iOS Programming: The Big Nerd Ranch Guide 5th Edition_第13张图片
    TableViewController.png
  1. MVC


    iOS Programming: The Big Nerd Ranch Guide 5th Edition_第14张图片
    MVC.png
  • 使用依赖注入:初始化传入(纯代码)或者通过属性传入(stroyboard)。
  1. UITableViewCell 层级关系


    iOS Programming: The Big Nerd Ranch Guide 5th Edition_第15张图片
    UITableViewCell.png

    iOS Programming: The Big Nerd Ranch Guide 5th Edition_第16张图片
    style.png
  2. 重用机制

  • 注册
  • dequeue
    首先根据identifier查看重用池(队列),如果有,则dequeue,如果没有,系统根据注册的类型创建。
  1. Content Insets
    // Get the height of the status bar
    let statusBarHeight = UIApplication.sharedApplication().statusBarFrame.height

     let insets = UIEdgeInsets(top: statusBarHeight, left: 0, bottom: 0, right: 0)
     tableView.contentInset = insets
     tableView.scrollIndicatorInsets = insets
    
  2. 设计模式

  • Delegation
  • Data source
  • Model - View - Controller
  • Target - action pairs
  1. dynamic type
  • storyboard(静态)


    iOS Programming: The Big Nerd Ranch Guide 5th Edition_第17张图片
    dynamic type.png

    iOS Programming: The Big Nerd Ranch Guide 5th Edition_第18张图片
    dynamic type2.png
  • code (动态)
    func updateLabels() {
        let bodyFont = UIFont.preferredFontForTextStyle(UIFontTextStyleBody)
        nameLabel.font = bodyFont
        valueLabel.font = bodyFont
        
        let caption1Font = UIFont.preferredFontForTextStyle(UIFontTextStyleCaption1)
        serialNumberLabel.font = caption1Font
    }
  1. stack view
    技巧:nested stackView + intrinsic size + content hugging priority + content compression resistance priority + auto layout

10 - NavigationController

  1. 触发segue
  • action item(button, tableViewCell, other UIControl) :storyboard 触发
  • identifier : 代码触发,判断segue
  • 传值: tableView.indexPathForSelectedRow
    override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
        // If the triggered segue is the "ShowItem" segue
        if segue.identifier == "ShowItem" {
            
            // Figure out which row was just tapped
            if let row = tableView.indexPathForSelectedRow?.row {
                
                // Get the item associated with this row and pass it along
                let item = itemStore.allItems[row]
                let detailViewController = segue.destinationViewController as! DetailViewController
                detailViewController.item = item
            }
        }
    }
  1. endEditing(_:):关闭键盘的便利方法。
  • 不用关心哪一个 text field 是响应者。它会检查自己层级中是否有是第一响应者的 text field,如果有,则对其调用 resignFirstResponder()
  • 重写becomeFirstResponder(),自定义 text field 的 borderStyle
  1. 每一个UIViewController 有一个 navigationItem 属性,它不是UIView的子类,而是为navigation bar 提供内容。navigation bar 根据 view controller 的navigationItem 配置自己。UIBarButtonItem 类似。
iOS Programming: The Big Nerd Ranch Guide 5th Edition_第19张图片
title.png
iOS Programming: The Big Nerd Ranch Guide 5th Edition_第20张图片
everything.png

11 - Camera

  1. UIImagePickerController
    设置 sourceType
  • Camera:使用相机
  • PhotoLibrary:使用相册
  • SavedPhotosAlbum:使用最近拍照


    source type.png
    @IBAction func takePicture(sender: UIBarButtonItem) {
        
        let imagePicker = UIImagePickerController()
        
        // If the device has a camera, take a picture, otherwise,
        // just pick from photo library
        if UIImagePickerController.isSourceTypeAvailable(.Camera) {
            imagePicker.sourceType = .Camera
        }
        else {
            imagePicker.sourceType = .PhotoLibrary
        }
        
        imagePicker.delegate = self
        
        // Place image picker on the screen
        presentViewController(imagePicker, animated: true, completion: nil)
    }

    func imagePickerController(picker: UIImagePickerController,
        didFinishPickingMediaWithInfo info: [String: AnyObject]) {
            
            // Get picked image from info dictionary
            let image = info[UIImagePickerControllerOriginalImage] as! UIImage
            
            // Store the image in the ImageStore for the item's key
            imageStore.setImage(image, forKey:item.itemKey)
            
            // Put that image onto the screen in our image view
            imageView.image = image
            
            // Take image picker off the screen -
            // you must call this dismiss method
            dismissViewControllerAnimated(true, completion: nil)
    }
  1. Cache
    将image 存储在内存,如果收到low-memory 通知,则释放占有的资源。

12 - Archiving

  1. 界面文件的对象是arhieved。
    数字使用:encodeInt(intv: Int32, forKey key: String)
    字符串使用:encodeObject(objv: AnyObject?, forKey key: String)
    原因:虽然String不是对象,但是它和NSString 桥接了,会自动转换。

  2. Encoding 是递归操作
    所有对象都必须遵守NSCoding协议!


    iOS Programming: The Big Nerd Ranch Guide 5th Edition_第21张图片
    encoding.png
  3. 沙盒
    Library/Preferences 是自动被NSUserDefaults管理。


    iOS Programming: The Big Nerd Ranch Guide 5th Edition_第22张图片
    sandbox.png
  4. 使用DocumentDirectory和first的原因
    iOS和OS X共用一套API。
    let itemArchiveURL: NSURL = {
    let documentsDirectories =
    NSFileManager.defaultManager().URLsForDirectory(.DocumentDirectory,
    inDomains: .UserDomainMask)
    let documentDirectory = documentsDirectories.first!
    return documentDirectory.URLByAppendingPathComponent("items.archive")
    }()

  5. application state

iOS Programming: The Big Nerd Ranch Guide 5th Edition_第23张图片
state.png
iOS Programming: The Big Nerd Ranch Guide 5th Edition_第24张图片
conclude.png
  1. image data
    UIImageJPEGRepresentation(image, 0.5)
    第二个参数为压缩质量。1.0 是最高质量,少压缩。
    data.writeToURL(imageURL, atomically: true)
    第二个参数如果为true,文件先写到文件的临时地方,一旦写操作完成,文件重命名为URL,替换以前存在的文件。

  2. bundle
    bundle中的文件是只读的,不能修改,在运行时也不能动态添加文件。

13 - SizeClasses

  1. 改变sizeClasses可以改变:
  • 视图的属性 (比如stackView)
  • subview 是否 installed
  • constraint 是否 installed
  • constraint 的 constant
  • subview 的字体

14 - TouchEvents
1.默认状态,view一次只能接受一个touch。一旦开始,其他touch的touch生命周期方法ignored。

iOS Programming: The Big Nerd Ranch Guide 5th Edition_第25张图片
multiple touch.png
  1. UIMenuController
  • only one UIMenuController per application
  • has list of UIMenuItem
  • item has a title and action
  • action message sends the first responder of the window
    func tap(gestureRecognizer: UIGestureRecognizer) {
       print("Recognized a tap")
       
       let point = gestureRecognizer.locationInView(self)
       selectedLineIndex = indexOfLineAtPoint(point)
       
       // Grab the menu controller
       let menu = UIMenuController.sharedMenuController()
       
       if selectedLineIndex != nil {
           
           // Make ourselves the target of menu item action messages
           becomeFirstResponder()
           
           // Create a new "Delete" UIMenuItem
           let deleteItem = UIMenuItem(title: "Delete", action: "deleteLine:")
           menu.menuItems = [deleteItem]
           
           // Tell the menu where it should come from and show it
           menu.setTargetRect(CGRect(x: point.x, y: point.y, width: 2, height: 2),
               inView: self)
           menu.setMenuVisible(true, animated: true)
       }
       else {
           // Hide the menu if no line is selected
           menu.setMenuVisible(false, animated: true)
       }
       
       setNeedsDisplay()
   }
   
   func deleteLine(sender: AnyObject) {
       // Remove the selected line from the list of finishedLines
       if let index = selectedLineIndex {
           finishedLines.removeAtIndex(index)
           selectedLineIndex = nil
           
           // Redraw everything
           setNeedsDisplay()
       }
   }
   
   override func canBecomeFirstResponder() -> Bool {
       return true
   }

14 - CollectionView

  1. the collection view will be pinned to the top of the entire view instead of to the top layout guide. This is useful for scroll views (and their subclasses, like UITableView and UICollectionView) so that the content will scroll underneath the navigation bar. The scroll view will automatically update its insets to make the content visible.

你可能感兴趣的:(iOS Programming: The Big Nerd Ranch Guide 5th Edition)