Swift小技巧(四)

所有小技巧都是基于Swift3

1.如何判断运行的设备类型,比如是iPad还是iPhone

        //判断设备类型,iPad或者iPhone
        if UIDevice.current.userInterfaceIdiom == .pad {
            print("设备是iPad")
        }else if UIDevice.current.userInterfaceIdiom == .phone {
            print("设备是iPhone")
        }

2.如何使用Timer

//创建timer,创建好5S后,会执行指定的方法,并且附带了userinfo信息,该信息可以不带
var timer: Timer? = Timer.scheduledTimer(timeInterval: 5, target: self, selector: #selector(show(timer:)), userInfo: ["custom":"msg"], repeats: false)

func show(timer: Timer) {
        print(Date())
        //打印出附带信息
        print(timer.userInfo)
    }

//销毁timer
if let time = timer {
        //销毁timer需要调用invalidate,并且,可以把timer置为nil
        time.invalidate()
        timer = nil
}

3.如何快速给方法、属性等添加文档

首先,写出方法或属性

func chreatString(name: String) -> String {
        return "你好,\(name)"
    }

然后在方法上一行使用:command + option + / 快捷键,会出现如下所示:

    /// <#Description#>
    ///
    /// - parameter name: <#name description#>
    ///
    /// - returns: <#return value description#>
    func chreatString(name: String) -> String {
        return "你好,\(name)"
    }

依次填入对应的值

    /// 生成一句话
    ///
    /// - parameter name: 名字
    ///
    /// - returns: 返回生成的话
    func chreatString(name: String) -> String {
        return "你好,\(name)"
    }

然后点击该方法,就能在属性观察器中查看到文档了

屏幕快照 2017-05-03 上午10.59.21.png

4.将数组内元素组装成各种需求的字符串

let array: [Character] = ["1","2","3"]
        //将一个字符数组依次组装成字符串,没有间隔
        print(String(array))//123
        
        let array2 = ["12","34","56"]
        //将一个字符串数组依次组装成字符串,没有间隔
        print(String(array2.flatMap { String.CharacterView($0) } ))
        //或者
        print(array2.joined())//123456
        
        //将一个字符串数组依次组装成字符串,有指定间隔字符
        print(array2.joined(separator: "-"))//12-34-56

        //将一个字符串数组依次拆开,并且指定间隔字符
        let string = array2.flatMap { String.CharacterView($0) }.map { String($0) }
        print(string.joined(separator: ","))//1,2,3,4,5,6
        
        //将一个float数组,组装成一个字符串,指定间隔字符
        let floatArray = [1, 2, 3, 4]
        let stringArray = floatArray.flatMap { String($0) }
        print(stringArray.joined(separator: "-"))//1-2-3-4

///////////////////////////////////////////////
//如果只是想简单的知道数组的内容,那么,使用description即可
        let arr = [1, 2, 3]
        print(arr.description)//[1, 2, 3]
        //特别的,如果是自定义的类,也想能够这样子打印出来,只需要重写description属性,即可实现
        let array = [Test(name: "a", age: 11), Test(name: "b", age: 22), Test(name: "c", age: 33)]
        print(array.description)
        //没有重写description属性,打印如下:[<_TtCC1s14ViewController4Test: 0x600000254730>, <_TtCC1s14ViewController4Test: 0x6000002546d0>, <_TtCC1s14ViewController4Test: 0x600000254700>]
        //重写后,打印如下:[a--11, b--22, c--33]

    class Test: NSObject{
        let name: String
        let age: Int
        
        init(name: String, age: Int) {
            self.name = name
            self.age = age
        }
        
        override var description: String {
            return "\(name)--\(age)"
        }
    }

5.使用try?和try!处理异常

//会抛出异常的方法
func someThrowingFunction() throws -> Int {}

//可以使用try?来调用,如果没有抛出异常,则返回x=Int?类型的值,抛出异常,则x=nil
let x = try? someThrowingFunction()
//try?和下方的代码是等价的
let y: Int?
do {
    y = try someThrowingFunction()
} catch {
    y = nil
}

//try!则是,如果抛出异常,程序会终止,不抛出,则返回解包后的值。try!用于100%确定不会抛出异常时使用

6.如何判断一个变量是否是某个类型

class Test {}

let test = Test()

print(type(of: test))//Test
print(Test.self)//Test
type(of: test) == Test.self//true

//判断Array
let arr = [1, 3]
type(of: arr) == Array<Int>.self//true

7.class和static的区别

class和static都表示类属性或者类方法。区别在于

class A {
    class func func1() -> String {
        return "1"
    }
    static func func2() -> String {
        return "2"
    }
}
class B: A {
    //正常使用,不会报错
    override class func func1() -> String {
        return "a"
    }
    //会报错,那是因为不能够重写static修饰的类方法
    override static func func2() -> String {
        return "b"
    }
    //可以看出,static相当于就是class final,不能够被重写
}

8.解决给UIImageView添加手势事件,无法触发的问题

let image = UIImageView(frame: CGRect(x: 20, y: 100, width: view.frame.width-40, height: 100))
        //必须要设置isuserinteractionenable为true时,才能触发手势事件
        image.isUserInteractionEnabled = true
        view.addSubview(image)
        let tap = UITapGestureRecognizer(target: self, action: #selector(tap(gr:)))
        image.addGestureRecognizer(tap)

func tap(gr: UITapGestureRecognizer) {
        print("点击了")
    }

9.如何使用NSLocalizedString加载内容

//首先,扩展一个方法
extension String {
    func localized(withComment:String) -> String {
        return NSLocalizedString(self, tableName: nil, bundle: Bundle.main, value: "", comment: withComment)
    }
}

//在 .strings文件中添加
/* with !!! */
"Hi" = "Привет!!!";

//使用
myLabel.text = "Hi".localized(withComment: "with !!!")

10.data与string互相转换

//data->string
let dataStr = String(data: data, encoding: .utf8)
//string->data
let data = "DataString".data(using: .utf8)

11.如何判断app是否是首次打开

//如何记录用户是否是第一次打开app
let userDefaults = UserDefaults.standard
if userDefaults.bool(forKey: "hasRunBefore") == false {
    //可以在这里清空以前保存的钥匙串的内容,或者做别的操作,比如加载首次打开的欢迎界面等
    
    //接下来更新userdefaults
    userDefaults.set(true, forKey: "hasRunBefore")
    userDefaults.synchronize()
}

12.保留指定位数的小数,进行四舍五入

extension Double {
    //保留指定位小数,四舍五入
    func roundTo(places: Int) -> Double {
        let divisor = pow(10.0, Double(places))
        return (self * divisor).rounded() / divisor
    }
}
let x = 0.123456.roundTo(places: 5)//0.12346

13.GCD实现子线程执行任务

//后台执行操作
DispatchQueue.global(qos: .background).async {
    print("子线程执行")
    DispatchQueue.main.async {
        print("子线程执行")
    }
}

//可以扩展一个方法,增加延时和执行完成后的回调处理
extension DispatchQueue {
    static func background(delay: Double = 0.0, background: (()->Void)? = nil, completion: (() -> Void)? = nil) {
        DispatchQueue.global(qos: .background).async {
            background?()
            if let completion = completion {
                DispatchQueue.main.asyncAfter(deadline: .now() + delay, execute: {
                    completion()
                })
            }
        }
    }
}
//使用
DispatchQueue.background(delay: 3.0, background: {
    //后台要执行的操作
    }, completion: {
        //后台执行完成后,延时3秒执行回调
})

DispatchQueue.background(background: {
    //后台要执行的操作
    }, completion:{
        //后台执行完成后,就执行回调
})

DispatchQueue.background(delay: 3.0, completion:{
    //不需要后台执行任何操作,延时3秒执行回调
})

14.oc中的isKindOfClass方法,在swift中如何使用

//在OC中,这样使用
if ([touch.view isKindOfClass: UIPickerView.class]) {
}
//swift中,使用is
let x: Any = "x"
if x is String {
    print("true")
}

15.如何实现nsrange与range之间的互相转换

extension String {
    func nsRange(from range: Range<String.Index>) -> NSRange {
        let from = range.lowerBound.samePosition(in: utf16)
        let to = range.upperBound.samePosition(in: utf16)
        return NSRange(location: utf16.distance(from: utf16.startIndex, to: from),
                       length: utf16.distance(from: from, to: to))
    }
}

extension String {
    func range(from nsRange: NSRange) -> Range<String.Index>? {
        guard
            let from16 = utf16.index(utf16.startIndex, offsetBy: nsRange.location, limitedBy: utf16.endIndex),
            let to16 = utf16.index(utf16.startIndex, offsetBy: nsRange.location + nsRange.length, limitedBy: utf16.endIndex),
            let from = from16.samePosition(in: self),
            let to = to16.samePosition(in: self)
            else { return nil }
        return from ..< to
    }
}
//使用
let str = "a👿b🇩🇪c"
let r1 = str.range(of: "🇩🇪")!

// range -> NSRange:
let n1 = str.nsRange(from: r1)
print((str as NSString).substring(with: n1)) // 🇩🇪

// NSRange -> range:
let r2 = str.range(from: n1)!
print(str.substring(with: r2)) // 🇩🇪

16.如何生成UUID

let uuid1 = UUID().uuidString

17.如何实现base64string与string之间的互相转换

let plainString = "你好"
//string -> base64string
let plainData = plainString.data(using: .utf8)
let base64string = plainData?.base64EncodedString()
print(base64string!)//5L2g5aW9

//base64string -> string
if let decodedData = Data(base64Encoded: base64string!) {
    let decodedString = String(data: decodedData, encoding: .utf8)
    print(decodedString!)//你好
}

18.如何将十六进制字符串#ffffff或ffffff字符串转换成相应的uicolor实例

//将#ffffff或ffffff字符串转换成响应的uicolor实例
func hexStringToUIColor (hex:String) -> UIColor {
    var cString:String = hex.trimmingCharacters(in: .whitespacesAndNewlines).uppercased()
    
    if (cString.hasPrefix("#")) {
        cString.remove(at: cString.startIndex)
    }
    
    if ((cString.characters.count) != 6) {
        return UIColor.gray
    }
    
    var rgbValue:UInt32 = 0
    Scanner(string: cString).scanHexInt32(&rgbValue)
    
    return UIColor(
        red: CGFloat((rgbValue & 0xFF0000) >> 16) / 255.0,
        green: CGFloat((rgbValue & 0x00FF00) >> 8) / 255.0,
        blue: CGFloat(rgbValue & 0x0000FF) / 255.0,
        alpha: CGFloat(1.0)
    )
}
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,372评论 6 498
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,368评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 162,415评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,157评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,171评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,125评论 1 297
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,028评论 3 417
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,887评论 0 274
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,310评论 1 310
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,533评论 2 332
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,690评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,411评论 5 343
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,004评论 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,659评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,812评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,693评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,577评论 2 353

推荐阅读更多精彩内容

  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 134,651评论 18 139
  • 1. Java基础部分 基础部分的顺序:基本语法,类相关的语法,内部类的语法,继承相关的语法,异常的语法,线程的语...
    子非鱼_t_阅读 31,622评论 18 399
  • 我下了车,点上一根烟,深吸一口气,肺中挤进了凛冽的冰凌。 路旁是光秃秃的黄土山,一束昏黄的灯光从远处打过来...
    奈何桥上唱小苹果阅读 374评论 0 0
  • 不知你是否遇到过这样的困境,看上一件衣服,红色穿着显大气,米色穿着显优雅,然后就在红色和米色之间来回徘徊,脑子里突...
    水清浅阅读 736评论 0 0