我为什么讨厌程序员

PM与工程师的交恶,由来已久。不仅如此,视觉与工程师的交恶也由来已久。
还有些哥们之所以能游刃有余,是因为在产品实现的过程中,已经习惯了打人情牌。

很多产品或工程师朋友可能会交流这些沟通过程中,如何很好的搞定SB般的对方?

这些冲突,我认为没有讨论的必要。等活在这些冲突里的朋友们,level up后,就会脱离这样的苦海,自当能理解“没有必要”的意思。

今天,我想说的是,我为什么讨厌程序员?!

我是谁?我是Producer。

真的很讨厌么?其实不然,我非常爱工程师。按我的经验来看,多数工程师比多数PM,其实更理解用户。

不仅是如此,我的技术涉猎也比较广,django、python、mootools、html/css这些写得很溜,在不知所以的情况下,node.js、Java、PHP、jython、AS等,也照用不误。

技术是什么?程序是什么?这跟程序语言没有本质的关系,极端的说,它就是+1和-1而已。

虽然常会误解为一个纯coder,但自己程序员这种角色,坦诚说,厌恶的很。

按照自己几年前的性格,逮到垃圾程序员,能直接破口大骂。后来,发现人都好面子,不能骂了。所以,憋了很久的气,今天要倒一倒。

##理由1:装逼

他们经常会用一些技术上的关键词来说话,如果关键词的含金量很高,咱听不懂,那没有办法,术业有专攻。但一旦你理解那些所谓的术语有多么简单以及自然的时候,你心里最想说的恐怕是骂娘了。

这样的程序员,比郭小四不相上下。

##理由2:傻逼

我需要你来设计产品的实现,换句话说,就是告诉我程序打算怎么写,数据结构是什么设计的,数据流动的环节是打算如何处理的。

你会给一个方案。基本上会是最笨的办法。然后,哥还得夸你,嗯,做的不错,有进步;不夸的话,你会觉得自己的价值没有得到尊重。

用谢耳朵的话说,你在你的领域做的非常出色,但你做的事情没有任何意义。

大白话:你是一名出色的傻逼。

##理由3:冷忽悠

程序员都很木讷?都不会忽悠?

知道什么叫冷暴力忽悠么?!

我们当前的结构不支持这样的实现的⋯⋯

这个技术上是没有办法实现的⋯⋯

但按照我的经验来看,对于你无法佩服的程序员,别信他们这样的鬼话,他们不仅仅会忽悠你,他们同时也在忽悠自己,因为他们自己真是这么想的。

碰到你非常佩服的程序员,请相信我,再逼一逼他,一起探讨各种hack的方法,有些所谓的“不可能”就迎刃而解了。

真遇到了不可能,那就让它去吧。有一天,灵感会光临的。

理由4:看起来很忙,出BUG都是有原因的

会存在没有原因的bug么?!!

不过,呃,这个bug的原因不是我造成的⋯⋯

靠!

##理由5:缺乏想象力,不思进取

对程序员来说,最大的侮辱,是重构他的代码,并且效率提升了100、10000倍。

但多数程序员不会碰到这样的事情,所以还有个办法,你直接骂他在写垃圾代码就好了。

但这算是侮辱么?!

真正的coder最关心的是对方重构的方式和思维的哲学,是不是质变性的。如果有人只为了骂而骂,为了重构而重构,coder倒是要开心了,又来个傻逼。

我认为现在这个行业的从业人员实在太多,弱者也实在太多,为了照顾弱者的脆弱心灵,容忍他们贫乏的想象力,容忍他们的不思进取,同时还谎称他们人不错,很上进;才是让我们的互联网技术力量无法跟老美他们匹敌的原罪。

##理由6:不知廉耻

写垃圾代码,做垃圾的解决方式,然后自鸣得意去分享。

被斥责的时候,会说,你不尊重人,退一万步讲,我就算写垃圾代码,那也是我能力所限呀。

我最厌恶这种固步自封的家伙,简直就是不知廉耻的流氓。

Excerpted from 我为什么讨厌程序员

06/08/2015 15:54 下午 posted in  apple

ios数据持久化存储&文件系统编程

##包系统
就是app程序本身,其实是个zip包,资源/可执行文件 都在里面

+ (NSBundle *)mainBundle 得到程序本身的bundle类. NSBundle提供了很多path相关函数
运行期只读,不可写
没有必要建立子文件夹,苹果不推荐在包中建立子文件夹
+ (UIImage *)imageNamed:(NSString *)name 可以直接加载包中的图片文件
包中带有的数据不能太多,不然不利于用户安装
NSBundle pathForResource:ofType: 使用这个函数查找包存放的文件
Sandbox 系统
每个app安装之后都存放在一个单独的目录当中,这个目录叫做沙盒,目录结构如下

  • Documents
  • Library/Caches
  • Library/Preferences
  • tmp

