错误提示ld: 2 duplicate symbols for architecture arm64
少年,这句话的意思是在编译的时候发现有一个类的名字被定义和写了两次,通常是你改了文件名,但是类名起的一样,导致链接的时候发生冲突。编译器不知道应该读哪个文件里的类作为定义。
出现的错误 duplicate symbols,有重复(异议)的符号
解决方法
找到重复的地方,从新写或者在target->Build phases->compile sources里编译列表去掉一个就可以了
均需要使用UITextFieldDelegate中的方法
1 | - (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string { |
上述判断条件是利用了删除键的长度为0,即当输入框输入为n位的时候
下述判断条件,输入为n时,也是用删除键传入的字符串实际为@””,进行是否在最后一位可以删除的判断
1 | - (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string { |
如果不进行判断,可能导致输入满n位却无法删除的现象
1 | - (void)instituteSubviews { |
一旦使用AutoLayout 的话与之对应的是所有View的Frame就无效了,需要通过指令设置
1 | [view setTranslatesAutoresizingMaskIntoConstraints:NO]; |
添加约束的方法有单条和多条两种,注意后边的“s”,单条约束添加的是NSLayoutConstraint,而多条约束添加的是以NSLayoutConstraint为元素的数组
1 | [view addConstraint:(NSLayoutConstraint *)constraint]; |
对应生成NSLayoutcontraint的方法也有两种,单条生成和生成一个数组,生成数组的方法称为VFL(Visual format language),类似颜文字的逗比方式
1 | /* Create constraints explicitly. Constraints are of the form "view1.attr1 = view2.attr2 * multiplier + constant" |
就像苹果源文件里注释的一样,单条生成的方法是要遵循一定公式的,公式是可以进行交换运算和乘除的。但是苹果的工作人员发现,这个坑爹的函数实在太长了,以至于最后一个参数的形参只用了一个c,所以才会有VFL
1 | //(NSArray<__kindof NSLayoutConstraint *> *) |
添加autolayout必须遵循以下原则
在确定了四项属性后,需要在正确的View添加上约束
VFL中字符串的意义
H:|[view()]-gap-|
虽然autolayout和控件的Frame互相冲突,但是并不是说Frame始终无法获取。以下是生命周期中可以获取到Frame的函数
1 | //.h |
1 | //.h |
1 | //在自定义的View中重载函数 |
以上动态更新都可以放在[UIView animateWithDuration:0.2 animations:^{}]中平滑过渡
1 | UIView *subView = [[UIView alloc]init];//实例化一块内存A,然后局部变量指向它 |
如果在.m的interface中使用强指针的话,那么在**[self.view addSubview]**也会存在一个强指针,那么就会有两个Retain。为了保证该内存伴随VC存在,只要VC的addSubview这个强指针一旦被释放就应该被释放,应该似的其Retain始终唯一。
理由: 一条狗应该只用一个绳子牵,绳子一松,狗就跑了,而不是一条狗用两条绳子拴着
!!!这是什么理由啊 (╯°Д°)╯︵ /(.□ . )
结论: 就是一个内存管理的强迫症,可以遵循也可以不遵循
1 | _subView = [[UIView alloc]init];//实例化一块内存A,直接用全局变量指向它 |
Copy: 根据旧内存空间的对象A开辟一个块新的内存空间新对象B,AB内存地址不同,内容完全一样,B的ARC计数为1,A的ARC计数不变
Retain: 新建一个指针指向旧内存空间的对象A,使A的ARC计数+1
iOS中并不是所有对象都可以进行Copy,仅有遵循了NSCopying协议的对象才可以进行Copy。所以说自定的NSObject对象需要遵循
与NSCopying对应的还有NSMutableCopying协议,分别是对固定内存空间和可变内存空间进行Copy
1 | //**正常开辟固定字符串a,可变字符串b** |
综上实验,如果实际内存空间和拷贝方法均为不可变时,系统执行浅拷贝,若实际内存空间和拷贝方法有一个为可变时,那么系统就执行深拷贝,开辟新内存。
系统容器的本身的深拷贝和浅拷贝的规律与NSString一模一样,但是至于容器内元素是否可以通过copyItems进行深拷贝仅仅和元素自己有关
1 | NSArray *array1 = [NSArray arrayWithObjects:@"a",@"b",@"c",nil];//开辟内存空间A(存放的array1) |
由于array1内实际存放的是元素的地址,那么虽rray3和array1的内存地址不同,但是存放的内容(元素地址)是相同的。如果通过array3对其中第一个元素进行了修改,然后通过array1[0]去访问这个元素时,就是array3修改后的值
所以说虽然容器array进行了深拷贝,但是array内部的元素并没有进行拷贝,仅仅是因为多开辟了内存B,出现了同样个数的指针,指向所有元素,让所有元素存在的内存ARC计数+1而已
1 | NSArray *array1 = [NSArray arrayWithObjects:@"a",@"b",@"c",nil];//开辟内存空间A(存放的array1) |
由以上描述可以看出重新初始化一块新内存进行深拷贝,然后根据copyItems去执行NSCopying协议对每个元素也进行深拷贝。
但是,如果容器内元素不自带NSCopying协议,例如自定义的NSObject,那么就会自动对该元素进行浅拷贝,即原内存地址ARC计数+1
1 | NSArray *array1 = [NSArray arrayWithObjects:@"a",@"b",@"c",nil];//开辟内存空间A(存放的array1) |
在不确定array内部元素是否有遵循NSCopying协议的情况下,这种方法可以进行真正的深拷贝,和原内存地址毫无关系,通过系统读取本地档案的方法来开辟新的内存。
由于OC中可以使用不可变指针指向可变内存,也可以使用可变指针指向不可变内存
1 | NSMutableString *str1 = @"constant"; |
如上所示,虽然编译器会提示警告,但是编译还是可以通过。
如果没有注意到警告经过多次指向,或者放入了某种容器Array然后取出,警告就会被隐藏。
1 | NSMutableString *str2 = st1; |
一旦错误的可变内存变量(str2,array2,dict2)执行了类似addValue之类改变内存空间的的指令就会Crash。
大坑:
所以说如果从服务器端接受到了Json字符串最开始存成了不可变的NSDictionary,那么想把其变成可变字典NSMutableDictionary尽兴操作时一定要深拷贝
1 | //.m |
1 | [self.navigationController.navigationBar setBarTintColor:[UIColor redColor]]; |
1 | [self.navigationController.navigationBar setTranslucent:YES]; |
1 | [self.navigationController.navigationBar setBackgroundImage:[UIImage imageNamed:@"FlyElephant.png"] forBarMetrics:UIBarMetricsDefault]; |
之前设置是通过UITextAttributeFont,UITextAttributeTextColor,UITextAttributeTextShadowColor和UITextAttributeTextShadowOffset设置,现在需要都根据NS开头的属性去设置
1 | NSDictionary *textAttributes=@{NSForegroundColorAttributeName:[UIColor whiteColor],NSFontAttributeName:[UIFont systemFontOfSize:20]}; |
1 | [self.navigationItem setTitle:@"旅行"]; |
1 | //单个leftItem设置: |
如果把字符串看成Char组成的Array的话,由于是可变的,那么一定是个Mutable的Array,于是需要用NSMutableAttributedString
NSMutableAttributedString *protocolText = [[NSMutableAttributedString alloc]initWithString:@"同意协议"];
[protocolText addAttribute:NSForegroundColorAttributeName value:COLOR_PEACHRED range:NSMakeRange(2, 2)];
//添加成某个Button的Title
[_protocolBtn setAttributedTitle:protocolText forState:UIControlStateNormal];
尼玛,我是个野路子,没用过
- (void)addAttribute:(NSString *)name value:(id)value range:(NSRange)range;
这个函数,怎么办?而且这个value是个id类型的,我不知道传什么怎么办,百度不到.
只好拿着这个函数去帮助文档搜索,看到对Value的解释
attributes
A dictionary containing the attributes to add.
Attribute keys can be supplied by another framework or can be custom ones you define.
For information about where to find the system-supplied attribute keys,
see the overview section in #NSAttributedString Class Reference#.
其中NSAttributedString Class Reference是个链接,看意思是可以传入的值,于是点进去看看
英文好的,基本就可以看得很明白了,讲这里是干嘛用的,英文不好的,只要认识Guide,就知道这个see Attributed String Programming Guide是指导,再进入.
进来后就是Cocoa的全部教程,第一个就是默认的都是哪些
Attributed Strings describes the attributed string objects instantiated from NSAttributedString,
NSMutableAttributedString, CFAttributedString and CFMutableAttributedString.
再次进入文档
For example, the text font is stored as an NSFont object under the name given by NSFontAttributeName.
这里的已经写的更明白了,叫For example,就是看NSFontAttributeName
NSForegroundColorAttributeName
The value of this attribute is a UIColor object. Use this attribute to specify the color of the text during rendering. If you do not specify this attribute, the text is rendered in black.
Available in iOS 6.0 and later.
找到了说明,看懂了之后赶快试一试,因为是字符串嘛,第一反映为把这个作为字符串传进去
[protocolText addAttribute:@"NSForegroundColorAttributeName" value:COLOR_PEACHRED range:NSMakeRange(2, 2)];
发现@”NSForegroundColorAttributeName”传入,并没有效果,于是去查NSForegroundColorAttributeName到底是什么
NSString *const NSForegroundColorAttributeName;
发现在OC中是个不变的字符串,头文件中如此定义
UIKIT_EXTERN NSString * const NSForegroundColorAttributeName NS_AVAILABLE(10_0, 6_0); // UIColor, default blackColor
这个可以去看UIKIT_EXTERN的讲解,总之NSForegroundColorAttributeName是个变量名,其实际字符串并不是这个,通过打印可以得到实际字符串是@”NSColor”;回想函数的第一个值是”id”是个指针类型,并不是String啊!又把C++的习惯带来了…坑
所以说有效的调用是以下两种
[protocolText addAttribute:NSForegroundColorAttributeName value:COLOR_PEACHRED range:NSMakeRange(2, 2)];
//但是第二个比较作死,只是能用,但是不要写
[protocolText addAttribute:@"NSColor" value:COLOR_PEACHRED range:NSMakeRange(2, 2)];
viewController里重写函数
1 | - (UIStatusBarStyle)preferredStatusBarStyle { |
viewController里重写函数
1 | - (BOOL)prefersStatusBarHidden { |
viewController使用了NavigationController,设置了NavigationController为Hidden,整个self.view上是一张大的ScrollView,因为VC对ScrollView的自动调整,无法让ScrollView的顶部对齐屏幕顶部,而是对齐了StatusBar的底部
1 | [self.navigationController setNavigationBarHidden:YES]; |
tag:
缺失模块。
1、请确保node版本大于6.2
2、在博客根目录(注意不是yilia根目录)执行以下命令:
npm i hexo-generator-json-content --save
3、在根目录_config.yml里添加配置:
jsonContent: meta: false pages: false posts: title: true date: true path: true text: false raw: false content: false slug: false updated: false comments: false link: false permalink: false excerpt: false categories: false tags: true