Mac Catalyst iPad App移植 笔记

0、

最简单的一步:


勾选Mac

官方教程

Xcode相关

注意!!!这个Architectures要加一个
Architectures -> valid architecture
添加一个 x86_64


添加一个 x86_64.png

1、更改platform

However, you may need to manually exclude other content. To do this, go to the Frameworks, Libraries, and Embedded Content list under the General tab for your iOS target. Then select iOS as the platform setting for the item. This setting excludes the item from the Mac version of your app.

Extention 需要舍弃

2、使用系统提供的宏来处理不兼容的代码

if frameworks or API that are unavailable to the Mac version of your app. To remedy this problem, find the code that doesn’t compile, and enclose it as shown here:

注意,这个宏很重要,macOS不兼容代码都可以搁这里边
#if !TARGET_OS_MACCATALYST

// Code to exclude from Mac.

#endif

另外,也可以这么干,macOS代码可以搁这里边(与上边相比去掉了  ! )
#if TARGET_OS_MACCATALYST

// Code to exclude from iOS .

#endif

3、一些无法编译的第三方

Showing All Errors Only

In /Users/XXXXXX/IJKMediaFramework.framework/IJKMediaFramework(IJKMediaPlayback.o), building for Mac Catalyst, but linking in object file built for iOS Simulator, for architecture x86_64

解决方法:

找到这个IJKMediaFramework在项目中引用的地方,

#if !TARGET_OS_MACCATALYST

目标framework

#endif

之后需要解决报错信息,方法同上

4、

Undefined symbol: _OBJC_CLASS_$_XXXXXXX.png

Showing All Errors Only

Undefined symbol: OBJC_CLASS$_ALBBSDK

解决方法同3(全局搜索 "ALBBSDK",屏蔽处理)

5、

LSSupportsOpeningDocumentsInPlace = NO' is not supported on macOS. Either remove the entry or set it to YES, and also ensure that the application does open documents in place on macOS.

解决方案:新建target
[XCode使用四:XCode工程中创建多个Targets]https://blog.csdn.net/hitfyb/article/details/50875657


19.10.22 程序编译成功!!

上边这些应该是都能遇到的问题,之后仍然有许多问题需要解决,大家加油。


如果使用了 pod

建议新建target,pod配置文件根据target配置

可能遇到的问题:

  1. 与iOS不同,所有在mac上运行的bundle都需要签名(sign)。
    解决步骤:点击 Pod Target 里 "Signing & Capabilities"中选择一个Team
bundle需要签名

上传商店遇到这个问题

ITMS-90284: Invalid Code Signing- The executable 'XXX.app/Contents/Frameworks/XXX.framework/Versions/A/Resources/XX.bundle' must be signed with the certificate that is contained in the provisioning profile.

需要在Bundle的Sign界面下的Signing Certificate中选取Sign to Run Locally。

以上解决方法参考Mac Catalyst 初步体验+排坑

2.pod中的三方使用 UIWebview等mac catalyst不支持的api,移除掉或者屏蔽掉,或者干脆不引用(pod配置文件中配置),注意, 执行pod install之后1中的配置修改会被抹掉 ,需要重新配置

关于优化

更像macOS App

Optimizing Your iPad App for Mac

Mac catalyst 支持的UIKit 库列表
官方教程,可以下载Demo做一下参考
UIKit Catalog: Creating and Customizing Views and Controls

添加状态栏菜单 以及 快捷键
Adding Menus and Shortcuts to the Menu Bar and User Interface.
示例代码(OC),官方给的Demo使用Swift,请自行查阅
在 AppDelegate中重写这个方法: buildMenuWithBuilder