##程序Bundle

  • Documents 会在用户通过itunes备份的时候被自动备份,其他目录随意用

  • NSHomeDirectory() 得到app的沙盒目录

  • NSTemporaryDirectory() 得到 $(沙盒目录)/tmp

  • NSSearchPathForDirectoriesInDomains( NSDocumentDirectory, NSUserDomainMask, YES) 得到 $(沙盒目录)/Documents (函数返回的是数组)

  • NSSearchPathForDirectoriesInDomains( NSLibraryDirectory, NSUserDomainMask, YES) 得到 $(沙盒目录)/Library
    NSString 定义了一堆 关于文件路径的 join,split的函数,路径相关函数主要定义在:NSPathUtilities.h 文件当中

##NSUserDefaults 系统
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
文件存放在 $(沙盒目录)/Library/Preferences/{Bundle Identifier}.plist
ios提供了一个工厂函数,没有容量限制,最好不要在里面存放业务数据, 这会破坏ios对此的语义设定,这里面应该存放程序设置相关信息
##Keychain 系统
专注于存放密码或者证书
数据是加密存储的
keychain里保存的信息不会因App被删除而丢失,在用户重新安装App后依然有效
##Cache系统
真的是cache,存储会有过期时间

NSURLCache,以url为单元,可以存在硬盘上
NSCache,只放在内存当中,和NSMutableDictionary区别不大,有意义的是:ios可以在程序运行期自行释放NSCache
##文件格式
二进制:NSData
plist: 最常见而且简单
对象序列化:NSKeyedArchiver
sqlite: 文件数据库,Core Data/libsqlite3/FMDB
plain text: 罕见,用Standard C Library操作,fopen/fwrite/fclose

06/06/2015 16:00 下午 posted in  apple

常用代码块整理

/* 常用代码块
 
 
1.copy:
@property (nonatomic,copy) NSString *<#string#>;
 
 
2.strong:
@property (nonatomic,strong) <#Class#> *<#object#>;

 
3.weak:
@property (nonatomic,weak) <#Class#> *<#object#>;

 
4.assign:
@property (nonatomic,assign) <#Class#> <#property#>;
 
 
5.delegate:
@property (nonatomic,weak) id<<#protocol#>> <#delegate#>;
 

6.block:
@property (nonatomic,copy) <#Block#> <#block#>;
 
 
7.mark:
#pragma mark <#mark#>

 
8.gmark:
#pragma mark - <#gmark#>
 
 
9.warning:
#warning <#message#>
 


 
10.ReUseCell:
 
 static NSString *rid=<#rid#>;
 
 <#Class#> *cell=[tableView dequeueReusableCellWithIdentifier:rid];
 
 if(cell==nil){
 
 cell=[[<#Class#> alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:rid];
 
 }
 
 return cell;
 
 
11.initObj:
 
 if(self=[super init]){
    <#init#>
 }
 
 return self;
 
12.dataFill:
 -(void)dataFill:(<#ModelClass#> *)<#model#>{
 
    <#code#>

 }
 
13.MainGCD:
 dispatch_async(dispatch_get_main_queue(), ^{
    <#code#>
 });

 
14.GlobalGCD:
 dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
    <#code#>
 });

15.AfterGCD:
 dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(<#delayInSeconds#> * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
    <#code to be executed after a specified delay#>
 });
 
16.OnceGCD:
 static dispatch_once_t onceToken;
 dispatch_once(&onceToken, ^{
    <#code to be executed once#>
 });
 
 
17.APPLICATION:
 [UIApplication sharedApplication]

 
18.NOTICENTER:
 [NSNotificationCenter defaultCenter]

 
17.DEFINEIOS6
#define ios6x ([[[UIDevice currentDevice] systemVersion] floatValue] < 7.0f)
 
18.NSLOG:
NSLog(@"<#content#>");
 
 
20.VIEWDIDLOAD
 -(void)viewDidLoad{
 
     [super viewDidLoad];
     
     <#code#>
 }

 
21.VIEWWILLAPPEAR
 -(void)viewWillAppear:(BOOL)animated{
     [super viewWillAppear:animated];
     <#code#>
 }
 
 
22.VIEWDIDAPPEAR
 -(void)viewDidAppear:(BOOL)animated{
 
     [super viewDidAppear:animated];
     
     <#code#>
 }
 
 
23.VIEWWILLDISAPPEAR
 -(void)viewWillDisappear:(BOOL)animated{
 
     [super viewWillDisappear:animated];
     
     <#code#>
 }
 
 
24.VIEWDIDDISAPPEAR
 -(void)viewDidDisappear:(BOOL)animated{
 
     [super viewDidDisappear:animated];
     
     <#code#>
 }
 
 
24.LAYOUTSUBVIEWS
 -(void)layoutSubviews{
 
     [super layoutSubviews];
     
     <#code#>
 }
 
 
25.AWAKEFROMNIB
 -(void)awakeFromNib{
 
     [super awakeFromNib];
     
     <#code#>
 }
 
26.LOADVIEW
 -(void)loadView{
 
    <#code#>
 }
 
27.INITFRAME
 -(instancetype)initWithFrame:(CGRect)frame{
 
     self = [super initWithFrame:frame];
     
     if(self){
     
     <#code#>
 
     }
 
     return self;
 }
 
 
28.INITCODER
 -(id)initWithCoder:(NSCoder *)aDecoder{
 
 self=[super initWithCoder:aDecoder];
 
     if(self){
     
         <#code#>
     
     }
 
 return self;
 }
 
29.weakSelf
 __weak typeof(self) weakSelf=self;

30.DEBUGSCROLLVIEW
 NSLog(@"\n\n scrollView的Debug信息: \n\n frame=%@,\n bounds=%@,\n contentSize=%@,\n contentOffset=%@,\n contentInset=%@.\n",NSStringFromCGRect(scrollView.frame),NSStringFromCGRect(scrollView.bounds),NSStringFromCGSize(scrollView.contentSize),NSStringFromCGPoint(scrollView.contentOffset),NSStringFromUIEdgeInsets(scrollView.contentInset));

31.CONSTRAINTS
 [<#view#> mas_makeConstraints:^(MASConstraintMaker *make) {
 <#make.#>
 }];
 
 
*/
05/28/2015 09:42 上午 posted in  apple Program

