import Foundation



public class Node<T> {

    var value: T

    var next: Node<T>?

    weak var previous: Node<T>?

    

    init(value: T) {

        self.value = value

    }

}


public class LinkedList<T> {


    private var head: Node<T>?

    private var tail: Node<T>?

    

    public var isEmpty: Bool {

        return head == nil

    }

    

    public var first: Node<T>? {

        return head

    }

    

    public var last: Node<T>? {

        return tail

    }

    

    public func append(value: T) {

        let newNode = Node(value: value)

        if let tailNode = tail {

            newNode.previous = tailNode

            tailNode.next = newNode

        } else {

            head = newNode

        }

        tail = newNode

    }

    

    public func nodeAt(index: Int) -> Node<T>? {

        if index >= 0 {

            var node = head

            var i = index

            while node != nil {

                if i == 0 { return node }

                i -= 1

                node = node!.next

            }

        }

        return nil

    }

    

    public func removeAll() {

        head = nil

        tail = nil

    }

    

    public func remove(node: Node<T>) -> T {

        let prev = node.previous

        let next = node.next

        

        if let prev = prev {

            prev.next = next

        } else {

            head = next

        }

        next?.previous = prev

        

        if next == nil {

            tail = prev

        }

        

        node.previous = nil

        node.next = nil

        

        return node.value

    }

}


extension LinkedList: CustomStringConvertible {

    public var description: String {

        var text = "["

        var node = head

        

        while node != nil {

            text += "\(node!.value)"

            node = node!.next

            if node != nil { text += ", " }

        }

        return text + "]"

    }

}



WRITTEN BY
[前草] 이승현 (wowlsh93@gmail.com)
스타코프 (데이터지능플랫폼pd) (관심분야: 에너지IoT, 시계열(NILM) 데이터, 폴리글랏 프로그래밍 )

트랙백  0 , 댓글이 없습니다.
secret

http://dev.iachieved.it/iachievedit/tcp-sockets-with-swift-on-linux/원본  
(구글번역기로 번역했습니다. 아~주 약간 다듬었을뿐입니다. 엄청나게 발전했군요.) 


TCP Sockets with Swift on Linux

먼 옛날 은하계에서 멀리 떨어져있는 소프트웨어 개발자들은 TCP / IP 소켓으로 클라이언트 - 서버 애플리케이션을 작성했었습니다. 그것은 어둠의 시대 이전, HTTP 이전이었지요.

물론 농담입니다. HTTP는 다양한 클라이언트 - 서버 응용 프로그램을 제공하기 위해 활용 될 수 있으며 REST 응용 프로그램의 기반에 있습니다.  HTTP 가 테이블에 가져오는것은  와이어상에서 패킷을 직접가져오는 작업은 아니지만  합의 된 프로토콜 구조 (그리고 어느 포트가 사용되는지에 대한 표준에 어느 정도의 차이가 있음) 는 패킷에 대한 것입니다.  GET, POST, PUT 등과 같은 동작 동사와 HTTP 헤더 자체가 클라이언트 - 서버 응용 프로그램을 개발하는 데 HTTP 를 이상적으로 만들어 줍니다.

결국 스택 맨 아래에서 운영 체제의 소켓 인터페이스를 통해 비트와 바이트가 마샬링됩니다. 네트워크 소켓과 상호 작용하기 위한 API는 매우 풍부하며 이 주제에 대한 많은 자습서와 서적이 있습니다. C의 IP 네트워킹 루틴은 상당히 장황 할 수 있으며 C ++로 객체 지향 루틴에 캡슐화 된 최초의 "실제"API 중 하나였습니다. 그 전통은 Foundation의 CFStream 클래스와 이제는 Swift  swiftysockets  API로 이어졌습니다.

Swiftychat

Swift에서 TCP / IP 네트워크 소켓을 사용하는 방법을 설명하기 위해 기본 "채팅 시스템" 응용 프로그램 인 Swiftychat 을 개발할 것입니다. 기능면에서 제한적이며 실제로 사용하기에 별다른 의미는 없지만 Swift의 TCP / IP 소켓에서 문자열을 보내고받는 방법의 실제 예입니다.

swiftysockets

