首页 文章 精选 留言 我的

精选列表

搜索[cocoa],共340篇文章
优秀的个人博客,低调大师

苹果iOS开发深入浅出Cocoa之类与对象

最近打算写一些ObjC中比较底层的东西,尤其是 runtime 相关的。苹果已经将 ObjC runtime 代码开源了,我们可以从:http://opensource.apple.com/source/objc4/objc4-493.9/runtime/浏览源代码,或点此下载源代码。 从哪里入手呢?那当然是最基本的类与对象。与C++相比,ObjC中的类与对象结构要简洁与一致得多(参考《深度探索C++对象模型》,你就知道C++中类与对象结构的复杂)。本文将详细讲解ObjC中类与对象的结构,下回将讲如何在 runtime 时操作类。 我们可以在/usr/include/objc/objc.h 和 runtime.h 中找到对 class 与 object 的定义: typedef struct objc_class *Class; typedef struct objc_object { Class isa; } *id; Class 是一个 objc_class 结构类型的指针;而 id(任意对象) 是一个 objc_object 结构类型的指针,其第一个成员是一个 objc_class 结构类型的指针。注意这里有一关键的引申解读:内存布局以一个 objc_class 指针为开始的所有东东都可以当做一个 object 来对待! 那 objc_class 又是怎样一个结构体呢?且看: struct objc_class { struct objc_class* isa; struct objc_class* super_class; const char* name; long version; long info; long instance_size; struct objc_ivar_list* ivars; struct objc_method_list** methodLists; struct objc_cache* cache; struct objc_protocol_list* protocols; } objc_class 结构体的各成员介绍如下: isa:是一个 objc_class 类型的指针,看到这里,想起我前面的引申解读了没?内存布局以一个 objc_class 指针为开始的所有东东都可以当做一个 object 来对待! 这就是说 objc_class 或者说类其实也可以当做一个 objc_object 对象来对待!对象是对象,类也是对象,是不是有点混淆?别急,ObjC发明(or 重用)了一个术语来区分这两种不同的对象:类对象(class object)与实例对象(instance object)。OK,名称混淆的问题解决,下面我将使用这两个术语来区分不同的对象,而使用“对象”这一术语来泛指所有的对象。ObjC还对类对象与实例对象中的 isa 所指向的类结构作了不同的命名:类对象中的 isa 指向类结构被称作 metaclass,metaclass 存储类的static类成员变量与static类成员方法(+开头的方法);实例对象中的 isa 指向类结构称作 class(普通的),class 结构存储类的普通成员变量与普通成员方法(-开头的方法)。 super_class:一看就明白,指向该类的父类呗!如果该类已经是最顶层的根类(如 NSObject 或 NSProxy),那么 super_class 就为 NULL。 好,先中断一下其他类结构成员的介绍,让我们厘清一下在继承层次中,子类,父类,根类(这些都是普通 class)以及其对应的 metaclass 的 isa 与 super_class 之间关系: 规则一:类的实例对象的 isa 指向该类;该类的 isa 指向该类的 metaclass; 规则二:类的 super_class 指向其父类,如果该类为根类则值为 NULL; 规则三:metaclass 的 isa 指向根 metaclass,如果该 metaclass 是根 metaclass 则指向自身; 规则四:metaclass 的 super_class 指向父 metaclass,如果该 metaclass 是根 metaclass 则指向该 metaclass 对应的类; 好吧,文字总是那么乏力,有图有真相! 那么 class 与 metaclass 有什么区别呢? class 是 instance object 的类类型。当我们向实例对象发送消息(实例方法)时,我们在该实例对象的 class 结构的 methodlists 中去查找响应的函数,如果没找到匹配的响应函数则在该 class 的父类中的 methodlists 去查找(查找链为上图的中间那一排)。如下面的代码中,向str 实例对象发送 lowercaseString 消息,会在 NSString 类结构的 methodlists 中去查找 lowercaseString 的响应函数。 NSString * str;[str lowercaseString]; metaclass 是 class object 的类类型。当我们向类对象发送消息(类方法)时,我们在该类对象的 metaclass 结构的 methodlists 中去查找响应的函数,如果没有找到匹配的响应函数则在该 metaclass 的父类中的 methodlists 去查找(查找链为上图的最右边那一排)。如下面的代码中,向 NSString 类对象发送 stringWithString 消息,会在 NSString 的 metaclass 类结构的 methodlists 中去查找 stringWithString 的响应函数。 [NSString stringWithString:@"str"]; 好,至此我们明白了类的结构层次,让我们接着看类结构中的其他成员。 name:一个 C 字符串,指示类的名称。我们可以在运行期,通过这个名称查找到该类(通过:id objc_getClass(const char *aClassName))或该类的 metaclass(id objc_getMetaClass(const char *aClassName)); version:类的版本信息,默认初始化为 0。我们可以在运行期对其进行修改(class_setVersion)或获取(class_getVersion)。 info:供运行期使用的一些位标识。有如下一些位掩码: CLS_CLASS (0x1L) 表示该类为普通 class ,其中包含实例方法和变量; CLS_META (0x2L) 表示该类为 metaclass,其中包含类方法; CLS_INITIALIZED (0x4L) 表示该类已经被运行期初始化了,这个标识位只被 objc_addClass 所设置; CLS_POSING (0x8L) 表示该类被 pose 成其他的类;(poseclass 在ObjC 2.0中被废弃了); CLS_MAPPED (0x10L) 为ObjC运行期所使用 CLS_FLUSH_CACHE (0x20L) 为ObjC运行期所使用 CLS_GROW_CACHE (0x40L) 为ObjC运行期所使用 CLS_NEED_BIND (0x80L) 为ObjC运行期所使用 CLS_METHOD_ARRAY (0x100L) 该标志位指示 methodlists 是指向一个 objc_method_list 还是一个包含 objc_method_list 指针的数组; instance_size:该类的实例变量大小(包括从父类继承下来的实例变量); ivars:指向 objc_ivar_list 的指针,存储每个实例变量的内存地址,如果该类没有任何实例变量则为 NULL; methodLists:与 info 的一些标志位有关,CLS_METHOD_ARRAY 标识位决定其指向的东西(是指向单个 objc_method_list还是一个 objc_method_list 指针数组),如果 info 设置了 CLS_CLASS 则 objc_method_list 存储实例方法,如果设置的是 CLS_META 则存储类方法; cache:指向 objc_cache 的指针,用来缓存最近使用的方法,以提高效率; protocols:指向 objc_protocol_list 的指针,存储该类声明要遵守的正式协议。 总结: ObjC 为每个类的定义生成两个 objc_class ,一个即普通的 class,另一个即 metaclass。我们可以在运行期创建这两个 objc_class 数据结构,然后使用 objc_addClass 动态地创建新的类定义。这个够动态够强大的吧?下回讲演示如何在运行期动态创建新类。 本文转自 wws5201985 51CTO博客,原文链接:http://blog.51cto.com/wws5201985/782033,如需转载请自行联系原作者

