分类目录归档:互联网

说说面试官在面试中不可犯的错误以及求职者哪些方面属于重大缺陷

每一个人都会经历求职,入职,工作,在工作中作为面试官面试求职者这些过程。面试和被面试的过程,是一个面试官发现求职者亮点,并判断求职者是否合适,同时,求职者也会评估当前公司的一个双向过程。在这个过程中,无论面试官还是求职者,都有许多要注意要的点,在这些要点之中,本文将结合近期王垠在他的博客中提到的赵海平对他的面试过程,以及赵海平在知乎上的回应,讲讲面试官和求职者各自站在自己的角度,都有哪些不要犯的错误,同时求职者应该如何更好地评估自己。

首先,我认为,作为面试官,在面试的过程中还是最好避免任何的“玩笑”,并且注意用词,否则很容易造成负面的影响。毕竟,我们不知道一个玩笑会被怎样解读。

王垠在他的博客《再谈“P vs NP”问题》中的“解密”部分提到了他曾经去阿里的杭州总部面试,在一次交叉面试中,一位P10面试了他,这位P10“是 Facebook 的第一个华人员工,他的 FB 工牌上写着“The Greatest Computer Scientist””。根据这个信息,尽管王垠没有明确说出名字,我们不难推断出,面试官就是赵海平了。王垠还提到,赵海平问他“你回国之后的一年怎么没去工作?你是富二代吗!”正好,一位自称是赵海平的知乎用户在《如何评价阿里 P10 赵海平对王垠的面试?》的回答中,提到了

好吧,我确实很爱开玩笑,当时开了一个玩笑,简历上有一年的空挡没有工作,这个是个 red flag (警惕性信息),我必须要询问原因,我很友好的开了个玩笑“不需要挣钱的呀,富二代那种?;-) 现在想想的确不合适,希望王垠原谅!

https://www.zhihu.com/question/360622233/answer/944141354

这么来看,在面试过程中,赵海平的确提到了“富二代”这样的话语,他也的确认为这样的话不太合适。尽管赵海平本身可能并没有任何恶意,这样的话语确实可以解读为一种歧视,挑衅,不礼貌。我们也许不清楚他人有什么禁忌,对于同一个词语,表达方式是否有不同的解读,不同的感受,因此,面试官本身在用词用语方面其实要非常注意,或许,注意的程度甚至会让人感觉比清朝的文字狱还要厉害。

其次,我认为,对于求职者来说,更重要的在于如何评估自己在面试官,甚至说在目标公司心目中的地位。这部分,我认为赵海平在他的知乎回答中给出了许多有用的信息。

简历上有一年的空挡没有工作,这个是个 red flag (警惕性信息),我必须要询问原因

我们可以看到,求职者首先要注意,尽量不要让自己的简历有空档,更不要有很长时间的空档,如果空档只是两三个月,一般还不太要紧,如果空档很长时间的话,如1年,那么,公司对你就会有负面的看法了,赵海平作为阿里的P10,已经属于很高级别,他既然特别提到了,就说明一年的空档是一个很不好的因素,即red flag。尽管赵的中文用词是“警惕性信息”,笔者认为,赵想要表达的真实含义其实比“警惕”还是要高一个级别的。

至于博客的讨论是在简历工作讨论之后了,如果不是出于寻求亮点发掘能力,我是不会去看博客的

赵海平在他的知乎回答中提到“如果不是出于寻求亮点发掘能力”,这就非常有意思了,为什么寻求亮点要看博客了呢?这里可能有至少两种解读,一种就是,赵海平在王垠的简历上找不到亮点,所以期望在王垠的博客中找亮点,还有一种就是,赵海平觉得简历上有亮点,但是希望找更多亮点,让王垠级别定更高。我个人猜测,可能真实的解读是第一种解读,即赵海平的确在简历上没找到亮点。

那么,为什么简历上找不到亮点呢。我认为,一个最合理的解释就是,王垠的确在前面的几家公司都定级不够高,职业连贯度不够,导致很难在公司项目和公司职级上对自己进行背书。例如,谷歌的L6,这个级别大家都认可,脸书的E6,亚马逊的L7,如果你在这些公司有这样的级别,那么,公司就给你背书了,而且,通常能升到这个级别的人,本身也要经过各种考核,有着有不错的impact的项目,对于团队也有影响力,在业界看来,公司已经考核过了,那么,自然就默认有L6/E6/L7的人应该很不错。

