2016.12.14

 • 

本周。


首先插播软件更新播报:
ArtWall 在大约两周前出现了无法刷新 Feed 流的问题,后来发现是 ArtStation RSS 本身输出格式更改了。昨天花了二十分钟修了。等待审核。
Contributions For GitHub 1.0.2 现已支持 Apple Watch,感谢 YunoCee 帮忙测试。以及我目前手上的三台 iOS 设备运行 Contributions 时都不能正常进行 background fetch(即挂件不刷新),如果正式上线版本有此问题,请发邮件告知我。


对于我而言比较有趣的(对我的顾客而言貌似不是)的一件事情
半年前写了 WebDrop,算是第一个 macOS 软件。当时初学 Cocoa 桌面开发练手,把这个软件上架到了 MAS 上定价一块钱,也是我目前所有应用商店里唯一一个收费软件(本身一直是开源的)。以现在的眼光来看这个软件的确没有什么用 —— 虽然的确在功能上还算是有些独特罢了。然而最近多了两个一星差评,现在总共三个全一星让我不得不考虑了下我要如何处理这个软件。
之前有个国区评价 “太烂啦,蒙了我一块”,我也没在意。最近多了一个墨西哥区的西班牙文评价,大概是说软件“什么都没有”。翻译看得我一头雾水,但说我是诈骗(原文 'fraud')这个我算是能看明白。我倒是挺好奇什么情况能让他如此激动。激动你就申请 refund 呗,又不能来中国打我。
在这种情况下,我只好在软件描述加了一段文字,大意是软件有开源版本,不想买就去 GitHub 下载好了,软件使用有问题发我邮件,可千万别再花一块钱买完给一星了,我真是倒过来送钱给你们都行
至于为何我还给这个软件定价一块:至少要保留一个收费软件(即使一年靠这挣不了 50 刀),让我作为一个开发者有个盼头啊。


除此以外本周就没有什么要说的了。想了下,发现本周关于自己貌似没有什么值得一提的事情。此外,最近总是睡不着。睡不着的时候,总是觉得自己要是还在北京呆着就好了。

2016.12.07

 • 

睡到了凌晨三点多。下楼买了瓶可乐,清醒了些。
这几天:
孤独星球 app 上架了,Google Play | App Store。对机器的要求比较高,安卓版本虽然做了自动分辨率 downgrade,但还是最好用 Nexus 5 及以上设备。至于苹果设备,A8 芯片及以上,A7 设备在显示地面 Shader 的时候会出现大面积黑色,这是一个新问题,尚不清楚原因,也不准备修了。这个版本的孤独星球就是一个 Demo,没有其他功能,苹果给上架我反而很惊讶。


用外包的钱买了 Apple Watch S1。可以写发射核弹的手表 app 了。
得益于心率传感器,现在我的 Gyroscope 可以显示心跳了。
和我妈聊天,谈到靠工资,外包什么的,有半年不问父母要生活费了。当然这学期学费还是爸妈交的,算是半自给自足。


Cetacea-Mac 的开发慢慢继续,还是把文档存储的基准改为了 NSDocument。之前一直有个偏见是如果用了 NSDocument 就不能在 iOS 端通过 iCloud 读取数据了,直到后来我才发现可以用 NSDocument 存为 bundle-based folder,类似于 .app / .xcproject,读取的时候其实就是读文件夹。因此花了些时间修改,也真正注册上了 .cetacea 的文件后缀。
之前给 Cetacea 加了很多类似于 Ulysses / Mou 的功能愿景,加了很多开关,现在全部砍掉,秉承着“我这软件就这样你爱用不用的”的原则。现在感觉好多了,至少感觉有生之年能填完坑


终于玩上了 Watch Dogs 2 (PC)。开车还是一如既往的卡,除此以外我很喜欢,我就是那种喜欢让角色蹲在墙角等敌人一个个来然后解决的无聊玩法玩家,好像玩 Deus Ex 的时候也是经常这样。


最近吃了好多次烤鱼和牛蛙,不得不感叹长沙在这一点上还是符合我胃口的。


