// ********************** 判断数组元素是否为空 **********************
NSString *element = [array objectAtIndex:2];
if ((NSNull *)element == [NSNull null]) {
}
今天做项目的时候就遇到,要判断数组元素是否为空,我的以下写法,都无效
if(!element)
if([element length]>0)
if(element== NULL)
if(element == Nil)
// ********************** 委托的格式 **********************
1 定义协议
@protocol uploadUserInfoDelegate <NSObject>
@required
-(void)uploadCallBack:(NSInteger )code msg:(NSString *)msg;
@end
2 定义委托属性
@property (nonatomic, weak) id<uploadUserInfoDelegate> delegate;
3 调用
if ([self.delegate respondsToSelector:@selector(uploadCallBack:msg:)]) {
[self.delegate uploadCallBack:111 msg:@"mmm"];
}
4 实现方遵循协议
传递委托对象实现协议方法
@interface ViewController () <uploadUserInfoDelegate>
obj.delegate = self;
-(void)uploadCallBack:(NSInteger )code msg:(NSString *)msg;
// ********************** block格式 **********************
1. 直接定义成属性
@property (copy, nonatomic) void (^submitUserInfoBlock)(NSString* gender, NSInteger age, NSString* hobbys);
2. typedef定义成类型 方便传参
typedef void (^Callback)(NSInteger code, NSString* msg);
- (void)uploadUserInfoWith:(NSString*)name callBack:(Callback) callback;
3. typedef 定义类型 再合成属性
typedef void(^headerInputBlock)(NSString *inputStr);
@property(nonatomic,copy)headerInputBlock inputBlock;
4. 直接定义Block形参
- (AFHTTPRequestOperation *)httpGetWithMethodName:(NSString *) methodName
param:(id)parameters
response:(void (^)(id dict,NSError *error))callback;
// ********************** 创建单例 **********************
+ (ViewController *)shared
{
static ViewController* instance;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
instance = [[ViewController alloc] init];
});
return instance;
}
// ********************** block 中的weakself **********************
block对于其变量都会形成strong reference,对于self也会形成strong reference,而如果self本身对block也是
strong reference的话,就会形成 strong reference
循环,造成内存泄露,为了防止这种情况发生,在block外部应该创建一个week(__block) reference。
所以在block内如果有self的话,一般都会在block外面加一句_block typeof(self)weakself
= self;
__block typeof(self) weakself = self;
[self methodThatTakesABlock:^ {
[weakself doSomething];
}
// ********************** 类别的使用category可以扩展系统类和自定义类**********************
1. 新建类别文件NSString+Util
2.添加方法
@interface NSString (Util)
- (void)hello;
+ (void) say;
@end
3.实现方法
#import "NSString+Util.h"
@implementation NSString (Util)
- (void)hello {
NSLog(@"hello");
}
+ (void)say {
NSLog(@"static say.");
}
@end
4.在其它类中导入并调用
#import "NSString+Util.h"
NSString* mm = @"aa";
[mm hello];
[NSString say];
// ***************************** 获取系统时间的时分秒 *****************************
NSDate *now = [[NSDate alloc] init];
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
//设定时间格式,这里可以设置成自己需要的格式
[dateFormatter setDateFormat:@"yyyy-MM-dd HH:mm:ss"];
NSString* dateString = [dateFormatter stringFromDate:now];
// ***************************** 定义宏weakSelf *****************************
#define WS(weakSelf) __weak __typeof(&*self)weakSelf = self;
// ***************************** ViewController的代码分组 *****************************
#pragma mark - Getters and Setters
#pragma mark - Init and Dealloc
#pragma mark - ViewController Lifecycle
#pragma mark - UITableViewDataSource
#pragma mark - UITableViewDelegate
#pragma mark - CustomDelegate
#pragma mark - Custom View
#pragma mark - View Event
#pragma mark - Event Response
#pragma mark - GestureRecognizer
#pragma mark - Private Methods
// ***************************** xcode 有用的 tips *****************************
// TODO: 判断登陆状态,如果没有登录,显示登录界面。
// FIXME: 判断登陆状态,如果没有登录,显示登录界面
// ???: How does this work?
// !!!: Verify that all objects are accounted for
#warning This selector will not fire unless…
// ***************************** xcode @synthesize什么时候不自动合成 *****************************
同时重写了setter和getter时
重写了只读属性的getter时
使用了@dynamic时
在 @protocol 中定义的所有属性
在 category 中定义的所有属性
重载的属性
除了后三条,对其他几个我们可以总结出一个规律:当你想手动管理@property的所有内容时,你就会尝试通过实现@property的所有“存取方法”(the
accessor methods)或者使用@dynamic来达到这个目的,这时编译器就会认为你打算手动管理@property,于是编译器就禁用了autosynthesis(自动合成)
当你同时重写了setter和getter时,系统就不会生成ivar(实例变量/成员变量)。这时候有两种选择:
1.手动创建ivar
2.使用@synthesize foo = _foo;,关联@property与ivar。
// ***************************** UIToolBar *****************************
1.工具栏UIToolBar管理了一组UIBarButtonItem,
UIBarButtonItem不能随意摆放在屏幕上,它不是继承自UIView。它由导航栏,标签栏或工具栏管理。
栏按钮条目UIBarButtonItem存储工具栏和导航栏的按钮的属性,它本身不是按钮。
2. UIBarButtonItem有两种类型:按钮元素,空白元素。
UIBarButtonSystemItem枚举表示着不同的系统预设UIBarButtonItem;
UIBarButtonSystemItemFixedSpace类型表示一段空白,需要设置它的宽度值;可以使用它替换需要隐藏的项,以保持位置不变;
在UIToolBar开头和末尾添加UIBarButtonSystemItemFlexibleSpace会使其它项有不同有水平对齐方式;
3.
初始化一个用于控制间距的UIBarButtonItem实例negativeSpacer,并设置negativeSpacer的width属性的值,设为-5的时候,正好可以使按钮与屏幕边界值为0
UIBarButtonItem *negativeSpacer = [[UIBarButtonItem alloc]
initWithBarButtonSystemItem:UIBarButtonSystemItemFixedSpace
target:nil action:nil];
/**
* width为负数时,相当于btn向右移动width数值个像素,由于按钮本身和边界间距为5pix,所以width设为-5时,间距正好调整
* 为0;width为正数时,正好相反,相当于往左移动width数值个像素
*/
negativeSpacer.width = -5;
leftItemsSupplementBackButton 设置是否只显示你自定义的Backbuttuon默认NO
显示自定义的
// ***************************** Category *****************************
、实现类别
同实现类相似,实现方法即可
2、类别的局限性
1.类别不能添加新的实例变量
2.命名冲突,如果类别中方法和类中已有方法同名,则类别具有更高优先级
3 类别的作用
1.将类的实现分散到多个不同文件或多个不同框架中
2.创建私有方法的前向引用
3.向对象添加非正式协议
4 利用类别分散实现
利用类别可以将类的方法分散到多个源文件中
特别指出的是:类别可以访问其继承的类的实例变量
在使用一个方法时,对象的方法是在接口中声明、父类中声明、还是类别中声明并不重要
类别不仅可以分散实现到不同源文件,也可跨框架
5、使用类别创建前向引用
虽然可以实现未声明的方法,但是编译器会提出警告
通过类别可以提供声明,而且,声明的方法不必要一定在类别的实现中实现,也可以在类的实现中实现
6、非正式协议和委托类别
委托(delegage)是一种对象,另一个类的对象会要求委托对象执行它的某些操作
委托对象接受其它对象对它的特定方法的调用
其实就是委托对象必须实现别的对象调用的方法,与接口类似
7、 ITunesFinder项目
8 、委托和类别
委托和类别有什么关系?委托强调类别的另一种应用:被发送给委托对象的方法可以声明为一个NSObject的类别
创建一个NSObject的类别称为“创建一个非正式协议”
9、响应选择器
选择器只是一个方法名称,可以使用@selector()预编译指令指定选择器,其中方法名位于圆括号中,但它以OC运行时使用的特殊方式编码,以快速执行查询
NSObject提供了一个respondsToSelector的方法,询问对象以确定其是否实现某个特定消息
10、选择器的其他应用
选择器可以被传递,可以作为方法参数,甚至可以作为实例变量存储
// ***************************** NSIndexPath *****************************
1. indexPath.row 适用TableView
2. indexPath.item 适用于CollectionView
3. 设置UITableViewStyleGrouped可以让header和footer随tableview一起滚动
// ***************************** navigationBar and navigationItem *****************************
self.navigationItem.leftBarButtonItem = nil; //隐藏导航栏回退item
self.navigationController.navigationBar.hidden = YES; //隐藏整个导航栏
// ***************************** Masonry *****************************
Masonry NSAutoLayout 说明
left NSLayoutAttributeLeft 左侧
top NSLayoutAttributeTop 上侧
right NSLayoutAttributeRight 右侧
bottom NSLayoutAttributeBottom 下侧
leading NSLayoutAttributeLeading 首部
trailing NSLayoutAttributeTrailing 尾部
width NSLayoutAttributeWidth 宽
height NSLayoutAttributeHeight 高
centerX NSLayoutAttributeCenterX 横向中点
centerY NSLayoutAttributeCenterY 纵向中点
baseline NSLayoutAttributeBaseline 文本基线
// ***************************** instancetype - id *****************************
①instancetype可以返回和方法所在类相同类型的对象,id只能返回未知类型的对象;
②instancetype只能作为返回值,不能像id那样作为参数
// ***************************** tableView
动态Cell *****************************
{
BOOL cellIsSelected;
NSIndexPath* _indexPath;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell* cell = [tableView cellForRowAtIndexPath:indexPath];
if ([cell isSelected] && cellIsSelected == NO) {
cellIsSelected = YES;
_indexPath = indexPath;
} else {
cellIsSelected = NO;
}
[tableView beginUpdates];
[tableView endUpdates];
}
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
if(cellIsSelected && _indexPath.row == indexPath.row) {
return 50 * 2.0;
}
return 50;
}
// ***************************** ios 异常崩溃
处理 *****************************
使用第三方库 UncaughtExceptionHandler
可以检测出常见错误,并友好的提示用户
例如
1.NSArray、NSDictionary、NSString、KVC等问题引起的闪退。
2.解决NSObject performSelector找不到selector引起的闪退。
使用方法:
1、首先需要在appDelegate中使用InstallUncaughtExceptionHandler()用于监听
2、添加UncaughtExceptionHandler这个类
iOS SDK提供的函数是NSSetUncaughtExceptionHandler来进行异常处理。但是无法处理内存访问错误、重复释放等错误,因为这些错误发送的SIGNAL。所以需要处理这些SIGNAL
4. SignalHandler不要在debug环境下测试。因为系统的debug会优先去拦截。我们要运行一次后,关闭debug状态。应该直接在模拟器上点击我们build上去的app去运行。而UncaughtExceptionHandler可以在调试状态下捕捉
// ***************************** 指针和引用的区别 *****************************
1. 引用在语言内部用指针实现(如何实现?)。
2. 对一般应用而言,把引用理解为指针,不会犯严重语义错误。
3. 引用是操作受限了的指针(仅容许取内容操作)
// ***************************** iOS 集合的深复制与浅复制 *****************************
1. 在非集合类对象中:对immutable对象进行copy操作,是指针复制,mutableCopy操作时内容复制;对mutable对象进行copy和mutableCopy都是内容复制。用代码简单表示如下:
[immutableObject copy] // 浅复制
[immutableObject mutableCopy] //深复制
[mutableObject copy] //深复制
[mutableObject mutableCopy] //深复制
2. 在集合类对象中,对immutable对象进行copy,是指针复制,mutableCopy是内容复制;对mutable对象进行copy和mutableCopy都是内容复制。但是:集合对象的内容复制仅限于对象本身,对象元素仍然是指针复制。用代码简单表示如下:
[immutableObject copy] // 浅复制
[immutableObject mutableCopy] //单层深复制
[mutableObject copy] //单层深复制
[mutableObject mutableCopy] //单层深复制
// ********** ios文件夹:Documents, Library和 tmp
。Library包含Caches、Preferences目录 **************
Documents:苹果建议将程序创建产生的文件以及应用浏览产生的文件数据保存在该目录下,iTunes备份和恢复的时候会包括此目录
Library:存储程序的默认设置或其它状态信息;
Library/Caches:存放缓存文件,保存应用的持久化数据,用于应用升级或者应用关闭后的数据保存,不会被itunes同步,所以为了减少同步的时间,可以考虑将一些比较大的文件而又不需要备份的文件放到这个目录下。
tmp:提供一个即时创建临时文件的地方,但不需要持久化,在应用关闭后,该目录下的数据将删除,也可能系统在程序不运行的时候清除。
1、Documents目录
您应该将所有的应用程序数据文件写入到这个目录下。
这个目录用于存储用户数据或其它应该定期备份的信息。
保存由应用程序产生的文件或者数据,例如:涂鸦程序生成的图片,游戏关卡记录
iCloud会自动备份Document中的所有文件。
上架注意 如果保存了从网络上下载的文件,在上架审批的时候会被拒!
2、AppName.app目录:这是应用程序的程序包目录,包含应用程序的本身。由于应用程序必须经过签名,所以您在运行时不能对这个目录中的内容进行修改,否则可能会使应用程序无法启动。
3、Library目录:这个目录下有两个子目录:Caches
和 Preferences
Preferences 目录:包含应用程序的偏好设置文件。您不应该直接创建偏好设置文件,而是应该使用NSUserDefaults类来取得和设置应用程序的偏好.
系统偏好,用户偏好,通过[NSUserDefaults standarDefaults]来直接操作
Caches 目录:用于存放应用程序专用的支持文件,保存应用程序再次启动过程中需要的信息。
缓存,保存网络下载的文件,后续仍然需要继续使用。例如:网络下载的离线数据
缓存目录中的文件系统不会自动删除,可做离线访问
程序必需要提供一个完善的清除缓存目录的“解决方案”!
4、tmp目录:用于存放临时文件(临时数据),保存应用程序再次启动过程中不需要的信息。
临时文件,保存在tmp中的文件,系统会自动回收,譬如磁盘空间紧张、重新启动手机、应用退出后删除
程序员不需要管tmp文件夹的释放
// ***************************** UIApplication openURL *****************************
1.设置icon上的数字图标
//设置主界面icon上的数字图标,在2.0中引进,缺省为0
[UIApplicationsharedApplication].applicationIconBadgeNumber = 4;
2.设置摇动手势的时候,是否支持redo,undo操作
//摇动手势,是否支持redo undo操作。
//3.0以后引进,缺省YES
[UIApplicationsharedApplication].applicationSupportsShakeToEdit =YES;
3.判断程序运行状态
//判断程序运行状态,在2.0以后引入
/*
UIApplicationStateActive,
UIApplicationStateInactive,
UIApplicationStateBackground
*/
if([UIApplicationsharedApplication].applicationState ==UIApplicationStateInactive){
NSLog(@"程序在运行状态");
}
4.阻止屏幕变暗进入休眠状态
//阻止屏幕变暗,慎重使用,缺省为no 2.0
[UIApplicationsharedApplication].idleTimerDisabled =YES;
慎重使用本功能,因为非常耗电。
5.显示联网状态
//显示联网标记 2.0
[UIApplicationsharedApplication].networkActivityIndicatorVisible =YES;
6.在map上显示一个地址
NSString* addressText [email protected]"1 Infinite Loop, Cupertino, CA 95014";
// URL encode the spaces
addressText = [addressTextstringByAddingPercentEscapesUsingEncoding:NSASCIIStringEncoding];
NSString* urlText = [NSStringstringWithFormat:@"http://maps.google.com/maps?q=%@", addressText];
[[UIApplicationsharedApplication]openURL:[NSURLURLWithString:urlText]];
7.发送电子邮件
NSString *recipients [email protected]"mailto:[email protected][email protected],[email protected]&subject=Hello from California!";
NSString *body [email protected]"&body=It is raining in sunny California!";
NSString *email = [NSStringstringWithFormat:@"%@%@", recipients, body];
email = [emailstringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
[[UIApplicationsharedApplication]openURL:[NSURLURLWithString:email]];
8.打电话到一个号码
// Call Google 411
[[UIApplicationsharedApplication]openURL:[NSURLURLWithString:@"tel://8004664411"]];
9.发送短信
// Text to Google SMS
[[UIApplicationsharedApplication]openURL:[NSURLURLWithString:@"sms://466453"]];
10.打开一个网址
// Lanuch any iPhone developers fav site
[[UIApplicationsharedApplication]openURL:[NSURLURLWithString:@"http://itunesconnect.apple.com"]];
// ***************************** AFNetWorking https SSL认证 *****************************
// ***************************** ios File IO *******************************
数组、字典只能将BOOL、NSNumber、NSString、NSData、NSDate、NSArray、NSDictionary写入属性列表plist文件
NSFileHandle类主要对文件内容进行读取和写入操作
NSFileManager类主要对文件的操作(删除、修改、移动、复制等等)
// ***************************** 加载本地html *******************************
- (void)loadExamplePage:(UIWebView*)webView {
NSString* htmlPath = [[NSBundle mainBundle] pathForResource:@"test" ofType:@"html"];
NSString* appHtml = [NSString stringWithContentsOfFile:htmlPath encoding:NSUTF8StringEncoding error:nil];
NSURL *baseURL = [NSURL fileURLWithPath:htmlPath];
[webView loadHTMLString:appHtml baseURL:baseURL];
}
- (void)loadDocument:(NSString*)docName {
NSString* path = [[NSBundle mainBundle] pathForResource:@"test" ofType:@"html"];
NSURL *url = [NSURL fileURLWithPath:path];
NSURLRequest *request = [NSURLRequest requestWithURL:url];
self.webView.scalesPageToFit = YES;
[self.webView loadRequest:request];
}
// ***************************** UIScrollView里面嵌套UITableView这种结构是否合理? *******************************
Q: 类似网易新闻和lofter这种多标签滚动切换的效果,我以为是在scrollview上添加tableview来实现的,但这样实现感觉会导致ViewController臃肿不堪,实现delegate和datasource也比较混乱;想听听大家对于架构这种界面有什么样的建议,能提高代码的复用还有把代码剥离放到合适的地方;真的好想写出结构清晰美观的代码啊思密达!
A: 每个标签对应的列表可以是一个viewController,它负责这个列表的内容和一切的交互。scrollView里装的是viewController.view。
scrollView所在的viewController可以称之为containerViewController,实际上起到了NavigationController之类的容器作用。而具体的内容,可以称之为contentViewController。
它的好处:
同一个contentVC可以在不同的容器中自由地拆下和装上,降低耦合,或者如题主所说“能提高代码的复用还有把代码剥离放到合适的地方”
可以做到动态地调整contentVC的数量,样式也可以各不相同,只要是vc即可,题主图中的网易新闻无疑是这么做的佼佼者
可以通过“两块木板过河”这样的原理,使用三个view来作为contentVC和scrollView的中间层,做到不论有多少个contentVC(比如网易新闻中添加很多标签),同时加载在scrollView上的都只有3个
肯定还有,我一时没想到。。。
总的来说,这种结构可以称得上“清晰美观”,但也要看实现者的水准,做得不好反而会带来很多问题,做得好的。。。你看网易新闻多好用:)
/*************************** 动态口令 ****************************/
每次认证时令牌与服务器分别根据同样的密钥,同样的随机数和同样的算法计算出认证时的动态口令,
动态密码的密码其实不是随机的,而是由规律的。当下动态密码分为两类,时间性和事件性。何为时间性动态密码?该类令牌产出动态密码是以时间为参数的,而事件性一般以使用次数为参数的。我们以时间性动态为主要说明对象。整个验证的过程如下:
1.动态密码令牌产生动态密码以时间和种子为参数,进行迭代,得出动态密码,这里的时间一般是秒数。每个时间性动态密码令牌中会内置一个时钟芯片。
2.服务器校验动态密码。服务器读取系统时间加上种子,以相同的迭代方法得出动态密码,然后双方进行比对。
讲到这边,可能有所怀疑难道令牌的时间和服务器的时间一定会一致吗?我的答案肯定是不一致的。那怎么能检验的过去呢?原来很简单,服务器校验是是在一个时间区间里校验的,比如现在是12:00,服务器会生成11:55-12:05中所有的动态密码,然后和令牌产生的动态密码比对,这样不就解决了时间不一致的问题了。另外服务器会把令牌和服务器相差的时间记录下来,下次检验的会先把这个偏移值记录下来,以减少动态密码迭代次数,这样就完成了另外一个比较重要的功能,偏移值自动调整。
显示Mac隐藏文件的命令:defaults write com.apple.finder AppleShowAllFiles YES
隐藏Mac隐藏文件的命令:defaults write com.apple.finder AppleShowAllFiles NO
输完单击Enter键,退出终端,重新启动Finder就可以了
重启Finder:鼠标单击窗口左上角的苹果标志-->强制退出-->Finder-->重新启动
/*************************** title使用self.navigationItem.title ****************************/
Q:楼主有没有试过,在ViewDidLoad方法中,对self.title和self.navigationItem.title分别进行设置,出现的效果是一样的?
A: 设置self.title会设置导航title,但是如果下面有tabBar,也会设置tabBarItem的title,所以还是单独设置好一些,导航title使用self.navigationItem.title
/*************************** iOS6以后在UILabel显示不同的字体和颜色 ****************************/
NSMutableAttributedString *str = [[NSMutableAttributedString alloc] initWithString:@"Using NSAttributed String"];
[str addAttribute:NSForegroundColorAttributeName value:[UIColor blueColor] range:NSMakeRange(0,5)];
[str addAttribute:NSForegroundColorAttributeName value:[UIColor redColor] range:NSMakeRange(6,12)];
[str addAttribute:NSForegroundColorAttributeName value:[UIColor greenColor] range:NSMakeRange(19,6)];
[str addAttribute:NSFontAttributeName value:[UIFont fontWithName:@"Arial-BoldItalicMT" size:30.0] range:NSMakeRange(0, 5)];
[str addAttribute:NSFontAttributeName value:[UIFont fontWithName:@"HelveticaNeue-Bold" size:10.0] range:NSMakeRange(6, 12)];
[str addAttribute:NSFontAttributeName value:[UIFont fontWithName:@"Courier-BoldOblique" size:30.0] range:NSMakeRange(19, 6)];
self.attrLabel.attributedText = str;
/*************************** xcode中的project.pbxproj冲突怎么解决 ****************************/
1 添加或改动文件布局时先更新,改完后要立即提交,团队成员都遵照这个约定。
/*************************** translucent IOS7
导航栏是否是半透明设置,子视图是否从屏幕 0, 0开始 ****************************/
self.navigationController.navigationBar.translucent = NO;
/*************************** 保持程序在后台长时间运行 ****************************/
iOS上的VOIP程序是肯定能后台监测到来电并提示用户的
VOIP的SIP报文走的是TCP通道,而语音报文走的是UDP通道。
在iOS平台中,NSStream即为TCP,并且NSStream有一个VOIP属性,如果设置了,那么你的程序处于后台时候,系统会托管你这个NSStream通道,并保持和服务器连接的畅通,如果这个时候服务器通过这个NSSream(TCP
socket)给客户端发送了数据,系统会激活你处于后台的程序运行10秒钟已处理这个报文,你可以在这个时候通过LocalNotification来提示用户有来电。
/*************************** 动态计算文字的高度 ****************************/
NSDictionary *attributes = @{NSFontAttributeName: [UIFont systemFontOfSize:16.0]}
CGSize size = [content boundingRectWithSize:CGSizeMake(UI_SCREEN_WIDTH, CGFLOAT_MAX) o
ptions: NSStringDrawingUsesFontLeading | NSStringDrawingUsesLineFragmentOrigin attributes:attributes context:nil].size;
/*************************** 打开其它app ****************************/
使用[[UIApplication sharedApplication] canOpenURL:instagramURL];来判断是否已安装该APP,
使用[[UIApplication sharedApplication] openURL:fansPageURL];来打开该APP,若未安装,
则默认在safari中打开相应页面.
1. source app
NSURL *sourcePageURL;
sourcePageURL = [NSURL URLWithString:[NSString stringWithFormat:@"joejoe://%@", @"aaa"]]; //不能有空格
[[UIApplication sharedApplication] openURL:sourcePageURL];
2.target app
2.1 在taget->info->URL Types->URL Schemes设置name为mbc2m
// 获取发送过来的值
- (BOOL)application:(UIApplication *)application openURL:(NSURL *)url sourceApplication:(NSString *)sourceApplication annotation:(id)annotation
{
NSString* str = [[url host] stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
}
/**************************** 模拟用户触发事件 **************************/
UIControl有一个sendActionsForControlEvents消息,可以使用它手动触发控件事件:
[button sendActionsForControlEvents:UIControlEventTouchUpInside]
[button sendAction:<#(nonnull SEL)#> to:<#(nullable id)#> forEvent:<#(nullable UIEvent *)#>]
/********************* 编码问题导致NSURL初始化一直为null的解决办法设置utf8编码
**********************/
NSURL *url = [NSURL URLWithString:[urlString stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]];
/********************* NSDictionary转json str **********************/
- (NSString *)toJSONorNSString:(id )o
{
NSData *data=[NSJSONSerialization dataWithJSONObject:o options:NSJSONReadingMutableLeaves|NSJSONReadingAllowFragments error:nil];
if (data == nil) {
return nil;
}
NSString *str=[[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
return str;
}
/***************************** MVVM ******************************/
在MVC的基础上,把C拆出一个ViewModel专门负责数据处理的事情,就是MVVM。然后,为了让View和ViewModel之间能够有比较松散的绑定关系,于是我们使用ReactiveCocoa,因为苹果本身并没有提供一个比较适合这种情况的绑定方法。iOS领域里KVO,Notification,block,delegate和target-action都可以用来做数据通信,从而来实现绑定,但都不如ReactiveCocoa提供的RACSignal来的优雅,如果不用ReactiveCocoa,绑定关系可能就做不到那么松散那么好,但并不影响它还是MVVM。
/***************************** 数组不转化成实体类的好处 ******************************/
数组内容的转化成本较高:数组里面每项都要转化成Item对象,如果Item对象中还有类似数组,就很头疼。
转化之后的数据在大部分情况是不能直接被展示的,为了能够被展示,还需要第二次转化。
只有在API返回的数据高度标准化时,这些对象原型(Item)的可复用程度才高,否则容易出现类型爆炸,提高维护成本。
调试时通过对象原型查看数据内容不如直接通过NSDictionary/NSArray直观。
同一API的数据被不同View展示时,难以控制数据转化的代码,它们有可能会散落在任何需要的地方。