第三,求职者避免自我感觉太好,特别是不要把公司和自己的位置颠倒了

当时阿里巴巴有一个项目组想请我加入他们。…… 我看他们好像很诚恳,最后终于决定跟他们聊一下。虽然我常常听说阿里的“996”现象和办公室政治,但这种高级别的职位,他们又求贤若渴的样子,心想就算最后不去,了解一下探探底也无妨。

解密(2019 年 12 月) 王垠的《再谈“P vs NP”问题

我发现,王垠在博客中提到是阿里的某个团队请他加入,而不是他主动求职的,在知乎的问题《如何评价阿里 P10 赵海平对王垠的面试?》中,不少回答也认为这是阿里求着王垠加入。然而,根据我个人多年的经验,这里的态度,邀请,其实性质上都是面试邀请,本质上只能表明求职者已经通过了简历筛选,并不意味着面试结果会如何。求职者切忌有一种对方既然求我去面试,说明我就是一个合格的人,入职时水到渠成的感觉。

最后总结,作为面试官,尽量避免开玩笑,用词用语一定要注意,避免触碰到各种禁忌。对于求职者,一定要准确估计自己在公司层面的定位,综合分析自己的优缺点,避免自我感觉太好。对于求职者来说,如果简历上有长时间的空档,并且职业生涯不太稳定,这都是一些很大的硬伤,在面试中难免遭受质疑,被质疑是正常的。即便如此,有硬伤也不意味着不能求职成功,只不过不能奢望很高级别的岗位,同时要做好常常失败的准备。

让Phabricator支持中文的全文搜索

Phabricator是一款优秀的开源项目管理、代码评审和代码管理平台,然而,默认情况下,它对于中文搜索的支持存在问题。

例如,如果你新建了一个标题为“公司年会准备工作”的Maniphest Task,那么,你在Phabricator中用“公司”或者“年会”进行搜索,是搜不到“公司年会准备工作”。这是因为Phabricator默认安装的时候,使用的是MySQL的全文索引,而MySQL默认的分词器是按照空白字符进行分词的,因此,“公司年会准备工作”是作为一个词语进行索引,而不是按照“公司”“年会”“准备”“工作”四个词语进行索引。

解决的办法有不少,例如,我们可以使用ElasticSearch为Phabricator的搜索引擎。不过,其实MySQL的全文索引是支持中文分词的,从MySQL 5.7.6开始,MySQL增加了NGRAM分词器,当你设置ngram_token_size=2时,“公司年会”会被分词为“公司” “司年” “年会”。

Phabricator的MySQL全文索引建立在phabricator_search库的search_documentfield表上,索引名称为corpus,对应的表的列名为corpus。 索引名称为key_corpus,对应的列为corpus和stemmedCorpus。



CREATE TABLE `search_documentfield` (
`phid` varbinary(64) NOT NULL,
`phidType` varchar(4) COLLATE {$COLLATE_TEXT} NOT NULL,
`field` varchar(4) COLLATE {$COLLATE_TEXT} NOT NULL,
`auxPHID` varbinary(64) DEFAULT NULL,
`corpus` longtext CHARACTER SET {$CHARSET_FULLTEXT} COLLATE {$COLLATE_FULLTEXT},
KEY `phid` (`phid`),
FULLTEXT KEY `corpus` (`corpus`)
) ENGINE=MyISAM DEFAULT CHARSET={$CHARSET} COLLATE={$COLLATE_TEXT};

我们看到,DDL语句中,创建全文索引的部分为“FULLTEXT KEY `corpus` (`corpus`)”,这使用的是默认的MySQL分词器,如果我们要使用NGRAM分词器,这个语句应该写成“FULLTEXT KEY `corpus` (`corpus`) WITH PARSER NGRAM”。

我已经有了一个已经安装好的Phabricator实例,我并不想重新安装Phabricator,所以,我的做法是删除掉corpus索引,然后重新建立以NGRAM作为分词器的corpus索引。

