HBuilderX

HBuilderX

极客开发工具
uni-app

uni-app

开发一次,多端覆盖
uniCloud

uniCloud

云开发平台
HTML5+

HTML5+

增强HTML5的功能体验
MUI

MUI

上万Star的前端框架

陈

1

1

李

1

1

谢

1

1

2

2

2

1

1

1

uniCloud

uniCloud

背景和优势
20年前,restful接口开发开始流行,服务器编写接口,客户端调用接口,传输json。

现在,替代restful的新模式来了。

云对象,服务器编写API,客户端调用API,不再开发传输json的接口。思路更清晰、代码更精简。

比如服务端编写一个云对象todo,该对象有add、get、remove、update等方法。客户端的js则可以直接import这个todo云对象,直接调用add等方法。

服务器示例代码如下:

HBuilderX中在uniCloud/cloudfunctions目录新建云函数,选择类型为云对象,起名为todo。打开云对象入口index.obj.js,添加一个add方法。

// 云对象名:todo
module.exports = {
add(title, content) {
title = title.trim()
content = content.trim()
if(!title || !content) {
return {
errCode: 'INVALID_TODO',
errMsg: 'TODO标题或内容不可为空'
}
}
// ...其他逻辑
return {
errCode: 0,
errMsg: '创建成功'
}
}
}
复制代码
然后在客户端的js中,import这个todo对象,调用它的add方法

const todo = uniCloud.importObject('todo') //第一步导入云对象
async function addTodo () {
try {
const res = await todo.add('title demo', 'content demo') //导入云对象后就可以直接调用该对象的方法了,注意使用异步await
uni.showToast({
title: '创建成功'
})
} catch (e) {
// 符合uniCloud响应体规范 https://doc.dcloud.net.cn/uniCloud/cf-functions?id=resformat,自动抛出此错误
uni.showModal({
title: '创建失败',
content: e.errMsg,
showCancel: false
})
}
}
复制代码
可以看到云对象的代码非常清晰,代码行数也只有33行。

而同样的逻辑,使用传统的接口方式则需要更多代码,见下:

// 传统方式调用云函数-云函数代码
// 云函数名:todo
// 云函数入口index.js内容如下
'use strict';
exports.main = async (event, context) => {
const {
method,
params
} = event
switch(method) {
case 'add': {
let {
title,
content
} = params
title = title.trim()
content = content.trim()
if(!title || !content) {
return {
errCode: 'INVALID_TODO',
errMsg: 'TODO标题或内容不可为空'
}
}
// ...省略其他逻辑
return {
errCode: 0,
errMsg: '创建成功'
}
}
}
return {
errCode: 'METHOD_NOT_FOUND',
errMsg: Method[${method}] not found
}
};

// 传统方式调用云函数-客户端代码
async function addToDo () {
try {
const res = await uniCloud.callFunction({
name: 'todo',
data: {
method: 'add',
params: {
title: 'title demo',
content: 'content demo'
}
}
})
const {
errCode,
errMsg
} = res.result
if(errCode) {
uni.showModal({
title: '创建失败',
content: errMsg,
showCancel: false
})
return
}
uni.showToast({
title: '创建成功'
})
} catch (e) {
uni.showModal({
title: '创建失败',
content: e.message,
showCancel: false
})
}
}
复制代码
以上传统开发需要68行代码,对比云对象的33行代码,不但工作量大,而且逻辑也不如云对象清晰。

_注:以上例子仅用于方便初学者理解。实际开发中对于简单的数据库操作,使用clientDB在前端直接操作数据库是更简单、代码更少的方案,都不需要写云端代码。

总结下云对象带来的好处:

更清晰的逻辑
更精简的代码
更少的协作成本(以及矛盾~)
客户端调用时在ide里有完善的代码提示,方法参数均可提示。(传输json可没法在ide里提示)
默认支持uniCloud响应体规范,方便错误拦截和统一处理
快速上手
创建云对象
云对象,其实是对云函数的封装。和创建云函数一样,在uniCloud/cloudfunctions目录右键新建云函数,选择云对象类型,输入云对象名称创建云对象,此处以云对象todo为例,创建的云对象包含一个index.obj.js。

创建云对象

一个空的云对象内容如下

// cloudfunctions/todo/index.obj.js
module.exports = {

}
复制代码
默认云对象模板是不包含任何方法的,我们为此对象添加一个add方法作为示例。

