3天时间从零到上架AppStore流程记录

清明假期刚过去一周,我如愿以偿把自己想要的一个App上架了AppStore

从有idea到技术选型,从设计稿到框架开发,从提审AppStore到上架一共经历了3天,这3天里我踩了很多坑,忙得焦头烂额,期间发现网上很多信息都是过时的,所以本着一个总结的想法,写了这篇文章。

一、idea到设计稿

(一)idea灵感来源

平常我上班很忙,休闲时会刷手机看B站、Youtube视频,
但因为平时关注了太多人,想看的却只有那几个,
但还是会忍不住点击算法推荐的视频。

  • "xdm干净又卫生啊"
  • "大佬别这样"
  • "守护每一个不切实际的梦想"

B站内容丰富,每次不仅看不到想看的视频,反而花了比预计好几倍的时间。

所以我想要做一个产品,喜欢能够帮我追踪B站、Youtube平台上我最想关注的人的动态,
不用我每次打开B站、Youtube去查看内容,所以我按照平日工作里排期的流程给自己做了功能的排期:

- 喵酱爱订阅
- 展示导航栏
- 搜索页面
- 写搜索的cgi
- 写解析用户状态的cgi
- 要支持右滑取消订阅
- 把用户状态数据更新到缓存
- 把缓存落到DB
- 每次启动读取DB
- 制作宣传视频
- 制作启动教育页
- 联系页
- 联系跳转等页面
- 性能优化
- 加一个by xxx 关注,然后谈起一个半屏
- 加一个 xx、yy和另外x人关注了此账号
- 需要加入loading等逻辑
- 全局extension call:按id注册,还是全部接收
- 开始更新订阅数据 - 搜索页面
- 出现导航栏
- 出现关闭按钮
- 点击搜索要能过渡到另外一个搜索界面
- 开始接B站搜索的api
- 开始实现订阅该Up主功能
- 滑动删除
- 搜索交互调整 - 订阅数据
- 开始更新订阅数据,获取更全的信息
- 按timeline排序 接下来要做的:
- 支持Youtube订阅
- 完成B站跳转逻辑
- 完成Youtube跳转逻辑
- 完成清理红点逻辑
- 调整搜索中间页逻辑
- 「关于」页面设计
- 帮助和常见问题
- 隐私政策
- 视觉还原和调整(添加约束)
- 添加主页元素的联动约束
- 主页下滑不到最底部
- 导航栏颜色问题
- 修bug
- 订阅完之后,不会立刻出现
- Youtube API无限调用
- App选一个图标

(二)自己搞定设计稿

有了idea之后,按照正经开发流程,相当于是产品方案确定了,接下来就需要设计稿了。

咨询了公司里的设计同事,他们给出了两个建议:Sketch 或者 Figma,体验之后自己选择了 Figma 这款设计软件。

选定软件,用了半天的时间画了简单的设计稿:

这里我要吹一下 Figma 这个软件,从零到上手真的半天都不用,真的是"有手就行"。

二、框架选型和开发

(一)基础框架

首先说一下这款软件我是使用 Objective-C 写的,为什么不用 Swift 呢?因为我之前积攒的基础库都是用 Objective-C 写的,所以为了求快,还是选择了 Objective-C 。

1. 清理 main.storyboard

一个稍微大点的项目基本都不会使用 main.storyboard ,所以我们首先上来无脑清理掉 main.storyboard ,改为纯代码模式。

(1) 删除main.storyboard和launchScreen.storyboard,右键delete-Move to Trash

删除SceneDelegate.h和SceneDelegate.m文件,也要选择Move to Trash

(2) 选中工程 - General - Deployment Info - Main Interface 设为空

App Icons and Launch Images - Launch Screen File 设为空

(3) 删除 Info.plist 下 Application Scene Windows

(4) 在AppDelegate.h 和AppDelegate.m文件中添加如下代码:

self.window = [[UIWindow alloc]initWithFrame:[UIScreen mainScreen].bounds];
self.window.backgroundColor = [UIColor whiteColor];
BNMainViewController *vc = [[BNMainViewController alloc] init];
self.navigationController = [[UINavigationController alloc] initWithRootViewController:vc];
self.window.rootViewController = self.navigationController;
[self.window makeKeyAndVisible];

(5) 注释掉 AppDelegate.m 中的 Lifecycle 代码

   #pragma mark - UISceneSession lifecycle

