2019年10-11月

最近两个月调整了很多事的方向。

有点焦虑,首先是Google封了我的Adsense账号,说我有无效的点击流量,之前的收入也不会支付给我。之后我给Google发了一封申诉邮件,然后第二天他们给我回复说不会恢复我的账号。简直莫名其妙,OK,fine。

之后就是每天解决各种不同的问题。幸运的是基本上都顺利解决掉了。再有可能是咖啡喝多了。

从iOS转到做Android,感觉是一个不错的变化,Kotlin写的也可以说很愉快。于是没事瞎折腾的我又开始了新项目的开发。这个新项目其实已经筹划了很久,近期决定动手去实现它,把自己的爱好做成一个App也是一件很有意义的事。Android的用户群体比较大,打算做完Android之后再开发iOS版。

每天阅读上一个App用户发来的邮件,回复问题,修改Bug和更新功能,其余大部分的时间都投入在新项目中,一个人做设计、开发后台、Api、Android端,翻译英文资料和整理素材。

之前看过一篇文章觉得很喜欢,大概是说人越向上,越容易受到幽灵的影响。它天天引导我们,催促我们,告诉我们什么是要做的事。

无力改变现状就先做好眼前的事。

开始尽量控制对咖啡的依赖,尽快让自己恢复到最好的状态。每一天都是自己制造的。

心如止水,正向积累

2019年的8月和9月初这几天几乎没做什么事情,一直在认真做公司的工作和Side Project的同时,也开始重新思考价值和金钱。

重新看之前的代码觉得晦涩难懂,这可能是件好事,在重构的过程中逐渐掌握更强的架构能力,同时思考更简单的解决方法,尽可能减少维护的精力。

近几个月的剁手清单:

  • Sheaffer Targa古董钢笔,买的NOS,被嵌入式14k笔尖种草,虽然是几十年前的笔,不过写感还是很棒。
  • Airpods二代线充版。搭配iPhone和Macbook用确实很方便,不过音质过于一般。近期内应该不会再买Apple的东西。
  • 鲶鱼家的彩墨。买了一瓶红色和一瓶绿色,颜色很好看。挑喜欢的名字买的:鳗鱼响尾蛇,短吻鳄绿。用来做标注用。
  • 各种格子衬衫


说说近况

最近得了一种伤心的病,任何事都好像可以影响我。

仍然是每天努力学习,努力工作赚钱,偶尔的倦怠和无力。

打算要做的:

1.继续维护手上几个Android和iOS App。

2.继续维护网站

3.把手上的项目完成以后学习SwiftUI

4.继续坚持翻译英语文章

最近喜欢听钢琴曲和大提琴曲,听《克罗地亚狂想曲》的时候觉得振奋,听《月半小夜曲》的时候又感觉伤感。在各种情绪中来回切换。

种草铁三角的黑胶唱片机,想边用它听歌边coding。

开发鲜橙油耗的一些经历

最近开了新项目觉得异常的忙,每天都在设计和coding中切换。

鲜橙油耗是我两年前一个旧项目,当时做了一款简单的查询油耗的App,后来再也没有维护过,于是把它下架了。

最近觉得自己有记录油耗的需求,决定捡起来把它好好重写一下。开始了设计之后把第一版做了出来,经过思考又发现应该把重要的功能放在第一个页面,然后又开始了第二次修改。把语法更新到swift4.2,最后设计了新的App图标,重新上了线。

现在的版本也是很多不完善的地方,正在不断的改进和思考中。

晚上的时候和小伙伴语音沟通一些想法和需求,然后第二天实现出来。作为一个半独立开发者,用业余时间做自己的东西,想做一个精致的App真的是一件很耗精力的事情,事情越做越多,但是看见commit记录还是很有成就感的。

以后会一直维护这个App,希望越做越好。2019年fighting。

iOS原生地图开发的一些心得

最近在开发鲜橙油耗iOS端,APP中需要获取附近的加油站并且在地图上显示大头钉。

如何获取我附近的加油站?

这里用到MapKit里的一个小部件: MKLocalSearch MKLocalSearch 允许开发者得到一个地理区域内附近的兴趣点。有了这个部件我们可以轻松获取到想要的加油站数据,代码如下:

let search = MKLocalSearch(request: request)
search.start { (response, error) in
guard let items = response?.mapItems else { return }
for item in items {
let annotation: MKPointAnnotation = MKPointAnnotation()
annotation.coordinate = item.placemark.coordinate
annotation.title = item.name
annotation.subtitle = item.phoneNumber ?? ""
self.mapView.addAnnotation(annotation)
}
}

