@class vs. #import,两种方式的讨论

很多刚开始学习iOS开发的同学可能在看别人的代码的时候会发现有部分#import操作写在m文件中,而h文件仅仅使用@class进行声明,不禁纳闷起来,为什么不直接把#import放到h文件中呢?

这是因为h文件在修改后,所有import该h文件的所有文件必须重新build,因此,如果把#import写在h文件中,import该h文件的文件也就会产生不必要的编译,增加编译时间,特别是在项目文件多的情况下。想象一下,如果只是修改一个h文件而导致上百个文件不必要的编译,那是一件多么让人纠结的事情。。。

对于@class只是告诉编译器有这个class,请不要报错或警告,因此不会给编译造成影响。

什么时候用@class这种方式声明比#import好呢?

stackoverflow上的高手们给了不少建议:

Randy Marsh:

When I develop, I have only three things in mind that never cause me any problems.

Import super classes
Import parent classes (when you have children and parents)
Import classes outside your project (like in frameworks and libraries)
For all other classes (subclasses and child classes in my project self), I declare them via forward-class.

Justin:

Simple answer: You #import or #include when there is a physical dependency. Otherwise, you use forward declarations (@class MONClass,struct MONStruct, @protocol MONProtocol).

Here are some common examples of physical dependence:

Any C or C++ value (a pointer or reference is not a physical dependency). If you have aCGPoint as an ivar or property, the compiler will need to see the declaration ofCGPoint.
Your superclass.
A method you use.

最后,我建议还是养成良好的import习惯,不要偷懒都把import放在h文件中,无论参与的项目大小,养成良好的编程习惯非常重要。

分享到 评论

更改navigationController push和pop界面切换动画

有时候我们需要自定义navigationController pushpop界面切换动画,用到的代码如下:

  • For Push:
1
2
3
4
5
6
7
8
MainView *nextView=[[MainView alloc] init];  
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationCurve:UIViewAnimationCurveEaseInOut];
[UIView setAnimationDuration:0.75];
[self.navigationController pushViewController:nextView animated:NO];
[UIView setAnimationTransition:UIViewAnimationTransitionFlipFromRight forView:self.navigationController.view cache:NO];
[UIView commitAnimations];
[nextView release];
  • For Pop:

方法一:

1
2
3
4
5
6
7
8
9
10
[UIView  beginAnimations:nil context:NULL];  
[UIView setAnimationCurve:UIViewAnimationCurveEaseInOut];
[UIView setAnimationDuration:0.75];
[UIView setAnimationTransition:UIViewAnimationTransitionFlipFromLeft forView:self.navigationController.view cache:NO];
[UIView commitAnimations];

[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDelay:0.375];
[self.navigationController popViewControllerAnimated:NO];
[UIView commitAnimations];

方法二:

可实现左右滑动动画,可设置滑动方向。

1
2
3
4
5
6
7
CATransition* transition = [CATransition animation];  
transition.duration = 0.5;
transition.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
transition.type = kCATransitionFade; //kCATransitionMoveIn; //, kCATransitionPush, kCATransitionReveal, kCATransitionFade
//transition.subtype = kCATransitionFromTop; //kCATransitionFromLeft, kCATransitionFromRight, kCATransitionFromTop, kCATransitionFromBottom
[self.navigationController.view.layer addAnimation:transition forKey:nil];
[[self navigationController] popViewControllerAnimated:NO];

具体的动画参数请自行更改。

分享到 评论

几个微博的同步——登录

最近做了个微博软件,可以直接通过软件发微博,用了一段时间后,开通了腾讯微博,于是想把之前的微博内容也同步到腾讯微博上。马上用firebug分析了一下腾讯微博的登录过程,果然发现腾讯又对发送的qq密码进行加密,所以,要想顺利登录腾讯微博,第一步要做的就是要加密算法拿到手。

既然发送qq密码之前已经进行了加密,那加密肯定是在客户端进行的,于是我直接用firebug在相关js里面进行搜索,很快就定位到了加密算法的js文件,在该js文件可以找到对qq密码进行加密的代码:

1
2
3
4
5
6
7
8
9
10
11
12
if (E[A].name == "p") {
var F = "";
F += E.verifycode.value;
F = F.toUpperCase();
B += md5(md5_3(E.p.value) + F)
} else {
if (E[A].name == "u1" || E[A].name == "ep") {
B += encodeURIComponent(E[A].value)
} else {
B += E[A].value
}
}

分析了一下加密主要是这部分:B += md5(md5_3(E.p.value) + F),E.p.value就是输入的密码,B是发送的参数,F是获取到的验证码。知道了加密过程,接下来的就好办了。直接用MSScriptControl来调用md5和md5_3函数对qq密码进行加密并且发送,当然在此之前比较先获取验证码。

对qq密码加密后,接着就直接根据firebug的分析,把相关数据进行发送就可以了,在发送之前需要注意的是记得要先获取并保存到相关的cookie,不然也会提示参数错误。

其实登录还有一个方法,就是通过webBrowser控件,直接定位到腾讯微博的登录窗口,在此之前开了qq的话就直接可以按快速登录进行登录了,然后通过webBrowser直接获取登录后的cookie就可以了。

分享到 评论