阅读更多
回顾过去一年发生在我们身边的事情时,有一点不得不提:对苹果开发者来讲,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的一贯风格,限制极多,不支持内部手势,...

  • 风光储直流微电网Simulink仿真模型:光伏发电、风力发电与混合储能系统的协同运作及并网逆变器VSR的研究,风光储直流微电网Simulink仿真模型:MPPT控制、混合储能系统、VSR并网逆变器的设

    风光储直流微电网Simulink仿真模型:光伏发电、风力发电与混合储能系统的协同运作及并网逆变器VSR的研究,风光储直流微电网Simulink仿真模型:MPPT控制、混合储能系统、VSR并网逆变器的设计与实现,风光储、风光储并网直流微电网simulink仿真模型。 系统由光伏发电系统、风力发电系统、混合储能系统(可单独储能系统)、逆变器VSR?大电网构成。 光伏系统采用扰动观察法实现mppt控制,经过boost电路并入母线; 风机采用最佳叶尖速比实现mppt控制,风力发电系统中pmsg采用零d轴控制实现功率输出,通过三相电压型pwm变器整流并入母线; 混合储能由蓄电池和超级电容构成,通过双向DCDC变器并入母线,并采用低通滤波器实现功率分配,超级电容响应高频功率分量,蓄电池响应低频功率分量,有限抑制系统中功率波动,且符合储能的各自特性。 并网逆变器VSR采用PQ控制实现功率入网。 ,风光储; 直流微电网; simulink仿真模型; 光伏发电系统; 最佳叶尖速比控制; MPPT控制; Boost电路; 三相电压型PWM变换器;

  • 以下是针对初学者的 **51单片机入门教程**,内容涵盖基础概念、开发环境搭建、编程实践及常见应用示例,帮助你快速上手

    以下是针对初学者的 **51单片机入门教程**,内容涵盖基础概念、开发环境搭建、编程实践及常见应用示例,帮助你快速上手。

  • 【Python毕设】根据你提供的课程代码,自动排出可行课表,适用于西工大选课_pgj.zip

    【Python毕设】根据你提供的课程代码,自动排出可行课表,适用于西工大选课_pgj

  • 【毕业设计】[零食商贩]-基于vue全家桶+koa2+sequelize+mysql搭建的移动商城应用.zip

    【毕业设计】[零食商贩]-基于vue全家桶+koa2+sequelize+mysql搭建的移动商城应用

  • 电动汽车充电背景下的微电网谐波抑制策略与风力发电系统仿真研究,电动汽车充电微电网的谐波抑制策略与风力发电系统仿真研究,基于电动汽车充电的微电网谐波抑制策略研究,包括电动汽车充电负 载模型,风电模型,光

    电动汽车充电背景下的微电网谐波抑制策略与风力发电系统仿真研究,电动汽车充电微电网的谐波抑制策略与风力发电系统仿真研究,基于电动汽车充电的微电网谐波抑制策略研究,包括电动汽车充电负 载模型,风电模型,光伏发现系统,储能系统,以及谐波处理模块 风力发电系统仿真 ,电动汽车充电负载模型; 风电模型; 光伏发现系统; 储能系统; 谐波处理模块; 风力发电系统仿真,电动汽车充电微电网的谐波抑制策略研究:整合负载模型、风电模型与光伏储能系统

  • Vscode部署本地Deepseek的continue插件windows版本

    Vscode部署本地Deepseek的continue插件windows版本

  • 模拟电子学中滤波器的F0和Q参数详解及各类滤波器的设计方法

    内容概要:本文详细介绍了滤波器的两个关键参数——截止频率(F0)和品质因素(Q),并探讨了不同类型的滤波器(包括低通、高通、带通和带阻滤波器)的设计方法及其特性。文章首先明确了F0和Q的基本概念及其在滤波器性能中的作用,接着通过数学推导和图形展示的方式,解释了不同Q值对滤波器频率响应的影响。文中特别指出,通过调整Q值可以控制滤波器的峰谷效果和滚降速度,进而优化系统的滤波性能。此外,还讨论了不同类型滤波器的具体应用场景,如低通滤波器适用于消除高频噪声,高通滤波器用于去除直流分量和低频干扰,而带通滤波器和带阻滤波器分别用于选取特定频段信号和排除不需要的频段。最后,通过对具体案例的解析,帮助读者更好地理解和应用相关理论。 适合人群:电子工程及相关领域的技术人员、研究人员以及高校学生,特别是那些需要深入了解滤波器设计原理的人群。 使用场景及目标:适用于从事模拟电路设计的专业人士,尤其是希望掌握滤波器设计细节和技术的应用场合。目标是让读者能够灵活运用Q值和F0来优化滤波器设计,提升系统的信噪比和选择性,确保信号的纯净性和完整性。

  • QUARTEUSⅡ在EDA技术中的应用: CPLD/FPGA电路设计全流程解析与实例展示

    内容概要:本文主要讲述了利用QUARTUSⅡ进行电子设计自动化的具体步骤和实例操作,详细介绍了如何利用EDA技术在QUARTUSⅡ环境中设计并模拟下降沿D触发器的工作过程,重点探讨了系统规格设计、功能描述、设计处理、器件编译和测试四个步骤及相关的设计验证流程,如功能仿真、逻辑综合及时序仿真等内容,并通过具体的操作指南展示了电路设计的实际操作方法。此外还强调了QUARTUSⅡ作为一款集成了多种功能的综合平台的优势及其对于提高工作效率的重要性。 适用人群:电子工程、自动化等相关专业的学生或者工程师,尤其适用于初次接触EDA技术和QuartusⅡ的用户。 使用场景及目标:旨在帮助用户理解和掌握使用QUARTUSⅡ这一先进的EDA工具软件进行从概念设计到最后成品制作整个电路设计过程的方法和技巧。目标是在实际工作中能够熟练运用QUARTUSⅡ完成各类复杂电子系统的高效设计。 其他说明:文中通过具体的案例让读者更直观理解EDA设计理念和技术特点的同时也为进一步探索EDA领域的前沿课题打下了良好基础。此外它还提到了未来可能的发展方向,比如EDA工具的功能增强趋势等。

  • Simulink建模下的光储系统与IEEE33节点配电网的协同并网运行:光照强度变化下的储能系统优化策略与输出性能分析,Simulink模型下的光伏微网系统:光储协同,实现380v电压等级下的恒定功率

    Simulink建模下的光储系统与IEEE33节点配电网的协同并网运行:光照强度变化下的储能系统优化策略与输出性能分析,Simulink模型下的光伏微网系统:光储协同,实现380v电压等级下的恒定功率并网与平抑波动,Simulink含光伏的IEEE33节点配电网模型 微网,光储系统并网运行 光照强度发生改变时,储能可以有效配合光伏进行恒定功率并网,平抑波动,实现削峰填谷。 总的输出有功为270kw(图23) 无功为0 检验可以并网到电压等级为380v的电网上 逆变侧输出电压电流稳定(图4) ,Simulink; 含光伏; 配电网模型; 微网; 光储系统; 储能配合; 恒定功率并网; 电压等级; 逆变侧输出。,Simulink光伏微网模型:光储协同并网运行,实现功率稳定输出

Global site tag (gtag.js) - Google Analytics