// cloudfunctions/todo/index.obj.js
module.exports = {
add: function(title = '', content = '') {
title = title.trim()
content = content.trim()
if(!title || !content) {
return {
errCode: 'INVALID_TODO',
errMsg: 'TODO标题或内容不可为空'
}
}
// ...其他逻辑,如操作todo数据表添加数据
return {
errCode: 0,
errMsg: '创建成功'
}
}
}
复制代码
至此云对象todo已经有了一个可以访问的方法了。接下来看如何使用客户端调用此云对象内的方法

客户端调用
客户端通过uniCloud.importObject方法获取云对象的实例,并可以通过此实例调用云对象内的方法。用法如下

const todo = uniCloud.importObject('todo')
const res = await todo.add('title demo', 'content demo')
复制代码
通过代码块cco可以快捷的输入以下代码:

const todo = uniCloud.importObject('todo')
复制代码
实际业务中需要考虑错误捕获,调用方式有两种:

try catch
const todo = uniCloud.importObject('todo')
try {
const res = await todo.add('title demo', 'content demo') //导入云对象后就可以直接调用该对象的方法了,注意使用异步await
console.log(res)
} catch (e) {
console.log(e.errCode)
console.log(e.errMsg)
}
复制代码
then catch(promise写法)
const todo = uniCloud.importObject('todo')
todo.add('title demo', 'content demo').then(res => {
console.log(res)
}).catch(e => {
console.log(e.errCode)
console.log(e.errMsg)
})
复制代码
importObject参数说明

interface ImportObjectOptions {
/**

  • 是否移除自动展示的ui
    */
    customUI?: boolean;
    /**
  • loading界面配置
    */
    loadingOptions?: ImportObjectLoadingOptions;
    /**
  • 错误提示配置
    */
    errorOptions?: ImportObjectErrorOptions;
    /**
  • 使用安全网络的方法及安全网络类型
    */
    secretMethods?: Record<string, 'none' | 'request' | 'response' | 'both'>;
    /**
  • 转化云对象内未捕获的错误或客户端网络错误
    */
    parseSystemError?: (params: ParseSystemErrorParams) => Promise<ParsedSystemError> | ParsedSystemError;
    }
    复制代码
    云对象的API
    云对象作为云函数的一种,可以调用所有node的API和uniCloud的API。

uniCloud有众多API,另见:uniCloud的API清单

除上述API之外,云对象的this对象还有一批专用方法来获取当前请求的上下文信息。

与云函数入参时的context不同,云对象没有context。它通过this对象挂载的几个内置方法来获取上下文信息。请注意开发者避免在this上挂载同名方法。

获取客户端信息
HBuilderX 3.4.9起此接口可获取所有客户端getSystemInfo返回的客户端信息,完整字段列表参考:getSystemInfo

接口形式

this.getClientInfo()

示例:

module.exports = {
add: function() {
const clientInfo = this.getClientInfo()
// clientInfo = {
// clientIP,
// appId,
// deviceId,
// source,
// //... 其他getSystemInfoSync返回值
// }
}
}
复制代码
返回值

getClientInfo返回的信息,是在客户端的uni.getSystemInfo的基础之上,增加了一些额外的信息。

除了getSystemInfo返回字段外,还包含以下信息

属性名 类型 说明
clientIP string 客户端ip
userAgent string 客户端ua,注意非本地运行环境下客户端getSystemInfoSync也会获取ua参数并上传给云对象,但是云对象会从http请求头里面获取ua而不是clientInfo里面的ua
source string 调用来源,返回值见下。HBuilderX 3.5.1+
requestId string 请求id。HBuilderX 3.5.1+
scene string 场景值。客户端uni.getLaunchOptionsSync返回的scene参数,新增于HBuilderX 3.5.1
getClientInfo().source,返回云函数调用来源,它的值域为:

取值 说明
client uni-app客户端导入云对象调用
function 由其他云函数或云对象调用
http 云对象URL化后通过http访问调用 HBuilderX 3.5.2+
timing 定时任务调用云对象 HBuilderX 3.5.2+
server 云函数上传并运行
注意事项

客户端上报的信息在理论上存在被篡改可能,实际业务中应验证前端传来的数据的合法性
除了clientIP外,其他客户端信息只有使用uni-app客户端以云对象的方式调用才能获取
云对象与云函数内获取客户端platform稍有不同,云函数未拉齐vue2、vue3版本app平台的platform值,vue2为app-plus,vue3为app。云对象无论客户端是vue2还是vue3,在app平台获取的platform均为app。这一点在使用uni-id时需要特别注意,详情见:uni-id文档 preferedAppPlatform
获取云端信息
接口形式

