github.com ↗
Kurulumhttps://github.com/Pariette-Inc/signalbird.sdk

Signalbird - Swift (iOS, macOS)

İki istemci taşır:

Sınıf Ne için Anahtar Nerede
SignalbirdApp son kullanıcıya canlı sohbet + push kaydı sb_public_live_… (açık) iOS uygulaması
SignalbirdClient Telsiz - log ve olay yazma sb_secret_live_… (gizli) sunucu tarafı Swift (Vapor, Hummingbird)

Gizli anahtar iOS uygulamasına gömülmez: uygulama paketi çözülebilir ve anahtar herkesin eline geçer. Mobil taraf sohbeti ve push kaydını açık anahtarla yapar.

Kurulum

Swift Package Manager - Xcode → File → Add Package Dependencies:

text
https://github.com/Pariette-Inc/signalbird.sdk

ya da Package.swift:

swift
dependencies: [
    .package(url: "https://github.com/Pariette-Inc/signalbird.sdk", from: "1.2.0"),
],
targets: [
    .target(name: "App", dependencies: [.product(name: "Signalbird", package: "signalbird.sdk")]),
]

iOS 15+, macOS 12+. Bağımlılığı yoktur - yalnız Foundation/URLSession.


Canlı sohbet

swift
import Signalbird

let client = try SignalbirdApp(config: .init(
    publicKey: "sb_public_live_…",
    chatKey: "destek",
    pushKey: "mobil"
))

chatKey sohbet kanalının, pushKey push kanalının modül anahtarıdır (panelde açtığınız kanal adları, gizli değildir). SDK cihaz ve push uçlarında (registerDevice, unregisterDevice, reportPushOpened) pushKey'i, sohbet uçlarında chatKey'i X-Signalbird-Module-Key başlığıyla gönderir; ilgili anahtar verilmezse API 400 MODULE_KEY_MISSING döner (2.10.0).

Uygulama anahtarını panelden (Gelen Kutusu → Ayarlar → Uygulamalar) ya da Yönetim SDK'sıyla createApp çağırarak alırsınız.

Açılış

swift
let boot = try await client.bootstrap()

guard let app = boot.dictionary?["app"] as? [String: Any],
      app["chat_enabled"] as? Bool == true else {
    return   // Sohbet bu uygulamada kapalı - hiçbir şey çizmeyin
}

bootstrap renk, karşılama metni, çalışma saatleri ve ön-form ayarlarını da döner; arayüzünüzü panelden yönetilebilir kılmak isterseniz oradan okuyun.

Oturum ve konuşma

swift
// Ziyaretçi oturumu - sır saklanır, sonraki açılışta geçmiş korunur
try await client.startSession(["name": "Ayşe", "email": "ayse@example.com"])

// İlk mesajla konuşma açılır. Kota burada harcanır: konuşma başına.
let started = try await client.startConversation(body: "Kargom nerede?")

let conversationID = (started.dictionary?["conversation"] as? [String: Any])?["id"] as? String ?? ""

try await client.sendMessage(conversationID: conversationID, body: "Sipariş no: 1234")

Yeni mesajları çekme

swift
// `after` imleci: yalnız bundan sonraki mesajlar döner
let updates = try await client.getConversation(conversationID, after: lastMessageID)

WebSocket yoktur. Panel açıkken 3 saniyede bir, kapalıyken kademeli olarak seyrelen (20 → 60 → 180 sn) aralıklarla yoklayın; uygulama arka plandayken tur atlayın. Bu, bağlantı kopmasında kendi kendini toparlar ve pil yakmaz.

Etkileşimler

swift
try await client.setTyping(conversationID: conversationID, isTyping: true)
try await client.markRead(conversationID: conversationID, lastMessageID: lastID)
try await client.reactToMessage(conversationID: conversationID, messageID: messageID, emoji: "👍")

// Yalnız kendi mesajı ve gönderimden sonraki 15 dakika içinde
try await client.editMessage(conversationID: conversationID, messageID: messageID, body: "Düzeltme")
try await client.deleteMessage(conversationID: conversationID, messageID: messageID)

try await client.rateConversation(conversationID, rating: 5, comment: "Teşekkürler")
try await client.closeConversation(conversationID)

Kimlik