-(void)buildMenuWithBuilder:(id<UIMenuBuilder>)builder{
    //插入已存在menu下
    //无快捷键
    UICommand * fileMenuCommend = [UICommand commandWithTitle:@"继续皮" image:nil action:@selector(jixuOpenAction) propertyList:nil];
    //有快捷键
    UIKeyCommand * openMenuCommend = [UIKeyCommand commandWithTitle:@"皮一下" image:nil action:@selector(openAction) input:@"O" modifierFlags:UIKeyModifierCommand propertyList:nil];//注意两个action不能一样
    UIMenu * openMenu = [UIMenu menuWithTitle:@"" image:nil identifier:@"com.example.apple-samplecode.menus.openMenu" options:UIMenuOptionsDisplayInline children:@[openMenuCommend,fileMenuCommend]];
    [builder insertChildMenu:openMenu atStartOfMenuForIdentifier:UIMenuFile];
//添加新的menu
    UICommand * cityCommend = [UICommand commandWithTitle:@"青岛" image:nil action:@selector(openActionP) propertyList:@"青岛"];
     UIKeyCommand * cityMenuCommend = [UIKeyCommand commandWithTitle:@"济南" image:nil action:@selector(openActionD) input:@"P" modifierFlags:UIKeyModifierCommand propertyList:@"济南"];
    UIMenu * cityMenu = [UIMenu menuWithTitle:@"城市" image:nil identifier:@"com.example.apple-samplecode.menus.cityMenu" options:@[] children:@[cityCommend,cityMenuCommend]];
    [builder insertSiblingMenu:cityMenu afterMenuForIdentifier:UIMenuFile];//添加到文件菜单之后
}
-(void)openAction{
    
     NSLog(@"openAction");
}
-(void) jixuOpenAction{
    
     NSLog(@"openAction");
}

在视图中检测鼠标的指针(位置)
使用UIHoverGestureRecognizer
To detect when the user moves the pointer over a view in your app, add a
UIHoverGestureRecognizer to that view.