听了:
Soulection #286 | Soulection #287 :Dope
Technologic by Daft Punk:之前被这首歌洗脑了一暑假,原因是写我司盒子放音乐的鼓点侦测功能时老板经常用这首歌测试,但我之前一直不知道叫什么....

2016.12.01

 • 

又是新的一月了,满眼灰色的冬天。

11.30 是我司(或者说我前司,我在学校已经不写公司项目了)新品发布会。没在现场,但看 Cee 直播还是略激动的,毕竟是自己参与开发的东西。而产品出来之前说什么相关的都不好,一个是签了 NDA,暑假因为这个还被坑过一次,另一个是空口无凭总有些不对劲。现在东西出来了,我也算是可以说这是我参与的第一个落地的公司项目了,作为一个前期负责写三维场景相关的程序员的身份。
今年断断续续写了一些代码,公司的外包的,有时候会觉得写的非常没有意义,因为生产出来的东西太易碎了。hackathon 的产出虽然快,但是是以牺牲稳定性得到的。如果为了赶功能或赶着给其他人 Demo 就 hackathon 一样地写,短期内没有什么问题,但之后不重构就直接合到主 branch 总归是一件让人提心吊胆的事情。同样类似的还有后端接口没有完成,iOS 为了赶上架在本地根据参数拼接网页地址,虽说可行,但总会遇到特殊字符挂掉的,而这么多不稳定的功能放在一起,基本上就是挂了一个就全挂了。
而我总不想让自己生产出来的内容像是那些 App Store 上的软件,还没过几年就已经不能正常运作了。很多 iOS 6 时代上架而现在看来截图仍然精美的软件,在想要怀念的时候打开却闪退,总归是一件没有生命力的事情。

11 月是我迄今为止生产力最旺盛的月份。写了 ArtWall,Board For GitHub,Lonely Planet,总还算是一个不错的成绩。接下来要写的是和 Kevin 的 Unity 项目,以及之前挖的一些小坑。

2016.11.27

 • 

周日了。
外包在周二还是周三提交了。到现在还没开始审核。
黑五促销买了一堆 app,bundle 以及游戏。值得一提的是买了两款 Trackmania 系列作品,但多少令我失望的是没有很久以前玩 Trackmania Sunrise 的那种随心所欲的感觉了。
Contributions 因为之前在 Hunt 上当日排名第四,下载量暴增(单周 +559%)。提了一个新版本,也在等审核,这一版 Cee 帮忙修了 7 Plus 上因为宽色域占用内存翻倍导致挂件崩溃的问题。
接下来应该去着手写之前答应的一个 Unity 项目了,而我一直挂念着 Epoch,索性花了两晚上把 Epoch Core 做成了一个单独的 app,叫 Lonely Planet。图标和截图如下:

做到今天早晨,提交了。所以这个也在等 App Store 过审。因为是 Unity 写的,port 到 Google Play 上提交也很容易,但我现在没这个力气了,我只想睡觉。

这几天听了 Summer Breeze by Piperじれったい(2010ヴァージョン) by Anzen ChitaiShadow on the Sun by Audioslave

总觉得有什么忘了写了,回头再说。

2016.11.22

 • 

ArtWall 在向 Apple Review Board appeal 三天后终于有了结果,准备提交一个新的二进制文件。这期间给 ArtWall 加了开机自启的功能,实现功能时发现能找到的教学资源都是 12 年左右的,有些地方在 10.12 上已经不能用了。或许后面会关于开机自启写一个小总结。


Epoch Core Demo 用 Unity 5.4.3f1 打开是一片粉红,陆地 Shader 又不能正常渲染了,sigh。如果连 0.0.x 这样的小版本都能有较大的 API break change,那我真的不知道要说什么了。估计要等几天把 Shader 适配到 5.4.3f1 上。