this.getCloudInfo()

示例

继续阅读 »

背景和优势
20年前,restful接口开发开始流行,服务器编写接口,客户端调用接口,传输json。

现在,替代restful的新模式来了。

云对象,服务器编写API,客户端调用API,不再开发传输json的接口。思路更清晰、代码更精简。

比如服务端编写一个云对象todo,该对象有add、get、remove、update等方法。客户端的js则可以直接import这个todo云对象,直接调用add等方法。

服务器示例代码如下:

HBuilderX中在uniCloud/cloudfunctions目录新建云函数,选择类型为云对象,起名为todo。打开云对象入口index.obj.js,添加一个add方法。

// 云对象名:todo
module.exports = {
add(title, content) {
title = title.trim()
content = content.trim()
if(!title || !content) {
return {
errCode: 'INVALID_TODO',
errMsg: 'TODO标题或内容不可为空'
}
}
// ...其他逻辑
return {
errCode: 0,
errMsg: '创建成功'
}
}
}
复制代码
然后在客户端的js中,import这个todo对象,调用它的add方法

const todo = uniCloud.importObject('todo') //第一步导入云对象
async function addTodo () {
try {
const res = await todo.add('title demo', 'content demo') //导入云对象后就可以直接调用该对象的方法了,注意使用异步await
uni.showToast({
title: '创建成功'
})
} catch (e) {
// 符合uniCloud响应体规范 https://doc.dcloud.net.cn/uniCloud/cf-functions?id=resformat,自动抛出此错误
uni.showModal({
title: '创建失败',
content: e.errMsg,
showCancel: false
})
}
}
复制代码
可以看到云对象的代码非常清晰,代码行数也只有33行。

而同样的逻辑,使用传统的接口方式则需要更多代码,见下:

// 传统方式调用云函数-云函数代码
// 云函数名:todo
// 云函数入口index.js内容如下
'use strict';
exports.main = async (event, context) => {
const {
method,
params
} = event
switch(method) {
case 'add': {
let {
title,
content
} = params
title = title.trim()
content = content.trim()
if(!title || !content) {
return {
errCode: 'INVALID_TODO',
errMsg: 'TODO标题或内容不可为空'
}
}
// ...省略其他逻辑
return {
errCode: 0,
errMsg: '创建成功'
}
}
}
return {
errCode: 'METHOD_NOT_FOUND',
errMsg: Method[${method}] not found
}
};

// 传统方式调用云函数-客户端代码
async function addToDo () {
try {
const res = await uniCloud.callFunction({
name: 'todo',
data: {
method: 'add',
params: {
title: 'title demo',
content: 'content demo'
}
}
})
const {
errCode,
errMsg
} = res.result
if(errCode) {
uni.showModal({
title: '创建失败',
content: errMsg,
showCancel: false
})
return
}
uni.showToast({
title: '创建成功'
})
} catch (e) {
uni.showModal({
title: '创建失败',
content: e.message,
showCancel: false
})
}
}
复制代码
以上传统开发需要68行代码,对比云对象的33行代码,不但工作量大,而且逻辑也不如云对象清晰。

_注:以上例子仅用于方便初学者理解。实际开发中对于简单的数据库操作,使用clientDB在前端直接操作数据库是更简单、代码更少的方案,都不需要写云端代码。

总结下云对象带来的好处:

更清晰的逻辑
更精简的代码
更少的协作成本(以及矛盾~)
客户端调用时在ide里有完善的代码提示,方法参数均可提示。(传输json可没法在ide里提示)
默认支持uniCloud响应体规范,方便错误拦截和统一处理
快速上手
创建云对象
云对象,其实是对云函数的封装。和创建云函数一样,在uniCloud/cloudfunctions目录右键新建云函数,选择云对象类型,输入云对象名称创建云对象,此处以云对象todo为例,创建的云对象包含一个index.obj.js。

创建云对象

一个空的云对象内容如下

// cloudfunctions/todo/index.obj.js
module.exports = {

}
复制代码
默认云对象模板是不包含任何方法的,我们为此对象添加一个add方法作为示例。

// cloudfunctions/todo/index.obj.js
module.exports = {
add: function(title = '', content = '') {
title = title.trim()
content = content.trim()
if(!title || !content) {
return {
errCode: 'INVALID_TODO',
errMsg: 'TODO标题或内容不可为空'
}
}
// ...其他逻辑,如操作todo数据表添加数据
return {
errCode: 0,
errMsg: '创建成功'
}
}
}
复制代码
至此云对象todo已经有了一个可以访问的方法了。接下来看如何使用客户端调用此云对象内的方法

