WJ's Den


  • 首页

  • 分类

  • 归档

  • 标签

  • 搜索
close

【转载】Ruby China的RubyGems镜像上线

发表于 2016-11-01   |   分类于 Ruby   |  

公告

huacnlee for Ruby China · 发布于 2016年3月09日 · 最后由 huopo125 回复于 2016年5月12日

几年前,由我起头,我们搭建了 ruby.taobao.org 为国内开发者解决 Gem 安装的问题,现在应该国内绝大多数,甚至所有(国内服务器,国内网络)的 Ruby 开发者企业,应该都在用它。

但最近越来越发现之前 ruby.taobao.org 很难同步了,原因有很多,之前的实现方式过于复杂,服务器在国内,同步困难,阿里的网络安全要求维护服务器得是公司员工…. 各种限制导致我们在维护的时候困难重重,尤其是当 @fsword @qhwa 离职以后,根本无法再继续维护了。

为了有一个可持续发展未来,我们考虑由 Ruby China 来负责这个事情,这样可以像现在 Ruby China 社区,RubyConf China 一样,由社区的很多参与者来共同维护。

这件事情我们已经考虑了一年了,之前一直没有找到一个好的方式来解决,以及一些其他因素,比如资金的问题。

这周,我们终于找到了解决方案,也找到了赞助商:腾讯云

整个 gems.ruby-china.org 的架构:

2016-05-18 Updated: Gems 存储放到了 UpYun 上面,通过 UpYun 的 CDN 来解决,同时配合 UpYun 的镜像存储功能,减少回源到国外的次数。

过程: https://ruby-china.org/topics/29978



新的方案的特点

  • 实时的,不再有同步耗时的问题;

  • 全球 400+ CDN 节点(据腾讯官方所说 ~~)为 Gem 下载加速;

  • 更加简单有效的架构,稳定性更高;

  • 背后有两台国外服务器,确保稳定性,确保 CDN 汇源能获取到数据;

原文链接

FFmpeg的安装与使用

发表于 2016-10-31   |   分类于 Tool   |  

简介

FFmpeg是一个自由软件,可以运行音频和视频多种格式的录影、转换、流功能,包含了libavcodec——这是一个用于多个项目中音频和视频的解码器库,以及libavformat——一个音频与视频格式转换库。
“FFmpeg”这个单词中的“FF”指的是“Fast Forward”。有些新手写信给“FFmpeg”的项目负责人,询问FF是不是代表“Fast Free”或者“Fast Fourier”等意思,“FFmpeg”的项目负责人回信说:“Just for the record, the original meaning of “FF” in FFmpeg is “Fast Forward”…”
这个项目最初是由Fabrice Bellard发起的,而现在是由Michael Niedermayer在进行维护。许多FFmpeg的开发者同时也是MPlayer项目的成员,FFmpeg在MPlayer项目中是被设计为服务器版本进行开发。
2011年3月13日,FFmpeg部分开发人士决定另组Libav,同时制定了一套关于项目继续发展和维护的规则。(From FFmpeg Wiki)

安装

brew install ffmpeg

由于license的原因,libvo-aacenc被默认安装,如果想要安装libfaac或者libfdk-aac可以通过以下命令:

brew reinstall ffmpeg --with-faac

brew reinstall ffmpeg --with-fdk-aac


项目组成

libavformat:用于各种音视频封装格式的生成和解析,包括获取解码所需信息以生成解码上下文结构和读取音视频帧等功能

libavcodec:用于各种类型声音/图像编解码

libavutil:包含一些公共的工具函数

libswscale:用于视频场景比例缩放、色彩映射转换

libpostproc:用于后期效果处理

ffmpeg:该项目提供的一个工具,可用于格式转换、解码或电视卡即时编码等

ffsever:一个 HTTP 多媒体即时广播串流服务器

ffplay:是一个简单的播放器,使用ffmpeg 库解析和解码,通过SDL显示

命令集

ffmpeg 命令集举例

1.获取视频的信息

ffmpeg -i video.avi

2.将图片序列合成视频

ffmpeg -f image2 -i image%d.jpg video.mpg

上面的命令会把当前目录下的图片(名字如:image1.jpg. image2.jpg. 等…)合并成video.mpg

3.将视频分解成图片序列

ffmpeg -i video.mpg image%d.jpg

