ios审核一周搞定,分享下过程
正好遇到国外圣诞节,中间有一周的空档,所以这里说的一周是扣除圣诞节放假的,我的app提交赶在他们的节前。累计被驳回5回,每次一天(23号他们给我驳回了2次)。
这里就说下需要注意的地方:
1、必须要隐私条款连接;
2、6.5英寸的预览和截屏得有留海(这个是看到别人说的,就我们修改了下,所以没因为截屏被驳回);
3、标题和副标题这个要特别注意。看appstore中很多标题都是带附加说明的,但是现在应该是不允许的。我们提交的app被驳回3次都是因为标题和副标题的原因:
a、第一次提交时,副标题添加了 一段说明他们认为是有关键词堆砌嫌疑,所以驳回了;
b、第二次我们将副标题的说明修改了,然后在增加了app名称的附加说明 “ app名称 - abc”,在appstore上可以看见很多类似的写法,不过那是以前现在貌似不行(反正被驳回了2次就不想再试了);
c、第三次我们去除了app名称上的附加说明“ - 附加说明”只留下单纯的app名称,然后附加标题采用“「app名称」期货交易数据分析与排名”,并说明为啥要用这个,接着跟他们商量我是否可以保留这个;
d、又一次被驳回,不过这次他们让我保留副标题说明了,驳回的原因是因为用户上传头像要权限,这个权限我没说明。在manifest.json中的“APP模块权限配置”中的“ios隐私信息访问的许可描述”添加说明后重新编译一个版本提交了上去。
e、最后一次被驳回,说我的副标题“「app名称」期货交易数据分析与排名”不符合政策。我在回复中把上次说明的情况再跟他说了一遍,并询问是否是同一个人审核的。最后问他,如果这个说明不符合政策,能否给个建议。这次提交上去后他们给通过了。
我感觉最主要的还是要尊重他们,我每次回复总是心平气和,因为这个其实是他们的工作,没必要耍小脾气。但是并不是说要低三下气,只是陈述事实即可。其实看下我们的副标题“期货交易数据分析与排名”,这个本身确实很难说没关键词堆砌嫌疑,因为含有“期货交易”,但是跟他们说明情况后他们放行了。
正好遇到国外圣诞节,中间有一周的空档,所以这里说的一周是扣除圣诞节放假的,我的app提交赶在他们的节前。累计被驳回5回,每次一天(23号他们给我驳回了2次)。
这里就说下需要注意的地方:
1、必须要隐私条款连接;
2、6.5英寸的预览和截屏得有留海(这个是看到别人说的,就我们修改了下,所以没因为截屏被驳回);
3、标题和副标题这个要特别注意。看appstore中很多标题都是带附加说明的,但是现在应该是不允许的。我们提交的app被驳回3次都是因为标题和副标题的原因:
a、第一次提交时,副标题添加了 一段说明他们认为是有关键词堆砌嫌疑,所以驳回了;
b、第二次我们将副标题的说明修改了,然后在增加了app名称的附加说明 “ app名称 - abc”,在appstore上可以看见很多类似的写法,不过那是以前现在貌似不行(反正被驳回了2次就不想再试了);
c、第三次我们去除了app名称上的附加说明“ - 附加说明”只留下单纯的app名称,然后附加标题采用“「app名称」期货交易数据分析与排名”,并说明为啥要用这个,接着跟他们商量我是否可以保留这个;
d、又一次被驳回,不过这次他们让我保留副标题说明了,驳回的原因是因为用户上传头像要权限,这个权限我没说明。在manifest.json中的“APP模块权限配置”中的“ios隐私信息访问的许可描述”添加说明后重新编译一个版本提交了上去。
e、最后一次被驳回,说我的副标题“「app名称」期货交易数据分析与排名”不符合政策。我在回复中把上次说明的情况再跟他说了一遍,并询问是否是同一个人审核的。最后问他,如果这个说明不符合政策,能否给个建议。这次提交上去后他们给通过了。
我感觉最主要的还是要尊重他们,我每次回复总是心平气和,因为这个其实是他们的工作,没必要耍小脾气。但是并不是说要低三下气,只是陈述事实即可。其实看下我们的副标题“期货交易数据分析与排名”,这个本身确实很难说没关键词堆砌嫌疑,因为含有“期货交易”,但是跟他们说明情况后他们放行了。
收起阅读 »【数位云】开放平台上线,共建位置服务生态~欢迎体验
12月13日,数位宣布即将上线位置服务开发者平台,面向行业开发者赋能采集、定位等基础能力,支持安卓、iOS、小程序等不同平台,帮助行业缩短开发周期,节省开发成本,以更高效的方式获取领先的精准室内位置识别能力。
定 位
基于数位自主研发的核心专利技术,赋能开发者店铺级精准室内位置识别能力,可以在不依赖硬件铺设的前提下,精准区分楼层、店铺、店内及店外。目前,这一定位能力已覆盖全国209座城市超4000万高价值室内场景并不断扩张,为开发者搭建精准室内定位能力通用平台。
采 集
针对不同行业面向的场景差异,数位开发者平台为开发者提供目标场景自采集功能,将原本专业采集团队才能完成的系统性采集工作,面向行业零门槛开放。开发者只需到达符合采集标准的目标采集地点,通过APP进行2步操作,10秒即可获取目标场景的精准定位能力。
目前,数位定位+采集能力已经为本地生活、新闻资讯、视频娱乐、电商母婴、考勤办公等诸多领域的服务类、工具类、娱乐类APP提供服务,赋能人员管理、定位打卡、用户画像、场景服务、数据分析、精细化运营等多种能力,打造从采集到定位,从定位到场景服务,从服务到数据分析的一整套位置服务系统。
即日起,开发者可联系数位工作人员获取免费体验工具。
未来,数位还将陆续开放地图导航、近场服务、数据分析等能力,丰富位置服务形态,构建位置服务生态,与行业共建全域感知的智能世界。
开发者平台链接地址:https://cloud.papakaka.com/flash/#/dashboard
体验中如有疑问
扫描或识别下方二维码
添加数位小助手
随时在线解答您的问题
12月13日,数位宣布即将上线位置服务开发者平台,面向行业开发者赋能采集、定位等基础能力,支持安卓、iOS、小程序等不同平台,帮助行业缩短开发周期,节省开发成本,以更高效的方式获取领先的精准室内位置识别能力。
定 位
基于数位自主研发的核心专利技术,赋能开发者店铺级精准室内位置识别能力,可以在不依赖硬件铺设的前提下,精准区分楼层、店铺、店内及店外。目前,这一定位能力已覆盖全国209座城市超4000万高价值室内场景并不断扩张,为开发者搭建精准室内定位能力通用平台。
采 集
针对不同行业面向的场景差异,数位开发者平台为开发者提供目标场景自采集功能,将原本专业采集团队才能完成的系统性采集工作,面向行业零门槛开放。开发者只需到达符合采集标准的目标采集地点,通过APP进行2步操作,10秒即可获取目标场景的精准定位能力。
目前,数位定位+采集能力已经为本地生活、新闻资讯、视频娱乐、电商母婴、考勤办公等诸多领域的服务类、工具类、娱乐类APP提供服务,赋能人员管理、定位打卡、用户画像、场景服务、数据分析、精细化运营等多种能力,打造从采集到定位,从定位到场景服务,从服务到数据分析的一整套位置服务系统。
即日起,开发者可联系数位工作人员获取免费体验工具。
未来,数位还将陆续开放地图导航、近场服务、数据分析等能力,丰富位置服务形态,构建位置服务生态,与行业共建全域感知的智能世界。
开发者平台链接地址:https://cloud.papakaka.com/flash/#/dashboard
体验中如有疑问
扫描或识别下方二维码
添加数位小助手
随时在线解答您的问题
【建议】ctrl+f搜索结果总是在画面最下面或最上面,很不明显不便于查看代码上下文。
ctrl+f搜索结果总是在画面最下面或最上面,很不明显不便于查看代码上下文。
能否将结果高亮显示在中间,这样比较明显,且方便用户查看关键词的上下文,以便用户分别是否是想要的结果。
感谢!
ctrl+f搜索结果总是在画面最下面或最上面,很不明显不便于查看代码上下文。
能否将结果高亮显示在中间,这样比较明显,且方便用户查看关键词的上下文,以便用户分别是否是想要的结果。
感谢!
【建议】需要回到上个编辑位置的功能。感谢
alt+方向 通常要按好多次效率非常低。希望增加编辑位置的跳转,类似目前光标位置的跳转,只不过是历史编辑位置的跳转。感谢!
alt+方向 通常要按好多次效率非常低。希望增加编辑位置的跳转,类似目前光标位置的跳转,只不过是历史编辑位置的跳转。感谢!
Nvue 首页快速启动模式
v3编译模式(HBuilderX 2.5.0+),支持 nvue 首页的快速启动,视图层层不等逻辑层初始化完毕,即可同时进行渲染。
启用方式
在 manifest.json 可视化视图,app其他常用设置里,勾上fast启动模式。
或者在 manifest.json 源码视图里 app-plus 节点下配置 nvueLaunchMode 为 fast。
注意事项
启用快速启动模式后,app启动时,逻辑层和首页视图层是同时初始化的。(非fast模式时,是逻辑层先初始化,然后才开始加载视图层)
由于视图层渲染时,逻辑层不一定初始化完毕,此时首页的nvue页面内不可以依赖逻辑层的状态,具体为:
- 纯nvue + fast,vuex可用
- V3 + fast,vuex不可用
- getApp() 使用存在限制,具体参考:getApp()
v3编译模式(HBuilderX 2.5.0+),支持 nvue 首页的快速启动,视图层层不等逻辑层初始化完毕,即可同时进行渲染。
启用方式
在 manifest.json 可视化视图,app其他常用设置里,勾上fast启动模式。
或者在 manifest.json 源码视图里 app-plus 节点下配置 nvueLaunchMode 为 fast。
注意事项
启用快速启动模式后,app启动时,逻辑层和首页视图层是同时初始化的。(非fast模式时,是逻辑层先初始化,然后才开始加载视图层)
由于视图层渲染时,逻辑层不一定初始化完毕,此时首页的nvue页面内不可以依赖逻辑层的状态,具体为:
- 纯nvue + fast,vuex可用
- V3 + fast,vuex不可用
- getApp() 使用存在限制,具体参考:getApp()
开启 optional chaining 语法
我是使用 uni-cli 构建的,所以开启 optional-chaining 语法只需要安装了@babel/plugin-proposal-optional-chaining 包后在项目下的 babel.config.js 中配置
const plugins = ["@babel/plugin-proposal-optional-chaining"];
就是在 plugins 中加上@babel/plugin-proposal-optional-chaining 就好了,但是有些玄学问题,昨天搞了半天这个语法都不能用各种报错,今天啥也没改重新开机就能用了。。。。
也就是说这样配置是没问题的,还报错就重启试试?
我是使用 uni-cli 构建的,所以开启 optional-chaining 语法只需要安装了@babel/plugin-proposal-optional-chaining 包后在项目下的 babel.config.js 中配置
const plugins = ["@babel/plugin-proposal-optional-chaining"];
就是在 plugins 中加上@babel/plugin-proposal-optional-chaining 就好了,但是有些玄学问题,昨天搞了半天这个语法都不能用各种报错,今天啥也没改重新开机就能用了。。。。
也就是说这样配置是没问题的,还报错就重启试试?
收起阅读 »APP读取本地文件夹内视频播放
需要用到的几个方法:
// 从本地缓存中同步获取指定 key 对应的内容。
uni.getStorageSync(KEY)
// 下载文件资源到本地,客户端直接发起一个 HTTP GET 请求,返回文件的本地临时路径。
uni.downloadFile(OBJECT)
// 保存视频到本地
uni.saveFile(OBJECT)
// 将 data 存储在本地缓存中指定的 key 中,会覆盖掉原来该 key 对应的内容,这是一个同步接口。
uni.setStorageSync(KEY,DATA)
首先定义一个变量:获取本地缓存数据,看本地视频是存在。
获取已下载视频目录中的视频列表,删除无关视频。
const videoData = uni.getStorageSync('videoData')
// 获取本地视频列表
uni.getSavedFileList({
success: function (res) {
let fileList = res.fileList
console.log(fileList);
let needArr = videoData.map(item => item.videoAddress)
fileList.forEach((item, index) => {
if(needArr.includes(item.filePath)){
item.text = "需要这个视频"
}else{
// 删除视频列表中无关视频
uni.removeSavedFile({
filePath: item.filePath,
complete: function (res) {
console.log(res);
}
});
}
});
console.log(fileList)
}
});
写个条件判断:如果存在直接将视频地址插入页面进行播放,如果不存在则进行下载视频-保存视频-缓存本地链接。
const _this = this;
// 判断是否有缓存
if(videoData){
console.log('我是视频-有缓存')
_this.videoSrc = videoData
}else{
console.log('我是视频-没有有缓存')
_this.videoSrc = url // 我是在线链接
// 下载视频
_this.downFile(videoUrlYi,'videoData');
}
// 下载视频
downFile(url,name){
const _this = this;
uni.downloadFile({
url: url,
success: (res) => {
if (res.statusCode === 200) {
console.log('下载成功');
console.log(res.tempFilePath)
//保存视频到本地
uni.saveFile({
tempFilePath: res.tempFilePath,
success: function (res) {
console.log('保存成功');
var savedFilePath = res.savedFilePath;
console.log(savedFilePath)
_this.videoSrc = savedFilePath
console.log('当前连接'+_this.videoSrc)
uni.setStorageSync(name, savedFilePath);
}
});
}
}
});
}
小编推荐:程序员网址导航
作为一名码农,随着平时工作的需要,这里收集了国内外很多优秀网站,这其中包括在线工具、在线运行、免费接口、在线资源、在线学习、技术论坛、技术博客等等,满足一般程序员日常需求。
需要用到的几个方法:
// 从本地缓存中同步获取指定 key 对应的内容。
uni.getStorageSync(KEY)
// 下载文件资源到本地,客户端直接发起一个 HTTP GET 请求,返回文件的本地临时路径。
uni.downloadFile(OBJECT)
// 保存视频到本地
uni.saveFile(OBJECT)
// 将 data 存储在本地缓存中指定的 key 中,会覆盖掉原来该 key 对应的内容,这是一个同步接口。
uni.setStorageSync(KEY,DATA)
首先定义一个变量:获取本地缓存数据,看本地视频是存在。
获取已下载视频目录中的视频列表,删除无关视频。
const videoData = uni.getStorageSync('videoData')
// 获取本地视频列表
uni.getSavedFileList({
success: function (res) {
let fileList = res.fileList
console.log(fileList);
let needArr = videoData.map(item => item.videoAddress)
fileList.forEach((item, index) => {
if(needArr.includes(item.filePath)){
item.text = "需要这个视频"
}else{
// 删除视频列表中无关视频
uni.removeSavedFile({
filePath: item.filePath,
complete: function (res) {
console.log(res);
}
});
}
});
console.log(fileList)
}
});
写个条件判断:如果存在直接将视频地址插入页面进行播放,如果不存在则进行下载视频-保存视频-缓存本地链接。
const _this = this;
// 判断是否有缓存
if(videoData){
console.log('我是视频-有缓存')
_this.videoSrc = videoData
}else{
console.log('我是视频-没有有缓存')
_this.videoSrc = url // 我是在线链接
// 下载视频
_this.downFile(videoUrlYi,'videoData');
}
// 下载视频
downFile(url,name){
const _this = this;
uni.downloadFile({
url: url,
success: (res) => {
if (res.statusCode === 200) {
console.log('下载成功');
console.log(res.tempFilePath)
//保存视频到本地
uni.saveFile({
tempFilePath: res.tempFilePath,
success: function (res) {
console.log('保存成功');
var savedFilePath = res.savedFilePath;
console.log(savedFilePath)
_this.videoSrc = savedFilePath
console.log('当前连接'+_this.videoSrc)
uni.setStorageSync(name, savedFilePath);
}
});
}
}
});
}
小编推荐:程序员网址导航
收起阅读 »作为一名码农,随着平时工作的需要,这里收集了国内外很多优秀网站,这其中包括在线工具、在线运行、免费接口、在线资源、在线学习、技术论坛、技术博客等等,满足一般程序员日常需求。
授权弹出误点或者测试点击拒绝授权后无法在弹出授权窗口auth deny终极解决方案
先贴代码
视图层部分
<template>
<view>
<button @tap="startRecord">开始录音</button>
<button @tap="endRecord">停止录音</button>
<button @tap="playVoice">播放录音</button>
<button @tap="uploadvoice">上传文件</button>
</view>
</template>
js部分
<script>
let recorderManager = uni.getRecorderManager();
let innerAudioContext = uni.createInnerAudioContext();
innerAudioContext.autoplay = true;
export default {
data: {
text: 'uni-app',
voicePath: ''
},
onLoad() {
},
methods: {
uploadvoice() {
var target = this
let haslogin = false
let accesstoken = ''
try {
accesstoken = uni.getStorageSync('accesstoken');
if (accesstoken) {
haslogin = true
} else {
uni.showToast({
title: '你还没有登录',
icon: 'none'
})
return
}
} catch (e) {
// error
}
if (target.voicePath == '') {
uni.showToast({
title: '你还没录音',
icon: 'none'
})
return
}
//上传音频文件
uni.uploadFile({
url: target.$api.UploadvoiceFile, //接口地址
filePath: target.voicePath, //临时音频文件
name: 'appfile',
formData: {
'accesstoken': accesstoken,
'viewfee': 5 //付费金额
},
success: (uploadFileRes) => {
console.log(uploadFileRes.data);
}
});
},
startRecord() {
//录音先判断是否有录音权限
uni.getSetting({
success(res) {
//获取设置成功
console.log(res.authSetting)
if (!res.authSetting['scope.record']) {
//如果没开启录音麦克风权限提示打开
uni.openSetting({
success(res) {
//打开成功,提示获取录音权限
console.log(res.authSetting)
uni.authorize({
scope: 'scope.record',
success() {
//录音权限获取成功开始录音
console.log('开始录音2');
recorderManager.start({
format: 'mp3',
duration: 600000
});
},
complete() {
console.log('调用接口完成');
},
fail(res) {
uni.showToast({
title: '您拒绝了应用获取麦克风权限',
icon: 'none'
})
console.log(res);
}
})
}
});
} else {
recorderManager.start({
format: 'mp3',
duration: 600000
});
}
}
})
},
endRecord() {
//默认官方把此onStop方法写onload里,但是如果被拒绝的状态后续录音成功也会不执行停止回调,onload只在加载状态执行一次
//保险起见,用户后续开启麦克风权限还能正常回调写停止方法里
let self = this;
recorderManager.onStop(function(res) {
console.log('recorder stop' + JSON.stringify(res));
self.voicePath = res.tempFilePath;
});
console.log('录音结束');
recorderManager.stop();
},
playVoice() {
console.log('播放录音');
if (this.voicePath) {
innerAudioContext.src = this.voicePath;
innerAudioContext.play();
}
}
}
}
</script>
音频文件设置了mp3格式,默认10分钟
上面demo是根据官方录音功能改进的,主要是小程序端,startRecord()录音方法里写了如何解决不弹出授权问题,demo可以直接使用测试,包含上传音频文件方法
php接收音频文件
function uploavoice() {
$message = array ();
$accesstoken = $_POST ['accesstoken'];
$user = $this->check_token ( $accesstoken );
if ($user) {
if (! empty ( $_FILES ['appfile'] )) {
// 获取扩展名
$pathinfo = pathinfo ( $_FILES ['appfile'] ['name'] );
$exename = strtolower ( $pathinfo ['extension'] );
if ($exename != 'mp3' ) {
$message ['code'] = 2001;
$message ['data'] = null;
$message ['message'] = "音频扩展不支持";
echo json_encode ( $message );
exit ();
}
$imageSavePath = 'data/weixinrecord/' . uniqid () . '.' . $exename;
if (move_uploaded_file ( $_FILES ['appfile'] ['tmp_name'], FCPATH . $imageSavePath )) {
$message ['code'] = 2000;
$message ['data'] = SITE_URL . $imageSavePath;
$message ['message'] = "音频上传成功";
echo json_encode ( $message );
exit ();
}
} else {
$message ['code'] = 2002;
$message ['data'] = null;
$message ['message'] = "请上传音频文件";
echo json_encode ( $message );
exit ();
}
} else {
$message ['code'] = 2088;
$message ['data'] = null;
$message ['message'] = "用户信息过期";
echo json_encode ( $message );
exit ();
}
} 先贴代码
视图层部分
<template>
<view>
<button @tap="startRecord">开始录音</button>
<button @tap="endRecord">停止录音</button>
<button @tap="playVoice">播放录音</button>
<button @tap="uploadvoice">上传文件</button>
</view>
</template>
js部分
<script>
let recorderManager = uni.getRecorderManager();
let innerAudioContext = uni.createInnerAudioContext();
innerAudioContext.autoplay = true;
export default {
data: {
text: 'uni-app',
voicePath: ''
},
onLoad() {
},
methods: {
uploadvoice() {
var target = this
let haslogin = false
let accesstoken = ''
try {
accesstoken = uni.getStorageSync('accesstoken');
if (accesstoken) {
haslogin = true
} else {
uni.showToast({
title: '你还没有登录',
icon: 'none'
})
return
}
} catch (e) {
// error
}
if (target.voicePath == '') {
uni.showToast({
title: '你还没录音',
icon: 'none'
})
return
}
//上传音频文件
uni.uploadFile({
url: target.$api.UploadvoiceFile, //接口地址
filePath: target.voicePath, //临时音频文件
name: 'appfile',
formData: {
'accesstoken': accesstoken,
'viewfee': 5 //付费金额
},
success: (uploadFileRes) => {
console.log(uploadFileRes.data);
}
});
},
startRecord() {
//录音先判断是否有录音权限
uni.getSetting({
success(res) {
//获取设置成功
console.log(res.authSetting)
if (!res.authSetting['scope.record']) {
//如果没开启录音麦克风权限提示打开
uni.openSetting({
success(res) {
//打开成功,提示获取录音权限
console.log(res.authSetting)
uni.authorize({
scope: 'scope.record',
success() {
//录音权限获取成功开始录音
console.log('开始录音2');
recorderManager.start({
format: 'mp3',
duration: 600000
});
},
complete() {
console.log('调用接口完成');
},
fail(res) {
uni.showToast({
title: '您拒绝了应用获取麦克风权限',
icon: 'none'
})
console.log(res);
}
})
}
});
} else {
recorderManager.start({
format: 'mp3',
duration: 600000
});
}
}
})
},
endRecord() {
//默认官方把此onStop方法写onload里,但是如果被拒绝的状态后续录音成功也会不执行停止回调,onload只在加载状态执行一次
//保险起见,用户后续开启麦克风权限还能正常回调写停止方法里
let self = this;
recorderManager.onStop(function(res) {
console.log('recorder stop' + JSON.stringify(res));
self.voicePath = res.tempFilePath;
});
console.log('录音结束');
recorderManager.stop();
},
playVoice() {
console.log('播放录音');
if (this.voicePath) {
innerAudioContext.src = this.voicePath;
innerAudioContext.play();
}
}
}
}
</script>
音频文件设置了mp3格式,默认10分钟
上面demo是根据官方录音功能改进的,主要是小程序端,startRecord()录音方法里写了如何解决不弹出授权问题,demo可以直接使用测试,包含上传音频文件方法
php接收音频文件
function uploavoice() {
$message = array ();
$accesstoken = $_POST ['accesstoken'];
$user = $this->check_token ( $accesstoken );
if ($user) {
if (! empty ( $_FILES ['appfile'] )) {
// 获取扩展名
$pathinfo = pathinfo ( $_FILES ['appfile'] ['name'] );
$exename = strtolower ( $pathinfo ['extension'] );
if ($exename != 'mp3' ) {
$message ['code'] = 2001;
$message ['data'] = null;
$message ['message'] = "音频扩展不支持";
echo json_encode ( $message );
exit ();
}
$imageSavePath = 'data/weixinrecord/' . uniqid () . '.' . $exename;
if (move_uploaded_file ( $_FILES ['appfile'] ['tmp_name'], FCPATH . $imageSavePath )) {
$message ['code'] = 2000;
$message ['data'] = SITE_URL . $imageSavePath;
$message ['message'] = "音频上传成功";
echo json_encode ( $message );
exit ();
}
} else {
$message ['code'] = 2002;
$message ['data'] = null;
$message ['message'] = "请上传音频文件";
echo json_encode ( $message );
exit ();
}
} else {
$message ['code'] = 2088;
$message ['data'] = null;
$message ['message'] = "用户信息过期";
echo json_encode ( $message );
exit ();
}
} 收起阅读 »
无条件支持Dcloud,希望Dcloud越走越远
在客户端产品开发没选型之前,北京一个客户建议用apicloud开发,我当时建议是uni-app,也算是眼缘吧,然后试着把老的vue项目重构成uni-app,并编译了百度小程序,头条小程序,微信小程序,体验流畅不卡,唯独app端还没做适配,估计改起来也不是很大工作量,uni-app开发文档写的还可以的,国产应该支持,本人就是做国产开源社区的,Dcloud是我唯一见过能快速编译到多平台且兼容性不错的开发工具,确实提升了开发速度。
有个小建议:
插件市场里的有些作者有点不负责,导致项目会开发可能会返工,他们有的开发完成没标注是否适合app端或者兼容到哪个平台小程序或者哪些机型有问题。
希望增加一个选择项,把已知问题让作者列出来,或者在插件入口给此插件单独开通一个话题讨论,这样利于知识沉淀,后来者也可以少踩坑,直接可以找到现成问题并解决。
在客户端产品开发没选型之前,北京一个客户建议用apicloud开发,我当时建议是uni-app,也算是眼缘吧,然后试着把老的vue项目重构成uni-app,并编译了百度小程序,头条小程序,微信小程序,体验流畅不卡,唯独app端还没做适配,估计改起来也不是很大工作量,uni-app开发文档写的还可以的,国产应该支持,本人就是做国产开源社区的,Dcloud是我唯一见过能快速编译到多平台且兼容性不错的开发工具,确实提升了开发速度。
有个小建议:
插件市场里的有些作者有点不负责,导致项目会开发可能会返工,他们有的开发完成没标注是否适合app端或者兼容到哪个平台小程序或者哪些机型有问题。
希望增加一个选择项,把已知问题让作者列出来,或者在插件入口给此插件单独开通一个话题讨论,这样利于知识沉淀,后来者也可以少踩坑,直接可以找到现成问题并解决。
hbuilderX编辑器貌似有点low
HBuilderX编辑器下载后,点击运行,出现卡死的界面。
我的是win10 64位机器。且发现官方给的windows下载版本是32位的。。
官方是不是有点太草率了。连一个编辑器安装都出现各种奇葩问题。。。
HBuilderX编辑器下载后,点击运行,出现卡死的界面。
我的是win10 64位机器。且发现官方给的windows下载版本是32位的。。
官方是不是有点太草率了。连一个编辑器安装都出现各种奇葩问题。。。