Swiftychat는 원래 Zewo 팀이 개발 한 Swift Package Manager-ready TCP / IP 소켓 구현 인 swiftysockets를 사용합니다. 불행히도 패키징 제약으로 인해 우리 시스템에 기본 C 라이브러리 Tide를 설치하기 위해 먼저 약간의 난리법석을 떨어야 합니다. 그럼 이제 해보죠.

$ git clone https://github.com/iachievedit/Tide
Cloning into 'Tide'...
...
$ cd Tide
$ sudo make install
clang -c Tide/tcp.c Tide/ip.c Tide/utils.c
ar -rcs libtide.a *.o
rm *.o
mkdir -p tide/usr/local/lib
mkdir -p tide/usr/local/include/tide
cp Tide/tcp.h Tide/ip.h Tide/utils.h Tide/tide_swift.h tide/usr/local/include/tide
# copy .a
cp libtide.a tide/usr/local/lib/
mkdir -p /usr/local
cp -r tide/usr/local/* /usr/local/

어떤 시점에서 우리는 Swift Package Manager가 나머지 패키지 빌드와 링크 될 수있는 C 라이브러리를 컴파일 할 수 있다고 생각되나  그때까지는 이것이 우리가 할 수 있는 최선의 방법입니다.

Tide가 설치되면 우리는 Swiftychat 앱에서 swiftysockets 을 활용할 수 있습니다.

Start Coding!

main.swift 파일은 매우 간단합니다. ChatterServer를 생성하고 시작하십시오.

main.swift

간략한 main.swift는 우리의 구현이 ChatterServer 클래스에 구현되어 있다는 것을 의미합니다.

ChatterServer.swift:


1. Initialization

 IP와 TCPServerSocket 클래스 (swiftysockets)가 모두 오류를 던질 수 있으므로 nil이 가능한 반환 값임을 알리는 이니셜 라이저. IP는 IP 주소와 포트 정보를 멋지게 캡슐화하고 TCPServerSocket 초기화 프로그램에 인스턴스를 제공합니다. initsucceeds가되면 우리는 주어진 포트에 들어오는 연결을 받아 들일 준비가 된 TCP 소켓을 갖게됩니다.

2. The Main Loop

함수의 이름을 startListening, start, main으로 지정하십시오. 새 클라이언트 연결 (server! .accept ())을 받아들이고 연결된 클라이언트 목록에 추가하는 기본 이벤트 루프입니다. server! .accept ()는  새로운 연결을 기다리고 받아드리는 기능입니다. 꽤 표준적인 것들이죠.

3. Client Management

나머지 ChatterServer에는 모든 "클라이언트 관리"기능이 포함되어 있습니다. 클라이언트를 관리하는 몇 가지 변수와 세 가지 루틴이 있습니다.

우리의 변수는 간단합니다.

  • 연결되어진 클라이언트의 배열 ([TCPClientSocket])
  • 클라이언트를 구분하는데 사용되는 연결 카운트

함수내용은 이렇습니다: 

  • addClient는 TCPClientSocket을 사용하여 연결 수를 증가시키고 클라이언트의 연결에 따라 "관리"되는 NSThread를 설정합니다. 추가 연결이 새로 추가됨에 따라 NSThread가 생성됩니다. 잠시 후에 NSThreadroutine에 대해 이야기하겠습니다. 스레드가 시작되면 addClient는 연결된 클라이언트 배열 끝에 TCPClientSocket을 추가합니다.
  • removeClient는 지정된 클라이언트를 "필터 아웃"하기 위해 필터 함수를 사용하여 연결된 클라이언트 목록에서 클라이언트를 제거합니다. 여기에! == identity 연산자를 사용합니다.
  • broadcastMessage는 ChatterServer를 채팅 서버로 만드는 것입니다. where 키워드를 사용하여 클라이언트가 만든 메시지를 다른 모든 연결된 클라이언트에 브로드 캐스팅하는 필터링 된 배열을 만듭니다. 다시, 우리는! == 연산자를 사용합니다.

스레드는 주 프로세스 내에서 실행되는 별도의 실행 경로임을 상기하십시오. 우리 서버는 연결된 각 클라이언트에 대해 별도의 스레드를 생성합니다. 이제는 그것이 좋은 아이디어인지 아닌지에 대해서는 상황에 따라 달라집니다만 수만 명의 클라이언트를 처리 할 서버를 설계한다면,  말리고 싶습니다.

우리 쓰레드를 한번더 봅시다.

클라이언트 처리 스레드는 또한 TCPClientSocket 클래스의 receiveString 메서드를 통해 입력을 기다리는 루프에 위치합니다. 문자열이 수신되면 서버는 이를 콘솔에 기록한 다음 응답을 브로드 캐스트합니다. try 시도로 인해 연결이 끊어지면 서버는 클라이언트를 제거합니다.

Putting it All Together

우리의 목표는 가능한 한 많이 Swift Package Manager를 사용하여 응용 프로그램을 빌드하는 것입니다. swiftpm에 대한 소개는 자습서를 확인하십시오.

Package.swift에 다음을 추가하십시오.

Sources라는 디렉토리에 main.swift 및 ChatterServer.swift 코드를 추가하십시오.

swifty빌드를 실행하면 두 가지 종속성 (Tide 및 swiftysockets)을 다운로드하여 빌드하고 응용 프로그램 코드를 컴파일해야합니다. 모두 잘되면 .build / debug / 디렉토리에 chatterserver라는 이름의 바이너리가 생깁니다.

Testing it Out

다음 튜토리얼은 멋진 chat 클라이언트를 작성하는 것이지만 지금은 nc (netcat) 명령으로 서버를 테스트 할 수 있습니다. 서버를 시작한 다음 다른 터미널 창에서 nc localhost 5555를 입력하십시오. 연결된 서버 1의 클라이언트 1 창이 표시됩니다. netcat "클라이언트"창에서 CTRL-C를 누르면 서버는 그 이유와 함께 연결 해제 메시지를 인쇄합니다 (예 : 연결 재설정 (연결 재설정)).

실제 테스트를 위해 서버와 연결된 세 개의 클라이언트를 시작합니다.

Chatville
Chatville

왼쪽 터미널에서 채팅 서버가 실행 중입니다. 오른쪽에는 3 개의 클라이언트가 있으며, 각각은 nc localhost 5555 명령을 입력하여 시작됩니다. 각 클라이언트가 연결되면 서버는 연결 메시지를 인쇄합니다.

우리의 broadcastMessage 함수는 브로드 캐스트로부터 메시지의 송신자를 제외시킵니다. 이렇게하면 클라이언트가 자신의 메시지를 다시받지 못하게 되겠지요. 

What’s Next

nc를 클라이언트로 사용하는 것은 약간 지루합니다. 닉네임을 설정할 수없고, 메시지에 "구조"가없고, 타임 스탬프가 없습니다. 위의 예에서 메시지를받는 사람은 누가 작성했는지 전혀 알지 못합니다! swiftysockets에는 이미 TCPClientSocket 클래스가 있으므로 더 강력한 채팅 클라이언트를 만들수 있습니다.

Getting the Code

 here 에 우리의 작은 채팅 서버에 대한 코드를 넣었습니다. 또한 현재 구현되지 않은 채터 클라이언트 프로젝트도 포함되어 있습니다. 다운로드를 하고 최상위 디렉토리에 make를 입력하면 클라이언트와 서버가 모두 빌드됩니다. 주의 사항 : swiftysockets을 사용하기 전에 libtide.a와 관련 헤더를 설치해야합니다!


WRITTEN BY
[前草] 이승현 (wowlsh93@gmail.com)
스타코프 (데이터지능플랫폼pd) (관심분야: 에너지IoT, 시계열(NILM) 데이터, 폴리글랏 프로그래밍 )

트랙백  0 , 댓글이 없습니다.
secret

https://www.zybuluo.com/Xiaojun-Jin/note/29874  원본

참고로 스위프트 3.0 기반으로 처음 개발하시는분들은 이걸 사용하는게 나을거 같습니다.

[Swift 3 ]  가장 쉬운 소켓 (TCP)  통신 방법을 찾고 계신가요? 

소켓 기반  iOS 프로그래밍 

소켓은 양방향으로 데이터를 전송할 수있는 도구입니다. 따라서 소켓은 양면을 가지며, 각면은 IP 주소와 포트라는 두 요소의 조합으로 식별됩니다.

데이터가 전송되는 방식 (프로토콜)이 다른 많은 종류의 소켓이 있습니다. 가장 많이 사용되는 유형은 TCP와 UDP 이며 . 이 튜토리얼에서는 TCP 소켓을 다루겠습니다.

iOS 프로젝트를 작성하기 전에 Python 언어를 사용하여 TCP 서버를 만들 계획입니다. 그러나 특정 서버 구현이 iOS 기술과 관련이 없으므로 여기서 건너 뛰고 서버가 준비 되었다고 가정합니다. 이제 App Client에 초점을 맞추고 소켓 프로그래밍을 해 보겠습니다.  클라이언트는 채팅 룸 가입, 메시지 보내기메시지 수신이라는 세 가지 주요 작업을 합니다.

Stream Programming

iOS에서 소켓 연결을 설정하기 위해 우리는 스트림을 사용합니다. 스트림은 데이터를 송수신하는 메커니즘에 대한 추상화입니다. 또한 스트림에는 "연결이 열려 있습니다", "데이터가 수신되었습니다", "연결이 닫혔습니다"등과 같은 특정 이벤트에 따라 대응할 수있는 대리자가 연결되어 있습니다.

Cocoa Framework에 포함 된 스트림과 관련된 중요한 클래스가 있습니다.

  • NSStream 
    This is the super class which defines some abstract features like open, close and delegate.
  • NSInputStream 
    A subclass of NSStream for reading input.
  • NSOutputStream 
    A subclass of NSSTream for writing output.

여기있는 유일한 문제는 NSStream 클래스가 원격 호스트에 연결할 수없는 반면 CFStream은 능력이 있다는 것입니다. 다행스럽게도 NSStream과 CFStream은 일종의 브리지 연결이므로 NSStream 형식의 CFStream을 쉽게 가져올 수 있습니다.

  1. NSInputStream *inputStream; NSOutputStream *outputStream;
  2. - (void)initNetworkCommunication
  3. {
  4. CFReadStreamRef readStream; CFWriteStreamRef writeStream;
  5. CFStreamCreatePairWithSocketToHost(NULL, (CFStringRef)@"localhost",
  6. 80, &readStream, &writeStream);
  7. inputStream = (NSInputStream *)readStream;
  8. outputStream = (NSOutputStream *)writeStream;
  9. [inputStream setDelegate:self]; [outputStream setDelegate:self];
  10. [inputStream scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
  11. [outputStream scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
  12. [inputStream open]; [outputStream open];
  13. }

CFStreamCreatePairWithSocketToHost는 두 스트림을 호스트와 포트에 바인딩하는 데 사용됩니다. 일단 호출하면 CFStream을 NSStream으로 자유롭게 캐스팅 할 수 있습니다.

스트림은 지속적으로 데이터를 보내거나받을 준비가되어 있어야합니다. 이 기능을 사용하려면 실행 루프에서 이벤트를 수신하도록 스트림을 예약해야합니다. 앱은 이벤트를 스트리밍하는 데 반응해야하지만 이벤트의 자비가되지는 않습니다. 실행 루프 스케줄링을 사용하면 다른 코드 (필요한 경우)를 실행할 수 있지만 스트림에서 문제가 발생하면 알림을받을 수 있습니다.

Joining the Chat

서버에 연결되면 채팅에 참여할 준비가되었습니다. 조인 메시지의 형식은 "iam : name"입니다. 그래서 우리는 문자열을 만들어서 outputStream에 써야합니다.

  1. - (IBAction)joinChat:(id)sender
  2. {
  3. NSString *res = [NSString stringWithFormat:@"iam:%@", inputNameField.text];
  4. NSData *dt = [[NSData alloc] initWithData:[res dataUsingEncoding:NSASCIIStringEncoding]];
  5. [outputStream write:[data bytes] maxLength:[dt length]];
  6. }

이벤트를 전달하기 위해 서버는 클라이언트 / 서버가주고받는 데이터의 예상 포맷 / 시퀀스를 정의하는 프로토콜을 정의해야합니다. 이 응용 프로그램에서는 매우 간단한 문자열 기반 프로토콜을 사용합니다. iammeans "사용자가 채팅에 참여했습니다."msg는 "메시지 보내기"를 나타냅니다.

Sending Messages

채팅에 참여하는 것과 매우 유사한 방식으로이를 구현합니다. "iam :"을 "msg :"로 전환하면됩니다.

  1. - (IBAction)sendMessage:(id)sender
  2. {
  3. NSString *res = [NSString stringWithFormat:@"msg:%@", inputMessageField.text];
  4. NSData *dt = [[NSData alloc] initWithData:[res dataUsingEncoding:NSASCIIStringEncoding]];
  5. [outputStream write:[data bytes] maxLength:[dt length]];
  6. }

Receiving Messages

애플리케이션이 서버에서 메시지를 수신하고 있다는 사실을 알리려면 NSStream 대리자 스트림 인 handleEvent를 구현해야합니다. 그러면 스트림에서 발생하는 활동에 Google 애플리케이션이 반응 할 수 있습니다.

  1. - (void)stream:(NSStream *)theStream handleEvent:(NSStreamEvent)streamEvent
  2. {
  3. NSLog(@"stream event %i", streamEvent);
  4. switch (streamEvent)
  5. {
  6. case NSStreamEventOpenCompleted:
  7. NSLog(@"Stream opened");
  8. break;
  9. case NSStreamEventHasBytesAvailable: // fundamental to receive messages
  10. if (theStream == inputStream)
  11. {
  12. uint8_t buffer[1024]; int len;
  13. while ([inputStream hasBytesAvailable])
  14. {
  15. len = [inputStream read:buffer maxLength:sizeof(buffer)];
  16. if (len > 0)
  17. {
  18. NSString *output = [[NSString alloc] initWithBytes:buffer
  19. length:len
  20. encoding:NSASCIIStringEncoding];
  21. if (nil != output)
  22. {
  23. NSLog(@"server said: %@", output);
  24. }
  25. }
  26. }
  27. }
  28. break;
  29. case NSStreamEventErrorOccurred:
  30. NSLog(@"Can not connect to the host!");
  31. break;
  32. case NSStreamEventEndEncountered:
  33. [theStream close];
  34. [theStream removeFromRunLoop:[NSRunLoop currentRunLoop]
  35. forMode:NSDefaultRunLoopMode];
  36. [theStream release];
  37. theStream = nil;
  38. break;
  39. default:
  40. NSLog(@"Unknown event");
  41. }
  42. }

while 루프를 사용하여 스트림의 바이트를 수집합니다. 스트림에 아무것도 남아 있지 않으면 read 메소드는 0을 리턴합니다. 결과가 0보다 큰 경우 버퍼를 String으로 변환하고 결과를 출력합니다.

기기에서 앱 실행 :

먼저 "localhost"문자열을 컴퓨터의 ip로 전환하십시오. 현재 IP를 찾으려면 "시스템 환경 설정> 네트워크"로 가십시오. 장치는 무선으로 컴퓨터를 서비스하는 동일한 라우터에 연결해야합니다. 3G 연결을 사용하려면 포트 80에서 네트워크 외부의 연결을 허용하도록 라우터를 구성해야합니다 (권장하지 않음).



WRITTEN BY
[前草] 이승현 (wowlsh93@gmail.com)
스타코프 (데이터지능플랫폼pd) (관심분야: 에너지IoT, 시계열(NILM) 데이터, 폴리글랏 프로그래밍 )

트랙백  0 , 댓글이 없습니다.
secret


iOS Swift 개발을 위한  라이브러리 TOP 10 

스위프트의 인기가 높아지면서 새 프로젝트를 시작할때 스위프트를 사용할 기회 또한 많아지고 있다.
시간도 절약하고 좀 더 쉽게 스위프트로 iOS 개발을 하기위해 여기 10가지 라이브러리를 소개하고자 한다. 

이전에 언급한  GitHub 와 Bitbucket 는 훌륭한 iOS 라이브러리를 찾기 위한 좋은 장소이다.
CocoaPods 나 Carthage 같은 툴은 라이브러리를 신속하게 인스톨링하고 관리하는데 도움을 줄 수 있다.
이 방식은 프로젝트 디펜던시를 관리하는것을 쉽게 만들어 줄 것이다.

Top 10 Swift libraries

1. Alamofire

앱에 네트워킹을 위한 기능을 간단히 추가하고 싶을때, Alamfire 는 안성마춤이다.Alamofire  는 HTTP 네트워킹 라이브러리이고 NSURLSession 과 Foundation URL 로딩 시스템에 기반해서 만들어졌다. 우아하고 간단한 스위프트 인터페이스로 네트워킹 메카니즘을 깔끔하게 감쌌다.


// Making a GET request

Alamofire.request(.GET, "https://httpbin.org/get", parameters: ["foo": "bar"])
         .responseJSON { response in
             print(response.request)  // original URL request
             print(response.response) // URL response
             print(response.data)     // server data
             print(response.result)   // result of response serialization

             if let JSON = response.result.value {
                 print("JSON: \(JSON)")
             }
         }

2. SwiftyJSON

Swift의 명시적 유형은 코드로 인한 실수를 저지르지 않게 도와주어  버그가 발생하지 않도록 합니다. 그러나 때로는 JSON을 사용하여 작업 할 때 특히 문제가 될 수 있습니다. 다행스럽게도 SwiftyJSON은 Swift의 JSON 데이터를 보다 읽기 쉬운 방식으로 처리하는 데 도움이됩니다. 선택적 언 래핑은 자동으로 처리됩니다!


// Typical JSON handling

if let statusesArray = try? NSJSONSerialization.JSONObjectWithData(data, options: .AllowFragments) as? [[String: AnyObject]],
    let user = statusesArray[0]["user"] as? [String: AnyObject],
    let username = user["name"] as? String {
    // Finally we got the username
}

// With SwiftyJSON

let json = JSON(data: dataFromNetworking)
if let userName = json[0]["user"]["name"].string {
  //Now you got your value
}

SwiftyJSON 는 Alamofire 와 함께 할 때 빛이 나죠.

Alamofire.request(.GET, url).validate().responseJSON { response in
    switch response.result {
    case .Success:
        if let value = response.result.value {
          let json = JSON(value)
          print("JSON: \(json)")
        }
    case .Failure(let error):
        print(error)
    }
}

3. ObjectMapper

API를 통해 정보를 다운로드하는 앱을 작성한 적이 있다면 아마도 응답을 객체에 매핑하는 코드를 작성하는 데 많은 시간을 할애했을 것입니다. ObjectMapper를 사용하면 JSON 응답을 모델 객체로 변환하거나 그 반대로 변환 할 수 있습니다. 즉, JSON을 객체에 매핑하고 객체를 JSON에 매핑하는 데 도움이됩니다. 중첩 된 객체도 지원됩니다.


// Temperature class that conforms to Mappable protocol

struct Temperature: Mappable {
    var celsius: Double?
    var fahrenheit: Double?

    init?(_ map: Map) {

    }

    mutating func mapping(map: Map) {
        celsius     <- map["celsius"]
        fahrenheit  <- map["fahrenheit"]
    }
}

또한 ObjectMapper를 사용할 때 JSON 응답 데이터를 Swift 객체로 변환하는 AlamofireObjectMapper라는 Alamofire 확장 기능에 대해서도 언급 할 가치가 있습니다.

4. Quick

Quick는 RSpec, Specta 및 Ginkgo에서 영감을 얻은 Swift의 행동 중심 개발 프레임 워크입니다. Quick는 Nimble과 함께 제공됩니다. Nimble은 테스트를 위한 matcher 프레임 워크입니다.

// Documentation directory spec

class TableOfContentsSpec: QuickSpec {
  override func spec() {
    describe("the 'Documentation' directory") {
      it("has everything you need to get started") {
        let sections = Directory("Documentation").sections
        expect(sections).to(contain("Organized Tests with Quick Examples and Example Groups"))
        expect(sections).to(contain("Installing Quick"))
      }

      context("if it doesn't have what you're looking for") {
        it("needs to be updated") {
          let you = You(awesome: true)
          expect{you.submittedAnIssue}.toEventually(beTruthy())
        }
      }
    }
  }
}

5. Eureka

Eureka는 간단하고 우아한 방식으로 동적 테이블 뷰 형식을 작성할 수 있도록 도와줍니다. 그것은 행, 섹션 및 양식으로 구성됩니다. 앱에 많은 양식이 포함되어있는 경우, 유레카 (Eureka)는 실시간 보호 기능을 입증합니다.

// Creating a form

class CustomCellsController : FormViewController {

    override func viewDidLoad() {
        super.viewDidLoad()
        form +++ Section("Custom cells")
                    <<< WeekDayRow(){
                        $0.value = [.Monday, .Wednesday, .Friday]
                    }
                    <<< TextFloatLabelRow() {
                        $0.title = "Float Label Row, type something to see.."
                    }
    }
}

6. RxSwift

RxSwift는 Functional Reactive Programming을위한 신속한 프레임 워크입니다. 보다 구체적으로, RxSwift는 Rx의 신속한 버전이며 목표는 비동기 작업과 이벤트 / 데이터 스트림을 쉽게 구성 할 수있게하는 것입니다. KVO 관찰, 비동기 작업 및 델리게이트는 모두 시퀀스 추상화로 통일되어 RxSwift를 강력한 프레임 워크로 만듭니다. ReactiveCocoa를 사용해 본 경험이 있다면 그 개념을 잘 알고있을 것입니다.

// Combine first and last name sequences, and bind the resulting string to label

combineLatest(firstName.rx_text, lastName.rx_text) { $0 + " " + $1 }
            .map { "Greeting \($0)" }
            .bindTo(greetingLabel.rx_text)

7. SnapKit

SnapKit은 가독성을 잃지 않으면 서 최소한의 코드만으로 자동 레이아웃을 코드에 작성하는 것을 단순화하는 자동 레이아웃 라이브러리입니다. 사용자 인터페이스를 코딩하는 동안 프로그래밍 오류를 피할 수 있도록 설계된 유형 안전타입입니다.

// Resizing and centering subview in its superview

let box = UIView()
let container = UIView()

container.addSubview(box)

box.snp_makeConstraints { (make) -> Void in
    make.size.equalTo(50)
    make.center.equalTo(container)
}

8. Spring

Spring은 코드에서 또는 스토리 보드에서 직접 애니메이션을 생성하는 데 도움이되는 애니메이션 라이브러리입니다. 런타임 속성을 사용하여 스토리 보드에서 애니메이션을 만들 수 있습니다 (IBInspectable 속성을 통해 설정). Spring은 많은 이미 작성된 애니메이션, 전환 및 속성을 지원하는 완전히 개발 된 애니메이션 라이브러리로 성장했습니다.

// Usage with code

layer.animation = "wobble"
layer.animate()

9. Kingfisher

Kingfisher는 웹에서 이미지를 다운로드하고 캐시하기위한 경량 라이브러리입니다. 다운로드 및 캐싱은 비동기 적으로 수행됩니다. 다운로드 한 이미지는 메모리와 디스크 모두에 캐시되므로 앱 환경이 상당히 향상 될 수 있습니다.

// Basic example of downloading and caching an image

imageView.kf_setImageWithURL(NSURL(string: "http://your_image_url.png")!)

10. CoreStore

CoreStore는 Core Data의 래퍼 라이브러리입니다. 그 목표는 핵심 데이터와 상호 작용할 때 유형 안전성과 Swift의 우아함을 제공하는 것입니다. CoreStore의 API는 데이터베이스와 효과적으로 상호 작용하는 모든 일반적인 방법을 제공합니다.

// Storing a person entity

CoreStore.beginAsynchronous { (transaction) -> Void in
    let person = transaction.create(Into(MyPersonEntity))
    person.name = "John Smith"
    person.age = 42

    transaction.commit { (result) -> Void in
        switch result {
            case .Success(let hasChanges): print("success!")
            case .Failure(let error): print(error)
        }
    }
}



WRITTEN BY
[前草] 이승현 (wowlsh93@gmail.com)
스타코프 (데이터지능플랫폼pd) (관심분야: 에너지IoT, 시계열(NILM) 데이터, 폴리글랏 프로그래밍 )

트랙백  0 , 댓글이 없습니다.
secret