TIP-맥OS

macOS에서 swift NSNotifications사용 하여 Broadcast 메시지 보내기 ( 간단한 채팅앱 구현 )

무한열정 2017. 7. 1. 15:01

macOS용 앱을 swift 3.0 기반으로 NSNotification을 사용하여 간단한 채팅앱을 구현해본다.


* AppDelegate.swift


메뉴의 File > New를 선택하면 새로운 윈도우컨트롤러가 생성되어야 한다.

이를 위해 위 코드를 작성한다.

var windowControllers: [ChatWindowController] = []


func applicationDidFinishLaunching(_ aNotification: Notification) {

    // Insert code here to initialize your application

    NSLog("applicationDidFinishLaunching")

    addWindowController()

}


func applicationWillTerminate(_ aNotification: Notification) {

    // Insert code here to tear down your application

}


// MARK: - Actions

@IBAction func displayNewWindow(_ sender: NSMenuItem) {

    addWindowController()

}

    

    

// MARK: - Helpers

func addWindowController() {

    NSLog("addWindowController")

    let windowController = ChatWindowController()

    windowController.showWindow(self)

    windowControllers.append(windowController)

}


 메뉴와 displayNewWindow를 연결한다.


* ChatWindowController

ChatWindowControllerDidSendMessageNotification는 노티피케이션의 명칭이되고

ChatWindowControllerMessageKey 노티피케이션에 전달할 메시지의 키가 된다.

UI의 property와 코드의 변수를 연결하기 위해 dynamic으로 정희하고 연결하는 점이 iOS하고 다른점이다.
UI의 객체에 접근하기 위해 IBOutlet을 설정한다.

import Cocoa


private let ChatWindowControllerDidSendMessageNotification = "com.bignerdranch.chatter.ChatWindowControllerDidSendMessageNotification"

private let ChatWindowControllerMessageKey = "com.bignerdranch.chatter.ChatWindowControllerMessageKey"



class ChatWindowController: NSWindowController {


    dynamic var log: NSAttributedString = NSAttributedString(string: "")

    dynamic var message: String?

    

    // NSTextView does not support weak references.

    @IBOutlet var textView: NSTextView!

    

    override var windowNibName: String {

        return "ChatWindowController"

    }


TextView의 Bindings Inspector에서 Value를 설정한다.

Bind to 에 체크해야하고

File's Owner로 선택한다.

Model Key Path는 log를 오타나지 않도록 주의하여 타이핑한다.


TextField를 선택하고

Bindings Inspector를 선택하고

Value항목에서 Bind to 체크, File's Owner를 선택한다.

Model Key Path는 message 변수를 타이핑하여 연결한다.


windowDidLoad() 델리게이트에 노티피케이션을 등록하는 구문을 추가한다.

selector를 지정할때 클래스명을 포함한 function명을 지정하는것이 특징이다.

override func windowDidLoad() {

    super.windowDidLoad()


    // Implement this method to handle any initialization after your window controller's window has been loaded from its nib file.

    let notificationCenter = NotificationCenter.default

    notificationCenter.addObserver(self,

                           selector: #selector(ChatWindowController.receiveDidSendMessageNotification(_:)),

                           name: NSNotification.Name(rawValue: ChatWindowControllerDidSendMessageNotification),

                           object: nil)


}


* 윈도우컨트롤러가 종료되면 노티피케이션도 같이 제거될수 있도록 한다.

deinit {

    let notificationCenter = NotificationCenter.default

    notificationCenter.removeObserver(self)

}


* 사용자가 버튼을 누르게 되면 비로소 노티피케이션이 발송되도록 처리한다.

  메시지는 Dictionary형태로 전달하면 된다. 

// MARK: - Actions

@IBAction func send(_ sender: NSButton) {

    sender.window?.endEditing(for: nil)

    if let message = message {

        let userInfo = [ChatWindowControllerMessageKey : message]

        let notificationCenter = NotificationCenter.default

        notificationCenter.post(name: Notification.Name(rawValue: ChatWindowControllerDidSendMessageNotification),

                                object: self,

                                userInfo: userInfo)

    }

    message = ""

}


Button의 IBAction이 send function과 제대로 연결이 되어야 한다.



* 노티피케이션이 모든 객체에 전체 발송되고 이를 수신할 리시버가될 델리케이션의 본문을 구현한다.

  log.mutableCopy() log변수에서 복사한다음 메시지를 추가하여

 mutableLog.copy()하여 다시 복사한 다음 log에 대입하여 준다.

function명에 copy가 들어간 것으로 보아 값을 새로운영역에 복사하여 만들어주는걸 알수 있다.

ARC가 내부적으로 동작할텐데 이부분도 심도있게 이해하면 좋을것이다.

// MARK: - Notifications

// ChatWindowControllerDidSendMessageNotification

func receiveDidSendMessageNotification(_ note: Notification) {

    let mutableLog = log.mutableCopy() as! NSMutableAttributedString

        

    if log.length > 0 {

        mutableLog.append(NSAttributedString(string: "\n"))

    }

        

    let userInfo = note.userInfo! as! [String : String]

    let message = userInfo[ChatWindowControllerMessageKey]!

        

    let logLine = NSAttributedString(string: message)

    mutableLog.append(logLine)

        

    log = mutableLog.copy() as! NSAttributedString

        

    textView.scrollRangeToVisible(NSRange(location: log.length, length: 0))

}



Chatter.zip


Chatter.zip
0.03MB