Framework的那些事

作者: 晚雪浓情 | 来源:发表于2016-11-08 13:34 被阅读108次

    写在前面:
    回想了一下这个项目,接手到现在也就是一个多月,真正难过的或许也只是理解Java代码并变成Swift,和后面联调的过程。多的不说,记录一下遇到的问题,争取能巩固,提高技术。


    还需要一点点前奏:
    现在Framework的制作方法真是,只要你想找,总有你要的。所以我挑了一个内容丰富一点的,供您参考。iOS 制作静态库 .a 文件 和 .framework 文件 以及解决第三方库冲突问题 (转载 mark 一下) - Luck_Developer的博客 - 博客频道 - CSDN.NET


    进入正题:
    那么现在,一个空的Framework应该已经被搭建完成并且编译通过了。其实本来我也只是想讲讲代码问题 :)。不得不说,关键在于,Swift严格的类型检查给我在调用C的Api的时候带来了不少小麻烦。


    Q1.Java的[Byte]如何在Swift中实现?
    A: Java的Byte数据类型,真身就是Int8。那么,我们只要:

    typealias Byte = Int8
    

    然后给String加一个扩展方法就可以啦

    extension String
    {
        func getBytes()->[Byte]
        {
            var byteArray = [Byte]()
            
            for char in utf8
            {
                byteArray.append(Byte(char))
            }
            
            return  byteArray
        }
    }```
    *****
    Q2.Java字符串的```trim```方法如何在Swift中实现?
    A:  同样只要给String加一个扩展方法
    

    extension String
    {
    func trim()->String
    {
    return contains(" ") ? trimmingCharacters(in: CharacterSet(charactersIn: " ")) : self
    }
    }

    *****
    Q3.那么,有时候Swift会把C的Api中,Java的```Byte```类型,识别成```UInt8```,导致参数要求是```[Byte]```,实际必须传```[UInt8]```(Swift:没错,我说它是```UInt```,你就得传```UInt```!),怎么破?
    A:  多的不说见代码。**不过,千万不要轻易尝试类似如下的代码:** 
    

    let num1:Int8 = 0
    let num2 = UInt8(num1)

    __正确的⬇️⬇️__
    

    func toInt8Array(arr:[UInt8])->[Int8]
    {
    var temp = Int8
    for c in arr
    {
    temp.append(Int8(bitPattern: c))
    }
    return temp
    }

    func toUInt8Array(arr:[Int8])->[UInt8]
    {
    var temp = UInt8
    for c in arr
    {
    temp.append(UInt8(bitPattern: c))
    }
    return temp
    }

    
    

    而且,我不会说我把好的东西都放在后面。

    *****
    Q4.Java中,arrayCopy这样的操作在Swift中如何实现?
    A: 确实拿到手后纠结了一小会。多的不说你们自己看代码
    
    

    func arrayCopy<T>(src:Array<T>,srcPos:Int,dest:Array<T>,destPos:Int,length:Int)->Array<T>
    {
    var temp = dest

    for i in 0..<length
    {
        if i < src.count
        {
            temp[destPos + i] = src[srcPos + i]
        }
    }
    return temp
    

    }

    这里写了一个__泛型__函数,不知道什么是泛型以及在这个函数中作用的,请问问度娘,她会教你的:)
    *****
    __Q5.各种算法__
    一直很赞同算法是一个好程序的灵魂。
    **Base64---Encode:**
    

    internal func base64Encode(array:[UInt8])->String
    {
    return Data.init(bytes: array, count: array.count).base64EncodedString(options: Data.Base64EncodingOptions.endLineWithLineFeed)
    }
    internal func base64Encode(array:[Int8])->String
    {
    return Data.init(bytes: array, count: array.count).base64EncodedString(options: Data.Base64EncodingOptions.endLineWithLineFeed)
    }

    By the way,```internal```关键字是因为我写在了一个单独的文件中,不熟悉的可以去查一下访问控制。这里写两个方法呢,也只是为了应付@Swift,(sad face)
    **Base64---Decode:**
    

    internal func base64Decode(base64String:String)->[UInt8]
    {
    let data = Data.init(base64Encoded: base64String, options: Data.Base64DecodingOptions.ignoreUnknownCharacters)!

    var tempArr = [UInt8]()
    
    for i in 0..<data.count
    {
        tempArr.append(data[i])
    }
    return tempArr
    

    }

    so,不要问我代码里为什么直接```!```,而不用```if let { }```或者```guard let else { throw }```,我相信你注意到了形参名是什么~
    
    **SHA1**
    

    internal func sha1(string: String) -> String
    {
    var Sha1Result = ""

    if let data = string.data(using: String.Encoding.utf8)
    {
        var digest = [UInt8](repeating: 0, count: Int(CC_SHA1_DIGEST_LENGTH))
        
        CC_SHA1((data as NSData).bytes, CC_LONG(data.count), &digest)
    
        
        for index in 0..<CC_SHA1_DIGEST_LENGTH
        {
            Sha1Result += String(format: "%02x", digest[Int(index)])
        }
    }
    return Sha1Result
    

    }

    **CRC32**
    �偷偷懒,拿个OC的凑合用吧,记得导入<zlib.h>
    
    • (uint32_t)CRC32Value
      {
      uLong crc = crc32(0L, Z_NULL, 0);
      crc32(crc, self.bytes, self.length);
      return crc;
      }
    *****
    Q6.那么,序列化
    A: 当我一开始知道,要将一个未知的模型转化成JSON的时候,其实我的心里是拒绝的。OC有MJExtension,Swift有Reflect了,拿来主义不就行了!但是在Framework里导入别人的框架不到万不得已,个人觉得还是不要这么干,原因有三,1.自己把握方法实现,出Bug了好查一点。2.还要做必要的配置工作,3.文件夹在明里会多3个文件。。好吧总结123就是,懒懒懒。
    那么,希望你们碰到这样需求的时候不会苦逼的要抽方法,抽模型出来调试:
    

    extension NSObject
    {
    func getProperty() throws ->[String:Any?]
    {
    struct getPropertyError: Error
    {
    var ErrorReason:String

            init(reason:String)
            {
                ErrorReason = reason
            }
        }
        
        var props = [String:Any?]()
        
        var outCount:UInt32 = 0
        
        if let properties = class_copyPropertyList(classForCoder, &outCount)
        {
            for i in 0..<outCount
            {
                if let name = String(cString: property_getName(properties[Int(i)]), encoding: String.Encoding.utf8),let value = value(forKey: name)
                {
                    props[name] = value
                }
                else
                {
                    //不能允许转换不完全
                    throw getPropertyError(reason:"转换失败")
                }
            }
        }
        return props
    }
    

    }

    *****
    Q7. 最后的最后,网络部分。
    A: 模型变字典,然后愉快的(~~并不~~)变成了JSON之后,我们要和服务器通讯了。Java�如果用流式传输,就是创建```Stream```对象然后用```read```or```write```方法给服务器传输数据,oh,no!To be frank,不习惯。怎么办?
    我们有```URLSession```.
    
    举个POST方法的例子吧。
    First:定义一个```URLRequest```,设置
    

    req.httpMethod = "POST"

    然后把要上传的数据准备好,这个例子就讲完了。(完结撒花,此处有没有👏不重要)
    *****
    
    “Wait,URLSession方法是异步的呀,放在有返回值的方法里,回调还没执行,方法就return啦!”
    “......”
    
     //创建信号量
     let semaphore = DispatchSemaphore(value: 0)  
    
     URLSession.shared.uploadTask(with: req, from: data, completionHandler: {
            (resData, response, error) in            
            /*do something */
    
            //�终于等到你 还好我没放弃
            semaphore.signal()
        }).resume()
         
        //如果要给等待加一个期限 我希望是永远  
        _ = semaphore.wait(timeout: DispatchTime.distantFuture)
    
    *****
    到这里基本上所有的大坑都踩完了。剩下的整理整理想一想遗漏的再更新啦,谢谢看到这里的人,希望你们喜欢,也希望对你们有帮助。
    如果觉得写的入得了各位看官老爷的法眼,请不要吝啬点个赞,Thank u very much!💗
    *****
    **最后感谢**[@xiaoheng](http://www.jianshu.com/users/bafc9a0f5df2/timeline),[@瑾瑾小泉](http://www.jianshu.com/users/d7ffbe4ce951)两位在闲暇时刻的讨论支持:)

    相关文章

      网友评论

      • 某非著名程序员:framework里的第三方与别人软件第三方冲突何解?
        晚雪浓情:@260d120058f7 不好意思现在才回。 我当时接这个SDK的项目之前就考虑过了,能不用尽量不用三方,原因比较简单,不好调试,不好配置,不好写文档。而且兼容性这个肯定是SDK必须为客户考虑的问题,所以就只能自己苦逼一点了。所以我这里面除了Keychain不是自己写的基本上都是手打的 :joy: 像上面那些方法只能各种尝试各种查资料 没办法呀
        某非著名程序员:@260d120058f7 有好的方法不
        晚雪浓情:@260d120058f7 这个问题很复杂。。看你怎么取舍吧 :joy:

      本文标题:Framework的那些事

      本文链接:https://www.haomeiwen.com/subject/kqeauttx.html