上面的命令会生成image1.jpg. image2.jpg. …
支持的图片格式有:PGM. PPM. PAM. PGMYUV. JPEG. GIF. PNG. TIFF. SGI

4.为视频重新编码以适合在iPod/iPhone上播放

ffmpeg -i source_video.avi input -acodec aac -ab 128kb -vcodec mpeg4 -b 1200kb -mbd 2 -flags +4mv+trell -aic 2 -cmp 2 -subcmp 2 -s 320x180 -title X final_video.mp4

说明:

  • 源视频:source_video.avi
  • 音频编码:aac
  • 音频位率:128kb/s
  • 视频编码:mpeg4
  • 视频位率:1200kb/s
  • 视频尺寸:320 X 180
  • 生成的视频:final_video.mp4

5.为视频重新编码以适合在PSP上播放

ffmpeg -i source_video.avi -b 300 -s 320x240 -vcodec xvid -ab 32 -ar 24000 -acodec aac final_video.mp4

说明:

  • 源视频:source_video.avi
  • 音频编码:aac
  • 音频位率:32kb/s
  • 视频编码:xvid
  • 视频位率:1200kb/s
  • 视频尺寸:320 X 180
  • 生成的视频:final_video.mp4

6.从视频抽出声音.并存为Mp3

ffmpeg -i source_video.avi -vn -ar 44100 -ac 2 -ab 192 -f mp3 sound.mp3

说明:

  • 源视频:source_video.avi
  • 音频位率:192kb/s
  • 输出格式:mp3
  • 生成的声音:sound.mp3

7.将wav文件转成Mp3

ffmpeg -i son_origine.avi -vn -ar 44100 -ac 2 -ab 192 -f mp3 son_final.mp3

8.将.avi视频转成.mpg

ffmpeg -i video_origine.avi video_finale.mpg

9.将.mpg转成.avi

ffmpeg -i video_origine.mpg video_finale.avi

10.将.avi转成gif动画(未压缩)

ffmpeg -i video_origine.avi gif_anime.gif

11.合成视频和音频

ffmpeg -i son.wav -i video_origine.avi video_finale.mpg

12.将.avi转成.flv

ffmpeg -i video_origine.avi -ab 56 -ar 44100 -b 200 -r 15 -s 320x240 -f flv video_finale.flv

13.将.avi转成dv

ffmpeg -i video_origine.avi -s pal -r pal -aspect 4:3 -ar 48000 -ac 2 video_finale.dv

或者:

ffmpeg -i video_origine.avi -target pal-dv video_finale.dv

14.将.avi压缩成divx

ffmpeg -i video_origine.avi -s 320x240 -vcodec msmpeg4v2 video_finale.avi

15.将Ogg Theora压缩成Mpeg dvd

ffmpeg -i film_sortie_cinelerra.ogm -s 720x576 -vcodec mpeg2video -acodec mp3 film_terminate.mpg

16.将.avi压缩成SVCD mpeg2
NTSC格式:

ffmpeg -i video_origine.avi -target ntsc-svcd video_finale.mpg

PAL格式:

ffmpeg -i video_origine.avi -target pal-svcd video_finale.mpg

17.将.avi压缩成VCD mpeg2
NTSC格式:

ffmpeg -i video_origine.avi -target ntsc-vcd video_finale.mpg

PAL格式:

ffmpeg -i video_origine.avi -target pal-vcd video_finale.mpg

18.多通道编码

ffmpeg -i fichierentree -pass 2 -passlogfile ffmpeg2pass fichiersortie-2

19.从flv提取mp3

ffmpeg -i source.flv -ab 128k dest.mp3

我的第一个爬虫程序

发表于 2016-10-26   |   分类于 Python   |  

前言

学习python一段时间了,也了解过爬虫,觉得甚是有趣,于是想自己动手试试,因此诞生了我的第一个爬虫。

环境

使用pip安装beautifulsoup4(先翻墙,不然pip会报timeout错误),beautifulsoup省去了繁复的正则,使得开发起来更加友好。

sudo -H pip --default-timeout=100 install beautifulsoup4

实现

以下程序主要实现了一个小功能即爬取链家网苏州工业园区100平以下的所有二手房房源,并且生成csv文件(可由excel打开),ps:网站dom会变更代码不具时效性😄。

#!/usr/bin/python
# -*- coding: utf-8 -*-

import sys
import time
import requests
import urllib2
import codecs

