-rw-r--r-- 2.9K Aug 12, 2016 · EC7C9DE · ~2 min

Custom Badge for UITabBarController in Swift

swift шпаргалки uitabbarcontroller

It was 2016, and to change the colors of a badge inside a tab you still had to create your own UI element and add it to the tab bar manually. A working solution in Swift:

// MARK: - UITabBarController extension for badges
extension UITabBarController {

    /**
    Set badges

    - parameter badgeValues: values array
    */
    func setBadges(badgeValues: [Int]) {

        for view in self.tabBar.subviews {
            if view is CustomTabBadge {
                view.removeFromSuperview()
            }
        }

        for index in 0...badgeValues.count-1 {
            if badgeValues[index] != 0 {
                addBadge(
                    index: index,
                    value: badgeValues[index],
                    color:UIColor.yellowColor(),
                    font: UIFont.systemFontOfSize(11)
                )
            }
        }

    }

    /**
    Add badge for tab

    - parameter index: index of tab
    - parameter value: badge value
    - parameter color: badge color
    - parameter font: badge font
    */
    func addBadge(index: Int, value: Int, color: UIColor, font: UIFont) {
        let badgeView = CustomTabBadge()

        badgeView.clipsToBounds = true
        badgeView.textColor = UIColor.whiteColor()
        badgeView.textAlignment = .Center
        badgeView.font = font
        badgeView.text = String(value)
        badgeView.backgroundColor = color
        badgeView.tag = index
        tabBar.addSubview(badgeView)

        self.positionBadges()
    }

    override public func viewDidLayoutSubviews() {
        super.viewDidLayoutSubviews()
        self.tabBar.setNeedsLayout()
        self.tabBar.layoutIfNeeded()
        self.positionBadges()
    }

    /**
    Positioning
    */
    func positionBadges() {

        var tabbarButtons = self.tabBar.subviews.filter { (view: UIView) -> Bool in
            return view.userInteractionEnabled // only UITabBarButton are userInteractionEnabled
        }

        tabbarButtons = tabbarButtons.sort({ $0.frame.origin.x < $1.frame.origin.x })

        for view in self.tabBar.subviews {
            if view is CustomTabBadge {
                let badgeView = view as! CustomTabBadge
                self.positionBadge(badgeView, items:tabbarButtons, index: badgeView.tag)
            }
        }
    }

    /**
    Position for badge

    - parameter badgeView: badge view
    - parameter items: tab bar buttons array
    - parameter index: index of tab
    */
    func positionBadge(badgeView: UIView, items: [UIView], index: Int) {

        let itemView = items[index]
        let center = itemView.center

        let xOffset: CGFloat = 12
        let yOffset: CGFloat = -14
        badgeView.frame.size = CGSizeMake(17, 17)
        badgeView.center = CGPointMake(center.x + xOffset, center.y + yOffset)
        badgeView.layer.cornerRadius = badgeView.bounds.width/2
        tabBar.bringSubviewToFront(badgeView)
    }

}

/// Custom UILabel class for badge view
class CustomTabBadge: UILabel {}
[↵] open page kastomnyj-bejdzh-dlya-uitabbarcontroller-na-swift.md
-rw-r--r-- 1.0K Aug 9, 2016 · FDC24F3 · ~1 min

Delay Function in Swift

swift шпаргалки

A very nice bit of syntactic sugar: a function for running code with a delay via Grand Central Dispatch using dispatch_after:

Update 2024. Swift 5.5+

If you need a delay inside an async function:
func someMethod() async throws {
    // sleep for 2 seconds
    try await Task.sleep(nanoseconds: NSEC_PER_SEC * 2)
}

Swift 2:

/**
Delay function using GCD. Syntax sugar.

- parameter delay: delay in seconds
- parameter closure: closure code to execute after delay
*/
func delay(delay:Double, closure:()->()) {
    dispatch_after(
        dispatch_time(
            DISPATCH_TIME_NOW,
            Int64(delay * Double(NSEC_PER_SEC))
        ),
    dispatch_get_main_queue(), closure)
}

Swift 3:

/**
Delay function using GCD. Syntax sugar.

- parameter delay: delay in seconds
- parameter closure: closure code to execute after delay
*/
func delay(_ delay: Double, closure:()->()) {
    let when = DispatchTime.now() + delay
    DispatchQueue.main.asyncAfter(deadline: when, execute: closure)
}

Usage:

delay(0.4) {
    // code
}
[↵] open page funktsiya-zaderzhki-na-swift.md
-rw-r--r-- 705B Jun 14, 2016 · B548F4B · ~1 min

A modal UIViewController with transparency

swift шпаргалки

Cheat sheet: how to present a UIViewController over another one so that it is semi-transparent and the content underneath shows through.

In Storyboard, set the Segue Kind field to «Present Modally». For the UIViewController you are showing, set the background color to Clear Color, then create an inner background (an image or another UIView) with an alpha value, for example 0.5.

In code:

self.performSegueWithIdentifier("segueName", sender: self)

override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
    if segue.identifier == "segueName" {
        let vc = segue.destinationViewController as! YourViewController
        vc.modalPresentationStyle = .Custom
    }
}
[↵] open page modal-nyj-uiviewcontroller-s-prozrachnost-yu.md
-rw-r--r-- 1.1K May 26, 2016 · EB1C751 · ~2 min

Blog redesign

бложек

I decided to study what websites look like in Google's Material Design. I found their Material Design Lite library and dropped it into the site. It seems more readable now, it has responsive design out of the box so it can be read on phones, and it looks better on Retina now too. It is convenient when you can assemble what you like from ready-made pieces. I like the result more than what you can build, for example, with Twitter Bootstrap.