客户端调用
客户端通过uniCloud.importObject方法获取云对象的实例,并可以通过此实例调用云对象内的方法。用法如下

const todo = uniCloud.importObject('todo')
const res = await todo.add('title demo', 'content demo')
复制代码
通过代码块cco可以快捷的输入以下代码:

const todo = uniCloud.importObject('todo')
复制代码
实际业务中需要考虑错误捕获,调用方式有两种:

try catch
const todo = uniCloud.importObject('todo')
try {
const res = await todo.add('title demo', 'content demo') //导入云对象后就可以直接调用该对象的方法了,注意使用异步await
console.log(res)
} catch (e) {
console.log(e.errCode)
console.log(e.errMsg)
}
复制代码
then catch(promise写法)
const todo = uniCloud.importObject('todo')
todo.add('title demo', 'content demo').then(res => {
console.log(res)
}).catch(e => {
console.log(e.errCode)
console.log(e.errMsg)
})
复制代码
importObject参数说明

interface ImportObjectOptions {
/**

  • 是否移除自动展示的ui
    */
    customUI?: boolean;
    /**
  • loading界面配置
    */
    loadingOptions?: ImportObjectLoadingOptions;
    /**
  • 错误提示配置
    */
    errorOptions?: ImportObjectErrorOptions;
    /**
  • 使用安全网络的方法及安全网络类型
    */
    secretMethods?: Record<string, 'none' | 'request' | 'response' | 'both'>;
    /**
  • 转化云对象内未捕获的错误或客户端网络错误
    */
    parseSystemError?: (params: ParseSystemErrorParams) => Promise<ParsedSystemError> | ParsedSystemError;
    }
    复制代码
    云对象的API
    云对象作为云函数的一种,可以调用所有node的API和uniCloud的API。

uniCloud有众多API,另见:uniCloud的API清单

除上述API之外,云对象的this对象还有一批专用方法来获取当前请求的上下文信息。

与云函数入参时的context不同,云对象没有context。它通过this对象挂载的几个内置方法来获取上下文信息。请注意开发者避免在this上挂载同名方法。

获取客户端信息
HBuilderX 3.4.9起此接口可获取所有客户端getSystemInfo返回的客户端信息,完整字段列表参考:getSystemInfo

接口形式

this.getClientInfo()

示例:

module.exports = {
add: function() {
const clientInfo = this.getClientInfo()
// clientInfo = {
// clientIP,
// appId,
// deviceId,
// source,
// //... 其他getSystemInfoSync返回值
// }
}
}
复制代码
返回值

getClientInfo返回的信息,是在客户端的uni.getSystemInfo的基础之上,增加了一些额外的信息。

除了getSystemInfo返回字段外,还包含以下信息

属性名 类型 说明
clientIP string 客户端ip
userAgent string 客户端ua,注意非本地运行环境下客户端getSystemInfoSync也会获取ua参数并上传给云对象,但是云对象会从http请求头里面获取ua而不是clientInfo里面的ua
source string 调用来源,返回值见下。HBuilderX 3.5.1+
requestId string 请求id。HBuilderX 3.5.1+
scene string 场景值。客户端uni.getLaunchOptionsSync返回的scene参数,新增于HBuilderX 3.5.1
getClientInfo().source,返回云函数调用来源,它的值域为:

取值 说明
client uni-app客户端导入云对象调用
function 由其他云函数或云对象调用
http 云对象URL化后通过http访问调用 HBuilderX 3.5.2+
timing 定时任务调用云对象 HBuilderX 3.5.2+
server 云函数上传并运行
注意事项

客户端上报的信息在理论上存在被篡改可能,实际业务中应验证前端传来的数据的合法性
除了clientIP外,其他客户端信息只有使用uni-app客户端以云对象的方式调用才能获取
云对象与云函数内获取客户端platform稍有不同,云函数未拉齐vue2、vue3版本app平台的platform值,vue2为app-plus,vue3为app。云对象无论客户端是vue2还是vue3,在app平台获取的platform均为app。这一点在使用uni-id时需要特别注意,详情见:uni-id文档 preferedAppPlatform
获取云端信息
接口形式

this.getCloudInfo()

示例

收起阅读 »

2

2

2

