初学者的iOS开发学习笔记

作为一个 iOS 开发的初学者,记录一下自己自学 iOS 过程中的一些坑和问题,仅供参考。

1、Main Bundle Id + Extension Bundle Id(小组件)

规则:前半部分相同,后半部分 + .extension

1
2
Main app bundle id: com.myapp.testapp
Extension app bundle id: com.myapp.testapp.myextension

2、iOS 加异常断点

https://blog.csdn.net/wu_shu_jun/article/details/9045911

https://www.jianshu.com/p/3a0803406d04

https://www.jianshu.com/p/7c0352231eca

3、Incompatible block pointer types sending ‘void

找到对应的报错库,添加:-Xclang -fcompatibility-qualified-id-block-type-checking

链接:https://www.jianshu.com/p/317bdbe86454

这种是临时解决方案,最好的方式是升级对应的第三方库;

4、uncaught exception ‘NSInvalidArgumentException’, reason: ‘+[_LSDefaults sharedInstance]: unrecognized selector sent to class

https://blog.csdn.net/survivorsfyh/article/details/104942440

5、从 pod 删除第三方库:

先在 podfile 文件中删除 pod ‘JSONKit’,然后在执行更新命令

1
pod update  --no-repo-update

6、**’sharedApplication’ is unavailable: not available on iOS (App Extension) - Use view controller based**

小组件中不能使用 sharedApplication 获取 UIApplication 对象;

https://stackoverflow.com/questions/29288217/watchkit-sharedapplication-is-unavailable-not-available-on-ios-app-extensi

7、设置APPLICATION_EXTENSION_API_ONLY

1
2
3
4
5
6
7
post_install do |installer_representation|
installer_representation.pods_project.targets.each do |target|
target.build_configurations.each do |config|
config.build_settings['APPLICATION_EXTENSION_API_ONLY'] = 'NO'
end
end
end

8、页面(ViewController)跳转

8.1 Push

1
2
BadgeController *vc = [[BadgeController alloc] init];
[self.navigationController pushViewController:vc animated:YES];

8.2 Pop(关闭页面)

1
2
3
4
5
6
7
8
[self dismissViewControllerAnimated:YES completion:^{
}];

// 或者
[self.navigationController dismissViewControllerAnimated:true completion:nil];

// 或者
[self.navigationController popViewControllerAnimated:YES];

9、ViewController中用代码实现显示 UIImageView UILabel UIButton UI 控件

页面步骤如下:

跟在Android中差不多:

1、创建view对象;

2、设置view的各种属性,如大小摆放位置等;

3、添加到父视图中;

10、Programming with Objective-C (Apple Development)

https://developer.apple.com/library/archive/documentation/Cocoa/Conceptual/ProgrammingWithObjectiveC/DefiningClasses/DefiningClasses.html#//apple_ref/doc/uid/TP40011210-CH3-SW1

11、iOS 设置点击事件:

// 方式一

1
2
3
4
[self.infoView addTapActionWithBlock:^(UIGestureRecognizer *gestureRecoginzer) {
@strongify(self)
// todo
}];

// 方式二:

1
2
3
4
5
6
7
UIImageView *iKnowIcon = [CYResource loadImageView:@"free-question-once-more-i-know.png"];
iKnowIcon.top = questionIcon.top + scaleWidthWith320(200);
iKnowIcon.centerX = self.width / 2;
[self addSubview:iKnowIcon];
UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(dismiss)];
iKnowIcon.userInteractionEnabled = YES;
[iKnowIcon addGestureRecognizer:tap];

方式三:

1
2
3
4
5
6
7
8
9
10
11
12
13
// 步骤1:创建手势响应函数
- (void)event:(UITapGestureRecognizer *)gesture
{
//处理事件
}

// 步骤2:创建手势
UITapGestureRecognizer * tapGesture = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(event:)];

// 步骤3:给View添加手势
//设置需要连续点击几次才响应,默认点击1次
[tapGesture setNumberOfTapsRequired:1];
[topView addGestureRecognizer:tapGesture];

12、iOS 事件传递