swift
// Kullanıcı giriş yaptığında ziyaretçiyi kişi kaydına bağlar
try await client.identify([
    "external_id": user.id,
    "email": user.email,
    "name": user.displayName,
    "attributes": ["plan": "pro"],
])

// Çıkışta yerel kimliği silin; sunucudaki kayıt kalır
client.signOut()

Push (APNs)

swift
func application(_ application: UIApplication,
                 didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
    let token = deviceToken.map { String(format: "%02x", $0) }.joined()

    Task {
        try? await client.registerDevice(
            token: token,
            externalID: currentUser?.id,
            deviceName: UIDevice.current.name,
            appVersion: Bundle.main.infoDictionary?["CFBundleShortVersionString"] as? String
        )
    }
}

Bildirim iznini istemek ve token'ı almak uygulamanın işidir: izni ne zaman soracağınız bir ürün kararıdır ve App Store bunu ciddiye alır. SDK yalnız token'ı iletir.

Çıkışta:

swift
try await client.unregisterDevice(token: token)   // kayıt silinmez, kapatılır

Ziyaretçi sırrının saklanması

Varsayılan UserDefaults'tur. Keychain isteyen kendi uyarlamasını verir:

swift
struct KeychainStorage: SignalbirdStorage {
    func get(_ key: String) -> String? { /* … */ }
    func set(_ key: String, _ value: String) { /* … */ }
    func remove(_ key: String) { /* … */ }
}

let client = try SignalbirdApp(config: .init(
    publicKey: "sb_public_live_…",
    chatKey: "destek",
    pushKey: "mobil",
    locale: "tr",
    storage: KeychainStorage()
))

Saklanan kayıt uygulama anahtarını da taşır: anahtarı yenilerseniz eski kimlik otomatik yok sayılır ve yeni oturum açılır. Aksi hâlde eski sırla yapılan her çağrı 401 alır ve sohbet sessizce ölürdü.


Telsiz (sunucu tarafı Swift)

swift
let radio = try SignalbirdClient(config: .init(
    domainKey: ProcessInfo.processInfo.environment["SIGNALBIRD_DOMAIN_KEY"] ?? "",
    source: "api-01"
))

try await radio.critical("critical", "ödeme servisi yanıt vermiyor", [
    "service": "iyzico",
])

try await radio.batch([
    ["channel": "deploy", "message": "v2.4.0 yayında", "level": "info"],
])

Beş seviye: .debug, .info, .warn, .error, .critical.


Sonuç biçimi

swift
public struct SbResult {
    public let ok: Bool
    public let status: Int
    public let data: Any?
    public let code: String?
    public let message: String?

    public var dictionary: [String: Any]? { get }
    public var array: [[String: Any]]? { get }
    public func decode<T: Decodable>(_ type: T.Type) -> T?
}

Kendi modelinize çözmek için:

swift
struct ConversationResponse: Decodable {
    struct Conversation: Decodable { let id: String; let status: String }
    let conversation: Conversation
}

let parsed = updates.decode(ConversationResponse.self)

Sürüm bildirimi

SDK her istekte sürümünü bildirir: X-Signalbird-Sdk: swift/<sürüm>. Yeni bir sürüm yayınlandığında API yanıtında Signalbird-Sdk-Status: outdated (ya da artık desteklenmiyorsa unsupported) döner ve SDK süreç başına bir kez uyarı yazar (print, yalnız DEBUG derlemede). Uyarı hata değildir: isteğin sonucu değişmez.

Panelde Domainler → [domain] → Anahtarlar her anahtarın hangi SDK sürümüyle kullanıldığını gösterir; eski sürümdeki anahtarlar için panelin tepesinde bir uyarı şeridi ve bildirim çıkar. Güncellemek için Xcode'da File → Packages → Update to Latest Package Versions.

Hata kodları

Kod Anlamı
NO_KEY / WRONG_KEY_TYPE Kurucu fırlatır - yanlış aileden anahtar
VISITOR_INVALID Sır geçersiz; yerel kimlik silinir, sonraki çağrı yeni oturum açar
CHAT_UNAVAILABLE Kota doldu ya da sohbet kapalı
MODULE_DISABLED Paketinizde chat ya da push modülü yok
NETWORK_ERROR / TIMEOUT Ağ (status 0)

Kurucudaki anahtar denetimi dışında hiçbir metot hata fırlatmaz; sonuç her zaman zarftır.