优秀的个人博客,低调大师

iOS CoCoa编程中视图控制器与视图类

UITabBarController类,选项卡类允许用户在多个视图控制器之间移动并在屏幕的底部可定制该栏。向不同的视图同时提供一次单击访问,向用户选择的屏幕和编辑底栏的屏幕同时提供More按钮。 选项卡类的方便之处就是不需要象导航栏那样以栈的方式推入和弹出视图的操作,而是组建一系列的控制器(它们各自可以是UIViewController、UINavigationController、UITableViewController或其他任何类型的视图控制器),并通过设置栏的viewControllers属性将其添加到选项卡栏,使每个选项卡对应一个试图控制器。 一、创建UITabBarController · 常见的在应用程序委托类的applicationDidFinishLaunching:方法中创建,这通常可为应用窗口提供根视图。 // 创建一个UITabBarController对象 UITabBarController *tabBarController = [[UITabBarController alloc] init]; // tabBarController.delegate = self; // 创建一系列要添加到每个具体Tab卡的视图控制器 MyViewController *vc1 = [[MyViewController alloc] init]; MyOtherViewController *vc2 = [[MyViewController alloc] init]; // 将创建好的这些视图控制器先添加到一个Array对象中,再将此数组分配给Tab Bar Controller的viewControllers属性 NSArray *controllers = [NSArray arrayWithObjects:vc1,vc2,nil]; tabBarControllers.viewControllers = controllers; /* 也或者 NSMutableArray *controllers =[[NSMutableArray alloc] initWithCapacity:2]; [controllers addObject:vc1]; [controllers addObject:vc2]; */ // 将TabBar控制器的当前视图添加到窗口 [window addSubview:tabBarController.view]; // 或者设置应用窗口的根视图管理器为TabBarController self.window.rootViewController = self.tabBarController; 当然在应用程序委托AppDelegate类中创建UITabBarController,相当于创建了一个基于Tab Bar的工程项目。不过,也可以视具体情况,我们直接在一个独立的视图控制器中创建UITabBarController实例对象,如自定义一个用于视图切换的控制器类ViewSwitcherViewController,就可在其中的viewDidLoad方法中创建所需要的TabBarController。 · 在实现UITabBarControllerDelegate委托的视图控制器中重写init方法来自定义UITabBarItem条目。 代码一是由initWithNibName:方法来加载具体的某个视图控制器并自定义该控制器中TabBarItem样式外观等。 - (id)init { if(self = [super initWithNibName:@"MyViewController" bundle:nil]) { self.title = @"My View Controller"; UIImage *anImage = [UIImage imageNamed:@"MyImage.png"]; UITabBarItem *theItem = [[UITabBarItem alloc] initWithTitle:@"Home" image:anImage tag:0]; self.tabBarItem = theItem; [theItem release]; } return self; } 代码二我们也可以直接在具体的视图控制器内部重写init方法。 - (id)init { if([super init] != nil) { UITabBarItem *item = [[UITabBarItem alloc] initWithTitle:@"Home" image:[UIImage imageNamed:@"MyImage.png"] tag:0]; self.tabBarItem = item; [item release]; } return self; } · 实现所需的委托方法,以让UITabBarController能够正常触发这些回调方法。 tabBarController:didSelectViewController: 是当用户选择一个新的选项卡时,控制器会发送这个消息。 - (void)tabBarController:(UITabBarController *)tabBarController didSelectViewController:(UIViewController *)viewController { // 捕捉selectedIndex,可确定当前所选选项卡 NSNumber *tabNumber = [NSNumber numberWithInt:[tabBarController selectedIndex]]; // 使用iPhone内置用户默认系统NSUserDefaults,利用setObject:forKey:为关键字设定值 [[NSUserDefaults standardUserDefaults] setObject:tabNumber forKey:@"selectedTab"]; [[NSUserDefaults standardUserDefaults] synchronize]; // 选项卡图标项右上角红色小红圈数字提示 viewController.tabBarItem.badgeValue = [NSString stringWithFormat:@"%d",80]; } 本文转自 wws5201985 51CTO博客,原文链接:http://blog.51cto.com/wws5201985/765698,如需转载请自行联系原作者

