Flutter 插件开发 iOS 平台篇
开发环境配置
1. iOS 开发环境
- Xcode 安装
- CocoaPods 配置
- iOS SDK 设置
2. 项目配置
ruby
# ios/example_plugin.podspec
Pod::Spec.new do |s|
s.name = 'example_plugin'
s.version = '0.0.1'
s.summary = 'A new Flutter plugin.'
s.description = 'A Flutter plugin for iOS platform.'
s.homepage = 'http://example.com'
s.license = { :file => '../LICENSE' }
s.author = { 'Your Company' => 'email@example.com' }
s.source = { :path => '.' }
s.source_files = 'Classes/**/*'
s.platform = :ios, '11.0'
s.dependency 'Flutter'
# 其他依赖
end
插件实现
1. Swift 实现
swift
// ios/Classes/SwiftExamplePlugin.swift
import Flutter
import UIKit
public class SwiftExamplePlugin: NSObject, FlutterPlugin {
public static func register(with registrar: FlutterPluginRegistrar) {
let channel = FlutterMethodChannel(
name: "example_plugin",
binaryMessenger: registrar.messenger()
)
let instance = SwiftExamplePlugin()
registrar.addMethodCallDelegate(instance, channel: channel)
}
public func handle(_ call: FlutterMethodCall, result: @escaping FlutterResult) {
switch call.method {
case "getPlatformVersion":
result("iOS " + UIDevice.current.systemVersion)
default:
result(FlutterMethodNotImplemented)
}
}
}
2. Objective-C 实现
objc
// ios/Classes/ExamplePlugin.h
#import <Flutter/Flutter.h>
@interface ExamplePlugin : NSObject<FlutterPlugin>
@end
// ios/Classes/ExamplePlugin.m
#import "ExamplePlugin.h"
@implementation ExamplePlugin
+ (void)registerWithRegistrar:(NSObject<FlutterPluginRegistrar>*)registrar {
FlutterMethodChannel* channel = [FlutterMethodChannel
methodChannelWithName:@"example_plugin"
binaryMessenger:[registrar messenger]];
ExamplePlugin* instance = [[ExamplePlugin alloc] init];
[registrar addMethodCallDelegate:instance channel:channel];
}
- (void)handleMethodCall:(FlutterMethodCall*)call result:(FlutterResult)result {
if ([@"getPlatformVersion" isEqualToString:call.method]) {
result([@"iOS " stringByAppendingString:[[UIDevice currentDevice] systemVersion]]);
} else {
result(FlutterMethodNotImplemented);
}
}
@end
生命周期管理
1. 视图控制器生命周期
swift
public class SwiftExamplePlugin: NSObject, FlutterPlugin {
private var viewController: UIViewController?
public static func register(with registrar: FlutterPluginRegistrar) {
let viewController = registrar.messenger() as? FlutterViewController
let instance = SwiftExamplePlugin(viewController: viewController)
// 注册插件
}
init(viewController: UIViewController?) {
self.viewController = viewController
super.init()
NotificationCenter.default.addObserver(
self,
selector: #selector(applicationWillResignActive),
name: UIApplication.willResignActiveNotification,
object: nil
)
}
@objc private func applicationWillResignActive() {
// 处理应用进入后台
}
deinit {
NotificationCenter.default.removeObserver(self)
}
}
2. 内存管理
swift
public class SwiftExamplePlugin: NSObject, FlutterPlugin {
private var cache = NSCache<NSString, AnyObject>()
override init() {
super.init()
NotificationCenter.default.addObserver(
self,
selector: #selector(clearMemory),
name: UIApplication.didReceiveMemoryWarningNotification,
object: nil
)
}
@objc private func clearMemory() {
cache.removeAllObjects()
}
}
系统特性集成
1. 权限处理
swift
import Photos
public class SwiftExamplePlugin: NSObject, FlutterPlugin {
private func checkPhotoLibraryPermission(result: @escaping FlutterResult) {
let status = PHPhotoLibrary.authorizationStatus()
switch status {
case .authorized:
result(true)
case .notDetermined:
PHPhotoLibrary.requestAuthorization { status in
DispatchQueue.main.async {
result(status == .authorized)
}
}
default:
result(false)
}
}
}
2. 系统服务集成
swift
import CoreLocation
public class SwiftExamplePlugin: NSObject, FlutterPlugin, CLLocationManagerDelegate {
private let locationManager = CLLocationManager()
private var locationResult: FlutterResult?
override init() {
super.init()
locationManager.delegate = self
}
private func requestLocation(result: @escaping FlutterResult) {
locationResult = result
locationManager.requestWhenInUseAuthorization()
locationManager.startUpdatingLocation()
}
public func locationManager(
_ manager: CLLocationManager,
didUpdateLocations locations: [CLLocation]
) {
guard let location = locations.first else { return }
locationResult?(["latitude": location.coordinate.latitude,
"longitude": location.coordinate.longitude])
locationResult = nil
locationManager.stopUpdatingLocation()
}
}
性能优化
1. 并发处理
swift
public class SwiftExamplePlugin: NSObject, FlutterPlugin {
private let queue = DispatchQueue(label: "com.example.plugin", qos: .userInitiated)
private func performHeavyTask(result: @escaping FlutterResult) {
queue.async {
// 执行耗时操作
let data = self.processData()
DispatchQueue.main.async {
result(data)
}
}
}
}
2. 资源管理
swift
public class SwiftExamplePlugin: NSObject, FlutterPlugin {
private var imageCache = NSCache<NSString, UIImage>()
private func cacheImage(_ image: UIImage, forKey key: String) {
imageCache.setObject(image, forKey: key as NSString)
}
private func getCachedImage(forKey key: String) -> UIImage? {
return imageCache.object(forKey: key as NSString)
}
}
调试与测试
1. 日志记录
swift
public class SwiftExamplePlugin: NSObject, FlutterPlugin {
private func log(_ message: String, level: LogLevel = .debug) {
#if DEBUG
print("[ExamplePlugin] \(level.rawValue): \(message)")
#endif
}
enum LogLevel: String {
case debug = "DEBUG"
case error = "ERROR"
case info = "INFO"
}
}
2. 单元测试
swift
// ios/Tests/ExamplePluginTests.swift
import XCTest
@testable import example_plugin
class ExamplePluginTests: XCTestCase {
var plugin: SwiftExamplePlugin!
override func setUp() {
super.setUp()
plugin = SwiftExamplePlugin()
}
func testPlugin() {
// 测试代码
}
}
最佳实践
1. 代码规范
- 使用 Swift 编写新代码
- 遵循 iOS 设计规范
- 采用 Swift 编码风格
2. 错误处理
swift
enum PluginError: Error {
case invalidArguments
case unauthorized
case notAvailable
var description: String {
switch self {
case .invalidArguments:
return "Invalid arguments provided"
case .unauthorized:
return "User not authorized"
case .notAvailable:
return "Feature not available"
}
}
}
3. 版本兼容
- 处理 iOS 版本差异
- 提供向后兼容性
- 文档化版本要求
总结
iOS 平台插件开发的关键点:
- 规范的项目结构
- 完善的生命周期管理
- 优秀的内存管理
- 良好的系统集成
通过本系列文章的学习,你应该已经掌握了 Flutter 插件在各个平台的开发要点,能够开发出高质量的跨平台插件。