随着博客越写越多,不免会遇到须要插入图片来讲明的状况。git
首先调研了市面上的图床服务,本着稳定长期的目标,过滤掉了打一枪换一个地方的野鸡小网站,剩余比较靠谱的优缺点以下。github
图床 | 优势 | 缺点 |
---|---|---|
腾讯云 | 免费 无需域名 | 将来可能会收费 |
七牛 | 免费 | 须要域名和备案 |
又拍云 | 免费 无需域名 | 将来可能会收费 |
阿里云 | 目前最完备 | 收费 须要域名 |
微博 | 免费 无需域名 | 不稳定 匿名上传 |
做为一个刚起步的小博客,应该把精力更多关注于内容,之后再考虑域名备案或者大流量套餐,所以尽可能选择免费的图床。 实际上是穷算法
微博做为国内数一数二的流量大户,其图床的CDN和质量确定没有问题,可是上传图片会自带水印,且匿名上传总以为不靠谱。编程
剩下的选择还有两个,又拍云进军对象存储领域比腾讯云早并且更成熟,可是就规模和技术来讲,我仍是更愿意相信腾讯。swift
注册完腾讯云帐号后,下一个问题就是怎么更方便的将图床与 MarkDown 结合起来使用,提升效率和体验。安全
iPic 完美符合个人需求,这是一款 Mac 上的状态栏软件,支持上传本地图片到设定的图床,获取图片地址后按照 
格式复制到剪贴板。markdown
那么好的应用为啥不用呢?编程语言
由于不想按年交钱。应用默认是微博图床,若是要使用其余图床就须要购买专业版,每一年60元。若是是一次买断的话,也就买了,年费内心总有疙瘩 矫情。工具
忽然,我就想到! 本身开发一个! 闲的蛋疼oop
开发iPhone
应用已经好多年了,还从未开发过Mac
上的状态栏软件,正好还能锻炼下Swift
,因而说干就干。没想到开发了一个月
产品使用逻辑基本与 iPic 一致,基于状态栏交互,选择png
jpg
文件上传。
能够设置是否压缩图片,压缩会压到500K
如下。
还须要有一个登陆界面记录腾讯云的帐号和存储库信息。
文件上传成功后,弹出通知提醒,并复制到剪贴板。
若是不慎复制了其余文本致使丢失了连接,再点击一次通知就能够从新获取。
第一关就是编程语言。
虽然也曾系统的学过Swift
,但因为常年使用Objective-C
开发,思惟方式还转不过来。
比较明显的区别就是处理空变量的方式。
在ObjC
中,指针变量能够是nil
(也就是0),对nil
执行方法不会发生任何事情,所以能够算是部分安全。
Swift
对待空变量更严格,!
修饰的变量必须有具体值,?
修饰的变量才具备空值的可能性。
nil
再也不表示为空对象,而是一个空值,向空值调用方法会致使闪退。对待?
修饰的变量必需要当心,最好先判断是否有值再使用,好在有语法糖能够解决这类问题。
//默认为nil var money : String? //变量有值 money = "million" //判断确定有值后再使用 if money != nil { print("I have \(money!) dollars.") } //保证变量有值并赋值给安全变量后执行 if let account = money { print("I have \(account) dollars.") } //变量若是没有值就执行else事件并return guard let account = money else { print("I have no money.") } print("I have \(account) dollars.") 复制代码
合理使用! ?
会使咱们的代码更安全与简洁。
Swift 的 nil 和 Objective-C 中的 nil 并不同。在 Objective-C 中,nil 是一个指向不存在对象的指针。在 Swift 中,nil 不是指针——它是一个肯定的值,用来表示值缺失。任何类型的可选状态均可以被设置为 nil,不仅是对象类型。
ObjC
有 @throw
的用法,可是根据苹果官方的描述,执行的成本很大。究其缘由在于 ObjC
基于 C
语言而不是 C++
,因此只能使用 setjmp()
和longjmp()
方法实现,所以可能会形成内存泄漏。
Important: Exceptions are resource-intensive in Objective-C. You should not use exceptions for general flow-control, or simply to signify errors (such as a file not being accessible)
Swift
从根本解决了这个问题,并结合枚举优化了整个流程。
enum CompressError : Error { case NoImage case OverSize(size : Int) } func compressImage(_ imageData: Data?) throws -> Data? { guard var compressData = imageData else { throw CompressError.NoImage } if compressData.count > maxSize { throw CompressError.OverSize(size: compressData.count) } } func uploadImage(_ imageData: Data?) { var compressData : Data? = nil do { compressData = try self.compressImage(imageData) } catch CompressError.NoImage { print("Image Not Exist") } catch CompressError.OverSize(let size) { print("Image over size of \(size)") } catch _ {} //简洁的方式,忽略处理警告 let compressData = try? self.compressImage(imageData) } 复制代码
利用Swift
强大的枚举类型,能够定制化警告从而传递出咱们须要的信息,使得整个流程更为顺畅。
语法还支持 try?
忽略警告获取一个可能为空值的变量,若是自信绝对不会抛出异常的话,还能使用try!
获取一个确定值。
实际编写Cocoa
代码过程当中,发现与UIKit
相差仍是比较多的。
UIKit
的层级通常是 UINavigationController -> UIViewController
Cocoa
的层级则不太同样,NSWindowController -> NSViewController
缘由也很简单,手机上通常只有一个窗口,依靠导航栏进行页面跳转。可是桌面端逻辑就不太同样,新页面通常都是以新窗口的形式弹出。
其次桌面端拥有特定的状态栏控件NSMenu
,在其中操做菜单项也是一个新的挑战。
因为腾讯云只提供了iOS
的库,因此我还须要先把库文件从新调整为Cocoa
代码。 这一部分也是吃了很多苦头,须要把设备相关的代码与应用、进出后台的通知等都去除,还要处理相似功能的转换(好比UIImage -> NSImage
)。
同时还有第二个坑,腾讯云的库都是ObjC
代码,因此须要混编。
建立一个工做空间后拖入两个工程,在主工程的 Targets / Build Phases / Embed Frameworks
中加入SDK库。
接着在Swift
工程中建立Project-Bridging-Header.h
头文件,在其中引用SDK库。
最后在 Targets / Build Settings / Objective-C Bridging Header
设置头文件,就能够解决代码混编的问题。
其原理在于自动建立了基于头文件的pch
,把头文件中引用到的ObjC
代码,都桥接到工程中。
之因此不使用现成的软件还有一个缘由,就是我想本身控制压缩图片的参数和效果。
经过调研和实验图片压缩效果,最终我选择压制成jpg
格式,500k
大小限制,压缩率限制为最小0.75
,等比宽度限制为1280px
。
文首那张美女图,初始是1.9M 5087x3661
,因为尺寸过大,第一次压缩图片质量后,容量反而增长到了2.4M
。
将宽高等比缩小到1280x922
,图片又变大了,此次增长到了4.7M
。(改变宽高须要新建一张画布,建立时必需要有alpha通道等其余设置,因此会变大)
咱们接着压缩,最终在压缩率为0.9
的状况下把图片压到了260K
,成功达到了目标。
距离上一次博客已经有两个月的间隔,其中一部分缘由在于生活上的一些变故,另外一个缘由就在于不熟悉 Cocoa + Swift
开发。
好在最终仍是啃出来了,Github项目已开源,欢迎你们指点与吐槽。
此次项目最大的收获在于脱离本身的温馨区。人的本性包含惰性,老是趋向于在熟悉的领域干熟悉的活。可是就和企业同样,不创新就死,技术不断在发展,若是没有跟上潮流,最终就会被淘汰。以此共勉!