iOS与macOS跨平台应用发布及Objective-C代码复用咨询
跨iOS和macOS应用的发布与Objective-C代码复用方案
刚好之前做过Objective-C的跨平台项目,来分享下我踩过坑后总结的方案,针对你的两个问题逐一解答:
一、如何发布同时支持iOS和macOS的应用
目前有两种主流方案,取决于你的现有项目状态:
1. 基于现有iOS应用用Mac Catalyst快速适配
如果你已经有成熟的iPhone/iPad应用,Mac Catalyst是最快的跨平台路径——它能直接把iOS应用转换成可在macOS上运行的版本:
- 打开你的iOS项目,在Xcode的「Targets」列表里点击「+」,选择「macOS」分类下的「Mac Catalyst」目标;
- 配置新目标的Bundle ID、开发者签名(建议和iOS目标用同一套签名,避免后续发布麻烦);
- 适配macOS特有的交互细节:比如处理鼠标悬停事件、窗口大小自适应、菜单栏功能等,这部分可以通过
UIDevice.current.userInterfaceIdiom或者预编译宏TARGET_OS_MAC来区分平台逻辑; - 测试无误后,分别打包iOS版本提交到App Store,Mac Catalyst版本提交到Mac App Store(都是通过Archive打包,再用Xcode Organizer提交)。
2. 从零开始创建Multi-platform原生项目
如果是新项目,直接创建Multi-platform项目能获得更原生的跨平台体验:
- 新建项目时选择「iOS & macOS」的App模板;
- Xcode会自动生成「Shared」「iOS」「macOS」三个目录,把通用的业务逻辑、工具类放在「Shared」目录,平台特有的UI或功能分别放在对应目录;
- 发布流程和普通应用一致,分别打包两个平台的版本,提交到各自的应用商店即可。
二、Objective-C项目的代码复用与跨平台自定义按钮
1. 避免重复代码构建Mac应用的方法
核心是共享通用代码+平台条件编译,具体操作:
- 在项目中新建一个「SharedCode」目录,把通用的模型类、工具类、业务逻辑的
.h和.m文件放在这里; - 添加这些文件时,同时勾选iOS和macOS两个Target(Xcode会自动帮你把文件关联到两个目标);
- 对于平台特有的代码,用Objective-C的预编译宏做区分,常用宏包括
TARGET_OS_IOS、TARGET_OS_MAC:#ifdef TARGET_OS_IOS // iOS专属逻辑,比如弹出UIAlertController UIAlertController *alert = [UIAlertController alertControllerWithTitle:@"提示" message:nil preferredStyle:UIAlertControllerStyleAlert]; [self presentViewController:alert animated:YES completion:nil]; #elif TARGET_OS_MAC // macOS专属逻辑,比如弹出NSAlert NSAlert *alert = [[NSAlert alloc] init]; [alert setMessageText:@"提示"]; [alert runModal]; #endif
2. 跨平台自定义按钮的实现
因为iOS用UIButton,macOS用NSButton,我们可以通过宏定义+通用逻辑抽离实现一套代码适配两个平台:
- 先创建
CustomButton.h头文件:#import <Foundation/Foundation.h> // 根据平台定义CustomButton的基类 #ifdef TARGET_OS_IOS #import <UIKit/UIKit.h> #define CustomButtonBase UIButton #elif TARGET_OS_MAC #import <AppKit/AppKit.h> #define CustomButtonBase NSButton #endif @interface CustomButton : CustomButtonBase // 通用方法:设置自定义样式 - (void)setupCustomStyle; @end - 再创建
CustomButton.m实现文件:#import "CustomButton.h" @implementation CustomButton - (void)setupCustomStyle { #ifdef TARGET_OS_IOS self.backgroundColor = [UIColor systemBlueColor]; self.titleLabel.font = [UIFont systemFontOfSize:16 weight:UIFontWeightMedium]; [self setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal]; self.layer.cornerRadius = 8.0; #elif TARGET_OS_MAC self.bezelStyle = NSBezelStyleRounded; self.titleFont = [NSFont systemFontOfSize:16 weight:NSFontWeightMedium]; [self setTitleColor:[NSColor whiteColor] forState:NSControlStateNormal]; self.backgroundColor = [NSColor systemBlueColor]; self.wantsLayer = YES; self.layer.cornerRadius = 8.0; #endif } // 统一初始化方法 - (instancetype)initWithFrame:(CGRect)frame { self = [super initWithFrame:frame]; if (self) { [self setupCustomStyle]; } return self; } // 针对macOS的initWithCoder(如果用Storyboard的话) - (instancetype)initWithCoder:(NSCoder *)coder { self = [super initWithCoder:coder]; if (self) { [self setupCustomStyle]; } return self; } @end - 最后把这两个文件添加到iOS和macOS的Target中,在两个平台的代码里就可以直接使用
CustomButton,调用setupCustomStyle就能应用统一的自定义样式,平台特有的差异已经在内部处理好了,不用重复写两套代码。
内容的提问来源于stack exchange,提问作者Vulkan