优秀的个人博客,低调大师

iOS-《编写高质量代码》笔记-第七章 设计模式与Cocoa编程

建议45:设计模式是特定环境下的特定问题的解决方案 设计模式是某种特定设计的模板或指导原则。 建议46:MVC模式是一种复合或聚合模式 MVC 是一种高级别的模式,关注的是应用程序的全局架构,并根据各种对象在程序中发挥的作用对其进行分类。 建议47:对象建模在数据库中也广泛使用 看不懂 建议48:类簇可简化框架的公开架构而又不减少功能的丰富性 1.类簇(class cluster)基于抽象工厂设计模式。 2.类簇,可以用于隐藏实现的具体细节,为调用者提供一个简单的接口。 3.类簇也可以有多个基类,如NSArray、NSMutableArray,后者就是继承的前者。对一些“大同小异”的问题,往往会有不错的结果。 这个架构的用户只看到一个公共类,即NSNumber。

优秀的个人博客,低调大师

《从零开始学Swift》学习笔记(Day 66)——Cocoa Touch设计模式及应用之通知机制

通知(Notification)机制是基于观察者(Observer)模式也叫发布/订阅(Publish/Subscribe)模式,是MVC(模型-视图-控制器)模式的重要组成部分。 问题提出 天气一直是英国人喜欢讨论的话题,而最近几年天气的变化也成为中国人非常关注的话题。我会根据天气预报决定是坐地铁还是开车上班,我的女儿也会根据天气预报决定明天穿哪件衣服。于是我在移动公司为我的手机定制了天气预报短信通知服务,它的工作模型如图所示。 每天气象局将天气预报信息投送给移动运营商,移动运营商的短信中心负责把天气预报发送给定制过这项服务的手机。 在软件系统中,一个对象状态改变也会连带影响其他很多对象的状态发生改变。能够实现这一需求的设计方案有很多,但能够做到复用性强且对象之间匿名通信的,观察者模式是其中最为适合的一个。 解决方案 通知机制可以实现“一对多”的对象之间的通信。如图所示,在通知机制中对某个通知感兴趣的所有对象都可以成为接收者。首先,这些对象需要向通知中心(NSNotificationCenter)发出addObserver消息进行注册通知,在投送对象通过postNotificationName消息投送通知给通知中心,通知中心就会把通知广播给注册过的接收者。所有的接收者都不知道通知是谁投送的,更不关心它的细节。投送对象与接收者是一对多的关系。接收者如果对通知不再关注,会给通知中心发出removeObserver消息注销通知,以后不再接收通知。 本文转自 tony关东升 51CTO博客,原文链接:http://blog.51cto.com/tonyguan/1749097,如需转载请自行联系原作者

