iOS开发技巧篇

在iOS开发中,有一些技巧可以提高程序猿的开发效率。

1,Xcode真机调试

Xcode 7推出之前,想要真机调试,iOS开发者必须花$99购买苹果开发者账号,而且步骤繁琐,需要下载证书认证。随着苹果公司推出了Xcode 7之后,大幅度的简化了真机调试的步骤。但是如果要测试推送等,还是需要证书的。

第一步:准备Mac电脑,Apple ID, iPhone手机,Xcode 集成开发环境; 第二步:打开Xcode选择屏幕左上角Xcode->Preferences->Account。

第三步,点击左下角的+按钮登陆Apple ID,登陆你的Apple ID,填写相关信息

第四步:打开需要真机测试的项目插上手机(Xcode第一次链接手机会很慢,可以选择Xcode菜单栏中的 window-> devices查看手机是否准备就绪了),选择 项目文件-> General - > Team-> 选择你属于你的Apple ID ,再点击Team 下面的fix issue修复Team 正下方的警告。 或者直接点击你的真机运行即可。

注:如果运行项目的时候弹出一个框(process launch failed: Security),则需要进行信任授权。依次点击设置->通用- >描述文件->选择你的Apple ID - >点击信任。

2,Xcode截屏

Xcode默认提供了截屏功能,在 Xcode的 debug菜单中找到viewDebugging,然后点击截屏选项,就可以将截屏的屏幕保存到桌面了。

3,code snippet

Xcode默认提供了非常丰富的代码片段可供选择,在实际开发中很多的提示就是一个代码片段,具体可以参加 Xcode 的右侧工具栏下方:

那如何创建自定义的代码段呢?很简单,首先在 Xcode 中写出你想创建的代码,然后选中拖动至上面图片的 code snippet library 中,这里有个技巧就是如果代码中有可变参数的话,可以用 <#parammeter#> 这样的形式包起来,比如我们经常创建的属性 property,首先在 Xcode 中写上:

@property (nonatomic, strong) <#UIView#> *<#myView#>;

然后选中这行代码,拖动到 code snippet library 中,然后你就会发现在代码段库的最底部生成了一个自定义的代码段,再进行编辑其 title,completion shortcut,如下:

点击右下角 Done 之后,再回到 Xcode 中键入 @property 你就回惊奇的发现刚才创建的代码段出现在代码自动提示列表中:

4,让 view 从屏幕顶部开始

iOS7 以后,有导航的话,controller 的 view 默认是会以导航栏的下方为起点开始,如果需要让它从屏幕顶部开始的话,只需要一句话就可以搞定。

 self.extendedLayoutIncludesOpaqueBars = YES;

5,屏幕旋转控制

假如应用中只有少数几个界面需要支持横屏时,我们不必打开设置文件进行配置,只需要按照下面的步骤添加一个BOOL属性即可。 (1) 首先在 appDelegate.h 中创建一个 BOOL 属性,当属性为YES时,就表示横屏。比如:

@property (nonatomic,assign)BOOL allowRotation; //是否支持横屏

然后到 appDelegate.m 中实现,

- (UIInterfaceOrientationMask)application:(UIApplication *)application supportedInterfaceOrientationsForWindow:(nullable UIWindow *)window{

    if (self.allowRotation) {
        return UIInterfaceOrientationMaskLandscapeLeft | UIInterfaceOrientationMaskLandscapeRight | UIInterfaceOrientationMaskPortrait ;
    }
    return UIInterfaceOrientationMaskPortrait;
}

(2) 在需要支持的页面中,修改 allowRotation 的值为 YES即可。

- (void)viewWillAppear:(BOOL)animated{
    [super viewWillAppear:animated];
    // 出现时可旋转
    ((AppDelegate *)[UIApplication sharedApplication].delegate).allowRotation = YES;
}

同样重要的是,在页面将要消失时修改为只支持竖屏:

- (void)viewWillDisappear:(BOOL)animated {
    [super viewWillDisappear:animated];
    // 消失时恢复竖屏
    ((AppDelegate *)[UIApplication sharedApplication].delegate).allowRotation = NO;
    // 立即变为竖屏
    [[UIDevice currentDevice] setValue:[NSNumber numberWithInteger:UIDeviceOrientationPortrait] forKey:@"orientation"];

(3) 上述代码实现的是自动旋转、如果需要强制旋转的的话,在上述把横屏打开的前提下,使用下面的代码即可进行强制的横屏或者竖屏。

// 竖屏
    [[UIDevice currentDevice] setValue:[NSNumber numberWithInteger:UIDeviceOrientationPortrait] forKey:@"orientation"];
    // 横屏
    [[UIDevice currentDevice] setValue:[NSNumber numberWithInt:UIInterfaceOrientationLandscapeRight] forKey:@"orientation"];

(4) 对于有导航栏的,使用侧滑返回时可能会出现问题,于是需要在将要进入横屏时禁用侧滑返回手势,退出横屏时再开启即可。

// 屏幕即将旋转
- (void)viewWillTransitionToSize:(CGSize)size withTransitionCoordinator:(id<UIViewControllerTransitionCoordinator>)coordinator{
    [super viewWillTransitionToSize:size withTransitionCoordinator:coordinator];
//    NSLog(@"here: %@  %@", NSStringFromCGSize(size), coordinator);

    if (size.width > size.height) {
        // 横屏,禁用侧滑返回手势
    } else {
        //竖屏,开启侧滑返回手势  
    }
}

5,修改App 名称

一般 App名称默认就是工程名、开发 App 过程中假如想到更合适的名字,这时候除了修改工程名这个办法外,其实更优雅的操作是在 info.plist 中添加一个key(Bundle display name),Value 就是你需要的新名字。

6,添加音乐播放代码

应用中添加适当的音效,可以提高用户体验。如果要实现播放一小段的音效功能,代码如下:

// 比如添加一个:截图音效
    // 1. 定义要播放的音频文件的URL
    NSURL *screenshotURL = [[NSBundle mainBundle] URLForResource:@"captureVoice" withExtension:@"wav"];
    // 2. 注册音频文件(第一个参数是音频文件的URL 第二个参数是音频文件的SystemSoundID)
    AudioServicesCreateSystemSoundID((__bridge CFURLRef)screenshotURL,&screenshotSound);
    // 3. 为crash播放完成绑定回调函数、可不绑定
    // AudioServicesAddSystemSoundCompletion(screenshot, NULL, NULL, (void*)completionCallback, NULL);
    // 4. 播放 ditaVoice 注册的音频 并控制手机震动
    // AudioServicesPlaySystemSound(screenshotSound); // 只播放声音
    // AudioServicesPlayAlertSound(screenshotSound); // 同时手机会震动
    // AudioServicesPlaySystemSound(kSystemSoundID_Vibrate); // 控制手机振动

7,让 section header view 不悬停

当 UITableView 的 style 属性设置为 Plain 时,这个tableview的section header在滚动时会默认悬停在界面顶端。而有时候则需要不悬停的效果,怎么做呢?只需要重载scrollview的delegate方法即可。

- (void)scrollViewDidScroll:(UIScrollView *)scrollView {
    CGFloat sectionHeaderHeight = 40;
    if (scrollView.contentOffset.y<=sectionHeaderHeight&&scrollView.contentOffset.y>=0) {
        scrollView.contentInset = UIEdgeInsetsMake(-scrollView.contentOffset.y, 0, 0, 0);
    } else if (scrollView.contentOffset.y>=sectionHeaderHeight) {
        scrollView.contentInset = UIEdgeInsetsMake(-sectionHeaderHeight, 0, 0, 0);
    }
}

8,屏幕截图并保存

系统为我们提供了截屏的功能,但是在应用中要实现截屏功能,怎么做呢?代码如下:

//snapshotImage 这个方法效率比较低,
- (UIImage *)snapshotImage {
    UIGraphicsBeginImageContextWithOptions(self.view.bounds.size, self.view.opaque, 0);
    [self.view.layer renderInContext:UIGraphicsGetCurrentContext()];
    UIImage *snap = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();
    return snap;
}
//iOS 7上UIView上提供了drawViewHierarchyInRect:afterScreenUpdates:来截图,速度比renderInContext:快15倍。
- (UIImage *)snapshotImageAfterScreenUpdates:(BOOL)afterUpdates {
    if ([self respondsToSelector:@selector(drawViewHierarchyInRect:afterScreenUpdates:)]) {
        return [self snapshotImage];
    }
    UIGraphicsBeginImageContextWithOptions(self.view.bounds.size, self.view.opaque, 0);
    [self.view drawViewHierarchyInRect:self.view.bounds afterScreenUpdates:afterUpdates];
    UIImage *snap = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();
    return snap;
}
//保存截图到相册
- (void)saveImageToPhotos:(UIImage *)image{
    UIImageWriteToSavedPhotosAlbum(image, self, @selector(image:didFinishSavingWithError:contextInfo:), nil);
}
//状态回调
- (void)image:(UIImage *)image didFinishSavingWithError:(NSError *)error contextInfo:(void *)contextInfo{
    if (!error) {
        NSLog(@"\n\n保存成功\n\n");
    } else {
        NSLog(@"\n\n保存失败\n\n");
    }
}

9,获得任意 view 相对于屏幕的 frame

使用下面的代码可以获得任意 view 相对于屏幕的 frame。

CGRect frame = [[UIApplication sharedApplication].keyWindow convertRect:CGRectMake(0, 0, targetView.frame.size.width, targetView.frame.size.height) fromView:targetView];

10,UIImage与字符串互转

使用下面的代码可以实现UIImage与字符串互转。

//图片转字符串  
-(NSString *)UIImageToBase64Str:(UIImage *) image  
{  
    NSData *data = UIImageJPEGRepresentation(image, 1.0f);  
    NSString *encodedImageStr = [data base64EncodedStringWithOptions:NSDataBase64Encoding64CharacterLineLength];  
    return encodedImageStr;  
}
//
//字符串转图片  
-(UIImage *)Base64StrToUIImage:(NSString *)_encodedImageStr  
{  
    NSData *_decodedImageData   = [[NSData alloc] initWithBase64Encoding:_encodedImageStr];  
    UIImage *_decodedImage      = [UIImage imageWithData:_decodedImageData];  
    return _decodedImage;  
}  

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏Guangdong Qi

小Q项目框架搭建及会动的Tabbar未完待续,持续更新中

1804
来自专栏岑志军的专栏

ReactNative-综合案例(02)

1797
来自专栏糊一笑

移动端效果之ScrollList

写在前面 列表一直是展示数据的一个重要方式,在手机端的列表展示又和PC端展示不同,毕竟手机端主要靠滑。之前手机端之前一直使用的IScroll,但是IScroll...

2816
来自专栏陈满iOS

iOS小技巧·把子视图控制器的视图添加到父视图控制器

882
来自专栏逆向技术

win32程序之子窗口编程

  在前边我们已经讲解了窗口的本质.以及如何注册窗口类跟创建窗口. 还讲了消息循环.

2392
来自专栏Android群英传

Lottie踩坑记

类似这样的组件,我们应该用的很多,比如一些开关Switch,一些状态切换,比如Toggle button,这些组件我们要设置动画,就可以借助Lottie来做一些...

2641
来自专栏移动开发

一个简单的ReactNative demo

本人非前端,请轻喷 ReactNative版本:0.31 github:https://github.com/X-FAN/reactnativelear...

4933
来自专栏一“技”之长

iOS文本布局探讨之三——使用TextKit框架进行富文本布局

        关于图文混排,其实以前的博客已经讨论很多,在实际开发中,经常使用第三方的框架来完成排版的需求,其中RCLabel和RTLabel是两个比较好用的...

1372
来自专栏青玉伏案

iOS开发之自定义表情键盘(组件封装与自动布局)

  下面的东西是编写自定义的表情键盘,话不多说,开门见山吧!下面主要用到的知识有MVC, iOS开发中的自动布局,自定义组件的封装与使用,Block回调,Cor...

26410
来自专栏Charlie's Road

Container ViewController自定义转场控制器。

最近接触到新公司的老项目改版。自从来了之后一直在忙另一个项目,也没有看老项目的实现逻辑。 看到设计稿的时候,并不是普通的树形标签导航的样子。大致效果如FaceU...

1271

扫码关注云+社区

领取腾讯云代金券