//创建一个手势,并添加到view上
let hover = UIHoverGestureRecognizer(target: self, action: #selector(hovering(_:)))
button.addGestureRecognizer(hover)
//手势触发的方法
 @objc
    func hovering(_ recognizer: UIHoverGestureRecognizer) {
        switch recognizer.state {
        case .began, .changed:
            button.titleLabel?.textColor = #colorLiteral(red: 1, green: 0, blue: 0, alpha: 1)
        case .ended:
            button.titleLabel?.textColor = UIColor.link
        default:
            break
        }
    }

//OC代码

UIHoverGestureRecognizer * hover = [[UIHoverGestureRecognizer alloc]initWithTarget:self action:@selector(hoveringWithRecognizer:)];
[View addGestureRecognizer:hover];

-(void)hoveringWithRecognizer:(UIHoverGestureRecognizer *)recognizer{
    
    switch (recognizer.state) {
        case (UIGestureRecognizerStateBegan):
            NSLog(@"----------------------------鼠标进入区域");
            break;
        case (UIGestureRecognizerStateEnded):
            NSLog(@"----------------------------鼠标离开区域");
            break;
        default:
            break;
    }
}

干掉頂栏

官方教程在这

///////也可以参考下边的方法

https://fleetingpixels.com/blog/2019/6/7/customising-nstoolbar-in-uikit-for-mac-marzipancatalyst

项目不包含 SceneDelegate.h/SceneDelegate.m的 (老项目不带这俩文件)
appDelegate.m 中

#import <Foundation/Foundation.h>
#import <UIKit/NSToolbar+UIKitAdditions.h>

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions{
            self.window.windowScene.titlebar.titleVisibility = UITitlebarTitleVisibilityHidden;//隐藏顶栏
}

项目中包含 SceneDelegate.h/SceneDelegate.m 的(xcode11创建默认创建的)
在SceneDelegate.m

#import <Foundation/Foundation.h>
#import <UIKit/NSToolbar+UIKitAdditions.h>
- (void)scene:(UIScene *)scene willConnectToSession:(UISceneSession *)session options:(UISceneConnectionOptions *)connectionOptions {
    UIWindowScene * windowScene = scene;
    windowScene.titlebar.titleVisibility = UITitlebarTitleVisibilityHidden;
}

demo:
https://github.com/davidcaddy/UIKitForMacTestTabBarApp
----效果

去掉顶栏

顶栏添加工具栏(NSToolbar)

在appdelegate的- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions 方法中添加代码


//macOS隐藏顶栏
     self.window.windowScene.titlebar.titleVisibility = UITitlebarTitleVisibilityHidden;
    NSToolbar * toolbar = [[NSToolbar alloc]initWithIdentifier:@"ITTitleToolbar"];
    toolbar.delegate = self;
    toolbar.centeredItemIdentifier = @"居中的ItemIdentifier";//例如ITtabbar
    self.window.windowScene.titlebar.toolbar = toolbar;


appdelegate遵循下协议 : NSToolbarDelegate
在.m中实现协议

#pragma mark - NSToolbarDelegate
  //所有的item 标识
-(NSArray<NSToolbarItemIdentifier> *)toolbarAllowedItemIdentifiers:(NSToolbar *)toolbar{
    return @[@"addButton",@"ITtabbar",NSToolbarFlexibleSpaceItemIdentifier,@"searchBar"];
}

-(NSArray<NSToolbarItemIdentifier> *)toolbarDefaultItemIdentifiers:(NSToolbar *)toolbar{
    return @[@"addButton",@"ITtabbar",NSToolbarFlexibleSpaceItemIdentifier,@"searchBar"];
}
//选中变灰
//-(NSArray<NSToolbarItemIdentifier> *)toolbarSelectableItemIdentifiers:(NSToolbar *)toolbar{
//    return @[@"addButton",@"ITtabbar",@"searchBar"];
//}
//根据item 标识 返回每个具体的NSToolbarItem对象实例
- (NSToolbarItem *)toolbar:(NSToolbar *)toolbar itemForItemIdentifier:(NSString *)itemIdentifier willBeInsertedIntoToolbar:(BOOL)flag {
    
    if ([itemIdentifier isEqualToString:@"ITtabbar"]) {
//这里要用NSToolbarItemGroup,子项不会分开,居中设置也可以是它(ITtabbar)
        NSToolbarItemGroup * group = [NSToolbarItemGroup groupWithItemIdentifier:@"ITtabbar" titles:@[@"资讯",@"辣品",@"圈子",@"我"] selectionMode:NSToolbarItemGroupSelectionModeSelectOne labels:@[@"section1", @"section2",@"section3", @"section4"] target:self action:@selector(toolbarItemClicked:)];
        [group setSelectedIndex:0];
        return group;
    }
    
     NSToolbarItem *toolbarItem = [[NSToolbarItem alloc] initWithItemIdentifier:itemIdentifier];
    if ([itemIdentifier isEqualToString:@"addButton"]) {
        [toolbarItem setToolTip:@"更多"];
        [toolbarItem setImage:[UIImage imageNamed:@"SmallAttentionButton"]];
        [toolbarItem setTarget:self];
        [toolbarItem setAction:@selector(addToolbarItemClicked:)];
        toolbarItem.bordered = YES;
        
    }
    else if ([itemIdentifier isEqualToString:@"searchBar"]) {
        [toolbarItem setToolTip:@"搜索"];
        [toolbarItem setImage:[UIImage imageNamed:@"short_search"]];
        [toolbarItem setTarget:self];
        [toolbarItem setAction:@selector(searchToolbarItemClicked:)];
        toolbarItem.bordered = YES;
    }
    else {
        toolbarItem = nil;
    }
 
    return toolbarItem;
}
- (void)toolbarItemClicked:(NSToolbarItemGroup *)toolbarItemGroup{

    switch (toolbarItemGroup.selectedIndex) {
        case 0:
            NSLog(@"点击的是资讯");

            break;
        case 1:
            NSLog(@"点击的是辣品");

            break;
        case 2:
            NSLog(@"点击的是圈子");

            break;
        case 3:
            NSLog(@"点击的是我");

            break;
        default:
            break;
    }
}
- (void)searchToolbarItemClicked:(NSToolbarItem *)toolbarItem{
    NSLog(@"点击的是%@",toolbarItem.toolTip);
}
- (void)addToolbarItemClicked:(NSToolbarItem *)toolbarItem{
    NSLog(@"点击的是%@",toolbarItem.toolTip);
}

NSToolbarFlexibleSpaceItemIdentifier的解释
用这个可以达到居右对齐效果
示例代码现在是左中右布局,要在中间的item之后加入这个,不然右边的item会紧挨着中间的这个item

参考!!!!!可解决一些问题,获得启发
https://www.highcaffeinecontent.com/blog/20190607-Beyond-the-Checkbox-with-Catalyst-and-AppKit

一个大而全的教程

打包问题:
1、archive 删掉Siri 功能(有的话)
2、苹果后台证书、appid、描述文件都不用动,签名选择自动(对外发布需要公证)
macOS应用Notarization公证机制

关于上架

在iOS提交界面选择macOS版本,按之前iOS的提交步骤提交即可

截屏2020-04-28下午8.38.07.png

上一张运行图

截屏2019-11-01下午6.53.58.png
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 158,560评论 4 361
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,104评论 1 291
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,297评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,869评论 0 204
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,275评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,563评论 1 216
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,833评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,543评论 0 197
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,245评论 1 241
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,512评论 2 244
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,011评论 1 258
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,359评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,006评论 3 235
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,062评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,825评论 0 194
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,590评论 2 273
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,501评论 2 268

推荐阅读更多精彩内容