SQL语句如下(之前的版本)

USE phabricator_search;
DROP INDEX `corpus` ON `search_documentfield`;
CREATE FULLTEXT INDEX `corpus` ON `search_documentfield`(`corpus`) WITH PARSER NGRAM;

SQL语句如下(最新的版本)

USE phabricator_search;
DROP INDEX `key_corpus` ON `search_documentfield`;
CREATE FULLTEXT INDEX `key_corpus` ON `search_documentfield`(`corpus`,`stemmedCorpus`) WITH PARSER NGRAM;

我设置MySQL的ngram_token_size为2,因为中文中两个字的词非常多。

我的my.cnf中添加了以下配置项

[mysqld]
ngram_token_size=2

2016年12月31日后,NSAllowsArbitraryLoads将被禁用,建议所有iOS App的Web API都升级为HTTPS

苹果的iOS 10正式版本马上就要发布了,而自iOS 10开始,苹果对于网络安全将更加重视,2016年12月31日以后,你将不能用NSAllowsArbitraryLoads来禁止App Transport Security了。

简单说,苹果坚持,你的所有的Web API请求都必须使用https,而如果你需要使用WebView加载外部的网页,考虑到你无法控制外部的网站,苹果引入了新的NSAllowsArbitraryLoadsInWebContent,允许WebView可以加载任意的网页。

The new NSAllowsArbitraryLoadsInWebContent key for your Info.plist file gives you a convenient way to allow arbitrary web page loads to work while retaining ATS protections for the rest of your app.

如果你需要在App中加载任意的网页,那么,你可以在Info.plist中添加NSAllowsArbitraryLoadsInWebContent,这样,你可以加载非安全的http页面,同时保证你的app的其他方面仍然受到App Transport Security的保护。

对于许多公司来说,API团队近期有一项非常重要的工作,也就是,如果你们的Web API仍然是通过明文的http进行调用的,那么,你们需要尽快将API的endpoint升级为https。

如果大家真的来不及升级到https,那怎么办呢。我突然想到,苹果只是禁止了NSAllowsArbitraryLoads,但是我们还是可以NSExceptionDomains,将API对应的域名添加到例外列表中的。

The following listing represents the overall structure of the NSAppTransportSecurity dictionary, showing all possible keys, all of which are optional. Keep this structure in mind as you configure each element of the dictionary, as needed, for your app:
以下代码是NSAppTransportSecurity字典的结构模型。该模型列举了所有可能的键值对,这些键值对都是非必须的。您可以根据这个结构中所示的键值对的信息来编辑Info.plist中的NSAppTransportSecurity字典。

NSAppTransportSecurity : Dictionary {
    NSAllowsArbitraryLoads : Boolean
    NSAllowsArbitraryLoadsInMedia : Boolean
    NSAllowsArbitraryLoadsInWebContent : Boolean
    NSAllowsLocalNetworking : Boolean
    NSExceptionDomains : Dictionary {
         : Dictionary {
            NSIncludesSubdomains : Boolean
            NSExceptionAllowsInsecureHTTPLoads : Boolean
            NSExceptionMinimumTLSVersion : String
            NSExceptionRequiresForwardSecrecy : Boolean   // Default value is YES
            NSRequiresCertificateTransparency : Boolean
        }
    }
}

应用退出登录,数据丢失,原来是iOS系统的bug,NSUserDefaults内容随机消失

最近,我突然发现用着用着很多应用就要我重新登录了,我自己的app在调试的时候,也经常发现原来保存的登录状态也消失了。经过调查,我发现,原因在于保存在NSUserDefaults中的登录信息没了,而保存在keychain和文件中的信息还有。

经过查找,我发现了如下信息,原来是iOS 9.3的一个bug,应用用于保存信息的NSUserDefaults的内容会随机消失。
https://forums.developer.apple.com/thread/44264

iOS 9.3.1 NSUserDefaults Wiped Bug?