VVDocumenter文档注释和appledoc生成文档

代码注释可以让代码更容易接受和使用,特别是在大型项目合作开发或模块开发中。Objective-C中也有一些很方便的注释插件和文档生成工具。本文推荐两个开源软件:VVDocumenter注释工具和appledoc文档生成工具。
###下载和安装VVDocumenter

VVDocumenter插件是github上的一个开源项目,地址是https://github.com/onevcat/VVDocumenter-Xcode。
你可以git clone或在github网站上下载工程的zip压缩文件。下载完成后,打开其中的工程,build&run一下就安装成功了。然后记得要重新启动一下Xcode应用,VVDocumenter插件就生效了。试试在方法定义前输入“///”。

VVDocumenter GitHub项目地址

###appledoc
我们开发自己的模块时,经常会将模块接口提供给别人使用,这样我们不得不写一些接口说明文档。很多语言都提供了这种工具比如javadoc,doxygen等,可以将注释代码转化成在线文档。这里推荐一个特别适合Objective-C语言的一种文档输出工具appledoc。它可以把一些格式的注释转换成Apple SDK风格的文档,同时它支持VVDocumenter的输出注释格式。

appledoc GitHub项目地址

1.安装

git clone git://github.com/tomaz/appledoc.git
cd ./appledoc
sudo sh install-appledoc.sh

安装完成后,验证一下OK了没

appledoc --version

2.使用
进入code所在目录,跑一下下面的命令,默认会编译出docset并安装进Xcode。

appledoc --project-name MyProject --project-company ibireme ./

其中 MyProject是生成的Docset文件名,执行上面的命令之后会在工程目录底下生成一个名字为docset-installed的txt文档。

docset-installed.txt:

Documentation set was installed to Xcode!

Path: /Users/liunian/Library/Developer/Shared/Documentation/DocSets/com.ibireme.lnuniversal.LNUniversal.docset
Time: 2015-05-26 10:01:00 +0000

如果想要详细的参数,可以查看帮助

appledoc --help

###如果想要集成进Xcode工程:
1.选中你的工程,点击Add Target按钮,选择 Other -> Aggregate模板新建.
2.点击Add Build Phase按钮,添加一个Run Script.
3.把下面的模板代码复制进去,把前几行参数改成你自己的.
4.在Xcode左上角选择这个新建的Target,然后点击build.
5.文档就会编译好并且自动安装进Xcode了(重启Xcode生效).

#appledoc Xcode script  
# Start constants  
company="ACME";  
companyID="com.ACME";
companyURL="http://ACME.com";
target="iphoneos";
#target="macosx";
outputPath="~/help";
# End constants
 
/usr/local/bin/appledoc \
--project-name "${PROJECT_NAME}" \
--project-company "${company}" \
--company-id "${companyID}" \
--docset-atom-filename "${company}.atom" \
--docset-feed-url "${companyURL}/${company}/%DOCSETATOMFILENAME" \
--docset-package-url "${companyURL}/${company}/%DOCSETPACKAGEFILENAME" \
--docset-fallback-url "${companyURL}/${company}" \
--output "${outputPath}" \
--publish-docset \
--docset-platform-family "${target}" \
--logformat xcode \
--keep-intermediate-files \
--no-repeat-first-par \
--no-warn-invalid-crossref \
--exit-threshold 2 \
"${PROJECT_DIR}"

PS:集成到Xcode我一直没走通,估计是代码没有设置好的原因,回头可以好好研究下

###其他
编译出的Docset默认会放在/Users/ibireme/Library/Developer/Shared/Documentation/DocSets路径下。

Docset格式,实际上是一个bundle,里面包含了一些xml和html。显示包内容后就可以查看和修改了。如果需要放到网站上,那单独将html部分取出来就行。