说到外包。最近这两周写这个外包真的是让我有些烦躁,原本接的时候以为前后端齐全只差 iOS 了,结果真正开始写的时候是服务器网页和客户端一起写一起商定接口再写的。然后就是没有文档这件事情,说大不大说小不小,但到最后就会很麻烦。
举个例子,UIButton 有很多 State,特别是对于 "On/Off" 而不单单只 "Push In" 这样的按钮,其显示状态是有很多的,对应业务上网络请求也有几种选择:若一开始是 On,是按下后立即更新到 Off 状态然后等到网络请求成功与否,还是加给按钮加一个 Requesting 的中间态作为网络请求时的过渡。两个方案都可行,但如果不说清楚,到后面再改就会很费劲。而单单一个 Sketch 设计稿很多情况下是没有包括这么多状态的,没文档只照着 Sketch 做就会有很多摸不准的情况需要再去问需求方,也耗费了很多时间在这个上面。
要说写软件期间有什么收获:WKWebView 不能拦截请求做本地缓存,在内存比较小的手机上和网络图片库一起用反而会因为 GPU 的某些问题出错。易白屏。坑略多,Hybird App 慎用。


Contributions for GitHub 这个小软件之前提到过,我写完后发现有一个 bug:不能使用后台刷新功能。我一直在找这个 bug 的原因,直到最近我才发现,大部分设备都是正常的,只有国行设备,因为“网络权限”没有弹出的原因,导致了软件不能联网获取 GitHub 的 contribution svg。既然这个 bug 不是我写的,那问题就算解决了。就把这个东西放上了 Product Hunt,目前有 157 个 upvote,最令我惊讶的是 MacStories 的编辑 Federico Viticci 也给这个软件 upvote 了。

2016.11.19

 • 

本周。

做了:

  • 花了两天设计和写了一个 macOS 小软件,叫 ARTWALL
    功能是常驻状态栏,刷新 ArtStation.com 上的 RSS 流,多显示器侦测,一键设置壁纸。


(上图为 App Store 宣传图) 。

然后被拒了:


拒绝理由是:

The experience that your app provides is not sufficiently different from browsing a content aggregator web site.
While your app may facilitate access to content from a range of web sites, even when including native Mac OS X features, the experience it provides is not significantly different from using Safari. Such apps do not include enough native Mac OS X functionality to be appropriate for the App Store.