elementarteilchen
May 6, 2016 5:11 AM
(in response to staminajim_sg)
Yes. It seems that the iOS just “forgets” to load the data sometimes. If this happens in my own App while debugging, I can easily kill the App and prevent that it will change the userdefaults, and the next time I lanuch it again, the settings are usually loaded just fine. The big problem is that when you are not debugging your own Apps, you do not have a chance to kill an App before it save any settings, and when an App does this, the old settings are overwritten and lost forever.
(给staminajim_sg的回复)
是的。这看起来是iOS似乎有时候忘记及时加载数据了。我在调试的时候常常发现这个现象发生,在这种情况下,我可以用杀掉app的方式防止我的app执行对NSUserDefaults的修改操作,这样子,下一次我再启动app,原来的设置都还在而且也会正确加载。最大的问题是,如果你不是在调试你的App,你就没有办法像我一样杀死App,这就导致App会执行写操作,原有的设置就会被覆盖掉了。

Rygen
May 27, 2016 6:10 AM
(in response to elementarteilchen)
Also facing the same issue since 9.3, and now it persists on 9.3.2.
I’ve had this issue happen with a first party app as well – Weather. It lost all the saved cities, about one month ago.
Whatsapp is by far the worst in terms of data loss. You can’t avoid some of it even if you’re obsessively backing it up to iCloud every single time you use the app.
I know of one person which is not using the iPhone as a development device and is also having the same problem, so this NSUserDefaults issue is probably not related to that.
Which iPhone models are you seeing the issue on? Mine is a 5S.

I’ve submitted a bug report to Apple.
(给elementarteilchen的回复)
我从iOS 9.3版本开始就遇到这样的问题,现在已经升级到9.3.2了,问题依旧存在。
我最开始遇到这个问题,是一个月以前,在我的天气应用上,我的天气应用中保存的城市列表都消失了。
Whatsapp则是受到影响最大的,即便你经常通过iClound备份,你的数据也会丢失。
我知道一个案例,一个用户并不是将他的/她的iPhone作为开发设备,而他/她也遇到了类似的现象,这表明NSUserDefaults问题并不是因为iPhone被设置为开发设备的缘故。
大家在那些iPhone型号上遇到这个问题了?我的是iPhone 5S

ChaoticBox
Jun 19, 2016 1:06 AM
(in response to NeilFau)
I’ve been seeing this as well but figured out a workaround for my own apps: If my keys aren’t found, call resetStandardUserDefaults and try again. It shouldn’t hurt to repeat that a few times before bailing and assuming it’s a first-run, but so far it has always worked after the first reset.
(给NeilFau的回复)
我也遇到了相同的问题,不过我找到了一个变通的方法。如果我的应用在启动的时候发现某个键值对应的值不存在,那么我会首先调用resetStandardUserDefaults,然后接着再试着获取该值。重复几次resetStandardUserDefaults的操作,如果这样仍然无法取到相应的值,那么可以认定这是首次运行。这样的操作并不繁琐复杂,但是截至到目前位置,我发现这个方案是有效的。

alexfit
Jul 6, 2016 12:30 AM
(in response to NeilFau)
This has been happening to me for the last few months. By FAR, the most distressing bug I’ve encountered on iOS as a user. Can’t use What’s App, as I’m constantly losing chat history. Have to log in again to Evernote, Instagram. Settings and tips for many apps reset and I’m sent back to onboarding screens.

For the first time, I’ve lost all trust in my iPhone. A thought of getting a “reliable” Android phone crossed my mind…

I hope this is getting fixed, soon.
(给NeilFau的回复)
这个问题在最近几个月一直困扰着我。到目前为止,这是我见过的最令人烦恼的一个iOS的bug。我不能用Whatsapp,因为我经常会丢失聊天记录。我不得不重复登录Evernote,Instagram。许多应用的设置和提示都被重置了,这导致我每次启动都见到欢迎界面。

这是我首次丧失了对iPhone的信任,我已经开始考虑买一个可靠的安卓手机了。

希望这个bug能够被尽快修复。

在OSX 10.11 El Captain上安装pybonjour时遇到dlopen(libSystem.B.dylib, 6): image not found错误