Docset安装后,在Xcode中就可以实时查看某个方法的说明了,体验和官方文档保持一致。(有一点,category中的注释不会出现在xcode的快速帮助中,不知道新版xcode是否会有改进..)

05/26/2015 18:04 下午 posted in  apple

解决在iOS App中集成支付宝时遇到的RSA密钥签名问题

最近在自己的iOS native App中集成支付宝功能,发现有即时到帐、手机网页、快捷支付,之间的区别说的不够清楚,接口及参数定义更是各不相同。对于Native App来说,选择快捷支付(wap)就对了。

说起集成文档及Demo,发现文档质量比起五年前没啥进步,一如既往的不知所云,甚至缺少某些关键步骤。而且Demo中的代码一直强调此代码不完全能直接使用,可是我想说,开发者看demo的意义就在于能够快速的解决问题,最好能一键集成,SDK的集成度可以做得更好。可是无论文档和代码都缺少版本控制,二者之间存在大量不一致现象,更不用说出错后的信息让人难以跟踪,跟当年Windows的出错信息有得一拼。

下面说说集成快捷支付中遇到的一些关键环节,特别是RSA加密的问题,因为快捷支付只支持RSA,不支持MD5方式。

  1. PID: 申请快捷支付服务后,会在商家服务网页上看到pid等信息
  2. RSA加密: 然后用openssl生成商户的公钥和私钥。私钥用于提交支付申请时加密,而公钥要在商家服务页面上提交,换取到支付宝的公钥。
  3. 提交公钥的时候,”合作伙伴密钥”和”无线产品密钥管理”都要提交,内容一样。公钥字符串不要包括-----Begin Public Key...字样,去掉空格换行后组装成一条字符串。这一步如果出错,就会在支付跳转时出现”ALI64错误”,文档中丝毫没提!
  4. 对于iOS来说,私钥要转为PKCS8格式,即下述代码的第三行,而Android的话则不需要第三行!在代码中使用时,同样要,去掉空格换行后组装成一条字符串
openssl genrsa -out rsa_private_key.pem 1024
openssl rsa -in rsa_private_key.pem -pubout -out rsa_public_key.pem
openssl pkcs8 -topk8 -inform PEM -in rsa_private_key.pem -outform PEM -nocrypt

  1. 链接库:按照文档所述,导入alipay.framework和alipay.bundle。此外,demo代码中的Order.m、\openssl、Util文件和目录都要导入,并在工程的build settings中修改Search Path,消除找不到头文件的编译错误。
  2. App之间跳转设置。按照在项目Info.plist中设置URL Types->URL Schemes,内容自定,比如”alisdkdemo”,后续提交订单时要带这个参数,以便能从支付宝跳回你的App.
  3. 对于快捷支付的接口,在进行参数字符串拼接时,每个参数都形为title="abc"&sign_type="RSA",注意到双引号了吗?这和PC端或手机网页接口都是不同的。
let order = Order()
order.partner = "<你的PID>"
order.seller = "<你的注册邮箱>"
order.tradeNO = "201412061500"
order.productName = "巧克力"
order.productDescription = "夹心"
order.amount = "0.01"
order.notifyURL = "http://127.0.0.1:8000/xxx"
order.service = "mobile.securitypay.pay"
order.paymentType = "1"
order.inputCharset = "utf-8"
order.itBPay = "30m"
order.showUrl = "m.alipay.com"

let privateKey = "<对于iOS App,要把生成的私钥转为PCKS8格式,比原始私钥字符串更长一些。字符串不要包括`-----Begin Public Key...`字样,去掉空格换行后组装成一条字符串。>";

let orderSpec = order.description
let signer = RSADataSigner(privateKey: privateKey)
let signedString = signer.signString(orderSpec)
let orderString = "\(orderSpec)&sign=\"\(signedString)\"&sign_type=\"RSA\""
println(orderString)
AlipaySDK.defaultService().payOrder(orderString, fromScheme: "alisdkdemo", callback: {resultDic in
    println("Alipay result = \(resultDic as Dictionary)")
})

转载:解决在iOS App中集成支付宝时遇到的RSA密钥签名问题

05/25/2015 16:22 下午 posted in  apple

Coredata开发之MagicalRecord

  1. 线程的创建
    先看两则代码:
    代码1:
    for (NSString *feedID in self.feedsToRemove) {
        [MagicalRecord saveWithBlock:^(NSManagedObjectContext *localContext) {
            [Feed MR_deleteAllMatchingPredicate:[NSPredicate predicateWithFormat:@“uid = %@“,feedID]];
        } completion:^(BOOL contextDidSave, NSError *error) {
            
        }];
    }

代码2:

    [MagicalRecord saveWithBlock:^(NSManagedObjectContext *localContext) {
        for (NSString *feedID in self.feedsToRemove) {
            [Feed MR_deleteAllMatchingPredicate:[NSPredicate predicateWithFormat:@“uid = %@“,feedID]];
        }
    } completion:^(BOOL contextDidSave, NSError *error) {
        
    }];

