Swift

import UIKit

protocol Emitterable {
    
}
//這里的 where Self : UIViewController 意思是對使用該效果必須繼承自UIViewController
extension Emitterable where Self : UIViewController {
    func start() {
        
        // 1.創(chuàng)建發(fā)射器
        let emitter = CAEmitterLayer()
        
        // 2.設(shè)置發(fā)射器的位置
        emitter.emitterPosition = CGPoint(x: view.bounds.width * 0.5, y: -60)
        
        // 3.開啟三維效果
        emitter.preservesDepth = true
        
        // 4.創(chuàng)建例子, 并且設(shè)置例子相關(guān)的屬性
        // 4.1.創(chuàng)建例子Cell
        let cell = CAEmitterCell()
        
        // 4.2.設(shè)置粒子速度
        cell.velocity = 150
        cell.velocityRange = 100
        
        // 4.3.設(shè)置例子的大小
        cell.scale = 0.7
        cell.scaleRange = 0.3
        
        // 4.4.設(shè)置粒子方向
        cell.emissionLongitude = CGFloat(M_PI_2)
        cell.emissionRange = CGFloat(M_PI_2 / 2)
        
        // 4.5.設(shè)置例子的存活時(shí)間
        cell.lifetime = 6
        cell.lifetimeRange = 1.5
        
        // 4.6.設(shè)置粒子旋轉(zhuǎn)
        cell.spin = CGFloat(M_PI_2)
        cell.spinRange = CGFloat(M_PI_2 / 2)
        
        // 4.6.設(shè)置例子每秒彈出的個(gè)數(shù)
        cell.birthRate = 20
        
        // 4.7.設(shè)置粒子展示的圖片
        cell.contents = UIImage(named: "good6_30x30")?.cgImage
        
        // 5.將粒子設(shè)置到發(fā)射器中
        emitter.emitterCells = [cell]
        
        // 6.將發(fā)射器的layer添加到父layer中
        view.layer.addSublayer(emitter)
    }
    
    func stop() {
        /*
        for layer in view.layer.sublayers! {
            if layer.isKind(of: CAEmitterLayer.self) {
                layer.removeFromSuperlayer()
            }
        }
        */
        view.layer.sublayers?.filter({ $0.isKind(of: CAEmitterLayer.self)}).first?.removeFromSuperlayer()
    }
}

調(diào)用很簡單:

class ViewController: UIViewController , Emitterable {

    override func viewDidLoad() {
        super.viewDidLoad()
    }

    override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
        
        self.start()
        
        DispatchQueue.main.asyncAfter(deadline: .now() + 5) {

            self.stop()
        }
    }
}

效果:

Snip20161212_5.png

import UIKit

/************************** 字典定義 *****************************/
// Swift中字典的類型Dictionary
// 不可變字典使用let修飾
// 可變字典使用var修飾
// 注意:字典在創(chuàng)建時(shí)使用[]
let dict : Dictionary = ["name" : "JJCoder", "age" : 18] as [String : Any]
// dict = ["name" : "lmj", "age" : 20]
let dict1 : Dictionary<String, AnyObject> = ["name" : "jack" as AnyObject, "age" : 20 as AnyObject]

// 開發(fā)中常見寫法
let dict2 : [String : AnyObject] = ["name" : "jack" as AnyObject, "age" : 22 as AnyObject]

// 類型推導(dǎo)
let dict3 = ["name" : "jjcoder", "age" : 26] as [String : Any]

// 可變字典
var dict4 = [String : AnyObject]()


/************************** 對可變字典的操作 *****************************/
// 1.在字典中添加元素
dict4["name"] = "lmj" as AnyObject?
dict4
dict4["age"] = 26 as AnyObject?
dict4
dict4["height"] = 1.74 as AnyObject?
dict4

// 2.從字典中移除元素
let age = dict4.removeValue(forKey: "age")


// 3.修改字典中的值
// 注意:通過一個(gè)鍵來修改字典中的值,如果存在這個(gè)鍵則修改.如果不存在就會添加新的鍵值對
dict4["weight"] = 62.0 as AnyObject?
dict4
dict4["height"] = 1.74 as AnyObject?
dict4