上一篇讲到,我需要安装PonyDebugger,而安装PonyDebugger需要安装pybonjour,然而,安装pybonjour时,又遇到了错误,错误信息如下,
Traceback (most recent call last):
File “setup.py”, line 32, in
import pybonjour
File “/Users/huangshaojun/Downloads/Eichhoernchen-pybonjour-c63b48c/pybonjour.py”, line 109, in
_libdnssd = ctypes.cdll.LoadLibrary(_libdnssd)
File “/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/ctypes/__init__.py”, line 443, in LoadLibrary
return self._dlltype(name)
File “/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/ctypes/__init__.py”, line 365, in __init__
self._handle = _dlopen(self._name, mode)
OSError: dlopen(libSystem.B.dylib, 6): image not found

我到github上也找到了对应的Issue 192 https://github.com/square/PonyDebugger/issues/192
Issue提到的解决方法是

well, okay i had to do a brew install python

即,不要用OSX内置的python,而用brew新安装一个python。

我并不想再新安装一个新的python,我还是希望用OSX内置的python,为此,我根据
http://stackoverflow.com/questions/32905322/oserror-dlopenlibsystem-dylib-6-image-not-found
的提示,修改了pybonjour.py

if sys.platform == 'darwin':
        _libdnssd = 'libSystem.B.dylib'
    else:

改为

if sys.platform == 'darwin':
        _libdnssd = '/usr/lib/libSystem.B.dylib'
    else:

这样用OSX内置的python就可以正确安装pybonjour了。

PonyDebugger安装错误:Could not find a version that satisfies the requirement pybonjour==1.1.1

之前一直用Reveal,不过Reveal只能查看View Hierarchy,而我听说PonyDebugger不仅仅可以查看View Hierarchy,还能debug network traffic和view core data,所以决定也集成PonyDebugger。