I thought about the header for a long time and in the end lovingly stole the idea from Apple's page dedicated to WWDC '16 :) I implemented it in SVG and animated the cursor in JS (though only in the desktop version). I looked at Polymer, but it did not really start up for me right away, and I had already done a lot with MDL by then. The idea of web components is certainly cool, and it looks great semantically, but for now I will postpone it until browser support gets better. There is also a feeling that everything there is heavily tied to Node.JS, and I no longer want to rewrite it in Node — I am waiting for new Swift releases so I can rewrite it in Swift.

[↵] open page redizajn-bloga.md
-rw-r--r-- 1.4K May 12, 2016 · 6FA87ED · ~1 min

Testing asynchronous code in XCTest

swift xctest тесты шпаргалки

While writing tests in the app, I ran into the fact that tests containing asynchronous code did not work. For example, if we make an asynchronous network request and then verify the result inside the callback block. The assertions simply did not run, and Xcode said the test had passed successfully even when it obviously should not have.

While googling, I found two solutions: one via semaphores from Grand Central Dispatch, the other with expectations. I liked the expectations approach more. Example test:

import XCTest

class apiClientTests: XCTestCase {
    override func setUp() {
        super.setUp()
    }

    override func tearDown() {
        super.tearDown()
    }

    /**
    SampleTest
    */
    func testSampleAsyncRequest() {
        let exp = expectationWithDescription("\(#function)\(#line)")

        APIClient.sharedInstance.someMethod { (responseObject, error) in
            XCTAssertNotNil(responseObject, "responseObject should not be nil")
            XCTAssertNil(error, "error should be nil")

            exp.fulfill()
        }

        waitForExpectationsWithTimeout(40) { (error) in
            if error != nil {
                XCTAssertTrue(false)
            }
        }
    }
}

P.S. — if you want tests to run in a specific order, remember that they are run in plain alphabetical order. So you need to name them test1Name, test2Name, and so on.

[↵] open page testirovanie-asinhronnogo-koda-v-xctest.md
-rw-r--r-- 3.2K May 12, 2016 · 46A3DE7 · ~3 min

On using Swift on the server

swift ubuntu

I started trying Swift on the server for backend work. With macOS, it is all fairly clear in terms of how to start using Swift (at least there is Xcode), but on Linux it turned out to be much less obvious.

The Swift.org website has instructions for OS X and for Ubuntu (14.04 and 15.04). I was immediately happy to see that they provide precompiled binaries. In short: download the archive, download various keys and signatures, verify the archive signature just in case, unpack the archive, and run export so the command can be executed from the console. For example:

swift --version
Swift version 2.2.1-dev (LLVM da67bff217, Clang 81d0486fb2, Swift 82adb8fc96)
Target: x86_64-unknown-linux-gnu

Start with some simple Hello World: just create a small project that prints text to the console, something like:

import Foundation

print("hello world")

Then you need to check whether it works. Run:

swift build
error: unable to invoke subcommand: /home/webserver/swift-2.2.1-SNAPSHOT-2016-04-23-a-ubuntu14.04/usr/bin/swift-build (No such file or directory)

Surprise! The release version of Swift 2.2.1 does not include swift-build. In other words, we cannot build a project with the release version. That is a bit mind-blowing. You start googling and it turns out that you need to download the dev version of Swift. And that is a pre-release version of Swift 3.0.

That version has everything, the project builds, the binary runs, and it prints text to the console. But it is still strange that the tutorial from the website does not work with the release version. Although they say it was present in previous releases.

The saddest part is that you still cannot even send network requests from open-source Swift: NSURLRequest is not implemented in Foundation, which means my idea of using CouchDB through its REST API can be postponed for now. And on GitHub there is still this line in the description of Swift's current state:


NSURLSession and related classes are not yet implemented.

You can, of course, use C libraries. For example, IBM use a CURL wrapper called CCurl. But I would prefer something out of the box, using language tools. So I will probably wait until they finally add it.

My tinkering with the Swift Express web framework showed that it is possible to build a website or REST API with it. Yesterday evening I even made a scaffold for rewriting this blog — templates are ready, routing is ready, the whole site design is rendered, only the database data remains to be wired in. And now the question is how to fetch data from the database. There are wrappers over C libraries for MySQL and MongoDB, but I still want to keep using CouchDB, since I already use it in many projects. And it has a REST API, which means the data must be fetched over network requests, which Foundation still does not provide, and I do not really want to use third-party tools because once everything is implemented, switching to built-in tools will make more sense, so I would have to rip that code out. I will wait a bit longer before rewriting my little blog in Swift :)

[↵] open page pro-ispol-zovanie-swift-na-servere.md
-rw-r--r-- 961B May 11, 2016 · 61AD73C · ~1 min

A note on Socket.IO-Client-Swift

socket.io swift шпаргалки

A small cheat sheet: there is a Swift client for socket.io. At first glance, GitHub documents how to use it pretty well. The problem is that it absolutely did not want to connect to my Node.js backend with the sample code.

The logs showed (when trying polling requests) that the client was hitting /engine.io and getting a 404 error. Studying the browser JavaScript library, which works with the same backend without any dancing with a tambourine, showed that a different path had to be specified: /socket.io. Fortunately, there is a dedicated option for that.

So in the end, this is what we get:

let socketURL = NSURL(string: "http://localhost:3000")
let socket = SocketIOClient(socketURL: socketURL!, options: [
    .ForceWebsockets(true),
    .Path("/socket.io/"),
    .ConnectParams(["token": "token"])
])

socket.on("connect") {data, ack in
    print("socket connected")
}

socket.connect() 
[↵] open page zametka-pro-socket-io-client-swift.md
makoni@arm1:~/blog$ cd ../page-11/ // ← previous cd ./page-13/ // more posts →