// 4.獲取值
// let height = dict4["height"]! as! Double
let height = dict4["height"]!
print(height)


/************************** 對可變字典的遍歷 *****************************/
// 1.遍歷字典中所有的鍵
for key in dict4.keys {
    print(key)
}

// 2.遍歷字典中所有的值
for value in dict4.values {
    print(value)
}

// 3.遍歷字典中的鍵值對
for (key, value) in dict4 {
    print(key)
    print(value)
}


/************************** 字典的合并 *****************************/
var d1 = ["name" : "jjcoder", "age" : 20] as [String : Any]
var d2 = ["height" : 174, "phoneNum" : "+86 15210100335", "name" : "majianjie"] as [String : Any]

// 兩個(gè)字典,即時(shí)類型一致也不可以彼此相加
// var d3 = d1 + d2

// 合并過程中,如果沒有對應(yīng)的鍵,添加對應(yīng)的鍵值對
// 如果有隊(duì)要你管的鍵,則修改原有的值
for (key, value) in d1 {
    d2[key] = value
}

>Swift中的元組
import UIKit

// 元祖也是一個(gè)數(shù)據(jù)集合,可以在集合中定義一組數(shù)據(jù)
// 元祖的定義使用:(元素1,元素2)
("1001", "JJCoder", 19, 1.74)
(id : "1001", name : "張三", age : 26, height : 1.74)

// 用一個(gè)數(shù)據(jù)類型來描述網(wǎng)絡(luò)請求錯(cuò)誤
// errorCode/errorInfo
[404, "Not Found"] as [Any]
["errorCode" : 404, "errorInfo" : "Not Found"] as [String : Any]

// 用元祖描述錯(cuò)誤信息
let error = (404, "Not Found")
error.0
error.1

let error1 = (errorCode : 404, errorInfo : "Not Found")
error1.errorCode
error1.errorInfo

switch (error1) {
case (404, "Not Found"):
    print("沒有找到host")
default :
    print("其他錯(cuò)誤")
}

let (errorCode2, errorInfo2) = (404, "Not Found")
errorCode2
errorInfo2


map : 可以對數(shù)組中的每一個(gè)元素做一次處理

如果求一個(gè)數(shù)組中字符串的長度可以用 map來處理


//方法1
let array = ["Objective-C", "HTML", "CSS"]
//定義方法 返回傳入的字符串的長度
func calcuCount(string: String) -> Int {
    return string.characters.count
}
//使用  打印
print(array.map(stringCount))

// 方法2
print(fruits.map{return $0.characters.count})

reduce:可以對數(shù)組中的元素進(jìn)行計(jì)算

// 將數(shù)組中的每個(gè)字符串用‘-’拼接
let array =  ["Objective-C", "HTML", "CSS"]

func appendString(string1: String, string2: String) -> String {
    return string1 == "" ? string2 : string1 + "-" + string2
}
// reduce方法中的第一個(gè)參數(shù)是初始值
print(array.reduce("第一個(gè)字符串", appendString))//打印第一個(gè)字符串-Objective-C-HTML-CSS

// $0表示計(jì)算后的結(jié)果, $1表示數(shù)組中的每一個(gè)參數(shù)
print(array.reduce("", {
    return $0 == "" ? $1 : $0 + "-" + $1
}))
//打印 Objective-C-HTML-CSS

filer:過濾,可以對數(shù)組中的元素按照某種規(guī)則進(jìn)行一次過濾

let stringArray = ["MJ-C", "Swift", "Cocos2d-x", "Python", "JavaScript"]
func stringCountLess10(string: String) -> Bool {
    return string.characters.count < 10
}
stringArray.filter(stringCountLess10)

stringArray.filter({string -> Bool in
    return string.characters.count < 10
})

// $0表示數(shù)組中的每一個(gè)元素
stringArray.filter{
    return $0.characters.count < 10
}


后期會陸續(xù)更新....

flatmap 可以把數(shù)組繼續(xù) '切割'

// 用flatMap
let arrayFlatMap = arraya.flatMap { $0 }
print(arrayFlatMap)
// [1, 2, 3, 4, 5, 6, 7, 8, 9]