优秀的个人博客,低调大师

《从零开始学Swift》学习笔记(Day 64)——Cocoa Touch设计模式及应用之目标与动作

目标(Target)与动作(Action)是iOS和OS X应用开发的中事件处理机制。 问题提出 如图所示是一个ButtonLabelSample案例设计原型图,其中包含一个标签和一个按钮,当点击按钮的时候,标签文本会从初始的Label替换为HelloWorld。 ButtonLabelSample案例首先要解决的问题是:按钮点击事件后有谁负责响应事件?谁进行事件处理?要答这个问题,可以打开ButtonLabelSample案例故事板文件Main.storyboard,如图所示,OK按钮是在故事板文件Main.storyboard定义的,响应事件以及处理事件应该是在程序代码ViewController.swift实现的。那么如何将OK按钮点击事件与ViewController.swift中的事件处理代码关联起来?不同的计算机语言实现的方式不同,在iOS和OS X应用开发中是通过目标和动作机制实现事件处理的。 解决方案 按钮等控件是继承自UIControl类,具有一些高级事件,目标和动作机制就是将特地的控件事件与视图控制器(或视图)中方法关联起来,这个过程称为“定义动作事件”。“目标”是响应事件对象,为了方便访问其他的控件状态,这个对象一般是视图控制器(或视图)。“动作”是控件的事件。 ButtonLabelSample案例中按钮是在故事板文件(或Xib文件)中定义的,响应按钮点击事件(动作)是在视图控制器(目标)的方法中定义的,如下图所示,通过定义动作事件方式把目标与动作连接起来。 要实现目标与动作的连接有两种方式:InterfaceBuilder连线实现和编程实现。 1. Interface Builder连线实现 InterfaceBuilder连线实现就是故事板或Xib文件中,通过连线而现实。 2.编程实现 编程实现是通过UIControl类addTarget(_:action:forControlEvents:)方法实现的,主要代码如下: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 class ViewController:UIViewController{ overridefuncviewDidLoad(){ super .viewDidLoad() self.view.backgroundColor=UIColor.whiteColor() letscreen=UIScreen.mainScreen().bounds; letlabelWidth:CGFloat= 90 letlabelHeight:CGFloat= 20 letlabelTopView:CGFloat= 150 letlabel=UILabel(frame:CGRectMake((screen.size.width -labelWidth)/ 2 ,labelTopView,labelWidth,labelHeight)) label.text= "Label" //字体左右剧中 label.textAlignment=.Center self.view.addSubview(label) letbutton=UIButton(type:UIButtonType.System) //创建UIButton对象 button.setTitle( "OK" ,forState:UIControlState.Normal) letbuttonWidth:CGFloat= 60 letbuttonHeight:CGFloat= 20 letbuttonTopView:CGFloat= 240 button.frame=CGRectMake((screen.size.width -buttonWidth)/ 2 ,buttonTopView,buttonWidth,buttonHeight) button.addTarget(self,action: "onClick:" , forControlEvents:UIControlEvents.TouchUpInside) self.view.addSubview(button) } funconClick(sender:AnyObject){ NSLog( "OKButtononClick." ) } ... } 上述代码中创建并设置UIButton对象,其中创建UIButton对象,参数type是设置按钮的样式,UIButton样式: Custom。自定义类型。如果不喜欢圆角按钮,可以使用该类型。 System。系统默认属性,表示该按钮没有边框,在iOS 7之前按钮默认为圆角矩形。 Detail Disclosure。细节展示按钮,主要用于表视图中的细节展示。 Info Light和Info Dark。这两个是信息按钮,样式上与细节展示按钮一样,表示有一些信息需要展示,或有可以设置的内容。 Add Contact。添加联系人按钮。 代码调用addTarget(_:action:forControlEvents:)方法,方法第一个参数是target,即事件处理对象,本例中是self;方法第二个参数是action,即事件处理对象中的方法, 代码中是"onClick:",方法第三个参数是事件,TouchUpInside事件是按钮的触摸点击事件。 如果调用如下无参数方法: 1 2 funconClick(){ } 调用代码如下: 1 2 button.addTarget(self,action: "onClick" , forControlEvents:UIControlEvents.TouchUpInside) 区别在于action参数"onClick"方法名不同,action参数方法名的冒号暗示了方法名应该具有几个参数。如果要调用的方法是如下3个参数形式: 1 2 funconClick(sender:AnyObject,forEventevent:UIEvent){ } 那么调用代码如下: 1 2 button.addTarget(self,action: "onClick:forEvent:" , forControlEvents:UIControlEvents.TouchUpInside) 其中"onClick:forEvent:"是调用方法名,onClick表示方法名也是,forEvent表示第二个参数的外部参数名。 本文转自 tony关东升 51CTO博客,原文链接:http://blog.51cto.com/tonyguan/1748673,如需转载请自行联系原作者

优秀的个人博客,低调大师

《从零开始学Swift》学习笔记(Day 68)——Cocoa Touch设计模式及应用之响应者链与触摸事件

应用与用户进行交互,依赖于各种各样的事件。事件响应者对象是可以响应事件并对其进行处理的对象,响应者链是由一系列链接在一起的响应者组成的。响应者链在事件处理中是非常重要的,响应者链可以把用户事件路由给正确的对象。 响应者对象与响应链 UIResponder是所有响应者对象的基类,它不仅为事件处理,而且也为常见的响应者行为定义编程接口。UIApplication、UIView(及其子类,包括UIWindow)和UIViewController(及其子类)都直接或间接地继承自UIResponder类。 第一响应者是应用程序中当前负责接收触摸事件的响应者对象(通常是一个UIView对象)。UIWindow对象以消息的形式将事件发送给第一响应者,使其有机会首先处理事件。如果第一响应者没有进行处理,系统就将事件(通过消息)传递给响应者链中的下一个响应者,看看它是否可以进行处理。 响应者链是一系列链接在一起的响应者对象,它允许响应者对象将处理事件的责任传递给其他更高级别的对象。随着应用程序寻找能够处理事件的对象,事件就在响应者链中向上传递。响应者链由一系列“下一个响应者”组成。 1.第一响应者将事件传递给它的视图控制器(如果有的话),然后是它的父视图。 2.类似地,视图层次中的每个后续视图都首先传递给它的视图控制器(如果有的话),然后是它的父视图。 3.最上层的容器视图将事件传递给UIWindow对象。 4.UIWindow对象将事件传递给UIApplication单例对象。 触摸事件 触摸(UITouch)对象表示屏幕上的一个触摸事件,访问触摸是通过UIEvent对象传递给事件响应者对象的。触摸对象有时间和空间两方面。 1.时间方面 时间方面信息称为阶段(phase),表示触摸是否刚刚开始、是否正在移动或处于静止状态,以及何时结束,也就是手指何时从屏幕抬起。 在给定的触摸阶段中,如果发生新的触摸动作或已有的触摸动作发生变化,则应用程序就会发送这些消息。 当一个或多个手指触碰屏幕时,发送touchesBegan:withEvent:消息。 当一个或多个手指在屏幕上移动时,发送touchesMoved:withEvent:消息。 当一个或多个手指离开屏幕时,发送touchesEnded:withEvent:消息。 2.空间方面 触摸点对象还包括当前在视图或窗口中的位置信息,以及之前的位置信息(如果有的话)。下面的方法是可以获得触摸点所在窗口或视图中的位置。 func locationInView(_ view:UIView?) -> CGPoint 获得前一个触摸点所在窗口或视图中的位置信息: func previousLocationInView(_view: UIView?) -> CGPoint 本文转自 tony关东升 51CTO博客,原文链接:http://blog.51cto.com/tonyguan/1749103,如需转载请自行联系原作者

资源下载

更多资源
腾讯云软件源

腾讯云软件源

为解决软件依赖安装时官方源访问速度慢的问题,腾讯云为一些软件搭建了缓存服务。您可以通过使用腾讯云软件源站来提升依赖包的安装速度。为了方便用户自由搭建服务架构,目前腾讯云软件源站支持公网访问和内网访问。

Rocky Linux

Rocky Linux

Rocky Linux(中文名:洛基)是由Gregory Kurtzer于2020年12月发起的企业级Linux发行版,作为CentOS稳定版停止维护后与RHEL(Red Hat Enterprise Linux)完全兼容的开源替代方案,由社区拥有并管理,支持x86_64、aarch64等架构。其通过重新编译RHEL源代码提供长期稳定性,采用模块化包装和SELinux安全架构,默认包含GNOME桌面环境及XFS文件系统,支持十年生命周期更新。

Sublime Text

Sublime Text

Sublime Text具有漂亮的用户界面和强大的功能,例如代码缩略图,Python的插件,代码段等。还可自定义键绑定,菜单和工具栏。Sublime Text 的主要功能包括:拼写检查,书签,完整的 Python API , Goto 功能,即时项目切换,多选择,多窗口等等。Sublime Text 是一个跨平台的编辑器,同时支持Windows、Linux、Mac OS X等操作系统。

WebStorm

WebStorm

WebStorm 是jetbrains公司旗下一款JavaScript 开发工具。目前已经被广大中国JS开发者誉为“Web前端开发神器”、“最强大的HTML5编辑器”、“最智能的JavaScript IDE”等。与IntelliJ IDEA同源,继承了IntelliJ IDEA强大的JS部分的功能。

用户登录
用户注册