代码1是错误的,因为会产生严重的线程问题,导致CPU居高不下,UI僵死等,
为什么呢?我们可以这样理解:MagicalRecord 的这个saveWithBlock方法,其实是创建一个子线程来处理数据事务,于是 当self.feedsToRemove有N个对象 那么就会产生N个线程,当然 对于一个设备来说线程总有一个最高数限制,直到把所有线程用光,于是乎整个世界就全被线程塞满了,卡死。。。

所以我们采用代码2中的写法,将枚举写如子线程中。

PS:这样的问题其实就是错误使用线程创建导致,还是自己马虎啊。。切记。

05/12/2015 22:50 下午 posted in  apple

NSPredicate是什么

##NSPredicate:谓词
字面翻译是这个意思,但是我觉得谓词这个词太难以理解了
NSPredicate的具体用途应该还是过滤,类似于过滤条件之类的,相当于一个主语的谓语,所以说会是谓词这个名字。(我是这么理解的)
##NSPredicate的创建
我们看到创建谓词使用类方法predicateWithFormat: (NSString*) format,format 里的东西真的
和SQL 的where 条件差不多。
另外,参数format 与NSLog 的格式化模版差不多,如果1 和
188.0 是传递过来的参数,你可以写成如下的形式:
@“pid>%d and height<%f”,1,188.0

##NSPredicate中主要的几种运算方式

  1. 比较运算符 > 、< 、== 、 >= 、<= 、 !=
    例:@“number >= 99”

  2. 逻辑运算符:AND、OR、NOT 这几个运算符计算并、或、非的结果。

  3. 范围运算符:IN 、BETWEEN
    例:@“number BETWEEN {1,5}”
    @“address IN {‘shanghai’,’nanjing’}”

  4. 字符串本身:SELF
    例:@“SELF == ‘APPLE’”

  5. 字符串相关:BEGINSWITH、ENDSWITH、CONTAINS
    例: @“name CONTAIN[cd] ‘ang’” //包含某个字符串
    @“name BEGINSWITH[c] ‘sh’” //以某个字符串开头
    @“name ENDSWITH[d] ‘ang’” //以某个字符串结束
    注:[c]不区分大小写 , [d]不区分发音符号即没有重音符号 , [cd]既不区分大小写,也不区分发音符号。

  6. 通配符:LIKE
    例:@“name LIKE[cd] ‘er’” //代表通配符,Like也接受[cd].
    @“name LIKE[cd] ‘???er
    ’”

  7. 正则表达式:MATCHES
    例:NSString *regex = @“^A.+e$”; //以A开头,e结尾
    @“name MATCHES %@“,regex

##如何使用NSPredicate对一个自定义实体进行筛选
NSPredicate我暂时都是用于过滤的,否则我们过滤就需要自己写判断 写循环,去判断输出了。
接下来就上代码和例子吧。

建立一个实体类 Dog

@property (copy   , nonatomic) NSString* name; 
@property (assign , nonatomic) int       age ;

这样我们就有一个类了
我们创建 5只Dog的实体


Dog * dog1=[Dog news];dog1.name=@“这是第一只Dog”;dog1.age=@“11”;
Dog * dog2=[Dog news];dog2.name=@“这是第二只Dog”;dog2.age=@“22”;
Dog * dog3=[Dog news];dog3.name=@“这是第三只Dog”;dog3.age=@“33”;
Dog * dog4=[Dog news];dog4.name=@“这是第四只Dog”;dog4.age=@“44”;
Dog * dog5=[Dog news];dog5.name=@“这是第五只Dog”;dog5.age=@“55”;

不要吐槽我的Dogs的年龄 → 。→
然后我们需要一个Array把他们都装进去

NSArray * dogArr=@[dog1,dog2,dog3,dog4,dog5];
酱紫所有的Dog都装到一个数组里了

使用NSPredicate的筛选
没有使用NSPredicate的筛选应该大家都会写,循环+判断。。。
使用NSPredicate的筛选
具体使用的代码
//创建谓词的对象 谓词条件是基于KVC的,所以需要说明一点,加入Dog里面有个属性是Doginfo指向Doginfo类,在使用的时候 我们的条件就要写成Doginfo.xxx了。

NSPredicate* predicate = [NSPredicate predicateWithFormat:@“name==‘这是第一只Dog’ AND age ==11”];
for(Dog * d in dogArr)
{
    if([predicate evaluateWithObject:d])
    {
        NSLog(d.name);
    }
}

以上的代码打印出来的结果就是 这是第一只Dog

NSPredicate筛选一个对象逻辑还是很清晰的,不过这里比较麻烦的就是 还有一个循环,这里我们会发现数组提供了一个方法可以更方便的检索数组对象
直接筛选出一个符合谓词的新数组。