>Swift類構(gòu)造函數(shù)
import UIKit

/*
 1.自定義構(gòu)造函數(shù)時(shí)會覆蓋原有的構(gòu)造函數(shù)
    如果不希望覆蓋,則可以明確的將原來的構(gòu)造函數(shù)寫出
*/

class Person {
    var name : String = ""
    var age : Int = 0
    
    init() {
        
    }
    
    init(name : String, age : Int) {
        self.name = name
        self.age = age
    }
    
    init(dict : [String : AnyObject]) {
        if let name = dict["name"] as? String {
            self.name = name
        }
        
        if let age = dict["age"] as? Int {
            self.age = age
        }
    }
}

// 1.使用init()構(gòu)造函數(shù)創(chuàng)建對象
let p = Person()
p.name = "jjcoder"
p.age = 18

// 2.使用init(name : String, age : Int)創(chuàng)建對象
let p1 = Person(name: "mjj", age: 19)

// 3.通過init(dict : [String : AnyObject])方法創(chuàng)建對象
let p2 = Person(dict: ["name" : "mjj" as AnyObject, "age" : 26 as AnyObject])

>Swift中的可選類型
import UIKit

// nil 只能賦值給可選類型,不能賦值給其他的任意類型

// var name : String = "why"
// name = nil

var view : UIView = UIView()
// view = nil

/*
// 1.可選類型如何定義
var name : Optional<String> = nil

// 2.給可選類型進(jìn)行賦值
name = Optional("123")
 */

// 1.可選類型如何定義
var name : String? = nil

// 2.給可選類型進(jìn)行賦值
name = "123"

// 3.取出可選類型中值 : 需要對可選類型進(jìn)行解包
// print(name)
print(name!)

// 4.可選類型 + ! --> 強(qiáng)制解包
// 如果可選可選類型為nil,那么強(qiáng)制解包程序就會崩潰

// 5.可選綁定 : 1> 判斷可選類型有沒有值, 如果沒有值,那么{}不執(zhí)行 2> 如果有值, 會先對name進(jìn)行解包, 并且將解包后的結(jié)果賦值給前面的標(biāo)識符
if let name = name {
    print(name)
}

Swift中的類型分為兩種 :

  1. 值類型
每個(gè)值類型的實(shí)例都擁有各自唯一的數(shù)據(jù),通常它們是結(jié)構(gòu)體,枚舉或元組
Array、String和Dictionary都是值類型
  1. 引用類型
引用類型的實(shí)例共享它們的數(shù)據(jù),通常是一個(gè)類。
class   是引用類型

區(qū)別?

值類型最基本的特征就是復(fù)制在賦值、初始化和傳遞參數(shù)過程中的數(shù)據(jù),并為這個(gè)數(shù)據(jù)創(chuàng)建一個(gè)獨(dú)立
的實(shí)例

下面舉2個(gè)粟子:??

// 值類型例子
struct MJJ { var data: Int = 1 }
var a = MJJ()
var b = a                       // 把a(bǔ)賦值給b
a.data = 42                     // a被改變了, b卻沒有
println("\(a.data), \(b.data)") // prints "42, 1"

// 引用類型的例子
class JJCoder { var data: Int = -1 }
var x = JJCoder()
var y = x                       // x被復(fù)制給了y
x.data = 4                    // x指向的數(shù)據(jù)被修改了 (同時(shí)y也被修改了)
println("\(x.data), \(y.data)") // prints "4, 4"

其實(shí)是隱式地創(chuàng)建了一個(gè)共享的實(shí)例。在賦值后,兩個(gè)實(shí)例指向了同一塊數(shù)據(jù),所以當(dāng)修改其中一個(gè)實(shí)例數(shù)據(jù)的時(shí)候,另一個(gè)實(shí)例的數(shù)據(jù)也被修改了

安全性方面考慮??

