1.销毁变量技巧.
学习XMPP的时候学到的一个很优雅的销毁和置nil方法:
- (void)setupStream;//对应着初始化stream
- (void)teardownStream;//对应着销毁stream
- (void)teardownStream//将相关的变量销毁,看见了没,remove deactivate dieconnect = nil
{
[xmppStreamremoveDelegate:self];
[xmppRosterremoveDelegate:self];
[xmppReconnect deactivate];
[xmppRoster deactivate];
[xmppvCardTempModule deactivate];
[xmppvCardAvatarModuledeactivate];
[xmppCapabilities deactivate];
[xmppStreamdisconnect];
xmppStream =nil;
xmppReconnect =nil;
xmppRoster =nil;
xmppRosterStorage =nil;
xmppvCardStorage =nil;
xmppvCardTempModule =nil;
xmppvCardAvatarModule =nil;
xmppCapabilities =nil;
xmppCapabilitiesStorage =nil;
}
- (void)applicationWillTerminate:(UIApplication *)application//应用被关闭的时候也销毁,所以销毁的情况也要注意!
{
DDLogVerbose(@"%@: %@",THIS_FILE, THIS_METHOD);
[selfteardownStream];
}
- (void)dealloc//最常见的啦
{
[selfteardownStream];
}
同样的:
- (void)cleanup
{
[[NSNotificationCenter defaultCenter] removeObserver:self];
[self.containerView removeFromSuperview];
[[[[UIApplication sharedApplication] delegate] window] makeKeyWindow];
[self.window removeFromSuperview];
self.contentViewController = nil;
self.window = nil;
}
- (void)dealloc
{
[self cleanup];
}
总结:不用的变量都要销毁,那内存才可以得以轻松,这是个好习惯,而怎么封装和编码得更漂亮,就得看个人的功底啦!
2.颜色的定义.
#define KCColor(r,g,b) [UIColor colorWithHue:r/255.0 saturation:g/255.0 brightness:b/255.0 alpha:1]
#define kStatusTableViewCellBackgroundColor KCColor(251,251,251)
3.iOS的API也存在嵌套.
sizeToFit的作用就不详说了,查看文档:
- (CGSize)sizeThatFits:(CGSize)size; // return 'best' size to fit given size. does not actually resize view. Default is return existing view size
- (void)sizeToFit; // calls sizeThatFits: with current view bounds and changes bounds size.
注意到 calls sizeThatFits : 这个方法意思是用当前的视图bounds调用方法sizeThatFits去改变bounds的大小,且用当前的视图bounds大小为参数,说明适度的嵌套又好看又方便!
dictionayVariable[keyValue] 就是等于: [dictionaryVariable objectForKey:keyValue]
iOS6以后提供的装箱拆箱:
NSNumber:
原始写法:
NSNumber *value1;
value1 = [NSNumber numberWithInt:12345];
value1 = [NSNumber numberWithFloat:123.45f];
value1 = [NSNumber numberWithDouble:123.45];
value1 = [NSNumber numberWithBool:YES];
便捷写法:
NSNumber *value2;
value2 = @12345;
value2 = @123.45f;
value2 = @123.45;
value2 = @YES;
例子:
NSNumber *piOverSixteen1 = [NSNumber numberWithDouble: ( M_PI / 16 )];
NSString *path1 = [NSString stringWithUTF8String: getenv("PATH")];
可以写成:
NSNumber *piOverSixteen2 = @( M_PI / 16 );
NSString *path2= @( getenv("PATH") );
NSArray:
NSArray *array;
array = @[]; //空数组
array = @[ a ]; //一个对象的数组
array = @[ a, b, c ]; //多个对象的数组
//编译器在处理时:
array = @[ a, b, c ];
//编译器生成的代码:
id objects[] = { a, b, c };
NSUInteger count = sizeof(objects)/ sizeof(id);
array = [NSArray arrayWithObjects:objects count:count];
这里小心的是上面这样写的话编译器无法帮你直面地检查是否有nil值的存在而通过编译
NSDictionary:
NSDictionary *dict;
dict = @{}; //空字典
dict = @{@"key1":@"value1" }; //包含一个键值对的字典
dict = @{ @"key1" : @"value1", @"key2" : @"value", @"key3" : @"value3" }; //包含多个键值对的字典
可以很明显地看到区别就是数组用的是[ ],而字典用的是 { }。
上面讲得都是不可变的,那可变的呢,记得深浅复制吧? 由可变到不可变和不可变到可变都是改变指针的复制,所以:
//采用上述写法构建的容器都是不可变的,如果需要生成可变容器,可以传递-mutableCopy消息。例如
NSMutableArray *mutablePlanets = [@[
@"Mercury", @"Venus", @"Earth",
@"Mars", @"Jupiter", @"Saturn",
@"Uranus", @"Neptune"
] mutableCopy];
NSMutableDictionary *dic=[@{ @"key1" : @"value1", @"key2" : @"value", @"key3" : @"value3" } mutableCopy];
生成可变容器, 传递xxx消息 多好的专业名词!
封装前:冗杂!
constraint = [NSLayoutConstraint constraintWithItem:newView
attribute:NSLayoutAttributeLeading
relatedBy:NSLayoutRelationEqual
toItem:self.view
attribute:NSLayoutAttributeLeading
multiplier:1.0f
constant:20];
[self.view addConstraint:constraint];
constraint = [NSLayoutConstraint constraintWithItem:newView
attribute:NSLayoutAttributeTrailing
relatedBy:NSLayoutRelationEqual
toItem:self.view
attribute:NSLayoutAttributeTrailing
multiplier:1.0f
constant:-20];
[self.view addConstraint:constraint];
constraint = [NSLayoutConstraint constraintWithItem:newView
attribute:NSLayoutAttributeTop
relatedBy:NSLayoutRelationEqual
toItem:self.view
attribute:NSLayoutAttributeTop
multiplier:1.0f
constant:20];
[self.view addConstraint:constraint];
constraint = [NSLayoutConstraint constraintWithItem:newView
attribute:NSLayoutAttributeBottom
relatedBy:NSLayoutRelationEqual
toItem:self.view
attribute:NSLayoutAttributeBottom
multiplier:1.0f
constant:-20];
[self.view addConstraint:constraint];
好的封装方式:
- (void)setEdge:(UIView*)superview view:(UIView*)view attr:(NSLayoutAttribute)attr constant:(CGFloat)constant
{
[superview addConstraint:[NSLayoutConstraint constraintWithItem:view attribute:attr relatedBy:NSLayoutRelationEqual toItem:superview attribute:attr multiplier:1.0 constant:constant]];
}
还有这样的:
- (NSMutableArray*)portraitConstraints:(UIView*)greenView yellowView:(UIView*)yellowView blueView:(UIView*)blueView
{
NSMutableArray* constraintArray = [NSMutableArray array];
[constraintArray addObjectsFromArray:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-20-[greenView]-20-[yellowView(==greenView)]-20-|" options:0 metrics:nil views:NSDictionaryOfVariableBindings(greenView, yellowView)]];
[constraintArray addObjectsFromArray:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|-20-[greenView]-20-[blueView(==greenView)]-20-|" options:0 metrics:nil views:NSDictionaryOfVariableBindings(greenView, blueView)]];
[constraintArray addObjectsFromArray:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|-20-[yellowView]-20-[blueView(==yellowView)]-20-|" options:0 metrics:nil views:NSDictionaryOfVariableBindings(yellowView, blueView)]];
[constraintArray addObjectsFromArray:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-20-[blueView]-20|" options:0 metrics:nil views:NSDictionaryOfVariableBindings(blueView)]];
return constraintArray;
}
好的封装在于:
1.重复的可以用一个来表示:上面的attr
2.约定俗成或者规定的可以直接在函数体里面设置好:上面的的NSLayoutRelationEqual multiplier: 1.0
3.可以语意化:例如上面的superView在语义上是优先级高的所以先作为变量,即时在API上并不是首个变量
有待补充...
6.适当使用宏
上面提到的有颜色方法的定义宏,还有很多字符串等等的操作都可以定义成宏,并写在一个.h文件中
定义:
/**
@brief 判断NSString是否为空
*/
#define isStringEmpty(str) ((str) == nil || [(str) isKindOfClass:[NSNull class]] || [(str) isEqual:@""])
使用:
if (money == 0 && isStringEmpty(serverId) && isStringEmpty(outId) && !dic &&([dic count] == 0) )
{
//do something.
}
比白白写一个 if 判断语句强多了吧!我经常说的要提高代码的质量,就是如此嘛。
7.“时机”的控制
- (void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration
{
NSLog(@"UIViewController will rotate to Orientation: %d", toInterfaceOrientation);
}
- (void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation
{
NSLog(@"did rotated to new Orientation, view Information %@", self.view);
}
will did 这种“时机”性的方法,要细细品味,为什么要如此做
待续: