分类 swift 下的文章

swift自动释放池,性能优化

Swift在内存管理上使用的是自动引用计数(ARC)的一套方法,在ARC中虽然不需要手动地调用像是retain,release或者是autorelease这样的方法来管理引用计数,但是这些方法还是都会被调用的——只不过是编译器在编译时在合适的地方帮我们加入了而已。其中retain和release都很直接,就是将对象的引用计数加一或者减一。但是autorelease就比较特殊一些,它会将接受该消息的对象放到一个预先建立的自动释放池 (auto release pool)中,并在自动释放池收到drain消息时将这些对象的引用计数减一,然后将它们从池子中移除(这一过程形象地称为“抽干池子”)。
在App中,整个主线程其实是跑在一个自动释放池里的,并且在每个主Runloop结束时进行drain操作。这是一种必要的延迟释放的方式,因为我们有时候需要确保在方法内部初始化的生成的对象在被返回后别人还能使用,而不是立即被释放掉。
在Objective-C中,建立一个自动释放池的语法很简单,使用@autoreleasepool就行了。如果你新建一个Objective-C项目,可以看到main.m中就有我们刚才说到的整个项目的autoreleasepool:

int main(int argc, char *argv[]) {  
    @autoreleasepool {  
        int retVal = UIApplicationMain(  
            argc,   
            argv,   
            nil,   
            NSStringFromClass([AppDelegate class]));  
        return retVal;  
    }  
}  

更进一步,其实@autoreleasepool在编译时会被展开为NSAutoreleasePool,并附带drain方法的调用。

而在Swift项目中,因为有了@UIApplicationMain,我们不再需要main文件和main函数,所以原来的整个程序的自动释放池就不存在了。即使我们使用main.swift来作为程序的入口时,也是不需要自己再添加自动释放池的。

但是在一种情况下我们还是希望自动释放,那就是在面对在一个方法作用域中要生成大量的autorelease对象的时候。在Swift 1.0时,我们可以写这样的代码:

func loadBigData() {  
    if let path = NSBundle.mainBundle()  
        .pathForResource("big", ofType: "jpg") {  
        for i in 1...10000 {  
            let data = NSData.dataWithContentsOfFile(  
                path, options: nil, error: nil)  
            NSThread.sleepForTimeInterval(0.5)  
        }          
    }  
}  

dataWithContentsOfFile返回的是autorelease的对象,因为我们一直处在循环中,因此它们将一直没有机会被释放。如果数量太多而且数据太大的时候,很容易因为内存不足而崩溃。在Instruments下可以看到内存alloc的情况:
这显然是一幅很不妙的情景。在面对这种情况的时候,正确的处理方法是在其中加入一个自动释放池,这样我们就可以在循环进行到某个特定的时候施放内存,保证不会因为内存不足而导致应用崩溃。在Swift中我们也是能使用autoreleasepool的——虽然语法上略有不同。相比于原来在Objective-C中的关键字,现在它变成了一个接受闭包的方法:

func autoreleasepool(code: () -> ())  

利用尾随闭包的写法,很容易就能在Swift中加入一个类似的自动释放池了:

func loadBigData() {  
    if let path = NSBundle.mainBundle()  
        .pathForResource("big", ofType: "jpg") {  
        for i in 1...10000 {  
            autoreleasepool {  
                let data = NSData.dataWithContentsOfFile(  
                    path, options: nil, error: nil)  
                NSThread.sleepForTimeInterval(0.5)  
            }  
        }          
    }  
}   

这样改动以后,内存分配就没有什么忧虑了:
这里我们每一次循环都生成了一个自动释放池,虽然可以保证内存使用达到最小,但是释放过于频繁也会带来潜在的性能忧虑。一个折中的方法是将循环分隔开加入自动释放池,比如每10次循环对应一次自动释放,这样能减少带来的性能损失。

其实对于这个特定的例子,我们并不一定需要加入自动释放。在Swift中更提倡的是用初始化方法而不是用像上面那样的类方法来生成对象,而且在Swift 1.1中,因为加入了可以返回nil的初始化方法,像上面例子中那样的工厂方法都已经从API中删除了。今后我们都应该这样写:

let data = NSData(contentsOfFile: path)  

使用初始化方法的话,我们就不需要面临自动释放的问题了,每次在超过作用域后,自动内存管理都将为我们处理好内存相关的事情。
转载自:http://www.csdn.net/article/2015-03-04/2824102