//- (UISceneConfiguration *)application:(UIApplication *)application configurationForConnectingSceneSession:(UISceneSession *)connectingSceneSession options:(UISceneConnectionOptions *)options {
// // Called when a new scene session is being created.
// // Use this method to select a configuration to create the new scene with.
// return [[UISceneConfiguration alloc] initWithName:@"Default Configuration" sessionRole:connectingSceneSession.role];
//}
//
//
//- (void)application:(UIApplication *)application didDiscardSceneSessions:(NSSet<UISceneSession *> *)sceneSessions {
// // Called when the user discards a scene session.
// // If any sessions were discarded while the application was not running, this will be called shortly after application:didFinishLaunchingWithOptions.
// // Use this method to release any resources that were specific to the discarded scenes, as they will not return.
//}

(6) 展示导航栏

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {新增:

[[UINavigationBar appearance] setTitleTextAttributes:@{NSFontAttributeName : [UIFont boldSystemFontOfSize:18], NSForegroundColorAttributeName : [UIColor whiteColor]}];

2. Cocoapods和基础库

之前我问过一些大学里的学生,学完iOS知识后为什么不自己尝试做一个项目呢?年轻人有想法有精力的,他们中有一些人的回答是:"太麻烦了,iOS语法真繁琐"

我有点惊讶,iOS的语法为什么会繁琐呢?后面和他们深入聊的时候才发现他们大多数人是因为缺少基础库,导致他们开发门槛非常高。

比如哪些基础功能呢? 最常见的就是:

@interface UIView (Extension)
@property (nonatomic, assign) CGFloat x;
@property (nonatomic, assign) CGFloat y;
@property (nonatomic, assign) CGFloat centerX;
@property (nonatomic, assign) CGFloat centerY;
@property (nonatomic, assign) CGFloat width;
@property (nonatomic, assign) CGFloat height;
@property (nonatomic, assign) CGSize size;
@property (nonatomic, assign) CGPoint origin;
@end

布局是项目中最高频出现的,一个新项目如果你没有做 UIView 如上的category方法,那么你每次改变一个frame都要写全,相当繁琐。

还有一些比如支持SVG图渲染、自定义颜色、导航栏状态栏默认高度等等,就是因为这些基础的逻辑无形中提升了开发的门槛。

所以我在项目中集成这些能力后,将这些基础能力抽成一个项目,如果想开发App的基础这个项目开发上手速度会更快:

一个通用的iOS开发底层模板(持续更新)

项目集成了如下的库:

 pod 'YYKit'
pod 'Colours'
pod 'SDWebImage'
pod 'SVGKit', :git => 'https://github.com/SVGKit/SVGKit.git', :branch => '3.x'
pod 'WCDB'
pod 'AFNetworking', '~> 3.1.0'
pod 'ViaBus'
pod 'FCAlertView'
pod "Aspects"
  • YYKit:提供各种基础通用能力的库
  • Colours:一个提供比系统更全的颜色库
  • SDWebImage:https图片加载框架
  • SVGKit:SVG图加载框架
  • WCDB:通用强大的iOS本地数据库
  • AFNetworking:开源的http网络请求框架
  • ViaBus:订阅总线框架
  • FCAlertView:比系统alertView功能更强大的类
  • Aspects:业内公用Num.1的AOP框架

因为使用cocoapods集成了基础库,所以下载使用前先执行 pod install

(二)B站、Youtube API 和 PostMan调试

1. 我是如何获取API的?-Chrome开发者模式

既然要搜索订阅的up主,那么就需要获取blibil和youtube的查询api,那怎么获取 B站 的API呢?

我们知道 Chrome 的开发者模式可以抓取网络请求,所以我们按照下面的流程操作:

打开B站的搜索界面:

然后打开Chrome浏览器自带的 开发者工具:

打开之后界面是这样的:

接着我们重新刷新界面,让开发者工作抓到我们的网络请求:

可以看到「网络」这一栏出现了如此多的网络请求回包,其中有一个网络请求就是我们查询B站的接口,我们如何快速从中获取我们想要的API?

我们在「响应」这一栏中可以看到网络回包的结果:

{
"code": 0,
"message": "0",
"ttl": 1,
"data": {
"seid": "1742183592668294498",
"page": 1,
"pagesize": 36,
"numResults": 1,
"numPages": 1,
"suggest_keyword": "",
"rqt_type": "search",
"cost_time": {
"params_check": "0.000513",
"get upuser live status": "0.002915",
"illegal_handler": "0.012658",
"as_response_format": "0.003668",
"as_request": "0.023251",
"save_cache": "0.000952",
"deserialize_response": "0.000201",
"as_request_format": "0.000448",
"total": "0.045491",
"main_handler": "0.027793"
},
"exp_list": {
"7706": true,
"5507": true,
"6604": true
},
"egg_hit": 0,
"result": [{
"type": "bili_user",
"mid": 41487006,
"uname": "木南之的技术生活",
"usign": "腾讯iOS开发工程师,有一只仓鼠(二狗)一只猫(芝士),我的网站:https://bninecoding.com",
"fans": 2,
"videos": 7,
"upic": "//i2.hdslb.com/bfs/face/2399a9747dbc4449139da82cbaff23e332a8d94d.jpg",
"face_nft": 0,
"verify_info": "",
"level": 4,
"gender": 1,
"is_upuser": 1,
"is_live": 0,
"room_id": 22106726,
"res": [],
"official_verify": {
"type": 127,
"desc": ""
},
"hit_columns": ["uname"]
}],
"show_column": 0
}
}

可以看到 data->result 中发现了 木南之的技术生活 的信息,而且还是一个标准的json格式,这肯定就是我们需要的 api了,我们点击请求头把请求api拷贝出来:

https://api.bilibili.com/x/web-interface/search/type?__refresh__=true&_extra=&context=&page=1&page_size=36&order=&duration=&from_source=&from_spmid=333.337&platform=pc&highlight=1&single_column=0&keyword=木南之的技术生活&category_id=&search_type=bili_user&order_sort=0&user_type=0&dynamic_offset=0&preload=true&com2co=true

里面有一些我们用不上的参数,经过精简,我们得到如下的B站查询接口api:

https://api.bilibili.com/x/web-interface/search/type?page=1&page_size=5&search_type=bili_user&order_sort=0&user_type=0&keyword=木南之的技术生活

2. B站、Youtube API大公开

(1)B站搜索API

https://api.bilibili.com/x/web-interface/search/type?page=1&page_size=5&search_type=bili_user&order_sort=0&user_type=0&keyword=木南之的技术生活

(2)B站获取发表内容API

https://api.bilibili.com/x/space/arc/search?mid=xxxxx

(3)Youtube搜索API

https://youtube.googleapis.com/youtube/v3/search?part=snippet&maxResults=5&type=channel&key=秘钥&q=搜索内容

秘钥可以在 Google Youtube API 上注册获取,免费但有每日调用约束。

(4)Youtube获取内容API

https://youtube.googleapis.com/youtube/v3/search?part=snippet&order=date&type=video&key=秘钥&channelId=xxxx

3. PostMan API调试利器

在调整API期间,我使用了 PostMan 这款API调试利器,可以非常方便帮我们验证究竟是iOS的代码有问题,还是接口的问题。

三、提审AppStore斗智斗勇

iOS 打包和上架流程可以参考这篇文章,iOS App的打包和上架流程

我按照这篇流程走下来,基本没踩什么坑,如果你要进行iOS App的打包和上架,建议你先看完上面这篇文章,然后再看我下面的补充:

在使用 Xcode - Product - Archive - upload 打包上传后,我们预期是能在 Apple Development 提审网站 的 「构建版本」 看到我们上传的ipa包的

但实际上会发现我们 upload 后,大约要等上个 10分钟 左右,才能在网站上刷到我们上传的包,是什么原因呢?

是因为Apple会对我们上传的包进行一遍静态代码扫描,比如调用私有API、使用过期无法维护的组件都会被reject,比如我下面收到的一个警告:

ITMS-90809: Deprecated API Usage - New apps that use UIWebView are no longer accepted. Instead, use WKWebView for improved security and reliability. Learn more (https://developer.apple.com/documentation/uikit/uiwebview).

意思很清楚,说我们不能在项目中使用 UIWebView ,因为已经被废弃了,建议我们改用 WKWebView,我们按建议修改即可。

当静态代码扫描通过后,我们会收到如下一封右键,这就表示我们可以提审ipa包了,我们添加构建版本即可。

3天时间从零到上架AppStore流程记录的更多相关文章

  1. Hbuilder用自有证书打包 ios App上架AppStore流程

    最近在用Hbuilder做跨平台开发,经过一番研究终于在苹果商店上架成功了一款产品!这款产品就很简单,直接用hbuilder打包好,然后上传到商店即可.这里参照ios app提交应用商店 这篇文章结合 ...

  2. iOS App上架AppStore 会遇到的坑

    前言部分 前言:非原创 文章摘自:http://zhuanlan.zhihu.com/100000PM/20010725 相信大家一定非常「深恶痛疾」AppStore的一系列产品上架规则.每次产品上架 ...

  3. (转))iOS App上架AppStore 会遇到的坑

    iOS App上架AppStore 会遇到的坑   前言:非原创 文章摘自:http://zhuanlan.zhihu.com/100000PM/20010725 相信大家一定非常「深恶痛疾」AppS ...

  4. iOS app 上架的流程与注意点

    这里整理了两个关于苹果应用商店上架方面的资料: 一个是app上架的流程,里面包含各个环节的截图,比较详细. 流程介绍链接   (提取码:52a4) 第二个是app上架的一些注意点,这里面主要说的是上架 ...

  5. 图文详解丨iOS App上架全流程及审核避坑指南

    App Store作为苹果官方的应用商店,审核严格周期长一直让用户头疼不已,很多app都"死"在了审核这一关,那我们就要放弃iOS用户了吗?当然不是!本期我们从iOS app上架流 ...

  6. Xcode7.1环境下上架iOS App到AppStore 流程③(Part 三)

    前言部分 part三 部分主要讲解 Xcode关联绑定发布证书的配置.创建App信息.使用Application Loader上传.ipa文件到AppStore 一.Xcode配置发布证书信息 1)给 ...

  7. 【转】Xcode7.1环境下上架iOS App到AppStore 流程 (Part 三)

    原文网址:http://www.cnblogs.com/ChinaKingKong/p/4964745.html 前言部分 part三 部分主要讲解 Xcode关联绑定发布证书的配置.创建App信息. ...

  8. iOS开发实战-上架AppStore 通过内购和广告获得收益

    写在前面 由于一些原因需要离职,准备重回大上海 忽然发现手头上也没什么独立App,那就随便写个放到AppStore上吧,凑个数吧.哈哈哈. 这个App是无聊找配色的时候看到的一套图 正好春节在家没什么 ...

  9. Xcode7.1环境下上架iOS App到AppStore 流程③

    前言部分 part三 部分主要讲解 Xcode关联绑定发布证书的配置.创建App信息.使用Application Loader上传.ipa文件到AppStore 一.Xcode配置发布证书信息 1)给 ...

