
ืฉืคื ๐ฎ๐ฑ ืขืืจืืช
ืชืืขืื
ืืชืืื
ืืืืืช
ืฉืืืืฉ
Add Comments to Your iOS App
ืืืื ืืกืคืจืืื ืืจืฉืืืช ื-iOS ืฉื FastComments.
ืืืืืขื ืืืืื'ืืื ืฉื ืชืืืืืช ืืืื ืืืช, ืฆ'ืื ืืืืงืืจืืช ืืืคืืืงืฆืืืช ื-iOS ืฉืืื.
ืืืืจ
ืชืืื ืืช 
- ืขืฆื ืชืืืืืช ืืกืืืจืื ืขื ืชืืืืืช ืืงืื ื ืืช ืืืืืงื ืืืคืื
- ืคืื ืืืจืชื ืขื ืืฆืืจืช ืคืืกืืื, ืชืืืืืช ืืืฆืืืื ืฉื ืืืื
- ืืฆื ืฆ'ืื ืื ืขื ืืืืื ืืืืืืืืช ืืืคืจืืื ืชืืจืืืื
- ืขืืืื ืื ืืืื ืืืช ืืืืฆืขืืช WebSocket (ืชืืืืืช ืืืฉืืช, ืืฆืืขืืช, ื ืืืืืช)
- ืื ืืกื ืื-ืคืขืืืช (SSO ืคืฉืื ืืืืืงืืช, SSO ืืืืืื ืืกืืืืช ืืืฆืืจ)
- ืขืจืืืช ืืงืกื ืขืฉืืจ ืขื ืืืืฉื, ื ืืื, ืงืื ื-@mentions
- ืืฆืืขื ืขื ืกืื ืื ืืช ื ืืชื ืื ืืืชืืื (ืืืฆืื ืืืขืื/ืืืื ืื ืืืืืช)
- ืคืขืืืืช ืืืืจืฆืื: ืืืืื, ื ืขืืฆื, ื ืขืืื, ืืกืืื
- ืขืืฆืื ืืงืืฃ ืขื ืชืื ืืืช ืืืชืืื ืืืฉืืช ืืืื
- ืืคืชืืจืื ืืืชืืืื ืืกืจืื ืืืืื ืืืฆืืจืช ืชืืืืืช ืืคืืกืืื ืืคืื
- ืืขืืืืช ืชืืื ืืช
- ืชืืืื ืืืืืจ ืืืืืื ืืืืจืืคื
- ื ืืืืืช ืืฉืชืืฉ (ืกืืืื ื ืืงืืื/ืื ืืงืืื)
- ืกืื ืื ืคืื ืืืืกืก ืชืืืืช
- ืชืืืื ืืืืงืืืืฆืื
ืืชืงื ื 
ืืืกืฃ ืืช FastCommentsUI ืืคืจืืืงื ืฉืื ืืืืฆืขืืช Swift Package Manager.
ืโXcode: File > Add Package Dependencies, ืืื ืืื ืืช ืืชืืืช ืืืืืจ.
ืื ืืืกืฃ ืืืชื ืึพPackage.swift:
dependencies: [
.package(url: "https://github.com/fastcomments/fastcomments-ios.git", from: "1.0.0")
]
ืืืืจ ืืื ืืืกืฃ ืืช ืืืืฆืจ ืึพtarget ืฉืื:
.target(
name: "YourApp",
dependencies: [
.product(name: "FastCommentsUI", package: "fastcomments-ios")
]
)
ืืืื ืืช ืฉื ื ืืืืืืืื ืืืื ืฉื ืืจืฉ:
import FastCommentsUI
import FastCommentsSwift
ืืชืืื ืืืืจื 
ืืืืืจื ืืืื ืืืืืช ืืืฆืืช ืืืืื'ื ืชืืืืืช:
import SwiftUI
import FastCommentsUI
struct ContentView: View {
@StateObject private var sdk = FastCommentsSDK(
config: FastCommentsWidgetConfig(
tenantId: "demo",
urlId: "my-page-1",
url: "https://example.com/page-1",
pageTitle: "My Page"
)
)
var body: some View {
FastCommentsView(sdk: sdk)
.task {
try? await sdk.load()
}
}
}
ืืืืฃ ืืช "demo" ืึพtenant ID ืฉื FastComments ืฉืื. ืึพurlId ืืืื ืืช ืืขืืื ืื ืืฉืจืฉืืจ ืฉืื ืืืืืกื ืืช ืืชืืืืืช.
ืืืืืช (SSO) 
FastComments ืชืืื ืืฉืืืฉื ืืฆืื ืืืืืช:
- Anonymous -- ืืื ืืกืืืื SSO; ืืืฉืชืืฉืื ื ืืชื ืืช ืืืืืืช ืืืืกืกืืช ืกืฉื
- Simple SSO -- ืืกืืืื ืืฆื ืืืงืื ืขืืืจ ืืืืืืช ืืืืืงืืช (ืื ืืืืืื)
- Secure SSO -- ืืกืืืื ืืืชืื ืขื ืืื ืืฉืจืช ืืฉืืืืฉ ืืืืฆืืจ
Simple SSO
ืฉืืืืฉื ืืืืืืืช ืืืืืงืืช ืืงืืืืืช. ืื ืืื ืืืื ืืืชืืคืฉ ืืื ืืฉืชืืฉ ืขื Simple SSO, ืืื ืื ืชืฉืชืืฉื ืื ืืคืจืืืงืฉื.
import FastCommentsSwift
let userData = SimpleSSOUserData(
username: "Jane Doe",
email: "jane@example.com",
avatar: "https://example.com/avatar.jpg"
)
let sso = FastCommentsSSO.createSimple(simpleSSOUserData: userData)
let token = try? sso.prepareToSend()
let config = FastCommentsWidgetConfig(
tenantId: "YOUR_TENANT_ID",
urlId: "my-page-1",
sso: token
)
let sdk = FastCommentsSDK(config: config)
SimpleSSOUserData ืชืืื ืื ืืฉืืืช ืืืคืฆืืื ืืืื:
id-- ืืืื ืืฉืชืืฉ (ืืจืืจืช ืืืื: ืืืืจ ืืืงืืจืื ื ืื ืื ืืืืืจ)displayName-- ืฉื ืชืฆืืื ื ืคืจืdisplayLabel-- ืชืืืืช ืืืชืืืช ืฉืืืฆืืช ืืฆื ืืฉื (ืืืฉื "VIP")websiteUrl-- ืงืืฉืืจ ืขื ืฉื ืืืฉืชืืฉlocale-- ืงืื ืฉืคื/ืืืืจisProfileActivityPrivate-- ืืกืชืจืช ืคืขืืืืช ืืคืจืืคืื (ืืจืืจืช ืืืื: true)
Secure SSO
ืืคืจืืืงืฉื, ื-backend ืฉืืื ืืืืฆืจ ืืกืืืื SSO ืืชืื ืืืืฆืขืืช ืกืื ื-API ืฉืืื. ืืคืืืงืฆืืืช iOS ืืงืืืช ืืช ืืืกืืืื ืืืฉืจืช ืฉืืื ืืืขืืืจื ืืืชื ืืงืื ืคืืืืจืฆืื.
ืืฆื ืืฉืจืช ืฉืืื (ืืืืฆืขืืช ื-FastComments Swift SDK ืื ืืื ืฉืคื):
let userData = SecureSSOUserData(
id: "user-123",
email: "user@example.com",
username: "Display Name",
avatar: "https://example.com/avatar.jpg"
)
let sso = try FastCommentsSSO.createSecure(apiKey: "YOUR_API_KEY", secureSSOUserData: userData)
let token = try sso.prepareToSend()
// Return this token to your iOS app via your API
ืืืืฉืื ื-iOS ืฉืืื:
struct MyView: View {
@StateObject private var sdk = FastCommentsSDK(
config: FastCommentsWidgetConfig(
tenantId: "YOUR_TENANT_ID",
urlId: "my-page-1"
)
)
@State private var isLoadingToken = true
var body: some View {
Group {
if isLoadingToken {
ProgressView("Loading...")
} else {
FastCommentsView(sdk: sdk)
}
}
.task {
// Fetch the token from your backend
let token = try? await fetchSSOTokenFromYourBackend()
// Create a new config with the token, or set it before load
isLoadingToken = false
try? await sdk.load()
}
}
}
SecureSSOUserData ืชืืื ืืฉืืืช ื ืืกืคืื:
optedInNotifications-- ืืกืืื ืืงืืืช ืืชืจืืืช ืืืืืจ ืืืงืืจืื ืdisplayLabel-- ืชืืืืช ืืืชืืืชdisplayName-- ืฉื ืชืฆืืืwebsiteUrl-- ืืชืืืช ืืืชืจgroupIds-- ืฉืืืืืช ืืงืืืฆืืชisAdmin-- ืืจืฉืืืช ืื ืืisModerator-- ืืจืฉืืืช ืืืืจืืืจisProfileActivityPrivate-- ืคืจืืืืช ืคืขืืืืช ืืคืจืืคืื
ืชืืืืืช ืืงืื ื ืืช 
ืฉืืืืฉ ืืกืืกื
struct CommentsPage: View {
@StateObject private var sdk = FastCommentsSDK(
config: FastCommentsWidgetConfig(
tenantId: "YOUR_TENANT_ID",
urlId: "article-42",
url: "https://example.com/article/42",
pageTitle: "Article Title"
)
)
var body: some View {
FastCommentsView(sdk: sdk)
.task {
try? await sdk.load()
}
}
}
ืกืื ืื ืืช ืืฆืืขื
ืืกืื ืื ืืจืืจืช ืืืืื ืืฆืื ืืฆืื ืืืขืื/ืืืื. ืืขืืจ ืืช ._1 ืืื ืืงืื ืืฆืืขืืช ืืกืื ืื ืื:
FastCommentsView(sdk: sdk, voteStyle: ._1)
| Style | Appearance |
|---|---|
._0 |
Up/down arrow buttons with net count |
._1 |
Single heart button with count |
ืงืจืืืืช ืืืจื ืฉื ืืืจืืขืื
ืืฉืชืืฉ ืืงืจืืืืช ืืืจื ืืกืื ืื modifier ืืื ืืืคื ืืืื ืืจืืงืฆืืืช ืืฉืชืืฉ:
FastCommentsView(sdk: sdk)
.onCommentPosted { comment in
print("New comment: \(comment.commentHTML)")
}
.onReplyClick { renderableComment in
print("Replying to: \(renderableComment.comment.id)")
}
.onUserClick { context, userInfo, source in
// ืืืงืืจ ืืื .name ืื .avatar
print("Tapped \(userInfo.displayName)")
}
ืืืืช ืขืจืืช ื ืืฉื
ืืขืืจ ืขืจืืช ื ืืฉื ืืจื ืกืืืืช SwiftUI:
FastCommentsView(sdk: sdk)
.fastCommentsTheme(myTheme)
.task { try? await sdk.load() }
ืื ืงืืข ืืืชื ืืฉืืจืืช ื-SDK:
sdk.theme = FastCommentsTheme.modern
ืืืืื ืืืืื
sdk.defaultSortDirection = .nf // ืืืืฉืื ืืืืชืจ ืชืืืื (ืืจืืจืช ืืืื)
sdk.defaultSortDirection = .of // ืืืฉื ืื ืืืืชืจ ืชืืืื
sdk.defaultSortDirection = .mr // ืืจืืืื ืืืื ืืืืชืจ
ืฆ'ืื ืื 
LiveChatView ืืกืคืง ืืืืืืช ืฆ'ืื ืืืื ืืืช ืขื ืืืืื ืืืืืืืืช, ืืคืจืืื ืชืืจืืืื ืืืืฉืง ืงืืืคืงืื. ืืื ืืืืืจ ืืืืืืืืช ืืช ื-SDK ืืืืื ืืืขืชืืง ืืืืฉ ืืชืฆืืื ืืื ืืืืืืช.
struct ChatView: View {
@StateObject private var sdk: FastCommentsSDK = {
let config = FastCommentsWidgetConfig(
tenantId: "YOUR_TENANT_ID",
urlId: "chat-room-1",
sso: ssoToken // ืืืืืฅ ืืืฉืชืืฉ ื-SSO ืืื ืฉืืืฉืชืืฉืื ืืืื ืฉืืืช
)
return FastCommentsSDK(config: config)
}()
var body: some View {
LiveChatView(sdk: sdk)
.onCommentPosted { comment in
print("Sent: \(comment.commentHTML)")
}
.task {
try? await sdk.load()
}
}
}
LiveChatView ืชืืื ืืงืจืืืืช ืืืจื ืืื:
.onCommentPosted-- ื ืงืจื ืืืฉืจ ืืืฉืชืืฉ ืฉืืื ืืืืขื.onCommentDeleted-- ื ืงืจื ืืืฉืจ ืืืืขื ื ืืืงืช.onUserClick-- ื ืงืจื ืืืฉืจ ื ืืืฅ ืฉื ืืืฉืชืืฉ ืื ืชืืื ืช ืืคืจืืคืื ืฉืื
ืคืื ืืืจืชื 
ืืืขืจืืช ืฉื ืืคืื ืืื SDK ื ืคืจื (FastCommentsFeedSDK) ืขื ืชืฆืืื ืืฉืื.
ืืขืื ื ืืืฆืืช ืืคืื
struct FeedPage: View {
@StateObject private var sdk: FastCommentsFeedSDK = {
let config = FastCommentsWidgetConfig(
tenantId: "YOUR_TENANT_ID",
urlId: "my-feed",
sso: ssoToken
)
return FastCommentsFeedSDK(config: config)
}()
@State private var commentsPost: FeedPost?
var body: some View {
FastCommentsFeedView(sdk: sdk)
.onPostSelected { post in
commentsPost = post
}
.onCommentsRequested { post in
commentsPost = post
}
.onSharePost { post in
// ืืฆื ืืืืื ืฉืืชืืฃ
}
.onUserClick { context, userInfo, source in
// ื ืืื ืืคืจืืคืื ืืืฉืชืืฉ
}
.onMediaClick { mediaItem, index in
// ืืฆื ืืฆืื ืชืืื ื ืืืกื ืืื
}
.task {
try? await sdk.loadIfNeeded()
}
}
}
ืชืฆืืืช ืืคืื ืืืืืช ืืฉืืื ืืจืขื ืื ืืืืืื ืืื ืกืืคืืช ืืืืืืืืช.
ืืฉืชืืฉ ื-loadIfNeeded() ืืขืช ืืืืืฉ ืืืืืจ ืืื ืืืกื ืืื ืฉืคืื ืงืืื ืื ืืฉืืืืจ ืื ืืืืคืก ืืืจื ืืืฃ 1.
ืืฆืืจืช ืคืืกืืื
ืืฉืชืืฉ ื-FeedPostCreateView ืืืฆืืช ืืืคืก ืืฆืืจืช ืคืืกื:
@State private var showCreatePost = false
// ืืืืฃ ืืชืฆืืื ืฉืื:
.sheet(isPresented: $showCreatePost) {
FeedPostCreateView(
sdk: sdk,
onPostCreated: { post in
showCreatePost = false
Task { try? await sdk.refresh() }
},
onCancelled: {
showCreatePost = false
}
)
}
ืชืืืื ืืคืืกืืื
ื-SDK ืืืคื ืืชืืืืืช ืขื ืขืืืื ืื ืืืคืืืืืกืืืื:
try await sdk.reactPost(postId: post.id, reactionType: "l")
// ืืืืง ืืช ืืฆื ืืชืืืื
let hasLiked = sdk.hasUserReacted(postId: post.id, reactType: "l")
let likeCount = sdk.getLikeCount(postId: post.id)
ืคืชืืืช ืชืืืืืช ืขื ืคืืกื
ืืฉืชืืฉ ื-CommentsSheet ืืื ืืืฆืื ืชืืืืืช ืขืืืจ ืคืืกื ืืคืื. ืืื ืืืฆืจ ืืืคืข ืฉื FastCommentsSDK ืคื ืืืืช ืืืืฆืขืืช ืืงืื ืคืืืืจืฆืื ืฉื ื-feed SDK:
.sheet(item: $commentsPost) { post in
CommentsSheet(post: post, feedSDK: sdk, onUserClick: { context, userInfo, source in
// ืืืคืื ืืืืืฆื ืขื ืืฉืชืืฉ
})
}
ืืขืจื: FeedPost ืืืื ืืืชืืื ื-Identifiable ืขืืืจ .sheet(item:). ืืืกืฃ ืืช ืืืจืืื ืืืื:
extension FeedPost: @retroactive Identifiable {}
ืกืื ืื ืคืื ืืคื ืชืืืืช
ืืืฉ ืืช ืคืจืืืืงืื TagSupplier ืืื ืืกื ื ืคืืกืืื ืืคืื ืืคื ืชืืืืช:
struct TeamTagSupplier: TagSupplier {
func getTags(currentUser: UserSessionInfo?) -> [String]? {
guard let user = currentUser else { return nil }
return ["team:\(user.id ?? "")", "public"]
}
}
sdk.tagSupplier = TeamTagSupplier()
ืืืืจ nil ืขืืืจ ืคืื ืืืืืื ืืื ืกืื ืื.
ืฉืืืจื ืืฉืืืืจ ืืฆื ืืคืื
ืฉืืืจ ืืช ืืฆื ืืืคืืืฃ (pagination) ืืื ืืืจืืขื ืืืืืจ ืืื ืืชืฆืืื:
let state = sdk.savePaginationState()
// ืืืืืจ ืืืชืจ...
sdk.restorePaginationState(state)
try? await sdk.loadIfNeeded()
ืื ืืืกื ืฉืื ื ืขืื ืืื ืืช, ืชืฆืืืช ืืคืื ืขืืฆืจืช ืขืืืื ืื ืืืื ืืืืืืืืช ืืืืฉืืื ืืืชื ืืืืคืขื ืืืืจืช ืืืื ืื ืงืืช ืคืืกืืื ืฉืืืืขื ื. ืงืจื ื-sdk.cleanup() ืจืง ืืฉืชืืื ืืืืช ืืืืจ ืขื ืืืคืข ื-SDK.
ืืืืงืช ืคืืกืืื
sdk.onPostDeleted = { postId in
print("Post \(postId) was deleted")
}
ืขืจืืืช ื ืืฉื 
ืชืื ืืืช ื ืืฉื
ืืจืืข ืชืื ืืืช ืืืื ืืช ืืืื ืืช:
// ืืจืืจืืช ืืืื ืฉื ืืืขืจืืช
sdk.theme = FastCommentsTheme.default
// ืงืืคืื ืขื ืฆืืืื ืืคืื ืืช ืืขืืืืืช ืืืืืืช
sdk.theme = FastCommentsTheme.modern
// ืฉืืื, ืืื ืฆืืืื, ืจืืืืก ืคืื ืืช ืงืื, ืืื ืงืืื ืฉืจืฉืืจ
sdk.theme = FastCommentsTheme.minimal
// ืงืืข ืืช ืื ืฆืืขื ืืคืขืืืืช ืืฆืืข ืืืชื ืืืื
sdk.theme = FastCommentsTheme.allPrimary(.indigo)
ืกืื ืื ืืช ืชืฆืืืช ืชืืืืืช
var theme = FastCommentsTheme()
theme.commentStyle = .flat // ืจืฉืืื ืฉืืืื ืขื ืืคืจืืืื (ืืจืืจืช ืืืื)
theme.commentStyle = .card // ืงืืคืื ืืขืืืืื ืขื ืฆืืืื
theme.commentStyle = .bubble // ืกืื ืื ืืืขืช ืฉืืื
ืฆืืขืื
ืื ืืืคืืื ื ืืฆืืข ืืืคืฆืืื ืืืื. ืขืจืืื ืฉืื ืืืืืจื ืืืืจื ืืืจืืจืืช ืืืืื ืืกืืืจืืช ืฉื ืืืขืจืืช.
var theme = FastCommentsTheme()
// ืฆืืขื ืืืชื
theme.primaryColor = .indigo
theme.primaryLightColor = .indigo.opacity(0.6)
theme.primaryDarkColor = Color(red: 0.2, green: 0.1, blue: 0.5)
// ืจืงืขืื
theme.commentBackgroundColor = Color(.secondarySystemGroupedBackground)
theme.containerBackgroundColor = Color(.systemGroupedBackground)
// ืืคืชืืจื ืคืขืืื
theme.actionButtonColor = .indigo
theme.replyButtonColor = .indigo
theme.toggleRepliesButtonColor = .indigo.opacity(0.8)
theme.loadMoreButtonTextColor = .indigo
// ืืฆืืขืืช
theme.voteActiveColor = .red
theme.voteCountColor = .primary
theme.voteCountZeroColor = .secondary
theme.voteDividerColor = Color(.separator)
// ืงืืฉืืจืื
theme.linkColor = .indigo
theme.linkColorPressed = .indigo.opacity(0.5)
// ืชืืืืช ืื-ืฉืื
theme.dialogHeaderBackgroundColor = .indigo
theme.dialogHeaderTextColor = .white
// ืกืจืื ืงืื
theme.inputBarBackgroundColor = Color(.systemBackground)
theme.inputBarBorderColor = Color(.separator)
// ืืืจืื
theme.onlineIndicatorColor = .green
theme.separatorColor = Color(.separator)
theme.badgeBackgroundColor = .gray.opacity(0.2)
theme.threadLineColor = .indigo.opacity(0.15)
ืืืคืืืจืคืื
theme.commenterNameFont = .subheadline.weight(.bold)
theme.bodyFont = .body
theme.captionFont = .caption
theme.actionFont = .caption.weight(.medium)
ืคืจืืกื ืืจืืืื
theme.cornerRadius = .large // ืืคืฉืจืืืืช: .none, .small, .medium, .large
theme.commentSpacing = 4 // ื ืงืืืืช ืืื ืฉืืจืืช ืชืืืืืช
theme.nestingIndent = 20 // ื ืงืืืืช ืืืื ืืื ืจืืช ืฉืจืฉืืจ
theme.avatarSize = 36 // ืงืืืจ ืืืืืืืจ ืืชืืืืืช ืฉืืจืฉ
theme.replyAvatarSize = 28 // ืงืืืจ ืืืืืืืจ ืืชืืืืืช ืืงืื ื ืืช
ืืคืงืืื ืืืืืืืืื
theme.showShadows = true // ืฆืืืื ืขืืื ืื ืขื ืงืืคืื
theme.showThreadLine = true // ืงื ืื ืื ืืืืืจ ืชืืืืืช ืืงืื ื ืืช
theme.animateVotes = true // ืื ืืืฆืืืช ืงืคืืฅ ืืขืช ืฉืื ืืื ืืฆืืขื
ืืืืช ืขืจืืืช ื ืืฉื
ืฉืชื ืืืฉืืช:
// Via SwiftUI environment (recommended for view hierarchy)
FastCommentsView(sdk: sdk)
.fastCommentsTheme(theme)
// Directly on the SDK
sdk.theme = theme
ืืคืชืืจื ืกืจืื ืืืื ืืืชืืืื 
ืืคืชืืจื ืกืจืื ืืืืื ืฉื ืชืืืืืช
ืืืฉ ืืช ืืคืจืืืืงืื CustomToolbarButton ืืื ืืืืกืืฃ ืืคืชืืจืื ืืกืจืื ืืืืื ืฉื ืฉืื ืืชืืืื:
struct EmojiButton: CustomToolbarButton {
let id = "emoji"
let iconSystemName = "face.smiling" // ืฉื ื-SF Symbol
let contentDescription = "Add Emoji"
let badgeText: String? = nil // ืกืคืืจืช ืชื ืืืคืฆืืื ืืืช
func onClick(text: Binding<String>) {
text.wrappedValue += "\u{1F44D}"
}
// ืืคืฉืจืืืืช ืืจืืจืช ืืืื ืฉื ืืชื ืืช ืืืืืคื (ืืจืืจืช ืืืื true)
func isEnabled() -> Bool { true }
func isVisible() -> Bool { true }
}
ืืขืืจ ืืคืชืืจืื ืืืชืืืื ืืขืช ืืฆืืจืช ืืชืฆืืื:
FastCommentsView(
sdk: sdk,
customToolbarButtons: [EmojiButton(), CodeBlockButton()]
)
ืื ืืืกืฃ ืืืชื ืืืืคื ืืืืืื ื-SDK (ืื ืขื ืื ืืืืคืขืื):
sdk.addGlobalCustomToolbarButton(EmojiButton())
sdk.removeGlobalCustomToolbarButton(id: "emoji")
sdk.clearGlobalCustomToolbarButtons()
ืืคืชืืจื ืกืจืื ืืืืื ืฉื ืืคืื
ืืืฉ ืืช FeedCustomToolbarButton ืขืืืจ ืืืคืก ืืฆืืจืช ืืคืืกื:
struct HashtagButton: FeedCustomToolbarButton {
let id = "hashtag"
let iconSystemName = "number"
let contentDescription = "Add Hashtag"
func onClick(content: Binding<String>) {
content.wrappedValue += "#"
}
}
ืืขืืจ ืืืชื ืืชืฆืืืช ืืืฆืืจื:
FeedPostCreateView(
sdk: sdk,
customToolbarButtons: [HashtagButton()],
onPostCreated: { _ in },
onCancelled: { }
)
ืื ืืืืจ ืืืชื ืืืืืืืช ื-SDK ืฉื ืืคืื:
sdk.globalFeedToolbarButtons = [HashtagButton()]
ืคืืงืื 
ืคืขืืืืช ืืืื ืืช ืืื ืืืฉืชืืฉืื
- ืกืื/ืืื ืกืืืื -- ืืืืื ืขื ืชืืืื ืืืืื ื
try await sdk.flagComment(commentId: commentId)
try await sdk.unflagComment(commentId: commentId)
- ืืกืื/ืืื ืืกืืื -- ืืืกืชืืจ ืืช ืื ืืชืืืืืช ืฉื ืืฉืชืืฉ (ืืฆืืคื ืกืคืฆืืคื)
try await sdk.blockUser(commentId: commentId)
try await sdk.unblockUser(commentId: commentId)
ืคืขืืืืช ืืื ืืืื ืืืื
- ืืฆืื/ืืื ืืฆืืื -- ืืืฆืืื ืชืืืื ืืจืืฉ ืืฉืจืฉืืจ
try await sdk.pinComment(commentId: commentId)
try await sdk.unpinComment(commentId: commentId)
- ื ืขื/ืืื ื ืขืืื -- ืืื ืืข ืชืืืืืช ืืืฉืืช ืขื ืชืืืื
try await sdk.lockComment(commentId: commentId)
try await sdk.unlockComment(commentId: commentId)
ืื ืคืขืืืืช ืืืืืจืฆืื ืืืื ืืช ืื ืืจื ืชืคืจืื ืืืงืฉืจ ืฉื ืชืืืื ืืืืฉืง ืืืฉืชืืฉ. ืคืขืืืืช ืื ืื ืืืคืืขืืช ืจืง ืืืฉืจ ืืืฉืชืืฉ ืื ืืืื ืืื ืื ืื ืืืชืจ (ื ืงืืข ืืืืฆืขืืช ืืื SSO isAdmin ืื ืืืืืจืืช ืืื ืืืงืจื).
ืขืืืื ืื ืืืื ืืืช 
ืืืืจ ืงืจืืื ื-sdk.load(), ื-SDK ื ืจืฉื ืืืืืืืืช ืืืืจืืขื WebSocket ืขืืืจ urlId ืืืืืืจ. ืืืืจืืขืื ืืืืื ืืืืคืืื:
- ืชืืืืืช ืืืฉืืช, ืขืจืืืืช ืืืืืงืืช
- ืืฆืืขืืช (ืืืกืคื ืืืกืจื)
- ืฉืื ืืืื ืืืฆื ื ืขืืฆื, ื ืขืืื, ืืื ืืืกืืื
- ื ืืืืืช ืืฉืชืืฉ (ืืฆืืจืคืืช/ืขืืืื)
- ืคืชืืื/ืกืืืจื ืฉื ืฉืจืฉืืจ
- ืืขื ืงืช ืชืืื
- ืขืืืื ื ืชืฆืืจืช ืืฉืจืช
ืฉืืืื ืืชืฆืืื ืืืื
ืืืจืืจืช ืืืื, ืชืืืืืช ืืืฉืืช ืืืฉืชืืฉืื ืืืจืื ืืืคืืขืืช ืืื:
sdk.showLiveRightAway = true // ืืืจืืจืช ืืืื: ืืฆื ืืื
ืืืืจ ืืืช ื-false ืืื ืืืืจ ืชืืืืืช ืืืฉืืช ืืืืืจื ืืคืชืืจ "N ืชืืืืืช ืืืฉืืช", ืื ืฉืืืคืฉืจ ืืืฉืชืืฉ ืืืืืจ ืืชื ืืืฉืืฃ ืืืชื:
sdk.showLiveRightAway = false
ื ืืืืืช ืืฉืชืืฉ
ืืืืื ื ืืงืืื/ืื ืืงืืื ืืืคืืขืื ืืืืืืืืช ืขื ืืืืืืจืื ืฉื ืืืฉืชืืฉืื ืืืฉืจ ืืฉืจืช ืืืคืฉืจ ืืขืงื ื ืืืืืช. ืืื ืฆืืจื ืืงืื ืคืืืืจืฆืื ื ืืกืคืช ืืฆื ืืืงืื.
ืขืืืื 
ืืืื ืขืืื
// ืชืืืืืช: ืืจืืจืช ืืืื 30
sdk.pageSize = 50
// ืคืื: ืืจืืจืช ืืืื 10
feedSDK.pageSize = 20
ืืขืื ืช ืชืืืืืช ื ืืกืคืืช
ืืืฉืง ืืืฉืชืืฉ ืืฆืื ืืืืืืืืช ืืงืจื ืขืืืื. ื ืืชื ืื ืืืคืขืื ืขืืืื ืืืืคื ืชืื ืืชื:
// ืืขื ืืช ืืขืืื ืืื
try await sdk.loadMore()
// ืืขื ืืช ืื ืื ืืชืจืื (ืืืฉืืช ืื >2000 ืชืืืืืช ืืืขืื ืืืฆืืขืื)
try await sdk.loadAll()
// ืืืืง ืืฆื
sdk.hasMore // ืืื ืงืืืืื ืขืืืืื ื ืืกืคืื
sdk.shouldShowLoadAll()
sdk.getCountRemainingToShow()
ืขืืืื ืชืืืืืช ืืฉื ื
ืชืฉืืืืช ืืงืื ื ืืช ื ืืขื ืืช ืืืืคื ืขืฆืื ื. ืืืฉืจ ืืฉืชืืฉ ืืจืืื ืฉืจืฉืืจ, ืืืฉ ื"ืืืืื" ืืจืืฉืื ืื ื ืืขื ืื. ืืคืชืืจ "ืืขื ืขืื ืชืืืืืช" ืืืคืืข ืื ืงืืืืืช ืชืืืืืช ื ืืกืคืืช. ืื ืื ืืื ืืืืืืืืช ืขื ืืื ืืืฉืง ืืืฉืชืืฉ.
ืืฆื ืืชืฆืคืืช 
ืฉื ื FastCommentsSDK ืึพFastCommentsFeedSDK ืื ืืืืงืืช ืืกืื ObservableObject ืขื ืชืืื ืืช @Published. ื ืืชื ืืฆืคืืช ืืื ืืชืื ืชืฆืืืืช SwiftUI ืฉืื ืืงืืืช ืขืืืื ื ืืืฉืง ืืฉืชืืฉ ืจืืืงืืืืืื.
ืชืืื ืืช Published ืฉื FastCommentsSDK
| Property | Type | Description |
|---|---|---|
commentCountOnServer |
Int |
ืืกืคืจ ืืืื ืฉื ืชืืืืืช ืืฉืจืช |
newRootCommentCount |
Int |
ืชืืืืืช ืืืฉืืช ืฉืืฆืืืจื (ืืืฉืจ showLiveRightAway ืืื false) |
currentUser |
UserSessionInfo? |
ืืืฉืชืืฉ ืืืืืืช ืื ืืืื |
isSiteAdmin |
Bool |
ืืื ืืืฉืชืืฉ ืื ืืืื ืืื ืื ืื ืืืชืจ |
isClosed |
Bool |
ืืื ืฉืจืฉืืจ ืืชืืืืืช ืกืืืจ |
hasBillingIssue |
Bool |
ืืื ืงืืืืช ืืขืืืช ืชืฉืืื |
isLoading |
Bool |
ืืื ืืงืฉืช ืจืฉืช ืืชืืืื |
hasMore |
Bool |
ืืื ืงืืืืื ืขืื ืืคื ืชืืืืืช |
blockingErrorMessage |
String? |
ืฉืืืื ืืืืกืืช ืืช ืคืขืืืช ืืืืฉืง |
warningMessage |
String? |
ืืืืขืช ืืืืจื ืื ืืืกืืช |
isDemo |
Bool |
ืืื ืคืืขื ืืืฆื ืืืืื |
commentsVisible |
Bool |
ืืชื ืืืฆืืช ืชืืืืืช |
toolbarEnabled |
Bool |
ืืื ืกืจืื ืืขืืฆืื ืืืฆื |
ืชืืื ืืช Published ืฉื FastCommentsFeedSDK
| Property | Type | Description |
|---|---|---|
feedPosts |
[FeedPost] |
ืคืืกืืื ืฉื ื-feed ืฉืืขืื ืื ืืจืืข |
hasMore |
Bool |
ืืื ืงืืืืื ืขืื ืืคืื |
currentUser |
UserSessionInfo? |
ืืืฉืชืืฉ ืืืืืืช ืื ืืืื |
blockingErrorMessage |
String? |
ืืืืขืช ืฉืืืื ืืืกืืช |
isLoading |
Bool |
ืืื ืืงืฉืช ืจืฉืช ืืชืืืื |
newPostsCount |
Int |
ืืกืคืจ ืคืืกืืื ืืืฉืื ืืื ืืืขืื ื ืืืืจืื ื |
ืขืฅ ืืชืืืืืช
ื ืืชื ืืืฉืช ืืขืฅ ืืชืืืืืช ืืจื sdk.commentsTree:
// ืจืฉืืื ืฉืืืื ืฉื ืฆืืชืื ืืืืืื ืืืฆืื
sdk.commentsTree.visibleNodes
// ืืืคืืฉ ืชืืืื ืืคื ืืืื
sdk.commentsTree.commentsById["comment-id"]
ืืืืจ ืืืืืื ืืืืจืืคื 
ืืื ืืืฉืชืืฉ ืืืจืื ืื ืชืื ืื ืฉื ืืืืืื ืืืืจืืคื, ืืืืจ ืืช ืืฉืื region ืืงืื ืคืืืืจืฆืื ืฉืื:
let config = FastCommentsWidgetConfig(
tenantId: "YOUR_TENANT_ID",
urlId: "my-page",
region: "eu"
)
ืื ืื ืชื ืืช ืื ืืงืฉืืช ื-API ืืืืืืืจืื ืฉื WebSocket ืื eu.fastcomments.com.
ื ืืงืื 
ืืฉืชืกืืืื ืขื ืืืคืข ืฉื ื-SDK (ืืืฉื, ืืืฉืจ ืืชืฆืืื ืืชืืืืช), ืงืจืื ื-cleanup() ืืื ืืกืืืจ ืืช ืืืืืจ ื-WebSocket ืืืืื ืืฉืืืืช ืืจืงืข:
sdk.cleanup()
ืขืืืจ ืชืฆืืืืช ืื ืืืืืช ืขื ืืื @StateObject ืฉื SwiftUI, ืืืจื ืืื ื ืงืจื ืืื ื-.onDisappear ืื ืืืฉืจ ืืชืฆืืื ืืฉืืืจืจืช ืืืืืืจืื.
ืืขืืืช ืชืืื ืืช 
ืชืืืืืช
let imageUrl = try await sdk.uploadImage(imageData: jpegData, filename: "photo.jpg")
ืืืืืจ ืืช ืืืจืืืช ื-URL ืฉื ืืชืืื ื ืฉืืืขืืชื.
ืคืืกืืื ืืคืื
let mediaItem = try await feedSDK.uploadImage(imageData: jpegData, filename: "photo.jpg")
// ืืขืืืช ืืกืคืจ ืชืืื ืืช ืืืงืืื
let mediaItems = try await feedSDK.uploadImages(images: [
(jpegData1, "photo1.jpg"),
(jpegData2, "photo2.jpg")
])
ืืืืืจืื ืืืฉืชืืฉืื 
Search for users to support @mention autocomplete:
let results = try await sdk.searchUsers(query: "jan")
// ืืืืืจ [UserSearchResult] ืขื userId, username, avatar ืืื'.
The built-in CommentInputBar ืืืคื ืืืฉืืื ืืืืืืืืืช ืฉื @mention.
ืขืจืืื ืืืืืงื ืฉื ืชืืืืืช 
ืขืจืืื
try await sdk.editComment(commentId: commentId, newText: "Updated text")
ืืฉืจืช ืืืืฆืจ ืืืืฉ ืืช ื-HTML. ืืชืืืื ืืืงืืืืช ืืชืขืืื ืช ืืืืืืืืช.
ืืืืงื
try await sdk.deleteComment(commentId: commentId)
ืืืืงืช ืชืืืื ืืกืืจื ืื ืืช ืืฆืืฆืืื ืฉืื ืืืขืฅ ืืืงืืื.
ืฉืชื ืืคืขืืืืช ืืืื ืืช ืืจื ืชืคืจืื ืืืงืฉืจ ืฉื ืืชืืืื ืืืืฉืง ืืืฉืชืืฉ ืืืฉืจ ืืืฉืชืืฉ ืื ืืืื ืืื ืืืืจ ืืชืืืื (ืื ืื ืื ืืืชืจ).
ืืืคืื ืืฉืืืืืช 
ืฉืืืืช SDK ืืืจืงืืช FastCommentsError, ืฉืืขืืืืช ื-LocalizedError:
do {
try await sdk.load()
} catch let error as FastCommentsError {
print(error.translatedError ?? error.reason ?? "Unknown error")
} catch {
print(error.localizedDescription)
}
FastCommentsError ืืืคืืื ืื:
code-- ืงืื ืฉืืืื ืื-APIreason-- ืชืืืืจ ืืฉืืืื ืืื ืืืืชtranslatedError-- ืืืืขืช ืฉืืืื ืืชืืจืืืช ืืืกืืคืงืช ืขื ืืื ืืฉืจืช
ืฉืืืืืช ืืืืกืืืช ืื ืืืฆืืืช ืืืืืืืืช ืืืืฆืขืืช sdk.blockingErrorMessage, ืฉืืชืฆืืืืช ืืืืื ืืช ืืฆืืืืช ืืืฉืชืืฉ.
ืืืงืืืืฆืื 
ืืขืืจ ืงืื locale ืืงืื ืคืืืืจืฆืื ืืื ืืืฆืข ืืืงืืืืฆืื ืฉื ืืืจืืืืช ืฉืืกืืคืงืืช ืขื ืืื ืืฉืจืช:
let config = FastCommentsWidgetConfig(
tenantId: "YOUR_TENANT_ID",
urlId: "my-page",
locale: "fr_fr"
)
ืืืจืืืืช ืืืฉืง ืืืฉืชืืฉ ืืฆื ืืืงืื ืืฉืชืืฉืืช ืืืืงืืืืฆืื ืืืืกืกืช bundle ืฉื iOS.
ืืคืืืงืฆืืืช ืืืืื 
ืืืืืจ ืืืื ืืคืืืงืฆืืืช ืืืืื ืืืื ืึพExampleApp/ ืขื ืืืืืืช ืฉื:
- ืชืืืืืช ืืงืื ื ืืช ืขื SSO ืื ืืฉืืื ืืืชืืืื
- ืคืื ืืืจืชื ืขื ืืฆืืจืช ืคืืกืืื ืืกืื ืื ืืคื ืชืืืืช
- ืฆ'ืื ืื
- ืืจืืืืช SSO ืคืฉืืืืช ืืืืืืืืืช
- ืืคืชืืจื ืกืจืื ืืืื ืืืชืืืื (ืืชืืืืืช ืืืคืื)
ืืงืืงืื ืืขืืจื?
ืื ืชืืชืงืื ืืืขืืืช ืื ืืฉ ืืื ืฉืืืืช ืืืื ืกืคืจืืืช iOS, ืื ื:
ืชืจืืืืช
ืชืจืืืืช ืืชืงืืืืช ืืืจืื! ืื ื ืืงืจื ื-ืืืืจ ื-GitHub ืืงืืืช ืื ืืืืช ืืชืจืืื.