不是很懂苹果审核人员,全原生写的,功能上也用了 NSWorkspace 的一些特性,可以检测显示器个数什么的,结果和我说体验和 Safari 差不多?Excuse me?
准备过几天把自启动,定时刷新,定时换壁纸,键盘快捷键都给做了,再试试。而如果现在想要体验下的话,可以去 Dropbox 的这个链接下载。


  • 外包
    还在写。(捂脸

  • Epoch Core Demo
    介于 Epoch 估计要很长时间才能继续开发,所以三天前开了一个新 branch,会出一个基于 Epoch Core 的一个小原型,展示下基于 LibNoise 的 Shader。

听了:


2016.11.13

 • 


这周三第一节 iOS 课不算很成功,我到了实验室才发现机器的状态都不太对 —— Mac Pro 不知道被谁升级了系统,学校采购的 OSX Server 跟着不能用了(说是采购,其实经销商只是用他的 Apple ID 登陆下载了一个副本而已 —— 账户仍然在他那里)。而作为学生机器用的 iMac 有一半没有安装 Xcode,系统也没有达到最新 Xcode 的最低要求。多亏了一起来的同学把所有机器都配置到了能用的状态,耽误了一个小时左右。除此以外我的表现只能说乏味可陈,还好大家能听懂跟着做,算是把基础知识和大家介绍了下。
备课的时候实验了下用 Nginx 的 RTMP 模块配合 OBS Studio 推流,学生机直接用 VLC 看我的实时屏幕,不知道为何在我的网络条件下延时差不多有 10 秒,做 Live Coding 的话还不如直接看投影仪。
下周三就要开始讲 C/ObjC 了,幻灯片还没做,头痛。


周日了,外包还是比想象中的要迟一些,不过也是我没有预估到一套 IM 系统模块需要的工作量 —— 不能 PM 说只是一个简单的私信就跟着觉得简单了,实际上“简单的单人站内信”和“复杂的多人聊天”两者从架构上来说是一样的,要写的代码也差不多多。


这周一的时候和崇哥一起去找辅导员谈话。谈话内容不能保证真实,毕竟都过去好几天了,也有个人偏差在里面,但大致如下:
我:觉得学校有些课没用,所以没去。
辅导员:学校的课上起来总是有用的,目前也许觉得没用,但你不能保证后面没用。
我:是,后面也许会有用处,但程序员本身就是终身学习,需要的时候再学其实也没什么大问题的样子。进大型互联网公司基本都要培训几个月,真正有用到的部分也是这几个月教的。
辅导员:那你们就真的甘心一直当个码农?
我:后面的我不知道,反正现在我的目标就是能在毕业的时候拿到大厂的 offer,然后先赚钱再说。
辅导员:我看错你们了,我原本以为你们俩是有情怀的程序员,就像是校长一样。
我:校长我不知道,但我斗胆说一句,程序员圈子里,情怀都是虚的,没有技术什么情怀都没用。况且我们也参加过一些学校的软件比赛,看着空有情怀没有成品的人拿奖
1
,所以我个人挺反感情怀。
辅导员:你这是鸡汤没喝够,人啊总要有虚的东西支撑着自己。你有什么来支撑自己?
我:我的三观吧,我猜。我这个人比较喜欢生产事物供别人消费,而且我想证明自己能做到。
辅导员:你这样不会幸福的。
我:我其实也有幸福的时候,我暑假在北京实习就很幸福,写自己擅长的软件,和志趣相投的人做朋友,有钱可赚,有钱可花。
辅导员:不要总想着要去证明什么,很幼稚的。而且你还是在说消费和挣钱这种现实的事情。我不希望你们就只是个码农,整天只谈论技术,而不去欣赏其他的事物(大意是这样,具体我也忘了)。
我:也许你会觉得我在学校很 nerd,整天点外卖,呆在寝室。但我也不只是做技术,我还做些设计,我也写写博客。我呆在寝室主要还是觉得时间不够用,否则拿不到 offer 啊。我看同龄人都那么厉害,我想追。
辅导员:你追的话永远也没有完结的一天的。你这样下去不会幸福的。然后辅导员举了一个好几届之前的一个人的例子,大致是这个人工作很忙,不过表现的积极向上,感染他人,至于房子这个人觉得年轻不需要考虑买房子的事情。
我:....(忘了中间说了什么)
辅导员:你和上一次来完全不一样,整个人显得状态很不好,建议你去看下心理医生吧。

聊完后,我的确一个下午都处于一种怀疑自己的状态。当然现在肯定不是了。
的确如辅导员所言,如果努力证明什么事情,他人会觉得自己过于用力而显得幼稚。但不去证明,只会被大家嘲笑“这个人觉得自己是天才可以不走寻常路实际上什么都不是”。而我也无意证明什么天才不天才,大部分人只不过用别人是天才的借口来把努力程度的差距转换为智商上的差距然后心安理得继续偷懒。我只想证明的是,想做什么就去做,够努力就能成功。
而至于情怀,我个人的看法仍然是,没有把情怀实现之前不要提自己有情怀。情怀本身是一个私密的东西,不宜轻易拿出来谈。如果连北京租房预付三个月都付不起,谈情怀又有什么用呢。现实世界里的乌托邦总是需要钱堆起来的,就如同为了岸头的绿灯,盖茨比干的那些勾当一样。

  1. 参见大一《软件外包赛校内答辩经过》http://www.justzht.com/waibaodasai/.

2016.11.7

 • 

过去的一周。

做了:

  • 续费了 Animatious 网站的域名。
    顺带更新了下 Google 字体的镜像源。
    一年过去,Animatious 已经不活跃了,不过网站还是要保证能访问的。
    至于动画,现在看我一年前的 repo 感觉写的太烂了,当时写一个按钮连按下后事件的 delegate 都没写都敢拿去骗 star。现在水平好多了,但不知道为什么,就是不想写动画控件了。现在反而是特别想完成一整个 app,从 layout 到单个 UIControl 能够达到自己认为完美无缺的那种,而不是单单写一个控件。
  • 外包进度完成大半,预计本周末能上线吧。
    这也算是我第一次做 hybrid app 的外包。
  • 学校的各种事情。课设,体测。
    说大三课少,但课设并不少。而且之前也说了,第一节课就写完了,老师仍然会让学生每节课都去机房呆着。我实在想不出来在没网的机房能干嘛,带着电脑还要开自己的手机热点,这种环境写外包效率为零。所以我第一节课写完后就一直没去,中间老师说我不来算挂了可以不用检查了。结果最后一节课老师又通知班长让我去检查。于是去了,查查算给过。
    十月份开始课设变多后,就经常有突然的通知。这种突然的通知总是让我很烦躁,没有一大段时间可以用来钻研某个问题,而且要是去了吧,老师点个名就聊天去了,留一堆学生在没网的机房玩手机。而我又特别痛恨无缘无故浪费时间,眼下外包没写完,一个说要和朋友一起做的 Unity 工程感觉都拖到无限远去了,再不抓紧真不知道我今年还能出什么东西。而那些家伙自以为学生的时间不值钱,当着你的面浪费你的时间,还指望你感谢他给你的课设提出了宝贵的建议。
  • 算是备了一会课
    中南大学的苹果实验室算是建立起来了,我估计后面每周三都会去讲一些 iOS 开发的内容。因为授课对象有大一的同学,所以应该从 C 语言开始讲起,再到 ObjC,Foundation,UIKit,等等等等。至于结果如何就看这周三了。

看了:

  • 但丁密码 (Inferno)
    还行。但我就想多嘴问一句为何这一部里面感情戏和温情回闪这么多。
  • 奇异博士 (Doctor Strange)
    CGI 不错。剧情速度感觉有些失衡。也是我见的第一个 Boss 被气走而不是被打死的英雄电影。
  • Unite 16 Los Angeles
    终于有 Metal Compute Shader 和 Mobile Instancing 的影子了。另外 Octane Renderer 虽然出现在里面但是并没有看出来究竟是干嘛用的,看 Demo 貌似是一个完整的实时 Renderer,但是实时跑起来的话感觉光线数估计要低到噪点很多的程度,挺期待的。

听了:

WKWebView Native & JS Stuff

 • 

目前在写一个半 web 半 native app。业务实现里网页带的 App.js 会在某些事件触发(比如点击元素跳转页面)时执行 window.jsInterface 这个 object 的某些 function,要求 iOS 监听 function 的触发并作出响应(比如 push 一个 ViewController)。
问题是网页本身没有 window.jsInterface,而且 WKWebView 里只能监听 window.webkit.messageHandlers 的事件,所以还需要注入一个 js Object 来转发这些事件。

具体实现写在了 WKWebView 的一个 subclass 里。


@interface YHWebView ()<WKScriptMessageHandler>

实现 WKScriptMessageHandler 协议,只有这么一个函数:

- (void)userContentController:(WKUserContentController *)userContentController didReceiveScriptMessage:(WKScriptMessage *)message

用此实现来监听 window.webkit.messageHandlers


在此基础上需要使用 WKWebViewConfiguration 来自定义接口(比如 jumpToNative )。

- (id)initWithFrame:(CGRect)frame
{
    self.webViewConfig = [[WKWebViewConfiguration alloc] init];
    self.webViewConfig.userContentController = [[WKUserContentController alloc] init];
    [self.webViewConfig.userContentController addScriptMessageHandler:self name:@"jumpToNative"];
    
    self = [super initWithFrame:frame configuration:self.webViewConfig];

#if DEBUG
// 开启 Safari Debug  
    [self.webViewConfig.preferences setValue:@YES forKey:@"developerExtrasEnabled"];
#endif
    
    return self;
}

这个时候如果 js 调用

window.webkit.messageHandlers.jumpToNative.postMessage()
``` 就可以在 `WKScriptMessageHandler` 的实现里面收到了,比如 js 发送:

window.webkit.messageHandlers.jumpToNative.postMessage({body: dict}); //dict 为一个 JSON String

则代理实现里可以读取:
  • (void)userContentController:(WKUserContentController *)userContentController didReceiveScriptMessage:(WKScriptMessage *)message
    {
    if ([message.name isEqualToString:@"jumpToNative"])
    {
    NSString *body = [message.body objectForKey:@"body"];
    NSData *bodyData = [body dataUsingEncoding:NSUTF8StringEncoding];
    NSError *error;
    NSDictionary *jsonDict = [NSJSONSerialization JSONObjectWithData:bodyData options:0 error:&error];
    // 处理 body 内的 key value
    }
    }

---
现在就差最后一步,注入 js 对象,把所有关于 `window.jsInterface` 的东西都发给 `window.webkit.messageHandlers`。使用 WKUserScript 可以在页面加载前注入这么一个对象:

NSString *jsCode = [NSString stringWithContentsOfFile:[[NSBundle mainBundle] pathForResource: @"YHWebView" ofType: @"js"] encoding:NSUTF8StringEncoding error:NULL];
self.jsInterfaceUserScript = [[WKUserScript alloc] initWithSource:jsCode injectionTime:WKUserScriptInjectionTimeAtDocumentStart forMainFrameOnly:NO];
[self.webViewConfig.userContentController addUserScript:self.jsInterfaceUserScript];

YHWebView.js:
```js
window.jsInterface =
{
    jumpToNative: function(dict)
    {
        window.webkit.messageHandlers.jumpToNative.postMessage({body: dict});
    }
};

Done.

2016.10.31

 • 

最近主要的两个感受就是 困和累。


大约两周前,一个非常好的挚友自己非常忙,所以给我介绍了一份外包。原本的计划是一到两周写完整个 iOS 的部分,结果写的时候遇到了一些常见的问题,比如没有需求文稿,需求方要求按照设计稿做;但设计稿有一些逻辑页面没有做,需要问;设计稿没切图,需要我手动切;一些没有考虑到的图比如 UIImageView 通过网络加载时的 placeholder 没有做,需要再去要;以及设计稿过几天就会做一些改动,不是很大但对于我这样用 xib 写界面习惯加一堆约束的人来说改起来还是有些麻烦(这个其实应该是我自己的问题)。
说这么多其实不是吐槽,这些问题对我的困扰也不大,因为这种事情谁都不能保证完美,自己能理解也有准备。只是说我两周前计划的是花两周写完,然后验收拿钱,然后我继续捣鼓 Unity 去,就这么简单。


然后乱七八糟的事情就出现了,比如学校里一堆课设,提前写完了还不能走。比如没去上课,多了一份 5000 字检讨。
然后上周初的时候,室友看到武汉有 hackathon,想去。当时看到奖项只说“实物奖品”也不说清楚具体,感觉不是很靠谱。而且我上上周刚从上海两场并行 hackathon 回来还没恢复正常,上海那场的奖金还没发给我呢 ... 不过舍友非常想参加,而且都拉好其他人了,那就尽力去参加吧。
周末以 NodeX 的身份去参加。是目前我见到的最烂的 hackathon。全程网络百度都打不开,更不用提需要代理的网站了。人数近三百人,又没有复旦那样的大厅,孵化器写字楼肯定装不下了。但我还是第一次见安置在厂房里的。总之,最烂的 hackathon,这场荣膺。


比赛的时候做了一个软件,叫 Café GO。大致就是 awesome-cn-cafe + MapzenGo,是一个 Unity 软件。就不开源了,因为包含了一部分 Asset Store 的收费内容,license 是 pre-seat 的。


主要还是觉得自己被活生生浪费了很多时间,所以很累。
我非常不喜欢原有计划被打乱的状态,特别是被不负责任的人和事物所打乱。课设写完了不检查又不给走,举办 hackathon 又没有准备好网络,这都是他人不负责任的事情,然而失去时间的是我自己。我有很多计划想要去实现,如果能够远离这些不负责任浪费他人生命的人,我花多少钱都愿意。