阅读更多
回顾过去一年发生在我们身边的事情时,有一点不得不提:对苹果开发者来讲,2014年是令人难以置信的一年。在这短短的一年中(有关APP的开发)发生了如此多的变化:在充满吸引力的Swift面前,我们几乎忘了之前是如何痴迷于Objective-C;以及充满想象力的iOS 8和WatchKit,难以想象还有什么API能与之相比。



NSHipster的惯例:请可爱的童鞋们,在新年的第一天,为大家展示你们(在开发中)常使用的技巧和方法。如今,随着来自Cupertino(苹果总部,位于旧金山)和众多开源社区的一系列API的涌现,妈妈再也不用担心我们找不到有趣的东西来分享啦!

在此,感谢以下童鞋们所做的贡献:

Colin Rofls、Cédric Luthi、Florent Pillet、Heath Borders、Joe Zobkiw、Jon Friskics、Justin Miller、Marcin Matczuk、Mikael Konradsson、Nolan O'Brien、Robert Widmann、Sachin Palewar、Samuel Defago、Sebastian Wittenkamp、Vadim Shpakovski、Zak。

成员函数的使用技巧(来自Robert Widmann

在用静态方式调用Swift类和结构中的成员函数时,通常使用以下格式:

Object->(参数)->Things

比如,你可以用以下两种方式调用reverse():
[1,2,3,4].reverse( )
Array.reverse([1,2,3,4])

用@()来封装C字符串(来自Samuel Defago

事实上文字大部分时候是数字和字母的集合,使用C字符串,尤其当我在使用运行时编码的时候,我常常会忘记用UTF8编码、以NULL结束:Objective-C字符串封装:
NSString *propertyAttributesString =
    @(property_getAttributes(class_getProperty([NSObject class], "description")));
// T@"NSString",R,C

AmIBeingDebugged
Nolan O'Brien这篇Q&A技术文档中让我们注意到了AmIBeingDebugged函数方法:
#include <assert.h>
#include <stdbool.h>
#include <sys/types.h>
#include <unistd.h>
#include <sys/sysctl.h>
static Bool AmIBeingDebugged(void) {
    int mib[4];
    struct kinfo_proc info;
    size_t size = sizeof(info);
    info.kp_proc.p_flag = 0;
    mib[0] = CTL_KERN;
    mib[1] = KERN_PROC;
    mib[2] = KERN_PROC_PID;
    mib[3] = getpid();
    sysctl(mib, sizeof(mib) / sizeof(*mib), &info, &size, NULL, 0);
    return (info.kp_proc.p_flag & P_TRACED) != 0;
}

使用延迟存储属性(来自Colin Rofls

在开发过程中,应该避免使用Optionals类型,更不应该使用隐式解包optionals类型。你想声明一个var变量却不想给一个初始值?使用“lazy”吧,唯一要注意的就是:在你的属性被赋值之前不要调用getter方法即可(童叟无欺!)
lazy var someModelStructure = ExpensiveClass()

假如你仅仅对这var变量调用set方法,而没有调用getter方法的话,这个被lazy修饰的var变量不会被赋值。例如,用lazy修饰那些直到viewDidLoad时才需要初始化的views变量就会非常合适。
获取Storyboard视图容器里的子视图控制器(来自Vadim Shpakovski

有一个比较方便的方法来获取故事板视图容器里的子视图控制器:
// 1. A property has the same name as a segue identifier in XIB
@property (nonatomic) ChildViewController1 *childController1;
@property (nonatomic) ChildViewController2 *childController2;
// #pragma mark - UIViewController
- (void)prepareForSegue:(UIStoryboardSegue *)segue
                 sender:(id)sender
{
    [super prepareForSegue:segue sender:sender];
 
    // 2. All known destination controllers assigned to properties
    if ([self respondsToSelector:NSSelectorFromString(segue.identifier)]) {
        [self setValue:segue.destinationViewController forKey:segue.identifier];
    }
}
- (void)viewDidLoad {
    [super viewDidLoad];
    // 3. Controllers already available bc viewDidLoad is called after prepareForSegue
    self.childController1.view.backgroundColor = [UIColor redColor];
    self.childController2.view.backgroundColor = [UIColor blueColor];
}

重复运行项目,不重复构建项目(来自Heath Borders

假如你一直在不停地调试同一个问题,你可以在不重复构建的情况下运行你的APP,这样:“Product>Perform Action>Run without Building”

快速获取Playground资源(来自Jon Friskics

Swift里的所有Playground共享相同的数据目录:/Users/HOME/Documents/Shared Playground Data

如果你喜欢使用很多Playgrounds,你将需要在上述共享目录下为每个Playground新建对应的子目录,来存储每个Playground用到的数据;但是那之后你需要告诉每个Playground在哪儿可以获取其对应的数据。下面是我常用的一个辅助解决方法:
func pathToFileInSharedSubfolder(file: String) -> String {
    return XCPSharedDataDirectoryPath + "/" + NSProcessInfo.processInfo().processName + "/" + file
}

processName属性是Playground文件的名字,因此只要你已经在Playground数据共享文件目录下以相同的名字新建了一个子目录,那么你可以很容易访问这些数据,和读取本地JSON数据一样:
var jsonReadError:NSError?
let jsonData = NSFileManager.defaultManager().contentsAtPath(pathToFileInSharedSubfolder("data.json"))!
let jsonArray = NSJSONSerialization.JSONObjectWithData(jsonData, options: nil, error: &jsonReadError) as [AnyObject]

....或者访问本地图片
let imageView = UIImageView()
imageView.image = UIImage(contentsOfFile: pathToFileInSharedSubfolder("image.png"))

Please attention!本篇文章剩余的部分来自Cédric Luthi大神的贡献,他分享了一些比较有用的开发技巧和技术,这些内容足够自成一篇,值得细细品读。这里再次感谢Cédric!

CocoaPods大揭秘

这儿有一个快速的方法来检查APP里用到的所有pods:
$ class-dump -C Pods_ /Applications/Squire.app | grep -o "Pods_\w+"

CREATE_INFOPLIST_SECTION_IN_BINARY

注意Xcode中为命令模式APP(command-line apps)设置的CREATE_INFOLIST_SECTION_IN_BINARY属性。这比使用-sectcreate__TEXT__info_plist链接标志位更加容易,前者还把已经编译好的Info.plist文件嵌入在二进制编码中。

关于如何向苹果提需求,它也给我们上了一课,这个特性需求早在2006年的 rdar://4722772 被提出,但直到7年后才被满足。

(译者注:言外之意是它是反面教材,应该更有技巧的提需求)

禁用dylib钩子(来自Sam Marshall

Sam Marshall这个技巧可谓是走自己的路,让黑客无路可走。

在你的“Other Linker Flags”里加上下面这行:
-Wl,-sectcreate,__RESTRICT,__restrict,/dev/null

NSBundle -preferredLocalizations

某些时候,你需要知道APP当前使用的是什么语言。通常,大家会使用NSLocal+preferredLanguages. 可惜的是这个方法不会告诉你APP实际呈现的文字语种。你仅仅会得到iOS系统里“Settings->General->Language&Region->Preferred Language”列表中的选项,或者OSX系统里“System Preferences->Language & Region->Preferred Languages”列表中的选项。想象一下:优先语言列表中只有{英语,法语},但你的APP仅使用德语;调用[[NSLocal preferredLanguages] firstObject]返回给你的是英语,而不是德语。

正确的方法是用[[NSBundle mainBundle] preferredLocalizations]方法。

苹果的开发文档是这样说的:

引用
一个包含了在bundle中本地化的语言ID的NSString对象的数组,里面的字符串排序是根据用户的语言偏好设置和可使用的地理位置而来的。


NSBundle.h里的备注:

引用
一个bundle中本地化的子集,重新排序到当前执行坏境的优先序列里,main bundle的语言顺序中最前面的是用户希望在UI界面上看到的语种。


当然你也许需要调用这个方法:
NSLocal+canonicalLanguageIdentifierFromString:

来确保你使用的文字语种是规范的语种。

保护SDK头文件

如果你用dmg安装Xcode,那么看看这篇Joar Wingfors的文章,它讲述了如何通过保留所有权来避免SDK头文件被意外修改:
$ sudo ditto /Volumes/Xcode/Xcode.app /Applications/Xcode.app

任意类型的实例变量检测

为了达到逆向处理的目的,查询对象的实例变量是一个常见可靠的途径。通常调用对象valueForKey:方法就能达到这一目的,除了少数重写了类方法+accessInstanceVariablesDirectly的类屏蔽了该操作。

下面是一个例子:当实例变量有一个为任意类型的属性时,上述提到的操作无效

这是iOS6.1 SDK中MediaPlayer 框架的一段引用:
@interface MPMoviePlayerController : NSObject {
    void *_internal;    // 4 = 0x4
    BOOL _readyForDisplay;  // 8 = 0x8
}

因为 id internal=[moviePlayerController valueForKey:@”internal”] 无效,下面有一个笨办法来取得这个变量:
id internal = *((const id*)(void*)((uintptr_t)moviePlayerController + sizeof(Class)));

注意!不要随意调用这段代码,因为ivar的布局可能改变(指针偏移量计算可能出错)。仅在逆向工程中使用!

NSDateFormatter +dateFormatFromTemplate:options:locale:

友情提示:假如你调用[NSDateFormatter setDateFormat],而没有调用[NSDateFormatter dateFormatFromTemplate:options:local:],n那么很可能出错。

苹果文档:
+ (NSString *)dateFormatFromTemplate:(NSString *)template
                             options:(NSUInteger)opts
                              locale:(NSLocale *)locale

不同地区有不同的日期格式。使用这个方法的目的:得到指定地区指定日期字段的一个合适的格式(通常你可以通过currentLocal查看当前所属地区)

下面这个例子给我们表现了英式英语和美式英语不同的日期格式:
NSLocale *usLocale = [[NSLocale alloc] initWithLocaleIdentifier:@"en_US"];
NSLocale *gbLocale = [[NSLocale alloc] initWithLocaleIdentifier:@"en_GB"];
 
NSString *dateFormat;
NSString *dateComponents = @"yMMMMd";
 
dateFormat = [NSDateFormatter dateFormatFromTemplate:dateComponents options:0 locale:usLocale];
NSLog(@"Date format for %@: %@",
    [usLocale displayNameForKey:NSLocaleIdentifier value:[usLocale localeIdentifier]], dateFormat);
 
dateFormat = [NSDateFormatter dateFormatFromTemplate:dateComponents options:0 locale:gbLocale];
NSLog(@"Date format for %@: %@",
    [gbLocale displayNameForKey:NSLocaleIdentifier value:[gbLocale localeIdentifier]], dateFormat);
 
// Output:
// Date format for English (United States): MMMM d, y
// Date format for English (United Kingdom): d MMMM y

通过调试获取内部常量

近期,Matthias Tretter在Twitter上问到:

有人知道在iOS8里modal viewController presentation的默认动画时间和跳转方式吗?

我们在UIKit的类库中发现了这样一个函数:[UITransitionView defaultDurationForTransition:],并在这个方法的位置加一个断点:
(lldb) br set -n "+[UITransitionView defaultDurationForTransition:]"

模态显示一个viewController,就会停在这个断点,输入finish执行该方法:
(lldb)finish

在defaultDurationForTransition:被执行时,你就能读到结果(在xmm0寄存器里)
(lldb) register read xmm0 --format float64
    xmm0 = {0.4 0}

回复:默认动画时间0.4s
DIY 弱关联对象

不幸的是,关联对象OBJC_ASSOCIATION_ASSIGN策略不支持引用计数为0的弱引用。幸运的是,你可以很容易实现它,你仅仅需要一个简单的类,并在这个类里弱引用一个对象:
@interface WeakObjectContainter : NSObject
@property (nonatomic, readonly, weak) id object;
@end
@implementation WeakObjectContainter
- (instancetype)initWithObject:(id)object {
    self = [super init];
    if (!self) {
        return nil;
    }
    self.object = object;
    return self;
}
@end

然后,通过OBJC_ASSOCIATION_RETAIN(_NONATOMIC)关联WeakObjectContainter:
objc_setAssociatedObject(self, &MyKey, [[WeakObjectContainter alloc] initWithObject:object], OBJC_ASSOCIATION_RETAIN_NONATOMIC);

用object属性指向这个所需的引用计数为0的弱引用对象。
id object = [objc_getAssociatedObject(self, &MyKey) object];

英文文章来源:NSHipster 译文出自:CocoaChina
  • 大小: 36.5 KB
来自: CocoaChina
0
0
评论 共 0 条 请登录后发表评论

发表评论

您还没有登录,请您登录后再发表评论

相关推荐

  • 跨平台开发模式盘点

    手机App的开发方式进入跨平台时代,但目前跨平台的开发方式很多,以至于App开发爱好者在进行技术选型时感到很迷茫,在此对App开发常见的几种方案做一个分析,包括原生开发、混合App、ReactNative、Weex、Flutter、...

  • 盘点国内程序员不常用的热门iOS第三方库:看完,还敢自称”精通iOS开发”吗?

    综合github上各个项目的关注度与具体使用情况,涵盖功能,UI,数据库,自动化测试,编程工具等类型,看完,还敢自称”精通iOS开发”吗? https://github.com/syedhali/EZAudio 基于核心音频,有助于进行实时,低延迟音频...

  • 盘点开发者最喜爱的Swift技巧

    Swift发布才半年左右,却已深得众多开发者的青睐,也有了许多学习资源、项目和开发工具。在本文中,来自objc.io、LinkedIn等各个公司的软件工程师及资深开发者总结了自己在接触Swift过程中最喜爱的贴士与技巧。

  • 盘点——iOS应用开发常用工具

    针对 iOS 平台的应用开发工作,通常都需要借助 IDE、 SDK 等开发工具以提升开发效率。iOS 平台的应用开发生态环境,正随着更...此外,也有一些混合工具可以同时支持安卓与 iOS 应用的开发,为开发者带来了进一步的便利.

  • 盘点iOS开发者必看的105个全球最佳博客

    如果你正在寻找见解深刻,并富有...无论是想要与同侪沟通的iOS开发老手,还是渴望学习以提高移动应用开发技巧的大学新鲜人,都能从这些博客中找到自己所需的工具、知识见解与技术,并在软件的开发过程中充分利用这...

  • iOS开发,面试BAT等公司的一点记录

    Leetcode官方也有类似的一些专题比如练习模式 有精力的可以看一遍《剑指offer》这本电子书。结合Leetcode,理解其思维逻辑,不容易忘记,这一关问题就不大了 基础 大厂最看重的是基础,基础扎实,其他稍微有点瑕疵...

  • 新年之际,盘点一些APP开发技巧

    大神的贡献,他分享了一些比较有用的开发技巧和技术,这些内容足够自成一篇,值得细细品读。这里再次感谢Cédric! CocoaPods大揭秘 这儿有一个快速的方法来检查APP里用到的所有pods: $ class-...

  • iOS开发——热门iOS第三方库大盘点

    本期fir.im Weekly 收集的热度资源,大部分关于Android、iOS 开发工具、源码和脑洞大开的 UI 动画,希望给你带来更多的工作创意与灵感。 盘点国内程序员不常用的热门iOS第三方库 @ios122 的这份整理综合了 ...

  • 移动开发周报 Issue #171:盘点 2016 年移动开发现状及未来展望

    写在前面本期移动开发周刊 Issue#171 期如约而至,聚焦 Android、iOS、VR/AR/MR、直播等前沿移动开发技术,收录一周最热点,解读开发技巧,每周三移动周刊抢先看,我们希望从中能够让你有一些收获,如果你有好的文章...

  • iOS 14 Widget:七夕节,缺僚机?这题我会!

    Widget是iOS14 新引入的桌面小组件,仅支持SwiftUI。在iOS 14之前, iOS也有与3DTouch关联的小组件,但这次更新基本上摒除了旧的组件,是苹果一次新的尝试。Widget继承了iOS的一贯风格,限制极多,不支持内部手势,...

  • java+sql server项目之科帮网计算机配件报价系统源代码.zip

    sql server+java项目之科帮网计算机配件报价系统源代码

  • 【java毕业设计】智慧社区老人健康监测门户.zip

    有java环境就可以运行起来 ,zip里包含源码+论文+PPT, 系统设计与功能: 文档详细描述了系统的后台管理功能,包括系统管理模块、新闻资讯管理模块、公告管理模块、社区影院管理模块、会员上传下载管理模块以及留言管理模块。 系统管理模块:允许管理员重新设置密码,记录登录日志,确保系统安全。 新闻资讯管理模块:实现新闻资讯的添加、删除、修改,确保主页新闻部分始终显示最新的文章。 公告管理模块:类似于新闻资讯管理,但专注于主页公告的后台管理。 社区影院管理模块:管理所有视频的添加、删除、修改,包括影片名、导演、主演、片长等信息。 会员上传下载管理模块:审核与删除会员上传的文件。 留言管理模块:回复与删除所有留言,确保系统内的留言得到及时处理。 环境说明: 开发语言:Java 框架:ssm,mybatis JDK版本:JDK1.8 数据库:mysql 5.7及以上 数据库工具:Navicat11及以上 开发软件:eclipse/idea Maven包:Maven3.3及以上

  • 【java毕业设计】智慧社区心理咨询平台(源代码+论文+PPT模板).zip

    zip里包含源码+论文+PPT,有java环境就可以运行起来 ,功能说明: 文档开篇阐述了随着计算机技术、通信技术和网络技术的快速发展,智慧社区门户网站的建设成为了可能,并被视为21世纪信息产业的主要发展方向之一 强调了网络信息管理技术、数字化处理技术和数字式信息资源建设在国际竞争中的重要性。 指出了智慧社区门户网站系统的编程语言为Java,数据库为MYSQL,并实现了新闻资讯、社区共享、在线影院等功能。 系统设计与功能: 文档详细描述了系统的后台管理功能,包括系统管理模块、新闻资讯管理模块、公告管理模块、社区影院管理模块、会员上传下载管理模块以及留言管理模块。 系统管理模块:允许管理员重新设置密码,记录登录日志,确保系统安全。 新闻资讯管理模块:实现新闻资讯的添加、删除、修改,确保主页新闻部分始终显示最新的文章。 公告管理模块:类似于新闻资讯管理,但专注于主页公告的后台管理。 社区影院管理模块:管理所有视频的添加、删除、修改,包括影片名、导演、主演、片长等信息。 会员上传下载管理模块:审核与删除会员上传的文件。 留言管理模块:回复与删除所有留言,确保系统内的留言得到及时处理。

  • 计算机系统基础实验LinkLab实验及解答:深入理解ELF文件与链接过程

    内容概要:本文档详细介绍了LinkLab实验的五个阶段,涵盖了ELF文件的组成、符号表的理解、代码节与重定位位置的修改等内容。每个阶段都有具体的实验要求和步骤,帮助学生理解链接的基本概念和链接过程中涉及的各项技术细节。 适合人群:计算机科学专业的本科生,特别是正在修读《计算机系统基础》课程的学生。 使用场景及目标:① 通过实际操作加深对链接过程和ELF文件的理解;② 掌握使用readelf、objdump和hexedit等工具的技巧;③ 实现特定输出以验证实验结果。 阅读建议:实验过程中的每个阶段都有明确的目标和提示,学生应按照步骤逐步操作,并结合反汇编代码和二进制编辑工具进行实践。在完成每个阶段的实验后,应及时记录实验结果和遇到的问题,以便于总结和反思。

  • 基于关键词的历时百度搜索指数自动采集资料齐全+详细文档+高分项目+源码.zip

    【资源说明】 基于关键词的历时百度搜索指数自动采集资料齐全+详细文档+高分项目+源码.zip 【备注】 1、该项目是个人高分项目源码,已获导师指导认可通过,答辩评审分达到95分 2、该资源内项目代码都经过测试运行成功,功能ok的情况下才上传的,请放心下载使用! 3、本项目适合计算机相关专业(人工智能、通信工程、自动化、电子信息、物联网等)的在校学生、老师或者企业员工下载使用,也可作为毕业设计、课程设计、作业、项目初期立项演示等,当然也适合小白学习进阶。 4、如果基础还行,可以在此代码基础上进行修改,以实现其他功能,也可直接用于毕设、课设、作业等。 欢迎下载,沟通交流,互相学习,共同进步!

  • 用C语言写出一个简单的圣诞树,让你的朋友们体验一下程序员的浪漫,点开即令哦!

    第一次发文的小白,解释的不好,各位大佬勿怪哦

  • 免费下载:Hilma af Klint a Biography (Julia Voss)_tFy2T.zip

    免费下载:Hilma af Klint a Biography (Julia Voss)_tFy2T.zip

  • 屏幕截图 2024-12-21 172527.png

    屏幕截图 2024-12-21 172527

  • 2024级涉外护理7班马天爱劳动实践总结1.docx

    2024级涉外护理7班马天爱劳动实践总结1.docx

Global site tag (gtag.js) - Google Analytics