在这段代码中,我获取到了附近的加油站数据,并且在mapView中显示出了大头钉。

如何自定义大头钉图片?

在MapViewController里继承MKMapViewDelegate,并且为mapView设置代理:

class MapViewController: UIViewController,UITableViewDelegate,UITableViewDataSource,CLLocationManagerDelegate,MKMapViewDelegate {
    @IBOutlet weak var mapView: MKMapView! {
        didSet {
            mapView.delegate = self
        }
    }
}

然后实现 func mapView(_ mapView: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView? 这个代理方法:

func mapView(_ mapView: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView? {
    let identifier = "item"
    var annotationView = mapView.dequeueReusableAnnotationView(withIdentifier: identifier)
    if (annotationView == nil) {
        annotationView = MKAnnotationView(annotation: annotation, reuseIdentifier: identifier)
    }
    annotationView?.annotation = annotation
    if (annotation is MKUserLocation) {
//这里如果是用户当前位置,设置不同的图片。 annotationView?.image = UIImage(named: "mylocation") } else { annotationView?.image = UIImage(named: "gasstation") } annotationView?.centerOffset = CGPoint(x: 0, y: 0) annotationView?.canShowCallout = true annotationView?.calloutOffset = CGPoint(x: 10, y: 0) annotationView?.isDraggable = true return annotationView }

最终效果如下:

iOS获取附近加油站

清单生活

每天在思考和开发side project的时候都会发现要做的事情越做越多。最后的解决方法就是全部列出来,然后挑几件觉得比较重要的做,测试效果。

需要自己做UI设计,想学Sketch,还有代码需要写,数据需要分析,运营思路需要自己想,产品内容需要自己整理和发布。基本上两台MacBook,一台躺着写app,一台坐着写网站。

囤了一批咖啡豆过年,用广告费购买了一些想看的书。

封面很好看,最近比较浮躁,应该多看看安静的文字。

有时间需要整理下最近这段时间要修复的bug和需要升级的功能。

这个月的状态关键词是自省。

开始相信一切事物都有趋势性,重要的是坚持下去。

使用Amaze UI Tree实现无限级分类

Amaze UI Tree是Amaze UI的一款jQuery树形插件最近我在做项目的时候使用了Amaze UI框架,做树形组织架构的时候找到了这款插件,由于组织架构是读取的钉钉部门列表,层级关系并不确定,研究了一下如何用这款插件来实现无限级分类。

简单说下实现方法和思路:

1.在 Amaze UI 样式之后引入 Tree 样式,然后在 jQuery 之后引入 Tree 插件。树形模板如下(这个是demo提供的模板,只修改了id为departmentTree):

<ul class="am-tree am-text-left" id="departmentTree">
    <li class="am-tree-branch am-hide" data-template="treebranch">
        <div class="am-tree-branch-header">
          <button class="am-tree-branch-name">
            <span class="am-tree-icon am-tree-icon-folder"></span>
            <span class="am-tree-label"></span>
          </button>
        </div>
        <ul class="am-tree-branch-children"></ul>
          <div class="am-tree-loader">
            <span class="am-icon-spin am-icon-spinner"></span>
          </div>
      </li>
      <li class="am-tree-item am-hide" data-template="treeitem">
          <button class="am-tree-item-name">
            <span class="am-tree-icon am-tree-icon-item"></span>
            <span class="am-tree-label"></span>
          </button>
      </li>
</ul>
2.初始化Tree:
  $('#departmentTree').tree({
    dataSource: function(options, callback) {
      // 异步加载
      var url = '/admin/ding/departments/' + (options.id ? options.id : '');
      $.get(url,function(json) {
        var data = jQuery.parseJSON(json);
        callback({data: options.products || data});
      });
    },
    multiSelect: false,
    cacheItems: true,
    folderSelect: false
  });

实现思路如下:

此处url是调用了我后台的一个获取部门的API,路由如下:

Route::get('admin/dingding/departments/{pid?}','DingController@getDepartment')->name('ding.departments');

可见路由中有一个可选参数pid,在对应的后台方法中,如果获取到pid这个参数,表示请求选中部门的所有子部门,否则返回所有顶级部门。

var url = '/admin/ding/departments/' + (options.id ? options.id : '');

这里options.id的id是我后台返回的部门id,如果获取到options.id说明展开了某一部门,要请求获取子部门,否则不传参数,获取全部顶级部门。

一些坑:

Amaze UI Tree中有一个type属性用来判断是否有子节点,folder代表含有子节点,item代表该层级为最后一层。
在API中需要返回这个type属性。我在后台中定义了一个getSubDepartment方法用来查找是否含有子部门,然后返回相应的type。
$d['type'] = count($this->getSubDepartment($departments,$d['id'])) > 0 ? 'folder' : 'item';

最终效果如下:

在Laravel中引入钉钉SDK

最近在用Laravel开发钉钉企业内部应用,需要调用钉钉的SDK。不得不说,钉钉开发文档写的真是感人,开发的时候那是相当刺激。在使用SDK的时候遇到不少坑,钉钉的文档写的不是很详细,记录下在Laravel中集成DingTalk SDK的方法:

  1. 首先在http://open-doc.dingtalk.com/microapp/serverapi2/vzzrkv中下载PHP版本SDK。解压后文件目录如图
    这里我只用到dingtalk中的文件,删除aliyun、QimenCloud目录,保留top目录Autoloader.php和TopSdk.php文件。
  2. 在composer.json中:
        "autoload": {
            "classmap": [
                "database"
            ],
            "files":[
                "app/Packages/taobao/TopSdk.php"
            ],
            "psr-4": {
                "App\\": "app/"
            }
    
        },
    

    然后执行composer dump-autoload

  3. 执行完毕后,在Controller中就可以直接使用DingTalk SDK了。测试结果如下(注意要加‘ \ ’):
            $c = new \DingTalkClient(\DingTalkConstant::$CALL_TYPE_OAPI, \DingTalkConstant::$METHOD_POST , \DingTalkConstant::$FORMAT_JSON);
            var_dump($c);
    

    打印出结果如下:

    object(DingTalkClient)#276 (9) { ["gatewayUrl"]=> string(34) "http://eco.taobao.com/router/rest" ["format"]=> string(4) "json" ["connectTimeout"]=> NULL ["readTimeout"]=> NULL ["apiCallType"]=> string(4) "oapi" ["httpMethod"]=> string(4) "POST" ["checkRequest"]=> bool(true) ["apiVersion":protected]=> string(3) "2.0" ["sdkVersion":protected]=> string(25) "dingtalk-sdk-php-20161214" }
    

遇到的坑:

  1. 在调用DingTalkClient的execute方法获取token的时候,报错如下:
    Missing argument 7 for DingTalkClient::_executeOapi(), called in /Web/proj/app/Packages/taobao/dingtalk/DingTalkClient.php on line 328 and defined
    

    查看DingTalkClient.php文件,328行

        public function execute($request, $session = null,$bestUrl = null){
            if(DingTalkConstant::$CALL_TYPE_OAPI == $this->apiCallType){
                return $this->_executeOapi($request, $session, $bestUrl, null, null, null); 
            }else{
                return $this->_execute($request, $session, $bestUrl);
            }
        }
    

    查看_executeOapi方法的代码:

    private function _executeOapi($request, $session = null,$bestUrl = null,$accessKey, $accessSecret, $suiteTicket, $corpId)
    

    此处发现_executeOapi方法需要传7个参数,而在execute中只传了6个参数。修改后的代码如下:

        public function execute($request, $session = null,$bestUrl = null){
            if(DingTalkConstant::$CALL_TYPE_OAPI == $this->apiCallType){
                return $this->_executeOapi($request, $session, $bestUrl, null ,null, null, null);
            }else{
                return $this->_execute($request, $session, $bestUrl);
            }
        }
    

一段过渡期,尽力过好生活

在冬天的夹缝里,似乎得了冬季无力症一样懒洋洋的。

开始了一个新项目,从粗糙上线,到自己在纸上设计,在Storyboard上画页面,不断完善和构想,不得不说过程是一件很有意思的事情,是只有做自己的东西才会有的一种感觉。

一些提升幸福感的物品清单:

  1. 胡桃木手机支架。买了两个,一个用来放手机,一个放Kindle,可以边看喜欢的书边做笔记。
  2. 胡桃木的理线器和魔术理线带,把杂乱的数据线都整理了一下,感觉世界干净了。
  3. 胡桃木的咖啡搅拌棒和黄油刀。
  4. J.Herbin钢笔清洗液。定期清洗所有的钢笔。
  5. 红酒真空塞。可以抽干瓶里的空气,喝不完的红酒可以多存储几天。
  6. 木质调香水。感觉适合自己现在的性格,比较冷清。
  7. Longines名匠腕表,喜欢机械在运行时的那种存在感。