NSPredicate *pre = [NSPredicate predicateWithFormat:@“age >11”];
NSMutableArray *arrayPre=[dogArr filteredArrayUsingPredicate: pre];

arrayPre里面的对象就会是 除了dog1之外的所有的dog。(至于为什么看我的条件...)

看到这里发现NSPredicate 可以用于自定义的实体的检索、筛选,那如果用于 NSString,NSInteger,bool呢?那我们再看一段代码吧

NSArray *arrays=[NSArray arrayWithObjects: @“Apple”, @“Google”, @“MircoSoft”, nil];
NSPredicate *pre2 = [NSPredicate predicateWithFormat:@“SELF==‘Apple’”];

上面这段代码是匹配字符串的时候 NSPredicate 需要如何声明

##使用NSPredicate在两个数组之间进行差异筛选

NSArray* array = @[@“aa”,@“bb”];
NSArray* array2 = @[@“aa”,@“bb”,@“cc”,@“dd”];
NSPredicate* thePredicate = [NSPredicate predicateWithFormat:@“NOT(SELF in %@)”,array];
NSArray* arr3 = [array2 filteredArrayUsingPredicate:thePredicate];
NSLog(@“%@“,arr3);

上面的代码输出结果 arr3={@“cc” ,@“dd”}
这样大家就很容易理解了
SELF在前面有介绍过 可以往回翻阅一下

如何使用正则筛选一个数组

NSString *regex = @“^A.+e$”;//以A 开头,以e 结尾的字符。
NSPredicate *pre= [NSPredicate predicateWithFormat:@“SELF MATCHES %@“, regex];
if([pre evaluateWithObject: @“Apple”]){
    printf(“YES\n”);
}else{
    printf(“NO\n”);
}

##关于NSPredicate的其他说明和注意事项,以及技巧

  1. 动态属性名
  2. 假如你的代码如下
NSPredicate *p = [NSPredicate predicateWithFormat:@“name = %@“, @“name1”]; 

显然代码没有任何问题,但是这个不是最好的写法我建议如下写法:

NSPredicate *preTemplate = [NSPredicate predicateWithFormat:@“name==$NAME”];
NSDictionary *dic=[NSDictionary dictionaryWithObjectsAndKeys:
@“name1”, @“NAME”,nil];
NSPredicate *pre=[preTemplate predicateWithSubstitutionVariables: dic];

这样看上去可能会让代码逻辑更清晰。

当过滤条件字段都是动态的时候

NSString *key = @“name”;     
NSString *value = @“name1”;      
NSPredicate *p = [NSPredicate predicateWithFormat:@“%@ = %@“, key, value];

然后当你执行到第三行的时候代码就会报错!
逻辑上没错误啊!!!为什么会出错呢?
NSPredicate要自动添加引号,所以最后得到的格式应该是@“’name’ = ‘name1’”。明显不对。要做的就是:

NSPredicate *p = [NSPredicate predicateWithFormat:@“%K = %@“, key, value];

##总结
NSPredicate 的简单的使用就介绍到这里,这里有些都是从网络上其他人的额博客转过来的内容,我自己加以修改和一些自己的理解。希望可以帮到大家。
转载:NSPredicate谓词的用法 数组过滤

贴一段实用代码

Cocoa用NSPredicate描述查询的方式,原理类似于在数据库中进行查询
计算谓词:
//基本的查询
NSPredicate *predicate;
predicate = [NSPredicate predicateWithFormat: @“name == ‘Herbie’”];
    BOOL match = [predicate evaluateWithObject: car];
    NSLog (@“%s”, (match) ? “YES” : “NO”);

//在整个cars里面循环比较
    predicate = [NSPredicate predicateWithFormat: @“engine.horsepower > 150”];
    NSArray *cars = [garage cars];
    for (Car *car in [garage cars]) {
        if ([predicate evaluateWithObject: car]) {
            NSLog (@“%@“, car.name);
        }
    }

//输出完整的信息
    predicate = [NSPredicate predicateWithFormat: @“engine.horsepower > 150”];
    NSArray *results;
    results = [cars filteredArrayUsingPredicate: predicate];
    NSLog (@“%@“, results);

//含有变量的谓词
    NSPredicate *predicateTemplate = [NSPredicate predicateWithFormat:@“name == $NAME”];
    NSDictionary *varDict;
    varDict = [NSDictionary dictionaryWithObjectsAndKeys:
               @“Herbie”, @“NAME”, nil];
    predicate = [predicateTemplate predicateWithSubstitutionVariables: varDict];
    NSLog(@“SNORGLE: %@“, predicate);
    match = [predicate evaluateWithObject: car];
  NSLog (@“%s”, (match) ? “YES” : “NO”);
//注意不能使用$VARIABLE作为路径名,因为它值代表值

//谓词字符窜还支持c语言中一些常用的运算符  
    predicate = [NSPredicate predicateWithFormat:
                 @“(engine.horsepower > 50) AND (engine.horsepower < 200)”];
    results = [cars filteredArrayUsingPredicate: predicate];
    NSLog (@“oop %@“, results);
   
    predicate = [NSPredicate predicateWithFormat: @“name < ‘Newton’”];
    results = [cars filteredArrayUsingPredicate: predicate];
    NSLog (@“%@“, [results valueForKey: @“name”]);

