给Android程序员看的Objective-C入门
yuyutoo 2024-11-17 03:42 3 浏览 0 评论
作者:snwrking
前言
最近两年因为公司业务需求, 我从Android开发转成了也涉猎前端的工作, 主要在做一些Android与ReactNative了.
但是众所周知的是, React Native其实是一个严重先天不足的跨平台框架. 简言之, 就是RN仅仅是一个UI框架, facebook在创建之初就是想使用yoga(跨平台的UI库)来包两个平台的UI代码. 而一旦是非UI的内容, 比如说sensor, network, security, permission, ..., 那RN就很捉急了.
当然RN并不是完全没办法, 它的做法就是分而治之, 把这些东西下放到两个native平台去做, 然后把结果通过bridge告诉js端就行了. 这一点, 其实也就意味着, 对于稍深一些的RN功能, 程序员得了解js, android, iOS平台的开发. 比如说, 我们最近要做一个本地的server, 运行在手机上. 这个明显就是非UI的内容, 所以我得在android与iOS平台上分别写代码. (其实有一个react-native-static-server的库可以参照, 但我们的需求还要读到内容后解密, 所以更复杂, 需要我们自己定制)
这样的native开发的需求, 就引发了我们js开发, android开发, 得去了解些iOS的知识. 另外, 因为RN中的iOS代码是objective-C, 所以我们学习的语言就不是swift, 而是更古老(更反人类)的OC了.
Swift 还是 OC?
上面讲过, 对于RN开发来说, 一般使用OC较多. 特别是一些特别需求, 如加密, Swift是2020年2月才有了crypto库, 以前都没有的. 这些东东都只好使用OC来开发.
另外, Swift其实底层也在利用OC, 像是selector, 所以即使使用Swift, 你还是得了解一些OC的内容.
最后, iOS开发中一个好处就是它可以直接利用C的库. OC可以方便的利用C的库. 例子有很多个
- 线程中的GCD, 其实使用的就是C语言的GCD库.
- iOS不像java, 不能天生支持zip压缩/解压. 这时OC可以方便利用MiniZip这样的库里的 .h, .c文件.
综上所述, 这篇文章主要还是在介绍OC
OC里的类型
数字
因为OC是C语言一系的, 所以那些复杂的数据类型在OC里都是支持的, 如short, unsigned long ... 这些类型在java中没有, 所以多提一句.
另外, 数字的字面值, java中直接使用数字就行, 如int i = 20; 但在OC中得加一个@, 表示是OC中的值(而不是C中的值), 所以OC中的数字20就是表示为 @20.
字符串
同理, OC中的String字面值, 也得前面加@. 不然的话, ""是表示C中的字符串, 也就是char[]. 只有@"", 才表示是一个NSString类型, 这是一个类, 而不是char数组了.
经常打印日志所用到的格式化输出则是用 %@来做占位符. 如:
NSString* name = @"xxx";
NSLog(@"hello %@", name); //=> hello xxx
对象
和java中不一样, java中的对象其实都是指针, 但你不用写明, 因为java本身并没有"指针"的概念. 但在C系语言中, 指针很常见. OC则是显示地认为每个对象都是指向一堆内存的指针, 所以我们得这样定义对象: NSString* name = @"xxx";.
(注意这里的*就表示是一个指针)
函数
好吧, 这可能是java/js程序员看起来最反人类的地方了.
先说结论:
- OC中的方法调用是用中括号表示的 (其它大多数语言都是使用小括号的);
- 参数要带参数说明
- 而参数与参数之间用空格表示
再来看例子:
java:
String memo = "memo.txt";
String extension = memo.substring(5);
OC:
NSString* memo = @"memo.txt";
NSString* extension = [memo substring: 5];
要是更多参数, 那就这样: [object method:arg1 arg2Name:arg2 arg3Name:arg3] 还是举例来说明:
/* declaration */ + (NSData *)decryptContent:(NSData *)encrypted withKey:(NSData *)key;
/* usage */ [obj decryptContent: encrypted withKey: key];
/* declaration */ - (void)stop;
/* usage */ [obj stop];
这里的withKey就是参数名, key是实参名. 在调用这个decryptContent方法时, 除了第一个参数, 都要带上参数名.
这其实就相当于java中的
obj.decryptContent(byte[] content, byte[] key);
obj.stop();
源文件
java中只有".java", js也只有".js"文件. 但是C系语言都分了头文件与实现文件. C中是 : .h, .c OC中是: .h, .m
其实.h是头文件, 类型于java中的public声明. 所有能被外部文件访问的成员与方法都定义到.h里.
.m就是真正实现. 一些不对外开放的方法成员, 在.m里也能存在.
类
OC中的类声明也得分两部分: interface与implementation, 分别代表定义与实现. 一般interface放到.h里去, 这样其它文件可以调用这个类. 而implementation一般写在.m文件里. 比如说:
// MyClass.h
@interface MyClass: NSObject {
NSString* name; //property
}
-(void)hello:(NSString*)name; //method
@end
注意:
1). 和java不同, 就是你的类是NSObject的子类, 你也得写明. java中若是Object的子类, 就不用写明extends Object也是行的.
2). 类的方法定义, 最前面是+或-.
- +就代表static方法, 以后调用就是[MyClass func]
- -代表成员方法, 调用使用对象, 而不是类名, 如[obj func]
3). 方法返回值放到小括号里, 如上面的(void).
4). 上面的name是参数. 在调用时就是: [obj hello:@"xx"];
实现体则是:
@implementation MyClass
-(void) hello:(NSString*)name{
NSLog(@"hello, %@", name);
}
@end
即
- interface中只有成员/方法的定义, 没有实现.
- implementation里就是写完方法体, 这个方法到底是干嘛的
category
这个有点类似kotlin中的extension. 即你可以任意扩展某个类. 即使这类是一个系统类, 你也可以扩展.
定义一个category就类似定义一个类, 只不过你不用写super class, 而是用(category名字)来代替父类名.
下面是一个例子. 普通NSString是没有uuid方法的. 现在我们给NSString新加一个uuid方法, 调用这个新方法就会得到一个随机uuid值.
// NSString+Uuid.h
#import <Foundation/Foundation.h>
@interface NSString (Uuid)
+ (NSString*) uuid;
@end
// NSString+Uuid.m
#import "NSString+Uuid.h"
@implementation NSString (Uuid)
+ (NSString*) uuid {
CFUUIDRef uuidRef = ...;
return uuidString;
}
@end
protocol
protocol就是java中的接口, 即一堆方法定义的集合. 因为都是表示抽象, 所以和java接口类似, protocol在OC中就只有.h文件, 没有.m文件.
@protocol ServerPlugin <NSObject>
@required -(void) serve: (int) id;
@end
// if you want to use the protocol, use it as a generics:
@interface HttpServer: NSObject<ServerPlugin>;
@end
protocol中的注意事项
在java中, 我们可以使用Map<String, Iinterface>. 取出值时就是: Iinterfae obj = map.get(key);
但在OC中, 是不能使用 某Protocol obj = [map objectForKey:key]; 因为Protocol本身根本就不是一个对象, 只是一个抽象概念. 所以正确的写法是:
NSOjbect<某Protocol> plugin1 = [dictionary objectForKey:@"key1"];
内存管理
C中的内存管理是手动的, 即当你malloc申请开辟新内存块后, 你最后也得注意把这内存给free了. OC也是这样的.
但java程序员, 或者说所有程序员, 都会觉得这样好烦, 而且容易忘记free某对象的引用时, 就会内存泄露, 极易出问题. 所以在2011年, apple也引入ARC(Auto Reference Counting), 即自动帮你记录引用数, 并在脱离作用域时帮你release掉引用. 这其实就类似java中的GC. 这样OC开发总算从内存的沼泽中被释放了出来.
当然你也不是100%全自动内存管理了. 当你在处理一些C的库, 或Core Foundation框架时,这些C的部分都没有被ARC覆盖, 所以你仍得注意自己得释放到申请的内存.
总结
以上就是我作为一个Android开发, 入手OC时碰到的一些基本知识点,分享出来, 希望能帮助更多有需要的人.
文末附上大厂学长给我的资料,内容包含:Android学习PDF+架构视频+面试文档+源码笔记,高级架构技术进阶脑图、Android开发面试专题资料,高级进阶架构资料 这几块的内容
分享给大家,非常适合近期有面试和想在技术道路上继续精进的朋友。也是希望可以帮助到大家提升进阶
如果你有需要的话,可以私信我【提升】我发给你
相关推荐
- MySQL中的数据类型(mysql数据类型有哪些,并举例)
-
MySQL中的数据类型...
- mysql窗口函数over中rows_MySQL窗口函数
-
下面的讲解将基于这个employee2表:mysql>SELECT*FROMemployee2;+----+-----------+------+---------+---------...
- 别再说你精通数据库,MySQL的设计和列类型选取真的很有讲究
-
总想写一篇MySQL的设计和列类型选取的文章,一直挤不出时间。天天晚上都要加班,正逢5.1放假,抽了几天就有了此文。如果对朋友们能有帮助的话,关注一波不过分吧?求关!选择更优的数据类型尽量选择存储空间...
- MySQL数据库知识(mysql数据库相关知识)
-
MySQL是一种关系型数据库管理系统;那废话不多说,直接上自己以前学习整理文档:查看数据库命令:(1).查看存储过程状态:showprocedurestatus;(2).显示系统变量:show...
- 数据库:MySQL 高性能优化规范建议
-
数据库命令规范所有数据库对象名称必须使用小写字母并用下划线分割所有数据库对象名称禁止使用MySQL保留关键字(如果表名中包含关键字查询时,需要将其用单引号括起来)数据库对象的命名要能做到见名识意,...
- MySQL实战——表结构设计之数字类型
-
整型不建议刻意去用unsigned属性,因为在做一些数据分析时,SQL可能返回的结果并不是想要得到的结果。比如在财务的场景下,经常会做一些加减操作。MySQL要求unsigned数值相减之...
- MySQL数据库入门(四)数据类型简介
-
在MySQL中数据类型有以下五种:数字整数:常用的有2种,一是int型,int型最多可以表示10位数字(无符号的4开头,有符号的2开头;二是tinyintunsigned,用来表示年龄(值范围是0-...
- mysql常用语句超级详细汇总(mysql常用语法)
-
1.连接数据库:连接本地数据库:mysql-uroot-p连接远程数据库:mysql-h192.169.22.199-uroot-p退出数据库:exit...
- MYSQL——CAST()函数的用法(mysql中case)
-
语法为:Cast(字段名as转换的类型),其中类型可以为:CHAR[(N)]字符型DATE日期型DATETIME日期和时间型...
- MySQL存储引擎背后的真相:为何InnoDB并非所有场景的最佳选择
-
MySQL存储引擎背后的真相:为何InnoDB并非所有场景的最佳选择引言部分你是否遇到过这样的情况:明明已经按照最佳实践选择了MySQL的InnoDB引擎,却发现某些查询依然缓慢得令人沮丧?或者当你的...
- MySQL 表分区?涨知识了(mysql数据表分区)
-
1.什么是表分区...
- 《MySQL必知必会》_笔记08(mysql必知必会mobi)
-
第19章插入数据一、数据插入概述INSERT语句用于向数据库表中插入(添加)数据,是SQL中常用的数据操作语句之一。它可以用多种方式使用,包括插入完整的行、插入行的一部分、插入多行以及插入某些查询的...
- 当 SQL Server(mssql-jdbc) 遇上 BigDecimal → 精度丢失,真坑!
-
开心一刻 中午和哥们一起喝茶 哥们说道:晚上喝酒去啊...
- MYSQL有哪些数据类型(mysql有哪些数据类型,有哪些运算符)
-
整理下以便查阅,还想吐槽下:这头条怎么就不能给文章分类呢?整数类型...
- 使用MySQL分区的注意事项(使用mysql分区的注意事项有哪些)
-
MySQL分区是将一个表分解成多个区块进行操作和保存,从而降低每次操作的数据量,提高性能。从逻辑上看,只有一个表,但物理上这个表可能由多个物理分区组成,每个分区都是一个独立的对象,可以进行独立处理。...
你 发表评论:
欢迎- 一周热门
-
-
前端面试:iframe 的优缺点? iframe有那些缺点
-
带斜线的表头制作好了,如何填充内容?这几种方法你更喜欢哪个?
-
漫学笔记之PHP.ini常用的配置信息
-
推荐7个模板代码和其他游戏源码下载的网址
-
其实模版网站在开发工作中很重要,推荐几个参考站给大家
-
[干货] JAVA - JVM - 2 内存两分 [干货]+java+-+jvm+-+2+内存两分吗
-
正在学习使用python搭建自动化测试框架?这个系统包你可能会用到
-
织梦(Dedecms)建站教程 织梦建站详细步骤
-
【开源分享】2024PHP在线客服系统源码(搭建教程+终身使用)
-
2024PHP在线客服系统源码+完全开源 带详细搭建教程
-
- 最近发表
- 标签列表
-
- mybatis plus (70)
- scheduledtask (71)
- css滚动条 (60)
- java学生成绩管理系统 (59)
- 结构体数组 (69)
- databasemetadata (64)
- javastatic (68)
- jsp实用教程 (53)
- fontawesome (57)
- widget开发 (57)
- vb net教程 (62)
- hibernate 教程 (63)
- case语句 (57)
- svn连接 (74)
- directoryindex (69)
- session timeout (58)
- textbox换行 (67)
- extension_dir (64)
- linearlayout (58)
- vba高级教程 (75)
- iframe用法 (58)
- sqlparameter (59)
- trim函数 (59)
- flex布局 (63)
- contextloaderlistener (56)