background
As you blog more and more, it’s inevitable that you’ll have to insert images to illustrate.
Figure bed choice
First of all, I investigated the map bed service on the market. In line with the goal of stability and long-term, I filtered out the small pheasant website that played a gun to change a place. The remaining reliable advantages and disadvantages are as follows.
Figure bed | advantages | disadvantages |
---|---|---|
Tencent cloud | Free domain name | There may be charges in the future |
Seven cattle | free | Domain name and registration required |
And take the cloud | Free domain name | There may be charges in the future |
Ali cloud | At present most complete | Charge for domain name |
Free domain name | Unstable anonymous upload |
As a small blog starting up, you should pay more attention to content, and then consider domain name registration or large data plan, so try to choose free chart bed. Is really poor
As one of the largest traffic users in China, Weibo certainly has no problem with the CDN and quality of its picture bed. However, uploaded pictures will have their own watermarks, and anonymous uploading always feels unreliable.
There are still two options left, and paiyun entered the object storage field earlier and more mature than Tencent Cloud, but in terms of scale and technology, I still prefer to believe Tencent.
tool
After registering Tencent cloud account, the next problem is how to combine Chart bed and MarkDown more conveniently to improve efficiency and experience.
IPic perfectly meets my needs, this is a Mac status bar software, support to upload local pictures to the set graph bed, after obtaining the picture address according to! [](URL) format copy to clipboard.
So why not use a good app?
Because I don’t want to pay yearly. The default application is weibo map bed, if you want to use other map bed you need to buy professional version, 60 yuan per year. If it is a buyout, also bought, annual fee in the heart always have a knot in one’s heart affectation.
Suddenly, IT hit me! Develop your own! Idle egg hurts
Having worked on iPhone apps for years and never developed a status bar for the Mac, it was a good time to exercise Swift, so I went ahead. Unexpectedly, it took a month to develop
Demand for design
The logic of the product is basically the same as that of iPic. Based on the status bar, PNG and JPG files are selected to upload.
You can set whether to compress the picture or not, and the compression will be below 500K.
There also needs to be a login interface to record Tencent cloud account and repository information.
After the file is successfully uploaded, a notification is displayed and the file is copied to the clipboard.
If you accidentally copy another text and lose the link, click the notification again to retrieve it.
Problems encountered
Swift
The first level is the programming language.
Although I have learned Swift systematically, I still cannot change my way of thinking due to years of using Objective-C development.
Strictly null variable
The obvious difference is the way empty variables are handled.
In ObjC, pointer variables can be nil (i.e., 0), and nothing happens when you perform a method on nil, so it’s partially safe.
Swift is stricter with empty variables. The modifier variable must have a specific value,? Modified variables have the possibility of having empty values.
Nil is no longer represented as an empty object, but as a null value, and calling a method to a null value causes a flash back. To treat? Modifier variables must be used carefully, and it is best to determine whether they have values before using them. Fortunately, syntactic sugar can solve these problems.
// Defaults to nil
var money : String?
// The variable has a value
money = "million"
// Check the value before using it
ifmoney ! =nil {
print("I have \(money!) dollars.")}// execute after ensuring that the variable has a value and assigning it to the security variable
if let account = money {
print("I have \(account) dollars.")}// If the variable has no value, an else event is executed and return is returned
guard let account = money else {
print("I have no money.")}print("I have \(account) dollars.")
Copy the code
Fair use! ? It makes our code safer and cleaner.
Nil for Swift is not the same as nil in Objective-C. In Objective-C, nil is a pointer to an object that doesn’t exist. In Swift, nil is not a pointer — it is a definite value used to indicate that a value is missing. Any type of optional state can be set to nil, not just object types.
Throw a warning
ObjC has the use of @throw, but according to Apple’s official description, it is expensive to implement. The reason is that ObjC is based on C rather than C++, so it can only be implemented using setjmp() and Longjmp () methods, which can cause memory leaks.
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 addresses this problem at its root and optimizes the entire process with enumerations.
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 _ {}
// In a concise way, ignore the processing warnings
let compressData = try? self.compressImage(imageData)
}
Copy the code
Swift’s powerful enumerated types allow you to customize warnings to deliver the information you need, making the process smoother.
The syntax also supports try? Ignore the warnings and get a variable that may be null. If you are confident that you will never throw an exception, you can use try! Gets an affirmative value.
Mac OS development
In the process of actually writing Cocoa code, I found that it was quite different from UIKit.
The control logic
The level of UIKit is usually UINavigationController -> UIViewController
Cocoa has a different level, NSWindowController -> NSViewController
The reason is also very simple, there is usually only one window on the phone, relying on the navigation bar to jump to the page. On the desktop side, however, the logic is different. New pages are usually displayed as new Windows.
The desktop side has a specific status bar control, NSMenu, in which to manipulate menu items is also a new challenge.
Tencent Cloud
Since Tencent Cloud only provides iOS library, I need to readjust the library file to Cocoa code first. This part is also a bit of a pain, removing device-specific code and applications, notifications to and from the background, and handling conversions to similar functions (such as UIImage -> NSImage).
At the same time, there is a second pit, Tencent cloud library is ObjC code, so it needs to be mixed.
Add the Targets/Build Phases/Embed Frameworks to the Targets/Build Phases/Embed Frameworks in the main project.
Next, create the project-bridge-header. h Header file in the Swift Project, where you reference the SDK libraries.
Finally, set the Targets/Build Settings/Objective-c Bridging Header files to solve the code mixing problem.
The principle is to automatically create a PCH based on a header file, and the ObjC code referenced in the header file is bridge to the project.
Image compression algorithm
Another reason for not using off-the-shelf software is that I want to control the parameters and effects of compressed images myself.
After investigating and experimenting with the compression effect of pictures, I finally chose to compress them into JPG format, with a size limit of 500K, compression ratio of 0.75 minimum and ratio width of 1280px.
The first picture of the beautiful woman, the initial is 1.9m 5087×3661, due to the large size, after the first compression of the picture quality, the capacity increased to 2.4m.
Shrink the aspect ratio to 1280×922 and the image becomes larger again, this time to 4.7m. (Changing width and height requires creating a new canvas, which must have alpha channels and other Settings, so it will be larger)
We then compressed the image to 260K at a compression rate of 0.9, successfully achieving our goal.
conclusion
It has been two months since my last blog, partly due to some changes in my life and partly due to my unfamiliarity with Cocoa + Swift development.
The Github project is now open source. Welcome to comment and ridicule.
The biggest takeaway from this project was getting out of your comfort zone. Human nature involves inertia, a tendency to do familiar work in familiar territory. But just like businesses, it’s either innovation or death. Technology is constantly evolving, and if it doesn’t keep up, it will eventually become obsolete. With this mutual encouragement!
The resources
Swift 4.0 tutorial
App picture compression cutting principle and upload scheme