一、Swift - 访问控制(fileprivate,private,internal,public,open)
在Swift语言中,访问修饰符有五种,分别为fileprivate,private,internal,public和open。
其中 fileprivate和open是Swift 3新添加的。由于过去 Swift对于访问权限的控制,不是基于类的,而是基于文件的。这样会有问题,所以Swift 3新增了两个修饰符对原来的private、public进行细分。
1.1、各个修饰符区别
1,private
private访问级别所修饰的属性或者方法只能在当前类里访问。
2,fileprivate
fileprivate访问级别所修饰的属性或者方法在当前的Swift源文件里可以访问。(比如上门样例把private改成fileprivate就不会报错了)
3,internal(默认访问级别,internal修饰符可写可不写)
internal访问级别所修饰的属性或方法在源代码所在的整个模块都可以访问。
如果是框架或者库代码,则在整个框架内部都可以访问,框架由外部代码所引用时,则不可以访问。
如果是App代码,也是在整个App代码,也是在整个App内部可以访问。
4,public
可以被任何人访问(包括不同module)。但其他module(同一个工程)中不可以被override和继承,而在module内可以被override和继承。
5,open
可以被任何人使用,包括override和继承。
• private:私有属性和方法,仅在当前类中可以访问,不包括分类;
• fileprivate:文件内私有属性和方法,仅在当前文件中可以访问,包括同一个文件中不同的类。
• public表示当前类、属性或者方法只能在当前module内被继承或者override,在当前module意外只能被访问;
• open表示当前类、属性或者方法可以在任何地方被继承或者override;
• final是一个辅助修饰词,表示当前类、属性或者方法在任何地方都只能被访问,不能被继承或者override;
internal表示默认级别。
二、变量
2.1、定义
let:常量,只能赋值一次。
var:变量,能多次赋值
2.2、字符串 String(NSString)
let myString = “hello world”
数字转字符串
let myCount = 18
let my = String(myCount)
更简单的把值转换成字符串的方法:把值写到括号中,并且在括号之前写一个反斜杠
let myCount = 18
let my = “my cout \(myCount)”
或者
let myCount = ["数组","第二个"]
letwithLable = String(describing: myCount)
2.3、数组 Array(NSArray)
var occupations = [“134”,”123”,"543","234"]
2.4、字典 Dictionary(NSDictionary)
let interestingNumbers = [
"Prime":[2,3,4,5,6],
"Fibonacci":[32,54,65,76],
"Square":[5,6,7,9]
]
2.5、数值
整形Int(NSInteger),小数Float(CGFloat),双精度Double(double),布尔bool(BOOL),无符号整数UInt (UInt8,UInt32…)
*变量后面加?代表变量可以为nil;变量后加!代表变量不能为nil,如果变量为nil程序将闪退
2.6、重写set和get方法(变量名需不一样,否则死循环)
var _juTitle: String?
var juTitle: String{
set{
_juTitle=newValue
}
get{
return _juTitle ?? "无值"
}
}
*无set方法时,默认是get方法此外还有didset、willset
可在didSet时重新赋值
open var juTitle: String?{
didSet{
juTitle = "newValue"
}
willSet{
NSLog("%@",newValue ?? "")
}
}
三、函数
3.1、函数多个返回值
函数申明:
func juBackMulit (scores :[Int]) -> (min:Int ,max:Int, sum:Int){
var mins = scores[0]
var maxs = scores[1]
var sums = 0
for score in scores{
if score > maxs {
maxs=score;
}else if score < mins{
mins=score
}
sums+=score;
}
return (mins,maxs,sums)
}
函数调用:
let statistics = juBackMulit(scores: [50,3,62,7,10])
NSLog("%d", statistics.sum)
NSLog("%d", statistics.2)
3.2、函数作为返回值
申明函数:
func juBackFunc(sum:Int) -> ((Int) -> Int) {
func addOne(number: Int) -> Int {
return 1 + number + sum
}
addOne(number: 15)
return addOne
}
调用函数:
let increment = juBackFunc(sum: 12)
increment(7)
3.3、函数内包含函数(嵌套函数)
申明函数:
func juBackFunc(sum:Int) -> Int {
func addOne(number: Int) -> Int {
return 1 + number + sum
}
return addOne(number: 15)
}
调用函数:
let increment = juBackFunc(sum: 12)
3.4、函数当做参数传入另一个函数
申明函数:
func juFuncParameter (list:[Int] ,condition: (Int)/**传入函数的参数类型*/ -> Bool/**传入返回值类型*/) ->Bool{
for item in list{
if condition(item) {
NSLog("对")
return true
}
}
NSLog("错")
return false
}
func lessThanTen (number :Int) -> Bool{
return number < 10
}
var numberss = [10,30,40,13,12]
调用函数:
juFuncParameter(list: numberss, condition: lessThanTen)
3.5、函数有可变参数
申明函数:
func juChangeParameters(numbers: Int...) ->Int{
var sum = 0
for number in numbers{
sum += number
}
return sum;
}
调用函数:
juChangeParameters()
juChangeParameters(numbers:42, 36, 12)
3.6、类方法和实例方法
在class类型上下文中,我们使用class;其他的使用static。
1)作用于结构
struct Point {
let x: Double
let y: Double
//存储属性
static let zero = Point(x: 0, y: 0)
//计算属性
static var ones: [Point] {
return [
Point(x: 1, y: 1),
Point(x: -1, y: 1),
Point(x: 1, y: -1),
Point(x: -1, y: -1)
]
}
//类型方法
static func add(p1: Point, p2: Point) -> Point {
return Point(x: p1.x + p2.x, y: p1.y + p2.y)
}
Class funcjuClass() {
NSLog(“类方法”)
}
}
let p = Point(x: 3, y: 4)
Point.zero
Point.ones
Point.add(Point(x: 1, y: 2), p2: Point(x: 2, y: 1))
作用于类
class Square {
//类型属性,用class关键字
class var PI: Double{
return 3.14
}
}
或者get方法写
class Square {
class var PI: Double{
get { return 3.14 }
}
}
*方法变量名前加_ 调用的时候可以不写参数名
四、闭包(函数表达式)
(参数类型) -> (返回值类型)
例子 (String,String) -> (String)
4.1、block变量
let juCompletionBlock: (String, String) -> String = {string1, string2 in
NSLog("调用了闭包")
return "闭包"
}
let blockBack = juCompletionBlock("参数1","参数2");
NSLog(blockBack)
4.2、block函数参数
函数
func juBlockClosure(closure: (String,String) -> String) { //函数体部分
NSLog("函数体部分:%@",closure("参数1","参数2"))
}
// 闭包函数调用太随意了
//以下是不使用尾随闭包进行函数调用
juBlockClosure(closure: {string1,string2 in
NSLog("闭包主体部分1:参数1:%@,参数2:%@",string1,string2)
return "123"
//闭包主体部分
})
//以下是使用尾随闭包进行函数调用
juBlockClosure() {string in
NSLog("闭包主体部分2")
return "321"
//闭包主体部分
}
juBlockClosure { (string1, string2) -> String in
NSLog("闭包主体部分3")
return "456"
}
4.3、返回值为block
函数申明
func juBlockClosure2() -> ((String,String) -> String) {
return {string1,string2 in
NSLog("闭包主体部分6:参数1:%@,参数2:%@",string1,string2)
return "1234512345"
//闭包主体部分
}
}
调用
juBlockClosure2()(“32342”,”r4544")
4.4、Block的返回值为Block
申明block的block
typealias funcBlockC = (Int,Int) -> (String)->String
申明block
let juCompletionBlock1: (String) -> String = {string2 in
NSLog(string2)
return "第一层"
}
申明函数
func testBlockC(blockfunc:funcBlockC!)
{
if (blockfunc) != nil
{
let retfunc = blockfunc(5,6)
let str = retfunc("最终果结是")
NSLog(str)
}
}
调用函数
self.testBlockC { (num1, num2) -> (String) -> String in
NSLog("乘机和:%@", String(num1*num2))
return self.juCompletionBlock1
}
五、控制流
5.1、for循环
例1:
for index in 1...5 {
print("\(index) times 5 is \(index * 5)")
}
例2:
let names = ["Anna", "Alex", "Brian", "Jack"]
for name in names {
print("Hello, \(name)!")
}
例3:
let numberOfLegs = ["spider": 8, "ant": 6, "cat": 4]
for (animalName, legCount) in numberOfLegs {
print("\(animalName)s have \(legCount) legs")
}
5.2、Guard
例1:
func fooGuard(x: Int?) {
//如果x不等于nil并且x大于0否则return
guard let x = x , x > 0 else {
//变量不符合条件判断时,执行下面代码
return
}
//使用x
x.description
}
例2:
func testGuart(x: NSString?,y:NSString?) {
//如果x不等于nil并且x大于0否则return
guard let first = x,let second = y else {
NSLog("错误1");
//变量不符合条件判断时,执行下面代码
return
}
NSLog("正确1");
//使用x
}
5.3 Switch支持任意类型的比较操作
let name = "jute"
switch name {
case "jute":
print("jute")
case "juvid":
print("juvid")
default:
print("none")
}
六、枚举和结构体
6.1、枚举:
Swift中的枚举比OC中的枚举强大, 因为Swift中的枚举是一等类型, 它可以像类和结构体一样增加属性和方法
格式:
enum Method{
case枚举值
}
6.2、结构体:
结构体是用于封装不同或相同类型的数据的, Swift中的结构体是一类类型, 可以定义属性和方法(甚至构造方法和析构方法等)
格式:
struct 结构体名称 {
结构体属性和方法
}
七、下标语法
7.1、一个参数
class JuOpneClass: NSObject {
subscript(juIndex: Int) -> Int{
get{ return juIndex}
set{}
} }
调用
let juOpne = JuOpneClass.init()
print(juOpne[3])
7.2、多个参数
subscript(juIndex: Int, juRow: Int) -> Int{
get{ return juIndex*juRow}
set{}
}
print(juOpne[3,2])
八、协议protocol
1)声明
//继承于class是因为只有继承于class才能用weak来修饰代理
public protocol JuDelegate : class {
//set表示可写,get可写
var juName : String {get set}
funcjuTestDelegage()
func juExtension()
}
2)实现
class JuModel: NSObject,JuDelegate {
var juName: String = “代理"
func juTestDelegage(){
NSLog("代理回调")
}
}
3)调用
class JuProtocol: NSObject {
weak open var delegate: JuDelegate?
func juHandle() {
delegate?.juTestDelegage()
delegate?.juName = "我来赋值"
print(delegate?.juName ?? "没有值")
}
}
*swift中协议没有可选类型,可以通过类拓展协议先实现部分方法
extension JuDelegate{
public funcjuExtension() {
print("可选协议实现方法")
}
}
九、分类extension
*分类的默认情况新增属性不能存储,利用runtime可实现
1)普通分类
extension NSString{
func juName() {
NSLog("分类")
}
}
2)采纳协议(一个或多个)
extension NSString:JuDelegate{
public var juName: String {
get {
return "分类实现协议"
}
set {
// 设置其他值
}
}
public func juTestDelegage() {
print("分类实现方法")
}
open func juNames() {
NSLog("分类")
}
}
*知识点
1.1、required(必需的在子类super父类方法)
1)required关键字,只能用于修饰构造方法
//1.当子类没实现任何构造方法,编译器就会认为子类可以使用父类中的所有指定构造器,required修饰的构造方法在子类中可以不写
//2当子类中定义了异于父类中的构造方法(参数名称不同、参数个数不同、参数类型不同),那么父类中使用required修饰的构造方法在子类中必须实现,而且这个方法必须使用required关键字而不能使用override修饰
1.2、override
override用于重写父类函数、属性等(final修饰的不能被重写)。
1.3、convenience(便利构造器),只能调用不能重写不能super;
//便利构造器
convenience init(name:String){
self.init(name: name,color: "黑人")
}
1.4、当使用module是 属性使用
self.setValue("字符串2", forKey: “_juTitle") 奔溃
申明累的时候使用
@objcMembers
open class JuRunTime: NSObject {
}
或者属性前加@objc
@objc open var _juTitle: String?
1.5、用类名字符串创建类
OC中可以直接通过类名的字符串转换成对应的类来操作,但是Swift中必须用到命名空间,也就是说Swift中通过字符串获取类的方式为NSClassFromString(命名空间.类名) // 1.获取命名空间
// 通过字典的键来取值,如果键名不存在,那么取出来的值有可能就为没值.所以通过字典取出的值的类型为AnyObject?
guard let clsName = NSBundle.mainBundle().infoDictionary!["CFBundleExecutable"] else {
ChaosLog("命名空间不存在")
return
}
// 2.通过命名空间和类名转换成类
let cls : AnyClass? = NSClassFromString((clsName as! String) + "." + “ViewController”)
得到了类名之后还不算完,Swift中通过class创建一个对象,必须告诉系统class的类型type
// swift 中通过Class创建一个对象,必须告诉系统Class的类型
guard let clsType = cls as? UITableViewController.Type else {
ChaosLog("无法转换成UITableViewController")
return
}
// 3.通过得到的class类型创建对象
let childController = clsType.init()
1.6、类型转换
类型转换在swift中使用 is 和 as操作实现(可加?可选)
letsomeObjects = ["zhutianwei",5432] as [Any]
for object in someObjects{
if let juObj = object as? Int{
// 可选转换
print("整数\(juObj)")
}else if object is String{
// 判断是否该类型
print("字符")
}
}
*在已经类型的时候可以用强制转换 as!
Any 和AnyObject 类型转换
AnyObject 可以表示任何类类型的实例
Any 可以表示任何类型,包括函数类型