xcode提示App Transport Security has blocked a cleartext HTTP (http://) resource load的解决办法

今天开发中,遇到下问题,Xcode提示如下:
“App TransportSecurity has blocked a cleartext HTTP (http://) resource load since it isinsecure. Temporary exceptions can be configured via your app's Info.plistfile.”
简而言之:ATS禁止了HTTP的明文传输,因为它不安全。可以修改Info.plist文件,让它临时允许明文传输。
解决办法:
在Info.plist文件中添加"App Transport SecuritySettings", Type为"Dictionary",再添加"Allow Arbitray Loads", Type 为"Boolean",“Value”为“YES”即可。
转载自:http://www.zhimengzhe.com/IOSkaifa/1852.html

ios互斥锁

//
//  ViewController.swift
//  多线程
//
//  Created by admin on 16/2/17.
//  Copyright © 2016年 jin. All rights reserved.
//

import UIKit

class ViewController: UIViewController {
    var ticketsNumber = 20
    override func viewDidLoad() {
        super.viewDidLoad()
    }
    override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {
        let threadA = NSThread(target: self, selector: "buyTicket", object: nil)
        threadA.name = "售票员A"
        threadA.start()
        let threadB = NSThread(target: self, selector: "buyTicket", object: nil)
        threadB.name = "售票员B"
        threadB.start()
    }
    // 模拟卖票
    func buyTicket()
    {
        /**
        注意点:
        1.锁定的代码尽量少
        2.加锁范围内的代码同一时间只允许一个程序执行
        3.继承自NSObject的类都可以作为互斥锁的参数
        4.要保证所有的线程访问到这个锁,并且所有的线程访问的都是同一个锁对象
        */
        while(self.ticketsNumber > 0)
        {
            sleep(1)
            // 锁
            objc_sync_enter(self)
            print(NSThread.currentThread().name! + "卖出了\(self.ticketsNumber)号票")
            self.ticketsNumber--
            // 解锁
            objc_sync_exit(self)
        }
    }
}

NSThread使用以及基本属性

//
//  ViewController.swift
//  多线程
//
//  Created by admin on 16/2/17.
//  Copyright © 2016年 jin. All rights reserved.
//

import UIKit

class ViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()
    }
    override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {
        self.threadStatus()
    }
    // 线程状态
    func threadStatus()
    {
        // 线程的状态有:就绪,运行,死亡,阻塞
        let thread = NSThread(target: self, selector: Selector("threadStatusRun:"), object: nil)

        // 放到可调度的线程池,等到被调度,就绪状态
        thread.start()
    }
    // 线程状态测试方法
    func threadStatusRun(parameter:AnyObject? = nil)
    {
        // 进入阻塞状态
        // 阻塞指定的时间
        //NSThread.sleepForTimeInterval(5)
        // 阻塞到指定的日期
        //NSThread.sleepUntilDate(NSDate(timeIntervalSinceNow: 5))
        // 退出,进入死亡状态
        NSThread.exit()
        print(parameter)
        for(var i = 1;i < 10000;i++)
        {
            // 打印当前线程  <NSThread: 0x7fd6ab50f480>{number = 2, name = (null)}
            print(NSThread.currentThread())
        }
    }
    // 线程属性
    func threadAttr()
    {
        let thread = NSThread(target: self, selector: Selector("run:"), object: "jin")
        // 优先级,一般不需要设置
        thread.threadPriority = 0.1
        // 名字
        thread.name = "jin"
        thread.start()
    }
    // 创建子进程的方式A和b比较方便(隐式创建),但是不能设置线程的详细的属性
    func createThreadA()
    {
        NSThread.detachNewThreadSelector(Selector("run:"), toTarget: self, withObject: nil)
    }
    func createThreadB()
    {
        self.performSelectorInBackground(Selector("run:"), withObject: nil)
    }
    // 可以设置线程的属性
    func createThreadC()
    {
        let thread = NSThread(target: self, selector: Selector("run:"), object: nil)
        thread.start()
    }
    // 测试方法
    func run(parameter:AnyObject? = nil)
    {
        print(parameter)
        for(var i = 1;i < 10000;i++)
        {
            // 打印当前线程  <NSThread: 0x7fd6ab50f480>{number = 2, name = (null)}
            print(NSThread.currentThread())
        }
    }
}

swift使用pthread

//
//  ViewController.swift
//  多线程
//
//  Created by admin on 16/2/17.
//  Copyright © 2016年 jin. All rights reserved.
//

import UIKit

class ViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()
    }
    override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {
        // 在当前线程中执行循环,在循环结束之前,界面会卡住
//        self.long()
        // 在子进程中执行循环,界面不会卡住
//        self.performSelectorInBackground("long", withObject: nil)
        self.start()
    }

    func start()
    {
        // 初始化需要的属性
        var pthread = pthread_t()
        var pthreadAttr = pthread_attr_t()
        var returnValue = pthread_attr_init(&pthreadAttr)
        returnValue = pthread_attr_set_qos_class_np(&pthreadAttr, QOS_CLASS_USER_INTERACTIVE, 0)
        // 线程执行的函数
        func run(x:UnsafeMutablePointer<Void>)->UnsafeMutablePointer<Void>
        {
            for(var i = 1;i < 10000;i++)
            {
                // 打印当前线程  <NSThread: 0x7fd6ab50f480>{number = 2, name = (null)}
                print(NSThread.currentThread())
                print(i)
            }
            return nil
        }
        // 闭包
//        pthread_create(&pthread, &pthreadAttr, { (x:UnsafeMutablePointer<Void>) in
//            for(var i = 1;i < 10000;i++)
//            {
//                // 打印当前线程  <NSThread: 0x7fd6ab50f480>{number = 2, name = (null)}
//                print(NSThread.currentThread())
//                print(i)
//            }
//            return nil
//        }, nil)
        /**
        (要开的线程变量,线程的属性,线程执行的函数,需要传递的参数)
        */
        // pthread_create(<#T##UnsafeMutablePointer<pthread_t>#>, <#T##UnsafePointer<pthread_attr_t>#>, <#T##((UnsafeMutablePointer<Void>) -> UnsafeMutablePointer<Void>)!##((UnsafeMutablePointer<Void>) -> UnsafeMutablePointer<Void>)!##(UnsafeMutablePointer<Void>) -> UnsafeMutablePointer<Void>#>, <#T##UnsafeMutablePointer<Void>#>)

        // 函数,用self.run就报错。。。。
        pthread_create(&pthread, &pthreadAttr, run, nil)
    }

    func run(x:UnsafeMutablePointer<Void>)->UnsafeMutablePointer<Void>
    {
        for(var i = 1;i < 10000;i++)
        {
            // 打印当前线程  <NSThread: 0x7fd6ab50f480>{number = 2, name = (null)}
            print(NSThread.currentThread())
            print(i)
        }
        return nil
    }
    func long()
    {
        for(var i = 1;i < 100000;i++)
        {
            // 打印当前线程  <NSThread: 0x7fd6ab50f480>{number = 2, name = (null)}
            print(NSThread.currentThread())
            print(i)
        }
    }
}