iOS 中只有继承了 UIResponse 的对象才能够接受处理事件。UIResponse是响应对象的基类,定义了处理上述各种事件的接口。常见的子类有:UIView,UIViewController,UIApplication和UIApplicationDelegate.

链接:https://juejin.cn/post/6873761108662943757

记账 app 中设置的点击事件

因为 MineController 是 UIResponse 的子类,而 UIResponse 扩展了QFEventHandle,实现了routerEventWithName 方法,所以,在 MineController 中实现了 routerEventWithName 方法,子 View 在调用这个方法时,传递了点击事件类型,MineController 中会收到回调,而它里面绑定了各种点击事件类型的处理,所有可以处理点击事件。

13、屏幕底部显示如下样式的popup window

IMG_4466

// 更多登录方式

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
- (IBAction)moreBtnClick:(UIButton *)sender {
UIActionSheet *sheet = [[UIActionSheet alloc] initWithTitle:nil delegate:nil cancelButtonTitle:@"取消" destructiveButtonTitle:nil otherButtonTitles:@"注册", @"手机登录", nil];

[sheet showInView:self.view];
[[sheet rac_buttonClickedSignal] subscribeNext:^(NSNumber *number) {
NSInteger index = [number integerValue];

// 注册
if (index == 0) {
RE1Controller *vc = [[RE1Controller alloc] init];
[self.navigationController pushViewController:vc animated:YES];
}

// 手机登录
else if (index == 1) {
PhoneController *vc = [[PhoneController alloc] init];
[self.navigationController pushViewController:vc animated:YES];
}
}];
}

14、NSNotificationCenter 使用(类似于EventBus)

// 前一个页面监听通知

1
2
3
- (void)rac_notification_register {
@weakify(self)
}

// 登录完成

1
2
3
4
5
6
7
8
9
10
11
[[[[NSNotificationCenter defaultCenter] rac_addObserverForName:LOPGIN_LOGIN_COMPLETE object:nil] takeUntil:self.rac_willDeallocSignal] subscribeNext:^(id x) {
@strongify(self)
// 回调
if (self.complete) {
self.complete();
}

// 关闭
[self.navigationController dismissViewControllerAnimated:true completion:nil];
}];
}

// 后一个页面发送通知

1
[[NSNotificationCenter defaultCenter] postNotificationName:LOPGIN_LOGIN_COMPLETE object:nil];

15、将View 跟 xib 文件绑定到一起

1
[_collection registerNib:[UINib nibWithNibName:@"FindBookCell" bundle:nil] forCellWithReuseIdentifier:@"FindBookCell"];

16、控件不显示

如果不显示,可能是被其他控件遮挡住了,设置的约束有问题,可通过 Debug View Hierarchy 看 View 的层级;

17、UIButton 才可以设置点击事件,UIImageView 不可以;

如果需要给 UIImageView 设置点击事件,需要设置它可点击。

18、 OC 中 #pragma mark的意义和作用

它们告诉Xcode编译器,要在编辑器窗格顶部的方法和函数弹出菜单中将代码分隔开,一些类(尤其是一些控制器类)可能很长,方法和函数弹出菜单可以便于代码导航。此时加入 #pragma 指令对代码进行逻辑组织很有效果。

19、设置启动图

有两种方式,方式一:LaunchImage,已被废弃,官方推荐使用 LaunchScreen.storyboard 配置启动图,从 2020.4.30 开始提交 App Store 必须使用故事板来设置启动图。

20、判断相等

1
2
3
4
5
6
7
8
9
10
void f1() {
NSNumber* num1 = [NSNumber numberWithInt:23];
NSNumber* num2 = [NSNumber numberWithFloat:23.0f];
BOOL b = [num1 isEqualToNumber:num2];
if (b) {
NSLog(@"相等");
}else {
NSLog(@"不相等");
}
}

21、《Objective-C For Absolute Beginners》源码

https://github.com/Apress/Objct-C-Abs-Begs

https://github.com/Apress/objective-c-for-absolute-begs-3ed

https://github.com/Apress/objective-c-for-absolute-begs-11

https://github.com/Apress/objective-c-for-absolute-begs