//强大的数组运算符
    predicate = [NSPredicate predicateWithFormat:
                 @“engine.horsepower BETWEEN { 50, 200 }”];
    results = [cars filteredArrayUsingPredicate: predicate];
    NSLog (@“%@“, results);
   
    NSArray *betweens = [NSArray arrayWithObjects:
                         [NSNumber numberWithInt: 50], [NSNumber numberWithInt: 200], nil];
    predicate = [NSPredicate predicateWithFormat: @“engine.horsepower BETWEEN %@“, betweens];
    results = [cars filteredArrayUsingPredicate: predicate];
    NSLog (@“%@“, results);
    predicateTemplate = [NSPredicate predicateWithFormat: @“engine.horsepower BETWEEN $POWERS”];
    varDict = [NSDictionary dictionaryWithObjectsAndKeys: betweens, @“POWERS”, nil];
    predicate = [predicateTemplate predicateWithSubstitutionVariables: varDict];
    results = [cars filteredArrayUsingPredicate: predicate];
    NSLog (@“%@“, results);

//IN运算符
    predicate = [NSPredicate predicateWithFormat: @“name IN { ‘Herbie’, ‘Snugs’, ‘Badger’, ‘Flap’ }”];
    results = [cars filteredArrayUsingPredicate: predicate];
    NSLog (@“%@“, [results valueForKey: @“name”]);
    predicate = [NSPredicate predicateWithFormat: @“SELF.name IN { ‘Herbie’, ‘Snugs’, ‘Badger’, ‘Flap’ }”];
    results = [cars filteredArrayUsingPredicate: predicate];
    NSLog (@“%@“, [results valueForKey: @“name”]);
   
    names = [cars valueForKey: @“name”];
    predicate = [NSPredicate predicateWithFormat: @“SELF IN { ‘Herbie’, ‘Snugs’, ‘Badger’, ‘Flap’ }”];
    results = [names filteredArrayUsingPredicate: predicate];//这里限制了SELF的范围
    NSLog (@“%@“, results);
//BEGINSWITH,ENDSWITH,CONTAINS

//附加符号,[c],[d],[cd],c表示不区分大小写,d表示不区分发音字符,cd表示什么都不区分
    predicate = [NSPredicate predicateWithFormat: @“name BEGINSWITH ‘Bad’”];
    results = [cars filteredArrayUsingPredicate: predicate];
    NSLog (@“%@“, results);
   
    predicate = [NSPredicate predicateWithFormat: @“name BEGINSWITH ‘HERB’”];
    results = [cars filteredArrayUsingPredicate: predicate];
    NSLog (@“%@“, results);
   
    predicate = [NSPredicate predicateWithFormat: @“name BEGINSWITH[cd] ‘HERB’”];
    results = [cars filteredArrayUsingPredicate: predicate];
    NSLog (@“%@“, results);

//LIKE运算符(通配符)
    predicate = [NSPredicate predicateWithFormat: @“name LIKE[cd] ‘*er*’”];
    results = [cars filteredArrayUsingPredicate: predicate];
    NSLog (@“%@“, results);
   
    predicate = [NSPredicate predicateWithFormat: @“name LIKE[cd] ‘???er*’”];
    results = [cars filteredArrayUsingPredicate: predicate];
    NSLog (@“%@“, results);
05/07/2015 16:14 下午 posted in  apple

关于JSONModel用法的一些简单介绍

早先我们设计一个Model的时候其实就是将一个字典NSDictionary中的Value有针对性的一个一个取出然后赋值;
eg:

self.id = [jsonDict objectForKey:@“id”];
self.name = [jsonDict objectForKey:@“name”];
self.profileImageBig = [jsonDict objectForKey:@“profile_image_big”];
self.profileImageSmall = [jsonDict objectForKey:@“profile_image_small”];
self.profileImageSquare = [jsonDict objectForKey:@“profile_image_square”];
self.firstName = [jsonDict objectForKey:@“firstName”];
self.familyName = [jsonDict objectForKey:@“familyName”];
self.age = [jsonDict objectForKey:@“age”];

当然我们有更好的方法,例如有很多第三方的解析库,这里我们使用JSONModel来进行JSON的实例化.

##Modle属性命名的注意地方

  • 我们只需要设置对应的Property熟悉即可,这个属性的命名 可以严格按照NSDictionary中的key名对应。
    eg:
{
  “id” : 1,
  “name”: Jon,
}

@interface MyModel: JSONModel
@property (strong, nonatomic) NSString* id;
@property (strong, nonatomic) NSString* name;

@end
  • 也可以自己自由命名Property 属性名,不过要在实现方法里实现方法:+ (JSONKeyMapper*)keyMapper
{
  “id” : 1,
  “name”: Jon,
}