reload(sys)
sys.setdefaultencoding('utf8')

from bs4 import BeautifulSoup

class houseInfo:
    def __init__(self,title = '',address = '',square =' ',huxing = '',priceInfo = '',unitPrice = '',link = ''):
        self.title = title
        self.address = address
        self.square = square
        self.huxing = huxing
        self.priceInfo = priceInfo
        self.unitPrice = unitPrice
        self.link = link

list = []

def grab(url):
    # 使用requests或者urllib2都可以
    # request = urllib2.Request(url)
    # response = urllib2.urlopen(request)
    # plain_text = response.read()
    source_code = requests.get(url)
    plain_text = source_code.text
    soup = BeautifulSoup(plain_text,"html.parser")
    list_soup = soup.find("ul", class_="house-lst").find_all('li');

    for item in list_soup:
        title = item.find("div", class_="info-panel").a.string
        address = item.find("div", class_="info-panel").find("div", class_="col-1").find("div", class_="where").a.string
        square = item.find("div", class_="info-panel").find("div", class_="col-1").find("div", class_="where").find_all('span')[2].string
        huxing = item.find("div", class_="info-panel").find("div", class_="col-1").find("div", class_="where").find_all('span')[1].string
        priceInfo = item.find("div", class_="info-panel").find("div", class_="col-3").find("div", class_="price").span.string
        unitPrice = item.find("div", class_="info-panel").find("div", class_="col-3").find("div", class_="price-pre").string
        link = 'http://su.lianjia.com'+item.find("div", class_="info-panel").a.get('href')
        info = houseInfo(title,address,square,huxing,priceInfo,unitPrice)
        single = '%s,%s,%s,%s,%s万,%s,%s\n'%(title,address,square,huxing,priceInfo,unitPrice,link)
        list.append(single)

for i in range(1, 23):
    page = "http://su.lianjia.com/ershoufang/gongyeyuan/d{0}p1/".format(str(i))
    grab(page)

with open('data.csv', 'w') as f:
    for item in list:
        # BOM_UTF8是为了excel中文不乱码
        f.write(codecs.BOM_UTF8.decode('utf-8'))
        f.write(item)

python打包可执行文件

发表于 2016-10-20   |   分类于 Python   |  

PyInstaller 是一个用来将 Python 程序打包成一个独立可执行软件包,支持 Windows、Linux 和 Mac OS X。

Installation

PyInstaller is available on PyPI. You can install it through pip:

pip install pyinstaller

Tips: 必须翻墙,不然会因为timeout报错,可以加一些参数:

sudo -H pip --default-timeout=100 install pyinstaller

usage

安装完pyinstaller之后就可以开始使用了。

使用pyinstaller生成可执行文件的方法

  • 将依赖文件集中到一个文件夹:
pyinstaller -D -w main.py   
  • 将所有依赖文件都打包到同一个可执行文件中:
pyinstaller -F -w  main.py  

把main.py替换成你的主入口python文件即可。
-w参数代表main.py是一个窗体程序。

objective-c的工程内使用swift类

发表于 2016-09-19   |   分类于 iOS   |  

主要步骤:添加swift桥接,修改项目配置项。

具体步骤如下图:



stackoverflow链接

git rebase 合并多条commit

发表于 2016-08-18   |   分类于 iOS   |  

目的

合并多次commit,保留一次commit信息

步骤

查看git log



合并commit2,3,4, 226b17为commit1的hash值

git rebase -i 226b17


:wq



:wq

commit合并成功



从git reset --hard中拯救代码

发表于 2016-08-02   |   分类于 iOS   |  

场景

如果git add .后还未commit输入了git reset --hard,会发现缓存区和本地都没有了这些改动的纪录,因为用了--hard。

挽救

由于每次git命令进行操作时git都会对相关文件进行快照,并通过一定形式把信息保存再.git/目录下。

由于此前我使用过git add .命令,因此当文件被放进暂存区时,快照信息对象就已经保存了,而实用git reset --hard之后,这些对象就变成了悬空文件对象(dangling blob)。

我们可以实用git fsck命令显示他们

git fsck:用于验证当前git仓库数据的有效性和一致性,能够显示那些”丢失”的commit、blob(文件)、tree等。

我们可以通过以下命令

git fsck --cache --unreachable $(git for-each-ref --format="%(objectname)")

我们得到一大堆blob的hash ID

unreachable blob 907b308167f0880fb2a5c0e1614bb0c7620f9dc3
unreachable blob 72663d3adcf67548b9e0f0b2eeef62bce3d53e03
...

接下来使用git show就能显示这些对象的内容了,例如git show 907b308。

疲民之术[转载]

发表于 2016-08-01   |   分类于 Life   |  

原文地址

作者:介子平 新浪博客

任何时代,人民都是被统治的基本因子。人民者,平时出力,战时卖命。崔永元概括曰:“用你当炮灰时,你是无畏的英勇战士。用你创造财富时,你是勤奋的劳动人民。用你当统治基础时,你是光荣的领导阶级。剥夺你的所有财富时,你是乐于奉献的无产者。分享社会财富时,你是体制外的闲杂人员。进行‘义务教育时’,你是非本地户籍暂住人口。疯狂维稳时,你是社会各类不安定因素。”其又谓黎民庶民、子民蒸民、生民草民、兆民平民,又谓苍生百姓、布衣白丁、匹夫群氓、赤子大众。

《商君书》有驭民五术:壹民、弱民、疲民,辱民,贫民。壹民:统一思想,垄断意识形态,实施愚民政策。弱民:民弱国强,国强民弱,治国之道,务在弱民。疲民:为民寻事,使之疲于奔命,不得消停,然后换来统治者的安稳;不停征战,更卒、正卒、戍卒,不停徭役,力役、杂役、军役,使民无暇顾及他事。辱民:使之匍匐于生计,毫无自尊自信,唆之相互检举揭发,终天生活于恐惧氛围。贫民:除却生存必须,剥夺余粮余财,人穷志短,马瘦毛长,只得依赖国家分给,否则便会饿死。五者若不灵,杀之。

制天下者,必先制民,历代统治者奉《商君书》为秘籍宝典,桑弘羊赞之:“功如丘山,名传后世。”王安石赋诗曰:“自古驱民在信诚,一言为重百金轻。今人未可非商鞅,商鞅能令政必行。”

1958年8月21日,毛泽东在北戴河会议上讲话:“民法和刑法那一类法律都不要了。民法刑法那样多条谁记得了?一搞大跃进,就没时间犯法了。”此即疲民之术。在其执政的28年间,大运动套小运动,小运动为大运动,一个运动未结,另一运动已始,大大小小五六十次,唐德刚便说:“毛当国28年,最大的特点就是搞‘运动’,中国老百姓简直可以说没有一时一刻不在胆战心惊的运动中讨生活。”此也疲民之术。人有张弛调剂,农有忙闲间歇,闲时,迎神赛社,赶集听戏,然在学大寨期间,惟剩一忙。耕耘收储自不必说,纵然天寒地冻之时,大搞农田水利建设,平整土地,熟田变生土,美其名曰海绵田,毁林开垦,填湖造地,生态为之破坏,美其名曰人定胜天。期间,送饭地头,送戏田间,只闻周文雍陈铁军刑场上举办过婚礼,却不知有将婚礼办到水库工地上者。捆绑农民于土地,使之不得自由迁徙,此仍疲民之术。

疲民身体的当间,还树立起了若干劳模,号召众人学习之。工业学大庆,农业学大寨,全国学人民解放军。解放军里的先进人物最多,雷锋王杰刘英俊,除去做好事救财产,共同的一点是均毕业于“毛泽东思想大学校”,《毛选》学得好。此外,各行各业各树各的先进,周恩来便欣然道:“天涯处处有芳草,祖国处处有英雄。”有歌唱道:“革命熔炉火最红,毛泽东时代出英雄。”仅大寨的模范人物就有陈永贵、郭凤莲、贾进才、宋立英等。知青中的模范人物更多,著名者有河北的邢燕子、江苏的董家耕、山西的蔡立坚、天津的侯隽等,后来每个省、每个县都树起了自己的模范。黑龙江的金训华名气最大,1969年8月,上海知青金训华在洪水激流中抢救国家财产英勇牺牲,这位知青用以生命为代价抢救的国家财产,原来只是两根电线杆子。之后学金训华成风,表现突出者,可回城可当兵,可推荐工农兵学员,还可巡回作报告,尤其对于那些家庭出生不好者,尚有为救羊羔、扑灭草原野火罹难者,总之,国家利益至上,财产比人命重要,与国家的存在相比,个人简直无足轻重。学先进,赶先进,乃疲民精神之术。精神疲民之要点,在于使民占心,无暇反思自省,无以判断是否。你一旦被别人的观点所左右,实已沦为别人的奴隶。鲁迅说:“做奴隶虽然不幸,但并不可怕,因为知道挣扎,毕竟还有挣脱的希望;若是从奴隶生活中寻出美来,赞叹、陶醉,就是万劫不复的奴才了。”不幸被鲁迅言中,多数人在奴隶生活中找到了乐趣。

