公告

👇欢迎大家关注公众号&私信交流👇

Skip to content

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 平台插件开发的关键点:

  1. 规范的项目结构
  2. 完善的生命周期管理
  3. 优秀的内存管理
  4. 良好的系统集成

通过本系列文章的学习,你应该已经掌握了 Flutter 插件在各个平台的开发要点,能够开发出高质量的跨平台插件。