从 3 天开发到收到苹果 4.3:一个 AI 项目的上架翻车记录

苹果审核

从 3 天开发到收到苹果 4.3:一个 AI 项目的上架翻车记录

最近接到一个客户的项目。

项目很简单。

客户使用 Cursor 配合 ChatGPT 开发,前后只用了不到一周时间,一个 AI 工具类 APP 就已经完成。

页面漂亮,功能正常,测试也没有发现明显问题。

客户原本以为提交审核后几天就能上线。

结果收到的第一条消息却是:

Guideline 4.3 - Design - Spam

很多开发者看到这里都会有一个疑问:

同样是 AI 项目,为什么别人能过,而自己却被判定为重复内容?

实际上问题往往不是出在 AI,而是出在开发过程中那些容易被忽略的细节。

⸻

这类项目通常长什么样?

我们拆包分析后发现,很多 AI 生成项目都有一个共同特点。

首页是聊天界面。

第二页是模型列表。

第三页是会员中心。

第四页是个人中心。

换句话说,虽然 APP 名称不同,但整体结构几乎一致。

今天叫 AI 助手。

明天叫 AI 创作。

后天叫 AI 写作。

从用户角度看可能是不同产品。

但从苹果审核角度看,它们更像是同一个产品的多个版本。

这也是很多开发者第一次收到 4.3 的主要原因。

⸻

苹果真的会检测代码吗?

很多人认为苹果审核员只是打开 APP 看几分钟。

实际上远不止如此。

一个 IPA 上传后,苹果首先进行自动化分析。

检测内容通常包括:

  • Bundle 信息
  • 资源文件
  • Framework 依赖
  • 页面结构
  • 类名与方法名
  • 权限申请情况
  • 历史提交记录

特别是 AI 生成代码。

由于大量开发者使用相同提示词生成项目,因此经常会出现类似情况:

HomePage
ChatPage
MinePage
VipPage

甚至整个目录结构都高度一致。

虽然用户看不到这些内容,但审核系统是可以分析到的。

⸻

UI 改了为什么还是收到 4.3?

这是很多人踩过的坑。

收到 4.3 后第一反应通常是:

换图标。

换配色。

换截图。

换启动页。

然后重新提交。

结果还是被拒。

原因很简单。

苹果审核从来不是只看 UI。

很多项目表面已经改头换面。

但实际上:

功能没变。

代码没变。

业务逻辑没变。

用户路径没变。

审核员看到后仍然会认为属于重复内容。

⸻

一个真实案例

去年有个 AI 写作项目。

第一次提交时:

功能包括:

  • AI 对话
  • AI 写作
  • AI 翻译

结果收到 4.3。

后来我们重新梳理产品定位。

保留 AI 能力的同时增加:

  • 写作素材库
  • 行业模板中心
  • 历史创作管理
  • 文案分类系统
  • 每日创作任务

同时重新调整页面结构。

将聊天入口从首页移动到二级页面。

增加内容运营模块。

重新设计会员体系。

第二次提交后顺利通过审核。

整个过程中代码修改量并不算大。

真正变化的是产品定位。

⸻

AI 项目最容易忽略的问题

很多开发者把重点放在代码上。

实际上苹果更关注的是产品本身。

如果审核员打开 APP 后发现:

第一页聊天。

第二页会员。

第三页个人中心。

无论你用的是 AI 写的代码,还是程序员手写的代码,最终都会面临同样的问题。

因为苹果审核的是产品,而不是开发工具。

⸻

我的建议

如果准备使用 AI 开发 APP 上架 App Store,可以把 AI 当成开发助手,而不是产品经理。

代码可以让 AI 写。

页面可以让 AI 画。

但是产品定位一定要自己设计。

在提交审核之前,至少要回答下面三个问题:

第一,这个 APP 解决什么问题?

第二,它和市场上已有产品有什么区别?

第三,用户为什么要下载它而不是别人?

如果这三个问题答不出来。

即使没有收到 4.3,也只是时间问题。

⸻

写在最后

很多人觉得 AI 降低了开发门槛。

这一点没错。

但同时也降低了同质化产品出现的门槛。

过去做一个 APP 需要一个团队。

现在一个人加一套 AI 工具就能完成。

这也是为什么近两年苹果对于 4.3 的审核越来越严格。

被拒的原因从来不是因为用了 AI。

而是因为太多人用 AI 做出了相似的产品。

真正能通过审核的项目,往往不是代码写得最复杂的,而是定位最清晰、差异化最明显的。

