iOS架构概览
以下是iOS应用架构的核心层次:
graph TB
A[用户界面层] --> B[业务逻辑层]
B --> C[数据访问层]
C --> D[系统框架层]
A1[UIViewController] --> A
A2[UIView] --> A
A3[SwiftUI/UIKit] --> A
B1[ViewModel] --> B
B2[Manager] --> B
B3[Service] --> B
C1[Repository] --> C
C2[Data Models] --> C
C3[Core Data/Realm] --> C
D1[Foundation] --> D
D2[Core Graphics] --> D
D3[Network] --> D
D4[Security] --> D
核心架构模式
1. MVC (Model-View-Controller)
swift
// Model
struct User {
let id: Int
let name: String
let email: String
}
// View
class UserView: UIView {
private let nameLabel = UILabel()
private let emailLabel = UILabel()
func configure(with user: User) {
nameLabel.text = user.name
emailLabel.text = user.email
}
}
// Controller
class UserViewController: UIViewController {
private let userView = UserView()
private var user: User?
override func viewDidLoad() {
super.viewDidLoad()
setupView()
fetchUser()
}
private func fetchUser() {
// 获取用户数据
user = User(id: 1, name: "John", email: "john@example.com")
userView.configure(with: user!)
}
}
2. MVVM (Model-View-ViewModel)
swift
// Model
struct Product {
let id: Int
let name: String
let price: Double
}
// ViewModel
class ProductViewModel {
private let product: Product
var displayName: String {
return product.name
}
var displayPrice: String {
return String(format: "$%.2f", product.price)
}
init(product: Product) {
self.product = product
}
}
// View
class ProductViewController: UIViewController {
@IBOutlet weak var nameLabel: UILabel!
@IBOutlet weak var priceLabel: UILabel!
var viewModel: ProductViewModel! {
didSet {
updateUI()
}
}
private func updateUI() {
nameLabel.text = viewModel.displayName
priceLabel.text = viewModel.displayPrice
}
}
3. VIPER (View-Interactor-Presenter-Entity-Router)
swift
// Entity
struct Article {
let title: String
let content: String
}
// Interactor
protocol ArticleInteractorProtocol {
func fetchArticles()
}
class ArticleInteractor: ArticleInteractorProtocol {
weak var presenter: ArticlePresenterProtocol?
func fetchArticles() {
// 网络请求获取文章
let articles = [Article(title: "iOS架构", content: "...")]
presenter?.articlesFetched(articles)
}
}
// Presenter
protocol ArticlePresenterProtocol: AnyObject {
func viewDidLoad()
func articlesFetched(_ articles: [Article])
}
class ArticlePresenter: ArticlePresenterProtocol {
weak var view: ArticleViewProtocol?
var interactor: ArticleInteractorProtocol
var router: ArticleRouterProtocol
init(view: ArticleViewProtocol, interactor: ArticleInteractorProtocol, router: ArticleRouterProtocol) {
self.view = view
self.interactor = interactor
self.router = router
}
func viewDidLoad() {
interactor.fetchArticles()
}
func articlesFetched(_ articles: [Article]) {
view?.showArticles(articles)
}
}
核心技术栈
1. 用户界面框架
SwiftUI (现代声明式UI)
swift
struct ContentView: View {
@State private var isLoggedIn = false
@StateObject private var userModel = UserModel()
var body: some View {
NavigationView {
if isLoggedIn {
DashboardView()
.environmentObject(userModel)
} else {
LoginView(isLoggedIn: $isLoggedIn)
}
}
}
}
struct LoginView: View {
@Binding var isLoggedIn: Bool
@State private var username = ""
@State private var password = ""
var body: some View {
VStack(spacing: 20) {
TextField("用户名", text: $username)
.textFieldStyle(RoundedBorderTextFieldStyle())
SecureField("密码", text: $password)
.textFieldStyle(RoundedBorderTextFieldStyle())
Button("登录") {
authenticateUser()
}
.disabled(username.isEmpty || password.isEmpty)
}
.padding()
}
private func authenticateUser() {
// 认证逻辑
isLoggedIn = true
}
}
UIKit (传统命令式UI)
swift
class ProfileViewController: UIViewController {
private let tableView = UITableView()
private let profileHeaderView = ProfileHeaderView()
private var user: User?
override func viewDidLoad() {
super.viewDidLoad()
setupTableView()
setupConstraints()
loadUserData()
}
private func setupTableView() {
tableView.delegate = self
tableView.dataSource = self
tableView.register(UserInfoCell.self, forCellReuseIdentifier: "UserInfoCell")
view.addSubview(tableView)
}
private func loadUserData() {
UserService.shared.fetchUser { [weak self] user in
self?.user = user
self?.tableView.reloadData()
}
}
}
2. 数据持久化
Core Data
swift
// Core Data Stack
class CoreDataStack {
static let shared = CoreDataStack()
lazy var persistentContainer: NSPersistentContainer = {
let container = NSPersistentContainer(name: "MyApp")
container.loadPersistentStores { description, error in
if let error = error {
fatalError("Unable to load persistent stores: \(error)")
}
}
return container
}()
var context: NSManagedObjectContext {
return persistentContainer.viewContext
}
}
// Data Model
class UserEntity: NSManagedObject {
@NSManaged var id: Int64
@NSManaged var name: String
@NSManaged var email: String
}
// Repository Pattern
class UserRepository {
private let context: NSManagedObjectContext
init(context: NSManagedObjectContext = CoreDataStack.shared.context) {
self.context = context
}
func saveUser(_ user: User) throws {
let userEntity = UserEntity(context: context)
userEntity.id = Int64(user.id)
userEntity.name = user.name
userEntity.email = user.email
try context.save()
}
func fetchUsers() throws -> [User] {
let request: NSFetchRequest<UserEntity> = UserEntity.fetchRequest()
let entities = try context.fetch(request)
return entities.map { User(id: Int($0.id), name: $0.name, email: $0.email) }
}
}
3. 网络层架构
swift
// API Client
protocol APIClient {
func request<T: Decodable>(_ endpoint: Endpoint) async throws -> T
}
class NetworkManager: APIClient {
private let session: URLSession
private let baseURL = "https://api.example.com"
init(session: URLSession = .shared) {
self.session = session
}
func request<T: Decodable>(_ endpoint: Endpoint) async throws -> T {
let request = try endpoint.urlRequest(baseURL: baseURL)
let (data, response) = try await session.data(for: request)
guard let httpResponse = response as? HTTPURLResponse,
(200...299).contains(httpResponse.statusCode) else {
throw NetworkError.invalidResponse
}
return try JSONDecoder().decode(T.self, from: data)
}
}
// Endpoint Protocol
protocol Endpoint {
var path: String { get }
var method: HTTPMethod { get }
var parameters: [String: Any]? { get }
var headers: [String: String]? { get }
}
extension Endpoint {
func urlRequest(baseURL: String) throws -> URLRequest {
guard let url = URL(string: baseURL)?.appendingPathComponent(path) else {
throw NetworkError.invalidURL
}
var request = URLRequest(url: url)
request.httpMethod = method.rawValue
request.allHTTPHeaderFields = headers
if let parameters = parameters {
if method == .get {
var components = URLComponents(url: url, resolvingAgainstBaseURL: false)
components?.queryItems = parameters.map {
URLQueryItem(name: $0.key, value: "\($0.value)")
}
request.url = components?.url
} else {
request.httpBody = try JSONSerialization.data(withJSONObject: parameters)
}
}
return request
}
}
依赖管理
Swift Package Manager
swift
// Package.swift
// swift-tools-version:5.5
import PackageDescription
let package = Package(
name: "MyApp",
platforms: [
.iOS(.v15)
],
products: [
.library(
name: "MyApp",
targets: ["MyApp"]),
],
dependencies: [
.package(url: "https://github.com/Alamofire/Alamofire.git", from: "5.6.0"),
.package(url: "https://github.com/SnapKit/SnapKit.git", from: "5.6.0")
],
targets: [
.target(
name: "MyApp",
dependencies: ["Alamofire", "SnapKit"]),
.testTarget(
name: "MyAppTests",
dependencies: ["MyApp"]),
]
)
测试架构
swift
// Unit Tests
class UserViewModelTests: XCTestCase {
var viewModel: UserViewModel!
var mockService: MockUserService!
override func setUp() {
super.setUp()
mockService = MockUserService()
viewModel = UserViewModel(userService: mockService)
}
func testUserLoading() async {
// Given
let expectedUser = User(id: 1, name: "Test User", email: "test@example.com")
mockService.user = expectedUser
// When
await viewModel.loadUser()
// Then
XCTAssertEqual(viewModel.user?.name, "Test User")
}
}
// UI Tests
class LoginUITests: XCTestCase {
var app: XCUIApplication!
override func setUp() {
super.setUp()
app = XCUIApplication()
app.launch()
}
func testSuccessfulLogin() {
let usernameTextField = app.textFields["username"]
let passwordTextField = app.secureTextFields["password"]
let loginButton = app.buttons["login"]
usernameTextField.tap()
usernameTextField.typeText("testuser")
passwordTextField.tap()
passwordTextField.typeText("password123")
loginButton.tap()
XCTAssertTrue(app.navigationBars["Dashboard"].exists)
}
}
基础
graph LR
A[Swift语法基础] --> B[iOS SDK基础]
B --> C[UIKit入门]
C --> D[简单项目实践]
A1[变量与类型] --> A
A2[控制流] --> A
A3[函数与闭包] --> A
A4[面向对象] --> A
B1[Cocoa Touch] --> B
B2[Foundation框架] --> B
B3[Auto Layout] --> B
进阶
- 架构模式:深入理解MVC、MVVM
- 网络编程:URLSession、RESTful API
- 数据持久化:Core Data、UserDefaults
- 并发编程:GCD、Operation Queue
高级
- 响应式编程:Combine框架
- 现代UI:SwiftUI深度掌握
- 性能优化:内存管理、性能调优
- 测试驱动开发:单元测试、UI测试
专家
- 架构设计:VIPER、Clean Architecture
- 工程化:CI/CD、模块化
- 底层原理:Runtime、内存管理机制
- 跨平台:Flutter、React Native对比学习