1.IOS适配问题
IOS6启动app时launchImage中出现了状态栏,而IOS7并没有出现这种情况。是因为IOS6的View不包含状态栏。在解决这个适配问题中,通常在项目勾选“Hide status bar”隐藏状态栏,然后在application的delegate的didFinishLaunchingWithOptions中用代码设置状态栏可见“application.statusBarHidden = NO;”
在代码中可拿到当前设备的版本号,可对此进行判别版本号来做适配
if ([[UIDevice currentDevice].systemVersiondoubleValue] >= 7.0){//IOS7以上
}else{//IOS7以下
}
由于在项目开发时经常做适配,所以应该将上面代码定义成宏抽取到pch文件,适用于全局
例如:#define ios7 ([[UIDevicecurrentDevice].systemVersion doubleValue] >= 7.0)
2.block循环引用引发内存泄露
block是copy属性,强引用。在block中调用self会对控制器进行强引用,导致self指向的控制器无法被释放,于是内存泄露。
所以在block中若需要使用self,需先把self改为若引用。
__unsafe_unretained NJShareViewController*unsafeSelf = self;
__weak NJShareViewController*unsafeSelf = self;
// __weak 当对象释放之后会自动设置为nil,而__unsafe_unretained不会,一般用weak
__weak typeof(self) unsafeSelf = self;//该代码有扩展性
常用小功能
3.打电话
方法1
最简单最直接的方式:直接跳到拨号界面
NSURL *url = [NSURL URLWithString:@"tel://10010"];
[[UIApplication sharedApplication] openURL:url];
缺点
电话打完后,不会自动回到原应用,直接停留在通话记录界面
方法2
拨号之前会弹框询问用户是否拨号,拨完后能自动回到原应用
NSURL *url = [NSURL URLWithString:@"telprompt://10010"];
[[UIApplication sharedApplication] openURL:url];
缺点
因为是私有API,所以可能不会被审核通过
方法3
创建一个UIWebView来加载URL,拨完后能自动回到原应用
if(_webView == nil){
_webView = [[UIWebViewalloc] initWithFrame:CGRectZero];
}
[_webView loadRequest:[NSURLRequestrequestWithURL:[NSURLURLWithString:@"tel://10010"]]];
需要注意的是:这个webView千万不要添加到界面上来,不然会挡住其他界面
4.发短信
方法1
直接跳到发短信界面,但是不能指定短信内容,而且不能自动回到原应用
NSURL *url = [NSURL URLWithString:@"sms://10010"];
[[UIApplication sharedApplication] openURL:url];
方法2
如果想指定短信内容,那就得使用MessageUI框架
包含主头文件
#import <MessageUI/MessageUI.h>
显示发短信的控制器
MFMessageComposeViewController *vc = [[MFMessageComposeViewControlleralloc] init];
// 设置短信内容
vc.body = @"吃饭了没?";
// 设置收件人列表
vc.recipients = @[@"10010",@"02010010"];
// 设置代理
vc.messageComposeDelegate= self;
// 显示控制器
[self presentViewController:vc animated:YES completion:nil];
代理方法,当短信界面关闭的时候调用,发完后会自动回到原应用
- (void)messageComposeViewController:(MFMessageComposeViewController *)controller didFinishWithResult:(MessageComposeResult)result
{
// 关闭短信界面
[controller dismissViewControllerAnimated:YES completion:nil];
if (result == MessageComposeResultCancelled){
NSLog(@"取消发送");
} else if (result== MessageComposeResultSent) {
NSLog(@"已经发出");
} else {
NSLog(@"发送失败");
}
}
5.发邮件
方法1
用自带的邮件客户端,发完邮件后不会自动回到原应用
NSURL *url = [NSURL URLWithString:@"mailto://10010@qq.com"];
[[UIApplication sharedApplication] openURL:url];
方法2
跟发短信的第2种方法差不多,只不过控制器类名叫做:MFMailComposeViewController
邮件发送后的代理方法回调,发完后会自动回到原应用
- (void)mailComposeController:(MFMailComposeViewController *)controllerdidFinishWithResult:(MFMailComposeResult)resulterror:(NSError *)error
{
// 关闭邮件界面
[controller dismissViewControllerAnimated:YES completion:nil];
if (result == MFMailComposeResultCancelled){
NSLog(@"取消发送");
} else if (result== MFMailComposeResultSent) {
NSLog(@"已经发出");
} else {
NSLog(@"发送失败");
}
}
6.打开其他常见文件
如果想打开一些常见文件,比如html、txt、PDF、PPT等,都可以使用UIWebView打开
只需要告诉UIWebView文件的URL即可
至于打开一个远程的共享资源,比如http协议的,也可以调用系统自带的Safari浏览器:
NSURL *url = [NSURL URLWithString:@”http://www.baidu.com"];
[[UIApplication sharedApplication] openURL:url];
7.应用间跳转
有时候,需要在本应用中打开其他应用,比如从A应用中跳转到B应用
首先,B应用得有自己的URL地址(在Info.plist中配置)
接着在A应用中使用UIApplication完成跳转
NSURL *url = [NSURL URLWithString:@"abc://ios.app.cn"];
[[UIApplication sharedApplication] openURL:url];
8.应用评分
为了提高应用的用户体验,经常需要邀请用户对应用进行评分
应用评分无非就是跳转到AppStore展示自己的应用,然后由用户自己撰写评论
如何跳转到AppStore,并且展示自己的应用
方法1
NSString *appid = @"444934666";
NSString *str = [NSString stringWithFormat:
@"itms-apps://ax.itunes.apple.com/WebObjects/MZStore.woa/wa/viewContentsUserReviews?type=Purple+Software&id=%@",appid];
[[UIApplication sharedApplication] openURL:[NSURL URLWithString:str]];
方法2
NSString *str = [NSString stringWithFormat:
@"itms-apps://itunes.apple.com/cn/app/id%@?mt=8",appid];
[[UIApplication sharedApplication] openURL:[NSURL URLWithString:str]];
9.练习中遇到的问题
往一个有tabBar和navigationBar的控制器的view中拖入一个控件,在IOS7模拟器运行正常,在IOS6位置却有变化。这是因为IOS7默认view的大小为320*480,而IOS6的view默认除去状态栏、tabBar、navigationBar的高度,只有320*367高度。
解决方法:如该View非tableView或scrollView,建议在storyboard中设置该控制器的"under top bars"和"underbottom bars"属性,将IOS7中的View变为320*367
[JNSettingItemsetDestVcClass:]: unrecognized selector sent to instance 0x786ca120
原因:子类JNSettingArrowItem继承父类JNSettingItem,增加一项属性,并重写父类方法,对增加的属性进行赋值时报错。
在重写父类时调用了父类的方法来创建一个对象。而父类是通过[[JNSettingItem alloc] init]来创建对象的,从而导致不管是谁调用,创建的都是JNSettingItem对象。当子类调用父类的方法来创建对象时,创建的依旧是JNSettingItem而非JNSettingArrowItem。父类对象没有新增加的那条属性,所以报错!!
解决方法:父类在创建对象时应使用[[self alloc] init]来创建对象,谁调用创建谁,子类调用即创建子类
self.imageView.image = [UIImageimageNamed:@"move@2x.png"];
运行结果并没有显示图片,而self.imageView.image = [UIImageimageNamed:@"move"];能显示图片,因此确定因为后缀@2x.png使得图片无法解析(图片的实际名称是move@2x.png)。但在另一份由Xcode5.1创建的代码,用Xcode6.1运行,却能使用move@2x.png解析图片。因此得出的结论是编译器问题
解决方法:在解析数据模型时,重写图片名属性的setter方法(例如用icon来存放图片名,则重写setIcon方法),对图片名进行字符串处理,[icon stringByReplacingOccurrencesOfString:@"@2x.png" withString:@""];将图片名中的@2x.png替换为空即可。