基本因子,永远是芸芸莘莘,铺天盖地。以前的教育是“永作革命的螺丝钉”,后来不提“革命”了,就作社会的螺丝钉吧。当你步入社会后便发现,在国家这部巨型机器上,哪有作螺丝钉的机会,你就是块铺路的碎石,终日被人车来回碾压。付出许多,所获极少,工资不高,纳税不低。卫生部部长陈竺曾在“小崔说事”栏目接受崔永元采访时,侃侃而谈医疗改革成果之惠民:“我们免费为一位农村大妈做了白内障手术。当摘下纱布时,她能看见了,她千谢万谢,要感谢这次‘白内障患者复明工程’的项目!靠她自己,她一辈子也做不起手术。”崔永元反问道:“她辛苦一辈子,连个白内障手术都做不起,那她得恨谁呢?”

时下为买房买车,孩子受教育家人看大夫,似乎所有人都在忙忙碌碌,蝇营狗苟,民疲矣。阳光少年一旦计较起柴米油盐,顿已进入中年,诗意泯灭,功利遂滋,浪漫殆尽,世故成习。而“买房保值”“孩子不能输在起跑线上”之类的口号,概念疲民也。这个路线,那个教育,这个主义,那个引导,精神疲民也。无形较之有型,劳心较之劳力,更甚。

在一个设定好的笼子里,任何动作,都是别人期望的表演。提笼之人,就怕你闲着,闲出自省自察、嗜欲爱好来,闲出条分缕析、擘肌剖理来,该是怎样的杵逆不道?圣人早有箴言:“民可使由之,不可使知之。”
韩惠王曾派手无寸铁的水利专家郑国,说服秦国兴修水利,意在疲秦而无暇顾及六国。然秦民早已习惯被疲,疲秦不成反利秦。然秦人连年征战,加之筑长城,修阿房,疲民之术终使天下疲民揭竿而起,亡秦者,秦民也。隋炀帝征辽东,挖运河,疲民无奈,篝火狐鸣,亡隋者,隋民也。

对民如此,对君亦然。仇士良檀权揽政20余年,先后杀二王、一妃、四宰相,甚至可当面指斥皇帝,唐文宗哀叹自己受家奴控制,不如亡国之君周赧王、汉献帝。仇士良的事君固位秘诀为:“天子不可令闲暇,暇必观书,见儒臣,则又纳谏,智深虑远,减玩好,省游幸,吾属恩且薄而权轻矣。为诸君计,莫若殖财货,盛鹰马,日以球猎声色蛊其心,极侈靡,使悦不知息,则必斥经术,阇外事,万机在我,恩泽权力欲焉往哉?”

Xcode打包.a静态库step by step

发表于 2016-07-20   |   分类于 iOS   |  

库介绍

库从本质上来说是一种可执行代码的二进制格式,可以被载入内存中执行。库分静态库和动态库两种。
iOS中的静态库有 .a 和 .framework两种形式;动态库有.dylib 和 .framework 形式,后来.dylib动态库又被苹果替换成.tbd的形式。

静态库与动态库的区别

静态库和动态库是相对编译期和运行期的:静态库在程序编译时会被链接到目标代码中,程序运行时将不再需要改静态库;而动态库在程序编译时并不会被链接到目标代码中,只是在程序运行时才被载入,因为在程序运行期间还需要动态库的存在。
总结:同一个静态库在不同程序中使用时,每一个程序中都得导入一次,打包时也被打包进去,形成一个程序。而动态库在不同程序中,打包时并没有被打包进去,只在程序运行使用时,才链接载入(如系统的框架如UIKit、Foundation等),所以程序体积会小很多,但是苹果不让使用自己的动态库,否则审核就无法通过。

创建.a静态库

第一步,新建工程。一般使用工程名就使用库的名称,比如我这里用任意一个NSString的Category来创建静态库,我的工程名就取名为Tool,创建的.a静态库就是libTool.a。



第二步,删除系统默认创建的【Tool.h】和【Tool.m】文件,导入需要打包的源文件。



第三步,修改配置 左上角加号->【New Headers Phase】-> 添加所有需要打包的头文件,如下图:



第四步,修改导出product配置



第五步,修改编译指令集



模拟器:iPhone4s~5 : i386 iPhone5s~6plus : x86_64
真机:iPhone3gs~4s : armv7 iPhone5~5c : armv7s iPhone5s~6plus : arm64
如果第五步这里,设置为YES,那么编译出来的.a静态库就只包含当前设备的指令集。
举个例子:如果我们选择iPhone 5模拟器【Command+B】编译,则编译出来的.a静态库只能用iPhone4s~5模拟器跑程序,用iPhone5s~6plus,则会报找不到x86_64的libTool库。
设置为NO,则会把所有指令集的都打包合并。

第六步,编译(快捷键【Command+B】
编译时,需要用模拟器和真机各编译一次,这样Products目录下的libTool.a静态库才会变为黑色,右键show in Finder,可以进入Products目录下。



注意:如果步骤四中,不将Build Configuration改为Release,则打包出来的静态库会存于【Debug-iphoneos】和【Debug-iphonesimulator】两个文件夹下。
我们一般都使用Release模式,因为程序最终发布之后是Release版的,所以静态库也是在Release模式下使用。

如果想要通用需要将模拟器使用的静态库与真机使用的静态库合并成一个静态库,可以使用终端命令来实现。命令格式:
lipo -create 第一个.a文件的绝对路径 第二个.a文件的绝对路径 -output 最终的.a文件路径。
本文中使用的命令如下:

lipo -create /Users/paul/Library/Developer/Xcode/DerivedData/Tool-fcimdkyxyorzxoafjvdaenioayfh/Build/Products/Release-iphoneos/libTool.a /Users/paul/Library/Developer/Xcode/DerivedData/Tool-fcimdkyxyorzxoafjvdaenioayfh/Build/Products/Release-iphonesimulator/libTool.a -output /Users/paul/Desktop/libTool.a

补充:经过多次实践,第三步的操作省略,依然可以导出可正常使用的包。
如果静态库中有category类,则在使用静态库的项目配置中【Other Linker Flags】需要添加参数【-ObjC】或者【-all_load】。

最后,将生成的.a文件以及相应include文件引入即可使用。

iOS 9 全新Contacts Framework解析

发表于 2016-07-18   |   分类于 iOS   |  

引言

在以前iOS开发中,涉及联系人相关的编程,代码都非常繁琐,并且框架的设计也不是Objective-C风格的,这使开发者用起来非常的难受。在iOS9中,apple终于解决了这个问题,全新的Contacts Framework将完全替代AddressBookFramework,AddressBookFramework也将成为历史被弃用。

Contact框架的使用

CNContact基本属性

/**
 *  设置联系人的基本属性
 *
 *  @return 返回联系人的对象
 */
- (CNMutableContact *)initializeContact{
    // 创建联系人对象
    CNMutableContact *contact = [[CNMutableContact alloc] init];
    // 设置联系人的头像
    contact.imageData = UIImagePNGRepresentation([UIImage imageNamed:@"7677360.png"]);
    // 设置联系人姓名
    contact.givenName = @"伟君";
    // 设置姓氏
    contact.familyName = @"丁";
    // 设置联系人邮箱
    CNLabeledValue *homeEmail = [CNLabeledValue labeledValueWithLabel:CNLabelHome value:@"12345qq.com"];
    CNLabeledValue *workEmail = [CNLabeledValue labeledValueWithLabel:CNLabelWork value:@"32467@sina.cn"];
    CNLabeledValue *otherEmail = [CNLabeledValue labeledValueWithLabel:CNLabelOther value:@"lanaj.com"];
    contact.emailAddresses = @[homeEmail,workEmail,otherEmail];
    // 设置机构名
    contact.organizationName = @"互联网";
    // 设置部门
    contact.departmentName = @"IT";
    // 设置工作的名称
    contact.jobTitle = @"ios";
    // 设置社会的简述
    CNSocialProfile *profile = [[CNSocialProfile alloc] initWithUrlString:@"12306.cn" username:@"Paul" userIdentifier:nil service:@"IT行业"];
    CNLabeledValue *socialProfile = [CNLabeledValue labeledValueWithLabel:CNSocialProfileServiceGameCenter value:profile];
    contact.socialProfiles = @[socialProfile];
    // 设置电话号码
    CNPhoneNumber *mobileNumber = [[CNPhoneNumber alloc] initWithStringValue:@"18500000000"];
    CNLabeledValue *mobilePhone = [[CNLabeledValue alloc] initWithLabel:CNLabelPhoneNumberMobile value:mobileNumber];
    contact.phoneNumbers = @[mobilePhone];
    // 设置与联系人的关系
    CNContactRelation *friend = [[CNContactRelation alloc] initWithName:@"好基友"];
    CNLabeledValue *relation = [CNLabeledValue labeledValueWithLabel:CNLabelContactRelationFriend value:friend];
    contact.contactRelations = @[relation];
    // 设置生日
    NSDateComponents *birthday = [[NSDateComponents alloc] init];
    birthday.day = 6;
    birthday.month = 5;
    birthday.year = 2000;
    contact.birthday = birthday;

    return contact;
}

CNSaveRequest使用

@interface CNSaveRequest : NSObject
//添加一个联系人
- (void)addContact:(CNMutableContact *)contact toContainerWithIdentifier:(nullable NSString *)identifier;

//更新一个联系人
- (void)updateContact:(CNMutableContact *)contact;
//删除一个联系人
- (void)deleteContact:(CNMutableContact *)contact;
//添加一组联系人
- (void)addGroup:(CNMutableGroup *)group toContainerWithIdentifier:(nullable NSString *)identifier;
//更新一组联系人
- (void)updateGroup:(CNMutableGroup *)group;
//删除一组联系人
- (void)deleteGroup:(CNMutableGroup *)group;
//向组中添加子组
- (void)addSubgroup:(CNGroup *)subgroup toGroup:(CNGroup *)group NS_AVAILABLE(10_11, NA);
//在组中删除子组
- (void)removeSubgroup:(CNGroup *)subgroup fromGroup:(CNGroup *)group NS_AVAILABLE(10_11, NA);
//向组中添加成员
- (void)addMember:(CNContact *)contact toGroup:(CNGroup *)group;
//向组中移除成员
- (void)removeMember:(CNContact *)contact fromGroup:(CNGroup *)group;

@end

CNSaveRequest的封装使用

/**
 *  在group里删除成员
 *
 *  @param contact 被删除的联系人
 *  @param group   在该group里删除联系人
 */
- (void)deleteMemberWithContact:(CNContact *)contact toGroup:(CNGroup *)group{
    CNSaveRequest *saveRequest = [[CNSaveRequest alloc] init];
    [saveRequest removeMember:contact fromGroup:group];
    // 写入
    CNContactStore *store = [[CNContactStore alloc] init];
    [store executeSaveRequest:saveRequest error:nil];

}

/**
 *  向group添加成员
 *
 *  @param contact 被添加的联系人
 *  @param group   添加到该group
 */
- (void)addMemberWithContact:(CNContact *)contact toGroup:(CNGroup *)group{
    CNSaveRequest *saveRequest = [[CNSaveRequest alloc] init];
    [saveRequest addMember:contact toGroup:group];
    // 写入
    CNContactStore *store = [[CNContactStore alloc] init];
    [store executeSaveRequest:saveRequest error:nil];

}

/**
 *  更新group
 *
 *  @param group 被更新的group
 */
- (void)updateGroup:(CNMutableGroup *)group{
    CNSaveRequest *saveRequest = [[CNSaveRequest alloc] init];
    [saveRequest updateGroup:group];
    // 写入
    CNContactStore *store = [[CNContactStore alloc] init];
    [store executeSaveRequest:saveRequest error:nil];
}

/**
 *  删除group操作
 *
 *  @param group 被删除的group
 */
- (void)deleteWithGroup:(CNMutableGroup *)group{
    CNSaveRequest *saveRequest = [[CNSaveRequest alloc] init];
    [saveRequest deleteGroup:group];
    // 写入
    CNContactStore *store = [[CNContactStore alloc] init];
    [store executeSaveRequest:saveRequest error:nil];
}

/**
 *  查询
 *
 *  @return 返回数组
 */
- (NSArray *)queryGroup{
    CNContactStore *store = [[CNContactStore alloc] init];
    // 查询所有的group(predicate参数为空时会查询所有的group)
    NSArray *arr = [store groupsMatchingPredicate:nil error:nil];
    return arr;
}

/**
 *  添加群组
 *
 *  @param name 群组的名称
 */
- (void)addGroupWithName:(NSString *)name{
    CNMutableGroup *group = [[CNMutableGroup alloc] init];
    group.name = name;
    CNSaveRequest *saveRequest = [[CNSaveRequest alloc] init];
    [saveRequest addGroup:group toContainerWithIdentifier:nil];
    // 写入
    CNContactStore *store = [[CNContactStore alloc] init];
    [store executeSaveRequest:saveRequest error:nil];
}

/**
 *  查询操作
 *
 *  @return 返回数组
 */
- (NSArray *)queryContactWithName:(NSString *)name{
    CNContactStore *store = [[CNContactStore alloc] init];
    // 检索条件
    NSPredicate *predicate = [CNContact predicateForContactsMatchingName:name];
    // 提取数据 (keysToFetch:@[CNContactGivenNameKey]是设置提取联系人的哪些数据)
    NSArray *contact = [store unifiedContactsMatchingPredicate:predicate keysToFetch:@[CNContactGivenNameKey] error:nil];
    return contact;
}

/**
 *  更新联系人
 *
 *  @param contact 被更新的联系人
 */
- (void)updateContact:(CNMutableContact *)contact{
// 创建联系人请求
    CNSaveRequest *saveRequest = [[CNSaveRequest alloc] init];
    [saveRequest updateContact:contact];
    // 重新写入
    CNContactStore *store = [[CNContactStore alloc] init];
    [store executeSaveRequest:saveRequest error:nil];

}

/**
 *  删除联系人
 *
 *  @param contact 被删除的联系人
 */
- (void)deleteContact:(CNMutableContact *)contact{
    // 创建联系人请求
    CNSaveRequest *saveRequest = [[CNSaveRequest alloc] init];
    [saveRequest deleteContact:contact];
    // 写入操作
    CNContactStore *store = [[CNContactStore alloc] init];
    [store executeSaveRequest:saveRequest error:nil];

}

/**
 *  添加联系人
 *
 *  @param contact 联系人
 */
- (void)addContact:(CNMutableContact *)contact{
    // 创建联系人请求
    CNSaveRequest *saveRequest = [[CNSaveRequest alloc] init];
    [saveRequest addContact:contact toContainerWithIdentifier:nil];
    // 写入联系人
    CNContactStore *store = [[CNContactStore alloc] init];
    [store executeSaveRequest:saveRequest error:nil];
}

实际工程中的操作使用

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a ni
    CNMutableContact *contact = [self initializeContact];    
    //添加联系人
    [self addContact:contact];
    //查询
    NSArray *arr = [self queryContactWithName:@"伟君"];
    //将不可变的CNContact转成CNMutableContact,便可执行以下操作
    CNMutableContact *contact = [arr[0] mutableCopy];
    //更新
    contact.givenName = @"大力";
    [self updateContact:contact];
    //删除
    [self deleteContact:contact];

    //添加群组
    [self addGroupWithName:@"Yudo"];
    //返回所有数组
    NSArray *array = [self queryGroup];
    NSLog(@"==%@",array);
    //删除group操作
    CNMutableGroup *group = [array[2] mutableCopy];
    [self deleteWithGroup:group];

    //更新group
    CNMutableGroup *group = [array[2] mutableCopy];
    group.name = @"Yudo";
    [self updateGroup:group];

    //向group添加成员
    NSArray *results = [self queryContactWithName:@"伟君"];
    for (int i=0; i<array.count; i++) {
        CNGroup *group=array[i];
        if ([group.name isEqualToString:@"Yudo"]) {
            [self addMemberWithContact:results[0] toGroup:group];
        }
    }


    //在group里删除成员
    NSArray *results = [self queryContactWithName:@"baba zhang"];
    for (int i=0; i<array.count; i++) {
        CNGroup *group=array[i];
        if ([group.name isEqualToString:@"Yudo"]) {
            [self deleteMemberWithContact:results[0] toGroup:group];
        }
    }
}
123
Paul Ding

Paul Ding

iOS & Python Developer

24 日志
8 分类
19 标签
github zhihu
© 2017 Paul Ding
由 Hexo 强力驱动
主题 - NexT.Mist