到PonyDebugger的主页(https://github.com/square/PonyDebugger)一看,发现README中有一个Quick Start,这个Quick Start提到首先要运行如下代码安装ponyd

curl -s https://cloud.github.com/downloads/square/PonyDebugger/bootstrap-ponyd.py | \
  python - --ponyd-symlink=/usr/local/bin/ponyd ~/Library/PonyDebugger

我运行了以后,遇到如下错误

Collecting pybonjour==1.1.1 (from ponyd)
  Could not find a version that satisfies the requirement pybonjour==1.1.1 (from ponyd) (from versions: )
No matching distribution found for pybonjour==1.1.1 (from ponyd)
Traceback (most recent call last):
  File "", line 2462, in 
  File "", line 946, in main
  File "", line 1794, in after_install
  File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/subprocess.py", line 540, in check_call
    raise CalledProcessError(retcode, cmd)

随后,我用关键字

Could not find a version that satisfies the requirement pybonjour==1.1.1 

进行搜索,发现了Issue #186 https://github.com/square/PonyDebugger/pull/186,此issue表明pybonjour的问题已经于2016年2月27日解决了。可是,我为什么仍然遇到了这个问题呢。

接下来,Issue 185解决了我的疑惑 https://github.com/square/PonyDebugger/issues/185,其中 justinseanmartin 在3月15日提到

I was able to clone and then install using python setup.py install. It isn't as convenient as the command from the readme, will look into getting the script fixed up as well.

Issue 188 https://github.com/square/PonyDebugger/issues/188 中,justinseanmartin也提到了,

Dupe of #100. You should be unblocked by:

git clone git@github.com:square/PonyDebugger.git
cd PonyDebugger
python setup.py install

Please confirm this works for you. I've logged #189 to track fixing the install script and/or instructions.

这说明,pybonjour问题的解决方案,还没有应用到https://cloud.github.com/downloads/square/PonyDebugger/bootstrap-ponyd.py,所以,用Quick Start的方式安装仍然有问题,我们目前还是需要把PonyDebugger的git库clone到本地,再进行安装。

iOS应用的糟糕例子:口碑外卖的用户体验越来越糟,这是把用户往饿了么赶

最近几年,O2O,特别是外卖,已经形成了白热化的砸钱补贴营销的战场,外卖市场上,饿了么,美团,口碑和百度四家基本上成为外卖的主流平台了,外卖配送方面,百度自己做了配送,美团也有自己的专送,饿了么做了蜂鸟配送,此外,还有一个达达,也是做了配送,同时达达也做了一个叫做派乐趣的外卖平台。

大战已经进行了快两年了,百度外卖,饿了么,美团和口碑这四家,现在也变成了三家,即口碑和饿了么合并,口碑外卖事实上被阿里巴巴抛弃了。

为什么说口碑事实上已经被抛弃了呢。

打开了最新更新的口碑外卖客户端,第一个感觉就是,怎么全都变成H5页面了?口碑外卖底部的tab bar,只有“外卖”、“订单”和“我的”三个按钮,我在这三个tab之间切换的时候,明显感觉到tab bar会闪一下,然后整个app中间有一个浏览器在加载某个页面。这样的感受让人感到非常糟糕。

到口碑外卖的某个店里一看,发现这个店在口碑只有三个宝贝在卖,而在饿了么里,却有几十个,明显感觉到商家要放弃口碑的样子。

再看看近期的新闻
口碑APP订餐出现平台即将关闭提示 官方回应:商家理解有误 2016-05-03 http://www.admin5.com/article/20160503/661207.shtml
饿了么开送口碑外卖:被收购进入倒计时 2016-04-21 http://www.mnw.cn/keji/mi/1159677.html

在5月3日的新闻中,饿了么方面回应称,“商户的理解不太正确。口碑外卖的业务目前都由饿了么提供,只是如此而已。”

然而,从口碑外卖的最新的app的交互体验,以及口碑外卖在苹果的App Store的差评来看,其实饿了么和阿里巴巴都已经把口碑当成了一个弃儿,就让口碑自生自灭吧。

既然口碑外卖已经是一个弃儿,一个不值得投入资源的产品,那么,自然产品、研发、运营和测试等团队就应该从口碑撤离了。这也是为什么口碑外卖更新以后,居然成了完全的H5应用的原因。

口碑当年被阿里巴巴收购后,已经死了一次,后来做外卖,业界以为口碑又会活过来,没想到,其实口碑从来没有活过,只不过被阿里打了强心剂,回光返照一下,作了一回饿了么的陪练而已,而阿里巴巴仅仅是做了个口碑和饿了么打了一架,然后趁机投资饿了么而已。

阿里做口碑,不是为了把口碑做好,而是把口碑当做为了投资饿了么的一个资本布局的一个小棋子罢了。

CDN导致的App内图片有时候无法显示

最近,我发现了一个之前都没有发生过的问题。时不时就发现某个应该显示某张图片的地方,显示着placeholder image。难道我的代码哪里没写好吗?

调试后发现,应该是CDN的问题。

我在下载图片的代码处添加了一个条件断点,一旦error对象不为nil,就触发断点,最后发现,error对象的code都是404。

随后,我将image url复制出来,用curl -vvv命令进行下载。我发现,一般来说,第一次curl命令会输出404错误,往往第二次或者多次以后的curl,才会下载到正确的image数据。

通过观察curl返回的header数据,我发现了“Power-by-ChinaCache”字样,这说明,我司的CDN用的是ChinaCache的服务。

自此,真相大白了,首次下载的时候,CDN不知为何,直接给了404错误,而多次重试后,CDN更新了数据,就返回了200代码和image数据。

解决微信登录 “Scope 参数错误或没有Scope 权限” 问题

目前,微信,微博登录已经成为各个手机应用不可或缺的登录方式之一了,如果谁的app还没有添加这两种登录方式,那么您就落后于市场主流了。

然而,微信登录功能增加后,还是要经常维护的,比如每年需要进行公众号的年检,如果您没有及时年检,那么,微信登录就会出现很多问题。

笔者近期在调试app的时候,就发现,点击app的微信登录按钮,跳转到微信后,微信提示“Scope 参数错误或没有Scope 权限”,这让我感到莫名其妙啊。怎么可能scope参数错误呢,微信的Api中,用于登录的是SendAuthReq这个class,我很确定我设置了SendAuthReq的scope属性,并且是正确的。这么看来,真实的原因就是没有scope权限了。

多试验了几次,发现,有几次不会出现这个“Scope 参数错误或没有Scope 权限”错误,微信也会正确跳转回app,并且也可以获取code,然而,这时候调用微信的sns/oauth2/access_token API就会出现48001, api unauthorized错误。

最开始,我通过bing和google搜索了以上错误信息,结果,这个错误的根本原因多重多样。

  1. 2014年微信增加了“网页授权”,如果不开启这个选项,那么就会出现本错误。http://www.w-nn.cn/jiaocheng/423.html
  2. 还有人发现,scope参数在url中的位置不一样也会导致scope参数错误,http://my.oschina.net/u/202293/blog/387513。不过,笔者这里是iOS app用微信登录,所以可以排除这种可能
  3. 还有一些论坛中开发者求助,然后过了一会,求助的人自问自答道:“解决”。http://bbs.youzan.com/forum.php?mod=viewthread&tid=1113。 笔者看到这里感到,既然解决了,为什么不把原因和解决方案共享出来呢。
  4. mob.com的ShareSDK论坛也有人求助:http://bbs.mob.com/thread-20961-1-1.html,这个最后没有提到怎么解决的。
  5. 此外,还发现了http://tieba.baidu.com/p/4081677132,其中提到 乐动力 微信登录异常,原因就是微信公众号年审还没通过。而这里面所说的登录异常,就是“Scope 参数错误或没有Scope 权限”

我这次遇到的问题,根源就在于公众号没年审,所以微信登录被停掉了。我找运营部门的同事进行以下公众号年审就行了。

以前都及时年审了,所以没遇到这个问题,近年来,微信公众号申请的越来越多,这下子每个人要负责很多个微信号,这导致很容易就会有某个微信号维护不及时。

在UITabBar上识别长按(long press)操作

大家或许都知道,现在的智能手机都支持各种手势操作,如长按,单手指或者多手指滑动或点击,随着技术的发展,屏幕还可以识别按压的力度。

在iOS上,我们可以通过Tap/Pan/Pinch/Swipe/Rotate/LongPress Gesture Recognizer来识别各种手势,所以,在UITabBar上识别Long Press(长按)手势其实并不困难,只需要在tab bar上添加一个Long Press Gesture Recognizer就好了。

然而,以上的方案存在一个小小的瑕疵。iOS默认的tab bar,在你点击某一个tab bar button后,就会选中该button对应的item,而如果是tab bar controller的话,就会切换到对应的view controller。实际上,UITabBar在检测到用户按下以后,而不是按下然后拿起手指之后,就选中了对应的bar item,所以,tab bar在识别long press之前,就已经认为用户进行了一次tap。

实际上,更好的方案是,识别long press的话,就不要识别tap了。这就要求,我们需要修改tab bar识别tap的逻辑,即,用户必须touch down(按下)然后touch up(手指离开屏幕),才算一次,而非tab bar默认的行为,touch down就开始处理tap事件。

我采取的措施是,扩展UITabBar,在Tab Bar的view里添加一个overlay view,即这个view确保在Tab Bar的其他subviews的上面,由这个overlay view去识别Tap Gesture,当识别到Tap操作后,根据点击的坐标识别用户点击了哪一个tab bar item。

_overlayView = [[UIView alloc] init];
_overlayView.backgroundColor = [UIColor clearColor];
[self addSubview:_overlayView];
self.tapGestureRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(tapGesture:)];
[_overlayView addGestureRecognizer:self.overlayGestureRecognizer];
- (void)tapGesture:(UIPanGestureRecognizer*)gestureRecognizer{
    CGPoint point = [gestureRecognizer locationInView:self];
    switch (gestureRecognizer.state) {
        case UIGestureRecognizerStateEnded:
        {
            NSInteger touchUpItemIndex = [self barButtonItemIndexAtPoint:point];
            if (touchUpItemIndex != NSNotFound) {
                //touch up inside event
                UITabBarItem *item = [self.items objectAtIndex:touchUpItemIndex];
                //接下来,将selectedItem设置为item,并调用享用的delegate方法。
            }
        }
        break;
    }
}

 
以上代码的重点,就在于barButtonItemIndexAtPoint的实现。一个比较简单的实现就是,

CGFloat itemWidth = self.view.frame.size.width / self.items.count;
NSInteger index = point.x / itemWidth;