Swift 语法小结
2015-08-03 17:52
441 查看
Swift
1.基本数据类型
a. Optional 就是枚举
AnOptional is just an enum
enum Optional<T>{
case None
case Some(T)
}
b.Array的声明
vara=Array<String>()
vara=[String]()
leta=[“A”,”B”,”C”]不可改
letb=a[3]
遍历Array可使用for in
forarray in a{
println(“\(array)”)
}
c.Dictionary
vardic=Dictionary<String,Int>()
vardic=[String:Int]()
dic[“mTitle”]=0//添加数据
vardic=[“title1”:1,”title2”:2]
访问一个dictionary的值将返回Optional
letvalue=dic[“title3”] 返回nil
使用tuple遍历Dictionary
for(key,value) in dic {
println(“\(key)=\(value)”)
}
d.结构体Range 一个起点,一个终点,称之为合理类型,Range是范型
struct Range<T>{
var startIndex:T
var endIndex:T
}
1)在Array中Range中的类型是Int型,因为Array是通过Int索引 Range<Int>
2)String中时String的索引 Range<String.Index>
3)声明
let array=[“a”,”b”,”c”,”d”]
let subArray1=array[2...3] ([“c”,”d”]) 闭区间
let subArray2=array[2..<3] ([“c”]) 左闭右开区间
遍历
for i in 27…104{
println(“i=\(i)”)
}
e.NSObject(swift中所有的类都可以继承NSObject)
Objective-C中所有类的基类,比如UIViewController
f.NSNumber 装数字的类
letn=NSNumber(double:35.5)
将会以自身的值转为int或double
letintversion=n.intValue / n.doubleVaule /n.boolValue
g.NSDate 存储日期,也可以获取当前日期和时间
Calendar,DateFormatter,DateComponents
h.NSData 比特包
传递无类型数据,原始数据
2.数据结构 类,枚举,结构
相同点:a.声明类似 b.可以有自己的属性和方法 c.都可以有自己的函数
不同点:a.Enum本身是不能存储任何值的,可以将值存储在枚举的关联信息中
b.枚举可以有计算型属性
c.结构体和类可以初始化
d.类有继承的性质,类型和转化都属于类的性质
e.枚举和结构体是 值传递,类是 引用传递
3.override 重写父类方法的关键字
final可以将一个方法标为final,表示这个方法不能被重写
4.类和实例都有自己的方法和属性
var d:Double = -10
ifd.isSignMinus {//isSignMinus是否是一个负数
d=Double.abs(d) //取绝对值
}
isSignMinus是实例d的变量或者说是d的属性
abs是Double类的方法(所有对象共享),向该方法中传入需要操作的Double类型的实例
类方法 static func abs(d:Double) -> Double
5.参数名
所有方法所有的参数都有一个内部名和外部名
内部名:在方法中拥有一个本地变量的名字,方法中冒号之前的
外部名:调用者准备使用的,调用方法是在冒号之前的
a.使用外部名
func foo(extenal internal:Int){
let local=internal
}
func bar(){
let result=foo(external: 123)
}
b.不使用外部名 _表示会被忽略,所有方法默认是采用该方式
//func foo(internal:Int)
func foo(_ internal:Int){
let local=internal
}
func bar(){
let result=foo(123)
}
c.强制使用内部名 #
func foo(#internal:Int){
let local=internal
}
func bar(){
let result=foo(internal:123)
}
d.非第一个参数推荐使用内部名和外部名,当然,你可以使用_忽略外表名,但这不是标准的做法
func foo(first:Int,externalSencond second:Double){
let local=second
}
func bar(){
let result=foo(123,externalSencond:5.5)
}
6.Property Observers(属性观察)
var someStoredProperty:Int = 42{
willSet{newValue}//属性设置前被调用
didSet{oldValue}//属性设置后被调用,可以用来对用户界面进行更新
}
override var someStoredProperty{
willSet{newValue}
didSet{oldValue}
}
使用场景:a.在自己的类中需存储属性,当其他方法设置它的值时,获得一个通知
b.当继承了某些类,你并不需要对这些类中的属性做什么修改,但当它们改变时你想知道
7.lazy 只有用到的时候才会被初始化
a.如果使用了很多资源,用lazy是不错的选择
lazy var brain=CalculatorBrain()
b.初始化的时候在后面放一个大括号,也就是通过执行这个闭包来初始化这个属性,但这个闭包直有在property被用到的时候才会执行
lazy var someProperty:Type={
return <the constructed vaule>
}()
c.可以使用一个方法来进行初始化,只有标记为lazy才可以这样用,因为在类初始化之前,类中的方法都是不可以被调用的
lazy var myProperty=self.initializeMyProperty()
8.initialization 初始化
a.无父类的类,默认有一个init()方法
b.如果一个结构体没有初始化,它将默认得到一个将所有属性作为参数的初始化方法,不需要实现
struct MyStruct{
var x: Int=42
var y: String=“moltuae”
init(x:Int,y:String)
}
c.在初始化方法里面可以设置任何属性的值,包括常量和变量
d.在类或结构体中可以调用自己的init方法 self.init(),类中可以调用父类的初始化方法 super.init()
e.在swift中提供两种构造器来初始化, Convenience Init 和 Designated Init(默认)
I.(指定构造器)Designated Init
a.必须在自己的init方法中调用父类的init方法
b.前面父类不能有Convenience
c.在调用父类的init方法前,必须初始化自己的所有属性,必须调用父类的初始化方法,然后才能给父类的属性赋值
II.(便捷构造器)Convenience Init
a.ConvenienceInit只能调用本类的Designated Init,不能调用任何父类的初始化方法
b.它能通过调用其他的Convenience Init间接调用Designated Init ,最后必须调用一个Designated Init
c.必须直接或间接调用Designated Init,然后才能访问其他的值
III.其他构造器,类必须被初始化,才能调用方法和属性
f.继承规则
a.如果类中没有实现任何的Designated Init,那么你将继承父类中的所有Designated Init,否则你将不继承任何一个父类中的Designated Init,也就是要么就不继承一个,要么就继承所有的,对于Convenience Init 也是一样的
b.如果你覆盖了你父类中的所有的Designated Init,重写了所有的这些Designated Init方法,那么你就继承来父类中所有的Convenience Init
c.如果没有实现任何一个初始化方法,你将继承所有的Designated Init和Convenience Init
g.required 初始化(与java中的抽象差不多abstract)
在init方法前面写上required,表示该方法子类必须实现这个方法
h.failable 初始化
有一些初始化允许失败并返回nil (optional)
eg:init?(arg1:Type1,..){
might return nil in heres
}
9.其他
a.UIImage 返回一个图片 optional
let image=UIImage(named:”foo”) 通过名称获取图片
通常写法
if letimage=UIImage(named:”foo”){
//image was successfully created
}else{
//couldn’t create the image
}
b.let button=UIButton.buttonWithType(UIButtonType.System)
join 返回一个由给定的分隔符合并的序列的元素。eg:join(":", ["A","B", "C"]) == "A:B:C"
那么
let separatedArrayElements:String =“,”.join(mArray)返回以逗号分割的字符串
这种写法是表示String有join()属性?
10.AnyObject 主要是用来兼容Objective-C API 和IOS
a.Swift是强类型语言,并有类型推断的特性,所以不推荐使用AnyObject来声明对象
b.AnyObject:指向一个未知对象的指针,也就是一个类的实例
c.使用场景
作为属性,eg:
var destinationViewController:AnyObject
var toolbarItems:[AnyObject]
作为方法参数,eg
func prepareForSegue(segue:UIStoryboardSegue,sender:AnyObject)
作为返回值
class fun buttonWithType(buttonType:UIButtonType) -> AnyObject
d.不能发任何消息,可通过 as 进行强转,eg:
let calcul=destinationViewController as CalculatorViewController
在不确定类型的情况下,可用 as? 返回一个Optional的值,eg:
if let calcul=destinationViewController as? CalculatorViewController{..}
使用 is 判断类型
if destinationViewController is CalculatorViewController{..}
c.AnyObject数组遍历,转换整个数组,不能使用 as? ,数组返回nil是没有意义的
for toolbarItem in toolbarItems as [UIBarButtonItem]{..}
d.lettitle=(button as UIButton).currentTitle
e.类型转换 可以对任何对象进行类型转换,转换的两个对象必须在同一条继承链上,向下转换
11.Array
Array<T>方法
a.+=[T]添加数组
b.first -> T? optional 返回Array的第一个元素
c.last -> T? optional 返回Array的最后一个元素
d.append(T) 添加元素
e.insert(T,atIndex:Int) 插入元素
f.splice(Array<T>,atIndex:Int) 将另一个Array添加到当前Array的指定位置
g.removeAtIndex(Int) 移除指定元素
h.removeRange(Range) 移除指定范围元素
m.replaceRange(Range,[T]) 替换一个范围的元素,替换元素的个数不需要等于被替换元素的个数,也就是可使Array变长
l.sort(isOrderedBefore:(T,T) -> Bool) 排序,eg:a.sort{$0<$1}
n.filter(includeElement:(T) -> Bool) -> [T] 将不需要的元素过滤掉,然后返回过滤后的数组,函数返回值Bool表示是否需要包含该元素
p.map(transform:(T) -> U) -> [U]) 映射,将原来的数组中的每一个元素映射到一个新的数组
e.g.: 将整型数组映射到字符串数组
let stringified:[String] =[1,2,3].map{“\($0)”}
g.reduce(initial:U(初始值), combine: (U,T) -> U) -> U 将整个数组减少为一个值
e.g.: 将整个数组相加 let sum:Int =[1,2,3].reduce(0){ $0+$1}
12.String.Index
a.advance(String.Index,Int)
eg: var s=“Hello”
第一个“l”出现的index
//index=start+distance=0+2
let index=advance(s.startIndex,2) //index is a String.Index to the 3rdglyph,”l”
s.splice("abc",atIndex: index) //s=“Heabcllo”从指定位置插入字符串
let mIndex=advance(s.startIndex,1)
let endIndex=advance(s.startIndex,6)
let subString=s[index..<endIndex] //subString=“abcl”
b.rangeOfString 返回一个Optional Range<String.Index>
e.g.:let num=“56.25”
if let decimalRange = num.rangeOfString(“.”){//找到小数点
//decimalRange 是Range<String.Index>
let wholeNumberPart=num[num.startIndex..<decimalRange.startIndex]//整数
}
c.removeRange 移除指定范围的字符
s.removeRange([s.startIndex..<decimalRange.startIndex])
d.repalaceRange(Range,String) 将某一范围的字符替换成指定字符
e.description -> String
endIndex -> String.Index
hasPrefix(String) -> Bool
hasSuffix(String) -> Bool
toInt() -> Int? 没有To Double()
capitalizedString -> String
lowercaseString -> String
uppercaseString -> String
f.使用指定字符合并字符串数组 join(Array) -> String
e.g:”,”.join([“1”,”2”,”3”])=“1,2,3”
g.以指定字符分割字符串为字符串数组 componentsSparatedByString(String) -> [String]
eg:“1,2,3”. componentsSparatedByString(“,”)=[“1”,”2”,”3”]
13.基本类型转换
let d:Double=37.5
let f:Float=37.5
let x=Int(d)
let xd=Double(x)
let cgf=CGFloat(d) 一种浮点数
let a=Array(“abc”) //a=[“a”,”b”,”c”]
let s=String([“a”,”b”,”c”]) //s=“abc”
14.Assertions断言
Optionals使得我们可以检测值是否存在。在某些情况下,如果某个值不存在或者没有提供特定的满足条件,代码不应该继续往下执行。
在这些情况下,可以使用触发断言来终止执行并提供调试。
断言是在运行时检测条件是否为true,如果为true,就继续往下执行,否则就在这里中断。
assert(() -> Bool,”message”)
e.g.:assert(validation()!=nil,”the validation function returned nil”)
15.其他方法
let count=countElements(aCollection) 集合元素的个数
let sub=dropFirst(aSliceable)
let sub=dropFirst(aSliceable)
let first=first(aCollection) 集合的第一个元素
let last= last(aCollection) 集合的最后一个元素
let prefix= prefix(aSliceable,X:Int)
let suffix=suffix(aSliceable,X:Int)
let reversed:Array=reverse(aCollection)
let backwardsString=String(reverse(s))
16.数据类型的转变
a.NString - String
NArray -Array<AnyObject>
NSDictionary -Dictionary<NSObject,AnyObject>
NSNumber - Int,Float,Double,Bool
b.数据强转
let length=(aString as NSString).length //.length是NSString中的方法,String没有
(anArray as NSArray).componentsJoinedByString(NSString)//componentsJoinedByString是NSArray中的方法
17.NSUserDefaults 小型数据库,它只会存储Property List,当App关闭时,它可以永久保存这些数据,可以自动保存
a.可以像字典一样存储以及导出Property List,其本身就是一个字典
b.方法
setObject(AnyObject, forKey:String) //AnyObject必须是Property List
objectForKey(String) -> AnyObject?
arrayForKey(String) -> Array<AnyObject>?
setDouble(Double,forkey:String)
doubleForKey(String) -> Double //如果找不到则返回0
c.声明
let defaults=NSUserDefaults.standardUserDefaults()
使用:letplist:AnyObject=defaults.objectForKey(String)
defaults.setObject(AnyObject,forKey:String)
e.synchronize() 强制保存数据到磁盘,当App不在前端或处于调试阶段时 是无法自动保存的,这时候就要使用synchronize
e.g.:if !defaults.synchronize(){..} 磁盘不能写入或磁盘已满
18.手动创建View
a.Controller中有个顶层View var view:UIView
addSubview(aView:UIView)
removeFromSuperview()
b.UIView 中有两个初始化方法
init(frame:CGRect) if the UIViewis created in code
init(coder:NSCoder) if the UIViewcomes out of a storyboard
手动创建初始化必须实现这两个方法
func setup(){..}
override init(frame:CGRect){//a designed initializer
super.init(frame:frame)
setup()
}
required init(coder aDecoder:NSCoder){//a required initializer
super.init(coder:aDecoder)
setup()
}
c.awakeFromNib() 表示刚从Storyboard中被加载出来,可以做一些初始化操作
19.坐标系统数据结构
a.坐标的单位是CGFloat,CGFloat在Swift中是结构体
b.CGPont 坐标点,结构体
eg:var point=CGPoint(x:37.0,y:55.2)
point.y -=30
point.x +=20.0
c.CGSize 矩形长和宽,结构体
e.g.:var size=CGSize(width:100.0,height:50.0)
size.width +=42.5
size.height +=75
e.CGRect 由一个CGPoint和CGSize组合的结构体
struct CGRect{
var origin:CGPoint 左上角的点坐标
var size:CGSize
}
let rect = CGRect(origin:aCGPoint,size:ACGSize)
属性和方法
var minX: CGFloat 矩形的左边界
var minY: CGFloat 矩形垂直方向上的中点
intersects(CGRect) -> Bool 两个矩形是否相交
intersect(CGRect) 创建一个更小的矩形,该矩形是两个矩形相交的部分
contains(CGPoint) -> Bool 是否在矩形中
20.控件坐标系统
a.一个点占多少个像素 var contentScaleFactor: CGFloat
b.边界属性 var bounds:CGRect
var center:CGPoint 自身视图矩形的中点,它是相对父视图的坐标系,而不是自身坐标系
var frame:CGRect 用来包含子视图的一个矩形,包含子视图的所有区域包括绘制部分,也是相对父视图的
一般来说,frame size和bounds size 完全相同,但视图View旋转的时候就不一定相同了
21.创建UIView
a.let newView = UIView(frame:myViewFrame)
let newView = UIView() //返回空视图CGRectZero,size和frame都是0
eg:
let labelRect = CGRect(x: 20,y:20,width:100,height:50)
let label=UILabel(frame: labelRect)
label.text = “Hello”
view.addSubview(label) //view是Controller中最顶层的视图
b.不要调用drawRect这个方法!!!
*drawRect是给系统调用的,当视图需要重新绘制时,系统会自动调用drawRect
setNeedsDisplay()
setNeedsDisplayInRect(regionThatNeedsToBeRedrawn: CGRect) 指定某个特定的范围来重绘
c.Core Graphics
22.UIBezierPath 绘制线条,图形
a.绘制三角形
let path=UIBezierPath()创建
path.moveToPoint(CGPoint(x:80,y:50))
path.addLineToPoint(CGPoint(x:140,y:150))
path.addLineToPoint(CGPoint(x:10,y:150))
path.closePath()
UIColor.greenColor().setFill() 内部填充颜色为绿色
UIColor.redColor().setStroke() 描边颜色为红色
path.linewidth=3.0
path.fill()
path.stroke()
b.其他
let roundRect = UIBezierPath(roundedRect: aCGRect,cornerRadius:aCGFloat) 绘制椭圆矩形
let oval = UIBezierPath(ovalInRect: aCGRect) 绘制圆或椭圆
addClip() 剪切任意的Path
funccontainsPoint(CGPoint) -> Bool 碰撞检测
usesEventOddFillRule 是否填充区域
23.UIColor
a.设置透明度
let green=UIColor.greenColor()
let transparentYellow = UIColor.yellowColor().colorWidthAlPhaComponent(0.5)设置颜色透明度 alpha取值0~1 ,0表示完全透明
b.View也可以设置透明度 (不推荐)
var opaque=fasle 设置透明度前必须先设置opaque=false
var alpha:CGFloat,
c.View可以隐藏 var hidden:Bool
24.NSAttributedString 绘制文本
a.let text = NSAttributedString(string:“hello”)
text.drawAtPoint(aCGPoint)
let textSize: CGSize = text.size 获取文本的大小
绘制可变文本:
letmutableText=NSMutableAttributedString(string:“some string”)
b.方法属性
eg:attributes:NSDicitionary
let mAttributes=[NSForegroundColorAttributeName:UIColor.greenColor(),//字体颜色
NSBackgroundColorAttributeName:UIColor.grayColor().colorWithAlphaComponent(0.1),//字体背景色
NSStrokeWidthAttributeName:CGFloat(0.5),//边线宽度
NSStrokeColorAttributeName:UIColor.redColor(),//边线颜色
NSStrikethroughStyleAttributeName:1,//删除线
NSStrikethroughColorAttributeName:UIColor.redColor(),//删除线颜色
NSUnderlineStyleAttributeName:1,//下划线
NSUnderlineColorAttributeName:UIColor.grayColor(),//下划线颜色
NSShadowAttributeName:NSShadow(),//字体阴影
NSFontAttributeName:UIFont.systemFontOfSize(25.0)]//字体
//绘制文本
let text =
NSAttributedString(string: "draw text",attributes:mAttributes)
text.drawAtPoint(CGPoint(x:10,y:250))
25.Font
a.使用推荐的字体
(static for struct,class for class type)
class func preferredFontForTextStyle(UIFontTextStyle) -> UIFont
UIFontTextStyleHeadline
UIFontTextStyleBody
UIFontTextStyleFontnate
eg:UIFont.preferredFontForTextStyle(UIFontTextStyleBody)
b.系统字体
class func systemFontOfSize(pointSize: CGFloat) -> UIFont
class funcboldSystemFontOfSize(pointSize: CGFloat) -> UIFont
eg:UIFont.systemFontOfSize(25.0)
26.显示图片
a.UIImageView
let image: UIImage? = UIImage(named: “foo”) 返回optional
let image: UIImage? = UIImage(contentsOfFile: aString)
let image: UIImage? = UIImage(data: anNSData) //raw jpg,png,tiff等
image.drawAtPoint(aCGPoint) 在左上角显示图片
image.drawInRect(aCGRect) 缩放图片让其适应这个View矩形
image.drawAsPatternInRect(aCGRect) 使图片填满整个区域
b.当View高宽改变时
View 中的属性 var contentMode: UIViewContentMode
让图片重新调整位置
mode: UIViewContentMode.Left/.Right/.Top/.Bottom/.TopRight/.TopLeft/.BottomRight/.BottomLeft/.Center
缩放:.ScaleToFill(默认)/.ScaleAspectFill/.ScaleAspectFit
重新绘制:.Redraw
27.a.在自定义控件中,class前声明@IBDesignable Xcode会自动识别这是一个IBDesignable类,可以让自定义控件的UI显示到视图板上,否则需运行的时候才能出现.
b.自定义控件的变量前配置 @IBInspectable设置自定义属性,可以在外部配置,如在storyboard
28.Extensions
给一个现存的类 结构或枚举添加新方法或属性,不需要修改源代码
a.限制
I.不能通过extension添加一个已存在的方法或属性,也就是不能替换
II.添加的属性不能有存储,只能是运算属性
b.作用:用作软件构架的核心基础
29.Protocols (协议)一种相对简便的表示API的方法,是一种数据类型 (类似于java中的接口Interface)
a.Protocols 本身是没有实现的,没有实现的数据类型,只是声明
b.使用Protocols来声明各种各样的属性和方法
c.使用条件
I.声明protocol
II.类,结构或枚举继承一个protocol必须实现它
III.必须实现protocol中所有的属性和方法
e.eg:
protocol SomeProtocol: InheritedProtocol1, InheritedProtocol2{
//必须定义一个属性是否有get方法或set方法
var someProperty:Int{get set}
fun aMethod(arg1:Double,anotherArgument:String) -> SomeType
// 任何可被改变的函数需要mutating关键字修饰
mutating func changeIt()
init(arg:Type)
}
某个类实现SomeProtocol时,也必须实现InheritedProtocol1,InheritedProtocol2,这两个也是Protocol,相当于SomeProtocol的父类。
f.protocol使用class修饰,说明该protocol只能被类实现,实例已引用被传递
e.g:protocol SomeProtocol: class,InheritedProtocol1, InheritedProtocol2{….. }
g.protocol可以要求实现的类,结构或枚举去实现特定的初始化方法
h.实现
class SomeClass:SuperclassOfSomeClass,SomeProtocol,AnotherProtocol{
required init(..) //初始化必须使用required修饰
}
enum SomeEnum:SomeProtocol,AnotherProtocol{…..}
struct SomeEnum:SomeProtocol,AnotherProtocol{…..}
一旦声明了Protocol就必须实现,否则无法通过编译
还可以使用Extension来扩展属性或方法
extension Something:SomeProtocol{..}
n.使用
protocol Moveable{
mutating fun moveTo(p: CGPoint)
}
class Car:Moveable{
func moveTo(p:CGPoint){…}
func changeOil()
}
struct Shape: Moveable{
mutating fun moveTo(p:CGPoint{…}
fun draw()
}
let prius:Car= Car()
let square: Shape = Shape()
var thingToMove:Moveable=prius
thingToMove.moveTo(..)
thingToMove=square
let thingsToMove:[Moveable]=[prius,square]
func slide(slider:Movearble){
let positionToSlideTo=..
slider.moveTO(positionToSlideTo)
}
slide(prius)
slide(square)
//使用<>,表示x这个参数必须同时实现Slippery和Moveable协议
funcslipAndSlide(x:protocol<Slippery,Moveable>)
eg:
protocol SomeProtocol{
func aMethod(username:String) ->
String
var doubleValue:Double{get
set}
}
class DrawView:
SomeProtocol{
func aMethod(username:
String) -> String {
return “You are \(username)”
}
var length:Double =
0
var doubleValue:Double {
set{
length = newValue}
get{
return length}
}
}
30.Delegation (代理) Protocol中的一种
a.Delegation是Protocol重要的用途
b.用法
1) 创建一个代理协议Delegation Protocol,它包含了许多方法的Protocol,可能包含属性,它描述了这个View要别人做的事情,也就是View代理给其他人的职责
2) 在View中创建一个delegation属性,称作代理或有时叫做数据源,Delegation Protocol就是属性被声明的类型
3) 使用View中的这个delegation属性去处理所有的代理,只要是任何遵循这个Protocol的对象都可以对这个delegation属性设置
4) Controller必须声明实现这个代理协议
5) Controller会将自身作为代理对象Delegation,它会设置这个视图的代理属性为其自身
6) Controller必须实现这个协议Protocol,实现协议规定的required实现的所有方法
eg: 相当于java接口实例对象,如
protocolSomeProtecol{
func method()
}
class A{
var delegate: SomeProtecol
func doSome(){
delegate.method()
}
var testB:B = B()
func init(){
delegate=testB
}
}
class B : SomeProtecol {
impl...
}
31.weak 指针的内存管理,相互引用时,无法释放内存,变量声明为weak,那么这个对象无论指向什么对象,这个被指向的对象都不应该保留在内存中
32.Gestures
一般识别View手势的对象是Controller
l UITabGestureRecognizer 拍击,任意次数的拍击
l UIPinchGestureRecognizer 向里或向外捏,用于缩放
l UIPanGestureRecognizer 摇动或拖拽,拖动
l UISwipeGestureRecognizer 擦碰,以任意方向
l UIRotationGestureRecognizer 旋转,手指朝向反方向移动
l UILongPressGestureRecognizer 长按
a.使用步骤
I. 为视图添加手势识别器addGestureRecognizer
II.当创建手势识别器的时候,必须指定一个对象,如果视图识别了这个手势,就报告给这个对象
b.UIPanGestureRecognizer
@IBOutlet weak var pannableView:UIView{
didSet{
//参数:target 当手势被识别时向target对象发送消息,一般这个是个Controller
// action 表示事件处理的方法名称,当事件触发后会调用这个方法,pan:冒号表示该方法后面有一个参数,如果没有冒号,则得不到这个参数
let recognizer=UIPanGestureRecognizer(target:self,action:”pan:”)
pannableView.addGestureRecognizer(recognizer)
}
}
UIPanGestureRecognizer方法
//手势被识别或重置,开始手指移动了多远距离,可以通过setTranslation重置这个起点
fun translationInView(view:UIView) -> CGPoint
//获取滑动的速度
func velocityInView(view:UIView) -> CGPint
funksetTranslation(translation:CGPoint,inView:UIView)
eg:
@IBOutlet
weak var btnMove:
UIButton!{
didSet{
let recognizer =
UIPanGestureRecognizer(target: self, action:
"handlePanGesture:")
btnMove.addGestureRecognizer(recognizer)
}
}
var netTranslation:CGPoint =
CGPoint(x:0,y:0)
func handlePanGesture(sender:
UIPanGestureRecognizer){
var translation:
CGPoint = sender.translationInView(btnMove)
btnMove.transform =
CGAffineTransformMakeTranslation(netTranslation.x+translation.x,
netTranslation.y+translation.y)
if sender.state ==
UIGestureRecognizerState.Ended{
netTranslation.x+=translation.x
netTranslation.y+=translation.y
}
}
c.UIGestureRecognizer 状态
//拖动手势的状态
var state:UIGestureRecognizerState { get }
.Possible状态,表示是一个拖动手势
.Recognized状态 表示一个非连续的手势,或一个swipe
.Began状态 表示拖动手势,即手势连续
.Changed状态 表示手势的移动,识别器会不断通知事件处理对象
.End状态 表示手势离开屏幕
.Canceled/.Failed状态 表示取消手势,如电话打进来时会中断手势
eg:
func pan(gesture:UIPanGestureRecognizer){
switch gesture.state{
//fall through在switch中说明当前case的函数实现,即为下一个case的函数实现,也就是直接跳到下一个case了
//本例中Changed和End执行了相同的代码
case .Changed:fall through
case .End:
lettranslation=gesture.translationInView(pannableView)
getsture.setTranslation(CGPointZero,inView:pannableView)
default:break
}
}
e.UIPinchGestureRecognizer 缩放,传递的是scale
var scale:CGFloat 缩放手势开始的时候,scale=1
varvelocity:CGFloat { get } 用户缩放的速度,只能获取
eg:
@IBOutlet
weak var mDrawView:
DrawView!{
didSet{
let pinchRecognizer=
UIPinchGestureRecognizer(target:
self, action: "handlePinchGesture:")
mDrawView.addGestureRecognizer(pinchRecognizer)
}
}
var lastScaleFactor:CGFloat =
1;
funchandlePinchGesture(sender:UIPinchGestureRecognizer){
let scale=sender.scale
if scale >
1{//放大
mDrawView.transform =
CGAffineTransformMakeScale(lastScaleFactor+scale-1,lastScaleFactor+scale-1)
}else{//缩小
mDrawView.transform =
CGAffineTransformMakeScale(lastScaleFactor*scale,lastScaleFactor*scale)
}
if sender.state ==
UIGestureRecognizerState.Ended {
if scale >
1 {
lastScaleFactor =
lastScaleFactor+scale-1
}else{
lastScaleFactor =
lastScaleFactor * scale
}
}
}
f.UIRotatonGestureRecognizer
var rotation:CGFloat 旋转弧度
varvelocity:CGFloat { get } 速度,只能获取
eg:
@IBOutlet
weak var mDrawView:
DrawView!{
didSet{
let rotationRecognizer =
UIRotationGestureRecognizer(target:
self, action: "handlerRotationGesture:")
mDrawView.addGestureRecognizer(rotationRecognizer)
}
}
var lastRotation:
CGFloat = 1;//旋转
funchandlerRotationGesture(sender:
UIRotationGestureRecognizer){
var rotation:
CGFloat = sender.rotation
mDrawView.transform =
CGAffineTransformMakeRotation(lastRotation+rotation)
if sender.state ==
UIGestureRecognizerState.Ended{
lastRotation += rotation
}
}
g.UISwipeGestureRecognizer
创建一个swipe手势时,必须设置点击所需的次数或滑动的方向
var derection:UISwipeGestureRecoginzerDirection 滑动的方向
varnumberOfTouchesRequired:Int 点击所需的次数
eg:
@IBOutlet
weak var mDrawView:
DrawView! {
didSet{
let swipeRecognizer =
UISwipeGestureRecognizer(target:self, action:"handleSwipeGesture:")
swipeRecognizer.direction =
UISwipeGestureRecognizerDirection.Left
mDrawView.addGestureRecognizer(swipeRecognizer)
}
}
func handleSwipeGesture(sender:
UISwipeGestureRecognizer){
var direction = sender.direction//滑动方向
switch (direction){
case
UISwipeGestureRecognizerDirection.Left:
println("Left")
case
UISwipeGestureRecognizerDirection.Right:
println("Right")
case
UISwipeGestureRecognizerDirection.Up:
println("Up")
case
UISwipeGestureRecognizerDirection.Down:
println("Down")
default:
break
}
}
h.UITapGestureRecognizer
设置点击和触摸的次数,双击(两次点击),可以通知第一次和第二次点击
var numberOfTapsRequired:Int 点击的次数
varnumberOfTouchesRequired:Int 触摸的次数
eg:
@IBOutlet
weak var mDrawView:
DrawView!{
didSet{
let tapRegognizer =
UITapGestureRecognizer(target:
self, action: "handleTapGesture:")
mDrawView.addGestureRecognizer(tapRegognizer)
}
}
var lastScaleFactor:CGFloat =
1;//放大缩小
var scale:CGFloat =
1.1
//双击屏幕时调用此方法
func handleTapGesture(sender:
UITapGestureRecognizer){
if
scale > 1{//放大
mDrawView.transform =
CGAffineTransformMakeScale(lastScaleFactor+scale-1,lastScaleFactor+scale-1)
}else{//缩小
mDrawView.transform =
CGAffineTransformMakeScale(lastScaleFactor*scale,lastScaleFactor*scale)
}
if sender.state ==
UIGestureRecognizerState.Ended {
if
scale > 1 {
lastScaleFactor =
lastScaleFactor+scale-1
scale =
0.8
}else{
lastScaleFactor =
lastScaleFactor *
scale
scale =
1.2
}
}
}
33.UISplitViewController 并列排放的控件
a.2重MVC,并排放,左边称为Master,右边称为Detail
b.只能放在拥有regular size的设备中
c.Master决定了Detail的内容是什么
d.创建
1)拖出Split View Controller并删除所有系统带出的其他的MVC
2)按住Control键拖动,去链接Master和Detail
e.Split View不能在iPhone上并排显示
f.转化为UINavigationController,Editor->Embed in->NavigationController
g.处于compact时,Split是不能平铺的
h.tableviewCell的标识符对应
j.为Master添加Segua选中tableViewCell按住Control拖动到Detail面板
k.必须先删除数据源再移除Table中的项
mData.removeAtIndex(indexPath.row)
tableView.deleteRowsAtIndexPaths([indexPath], withRowAnimation: .Fade)
34.Size Classes屏幕适配
a.regular width ,regular height(iPaid)
b.compact width ,compact height (iPhone)
35.UINavigationController 就是一个MVC,它的View由其他MVC组成,可以包含任意数量的MVC
a.它把其他都MVC放在屏幕上,与其他类型的Controller不同的是,它共享这个屏幕。类似Card叠加放置。
b.在多重MVC之间共享一个小的屏幕空间,它会将这些MVC堆起来
36.获取子MVCs
a.通过viewConrollers这个属性去获取Card子项,它们是由UIViewController组成的数组
var viewControllers:[UIViewController] {get set}
Tab bar: 有序的数组
Split view: 只有两个元素,Master是下标为[0]的,Detail是下标为[1]的,设值Push/Pop
Navigation controller: root view[0],剩下的就按顺序排列在栈中
b.如何获取ViewController
var tabBarContoller:UITabBarController?{get}
var splitViewController:UISplitViewController?{get}
var navigationController:UInavigationController?{get}
eg:获取一个splitView的Detail
if(letdetailVC:UIViewController==splitViewController?.viewControllers[1]){…}
37.Segues 从一个viewController转换到另一个viewController,类似于Android的监听器 按Control拖动
a.系统定义了四种Segues,也可以自定义Segues
Show Segue 展示正在交互的MVC
Show Detail Segue在SplitView中就是显示Detail,其他情况和Show Segue的效果一样
Modal Segue 完全布满整个屏幕,不推荐
Popover segue 一个小窗口,并不完全布满整个屏幕,点击窗口外的其它地方该窗口会消失,类似于Android的PopWindow
b.触发Segues可调用方法performSegueWidthIdentifier
func performSegueWidthIdentifier(idenifier:String,sender:AnyObject)
前提条件是:定义了identifier
c.prepareForeSegue
func perpareForSegue(segue:UIStoryboardSegue,sender:AnyObject?){//sender触发这个Segue的控件
if let identifier = segue.identifier{
switch identifier{
case “Show Graph”://某个Segue的identifier
if let vc =segue.destinationViewController as? MyController{
vc.property1=…
vc.callMethodToSetItUp(…)
}
default:break;
}
}
}
d.当你准备创建新的MVC时,它的outlet还没被设定时,这会让你的程序崩溃,也可能产生一些意想不到的行为
38.更改ViewController的命名步骤
a.更改类名
b.双击更改文件名
c.Main.storyboard中选择Custom Class的Class为更名后的ViewController
39.storyboard
a.设置是否固定字体大小 Autoshrink
Minimum Font Size自动根据屏幕缩放字体,但有最小字体的限制
Fixed Font Size固定控件大小
b.storyboard中插入View/Navigation View/Scroll View/Split View,选中控件
c.Label换行
选中Label ->Line Breaks
TruncateTail删减尾部,尾部点点
Word Wrap自动换行
d.UILabel适用于三行内的静态文本
d.设置启动View
40.Popover 弹窗窗口
a.并不是一个UIViewController
b.PopoverPrepare
eg:func prepareForSegue(segue:UIStoryboardSegue,send:AnyObject?){
iflet identifier=segue.identifier{
switch identifier{
case “popover segue”:
if let vc=Segue.destinationViewController as? MyController{
if let ppc=vc.popoverPresentationController{
ppc.permittedArrowDirections=
UIPopoverArrowDirection.Any
ppc.delegate=self
}
}
}
}
}
c.Presentation Controller 不能使用segue
1)当Popover弹窗时的相关适配,如显示位置,弹窗大小
默认会以modal方式全屏显示,可以设置为none,表示不需要适配
funcadaptivePresentationStyleForPresentationController(UIPresentationController)->UIModalPresentationStyle
{ returnUIModalPresentationStyle.None }
2)自定义窗口
func presentationController(UIPresentationController,viewControllerForAdaptivePresentationStyle:UIModalPresentationStyle)->UIViewController?
{ //returna UIViewController to use }
3)需实现代理协议 UIViewControllerTransitioningDelegate
eg:
class ViewController:
UIViewController, UIViewControllerTransitioningDelegate {
@IBAction
funcshowDidTouch(sender: UIBarButtonItem) {//按钮点击的Action
//create a controller,绑定 PresentViewController
let controller:UINavigationController! =
self.storyboard?.instantiateViewControllerWithIdentifier("ShowNavigationController")
as? UINavigationController
//"ShowNavigationController" storyboard中定义的controller标识
controller.modalPresentationStyle = .Custom
controller.transitioningDelegate =
self
self.presentViewController(controller, animated:
true, completion: {})
}
//UIViewControllerTransitioningDelegate
实现方法
funcpresentationControllerForPresentedViewController(presented:
UIViewController, presentingViewControllerpresenting:
UIViewController!, sourceViewControllersource:
UIViewController) ->
UIPresentationController? {
return
CustomPresentationController(presentedViewController:presented,presentingViewController:presenting)
}
}
CustomPresentationController是自定义的一个controller,它继承于UIPresentationController
d.设置窗口大小,结合segue使用
var preferredContentSize:CGSize
41.View Controller 生命周期
总结:
初始化,awakeFromNib,segue preparation被初始化,outline设置,viewDidLoad,……..
42.自动化布局AutoLayout
l 使用蓝色当虚线达到想要的效果
l 使用Ctrl+拖动来创建view与view之间的关系
l storyboard右下角 Pin 和Arrange窗口
l 使用Reset to Suggested Contraints调整自适应边距
l Document Outline 解决错误或冲突(点击storyboard左下角展开,红色或黄色的提示)
l Size Inspector (选中view的详情约束,storyboard右上角)
l 点击一个约束并选择它,然后设置属性检查
其他:
a. MasteringAutolayout 需要经验
b. 自动化布局也可使用代码实现
各种设备比较:
*竖屏 Any Width+Regular Height
storyboard自动化布局:
43.预览视图
操作:在双屏的模式下,打开View Controller,点击最左边的蓝色圈Automatic,选择Preview,即可预览,可预览横竖屏视图
a.打开双屏的模式
b.点击最左边的蓝色圈Automatic,选择Preview
c.预览效果
44.icon size
1x:低分辨率设备 2x:高分辨率设备 3x:极高分辨率设备,如iPhone 6 plus
45.杂七杂八
l 约束 NSLayoutContranit
l 等比放缩图片
//添加约束 NSLayoutConstraint约束类型 imageView是图片控件
var aspectRatioContstraint:
NSLayoutConstraint?{
willSet{
if
let existingConstraint = aspectRatioContstraint{//设置前移除约束
view.removeConstraint(existingConstraint)
}
}
didSet{
if
let newConstraint = aspectRatioContstraint{
view.addConstraint(newConstraint)
}
}
}
设置约束
imageView.image = newValue
if
let constrainedView = imageView{
if
let newImage = newValue{//判断newValue不为nil
aspectRatioContstraint =
NSLayoutConstraint(
item: imageView,//item
需要添加约束的控件
attribute: .Width,//被约束的属性
relatedBy: .Equal,//Constants和multipliers的关系
.Equal:width=heigth*等高比
toItem: constrainedView,//相对其他控件,这里是imageview自己的宽高比,所以相对于自己
attribute:.Height,//相对的属性
multiplier: newImage.aspectRatio,//相乘的系数:等高比
constant: 0)//增加的常量
}else{
aspectRatioContstraint =
nil
}
}
l storyboard消除SubView关系
比如当storyboard在ScrollView满屏后再拖入其他控件,storyboard会自动将该控件添加为ScrollView的子控件,这种情况不一定是想要的。如何消除这种SubView关系:
a. 点击storyboard左下角的Document Outline,直接将子控件拖出ScrollView,将控件顺序拖到ScrollView的下方,控件就在ScrollView的上层了
b. 添加约束
选择控件,按Ctrl键拖动到View,即可添加约束
46.Scroll View(滚动条)
1)滚动区域设置 必须设置,否则不会显示
scrollView.contentSize= CGSize(width: 3000, height: 2000)
2)添加子View
login.frame = CGRect(x: 2700, y:50, width:120, height: 180)
scrollView.addSubview(log0)
图片:
letimage=UIImage(named:”xx.jpg”)
letiv=UIImageView(image:image)//iv.frmage.
=image.size
scrollView.addScrollview(iv)
scrollView.contentSize=imageView.bounds.size
3)获取当前滑动的坐标区域
letupperLeftOfVisible: CGPoint = scrollView.contentOffset
4)通过代码滑动到制定区域
funcscrollRectToVisible(CGRect, animated: Bool)// animated:true滑动过去,false 直接跳过去。
如果contentSize修改了,scrollView会闪一下。
5) Zooming
a.放缩的比例
srollView.minmumZoonScale=0.5 //默认大小的一半
scrollView.maxmumZoomScale=2.0//两倍大小
b.代理delegate
当ScrollView在Zooming时,它只zoom in
func viewForZoomingInScrollView(sender: UIScrollView)-> UIView
手势离开屏幕的时候调用的delegate
func scrollViewDidEndZooming(UIScrollView,withView:UIView,atScale: CGFloat)
c.其他
var zoomScale: CGFloat
func setZoomScale(CGFloat, animated: Bool) 设置缩放比例
func zoomToRect(CGRect, animated: Bool)
eg:
6)Closures 闭包方法
样例一:
class Grapher{
var yForX: ((x:Double) -> Double?)?//闭包
}
let grapher = Grapher()
let graphingBrain = CalculatorBrain()
graphingBrain.program = theProgramToGraph
grapher.yForX = { (x:Double) -> Doublein //闭包的实现
graphingBrain.variableValues[“M”] = x
return graphingBrain.evaluate()
}
调用eg: grapher.yForX!(x:1.0)
样例二:
class Foo{
var action: () -> Void = {}
func show(value: Int){ println(“\(value)”)}
func setupMyAction(){
var x: Int = 0
action={//闭包
x=x+1
self.show(x)//闭包内部有个指针指向self
}
}
func doMyAction10Times(){for i in 1..10{action()}}
}
闭包内相互指向,会造成两者永远存在内存中,它们永远不会被释放,造成捕获异常泄漏,解决:不捕获self指针[unowned self] in
action={ [unowned self] in
x=x+1
self.show(x)//闭包内部有个指针指向self
}
yForx = {[unowned
self](x:Double)->
Double in
self.showSomething()
return
1
}
47. Multithreading(多线程)
iOS有多重队列,一个函数队列,基础的闭包,每个队列都有一个自己的线程去运行这些队列
a.执行队列,执行一个函数或一个闭包
letqueue: dispatch_queue_t=….
dispatch_async(queue){……..} 两个参数,一个队列一个闭包,闭包不需要参数也不返回值
b.主队列,是一个串行队列
主队列一次从队列里只拉出一个函数执行,所有的UI活动都必须发生在主队列
主队列不能做任何可能阻塞的任务,比如URL的NSData下载
MVC的代码都在主队列中执行
letmainQ: dispatch_queue_t=dispatch_get_main_queue()//获取主队列
letmainQ: NSOperationQueue=NSOperationQueue.mainQueue()//OC获取主队列
eg:
dispatch_async(notTheMainQueue){//notTheMainQueue中处理阻塞UI的任务
dispatch_async(dispatch_get_main_queue()){//主线程中处理不阻塞UI的任务
}
}
c.其他并行队列
QOS_CLASS_USER_INTERACTIVE优先级最高
QOS_CLASS_USER_INITIATED 优先级高
QOS_CLASS_UTILITY 优先级一般
QOS_CALSS_BACKGROUND 后台任务,优先级低
letqos = Int(x.value)
letqueue=dispatch_get_global_queue(qos,0)
d.建立自己的串行队列
letserial=dispatch_queue_create(“name”,DISPATCH_QUEUE_SERIAL)
e.Example
Example1:
letdelayInSeconds=25.0
letdelay=Int64(delayInseconds*Double(NSEC_PER_MSEC))
letdispatchTime=dispatch_time(DISPATCH_TIME_NOW,delay)
dispatch_after(dispatchTime,dispatch_get_main_queue()){
}
Example2: NSURLSession API
let session = NSURLSession(NSURLSessionConfiguration.defaultSessionConfiguration())
if let url=NSURL(string: http://url”){
let request=NSURLRequest(URL:url)
lettask=session.downloadTaskWithRequest(request){//异步下载一个文件
(localURL,response,error) in collection
}
task.resume()
}
48.进度条 Activity Indicator View
49.文本框 UITextField
1) 显示键盘becomeFirstResponder()
2) 隐藏键盘 resignFirstResponder()
3) 一个重要的代理delegate UITextFieldDelegate
functextFieldShouldReturn(sender: UITextField)
在用户点击键盘上的return键后触发(也可能是search或go,取决于键盘类型),此时需调用resignFirstResponder隐藏键盘
4) UITextField 是一种UIControl,可以设置target/action,但通常我们使用
delegate,因为系统会自动调用resignFirstResponder
5) 编辑已结束,即使没有按return按钮
func textFieldDidEndEditing(sender:UITextField)
6) 键盘弹出时UITextField需移动到键盘之上
方式:把UITextField放在静态到TableView中或UITextField在顶部
7)其他属性
varclearsOnBeginEditing: Bool
varadjustFontSizeToFitWidth: Bool
varplaceholder: String//提示语
varbackground/disabledBackground: UIImage
vardefaultTextAttributes: Dictionary
varinputAccessoryView: UIView//可以在键盘上面添加其他控件
8) UITextView是一个非常强大的编辑对象,多行,多种字体等等
UITextInputTraits协议监听键盘输入
UITextField属性,包括键盘类型,是否自动大写,是否密码形式输入:
varUITextAutocapitalicationType auctocapitalizationType//words,sentences等
varUITextAutocorrectionType autocorrectionType//yes or no
varUIReturnKeyType returnkeyType//Go, search, Google, Done 等
varBOOL secureTextEntry//设置密码形式输入
varUIKeyboardType keyboardType//ASCII,URL,PhonePad等
9)NSNotification 键盘总是在视图之上
当TextFiled在底部,需要调整输入框的位置时,要用到NSNotification
UIKeyboard{will,Did}{Show,Hide}Notifications
注册一个事件 UIKeyboardDidShowNotification
NSNotificationCenter.defaultCenter().addObeserver(self,
selector:”theKeyboardappeared:”,
name:UIKeyboardDidShowNotification
object:view.window)
键盘弹出的时候将会调用自定义方法
functheKeyboardAppeared(notification:NSNotification)
eg:
classUITextFieldViewController:
UIViewController,UITextFieldDelegate,UITextInputTraits {
@IBOutlet
weak var textField:
UITextField!{
didSet{
textField.autocapitalizationType =
UITextAutocapitalizationType.Words
textField.autocorrectionType =
UITextAutocorrectionType.Yes
textField.returnKeyType =
UIReturnKeyType.Done
textField.secureTextEntry =
false
textField.keyboardType =
UIKeyboardType.URL
textField.becomeFirstResponder()
textField.delegate =
self
let view:UIView =
UIView(frame: CGRect(x:
10, y: 20, width:
20, height: 20))
view.backgroundColor =
UIColor.blueColor()
textField.inputAccessoryView = view
}
}
override
func viewDidLoad() {
super.viewDidLoad()
NSNotificationCenter.defaultCenter().addObserver(self, selector:
"theKeyboardappeared:", name:
UIKeyboardWillShowNotification, object: textField.window)
// Do any additional setup after loading the view.
}
functheKeyboardappeared(sender:NSNotification){
//软键盘遮挡处理
}
//点击了return/search/go,表示输入完成
functextFieldShouldReturn(textField:
UITextField) -> Bool {
textField.resignFirstResponder()//收起键盘
return
true
}
//编辑已结束,即使没有按return按钮
functextFieldDidEndEditing(textField:
UITextField) {
textField.resignFirstResponder()//收起键盘
}
}
50. UITableView 展示大量数据
1)本质是一个一维表格,也可以当成列表,它是UIScrollView的子类,在拥有大量数据的时候非常有效率
2)可以把多个TableView嵌套到NavigationController中,建立二位表格,因为无法建立真正的二维表格
3)Table显示方式
plain Style:长列表,用于动态数据
Group Style: 可以把一列的信息管理起来,用于固定数据
4)Table的组成
Header(头部):UIView
Section(组项): ,多个项归类,每个 section 都有一个 header和Foot
Footer(底部): UIView
复杂的Header和Footer可以使用TableViewCell
UITableViewDataSource’s tableView(UITableView, cellForRowAtIndexPath:NSIndexPath)
5)列表样式
Subtitle:UITableViewCellStyle.Subtitle ,子标题
Basic: UITableViewCellStyle.default ,常见不分类列表
Right Detail: UITableViewCellStyle.value1,左边是归纳,右边是详情
Left Detail: UITableViewCellStyle.value2,右边是归纳,左边是详情
6)UITableViewController
缺点:MVC 的全部 view 都必须得是 tableview
优点:storyboard中建立UITableViewController时它会自动将data sourch数据源和delegate连接到TableView上,普通的ViewController需要自己连接。
7)设置cell的类型
static:可以放置任何控件,table会将它们分组,可以给它们设置outlets,静态的
dynamic:一系列相同的控件集合,plain
custom:
8)Detail Disclusure
添加segue时应选择Accessory Action中的show
9)实现data source协议
a.table中section的数量
b.制定section中有几行
c.给它一个UITableViewCell 或它的子类来显示这一行
10)通过它们可以向Table载入数据
a.普通Cell
functableView(tv:UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) ->UITableViewCell{
let data=myInternalDataStructure[indexPath.section][indexPath.row]
let cell=…//创建一个UITableViewCell并加载数据
returncell
}
b.SubTitle Cell
func tableView(tv:UITableView,cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell{
let data=myInternalDataStructure[indexPath.section][indexPath.row]
//自定义UITabeleViewCell
let dequeued:AnyObject=tv.dequeueReusableCellWithIdentifier(“MyCell”,forIndexPath:indexPath)//由于历史的原因,它并没有返回一个UITableCell,而是AnyObject,需要我们强转
letcell=dequeued as UITableViewCell
cell.textLabel?.text=”Title”//较大的文字
cell.detailTextLabel?.text=”Subtitle”//较小的文字
//也可载入图片,有imageView属性
returncell
}
c.自定义Custom Cell
func tableView(tv:UITableView,cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell{
let data=myInternalDataStructure[indexPath.section][indexPath.row]
let dequeued: AnyObject=tv.dequeueReusableCellWithIdentifier(“MyCustomCell”,forIndexPath:indexPath)//由于历史的原因,它并没有返回一个UITableCell,而是AnyObject,需要我们强转
letcell=dequeued as MyTableViewCell
cell.publicAPIofMyTableViewCell=data.theDataTheCellNeedsToDisplayItsCustomLabelsEtc
…
returncell
}
11)UITableViewDataSource
funcnumberOfSectionsInTableView(sender:UITableView) -> Int //必须实现该方法,必须设置每个section有多少行
func tableView(sender:UITableView,numberOfRowsInSection:Int) -> Int
cellForRowAtIndexPath也是必须实现的方法,如果是静态的table就不需要实现,因为在storyboard中已经设置好了
获取标题
func tableView(UITableView, titleFor{Header, Footer}InSection: Int)-> String
也可以实现UITableView的delegate去获取标题
12)TableView Segues
//sender 是UIButton/UITableViewCell
func prepareForSegue(segue:UIStoryboardSegue, sender: AnyObject){
iflet identifier= segue.identifier{
switch identifier{
case “XyzSegue”:
case “AbcSegue”:
let cell=sender as MyTableViewCell//强转
if let indexPath =tableView.indexPathForCell(cell){
letseguedToMVC=segue.destinationViewController as MyVC
seguedToMVC.publicAPI=data[indexPath.section][indexPath.row]
}
default: break
}
}
}
13)UITableViewDelegate
delegate可以监听table内部发生的情况,例如:
当Table中一行被点击时,可以设置segue到其他视图,也可以在didSelectRowAtIndexPath代理方法中获取到,它会提供section和Row
其他方法:will/did willBegin/didEnd
14)UITableView Target/Action 更新Table UI
func tableView(sender: UITableView, didSelectRowAtIndexPathindexPath:NSIndexPath){
}
//点击 detail disclosure响应
functableView(UITableView, accessoryButtonTappedForRowWithIndexPath: NSIndexPath)
15)刷新数据
func reloadData(),它会发送numberOfSectionsInTableView和numberOfRowsInTableView,并且对每一个可见的cell调用cellFortowAtIndexPath,重新载入所有的数据
也可以调用
funcreloadRowsAtIndexPaths(indexPaths: [NSIndexPath], widthRowAnimation:UITableViewRowAnimation)
传递给它一个IndexPath数组,它只会重新载入这些cell
更新数据时行高可能会改变,应代码设置Table的高度为UITableViewAutomaticDimension自适应,如果设置了AutomaticDimension也需要设置estimatedRowHeight,因为table view是scroll view ,estimatedRowHeight可以获取size的大小
通过delegate获取行高
func tableView(UITableView, {estimated} heightForRowAtIndexPath: NSIndexPath) -> CGFloat
16)创建TableView
在storyboard中拖入一个UITableViewController后,将它放入Navigation Controller中,选中该controller,点击Edit->Embed In(放入)->Navigation Controller
因为可能需要点击某条tweet然后展示更多信息
63.Unwind Segues 不会创建视图
1)优点:
a.能直接或间接地回到之前地位置,解开连接
b.如果你有一个MVC并且是通过modal的方式展示的
2)modal
Modal segue:取代整个屏幕
popover就是一种modal,每当popover弹出的时候,除了这个popover其他都无法操作
3)当你在任何MVC中添加了IBAction方法,如果它的参数是UIStoryboardSegue,当使用Ctrl+拖动到退出按钮时,需选择goBack: Segue/Action
64.Alerts和Action Sheets 两种用户请求弹出框
1)区别:
Alerts:直接弹出在屏幕的中央,都是modal的形式,类似于Android的Dialoag
Action Sheets:从屏幕底部滑出,popover,集结了一堆选项的表单,如选择图片/拍照,类似于Android的popupWindow
2)创建Action Sheets 在iPhone(底部弹出层)和iPad(popover)显示效果不同
varalert=UIAlertController(
title:”Redeploy Cassini”,
message:”Issue commands to Cassini’sguidance system.”
preferredStyle:UIAlertContrllerStyle.ActionSheet
)
添加事件监听
alert.addAction(UIAlertAction(
title:”Orbit Staturn”, //标题
style:UIAlertActionStyle.Default, //样式, Default蓝色的字体,.Destructive红色文字
//handler:(action:UIAlertAction) -> Void//闭包,action就是这个UIAlertAction本身
{
(action: UIAlertAction) ->Void in
…..
}
))
显示ViewController
//设置显示的方式为popover
alert.modalPresentationStyle=.Popover
let ppc=alert.popoverPresentationController
ppc?.barButtonItem=redeployBarButtongItem
presentViewController(alert, animated:true,completion:nil)
3)创建Alert 在iPhone和iPad显示效果一样
var alert=UIAlertController(
title:”Login Required”,
message:”Please enter your Cassini guidancesystem.”
preferredStyle: UIAlertContrllerStyle.Alert
)
添加底部按钮
alert.addAction(UIAlertAction(
title:”Cancel”
style:.Cancel)
{(action:UIAlertAction) ->Void in
….
}
)
添加登录事件
alert.addAction(UIAlertAction(
title:”Login”,
style:.Default)
{(action: UIAlertAction) -> Void in
let tf=self.alert.textFields?.first as?UITextField //获取密码
if tf!=nill{self.loginWithPassword(tf.text) }//登录
}
)
//添加输入框
alert.addTextFieldWithConfigurationHandler{(textField) in
textField.placeholer=”Guidance System Password”
}
65.NSTimer 定时器
1)永远在主队列中使用定时器
2)启动定时器
NSTimer .scheduledTimeWithTimeInterval(
_seconds: 2.0,//启动的间隔时间
target:self, //向谁发消息AnyObject
selector:”fire”, //需要定时器执行的方法Selector(String)
userInfor:nil, //参数存储传递AnyObject?
repeats: true//是否只执行一次,true表示每两秒执行一次
)
func fire(timer: NSTimer){
lettheTimersUserInfo = timer.userInfo
}
3)停止计时器
func fire(timer: NSTimer){
if imDoneWithThisTimer{
timer.invalidate()//销毁
}
}
还可以使用tolerance可以优化系统性能(推荐)
myOneMinuteTimer.tolerance=10//每十秒执行一次
tolerance只设置一个秒为单位的时间
使用tolerance使得应用处于一个低耗能状态,否则它就会一直保持唤醒状态,以确保定时器的触发
66.动画Animation
分类
1) 使用view属性的执行动画
a) frame:视图随意移动
class func animateWithDuration(
duration: NSTimeInterval,//动画执行的时间
delay:NSTimeInterval,//等待的时间
options:UIViewanimationOptions,//动画
animations:()-> Void,//block,无参数也无返回值,修改视图属性
completion:((finished: Bool) -> Void)?)//动画执行完毕
eg:2秒后开始执行,开始3秒的淡出视图,完成后将它从父视图中移除
if myView.alpha=1.0{
UIView.animateWithDuration(3.0,
Delay:2.0,
Options:UIViewAnimationOptions.CurveEaseInEaseOut,//动画
Animations:{myView.alpha=0.0},// 修改透明度
completion:{if $0{myView.removeFromSuperView()}})
println(“myView.alpha=\(myView.alpha)”)
}
b) transform:旋转放缩视图
UI View.transitionWithView(
view:UIView,
duration: NSTimeInterval,//动画执行时间
options:UIViewAnimationOptions,//动画
animations:() -> Void,
completion:((finished: Bool) -> Void)?)
eg:
UIView.transitionWithView(view:myPlayingCardView,
duration:0.75,
options:UIViewAnimationOptions.TransitionFlipFromLeft
animations:{cardIsFaceUp=!cardIsFaceUp}
completions:nil )
c) alpha:透明度
UIViewAnimationOptions:
BegainFromCurrentState
AllowUserInteraction
LayoutSubviews
Repeat
Autoreverse
OverrideInheritedDuration
OverrideInheritedCurve
AllowAnimatedContent
CurveEaseInEaseOut
CurverLinear
2) viewController的跳转动画
3) CoreAnimation是在UI View Core Animation动画,底层的一种,非常强大的动画引擎,可操纵大量属性的执行动画
4) DynamicAnimation动态动画,基于物理引擎的动画,它会赋予视图重力和碰撞
67. Dynamic Animation
1)步骤:
a.创建UIDynamicAnimator
varanimator=UIDynamicAnimator(referenceView:UIView)
referenceView必须指定最顶层的UIView
b.添加UIDynamicBehaviors 动态行为,比如重力或碰撞之类的
eg: let gravity=UIGravityBehavitor()
animator.addBehavior(gravity)
eg:collider=UICollisionBehavior()
animator.addBehaviot(collider)
c.添加UIDynamicItems
let item1:UIDynamicItem=…
let item2:UIDYnamicItem=…
grivate.addItem(item1)
collider.addItem(item1)
gravity.addItem(item2)
item1将会受其他重力和碰撞所影响
item2只受重力影响
2)UIDynamicItem protocol协议
protocol UIDynamicItem{
var bounds:CGRect{get}//只读,动画器无法改变一个东西的大小
var center:CGPoint{get set}//对象的位置
var transform:CGAffineTransform{get set}//用于旋转
}
改变一个视图中心或使视图变形
func updateItemUsingCurrentState(item:UIDynamicItem)
3)UIGravityBehavior
varangle: CGFloat//设置一个角度
varmagnitude:CGFloat//比例1:1000,每1000像素点每二次方秒
任意对象在这个方向上就会有一个加速度
4)UIAttachmentBehavior其他行为动画效果
int(item:UIDynamicItem,attachedToAnchor:CGPoint)
init(item:UIDynamicItem,attachedToItem:UIDynamicItem)
init(item:UIDynamicItem,offsetFromCenter:CGPoint,
attachedToItem/Anchor…)
varlength:CGFloat
varanchorPoint:CGPoint
5)UICollisionBehavior碰撞效果
能控制对象间的碰撞,还可以控制对象和一个边界间的碰撞
varcollisionMode:UICollisitionBehaviorMode
设置路径UIBezierPath曲线,它会使用这个UIBezierPath当作它的外部边界
设置边界时必须设置identifier标志符
funcaddBoundaryWithIdentifier(identifier:NSCopying,forPath:UIBezierPath)
也可以设置translatesReferenceBoundsIntoBoundary为true,那么动画对象的所有外边框就会变成一个边界
vartranslatesReferenceBoundsIntoBoundary:Bool
func removeBoundaryWithIdentifier(identifier:NSCopying)
设置代理
varcollisionDelegate:UICollisionBehaviorDelegate
当碰触到一个边界时,将会得到这个代理消息
func collisionBehavior(behavior:UICollistionBehavior,
began/endedContactForItem:UIDynamicItem,
withBoundaryIdentifier:NSCopying)//需转为字符串或其他类型
6)IUSnapBehavior 移动到某个地方,发生类碰撞然后震荡
init(item:UIDynamicItem, snapToPoint:CGPoint)
vardamping:CGFloat 震荡的幅度
7)UIPushBehavior 将某个东西推向特定的角度或是一个力度
push会影响所有被添加到这个动画里的东西
push和重力的区别:push行为可以是一个一次性的效果,也可以是一个持续性或连续性的效果,不会加速,它是恒速
varmode:UIPushBehaviorMode
varpushDirection:CGVector
varangle:CGFloat
varmagnitude:CGFloat
8)UIDynamicItemBehavior 动态对象行为,所有行为的父类,本身是UIDynamicBehavior的子类
varallowsRotation:Bool
varfriction: CGFloat
varelasticity: CGFloat //设置弹性,弹跳的幅度
=1完全失重弹跳不停止
funclinearVelocityForItem(UIDynamicItem) -> CGPoint 线速度
func addLinearVelocity(CGPoint, forItem:UIDynamicItem) 在特定方向添加速度
func angularVelocityForItem(UIDynamicItem) -> CGFloat 角速度
9)UIDynamicBehavior 所有行为的父类
func addChildBehavior(UIDynamicBehavior)//添加子行为
可以拥有复合行为
所有的行为一次只能在一个动画中
10)UIDynamicAnimator
vardynamicAnimator: UIDynamicAnimator{get}
funcwillMoveToAnimator(UIDynamicAnimator)
var delegate:UIDynamicAnimatorDelegate
func dynamicAnimatorDidPause(UIDynamicAnimator)动画暂停
func dynamicAnimatorWillResume(UIDynamicAnimator)动画恢复
l 不要在一个视图放入一个行为中,当一个视图不在动画的参考视图的视图体系中,程序就会崩溃
l 不要使用一个大小为(0,0)的对象动画
eg:避免内存循环
if letpushBehavior=UIPushBehavior(items:[..], mode:.Instantaneous){
pushBehavior.magnitude=..
pushBehavior.angle=..
//调用自身,造成内存循环不释放
pushBehavior.action={ [unowned pushBehavior] in //改进
//改进后,表示pushBehavior在闭包中是不会被强引用的,所以不需要捕获
pushBehavior.dynamicAnimator!.removeBehavior(pushBehavior)
}
animator.addBehavior(pushBehavior)
}
68.Application 生命周期
1)生命周期
a. Not running
b. Inactive
l Not running à Inactive状态切换
AppDelegate会受到通知:
Funcapplication(UIapplication, didFinishLaunchingWithOptions:
[NSObject:AnyObject])
observe:每次应用启动
UIApplicationDidFinishLauncheingNotification
l Active à InActivity
AppDelegate会受到通知:
Func applicationWillResignActive(UIApplication)
observe:每次应用启动
UIApplicationWillResignActiveNotification
l Backgroundà InActivity
AppDelegate会受到通知:
Func applicationWillEnterForeground (UIApplication)
observe:每次应用启动
UIApplicationWillEnterForegroundNotification
c. Active
l InActivity à Active应用暂停Pause
AppDelegate会受到通知:
Func applicationDidBecomeActivite(UIApplication)
observe:
UIApplicationDidBecomeActiviteNotification
d. Background
l InActivityàBackground应用
AppDelegate会受到通知:
FuncapplicationDidEnterBackground(UIApplication)
开启线程,启动后台任务之类的
observe:
UIApplicationDidEnterBackgroundNotification
e. Suspended
机制:在手机锁定后,应用访问的数据需要加密
2) UIApplication
a.获取共享对象let myApp = UIApplication.sharedApplication()
b. 打开URL
func openURL(NSURL)
func canOpenURL(NSURL) -> Bool
c. 本地通知
func(un)registerForRemoteNotifications()
func scheduleLocalNotification(UILocalNotification)
funcregisterUserNotificationSettings(UIUserNotificationSettings)
d. 设置获取间隔,启动后台工作Background Fetch
funcsetMinimumBackgroundFetchInterval(NSTimeInterval) 默认值是Never
如果不设置,那么应用不会被唤醒
一般需设置为UIApplicationBackgroudFetchIntervalMinimum,尽多可能多的唤醒应用程序后台
e. 运行后台任务,后台时主线程会被暂停
func backgroundTaskWithExpirationHandler(handler:() -> Void) -> UIBackgroundTaskIdentifier
完成时需调用 endBackgroundTask(UIBackgroundTaskIdentifier)
默认情况下,如果在期限内,后台任务没有完成,那么iOS将终止应用程序,这时候还可以使用
begainBackgroundTaskWithExpirationHandler再向系统申请点时间
f. 网络进度条显示/隐藏设置
varnetworkActivityIndicatorVisible: Bool
g. 其他属性
varbackgroundTimeRemaining: NSTimeInterval{get}
varpreferredContentSizeCategory: String{get} 字体的大小
varapplicationState: UIApplicationState{get} 应用程序状态,foreground/background/active
3) info.plist 字典,包括很多应用程序的设置
69.NSNotification通知
1)NSNotificationCenter 接收消息
func addObserverForName(String, //接收消息标志名
object:AnyObject?, 发送广播者,=nil的话表示接收所有这类型的的广播
queue:NSOperationQueue?)//队列
{ (notification: NSNotification) -> Void in //队列闭包
可能是当前队列,也可能是主队列
let info: [NSObject:AnyObject]? = nofification.userInfo
userInfo是一个OC里面的字典,key: NSObject, values: AnyObject
}
NSOperationQueue类似一个在分发工作中顶端的面向对象的API
eg:
let center =NSNotificationCenter.defaultCenter()
//UIContentSizeCategoryDidChangeNotification系统自体更改的通知标识
center.addObserverForName(UIContentSizeCategoryDidChangeNotification,
object: UIApplication.sharedApplication(),
queue: NSOperationQueue.mainQueue())
{ notifaction in
letc = notification.userInfo?[UIContentSizeCategoryNewValueKey]
}
70.Core Motion
CMMotionManager
1)检测硬件设备是否可用
var {accelerometer,gyro,magnetometer,deviceMotion}Available:Bool accelerometer加速器
2)开启硬件
func start{Accelerometer, Gyro,magnetometer, DeviceMotion}updates()
3)硬件是否活跃
var{accelerometer,gyro,magnetometer,deviceMotion}Active: Bool
4)停止硬件
funcstop{Accelerometer,Gyro,Magnetometer,DeviceMotion}upates()
5)设备移动获取加速数据
var accelerometerData: CMAccelerometerData
var acceleration: CMAcceleration
struct CMAcceleration{
varx: Double //g(9.8 m/s/s)
vary: Double
varz:Double
}
g:重力加速度
陀螺仪
var gyroData: CMGyroData
var rotationRate:CMRotationRate 转速
struct CMRotationRate{
varx: Double //radius/s
var y: Double //radius/s
var z: Double //radius/s
}
磁力计
var magnetometerData: CMMagnetometerData
var magneticField: CMMagneticField
struct CMMagneticField{
var x: Double
var y: Double
var z: Double
}
6)CMDeviceMotion
var gravity: CMAcceleration 重力
var userAcceleration: CMAcceleration 用户加速度
var rotationRate: CMRotationRate
var attitude: CMAttitude
class CMAttitude: NSObject{
var roll: Double 滚动
var pitch: Double 投掷
var yaw: Double 偏航方向
}
var magneticField:CMCalibratedMagneticField
struct CMCalibratedMagneticField{
varfield: CMMagneticField
varaccuracy: CM
}
7)注册一个block
a.注册一个block接收Accelerometer数据
funcstartAccelerometerUpdatesToQueue(queue: NSOperationQueue!,withHandler:CMAccelerometerHandler)
typealiasCMAccelerationHandler=(CMAccelerometerData!, NSError!) -> Void
队列NSOperationQueue()或NSOperation.mainQueue或当前队列
b.注册一个block接收Gyro数据
func startGyroUpdatesToQueue(queue:NSOperationQueue!, withHandler:CMGyroHandler)
typealias CMGyroHandler=(CMAGyroData!,NSError!) -> Void
c.注册一个block接收DeviceMotion数据
func startDeviceMotionUpdatesToQueue(queue:NSOperationQueue!, withHandler: CMDeviceMotionHandler)
typealias CMDeviceMotionHandler=(CMDeviceMotion!,NSError!) -> Void
8)设置rate 单位是秒
var accelerometerUpdateInterval:NSTimeInterval
var gyroUpdateInterval: NSTimeInterval
var magnetometerUpdateInterval:NSTimeInterval
var deviceMotionUpdateInterval:NSTimeInterval
71.Core Location
1) 代表基本位置的对象CLLocation(CL:Core Location)
a.属性:coordinate坐标, altitude高度, horizontalAccuracy/verticalAccuracy水平或垂直精度,
timestamp时间戳, speed速度, course 方向
b.经纬度
varcoordinate: CLLocationCoordinate2D//平面坐标,不包括高度
struct CLLocationCooordinate2D{
CLLocationDegrees latitude //Double
CLLocationDegrees longitude //Double
}
c.精确度
衡量水平和垂直空间的,精确度并不是一个百分比的数值或类似,是一组预定义好的信息
varhorizontalAccuracy: CLLocationAccuracy
varverticalAccuracy: CLLocationAccuracy
精度越高越耗电,与基站通讯耗电非常低,手机会一直和基站通讯,wifi也比较耗电
kCLLocaitonAccuracyBestForNavigation 最高精度 GPS
kCLLocaitonAccuracyBest 高精度 GPS
kCLLocaitonAccuracyNearestTenMeters 10米附近的精度 GPS+wifi混合
kCLLocaitonAccuracyHundredMeters 百米附近的精度 wifi
kCLLocaitonAccuracyKilometer 一公里的精度 基站
kCLLocaitonAccuracyThreeKilometers 三公里的精度 基站
d.速度:瞬时速度
varspeed: CLLocationSpeed
e.方向: 更倾向于运动轨迹的方向
varcourse: CLLocationDirection
f.时间戳:重要属性,当获取位置可能不是一个实时的操作,可以查看时间戳检查位置信息获取的时间
vartimestamp: NSDate
2)获取CLLocation
CLLocationManager
a.检查是否有相应的硬件,不是所有手机都有点位硬件
b.创建一个实例并且设置代理delegate
c.按需求配置位置信息
d.开始发送代理信息
它会通过一个稳定的流向你发信息
3)监控手机的地理位置方式
a.基于一个特定的精确度,提供持续的更新
b.地理位置有显著改变的时候通知,可以设置区域
4)CLLocaionManager的类方法
授权状态:Authorized, Denied, Restricted
classfunc authorizationStatus() -> CLAuthorizationStatus
class func locationServicesEnabled() ->Bool 位置服务是否开启
class func significantLocationChangeMonitoringAvailable() -> Bool 显著位置变更监控方式是否可用
class func isMonitoringAvailableForClass(AnyClass!) -> Bool
class func isRangingAvailable() -> Bool
5)获取授权
func requestWhenInUseAthorization() 仅在app是当前活动的app时启动
func rquestAlwaysAuthorization() 申请在任何时候都获取位置,即使app在后台
使授权申请生效需在info.plist文件里加入一个键,在这两个键二选一,只要有键就可以不需要有值。
NSLocationWhenInUseageDescription
NSLocationAlwaysUseageDescription
在CLLocationManager里设置desiredAccuracy
vat desiredAccuracy: CLLocationAccuracy 精确度
var distanceFilter: CLLocationDistance 指定距离更新过滤器
func startUpdatingLocation() 开始更新位置信息
func stopUpdatingLocation() 停止更新位置信息
6)代理信息方法
CLLocationManager:发送消息方
func locationManager(CLLocationManager,didUpdateLocations: [CLLocation])
手机处于休眠状态时,GPS也可以纪录位置信息
7)向delegate回调错误信息
func locationManager(CLLocationManager,didFailWithError: NSError)
错误信息
kCLErrorLocationUnknown
kCLErrorDenied
kCLErrorHeadingFailure
8)显著变更
funcstartMonitoringSignificantLocationChanges()
func stopMonitoringSignificantLocationChanges()
app启动时会调用didFinishLaunchingWithOptions方法
func application(UIApplication,didFinishLaunchingWithOptions: [NSObject, AnyObject])
这个字典有一个key: UIApplicationLaunchOptionsLocationKey, 这个说明app启动时由于一个显著位置变更导致的,你需要去查看当前位置然后作出响应。
var location: CLLocation
9)区域
靠近或离开区域时,会调用它的代理方法
func locationManager(CLLocationManager,didEnterRegion: CLRegion)
func locationManager(CLLocationManager,didExitRegion: CLRegion)
func locationManager(CLLocationManager,monitoringDidFailForRegion: CLRegion, withError: NSError)
a. CLCircularRegion圆圈区域
func startMonitoringForRegion(CLRegion)
func stopMonitoringForRegion(CLRegion)
let cr=CLCirularRegion(center:CLLocationCoordinate2D, 圆点
radius: CLLocationDistance, 半径
identifier:String) 标识是必要的
app没有启动或在后台时也能监控区域,需要特定点时间唤醒app,app被唤醒时会提醒已进入预设区域
b. CLBeaconRegion 灯塔区域
你是否靠近另一台iOS设备,需要用到Core Bluetooth框架技术,需要定义identifier并注册该identifier
系统可以检测到与灯塔间的距离
funcstartRangingBeaconsInRegion(CLBeaconRegion)调用该方法后,将会受到didRangeBeacons 这个代理方法发送的信息
10)app在后台时也可以区域监控
可以在CLLocationManager的monitoredRegions属性里找到
var monitoredRegions: NSSet 无序数组
var maximumRegionMonitoringDistance:CLLocationDistance{get}
72.地图 Map
1)MKMapView: UIView的子类
coordinate,title,subtitle
MKAnnotationView的子类展示,地图上的标识图形,默认是个大头针
MKPinAnnotationView 点击弹出框
a.初始化
importMapKit
letmapView = MKMapView()
varannotations: [MKAnnotation]{get} 是一个AnyObject的只读数组,但是不能把非MKAnnotation的对象放入这个数组中
协议protocol
protocol MKAnnotation: NSObject
var coordinate: CLLocationCoordinate2D{get} 坐标
var title: String!{get} 标题,必须设置
var subtitle: String!{get} 子标题
2)MKAnnotation
只读属性
var annotations: [MKAnnotation] {get}
必须添加/移除annotation
func addAnnotation(MKAnnotation)
func addAnnotations([MKAnnotation])
func removeAnnotation(MKAnnotation)
func removeAnnotations([MKAnnotation])
3)MKAnnotationView
a.MKAnnotationView如何加载以及和annotation数组联系起来
viewForAnnotation会提供一个annotation并需要为它创建视图
func mapView(sender: MKMapView,viewForAnnotation: MKannotation) -> MKAnnotationView{
//把一个复用的视图从队列中取出
varview = sender.dequeueReusableAnnotationViewWithIdentifier(IDENT)
ifview==nil{
// reuseIdentifier复用标识符
view = MKPinAnnotationView(annotation: annotation, reuseIdentifier:IDENT)
view.canShowCallout=true/false是不是允许弹出标识视图
}
aView.annotation=annotation
return view
}
b.其他属性
var annotation: MKAnnotation
var image: UIImage 设置地图标识图片,默认是个大头针
左右辅助视图
var leftCalloutAccessoryView: UIView
var rightCalloutAccessoryView: UIView
var enabled: Bool 激活或隐藏
var centerOffset: CGPoint 中心偏移量
var draggable: Bool 大头针是否可拖拽,坐标coordinate属性{get set}
c.特性:如果标识视图的辅助视图是一个UIControl,通常是一个UIButton,当它被点击时,地图视图当代理方法calloutAccessoryControlTapped就会被调用(弹出框的点击事件)
eg:view.rightCalloutAccessoryView=UIButton.buttonWithType(UIButtonTypeDetailDisclusure)
func mapView(MKMapView, annotationView:MKAnnotationView, calloutAccessoryControlTapped: UIControl)
d.点击地图标志图会调用didSelectAnnotationView
mapView(viewForAnnotation:)
letview.leftCalloutAccessoryView=UIImageView()
func mapView(MKMapView,didSelectAnnotationView aView:MKAnnotationView)
{
检查左辅助视图是否是一个图片视图
iflet imageView = aView.leftCalloutAccessoryView as? UIImageView{
imageView.image=..设置图片,然后开启一个线程开始下载
}
}
3)配置地图类型
卫星视图Statellite,混合视图Hybrid,标准的街道视图Standard
var mapType: MKMapType
var showsUserLoaction: Bool true:定位到当前位置
var isUserLocationVisible: Bool 可以设置当前位置是否显示
var userLocation: MKUserLocation 用户位置信息
限制用户操作
var zoomEnabled: Bool 放缩
var scrollEnabled: Bool 滚动
var pitchEnable: Bool 所有手势//3D
var rotateEnable:Bool 旋转
4)MKMapCamera
var camera:MKMapCamera
调整视角的坐标
letcamera=MKMapCamera(lookingAtCenterCoordinate: CLLocationCoordinate2D,
fromEyeCoordinate:CLLocationCoordinate2D,
eyeAltitude:CLLocationDistance)
5)MKCoordinateRegion控制显示地图的部分
var region:MKCoordinateRegion
structMKCoordinateRegion{
var center: CLLocationCoordinate2D
var span: MKCoordinateSpan
}
structMKCoordinateSpan{围绕这个点的经纬度
var latitudeDelta: CLLocationDegrees
var longitudeDelta: CLLocationDegrees
}
func setRegion(MKCoordinateRegion,animated: Bool)
varcenterCoordinate: CLLocationCoordinate2D 设置区域中心的坐标
funcsetCenterCoordinate(CLLocationCoordinate2D, animated: Bool)
funcshowAnnotations([MKAnnotation, animated: Bool])
6)其他方法和函数
MKMapRectContainsPoint,MKMapPointForCoordinate
转换不同的坐标空间 地球坐标,地图坐标
funcmapPointForPoint(CGPoint) -> MKMapPoint
funcmapRectForRect(CGRect) -> MKMapRect
funcpointForMapPoint(MKMapPoint) -> CGPoint
funcrectForMapRect(MKMapRect) -> CGRect
代理方法 didChangeRegionAnimated,它会告诉你现在显示在地图里的区域变化
funcmapView(MKMapView, didChangeRegionAnimated: Bool)
有时候需要调用地图视图的动画链,比如切换地点时,可以先缩小到整个区域,再放大到具体的地点,这样比直接跳过去更好
7)MKLocalSearch地图搜素
varrequest=MKLocalSearchRequest()
request.naturalLanguageQuery=@”Ike’s” 搜素地名
request.region=..
letsearch=MKLocalSearch(request: request)
search.startWithCompletionHandler{(MKLocalSearchResponse,NSError) -> Void in
主线程使用网络查询,返回一个MKPlacemark
}
MKMapItem
funcopenInMapsWithLaunchOptions([NSObject: AnyObject]) -> Bool
8)路线规划
MKRoute MKPolyline
9)Overlays 覆盖层
MKOverlay是MKAnnotation的子类
funcaddOverlay(MKOverlay, level: MKOverlayLevel)
funcremoveOverlay(MKOverlay)
varboundingMapRect: MKMapRect 包含整个覆盖层的矩形
func intersectsMapRect(MKMapRect)-> Bool 矩形是否有交叉
给覆盖层定义自定义视图
funcmapView(MKMapView, rendererForOverlay: MKOverlay) -> MKOverlayRenderer
MKOverlayRenderer在地图上绘制覆盖层
系统渲染
MKCircleRenderer 渲染圆形
MKPolylineRenderer画路线
MKPolygonRederer 渲染多边形
MKTileOverlayRenderer 平铺图片
73.Modal Segue
1)主要是用来处理屏幕上的内容 弹出层
以modal的形态显示选择present modally
funcperformSegue(UIStoryboardSegue, withIdentifier: String) 直接调用segue
展示ViewController
funcpresentViewController(UIViewController, animated: Bool, completion: () ->Void)
modalPresentationStyle:.FullScreen(全屏,默认值), .OverFullScreen(全屏,但并不阻止下面但屏幕互动), .Popover(弹出窗口), .FormSheet
2)如何通过modally segued返回到MVC
funcprepareForSegue(segue: UIStoryboardSegue, sender: AnyObject!){
if segue.identifier == “GOTOMyModalVC” {
let vc = segue.destinationViewControlleras MyModalVC
}
}
大部分modal segue完成工作后就会移除自己
unwind可以移除自己
也可以手动调用dismissViewControllerAnimated
funcdismissViewControllerAnimated(Bool, completion: () -> Void)
3)如何将一个modal view controller展示到屏幕上
varmodalTransitionStyle: UIModalTransitionStyle 出现或离开的动画样式
.CoverVertical 从底部滑出,默认效果
.FlipHorizontal 翻转的效果
.CrossDissolve 淡出
.PartialCurl 从底部的一个角落翻起
1.基本数据类型
a. Optional 就是枚举
AnOptional is just an enum
enum Optional<T>{
case None
case Some(T)
}
b.Array的声明
vara=Array<String>()
vara=[String]()
leta=[“A”,”B”,”C”]不可改
letb=a[3]
遍历Array可使用for in
forarray in a{
println(“\(array)”)
}
c.Dictionary
vardic=Dictionary<String,Int>()
vardic=[String:Int]()
dic[“mTitle”]=0//添加数据
vardic=[“title1”:1,”title2”:2]
访问一个dictionary的值将返回Optional
letvalue=dic[“title3”] 返回nil
使用tuple遍历Dictionary
for(key,value) in dic {
println(“\(key)=\(value)”)
}
d.结构体Range 一个起点,一个终点,称之为合理类型,Range是范型
struct Range<T>{
var startIndex:T
var endIndex:T
}
1)在Array中Range中的类型是Int型,因为Array是通过Int索引 Range<Int>
2)String中时String的索引 Range<String.Index>
3)声明
let array=[“a”,”b”,”c”,”d”]
let subArray1=array[2...3] ([“c”,”d”]) 闭区间
let subArray2=array[2..<3] ([“c”]) 左闭右开区间
遍历
for i in 27…104{
println(“i=\(i)”)
}
e.NSObject(swift中所有的类都可以继承NSObject)
Objective-C中所有类的基类,比如UIViewController
f.NSNumber 装数字的类
letn=NSNumber(double:35.5)
将会以自身的值转为int或double
letintversion=n.intValue / n.doubleVaule /n.boolValue
g.NSDate 存储日期,也可以获取当前日期和时间
Calendar,DateFormatter,DateComponents
h.NSData 比特包
传递无类型数据,原始数据
2.数据结构 类,枚举,结构
相同点:a.声明类似 b.可以有自己的属性和方法 c.都可以有自己的函数
不同点:a.Enum本身是不能存储任何值的,可以将值存储在枚举的关联信息中
b.枚举可以有计算型属性
c.结构体和类可以初始化
d.类有继承的性质,类型和转化都属于类的性质
e.枚举和结构体是 值传递,类是 引用传递
3.override 重写父类方法的关键字
final可以将一个方法标为final,表示这个方法不能被重写
4.类和实例都有自己的方法和属性
var d:Double = -10
ifd.isSignMinus {//isSignMinus是否是一个负数
d=Double.abs(d) //取绝对值
}
isSignMinus是实例d的变量或者说是d的属性
abs是Double类的方法(所有对象共享),向该方法中传入需要操作的Double类型的实例
类方法 static func abs(d:Double) -> Double
5.参数名
所有方法所有的参数都有一个内部名和外部名
内部名:在方法中拥有一个本地变量的名字,方法中冒号之前的
外部名:调用者准备使用的,调用方法是在冒号之前的
a.使用外部名
func foo(extenal internal:Int){
let local=internal
}
func bar(){
let result=foo(external: 123)
}
b.不使用外部名 _表示会被忽略,所有方法默认是采用该方式
//func foo(internal:Int)
func foo(_ internal:Int){
let local=internal
}
func bar(){
let result=foo(123)
}
c.强制使用内部名 #
func foo(#internal:Int){
let local=internal
}
func bar(){
let result=foo(internal:123)
}
d.非第一个参数推荐使用内部名和外部名,当然,你可以使用_忽略外表名,但这不是标准的做法
func foo(first:Int,externalSencond second:Double){
let local=second
}
func bar(){
let result=foo(123,externalSencond:5.5)
}
6.Property Observers(属性观察)
var someStoredProperty:Int = 42{
willSet{newValue}//属性设置前被调用
didSet{oldValue}//属性设置后被调用,可以用来对用户界面进行更新
}
override var someStoredProperty{
willSet{newValue}
didSet{oldValue}
}
使用场景:a.在自己的类中需存储属性,当其他方法设置它的值时,获得一个通知
b.当继承了某些类,你并不需要对这些类中的属性做什么修改,但当它们改变时你想知道
7.lazy 只有用到的时候才会被初始化
a.如果使用了很多资源,用lazy是不错的选择
lazy var brain=CalculatorBrain()
b.初始化的时候在后面放一个大括号,也就是通过执行这个闭包来初始化这个属性,但这个闭包直有在property被用到的时候才会执行
lazy var someProperty:Type={
return <the constructed vaule>
}()
c.可以使用一个方法来进行初始化,只有标记为lazy才可以这样用,因为在类初始化之前,类中的方法都是不可以被调用的
lazy var myProperty=self.initializeMyProperty()
8.initialization 初始化
a.无父类的类,默认有一个init()方法
b.如果一个结构体没有初始化,它将默认得到一个将所有属性作为参数的初始化方法,不需要实现
struct MyStruct{
var x: Int=42
var y: String=“moltuae”
init(x:Int,y:String)
}
c.在初始化方法里面可以设置任何属性的值,包括常量和变量
d.在类或结构体中可以调用自己的init方法 self.init(),类中可以调用父类的初始化方法 super.init()
e.在swift中提供两种构造器来初始化, Convenience Init 和 Designated Init(默认)
I.(指定构造器)Designated Init
a.必须在自己的init方法中调用父类的init方法
b.前面父类不能有Convenience
c.在调用父类的init方法前,必须初始化自己的所有属性,必须调用父类的初始化方法,然后才能给父类的属性赋值
II.(便捷构造器)Convenience Init
a.ConvenienceInit只能调用本类的Designated Init,不能调用任何父类的初始化方法
b.它能通过调用其他的Convenience Init间接调用Designated Init ,最后必须调用一个Designated Init
c.必须直接或间接调用Designated Init,然后才能访问其他的值
III.其他构造器,类必须被初始化,才能调用方法和属性
f.继承规则
a.如果类中没有实现任何的Designated Init,那么你将继承父类中的所有Designated Init,否则你将不继承任何一个父类中的Designated Init,也就是要么就不继承一个,要么就继承所有的,对于Convenience Init 也是一样的
b.如果你覆盖了你父类中的所有的Designated Init,重写了所有的这些Designated Init方法,那么你就继承来父类中所有的Convenience Init
c.如果没有实现任何一个初始化方法,你将继承所有的Designated Init和Convenience Init
g.required 初始化(与java中的抽象差不多abstract)
在init方法前面写上required,表示该方法子类必须实现这个方法
h.failable 初始化
有一些初始化允许失败并返回nil (optional)
eg:init?(arg1:Type1,..){
might return nil in heres
}
9.其他
a.UIImage 返回一个图片 optional
let image=UIImage(named:”foo”) 通过名称获取图片
通常写法
if letimage=UIImage(named:”foo”){
//image was successfully created
}else{
//couldn’t create the image
}
b.let button=UIButton.buttonWithType(UIButtonType.System)
join 返回一个由给定的分隔符合并的序列的元素。eg:join(":", ["A","B", "C"]) == "A:B:C"
那么
let separatedArrayElements:String =“,”.join(mArray)返回以逗号分割的字符串
这种写法是表示String有join()属性?
10.AnyObject 主要是用来兼容Objective-C API 和IOS
a.Swift是强类型语言,并有类型推断的特性,所以不推荐使用AnyObject来声明对象
b.AnyObject:指向一个未知对象的指针,也就是一个类的实例
c.使用场景
作为属性,eg:
var destinationViewController:AnyObject
var toolbarItems:[AnyObject]
作为方法参数,eg
func prepareForSegue(segue:UIStoryboardSegue,sender:AnyObject)
作为返回值
class fun buttonWithType(buttonType:UIButtonType) -> AnyObject
d.不能发任何消息,可通过 as 进行强转,eg:
let calcul=destinationViewController as CalculatorViewController
在不确定类型的情况下,可用 as? 返回一个Optional的值,eg:
if let calcul=destinationViewController as? CalculatorViewController{..}
使用 is 判断类型
if destinationViewController is CalculatorViewController{..}
c.AnyObject数组遍历,转换整个数组,不能使用 as? ,数组返回nil是没有意义的
for toolbarItem in toolbarItems as [UIBarButtonItem]{..}
d.lettitle=(button as UIButton).currentTitle
e.类型转换 可以对任何对象进行类型转换,转换的两个对象必须在同一条继承链上,向下转换
11.Array
Array<T>方法
a.+=[T]添加数组
b.first -> T? optional 返回Array的第一个元素
c.last -> T? optional 返回Array的最后一个元素
d.append(T) 添加元素
e.insert(T,atIndex:Int) 插入元素
f.splice(Array<T>,atIndex:Int) 将另一个Array添加到当前Array的指定位置
g.removeAtIndex(Int) 移除指定元素
h.removeRange(Range) 移除指定范围元素
m.replaceRange(Range,[T]) 替换一个范围的元素,替换元素的个数不需要等于被替换元素的个数,也就是可使Array变长
l.sort(isOrderedBefore:(T,T) -> Bool) 排序,eg:a.sort{$0<$1}
n.filter(includeElement:(T) -> Bool) -> [T] 将不需要的元素过滤掉,然后返回过滤后的数组,函数返回值Bool表示是否需要包含该元素
p.map(transform:(T) -> U) -> [U]) 映射,将原来的数组中的每一个元素映射到一个新的数组
e.g.: 将整型数组映射到字符串数组
let stringified:[String] =[1,2,3].map{“\($0)”}
g.reduce(initial:U(初始值), combine: (U,T) -> U) -> U 将整个数组减少为一个值
e.g.: 将整个数组相加 let sum:Int =[1,2,3].reduce(0){ $0+$1}
12.String.Index
a.advance(String.Index,Int)
eg: var s=“Hello”
第一个“l”出现的index
//index=start+distance=0+2
let index=advance(s.startIndex,2) //index is a String.Index to the 3rdglyph,”l”
s.splice("abc",atIndex: index) //s=“Heabcllo”从指定位置插入字符串
let mIndex=advance(s.startIndex,1)
let endIndex=advance(s.startIndex,6)
let subString=s[index..<endIndex] //subString=“abcl”
b.rangeOfString 返回一个Optional Range<String.Index>
e.g.:let num=“56.25”
if let decimalRange = num.rangeOfString(“.”){//找到小数点
//decimalRange 是Range<String.Index>
let wholeNumberPart=num[num.startIndex..<decimalRange.startIndex]//整数
}
c.removeRange 移除指定范围的字符
s.removeRange([s.startIndex..<decimalRange.startIndex])
d.repalaceRange(Range,String) 将某一范围的字符替换成指定字符
e.description -> String
endIndex -> String.Index
hasPrefix(String) -> Bool
hasSuffix(String) -> Bool
toInt() -> Int? 没有To Double()
capitalizedString -> String
lowercaseString -> String
uppercaseString -> String
f.使用指定字符合并字符串数组 join(Array) -> String
e.g:”,”.join([“1”,”2”,”3”])=“1,2,3”
g.以指定字符分割字符串为字符串数组 componentsSparatedByString(String) -> [String]
eg:“1,2,3”. componentsSparatedByString(“,”)=[“1”,”2”,”3”]
13.基本类型转换
let d:Double=37.5
let f:Float=37.5
let x=Int(d)
let xd=Double(x)
let cgf=CGFloat(d) 一种浮点数
let a=Array(“abc”) //a=[“a”,”b”,”c”]
let s=String([“a”,”b”,”c”]) //s=“abc”
14.Assertions断言
Optionals使得我们可以检测值是否存在。在某些情况下,如果某个值不存在或者没有提供特定的满足条件,代码不应该继续往下执行。
在这些情况下,可以使用触发断言来终止执行并提供调试。
断言是在运行时检测条件是否为true,如果为true,就继续往下执行,否则就在这里中断。
assert(() -> Bool,”message”)
e.g.:assert(validation()!=nil,”the validation function returned nil”)
15.其他方法
let count=countElements(aCollection) 集合元素的个数
let sub=dropFirst(aSliceable)
let sub=dropFirst(aSliceable)
let first=first(aCollection) 集合的第一个元素
let last= last(aCollection) 集合的最后一个元素
let prefix= prefix(aSliceable,X:Int)
let suffix=suffix(aSliceable,X:Int)
let reversed:Array=reverse(aCollection)
let backwardsString=String(reverse(s))
16.数据类型的转变
a.NString - String
NArray -Array<AnyObject>
NSDictionary -Dictionary<NSObject,AnyObject>
NSNumber - Int,Float,Double,Bool
b.数据强转
let length=(aString as NSString).length //.length是NSString中的方法,String没有
(anArray as NSArray).componentsJoinedByString(NSString)//componentsJoinedByString是NSArray中的方法
17.NSUserDefaults 小型数据库,它只会存储Property List,当App关闭时,它可以永久保存这些数据,可以自动保存
a.可以像字典一样存储以及导出Property List,其本身就是一个字典
b.方法
setObject(AnyObject, forKey:String) //AnyObject必须是Property List
objectForKey(String) -> AnyObject?
arrayForKey(String) -> Array<AnyObject>?
setDouble(Double,forkey:String)
doubleForKey(String) -> Double //如果找不到则返回0
c.声明
let defaults=NSUserDefaults.standardUserDefaults()
使用:letplist:AnyObject=defaults.objectForKey(String)
defaults.setObject(AnyObject,forKey:String)
e.synchronize() 强制保存数据到磁盘,当App不在前端或处于调试阶段时 是无法自动保存的,这时候就要使用synchronize
e.g.:if !defaults.synchronize(){..} 磁盘不能写入或磁盘已满
18.手动创建View
a.Controller中有个顶层View var view:UIView
addSubview(aView:UIView)
removeFromSuperview()
b.UIView 中有两个初始化方法
init(frame:CGRect) if the UIViewis created in code
init(coder:NSCoder) if the UIViewcomes out of a storyboard
手动创建初始化必须实现这两个方法
func setup(){..}
override init(frame:CGRect){//a designed initializer
super.init(frame:frame)
setup()
}
required init(coder aDecoder:NSCoder){//a required initializer
super.init(coder:aDecoder)
setup()
}
c.awakeFromNib() 表示刚从Storyboard中被加载出来,可以做一些初始化操作
19.坐标系统数据结构
a.坐标的单位是CGFloat,CGFloat在Swift中是结构体
b.CGPont 坐标点,结构体
eg:var point=CGPoint(x:37.0,y:55.2)
point.y -=30
point.x +=20.0
c.CGSize 矩形长和宽,结构体
e.g.:var size=CGSize(width:100.0,height:50.0)
size.width +=42.5
size.height +=75
e.CGRect 由一个CGPoint和CGSize组合的结构体
struct CGRect{
var origin:CGPoint 左上角的点坐标
var size:CGSize
}
let rect = CGRect(origin:aCGPoint,size:ACGSize)
属性和方法
var minX: CGFloat 矩形的左边界
var minY: CGFloat 矩形垂直方向上的中点
intersects(CGRect) -> Bool 两个矩形是否相交
intersect(CGRect) 创建一个更小的矩形,该矩形是两个矩形相交的部分
contains(CGPoint) -> Bool 是否在矩形中
20.控件坐标系统
a.一个点占多少个像素 var contentScaleFactor: CGFloat
b.边界属性 var bounds:CGRect
var center:CGPoint 自身视图矩形的中点,它是相对父视图的坐标系,而不是自身坐标系
var frame:CGRect 用来包含子视图的一个矩形,包含子视图的所有区域包括绘制部分,也是相对父视图的
一般来说,frame size和bounds size 完全相同,但视图View旋转的时候就不一定相同了
21.创建UIView
a.let newView = UIView(frame:myViewFrame)
let newView = UIView() //返回空视图CGRectZero,size和frame都是0
eg:
let labelRect = CGRect(x: 20,y:20,width:100,height:50)
let label=UILabel(frame: labelRect)
label.text = “Hello”
view.addSubview(label) //view是Controller中最顶层的视图
b.不要调用drawRect这个方法!!!
*drawRect是给系统调用的,当视图需要重新绘制时,系统会自动调用drawRect
setNeedsDisplay()
setNeedsDisplayInRect(regionThatNeedsToBeRedrawn: CGRect) 指定某个特定的范围来重绘
c.Core Graphics
22.UIBezierPath 绘制线条,图形
a.绘制三角形
let path=UIBezierPath()创建
path.moveToPoint(CGPoint(x:80,y:50))
path.addLineToPoint(CGPoint(x:140,y:150))
path.addLineToPoint(CGPoint(x:10,y:150))
path.closePath()
UIColor.greenColor().setFill() 内部填充颜色为绿色
UIColor.redColor().setStroke() 描边颜色为红色
path.linewidth=3.0
path.fill()
path.stroke()
b.其他
let roundRect = UIBezierPath(roundedRect: aCGRect,cornerRadius:aCGFloat) 绘制椭圆矩形
let oval = UIBezierPath(ovalInRect: aCGRect) 绘制圆或椭圆
addClip() 剪切任意的Path
funccontainsPoint(CGPoint) -> Bool 碰撞检测
usesEventOddFillRule 是否填充区域
23.UIColor
a.设置透明度
let green=UIColor.greenColor()
let transparentYellow = UIColor.yellowColor().colorWidthAlPhaComponent(0.5)设置颜色透明度 alpha取值0~1 ,0表示完全透明
b.View也可以设置透明度 (不推荐)
var opaque=fasle 设置透明度前必须先设置opaque=false
var alpha:CGFloat,
c.View可以隐藏 var hidden:Bool
24.NSAttributedString 绘制文本
a.let text = NSAttributedString(string:“hello”)
text.drawAtPoint(aCGPoint)
let textSize: CGSize = text.size 获取文本的大小
绘制可变文本:
letmutableText=NSMutableAttributedString(string:“some string”)
b.方法属性
eg:attributes:NSDicitionary
let mAttributes=[NSForegroundColorAttributeName:UIColor.greenColor(),//字体颜色
NSBackgroundColorAttributeName:UIColor.grayColor().colorWithAlphaComponent(0.1),//字体背景色
NSStrokeWidthAttributeName:CGFloat(0.5),//边线宽度
NSStrokeColorAttributeName:UIColor.redColor(),//边线颜色
NSStrikethroughStyleAttributeName:1,//删除线
NSStrikethroughColorAttributeName:UIColor.redColor(),//删除线颜色
NSUnderlineStyleAttributeName:1,//下划线
NSUnderlineColorAttributeName:UIColor.grayColor(),//下划线颜色
NSShadowAttributeName:NSShadow(),//字体阴影
NSFontAttributeName:UIFont.systemFontOfSize(25.0)]//字体
//绘制文本
let text =
NSAttributedString(string: "draw text",attributes:mAttributes)
text.drawAtPoint(CGPoint(x:10,y:250))
25.Font
a.使用推荐的字体
(static for struct,class for class type)
class func preferredFontForTextStyle(UIFontTextStyle) -> UIFont
UIFontTextStyleHeadline
UIFontTextStyleBody
UIFontTextStyleFontnate
eg:UIFont.preferredFontForTextStyle(UIFontTextStyleBody)
b.系统字体
class func systemFontOfSize(pointSize: CGFloat) -> UIFont
class funcboldSystemFontOfSize(pointSize: CGFloat) -> UIFont
eg:UIFont.systemFontOfSize(25.0)
26.显示图片
a.UIImageView
let image: UIImage? = UIImage(named: “foo”) 返回optional
let image: UIImage? = UIImage(contentsOfFile: aString)
let image: UIImage? = UIImage(data: anNSData) //raw jpg,png,tiff等
image.drawAtPoint(aCGPoint) 在左上角显示图片
image.drawInRect(aCGRect) 缩放图片让其适应这个View矩形
image.drawAsPatternInRect(aCGRect) 使图片填满整个区域
b.当View高宽改变时
View 中的属性 var contentMode: UIViewContentMode
让图片重新调整位置
mode: UIViewContentMode.Left/.Right/.Top/.Bottom/.TopRight/.TopLeft/.BottomRight/.BottomLeft/.Center
缩放:.ScaleToFill(默认)/.ScaleAspectFill/.ScaleAspectFit
重新绘制:.Redraw
27.a.在自定义控件中,class前声明@IBDesignable Xcode会自动识别这是一个IBDesignable类,可以让自定义控件的UI显示到视图板上,否则需运行的时候才能出现.
b.自定义控件的变量前配置 @IBInspectable设置自定义属性,可以在外部配置,如在storyboard
28.Extensions
给一个现存的类 结构或枚举添加新方法或属性,不需要修改源代码
a.限制
I.不能通过extension添加一个已存在的方法或属性,也就是不能替换
II.添加的属性不能有存储,只能是运算属性
b.作用:用作软件构架的核心基础
29.Protocols (协议)一种相对简便的表示API的方法,是一种数据类型 (类似于java中的接口Interface)
a.Protocols 本身是没有实现的,没有实现的数据类型,只是声明
b.使用Protocols来声明各种各样的属性和方法
c.使用条件
I.声明protocol
II.类,结构或枚举继承一个protocol必须实现它
III.必须实现protocol中所有的属性和方法
e.eg:
protocol SomeProtocol: InheritedProtocol1, InheritedProtocol2{
//必须定义一个属性是否有get方法或set方法
var someProperty:Int{get set}
fun aMethod(arg1:Double,anotherArgument:String) -> SomeType
// 任何可被改变的函数需要mutating关键字修饰
mutating func changeIt()
init(arg:Type)
}
某个类实现SomeProtocol时,也必须实现InheritedProtocol1,InheritedProtocol2,这两个也是Protocol,相当于SomeProtocol的父类。
f.protocol使用class修饰,说明该protocol只能被类实现,实例已引用被传递
e.g:protocol SomeProtocol: class,InheritedProtocol1, InheritedProtocol2{….. }
g.protocol可以要求实现的类,结构或枚举去实现特定的初始化方法
h.实现
class SomeClass:SuperclassOfSomeClass,SomeProtocol,AnotherProtocol{
required init(..) //初始化必须使用required修饰
}
enum SomeEnum:SomeProtocol,AnotherProtocol{…..}
struct SomeEnum:SomeProtocol,AnotherProtocol{…..}
一旦声明了Protocol就必须实现,否则无法通过编译
还可以使用Extension来扩展属性或方法
extension Something:SomeProtocol{..}
n.使用
protocol Moveable{
mutating fun moveTo(p: CGPoint)
}
class Car:Moveable{
func moveTo(p:CGPoint){…}
func changeOil()
}
struct Shape: Moveable{
mutating fun moveTo(p:CGPoint{…}
fun draw()
}
let prius:Car= Car()
let square: Shape = Shape()
var thingToMove:Moveable=prius
thingToMove.moveTo(..)
thingToMove=square
let thingsToMove:[Moveable]=[prius,square]
func slide(slider:Movearble){
let positionToSlideTo=..
slider.moveTO(positionToSlideTo)
}
slide(prius)
slide(square)
//使用<>,表示x这个参数必须同时实现Slippery和Moveable协议
funcslipAndSlide(x:protocol<Slippery,Moveable>)
eg:
protocol SomeProtocol{
func aMethod(username:String) ->
String
var doubleValue:Double{get
set}
}
class DrawView:
SomeProtocol{
func aMethod(username:
String) -> String {
return “You are \(username)”
}
var length:Double =
0
var doubleValue:Double {
set{
length = newValue}
get{
return length}
}
}
30.Delegation (代理) Protocol中的一种
a.Delegation是Protocol重要的用途
b.用法
1) 创建一个代理协议Delegation Protocol,它包含了许多方法的Protocol,可能包含属性,它描述了这个View要别人做的事情,也就是View代理给其他人的职责
2) 在View中创建一个delegation属性,称作代理或有时叫做数据源,Delegation Protocol就是属性被声明的类型
3) 使用View中的这个delegation属性去处理所有的代理,只要是任何遵循这个Protocol的对象都可以对这个delegation属性设置
4) Controller必须声明实现这个代理协议
5) Controller会将自身作为代理对象Delegation,它会设置这个视图的代理属性为其自身
6) Controller必须实现这个协议Protocol,实现协议规定的required实现的所有方法
eg: 相当于java接口实例对象,如
protocolSomeProtecol{
func method()
}
class A{
var delegate: SomeProtecol
func doSome(){
delegate.method()
}
var testB:B = B()
func init(){
delegate=testB
}
}
class B : SomeProtecol {
impl...
}
31.weak 指针的内存管理,相互引用时,无法释放内存,变量声明为weak,那么这个对象无论指向什么对象,这个被指向的对象都不应该保留在内存中
32.Gestures
一般识别View手势的对象是Controller
l UITabGestureRecognizer 拍击,任意次数的拍击
l UIPinchGestureRecognizer 向里或向外捏,用于缩放
l UIPanGestureRecognizer 摇动或拖拽,拖动
l UISwipeGestureRecognizer 擦碰,以任意方向
l UIRotationGestureRecognizer 旋转,手指朝向反方向移动
l UILongPressGestureRecognizer 长按
a.使用步骤
I. 为视图添加手势识别器addGestureRecognizer
II.当创建手势识别器的时候,必须指定一个对象,如果视图识别了这个手势,就报告给这个对象
b.UIPanGestureRecognizer
@IBOutlet weak var pannableView:UIView{
didSet{
//参数:target 当手势被识别时向target对象发送消息,一般这个是个Controller
// action 表示事件处理的方法名称,当事件触发后会调用这个方法,pan:冒号表示该方法后面有一个参数,如果没有冒号,则得不到这个参数
let recognizer=UIPanGestureRecognizer(target:self,action:”pan:”)
pannableView.addGestureRecognizer(recognizer)
}
}
UIPanGestureRecognizer方法
//手势被识别或重置,开始手指移动了多远距离,可以通过setTranslation重置这个起点
fun translationInView(view:UIView) -> CGPoint
//获取滑动的速度
func velocityInView(view:UIView) -> CGPint
funksetTranslation(translation:CGPoint,inView:UIView)
eg:
@IBOutlet
weak var btnMove:
UIButton!{
didSet{
let recognizer =
UIPanGestureRecognizer(target: self, action:
"handlePanGesture:")
btnMove.addGestureRecognizer(recognizer)
}
}
var netTranslation:CGPoint =
CGPoint(x:0,y:0)
func handlePanGesture(sender:
UIPanGestureRecognizer){
var translation:
CGPoint = sender.translationInView(btnMove)
btnMove.transform =
CGAffineTransformMakeTranslation(netTranslation.x+translation.x,
netTranslation.y+translation.y)
if sender.state ==
UIGestureRecognizerState.Ended{
netTranslation.x+=translation.x
netTranslation.y+=translation.y
}
}
c.UIGestureRecognizer 状态
//拖动手势的状态
var state:UIGestureRecognizerState { get }
.Possible状态,表示是一个拖动手势
.Recognized状态 表示一个非连续的手势,或一个swipe
.Began状态 表示拖动手势,即手势连续
.Changed状态 表示手势的移动,识别器会不断通知事件处理对象
.End状态 表示手势离开屏幕
.Canceled/.Failed状态 表示取消手势,如电话打进来时会中断手势
eg:
func pan(gesture:UIPanGestureRecognizer){
switch gesture.state{
//fall through在switch中说明当前case的函数实现,即为下一个case的函数实现,也就是直接跳到下一个case了
//本例中Changed和End执行了相同的代码
case .Changed:fall through
case .End:
lettranslation=gesture.translationInView(pannableView)
getsture.setTranslation(CGPointZero,inView:pannableView)
default:break
}
}
e.UIPinchGestureRecognizer 缩放,传递的是scale
var scale:CGFloat 缩放手势开始的时候,scale=1
varvelocity:CGFloat { get } 用户缩放的速度,只能获取
eg:
@IBOutlet
weak var mDrawView:
DrawView!{
didSet{
let pinchRecognizer=
UIPinchGestureRecognizer(target:
self, action: "handlePinchGesture:")
mDrawView.addGestureRecognizer(pinchRecognizer)
}
}
var lastScaleFactor:CGFloat =
1;
funchandlePinchGesture(sender:UIPinchGestureRecognizer){
let scale=sender.scale
if scale >
1{//放大
mDrawView.transform =
CGAffineTransformMakeScale(lastScaleFactor+scale-1,lastScaleFactor+scale-1)
}else{//缩小
mDrawView.transform =
CGAffineTransformMakeScale(lastScaleFactor*scale,lastScaleFactor*scale)
}
if sender.state ==
UIGestureRecognizerState.Ended {
if scale >
1 {
lastScaleFactor =
lastScaleFactor+scale-1
}else{
lastScaleFactor =
lastScaleFactor * scale
}
}
}
f.UIRotatonGestureRecognizer
var rotation:CGFloat 旋转弧度
varvelocity:CGFloat { get } 速度,只能获取
eg:
@IBOutlet
weak var mDrawView:
DrawView!{
didSet{
let rotationRecognizer =
UIRotationGestureRecognizer(target:
self, action: "handlerRotationGesture:")
mDrawView.addGestureRecognizer(rotationRecognizer)
}
}
var lastRotation:
CGFloat = 1;//旋转
funchandlerRotationGesture(sender:
UIRotationGestureRecognizer){
var rotation:
CGFloat = sender.rotation
mDrawView.transform =
CGAffineTransformMakeRotation(lastRotation+rotation)
if sender.state ==
UIGestureRecognizerState.Ended{
lastRotation += rotation
}
}
g.UISwipeGestureRecognizer
创建一个swipe手势时,必须设置点击所需的次数或滑动的方向
var derection:UISwipeGestureRecoginzerDirection 滑动的方向
varnumberOfTouchesRequired:Int 点击所需的次数
eg:
@IBOutlet
weak var mDrawView:
DrawView! {
didSet{
let swipeRecognizer =
UISwipeGestureRecognizer(target:self, action:"handleSwipeGesture:")
swipeRecognizer.direction =
UISwipeGestureRecognizerDirection.Left
mDrawView.addGestureRecognizer(swipeRecognizer)
}
}
func handleSwipeGesture(sender:
UISwipeGestureRecognizer){
var direction = sender.direction//滑动方向
switch (direction){
case
UISwipeGestureRecognizerDirection.Left:
println("Left")
case
UISwipeGestureRecognizerDirection.Right:
println("Right")
case
UISwipeGestureRecognizerDirection.Up:
println("Up")
case
UISwipeGestureRecognizerDirection.Down:
println("Down")
default:
break
}
}
h.UITapGestureRecognizer
设置点击和触摸的次数,双击(两次点击),可以通知第一次和第二次点击
var numberOfTapsRequired:Int 点击的次数
varnumberOfTouchesRequired:Int 触摸的次数
eg:
@IBOutlet
weak var mDrawView:
DrawView!{
didSet{
let tapRegognizer =
UITapGestureRecognizer(target:
self, action: "handleTapGesture:")
mDrawView.addGestureRecognizer(tapRegognizer)
}
}
var lastScaleFactor:CGFloat =
1;//放大缩小
var scale:CGFloat =
1.1
//双击屏幕时调用此方法
func handleTapGesture(sender:
UITapGestureRecognizer){
if
scale > 1{//放大
mDrawView.transform =
CGAffineTransformMakeScale(lastScaleFactor+scale-1,lastScaleFactor+scale-1)
}else{//缩小
mDrawView.transform =
CGAffineTransformMakeScale(lastScaleFactor*scale,lastScaleFactor*scale)
}
if sender.state ==
UIGestureRecognizerState.Ended {
if
scale > 1 {
lastScaleFactor =
lastScaleFactor+scale-1
scale =
0.8
}else{
lastScaleFactor =
lastScaleFactor *
scale
scale =
1.2
}
}
}
33.UISplitViewController 并列排放的控件
a.2重MVC,并排放,左边称为Master,右边称为Detail
b.只能放在拥有regular size的设备中
c.Master决定了Detail的内容是什么
d.创建
1)拖出Split View Controller并删除所有系统带出的其他的MVC
2)按住Control键拖动,去链接Master和Detail
e.Split View不能在iPhone上并排显示
f.转化为UINavigationController,Editor->Embed in->NavigationController
g.处于compact时,Split是不能平铺的
h.tableviewCell的标识符对应
j.为Master添加Segua选中tableViewCell按住Control拖动到Detail面板
k.必须先删除数据源再移除Table中的项
mData.removeAtIndex(indexPath.row)
tableView.deleteRowsAtIndexPaths([indexPath], withRowAnimation: .Fade)
34.Size Classes屏幕适配
a.regular width ,regular height(iPaid)
b.compact width ,compact height (iPhone)
35.UINavigationController 就是一个MVC,它的View由其他MVC组成,可以包含任意数量的MVC
a.它把其他都MVC放在屏幕上,与其他类型的Controller不同的是,它共享这个屏幕。类似Card叠加放置。
b.在多重MVC之间共享一个小的屏幕空间,它会将这些MVC堆起来
36.获取子MVCs
a.通过viewConrollers这个属性去获取Card子项,它们是由UIViewController组成的数组
var viewControllers:[UIViewController] {get set}
Tab bar: 有序的数组
Split view: 只有两个元素,Master是下标为[0]的,Detail是下标为[1]的,设值Push/Pop
Navigation controller: root view[0],剩下的就按顺序排列在栈中
b.如何获取ViewController
var tabBarContoller:UITabBarController?{get}
var splitViewController:UISplitViewController?{get}
var navigationController:UInavigationController?{get}
eg:获取一个splitView的Detail
if(letdetailVC:UIViewController==splitViewController?.viewControllers[1]){…}
37.Segues 从一个viewController转换到另一个viewController,类似于Android的监听器 按Control拖动
a.系统定义了四种Segues,也可以自定义Segues
Show Segue 展示正在交互的MVC
Show Detail Segue在SplitView中就是显示Detail,其他情况和Show Segue的效果一样
Modal Segue 完全布满整个屏幕,不推荐
Popover segue 一个小窗口,并不完全布满整个屏幕,点击窗口外的其它地方该窗口会消失,类似于Android的PopWindow
b.触发Segues可调用方法performSegueWidthIdentifier
func performSegueWidthIdentifier(idenifier:String,sender:AnyObject)
前提条件是:定义了identifier
c.prepareForeSegue
func perpareForSegue(segue:UIStoryboardSegue,sender:AnyObject?){//sender触发这个Segue的控件
if let identifier = segue.identifier{
switch identifier{
case “Show Graph”://某个Segue的identifier
if let vc =segue.destinationViewController as? MyController{
vc.property1=…
vc.callMethodToSetItUp(…)
}
default:break;
}
}
}
d.当你准备创建新的MVC时,它的outlet还没被设定时,这会让你的程序崩溃,也可能产生一些意想不到的行为
38.更改ViewController的命名步骤
a.更改类名
b.双击更改文件名
c.Main.storyboard中选择Custom Class的Class为更名后的ViewController
39.storyboard
a.设置是否固定字体大小 Autoshrink
Minimum Font Size自动根据屏幕缩放字体,但有最小字体的限制
Fixed Font Size固定控件大小
b.storyboard中插入View/Navigation View/Scroll View/Split View,选中控件
c.Label换行
选中Label ->Line Breaks
TruncateTail删减尾部,尾部点点
Word Wrap自动换行
d.UILabel适用于三行内的静态文本
d.设置启动View
40.Popover 弹窗窗口
a.并不是一个UIViewController
b.PopoverPrepare
eg:func prepareForSegue(segue:UIStoryboardSegue,send:AnyObject?){
iflet identifier=segue.identifier{
switch identifier{
case “popover segue”:
if let vc=Segue.destinationViewController as? MyController{
if let ppc=vc.popoverPresentationController{
ppc.permittedArrowDirections=
UIPopoverArrowDirection.Any
ppc.delegate=self
}
}
}
}
}
c.Presentation Controller 不能使用segue
1)当Popover弹窗时的相关适配,如显示位置,弹窗大小
默认会以modal方式全屏显示,可以设置为none,表示不需要适配
funcadaptivePresentationStyleForPresentationController(UIPresentationController)->UIModalPresentationStyle
{ returnUIModalPresentationStyle.None }
2)自定义窗口
func presentationController(UIPresentationController,viewControllerForAdaptivePresentationStyle:UIModalPresentationStyle)->UIViewController?
{ //returna UIViewController to use }
3)需实现代理协议 UIViewControllerTransitioningDelegate
eg:
class ViewController:
UIViewController, UIViewControllerTransitioningDelegate {
@IBAction
funcshowDidTouch(sender: UIBarButtonItem) {//按钮点击的Action
//create a controller,绑定 PresentViewController
let controller:UINavigationController! =
self.storyboard?.instantiateViewControllerWithIdentifier("ShowNavigationController")
as? UINavigationController
//"ShowNavigationController" storyboard中定义的controller标识
controller.modalPresentationStyle = .Custom
controller.transitioningDelegate =
self
self.presentViewController(controller, animated:
true, completion: {})
}
//UIViewControllerTransitioningDelegate
实现方法
funcpresentationControllerForPresentedViewController(presented:
UIViewController, presentingViewControllerpresenting:
UIViewController!, sourceViewControllersource:
UIViewController) ->
UIPresentationController? {
return
CustomPresentationController(presentedViewController:presented,presentingViewController:presenting)
}
}
CustomPresentationController是自定义的一个controller,它继承于UIPresentationController
d.设置窗口大小,结合segue使用
var preferredContentSize:CGSize
41.View Controller 生命周期
生命周期 | 调用场景 | 相关处理 | 说明 | 其他 |
awakeFromNib | 当.nib文件被加载时,即通过nib文件创建view时 | 不要滥用该方法 | ||
viewDidLoad() | 从dashborad中准备就绪,Outline设置完毕后调用。 只调用一次 | 初始化视图,更新UI | 一旦Model发生了改变,可以property observer中更新UI;但是,当新建一个View Controller,同样需要更新UI,那是因为property observer并不会在outlet设置之前去真正更新UI,因为你正在preparedForSegue的过程中。 很多时候当View Controller被调用viewDidLoad时UI界面并没有被真正更新,因为outline还没设置好。 | 注意:不要在该方法中做与几何位置相关当操作,因为此时视图的边界位置还没有确定 |
viewWillAppear( animated: Bool) | View Controller 马上要显示在屏幕上。 可调用多次 | 处理一些与几何位置相关到事情 | 视图边界已设置好 | 该方法有个参数animated,代表是否页面显示时需要有动画效果,一般在一个Navigation Controller里需要使用到这个参数 |
viewDidAppear( animated: Bool) | View Controller已显示在屏幕上 | |||
viewWillDisappear( animated: Bool) | View Controlle将要消失在屏幕上 | 清除一些占用资源的对象,比如图片 | 横竖屏切换的时候SplitView的Master经常会调用这个方法 | 注意:不要处理任何耗时的操作,容易卡死线程 |
viewDidDisappear( animated: Bool) | View Controlle消失在屏幕上 | |||
viewWillTransitionToSize | 屏幕旋转 | func viewWillTransitionToSize( size: CGSize, withTransitionCoordinator: UIViewControllerTransitionCoordinator ) 可以使用animate alongside动画 | 屏幕并不是一个事件,可以去取消特定的Autorotation,默认是取消的,竖屏模式 | |
didReceiveMemoryWarning | 电量低 | 清理大内存对象 | 比如一个指向图片的弱指针,此时将会被释放 | |
viewWillLayoutSubviews | 当视图层次或顶层视图当边界发生改变 | 当几何位置发生变化时,边界同样发生了变化,大部分的重新布局都是系统自动完成的,如果已经设置好Auto Layout属性的话。 但是,如果你需要在这个过程中处理一些自己的东西的话,就必须重写系统的两个方法 viewWillLayoutSubviews viewDidLayoutSubviews | 几何位置 启动(viewWillAppear后)或横竖屏(viewWillTransitionToSize后)时调用 | |
viewDidLayoutSubviews | 几何位置 |
初始化,awakeFromNib,segue preparation被初始化,outline设置,viewDidLoad,……..
42.自动化布局AutoLayout
l 使用蓝色当虚线达到想要的效果
l 使用Ctrl+拖动来创建view与view之间的关系
l storyboard右下角 Pin 和Arrange窗口
l 使用Reset to Suggested Contraints调整自适应边距
l Document Outline 解决错误或冲突(点击storyboard左下角展开,红色或黄色的提示)
l Size Inspector (选中view的详情约束,storyboard右上角)
l 点击一个约束并选择它,然后设置属性检查
其他:
a. MasteringAutolayout 需要经验
b. 自动化布局也可使用代码实现
各种设备比较:
设备 | 竖屏 | 横屏 | 说明 |
iPhone 6 plus | width:Compact height:Regular | width:Regular height:Compact | |
iPhone | width:Compact height:Regular | width:Compact height:Compact | 除iPhone 6 plus以外的设备 |
iPad | Regular | Regular | 特别的:Split view 中的master是Compact width,Regular height |
storyboard自动化布局:
操作 | 详细 | 备注 | 图例 |
右边界对齐 | 选中控件,按Ctrl向右拖动到右边界线,选择Trailling Space to Container Margin。 | 选择时,可按Shift可多选 | |
上边界对齐 | 选中控件,按Ctrl向上拖动到上边界线,选择Top Space to Top Layout Guide。 | 选择时,可按Shift可多选 | |
左边界对齐 | 选中控件,按Ctrl向左拖动到左边界线,选择Leading Space to Container Margin | 选择时,可按Shift可多选 | |
下边界对齐 | 选中控件,按Ctrl向下拖动到下边界线,选择Bottom Space to Bottom Layout Guide。 | 选择时,可按Shift可多选 | |
两个控件间的相对间距 | 选中控件,按Ctrl向垂直方向拖动到相对控件内部,选择verticl spaceing。 选中控件,按Ctrl向水平方向拖动到相对控件内部,选择Horizentol spaceing。 | 设置成功后,两控件间会形成一条蓝色的I形线条 选择时,可按Shift可多选 | |
两个控件间基线对齐 | 选中控件,按Ctrl拖动到相对控件内部,选择Baseline | 选择时,可按Shift可多选 | |
两个控件等宽/等高 | 选中控件,按Ctrl拖动到相对控件内部,选择Equal Widths/Equal Heights | 选择时,可按Shift可多选 | |
消除约束固定值,使用相对值 | 点击某个约束,打开编辑页面,在Contant值出选择Use Standard Value | 约束使用固定值,对自动化布局不利,设置Standard Value后约束会显示Equals:default | |
消除UI调整不适应的黄色警告 | 选中viewController,点击右下角的第三个图标,选择All Views in View Controller下的Update Frames,系统会将控件调整到最适应的位置 | ||
阻止内容压缩优先级 | Content Compression Resistance Priority中设置的优先级系数越低,越优先不被压缩 | 主要处理图片伸缩的问题,当遇到不同分辨率图片适配当压缩问题时,应将图片控件系数调低 | |
内容压缩优先级 | Content Hugging Priority中设置的优先级系数越低,越先被压缩 | ||
相对某控件Y方向中间的上方(图中的Name) | 添加约束Y居中(CenterY)对齐后,点击约束详情,Second Item 选择Bottom | ||
相对某控件Y方向中间的下方(图中的Company) | 添加约束Y居中(CenterY)对齐后,点击约束详情,Second Item 选择Top | ||
操作:在双屏的模式下,打开View Controller,点击最左边的蓝色圈Automatic,选择Preview,即可预览,可预览横竖屏视图
a.打开双屏的模式
b.点击最左边的蓝色圈Automatic,选择Preview
c.预览效果
44.icon size
1x:低分辨率设备 2x:高分辨率设备 3x:极高分辨率设备,如iPhone 6 plus
45.杂七杂八
l 约束 NSLayoutContranit
l 等比放缩图片
//添加约束 NSLayoutConstraint约束类型 imageView是图片控件
var aspectRatioContstraint:
NSLayoutConstraint?{
willSet{
if
let existingConstraint = aspectRatioContstraint{//设置前移除约束
view.removeConstraint(existingConstraint)
}
}
didSet{
if
let newConstraint = aspectRatioContstraint{
view.addConstraint(newConstraint)
}
}
}
设置约束
imageView.image = newValue
if
let constrainedView = imageView{
if
let newImage = newValue{//判断newValue不为nil
aspectRatioContstraint =
NSLayoutConstraint(
item: imageView,//item
需要添加约束的控件
attribute: .Width,//被约束的属性
relatedBy: .Equal,//Constants和multipliers的关系
.Equal:width=heigth*等高比
toItem: constrainedView,//相对其他控件,这里是imageview自己的宽高比,所以相对于自己
attribute:.Height,//相对的属性
multiplier: newImage.aspectRatio,//相乘的系数:等高比
constant: 0)//增加的常量
}else{
aspectRatioContstraint =
nil
}
}
l storyboard消除SubView关系
比如当storyboard在ScrollView满屏后再拖入其他控件,storyboard会自动将该控件添加为ScrollView的子控件,这种情况不一定是想要的。如何消除这种SubView关系:
a. 点击storyboard左下角的Document Outline,直接将子控件拖出ScrollView,将控件顺序拖到ScrollView的下方,控件就在ScrollView的上层了
b. 添加约束
选择控件,按Ctrl键拖动到View,即可添加约束
46.Scroll View(滚动条)
1)滚动区域设置 必须设置,否则不会显示
scrollView.contentSize= CGSize(width: 3000, height: 2000)
2)添加子View
login.frame = CGRect(x: 2700, y:50, width:120, height: 180)
scrollView.addSubview(log0)
图片:
letimage=UIImage(named:”xx.jpg”)
letiv=UIImageView(image:image)//iv.frmage.
=image.size
scrollView.addScrollview(iv)
scrollView.contentSize=imageView.bounds.size
3)获取当前滑动的坐标区域
letupperLeftOfVisible: CGPoint = scrollView.contentOffset
4)通过代码滑动到制定区域
funcscrollRectToVisible(CGRect, animated: Bool)// animated:true滑动过去,false 直接跳过去。
如果contentSize修改了,scrollView会闪一下。
5) Zooming
a.放缩的比例
srollView.minmumZoonScale=0.5 //默认大小的一半
scrollView.maxmumZoomScale=2.0//两倍大小
b.代理delegate
当ScrollView在Zooming时,它只zoom in
func viewForZoomingInScrollView(sender: UIScrollView)-> UIView
手势离开屏幕的时候调用的delegate
func scrollViewDidEndZooming(UIScrollView,withView:UIView,atScale: CGFloat)
c.其他
var zoomScale: CGFloat
func setZoomScale(CGFloat, animated: Bool) 设置缩放比例
func zoomToRect(CGRect, animated: Bool)
eg:
6)Closures 闭包方法
样例一:
class Grapher{
var yForX: ((x:Double) -> Double?)?//闭包
}
let grapher = Grapher()
let graphingBrain = CalculatorBrain()
graphingBrain.program = theProgramToGraph
grapher.yForX = { (x:Double) -> Doublein //闭包的实现
graphingBrain.variableValues[“M”] = x
return graphingBrain.evaluate()
}
调用eg: grapher.yForX!(x:1.0)
样例二:
class Foo{
var action: () -> Void = {}
func show(value: Int){ println(“\(value)”)}
func setupMyAction(){
var x: Int = 0
action={//闭包
x=x+1
self.show(x)//闭包内部有个指针指向self
}
}
func doMyAction10Times(){for i in 1..10{action()}}
}
闭包内相互指向,会造成两者永远存在内存中,它们永远不会被释放,造成捕获异常泄漏,解决:不捕获self指针[unowned self] in
action={ [unowned self] in
x=x+1
self.show(x)//闭包内部有个指针指向self
}
yForx = {[unowned
self](x:Double)->
Double in
self.showSomething()
return
1
}
47. Multithreading(多线程)
iOS有多重队列,一个函数队列,基础的闭包,每个队列都有一个自己的线程去运行这些队列
a.执行队列,执行一个函数或一个闭包
letqueue: dispatch_queue_t=….
dispatch_async(queue){……..} 两个参数,一个队列一个闭包,闭包不需要参数也不返回值
b.主队列,是一个串行队列
主队列一次从队列里只拉出一个函数执行,所有的UI活动都必须发生在主队列
主队列不能做任何可能阻塞的任务,比如URL的NSData下载
MVC的代码都在主队列中执行
letmainQ: dispatch_queue_t=dispatch_get_main_queue()//获取主队列
letmainQ: NSOperationQueue=NSOperationQueue.mainQueue()//OC获取主队列
eg:
dispatch_async(notTheMainQueue){//notTheMainQueue中处理阻塞UI的任务
dispatch_async(dispatch_get_main_queue()){//主线程中处理不阻塞UI的任务
}
}
c.其他并行队列
QOS_CLASS_USER_INTERACTIVE优先级最高
QOS_CLASS_USER_INITIATED 优先级高
QOS_CLASS_UTILITY 优先级一般
QOS_CALSS_BACKGROUND 后台任务,优先级低
letqos = Int(x.value)
letqueue=dispatch_get_global_queue(qos,0)
d.建立自己的串行队列
letserial=dispatch_queue_create(“name”,DISPATCH_QUEUE_SERIAL)
e.Example
Example1:
letdelayInSeconds=25.0
letdelay=Int64(delayInseconds*Double(NSEC_PER_MSEC))
letdispatchTime=dispatch_time(DISPATCH_TIME_NOW,delay)
dispatch_after(dispatchTime,dispatch_get_main_queue()){
}
Example2: NSURLSession API
let session = NSURLSession(NSURLSessionConfiguration.defaultSessionConfiguration())
if let url=NSURL(string: http://url”){
let request=NSURLRequest(URL:url)
lettask=session.downloadTaskWithRequest(request){//异步下载一个文件
(localURL,response,error) in collection
}
task.resume()
}
48.进度条 Activity Indicator View
49.文本框 UITextField
1) 显示键盘becomeFirstResponder()
2) 隐藏键盘 resignFirstResponder()
3) 一个重要的代理delegate UITextFieldDelegate
functextFieldShouldReturn(sender: UITextField)
在用户点击键盘上的return键后触发(也可能是search或go,取决于键盘类型),此时需调用resignFirstResponder隐藏键盘
4) UITextField 是一种UIControl,可以设置target/action,但通常我们使用
delegate,因为系统会自动调用resignFirstResponder
5) 编辑已结束,即使没有按return按钮
func textFieldDidEndEditing(sender:UITextField)
6) 键盘弹出时UITextField需移动到键盘之上
方式:把UITextField放在静态到TableView中或UITextField在顶部
7)其他属性
varclearsOnBeginEditing: Bool
varadjustFontSizeToFitWidth: Bool
varplaceholder: String//提示语
varbackground/disabledBackground: UIImage
vardefaultTextAttributes: Dictionary
varinputAccessoryView: UIView//可以在键盘上面添加其他控件
8) UITextView是一个非常强大的编辑对象,多行,多种字体等等
UITextInputTraits协议监听键盘输入
UITextField属性,包括键盘类型,是否自动大写,是否密码形式输入:
varUITextAutocapitalicationType auctocapitalizationType//words,sentences等
varUITextAutocorrectionType autocorrectionType//yes or no
varUIReturnKeyType returnkeyType//Go, search, Google, Done 等
varBOOL secureTextEntry//设置密码形式输入
varUIKeyboardType keyboardType//ASCII,URL,PhonePad等
9)NSNotification 键盘总是在视图之上
当TextFiled在底部,需要调整输入框的位置时,要用到NSNotification
UIKeyboard{will,Did}{Show,Hide}Notifications
注册一个事件 UIKeyboardDidShowNotification
NSNotificationCenter.defaultCenter().addObeserver(self,
selector:”theKeyboardappeared:”,
name:UIKeyboardDidShowNotification
object:view.window)
键盘弹出的时候将会调用自定义方法
functheKeyboardAppeared(notification:NSNotification)
eg:
classUITextFieldViewController:
UIViewController,UITextFieldDelegate,UITextInputTraits {
@IBOutlet
weak var textField:
UITextField!{
didSet{
textField.autocapitalizationType =
UITextAutocapitalizationType.Words
textField.autocorrectionType =
UITextAutocorrectionType.Yes
textField.returnKeyType =
UIReturnKeyType.Done
textField.secureTextEntry =
false
textField.keyboardType =
UIKeyboardType.URL
textField.becomeFirstResponder()
textField.delegate =
self
let view:UIView =
UIView(frame: CGRect(x:
10, y: 20, width:
20, height: 20))
view.backgroundColor =
UIColor.blueColor()
textField.inputAccessoryView = view
}
}
override
func viewDidLoad() {
super.viewDidLoad()
NSNotificationCenter.defaultCenter().addObserver(self, selector:
"theKeyboardappeared:", name:
UIKeyboardWillShowNotification, object: textField.window)
// Do any additional setup after loading the view.
}
functheKeyboardappeared(sender:NSNotification){
//软键盘遮挡处理
}
//点击了return/search/go,表示输入完成
functextFieldShouldReturn(textField:
UITextField) -> Bool {
textField.resignFirstResponder()//收起键盘
return
true
}
//编辑已结束,即使没有按return按钮
functextFieldDidEndEditing(textField:
UITextField) {
textField.resignFirstResponder()//收起键盘
}
}
50. UITableView 展示大量数据
1)本质是一个一维表格,也可以当成列表,它是UIScrollView的子类,在拥有大量数据的时候非常有效率
2)可以把多个TableView嵌套到NavigationController中,建立二位表格,因为无法建立真正的二维表格
3)Table显示方式
plain Style:长列表,用于动态数据
Group Style: 可以把一列的信息管理起来,用于固定数据
4)Table的组成
Header(头部):UIView
Section(组项): ,多个项归类,每个 section 都有一个 header和Foot
Footer(底部): UIView
复杂的Header和Footer可以使用TableViewCell
UITableViewDataSource’s tableView(UITableView, cellForRowAtIndexPath:NSIndexPath)
5)列表样式
Subtitle:UITableViewCellStyle.Subtitle ,子标题
Basic: UITableViewCellStyle.default ,常见不分类列表
Right Detail: UITableViewCellStyle.value1,左边是归纳,右边是详情
Left Detail: UITableViewCellStyle.value2,右边是归纳,左边是详情
6)UITableViewController
缺点:MVC 的全部 view 都必须得是 tableview
优点:storyboard中建立UITableViewController时它会自动将data sourch数据源和delegate连接到TableView上,普通的ViewController需要自己连接。
7)设置cell的类型
static:可以放置任何控件,table会将它们分组,可以给它们设置outlets,静态的
dynamic:一系列相同的控件集合,plain
custom:
8)Detail Disclusure
添加segue时应选择Accessory Action中的show
9)实现data source协议
a.table中section的数量
b.制定section中有几行
c.给它一个UITableViewCell 或它的子类来显示这一行
10)通过它们可以向Table载入数据
a.普通Cell
functableView(tv:UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) ->UITableViewCell{
let data=myInternalDataStructure[indexPath.section][indexPath.row]
let cell=…//创建一个UITableViewCell并加载数据
returncell
}
b.SubTitle Cell
func tableView(tv:UITableView,cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell{
let data=myInternalDataStructure[indexPath.section][indexPath.row]
//自定义UITabeleViewCell
let dequeued:AnyObject=tv.dequeueReusableCellWithIdentifier(“MyCell”,forIndexPath:indexPath)//由于历史的原因,它并没有返回一个UITableCell,而是AnyObject,需要我们强转
letcell=dequeued as UITableViewCell
cell.textLabel?.text=”Title”//较大的文字
cell.detailTextLabel?.text=”Subtitle”//较小的文字
//也可载入图片,有imageView属性
returncell
}
c.自定义Custom Cell
func tableView(tv:UITableView,cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell{
let data=myInternalDataStructure[indexPath.section][indexPath.row]
let dequeued: AnyObject=tv.dequeueReusableCellWithIdentifier(“MyCustomCell”,forIndexPath:indexPath)//由于历史的原因,它并没有返回一个UITableCell,而是AnyObject,需要我们强转
letcell=dequeued as MyTableViewCell
cell.publicAPIofMyTableViewCell=data.theDataTheCellNeedsToDisplayItsCustomLabelsEtc
…
returncell
}
11)UITableViewDataSource
funcnumberOfSectionsInTableView(sender:UITableView) -> Int //必须实现该方法,必须设置每个section有多少行
func tableView(sender:UITableView,numberOfRowsInSection:Int) -> Int
cellForRowAtIndexPath也是必须实现的方法,如果是静态的table就不需要实现,因为在storyboard中已经设置好了
获取标题
func tableView(UITableView, titleFor{Header, Footer}InSection: Int)-> String
也可以实现UITableView的delegate去获取标题
12)TableView Segues
//sender 是UIButton/UITableViewCell
func prepareForSegue(segue:UIStoryboardSegue, sender: AnyObject){
iflet identifier= segue.identifier{
switch identifier{
case “XyzSegue”:
case “AbcSegue”:
let cell=sender as MyTableViewCell//强转
if let indexPath =tableView.indexPathForCell(cell){
letseguedToMVC=segue.destinationViewController as MyVC
seguedToMVC.publicAPI=data[indexPath.section][indexPath.row]
}
default: break
}
}
}
13)UITableViewDelegate
delegate可以监听table内部发生的情况,例如:
当Table中一行被点击时,可以设置segue到其他视图,也可以在didSelectRowAtIndexPath代理方法中获取到,它会提供section和Row
其他方法:will/did willBegin/didEnd
14)UITableView Target/Action 更新Table UI
func tableView(sender: UITableView, didSelectRowAtIndexPathindexPath:NSIndexPath){
}
//点击 detail disclosure响应
functableView(UITableView, accessoryButtonTappedForRowWithIndexPath: NSIndexPath)
15)刷新数据
func reloadData(),它会发送numberOfSectionsInTableView和numberOfRowsInTableView,并且对每一个可见的cell调用cellFortowAtIndexPath,重新载入所有的数据
也可以调用
funcreloadRowsAtIndexPaths(indexPaths: [NSIndexPath], widthRowAnimation:UITableViewRowAnimation)
传递给它一个IndexPath数组,它只会重新载入这些cell
更新数据时行高可能会改变,应代码设置Table的高度为UITableViewAutomaticDimension自适应,如果设置了AutomaticDimension也需要设置estimatedRowHeight,因为table view是scroll view ,estimatedRowHeight可以获取size的大小
通过delegate获取行高
func tableView(UITableView, {estimated} heightForRowAtIndexPath: NSIndexPath) -> CGFloat
16)创建TableView
在storyboard中拖入一个UITableViewController后,将它放入Navigation Controller中,选中该controller,点击Edit->Embed In(放入)->Navigation Controller
因为可能需要点击某条tweet然后展示更多信息
63.Unwind Segues 不会创建视图
1)优点:
a.能直接或间接地回到之前地位置,解开连接
b.如果你有一个MVC并且是通过modal的方式展示的
2)modal
Modal segue:取代整个屏幕
popover就是一种modal,每当popover弹出的时候,除了这个popover其他都无法操作
3)当你在任何MVC中添加了IBAction方法,如果它的参数是UIStoryboardSegue,当使用Ctrl+拖动到退出按钮时,需选择goBack: Segue/Action
64.Alerts和Action Sheets 两种用户请求弹出框
1)区别:
Alerts:直接弹出在屏幕的中央,都是modal的形式,类似于Android的Dialoag
Action Sheets:从屏幕底部滑出,popover,集结了一堆选项的表单,如选择图片/拍照,类似于Android的popupWindow
2)创建Action Sheets 在iPhone(底部弹出层)和iPad(popover)显示效果不同
varalert=UIAlertController(
title:”Redeploy Cassini”,
message:”Issue commands to Cassini’sguidance system.”
preferredStyle:UIAlertContrllerStyle.ActionSheet
)
添加事件监听
alert.addAction(UIAlertAction(
title:”Orbit Staturn”, //标题
style:UIAlertActionStyle.Default, //样式, Default蓝色的字体,.Destructive红色文字
//handler:(action:UIAlertAction) -> Void//闭包,action就是这个UIAlertAction本身
{
(action: UIAlertAction) ->Void in
…..
}
))
显示ViewController
//设置显示的方式为popover
alert.modalPresentationStyle=.Popover
let ppc=alert.popoverPresentationController
ppc?.barButtonItem=redeployBarButtongItem
presentViewController(alert, animated:true,completion:nil)
3)创建Alert 在iPhone和iPad显示效果一样
var alert=UIAlertController(
title:”Login Required”,
message:”Please enter your Cassini guidancesystem.”
preferredStyle: UIAlertContrllerStyle.Alert
)
添加底部按钮
alert.addAction(UIAlertAction(
title:”Cancel”
style:.Cancel)
{(action:UIAlertAction) ->Void in
….
}
)
添加登录事件
alert.addAction(UIAlertAction(
title:”Login”,
style:.Default)
{(action: UIAlertAction) -> Void in
let tf=self.alert.textFields?.first as?UITextField //获取密码
if tf!=nill{self.loginWithPassword(tf.text) }//登录
}
)
//添加输入框
alert.addTextFieldWithConfigurationHandler{(textField) in
textField.placeholer=”Guidance System Password”
}
65.NSTimer 定时器
1)永远在主队列中使用定时器
2)启动定时器
NSTimer .scheduledTimeWithTimeInterval(
_seconds: 2.0,//启动的间隔时间
target:self, //向谁发消息AnyObject
selector:”fire”, //需要定时器执行的方法Selector(String)
userInfor:nil, //参数存储传递AnyObject?
repeats: true//是否只执行一次,true表示每两秒执行一次
)
func fire(timer: NSTimer){
lettheTimersUserInfo = timer.userInfo
}
3)停止计时器
func fire(timer: NSTimer){
if imDoneWithThisTimer{
timer.invalidate()//销毁
}
}
还可以使用tolerance可以优化系统性能(推荐)
myOneMinuteTimer.tolerance=10//每十秒执行一次
tolerance只设置一个秒为单位的时间
使用tolerance使得应用处于一个低耗能状态,否则它就会一直保持唤醒状态,以确保定时器的触发
66.动画Animation
分类
1) 使用view属性的执行动画
a) frame:视图随意移动
class func animateWithDuration(
duration: NSTimeInterval,//动画执行的时间
delay:NSTimeInterval,//等待的时间
options:UIViewanimationOptions,//动画
animations:()-> Void,//block,无参数也无返回值,修改视图属性
completion:((finished: Bool) -> Void)?)//动画执行完毕
eg:2秒后开始执行,开始3秒的淡出视图,完成后将它从父视图中移除
if myView.alpha=1.0{
UIView.animateWithDuration(3.0,
Delay:2.0,
Options:UIViewAnimationOptions.CurveEaseInEaseOut,//动画
Animations:{myView.alpha=0.0},// 修改透明度
completion:{if $0{myView.removeFromSuperView()}})
println(“myView.alpha=\(myView.alpha)”)
}
b) transform:旋转放缩视图
UI View.transitionWithView(
view:UIView,
duration: NSTimeInterval,//动画执行时间
options:UIViewAnimationOptions,//动画
animations:() -> Void,
completion:((finished: Bool) -> Void)?)
eg:
UIView.transitionWithView(view:myPlayingCardView,
duration:0.75,
options:UIViewAnimationOptions.TransitionFlipFromLeft
animations:{cardIsFaceUp=!cardIsFaceUp}
completions:nil )
c) alpha:透明度
UIViewAnimationOptions:
BegainFromCurrentState
AllowUserInteraction
LayoutSubviews
Repeat
Autoreverse
OverrideInheritedDuration
OverrideInheritedCurve
AllowAnimatedContent
CurveEaseInEaseOut
CurverLinear
2) viewController的跳转动画
3) CoreAnimation是在UI View Core Animation动画,底层的一种,非常强大的动画引擎,可操纵大量属性的执行动画
4) DynamicAnimation动态动画,基于物理引擎的动画,它会赋予视图重力和碰撞
67. Dynamic Animation
1)步骤:
a.创建UIDynamicAnimator
varanimator=UIDynamicAnimator(referenceView:UIView)
referenceView必须指定最顶层的UIView
b.添加UIDynamicBehaviors 动态行为,比如重力或碰撞之类的
eg: let gravity=UIGravityBehavitor()
animator.addBehavior(gravity)
eg:collider=UICollisionBehavior()
animator.addBehaviot(collider)
c.添加UIDynamicItems
let item1:UIDynamicItem=…
let item2:UIDYnamicItem=…
grivate.addItem(item1)
collider.addItem(item1)
gravity.addItem(item2)
item1将会受其他重力和碰撞所影响
item2只受重力影响
2)UIDynamicItem protocol协议
protocol UIDynamicItem{
var bounds:CGRect{get}//只读,动画器无法改变一个东西的大小
var center:CGPoint{get set}//对象的位置
var transform:CGAffineTransform{get set}//用于旋转
}
改变一个视图中心或使视图变形
func updateItemUsingCurrentState(item:UIDynamicItem)
3)UIGravityBehavior
varangle: CGFloat//设置一个角度
varmagnitude:CGFloat//比例1:1000,每1000像素点每二次方秒
任意对象在这个方向上就会有一个加速度
4)UIAttachmentBehavior其他行为动画效果
int(item:UIDynamicItem,attachedToAnchor:CGPoint)
init(item:UIDynamicItem,attachedToItem:UIDynamicItem)
init(item:UIDynamicItem,offsetFromCenter:CGPoint,
attachedToItem/Anchor…)
varlength:CGFloat
varanchorPoint:CGPoint
5)UICollisionBehavior碰撞效果
能控制对象间的碰撞,还可以控制对象和一个边界间的碰撞
varcollisionMode:UICollisitionBehaviorMode
设置路径UIBezierPath曲线,它会使用这个UIBezierPath当作它的外部边界
设置边界时必须设置identifier标志符
funcaddBoundaryWithIdentifier(identifier:NSCopying,forPath:UIBezierPath)
也可以设置translatesReferenceBoundsIntoBoundary为true,那么动画对象的所有外边框就会变成一个边界
vartranslatesReferenceBoundsIntoBoundary:Bool
func removeBoundaryWithIdentifier(identifier:NSCopying)
设置代理
varcollisionDelegate:UICollisionBehaviorDelegate
当碰触到一个边界时,将会得到这个代理消息
func collisionBehavior(behavior:UICollistionBehavior,
began/endedContactForItem:UIDynamicItem,
withBoundaryIdentifier:NSCopying)//需转为字符串或其他类型
6)IUSnapBehavior 移动到某个地方,发生类碰撞然后震荡
init(item:UIDynamicItem, snapToPoint:CGPoint)
vardamping:CGFloat 震荡的幅度
7)UIPushBehavior 将某个东西推向特定的角度或是一个力度
push会影响所有被添加到这个动画里的东西
push和重力的区别:push行为可以是一个一次性的效果,也可以是一个持续性或连续性的效果,不会加速,它是恒速
varmode:UIPushBehaviorMode
varpushDirection:CGVector
varangle:CGFloat
varmagnitude:CGFloat
8)UIDynamicItemBehavior 动态对象行为,所有行为的父类,本身是UIDynamicBehavior的子类
varallowsRotation:Bool
varfriction: CGFloat
varelasticity: CGFloat //设置弹性,弹跳的幅度
=1完全失重弹跳不停止
funclinearVelocityForItem(UIDynamicItem) -> CGPoint 线速度
func addLinearVelocity(CGPoint, forItem:UIDynamicItem) 在特定方向添加速度
func angularVelocityForItem(UIDynamicItem) -> CGFloat 角速度
9)UIDynamicBehavior 所有行为的父类
func addChildBehavior(UIDynamicBehavior)//添加子行为
可以拥有复合行为
所有的行为一次只能在一个动画中
10)UIDynamicAnimator
vardynamicAnimator: UIDynamicAnimator{get}
funcwillMoveToAnimator(UIDynamicAnimator)
var delegate:UIDynamicAnimatorDelegate
func dynamicAnimatorDidPause(UIDynamicAnimator)动画暂停
func dynamicAnimatorWillResume(UIDynamicAnimator)动画恢复
l 不要在一个视图放入一个行为中,当一个视图不在动画的参考视图的视图体系中,程序就会崩溃
l 不要使用一个大小为(0,0)的对象动画
eg:避免内存循环
if letpushBehavior=UIPushBehavior(items:[..], mode:.Instantaneous){
pushBehavior.magnitude=..
pushBehavior.angle=..
//调用自身,造成内存循环不释放
pushBehavior.action={ [unowned pushBehavior] in //改进
//改进后,表示pushBehavior在闭包中是不会被强引用的,所以不需要捕获
pushBehavior.dynamicAnimator!.removeBehavior(pushBehavior)
}
animator.addBehavior(pushBehavior)
}
68.Application 生命周期
1)生命周期
a. Not running
b. Inactive
l Not running à Inactive状态切换
AppDelegate会受到通知:
Funcapplication(UIapplication, didFinishLaunchingWithOptions:
[NSObject:AnyObject])
observe:每次应用启动
UIApplicationDidFinishLauncheingNotification
l Active à InActivity
AppDelegate会受到通知:
Func applicationWillResignActive(UIApplication)
observe:每次应用启动
UIApplicationWillResignActiveNotification
l Backgroundà InActivity
AppDelegate会受到通知:
Func applicationWillEnterForeground (UIApplication)
observe:每次应用启动
UIApplicationWillEnterForegroundNotification
c. Active
l InActivity à Active应用暂停Pause
AppDelegate会受到通知:
Func applicationDidBecomeActivite(UIApplication)
observe:
UIApplicationDidBecomeActiviteNotification
d. Background
l InActivityàBackground应用
AppDelegate会受到通知:
FuncapplicationDidEnterBackground(UIApplication)
开启线程,启动后台任务之类的
observe:
UIApplicationDidEnterBackgroundNotification
e. Suspended
机制:在手机锁定后,应用访问的数据需要加密
2) UIApplication
a.获取共享对象let myApp = UIApplication.sharedApplication()
b. 打开URL
func openURL(NSURL)
func canOpenURL(NSURL) -> Bool
c. 本地通知
func(un)registerForRemoteNotifications()
func scheduleLocalNotification(UILocalNotification)
funcregisterUserNotificationSettings(UIUserNotificationSettings)
d. 设置获取间隔,启动后台工作Background Fetch
funcsetMinimumBackgroundFetchInterval(NSTimeInterval) 默认值是Never
如果不设置,那么应用不会被唤醒
一般需设置为UIApplicationBackgroudFetchIntervalMinimum,尽多可能多的唤醒应用程序后台
e. 运行后台任务,后台时主线程会被暂停
func backgroundTaskWithExpirationHandler(handler:() -> Void) -> UIBackgroundTaskIdentifier
完成时需调用 endBackgroundTask(UIBackgroundTaskIdentifier)
默认情况下,如果在期限内,后台任务没有完成,那么iOS将终止应用程序,这时候还可以使用
begainBackgroundTaskWithExpirationHandler再向系统申请点时间
f. 网络进度条显示/隐藏设置
varnetworkActivityIndicatorVisible: Bool
g. 其他属性
varbackgroundTimeRemaining: NSTimeInterval{get}
varpreferredContentSizeCategory: String{get} 字体的大小
varapplicationState: UIApplicationState{get} 应用程序状态,foreground/background/active
3) info.plist 字典,包括很多应用程序的设置
69.NSNotification通知
1)NSNotificationCenter 接收消息
func addObserverForName(String, //接收消息标志名
object:AnyObject?, 发送广播者,=nil的话表示接收所有这类型的的广播
queue:NSOperationQueue?)//队列
{ (notification: NSNotification) -> Void in //队列闭包
可能是当前队列,也可能是主队列
let info: [NSObject:AnyObject]? = nofification.userInfo
userInfo是一个OC里面的字典,key: NSObject, values: AnyObject
}
NSOperationQueue类似一个在分发工作中顶端的面向对象的API
eg:
let center =NSNotificationCenter.defaultCenter()
//UIContentSizeCategoryDidChangeNotification系统自体更改的通知标识
center.addObserverForName(UIContentSizeCategoryDidChangeNotification,
object: UIApplication.sharedApplication(),
queue: NSOperationQueue.mainQueue())
{ notifaction in
letc = notification.userInfo?[UIContentSizeCategoryNewValueKey]
}
70.Core Motion
CMMotionManager
1)检测硬件设备是否可用
var {accelerometer,gyro,magnetometer,deviceMotion}Available:Bool accelerometer加速器
2)开启硬件
func start{Accelerometer, Gyro,magnetometer, DeviceMotion}updates()
3)硬件是否活跃
var{accelerometer,gyro,magnetometer,deviceMotion}Active: Bool
4)停止硬件
funcstop{Accelerometer,Gyro,Magnetometer,DeviceMotion}upates()
5)设备移动获取加速数据
var accelerometerData: CMAccelerometerData
var acceleration: CMAcceleration
struct CMAcceleration{
varx: Double //g(9.8 m/s/s)
vary: Double
varz:Double
}
g:重力加速度
陀螺仪
var gyroData: CMGyroData
var rotationRate:CMRotationRate 转速
struct CMRotationRate{
varx: Double //radius/s
var y: Double //radius/s
var z: Double //radius/s
}
磁力计
var magnetometerData: CMMagnetometerData
var magneticField: CMMagneticField
struct CMMagneticField{
var x: Double
var y: Double
var z: Double
}
6)CMDeviceMotion
var gravity: CMAcceleration 重力
var userAcceleration: CMAcceleration 用户加速度
var rotationRate: CMRotationRate
var attitude: CMAttitude
class CMAttitude: NSObject{
var roll: Double 滚动
var pitch: Double 投掷
var yaw: Double 偏航方向
}
var magneticField:CMCalibratedMagneticField
struct CMCalibratedMagneticField{
varfield: CMMagneticField
varaccuracy: CM
}
7)注册一个block
a.注册一个block接收Accelerometer数据
funcstartAccelerometerUpdatesToQueue(queue: NSOperationQueue!,withHandler:CMAccelerometerHandler)
typealiasCMAccelerationHandler=(CMAccelerometerData!, NSError!) -> Void
队列NSOperationQueue()或NSOperation.mainQueue或当前队列
b.注册一个block接收Gyro数据
func startGyroUpdatesToQueue(queue:NSOperationQueue!, withHandler:CMGyroHandler)
typealias CMGyroHandler=(CMAGyroData!,NSError!) -> Void
c.注册一个block接收DeviceMotion数据
func startDeviceMotionUpdatesToQueue(queue:NSOperationQueue!, withHandler: CMDeviceMotionHandler)
typealias CMDeviceMotionHandler=(CMDeviceMotion!,NSError!) -> Void
8)设置rate 单位是秒
var accelerometerUpdateInterval:NSTimeInterval
var gyroUpdateInterval: NSTimeInterval
var magnetometerUpdateInterval:NSTimeInterval
var deviceMotionUpdateInterval:NSTimeInterval
71.Core Location
1) 代表基本位置的对象CLLocation(CL:Core Location)
a.属性:coordinate坐标, altitude高度, horizontalAccuracy/verticalAccuracy水平或垂直精度,
timestamp时间戳, speed速度, course 方向
b.经纬度
varcoordinate: CLLocationCoordinate2D//平面坐标,不包括高度
struct CLLocationCooordinate2D{
CLLocationDegrees latitude //Double
CLLocationDegrees longitude //Double
}
c.精确度
衡量水平和垂直空间的,精确度并不是一个百分比的数值或类似,是一组预定义好的信息
varhorizontalAccuracy: CLLocationAccuracy
varverticalAccuracy: CLLocationAccuracy
精度越高越耗电,与基站通讯耗电非常低,手机会一直和基站通讯,wifi也比较耗电
kCLLocaitonAccuracyBestForNavigation 最高精度 GPS
kCLLocaitonAccuracyBest 高精度 GPS
kCLLocaitonAccuracyNearestTenMeters 10米附近的精度 GPS+wifi混合
kCLLocaitonAccuracyHundredMeters 百米附近的精度 wifi
kCLLocaitonAccuracyKilometer 一公里的精度 基站
kCLLocaitonAccuracyThreeKilometers 三公里的精度 基站
d.速度:瞬时速度
varspeed: CLLocationSpeed
e.方向: 更倾向于运动轨迹的方向
varcourse: CLLocationDirection
f.时间戳:重要属性,当获取位置可能不是一个实时的操作,可以查看时间戳检查位置信息获取的时间
vartimestamp: NSDate
2)获取CLLocation
CLLocationManager
a.检查是否有相应的硬件,不是所有手机都有点位硬件
b.创建一个实例并且设置代理delegate
c.按需求配置位置信息
d.开始发送代理信息
它会通过一个稳定的流向你发信息
3)监控手机的地理位置方式
a.基于一个特定的精确度,提供持续的更新
b.地理位置有显著改变的时候通知,可以设置区域
4)CLLocaionManager的类方法
授权状态:Authorized, Denied, Restricted
classfunc authorizationStatus() -> CLAuthorizationStatus
class func locationServicesEnabled() ->Bool 位置服务是否开启
class func significantLocationChangeMonitoringAvailable() -> Bool 显著位置变更监控方式是否可用
class func isMonitoringAvailableForClass(AnyClass!) -> Bool
class func isRangingAvailable() -> Bool
5)获取授权
func requestWhenInUseAthorization() 仅在app是当前活动的app时启动
func rquestAlwaysAuthorization() 申请在任何时候都获取位置,即使app在后台
使授权申请生效需在info.plist文件里加入一个键,在这两个键二选一,只要有键就可以不需要有值。
NSLocationWhenInUseageDescription
NSLocationAlwaysUseageDescription
在CLLocationManager里设置desiredAccuracy
vat desiredAccuracy: CLLocationAccuracy 精确度
var distanceFilter: CLLocationDistance 指定距离更新过滤器
func startUpdatingLocation() 开始更新位置信息
func stopUpdatingLocation() 停止更新位置信息
6)代理信息方法
CLLocationManager:发送消息方
func locationManager(CLLocationManager,didUpdateLocations: [CLLocation])
手机处于休眠状态时,GPS也可以纪录位置信息
7)向delegate回调错误信息
func locationManager(CLLocationManager,didFailWithError: NSError)
错误信息
kCLErrorLocationUnknown
kCLErrorDenied
kCLErrorHeadingFailure
8)显著变更
funcstartMonitoringSignificantLocationChanges()
func stopMonitoringSignificantLocationChanges()
app启动时会调用didFinishLaunchingWithOptions方法
func application(UIApplication,didFinishLaunchingWithOptions: [NSObject, AnyObject])
这个字典有一个key: UIApplicationLaunchOptionsLocationKey, 这个说明app启动时由于一个显著位置变更导致的,你需要去查看当前位置然后作出响应。
var location: CLLocation
9)区域
靠近或离开区域时,会调用它的代理方法
func locationManager(CLLocationManager,didEnterRegion: CLRegion)
func locationManager(CLLocationManager,didExitRegion: CLRegion)
func locationManager(CLLocationManager,monitoringDidFailForRegion: CLRegion, withError: NSError)
a. CLCircularRegion圆圈区域
func startMonitoringForRegion(CLRegion)
func stopMonitoringForRegion(CLRegion)
let cr=CLCirularRegion(center:CLLocationCoordinate2D, 圆点
radius: CLLocationDistance, 半径
identifier:String) 标识是必要的
app没有启动或在后台时也能监控区域,需要特定点时间唤醒app,app被唤醒时会提醒已进入预设区域
b. CLBeaconRegion 灯塔区域
你是否靠近另一台iOS设备,需要用到Core Bluetooth框架技术,需要定义identifier并注册该identifier
系统可以检测到与灯塔间的距离
funcstartRangingBeaconsInRegion(CLBeaconRegion)调用该方法后,将会受到didRangeBeacons 这个代理方法发送的信息
10)app在后台时也可以区域监控
可以在CLLocationManager的monitoredRegions属性里找到
var monitoredRegions: NSSet 无序数组
var maximumRegionMonitoringDistance:CLLocationDistance{get}
72.地图 Map
1)MKMapView: UIView的子类
coordinate,title,subtitle
MKAnnotationView的子类展示,地图上的标识图形,默认是个大头针
MKPinAnnotationView 点击弹出框
a.初始化
importMapKit
letmapView = MKMapView()
varannotations: [MKAnnotation]{get} 是一个AnyObject的只读数组,但是不能把非MKAnnotation的对象放入这个数组中
协议protocol
protocol MKAnnotation: NSObject
var coordinate: CLLocationCoordinate2D{get} 坐标
var title: String!{get} 标题,必须设置
var subtitle: String!{get} 子标题
2)MKAnnotation
只读属性
var annotations: [MKAnnotation] {get}
必须添加/移除annotation
func addAnnotation(MKAnnotation)
func addAnnotations([MKAnnotation])
func removeAnnotation(MKAnnotation)
func removeAnnotations([MKAnnotation])
3)MKAnnotationView
a.MKAnnotationView如何加载以及和annotation数组联系起来
viewForAnnotation会提供一个annotation并需要为它创建视图
func mapView(sender: MKMapView,viewForAnnotation: MKannotation) -> MKAnnotationView{
//把一个复用的视图从队列中取出
varview = sender.dequeueReusableAnnotationViewWithIdentifier(IDENT)
ifview==nil{
// reuseIdentifier复用标识符
view = MKPinAnnotationView(annotation: annotation, reuseIdentifier:IDENT)
view.canShowCallout=true/false是不是允许弹出标识视图
}
aView.annotation=annotation
return view
}
b.其他属性
var annotation: MKAnnotation
var image: UIImage 设置地图标识图片,默认是个大头针
左右辅助视图
var leftCalloutAccessoryView: UIView
var rightCalloutAccessoryView: UIView
var enabled: Bool 激活或隐藏
var centerOffset: CGPoint 中心偏移量
var draggable: Bool 大头针是否可拖拽,坐标coordinate属性{get set}
c.特性:如果标识视图的辅助视图是一个UIControl,通常是一个UIButton,当它被点击时,地图视图当代理方法calloutAccessoryControlTapped就会被调用(弹出框的点击事件)
eg:view.rightCalloutAccessoryView=UIButton.buttonWithType(UIButtonTypeDetailDisclusure)
func mapView(MKMapView, annotationView:MKAnnotationView, calloutAccessoryControlTapped: UIControl)
d.点击地图标志图会调用didSelectAnnotationView
mapView(viewForAnnotation:)
letview.leftCalloutAccessoryView=UIImageView()
func mapView(MKMapView,didSelectAnnotationView aView:MKAnnotationView)
{
检查左辅助视图是否是一个图片视图
iflet imageView = aView.leftCalloutAccessoryView as? UIImageView{
imageView.image=..设置图片,然后开启一个线程开始下载
}
}
3)配置地图类型
卫星视图Statellite,混合视图Hybrid,标准的街道视图Standard
var mapType: MKMapType
var showsUserLoaction: Bool true:定位到当前位置
var isUserLocationVisible: Bool 可以设置当前位置是否显示
var userLocation: MKUserLocation 用户位置信息
限制用户操作
var zoomEnabled: Bool 放缩
var scrollEnabled: Bool 滚动
var pitchEnable: Bool 所有手势//3D
var rotateEnable:Bool 旋转
4)MKMapCamera
var camera:MKMapCamera
调整视角的坐标
letcamera=MKMapCamera(lookingAtCenterCoordinate: CLLocationCoordinate2D,
fromEyeCoordinate:CLLocationCoordinate2D,
eyeAltitude:CLLocationDistance)
5)MKCoordinateRegion控制显示地图的部分
var region:MKCoordinateRegion
structMKCoordinateRegion{
var center: CLLocationCoordinate2D
var span: MKCoordinateSpan
}
structMKCoordinateSpan{围绕这个点的经纬度
var latitudeDelta: CLLocationDegrees
var longitudeDelta: CLLocationDegrees
}
func setRegion(MKCoordinateRegion,animated: Bool)
varcenterCoordinate: CLLocationCoordinate2D 设置区域中心的坐标
funcsetCenterCoordinate(CLLocationCoordinate2D, animated: Bool)
funcshowAnnotations([MKAnnotation, animated: Bool])
6)其他方法和函数
MKMapRectContainsPoint,MKMapPointForCoordinate
转换不同的坐标空间 地球坐标,地图坐标
funcmapPointForPoint(CGPoint) -> MKMapPoint
funcmapRectForRect(CGRect) -> MKMapRect
funcpointForMapPoint(MKMapPoint) -> CGPoint
funcrectForMapRect(MKMapRect) -> CGRect
代理方法 didChangeRegionAnimated,它会告诉你现在显示在地图里的区域变化
funcmapView(MKMapView, didChangeRegionAnimated: Bool)
有时候需要调用地图视图的动画链,比如切换地点时,可以先缩小到整个区域,再放大到具体的地点,这样比直接跳过去更好
7)MKLocalSearch地图搜素
varrequest=MKLocalSearchRequest()
request.naturalLanguageQuery=@”Ike’s” 搜素地名
request.region=..
letsearch=MKLocalSearch(request: request)
search.startWithCompletionHandler{(MKLocalSearchResponse,NSError) -> Void in
主线程使用网络查询,返回一个MKPlacemark
}
MKMapItem
funcopenInMapsWithLaunchOptions([NSObject: AnyObject]) -> Bool
8)路线规划
MKRoute MKPolyline
9)Overlays 覆盖层
MKOverlay是MKAnnotation的子类
funcaddOverlay(MKOverlay, level: MKOverlayLevel)
funcremoveOverlay(MKOverlay)
varboundingMapRect: MKMapRect 包含整个覆盖层的矩形
func intersectsMapRect(MKMapRect)-> Bool 矩形是否有交叉
给覆盖层定义自定义视图
funcmapView(MKMapView, rendererForOverlay: MKOverlay) -> MKOverlayRenderer
MKOverlayRenderer在地图上绘制覆盖层
系统渲染
MKCircleRenderer 渲染圆形
MKPolylineRenderer画路线
MKPolygonRederer 渲染多边形
MKTileOverlayRenderer 平铺图片
73.Modal Segue
1)主要是用来处理屏幕上的内容 弹出层
以modal的形态显示选择present modally
funcperformSegue(UIStoryboardSegue, withIdentifier: String) 直接调用segue
展示ViewController
funcpresentViewController(UIViewController, animated: Bool, completion: () ->Void)
modalPresentationStyle:.FullScreen(全屏,默认值), .OverFullScreen(全屏,但并不阻止下面但屏幕互动), .Popover(弹出窗口), .FormSheet
2)如何通过modally segued返回到MVC
funcprepareForSegue(segue: UIStoryboardSegue, sender: AnyObject!){
if segue.identifier == “GOTOMyModalVC” {
let vc = segue.destinationViewControlleras MyModalVC
}
}
大部分modal segue完成工作后就会移除自己
unwind可以移除自己
也可以手动调用dismissViewControllerAnimated
funcdismissViewControllerAnimated(Bool, completion: () -> Void)
3)如何将一个modal view controller展示到屏幕上
varmodalTransitionStyle: UIModalTransitionStyle 出现或离开的动画样式
.CoverVertical 从底部滑出,默认效果
.FlipHorizontal 翻转的效果
.CrossDissolve 淡出
.PartialCurl 从底部的一个角落翻起
相关文章推荐
- Swift语法——Swift Sequences 探究
- 初探 Swift SPriteKit
- Swift学习之路02-类,初始化
- Swift学习之路01-基础类型
- 关于oc和swift混编 框架framework时 只能在真机运行或只能在模拟器单独运行的解决方案
- swift NSComparator
- swift数据分布原理分析博文推荐
- Swift-ReactiveCocoa3.0(二)SignalProducer
- Swift备忘
- 用Swift编写iOS录
- Swift 2.0特有的枚举函数的实现方法和调用方法
- swift学习之...和..<
- Swift入门(六)——字典(Dictionary)
- swift学习之闭包(closure)
- swift--runtim获取变量信息
- Swift 懒加载(lazy)
- Swift入门(五)——数组(Array)
- swift学习之函数类型
- swift2 泛型
- Swift对于可选类型(Optionals)讲解不错的文章