@interface MyModel: JSONModel
@property (strong, nonatomic) NSString* uid;
@property (strong, nonatomic) NSString* username;
@end

#import “MyModel.h”
@implementation MyModel
+ (JSONKeyMapper*)keyMapper {
    NSDictionary *map = @{ @“id”: @“uid”, @“name”: @“username” };
    return [[JSONKeyMapper alloc] initWithDictionary:map];
}
@end

##属性命名类型
在我们不实用JSONModel,自己定义一个模型的时候当你要声明类型的时候还需要在实现方法里进行类型转换,比如

@property (nonatomic, assign) NSInteger id;;

self.id = [jsonDict objectForKey:@“id”] IntegerValue];

使用JSONModel的时候可以不必关心实现方法,你只管声明你需要的数据类型即可:

{
  “purchaseDate” : “2012-11-26T10:00:01+02:00”,
  “blogURL” : “http://www.touch-code-magazine.com”
}

@interface SmartModel: JSONModel
 
@property (strong, nonatomic) NSDate* purchaseDate;
@property (strong, nonatomic) NSURL* blogUrl;
 
@end

ps:当然如果你强制讲一个本是NSString的文笔声明为一个int 这种问题我们不做讨论。

##多层封装和对象

  • 对于一个NSDictionary如果一个value也是一个NSDictionary,那么如果你或许会考虑将这个子NSDictionary声明为一个对象类.
{
  “idImage”: 1, 
  “name”: “house.jpg”, 
  “copyright”: {“author”:”Marin Todorov”, “year”:2012} 
}

@interface CopyModel: JSONModel
 
@property (strong, nonatomic) NSString* author;
@property (assign, nonatomic) int year;
 
@end


#import “CopyModel.h”
@interface ImageModel: JSONModel
 
@property (assign, nonatomic) int idImage;
@property (strong, nonatomic) NSString* name;
@property (strong, nonatomic) CopyModel* copyright;
 
@end

上面的例子就是这样的一个情况,当然每个类的实现方法都按照自己的声明进行自由实现。

  • 那么如果这个value是一个包含字典的数组,例如:
{
  “idImage”: 1, 
  “name”: “house.jpg”, 
  “copyrights”: [{“author”:”Marin Todorov”, “year”:2012},{“author”:”Marin Todorov”, “year”:2012},{“author”:”Marin Todorov”, “year”:2012},...] 
}

@protocol CopyModel @end
@interface CopyModel: JSONModel
@property (strong, nonatomic) NSString* author;
@property (assign, nonatomic) int year;
 
@end

#import “CopyModel.h”
@interface ImageModel: JSONModel
 
@property (assign, nonatomic) int idImage;
@property (strong, nonatomic) NSString* name;
@property (strong, nonatomic) NSArray<CopyModel>* copyrights;
 
@end

上面的情况 要注意的地方是

@protocol CopyModel @end

这个协议是为了匹配这个对象命名的如果没有则会提示报错。

###将下一层属性提到上一层解析
eg

{
  “order_id”: 104,
  “order_details” : [
    {
      “name”: “Product#1”,
      “price”: {
        “usd”: 12.95
      }
    }
  ]
}

对于上面的这样一个JSON 你想把价格_usd_提到上一个对象
可以使用 *.*联系到一起

@interface OrderModel : JSONModel
@property (assign, nonatomic) int id;
@property (assign, nonatomic) float price;
@property (strong, nonatomic) NSString* productName;
@end

@implementation OrderModel

+(JSONKeyMapper*)keyMapper
{
  return [[JSONKeyMapper alloc] initWithDictionary:@{
    @“order_id”: @“id”,
    @“order_details.name”: @“productName”,
    @“order_details.price.usd”: @“price”
  }];
}

@end

##可选属性
在这样的一个场景,当API返回的接口中某个字段不是必选返回的时候,既有值的时候返回,没有的时候这个key就没有,还有一种情况是返回的值是一个空对象, 这种情况下,如果我们上上面的写法声明属性会发现JSONModel无法解析,这时候就需要用到 Optional
eg:

//this property is required
@property (strong, nonatomic) NSString* string;
 
//this one’s optional
@property (strong, nonatomic) NSNumber<Optional>* number;

##忽略属性
对于一些属性可以忽略解析的,可以使用*Ignore_进行忽略

{
  “id”: “123”,
  “name”: null
}

@interface ProductModel : JSONModel
@property (assign, nonatomic) int id;
@property (strong, nonatomic) NSString<Ignore>* customProperty;
@end

@implementation ProductModel
@end

当然也可以在实现方法里复写类方法

@implementation ProductModel
+(BOOL)propertyIsOptional:(NSString*)propertyName
{
	 if ([propertyName isEqualToString:@“name”]) {
        return YES;
    }
  return NO;
}
@end

参考:JSONModel简介 ,Magical Data Modelling Framework for JSON

04/20/2015 09:51 上午 posted in  apple