继续阅读 »

从 3 天开发到收到苹果 4.3:一个 AI 项目的上架翻车记录

最近接到一个客户的项目。

项目很简单。

客户使用 Cursor 配合 ChatGPT 开发,前后只用了不到一周时间,一个 AI 工具类 APP 就已经完成。

页面漂亮,功能正常,测试也没有发现明显问题。

客户原本以为提交审核后几天就能上线。

结果收到的第一条消息却是:

Guideline 4.3 - Design - Spam

很多开发者看到这里都会有一个疑问:

同样是 AI 项目,为什么别人能过,而自己却被判定为重复内容?

实际上问题往往不是出在 AI,而是出在开发过程中那些容易被忽略的细节。

⸻

这类项目通常长什么样?

我们拆包分析后发现,很多 AI 生成项目都有一个共同特点。

首页是聊天界面。

第二页是模型列表。

第三页是会员中心。

第四页是个人中心。

换句话说,虽然 APP 名称不同,但整体结构几乎一致。

今天叫 AI 助手。

明天叫 AI 创作。

后天叫 AI 写作。

从用户角度看可能是不同产品。

但从苹果审核角度看,它们更像是同一个产品的多个版本。

这也是很多开发者第一次收到 4.3 的主要原因。

⸻

苹果真的会检测代码吗?

很多人认为苹果审核员只是打开 APP 看几分钟。

实际上远不止如此。

一个 IPA 上传后,苹果首先进行自动化分析。

检测内容通常包括:

  • Bundle 信息
  • 资源文件
  • Framework 依赖
  • 页面结构
  • 类名与方法名
  • 权限申请情况
  • 历史提交记录

特别是 AI 生成代码。

由于大量开发者使用相同提示词生成项目,因此经常会出现类似情况:

HomePage
ChatPage
MinePage
VipPage

甚至整个目录结构都高度一致。

虽然用户看不到这些内容,但审核系统是可以分析到的。

⸻

UI 改了为什么还是收到 4.3?

这是很多人踩过的坑。

收到 4.3 后第一反应通常是:

换图标。

换配色。

换截图。

换启动页。

然后重新提交。

结果还是被拒。

原因很简单。

苹果审核从来不是只看 UI。

很多项目表面已经改头换面。

但实际上:

功能没变。

代码没变。

业务逻辑没变。

用户路径没变。

审核员看到后仍然会认为属于重复内容。

⸻

一个真实案例

去年有个 AI 写作项目。

第一次提交时:

功能包括:

  • AI 对话
  • AI 写作
  • AI 翻译

结果收到 4.3。

后来我们重新梳理产品定位。

保留 AI 能力的同时增加:

  • 写作素材库
  • 行业模板中心
  • 历史创作管理
  • 文案分类系统
  • 每日创作任务

同时重新调整页面结构。

将聊天入口从首页移动到二级页面。

增加内容运营模块。

重新设计会员体系。

第二次提交后顺利通过审核。

整个过程中代码修改量并不算大。

真正变化的是产品定位。

⸻

AI 项目最容易忽略的问题

很多开发者把重点放在代码上。

实际上苹果更关注的是产品本身。

如果审核员打开 APP 后发现:

第一页聊天。

第二页会员。

第三页个人中心。

无论你用的是 AI 写的代码,还是程序员手写的代码,最终都会面临同样的问题。

因为苹果审核的是产品,而不是开发工具。

⸻

我的建议

如果准备使用 AI 开发 APP 上架 App Store,可以把 AI 当成开发助手,而不是产品经理。

代码可以让 AI 写。

页面可以让 AI 画。

但是产品定位一定要自己设计。

在提交审核之前,至少要回答下面三个问题:

第一,这个 APP 解决什么问题?

第二,它和市场上已有产品有什么区别?

第三,用户为什么要下载它而不是别人?

如果这三个问题答不出来。

即使没有收到 4.3,也只是时间问题。

⸻

写在最后

很多人觉得 AI 降低了开发门槛。

这一点没错。

但同时也降低了同质化产品出现的门槛。

过去做一个 APP 需要一个团队。

现在一个人加一套 AI 工具就能完成。

这也是为什么近两年苹果对于 4.3 的审核越来越严格。

被拒的原因从来不是因为用了 AI。

而是因为太多人用 AI 做出了相似的产品。

真正能通过审核的项目,往往不是代码写得最复杂的,而是定位最清晰、差异化最明显的。

收起阅读 »

1

1

1