随机推荐

  1. C# 静态成员和方法的学习小结

    C# 静态成员和方法的学习小结 数据成员:数据成员可以分静态变量.实例变量两种.静态成员:静态成员变量是和类相关联的,可以作为类中"共"有的变量(是一个共性的表现),他不依赖特定对 ...

  2. ASP.NET Core 6框架揭秘实例演示[26]:跟踪应用接收的每一次请求

    很多人可能对ASP.NET Core框架自身记录的诊断日志并不关心,其实这些日志对纠错排错和性能监控提供了很有用的信息.如果需要创建一个APM(Application Performance Mana ...

  3. [SPDK/NVMe存储技术分析]009 - Introduction to RDMA Send | RDMA Send操作概论

    来源: https://zcopy.wordpress.com/ 说明: 本文不是对原文的逐字逐句翻译,而是摘取核心部分以介绍RDMA Send操作(后面凡是提到RDMA send, 都对应于IBA里 ...

  4. session 会话机制以及变量覆盖

    session会话机制介绍如下 http是无状态协议.服务器靠cookie和session来记住用户.$_SESSION 和 $_GET等一样,是超全局变量. 后台脚本里面会写: session() ...

  5. TypeScript编译tsconfig.json配置

    配置预览 { "include": ["src/**/*"], "exclude": ["ndoe_modules", ...

  6. ConcurrentHashMap 的并发度是什么 ?

    ConcurrentHashMap 的并发度就是 segment 的大小,默认为 16,这意味着最多同时可以有 16 条线程操作 ConcurrentHashMap,这也是ConcurrentHash ...

  7. kafka中的回调函数

    kafka客户端中使用了很多的回调方式处理请求.基本思路是将回调函数暂存到ClientRequest中,而ClientRequest会暂存到inFlightRequests中,当返回response的 ...

  8. 两个链表有一个交点,如何在时间复杂度 O(n) 和 空间复杂度 O(1) 的条件下实现?_字节跳动面试题

    输入两个链表,找出它们的第一个公共结点 我们可以首先遍历两个链表得到它们的长度,就能知道哪个链表比较长, 我们可以首先遍历两个链表得到它们的长度,就能知道哪个链表比较长,以及长的链表比短的链表多几个结 ...

  9. 使用conda管理python环境和包

    操作系统:CentOS7使用virtualenv管理python虚拟环境virtualenv是一款轻量级第三方虚拟环境管理工具,不像Anaconda大小达上百M,virtualenv大小只有10M左右 ...

  10. 【Azure Developer】使用PowerShell Where-Object方法过滤多维ArrayList时候,遇见的诡异问题 -- 当查找结果只有一个对象时,返回结果修改了对象结构,把多维变为一维

    问题描述 编写PowerShell脚本,以多维(3维)数组中第二维度的值进行过滤,并打印出结果 #三维数组源数据 "A", "11", "Cheng ...