選擇值類型而不是引用類型的一個(gè)主要原因是能讓你的代碼變得更加簡單。你在任何情況下用一個(gè)值類型,都能夠假設(shè)你的其他代碼不會使它改變,這通常在多線程環(huán)境中很有用,如果一個(gè)線程中使用的數(shù)據(jù)被另一個(gè)線程給意外的修改了,這通常會產(chǎn)生非常嚴(yán)重的Bug,且相當(dāng)難以調(diào)試。
由于只有當(dāng)你需要修改數(shù)據(jù)時(shí)兩者的區(qū)別才會得到體現(xiàn),所以當(dāng)你的實(shí)例不會對數(shù)據(jù)進(jìn)行修改的時(shí)候,值類型和引用類型看起來是完全相同的。
你也許會想,寫一個(gè)完全不可變的類,這或許是有價(jià)值的,使用Cocoa的NSObject能簡化這個(gè)過程,并且能很好地保持原有的語義?,F(xiàn)在,你能通過使用不可變的存儲屬性,以及避免暴露修改數(shù)據(jù)的接口,從而在Swift里實(shí)現(xiàn)一個(gè)不可變的類。事實(shí)上,大多數(shù)的Cocoa類,比如NSURL等,都被設(shè)計(jì)為不可變的類,然而,Swift當(dāng)前并沒有提供任何語言機(jī)制去強(qiáng)制申明一個(gè)類不可改變(比如子類化就能修改一個(gè)類的實(shí)現(xiàn)),只有結(jié)構(gòu)體和枚舉才是強(qiáng)制不可變的。

如何抉擇:??

使用值類型:
1. 通過使用==去比較實(shí)例的數(shù)據(jù)
2. 想得到一個(gè)實(shí)例的獨(dú)立副本
3. 數(shù)據(jù)在多線程環(huán)境下被修改

使用引用類型(比如使用一個(gè)類):
1. 通過使用===去判斷兩個(gè)實(shí)例是否恒等
2. 你想要?jiǎng)?chuàng)建一個(gè)共享的,可變的對象

iOS默認(rèn)是不支持播放GIF圖片的,但是系統(tǒng)也沒有禁止播放它,該有的API還是有的,下面就 來一發(fā)吧!

一定要導(dǎo)入ImageIO 這個(gè) 庫

//首先你得有個(gè)imageview吧~~~~~
 @IBOutlet weak var imageView: UIImageView!
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        // 1??.在本地加載Gif圖片(不要放在imageassert中,其實(shí)也放不進(jìn)去~~`), 并且轉(zhuǎn)成Data類型(這里不再寫swift語法,guard 做一下校驗(yàn)...)
        guard let path = Bundle.main.path(forResource: "demo.gif", ofType: nil) else { return }
        guard let data = NSData(contentsOfFile: path) else { return }
        
        // 2??. 將data轉(zhuǎn)成CGImageSource對象,返回CGImageSource
        guard let imageSource = CGImageSourceCreateWithData(data, nil) else { return }
        //3??通過CGImageSource可以拿到分解了多少張圖片(看成是一幀一幀的)
        let imageCount = CGImageSourceGetCount(imageSource)
        
        // 4??遍歷所有的圖片
        var images = [UIImage]()
        var totalDuration : TimeInterval = 0
        for i in 0..<imageCount {
            // 3??.1??取出圖片
            guard let cgImage = CGImageSourceCreateImageAtIndex(imageSource, i, nil) else { continue }
            let image = UIImage(cgImage: cgImage)
            if i == 0 {
                imageView.image = image
            }
            //3??.2??加入到一個(gè)images的數(shù)組中
            images.append(image)
            
            // 3??.3??取出持續(xù)的時(shí)間(這里記住就可以了)
            guard let properties = CGImageSourceCopyPropertiesAtIndex(imageSource, i, nil) as? NSDictionary else { continue }
            guard let gifDict = properties[kCGImagePropertyGIFDictionary] as? NSDictionary else { continue }
            guard let frameDuration = gifDict[kCGImagePropertyGIFDelayTime] as? NSNumber else { continue }
            totalDuration += frameDuration.doubleValue
        }
        
        // 4??.給imageView設(shè)置屬性
        imageView.animationImages = images
        imageView.animationDuration = totalDuration
        imageView.animationRepeatCount = 0
        
        // 5??.開始播放
         imageView.startAnimating()
    }


最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容