Flutter 工程在 MacOS 中不能用中文命名?

339 阅读2分钟

前言

在上架一款应用到 Mac App Store 时,审核给出审核不通过的原因,如下:

image.png 也就是说打包后的app安装包的名字是wenzdoc.app,但是提交的应用名称是温知文档,所以审核不通过。

在解决此问题时,我遇到2个问题:

1.如何重命名项目?

2.命名中文后打开app后空白:github.com/flutter/flu…

命名问题

首先是flutter命名问题,因为创建工程是,用的是英文命名,但是不知道如何修改,经过搜索找到方案,通过下述命令行解决问题:

flutter pub global activate rename

flutter pub global run rename setAppName --targets windows,macos,ios,android --value "项目名称"
flutter pub global run rename setBundleId --targets windows,macos,ios,android --value "com.example.bundleId"  

中文命名在 macos 无法正常运行

经过搜索,github中有人提了类似的问题,github.com/flutter/flu…

说是使用中文命名,着色器存在bug,有人给出了偏方,我尝试了半天都无效。

A temporary and dirty workaround by swizzling  NSBundle resourcePath: might be effective until Apple addresses this issue.

Note: Just put this code in a .mm file then add to your xcodeproj

后来学习了一下macos开发,做出以下步骤解决了问题:

1.使用xcode工具,在Runner文件夹中添加该文件,这样文件就会自动添加到 project.pbxproj

2.如果编译错误,可以在里面加上下面的代码

#import <Foundation/Foundation.h>

详细步骤如下: 1.用xcode工具打开工程

2.在Runner右键添加文件

3.输入名称“FixMacOS15MetalShader.mm”,也可以是其它名称

image.png 4.在文件中输入以下代码

//

//  FixMacOS15MetalShader.mm

//  Runner

//

//  Created by lyming on 2024/10/15.

//

#include <execinfo.h>

#import <objc/runtime.h>

#import <Foundation/Foundation.h>

@interface NSBundle (FixMacOS15MetalShader)

@end

@implementation NSBundle (FixMacOS15MetalShader)

bool shouldBeginSwizzleHook() {

  if (@available(macOS 15.0, *)) {

    NSString* bundlePath = [[NSBundle mainBundle] bundlePath];

    NSUInteger characterCount = [bundlePath length];

    NSUInteger byteLength = [bundlePath lengthOfBytesUsingEncoding:NSUTF8StringEncoding];

    // Multiple byte characters

    return characterCount != byteLength;

  }

  return false;

}

void swizzleInstanceMethod(Class cls, SEL original, SEL swizzled) {

  Method originalMethod = class_getInstanceMethod(cls, original);

  Method swizzledMethod = class_getInstanceMethod(cls, swizzled);

  if (!originalMethod || !swizzledMethod) {

    return;

  }

  method_exchangeImplementations(originalMethod, swizzledMethod);

}

NSString* GetAppCachesDirectory() {

  static NSString* cachesPath = nil;

  if (!cachesPath) {

    NSArray* paths = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES);

    if (paths.count > 0) {

      cachesPath = [[paths firstObject] copy];

    } else {

      return NSTemporaryDirectory();

    }

  }

  return cachesPath;

}

+ (void)load {

  static dispatch_once_t onceToken;

  dispatch_once(&onceToken, ^{

    if (shouldBeginSwizzleHook()) {

      swizzleInstanceMethod(self, @selector(resourcePath), @selector(swizzled_resourcePath));

      NSLog(@"Did swizzle bundle resourcePath method.");

    }

  });

}

- (NSString*)swizzled_resourcePath {

  static constexpr int backtrace_size = 2;

  static void* mtlGetCompilerWorkingDirFunc = NULL;

  void* stack[backtrace_size];

  int count = backtrace(stack, backtrace_size);

  if (count < backtrace_size) {

    return [self swizzled_resourcePath];

  } else {

    void* stack_frame = stack[1];

    if (mtlGetCompilerWorkingDirFunc != NULL) {

      if (stack_frame == mtlGetCompilerWorkingDirFunc) {

        return GetAppCachesDirectory();

      }

    } else {

      char** symbols = backtrace_symbols(stack, count);

      char *symbol = symbols[1];

      if (symbol != NULL && strstr(symbol, "MTLGetCompilerWorkingDir") != NULL) {

        mtlGetCompilerWorkingDirFunc = stack_frame;

        free(symbols);

        return GetAppCachesDirectory();

      }

      free(symbols);

    }

  }

  return [self swizzled_resourcePath];

}

@end

最后问题得到解决。

总结

各位小伙伴,在官方解决这个问题前,只能这样处理一下了。

在issue中了解到,英文系统下还是没问题的,中文系统下中文命名app就是会空白。