avatar

mdo

Hello

  • 首页
  • 知识库
  • 归档
  • 标签
  • 关于
主页 开发一个博客文章发布 App
文章

开发一个博客文章发布 App

发表于 2026-06-19 更新于 2026-06- 19
作者 mdo
27~34 分钟 阅读

针对 iOS 平台开发一个博客文章发布 App(支持写文章、编辑、管理和一键发布),需要兼顾极致的富文本编辑体验与高能的网络通信同步。

以下是为您量身定制的完整开发技术栈、核心架构和功能实现方案:


🎨 核心功能模块

  • 富文本编辑器:支持 Markdown 解析、实时预览、图片/视频插入。

  • 本地草稿箱:支持断网离线编辑,自动保存,防止内容丢失。

  • 媒体库管理:异步上传图片到云存储(如 OSS/S3),获取 URL 插入文章。

  • 文章发布/管理:分类、标签、状态管理(草稿、已发布、私密)。

  • 全双工同步(选配):配合您之前提到的 Golang RPC WebSocket,实现多端多设备文章状态实时同步。


🛠️ 推荐技术栈 (iOS 端)

模块 [1]

推荐方案

说明

UI 框架

SwiftUI

苹果主流,声明式 UI,极其适合做列表和表单展示。

编辑器核心

TextKit 2 / MarkdownUI

TextKit 2 适合定制原生富文本;MarkdownUI 适合渲染排版。

网络层

Alamofire / NWWebSocket

Alamofire 处理标准 RESTful API;NWWebSocket 处理 RPC 通信。

本地数据库

Core Data / GRDB.swift

存储本地草稿、离线文章列表,GRDB 性能极佳。

图片加载

Kingfisher

缓存和异步加载文章内的插图。


💻 核心代码实现:Markdown 编辑器与发布

以下是一个使用 SwiftUI 编写的简单文章编辑器界面,并演示如何将其转化为 JSON 数据准备发布。

swift

import SwiftUI

// 1. 定义文章数据模型
struct BlogPost: Codable {
    var title: String
    var content: String
    var tags: [String]
    var status: String // "draft" 或 "published"
}

struct EditorView: View {
    @State private var title: String = ""
    @State private var content: String = ""
    @State private var tags: String = ""
    @State private var isPublishing = false
    
    var body: some View {
        NavigationView {
            VStack(spacing: 16) {
                // 文章标题输入
                TextField("请输入文章标题...", text: $title)
                    .font(.title2)
                    .bold()
                    .padding(.horizontal)
                
                Divider()
                
                // 标签输入
                TextField("标签 (用逗号分隔)", text: $tags)
                    .font(.subheadline)
                    .foregroundColor(.gray)
                    .padding(.horizontal)
                
                Divider()
                
                // 文章正文编辑器 (支持多行)
                TextEditor(text: $content)
                    .font(.body)
                    .padding(.horizontal)
                    .frame(maxHeight: .infinity)
            }
            .navigationTitle("写文章")
            .navigationBarTitleDisplayMode(.inline)
            .toolbar {
                ToolbarItem(placement: .navigationBarTrailing) {
                    Button(action: publishPost) {
                        if isPublishing {
                            ProgressView()
                        } else {
                            Text("发布")
                                .bold()
                                .foregroundColor(.blue)
                        }
                    }
                    .disabled(title.isEmpty || content.isEmpty || isPublishing)
                }
            }
        }
    }
    
    // 2. 发布文章逻辑
    func publishPost() {
        isPublishing = true
        
        let tagArray = tags.components(separatedBy: ",").map { $0.trimmingCharacters(in: .whitespacesAndNewlines) }
        let post = BlogPost(title: title, content: content, tags: tagArray, status: "published")
        
        // 序列化为 JSON
        guard let jsonData = try? JSONEncoder().encode(post) else { return }
        
        // 发送网络请求 (此处可对接您的 Golang 后端 HTTP API 或 WebSocket RPC)
        sendToServer(data: jsonData)
    }
    
    func sendToServer(data: Data) {
        guard let url = URL(string: "https://yourblogapi.com") else { return }
        var request = URLRequest(url: url)
        request.httpMethod = "POST"
        request.setValue("application/json", forHTTPHeaderField: "Content-Type")
        request.httpBody = data
        
        URLSession.shared.dataTask(with: request) { _, response, error in
            DispatchQueue.main.MainActor.run {
                self.isPublishing = false
                if let error = error {
                    print("发布失败: \(error.localizedDescription)")
                } else {
                    print("发布成功!")
                    // 清空当前输入或返回上一级
                }
            }
        }.resume()
    }
}

请谨慎使用此类代码。


🔗 进阶:如何与 Golang WebSocket RPC 对接?

如果您希望利用上一条聊到的 Golang WebSocket RPC 来发布文章,iOS 端可以采用以下策略:

  1. 消息封装:在 iOS 端将 BlogPost 作为 params,封装进标准的 JSON-RPC 格式:

    json

    {
      "jsonrpc": "2.0",
      "method": "Blog.Publish",
      "params": {
        "title": "我的第一篇iOS文章",
        "content": "内容...",
        "tags": ["Swift", "Go"]
      },
      "id": 101
    }
    

    请谨慎使用此类代码。

  2. 长连接维护:使用原生 URLSessionWebSocketTask 或 Starscream 库保持与 Golang 后端的连接,在用户点击发布时,直接通过 WebSocket 帧(Frame)发送该 JSON 字符串。

  3. 实时状态反馈:后端处理完毕后,通过相同连接返回 id: 101 的 Response,iOS 监听到该消息后更新 UI 为“发布成功”。

技术
许可协议:  CC BY 4.0
分享

相关文章

10月 2, 2026

iOS 侧载(Sideloading)工具

AltStore 和 Sideloadly 都是目前最流行的 iOS 侧载(Sideloading)工具。 简单来说,它们的作用就是让你绕过苹果的官方 App Store,直接把第三方的 IPA 安装包(也就是 iOS 的应用安装文件)安装到你的 iPhone 或 iPad 上。 通过这两个工具,你

9月 28, 2026

注册 Chat Participant

将当前服务接入 VS Code 的 AI 聊天窗口是完全可行的。VS Code 在近期的版本中正式推出了 Chat Extensions API(github.copilot.chat),允许第三方扩展将自定义的 LLM 服务或工具注册到 Copilot Chat 面板中。 结合当前 code_ge

9月 23, 2026

php intelephense 设置 if 空格

在 VS Code 中,如果你使用的是 PHP Intelephense 插件,控制 if 关键字后面是否加空格的设置是由其内置的格式化引擎(基于 PSR-12 标准)决定的。 你可以通过修改 VS Code 的 settings.json 来配置这个行为: 1. 开启 if 后面的空格(默认/推荐

下一篇

Golang 中,结合使用 RPC(远程过程调用)与 WebSocket

上一篇

Redis 缓存余额 + 前端异步局部刷新 + 提供手动刷新按钮

最近更新

  • 比尔盖茨的智慧:想多赚钱,就每天循环做这3件事
  • iOS 侧载(Sideloading)工具
  • 程序员越想创业,越不要急着动手
  • 注册 Chat Participant
  • 中秋给在外游子的一封信

热门标签

API CodeGeex Coding Cursor DeepSeek Docker Gitkraken Harness Laravel Management

目录

©2026 mdo. 保留部分权利。