iOS-常见问题

11.21常见问题

一storyboard连线问题

产生原因:将与storyboard关联的属性删除了,但是storyboard中还保持之前所关联的属性。

解决:

  1. 点击view controller
  2. 点击这排最后一个按钮
  3. 会出现
  4. 发现感叹号。点击感叹号的左边的x,取消关联就不会报错了。

二 文本框中怎么输入显示类似输入密码时候的东东。

解决:勾选这个

三.输入文本的时候,怎么显示右边的X按钮

1.点击

2.会显示

3.选择 ,表示当编辑的时候,会出出现X。

效果:

11.22 常见问题

一.Storyboard连线问题。

报错原因:1.没有实现btnClick这个方法。

解决方式一:添加这个btnClick这个方法

解决方式二:

1.点击view controller

2.点击这排最后一个按钮

3.会出现

4.发现感叹号没,和之前一样,x了它,就哦了。

注意点;OC中冒号也算做方法名的一部分喔,记住!

二.结构体问题

报错原因:OC语法规定:不允许直接修改某个对象的结构体属性的成员

_btn 是个对象

frame是个结构体。

对象和结构体是不一样的,结构体是C语言中的,里面可以定义许多属性,但是不能定义方法,而对象是即可以定义属性又可以定义方法的,是典型的面向对象语法。

如何改变对象中结构体属性的成员:

解决方法一:

// 既然不能直接修改对象中的结构体属性成员

// 先取出结构体

CGRect frame = _btn.frame;

// 修改结构体

frame.origin.y -= 10;

// 将修改后的结构体重新赋值回去

_btn.frame = frame;

 

解决方法二:

// 先取出y值

CGFloat y = _btn.frame.origin.y;

// 修改y值

y -= 10;

// 重新设置_btn的y值,其他属性和_btn保持不变

_btn.frame = CGRectMake(_btn.frame.origin.x, y, _btn.frame.size.width,_btn.frame.size.height);

三.Id问题

报错原因:id类型不能使用点语法

解决方式一:

// 利用get方法获取tag值

NSInteger i = [sender tag];

解决方式二:

// 将id强转为UIButton

UIButton *button = (UIButton *)sender;

// 就能使用点语法获取tag,编译器很笨的,他只会根据当前类型,去判断是否能使用这个语法。一般强转为对应类型,就能使用对应类型的方法了。

NSInteger i = button.tag;

四.如果发现给控件设置transform属性,控件没有任何反应,或者反应了,但是效果不对。

解决方法: 将这个选项取消勾选。

五.如果想让同一个控件同时即改变位置的移动,又放大。这样设置是无效果的。

_btn.transform = CGAffineTransformMakeTranslation(0, 100);

_btn.transform = CGAffineTransformMakeScale(1.2, 1.2);

这样操作是创建新的transform然后赋值,给按钮的transform,第二次赋值的会把之前赋值的给覆盖,所以会达不到想要的效果。

解决方法:

_btn.transform = CGAffineTransformMakeTranslation(0, 100);

// 在之前的transform情况下,继续添加缩放的形变。

_btn.transform = CGAffineTransformScale(_btn.transform, 1.2, 1.2);

六.四舍五入问题。

float i = 1.7;

// 会自动四舍五入,不保留小数

NSLog(@"%0.f",i); // 打印结果2

// 强转类型不会四舍五入

int j = (int)i;

NSLog(@"%d",j); // 打印结果1

七.优先级问题

//    int b = 2;

//    int a = 4 * (b == 2? 1:2);

//    NSLog(@"%d",a); 打印出4

//    int a = 4 * b == 2? 1:2;

//    NSLog(@"%d",a); 打印出2

//    由此得出 * 比 == 优先级高,先算*,在算==

八.模拟器黑屏

解决方法:

九.打代码时,Xcode没提示

解决方法:

  1. 点击Preferences

1. 进入Text Editing

2. 勾选

十.有的同学可能在勾选 Autolayout的时候,搞错了对象,误把控制器的View的User Interaction Enabled勾选掉了。

解决办法:User Interaction Enabled 必须勾选,否则控制器根视图中所有子控件无法进行任何操作。

11.23 常见问题

一.访问权限

错误:

会报链接错误。

报错原因,利用下划线访问了@package这个权限里的东西。

被@package 修饰的成员属性只能在同一个框架内部才允许访问。否则会引发link erro。

@private 实例变量只能被声明它的类访问

@protected 实例变量能被声明它的类和子类访问。

@public 实例变量可以被任何类访问。

11.24 常见问题

一.运行程序时,显示运行完成,但是模拟器没反应。

问题原因: 有时候应用程序的标示符一样,会导致程序不能成功运行。

解决方式一:将模拟器之前的程序删除。

解决方式二:  将模拟器还原

二.2d表示保留两位 02d 表示不够了 用0来补齐。

NSLog(@"%02d",cols);

三.Plist文件读取。

错误原因:不要看到有很多元素的,就认为是数组。

这样解析是错误的。

_dict = [NSArray arrayWithContentsOfFile:path];

这个pist文件是一个字典,正确的解析此plist文件。

// 2.根据文件路径加载字典

_dict = [NSDictionary dictionaryWithContentsOfFile:path];

四,给程序拖图片的时候,一定要注意,如下图勾选的,都要勾选中。

五.禁用UITextField的双击出现复制粘贴剪切等操作

解决方式:

有时候我们需要禁用UITextField的双击出现copy paste的功能,然而UITextField本身没有直接设置禁止用户复制粘贴剪切操作等方法,但是可以重载canPerformAction方法来实现。

新建一个类继承UITextField,然后实现canPerformAction方法:
只需覆盖canPerformAction:withSender方法就可以,canPerformAction:withSender属于UIResponder类的。

如下:

-(BOOL)canPerformAction:(SEL)action withSender:(id)sender {

UIMenuController *menuController = [UIMenuController sharedMenuController];

if (menuController) {

[UIMenuController sharedMenuController].menuVisible = NO;

}

return NO;

}

11.25 常见问题

1.将UIButton添加到UILabel,UIButton是不能点击的。

原因: 1.UILabel是继承UIView的,默认不能监听点击事件。UIButton是继承UIControl能够监听点击事件。

2.将UIButton添加到UILabel,他们之间的关系是UILabel是UIButton的父视图,父视图都不能监听点击事件,自然而然不会将事件传递给子视图,因此UIButton也不能监听点击事件了。

思维指导:有些人会认为UIControl不是继承UIView的吗,都是继承UIView,为什么单独继承UIControl可以监听点击事件,继承UIControl的父类UIView不能监听事件了,这是因为我们一般在父类里实现的都是一些共用的属性和方法,而在子类中具体实现子类特有的方法。因此在UIControl实现了监听点击的特有方法,即继承UIControl才能监听点击事件。

2.发现不少人在给成员变量初始化的时候,容易进错一个方法去初始化。

注意这个方法只有在内存发生警告的时候才会调用。

- (void)didReceiveMemoryWarning

{

[super didReceiveMemoryWarning];

// Dispose of any resources that can be recreated.

}

大部分成员属性的初始化应该在viewDidLoad里面进行。

- (void)viewDidLoad

{

[super viewDidLoad];

}

最牛解决方法:在一开始就将didReceiveMemoryWarning这个方法删掉。删掉不会影响程序运行。

3.模拟器问题

当出现这个问题的时候,原因:没有选择模拟器。

解决办法:

11.26常见问题

1.对象方法和类方法问题(此问题基础好的可以看看,基础稍微差的,可以先放着,以后回顾的时候,看看。)

// 创建视图的工厂方法

+ (UIView *)rowViewInitWithicon:(UIImage *)icon shuju:(NSString *)shuju

{

rowView *viewtext = [[NSBundle mainBundle]loadNibNamed:@"rowView" owner:nil options:nil][0];

[viewtext.btntouxiang setBackgroundImage:icon forState:UIControlStateNormal];

viewtext.mingzilablexiao.text = shuju;

// 重点是这句

//  这是往通知中心添加一条通知 指定通知名称为  back  当观察者self监听到 back 通知是 就调用 callback

[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(callback) name:@"back" object:nil];

/*   以下是报错信息:

+[rowView callback]: unrecognized selector sent to class 0x79d8

2013-11-26 15:31:02.581 lianxirenlianxi[1266:c07] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '+[rowView callback]: unrecognized selector sent to class 0x79d8'

*/

// reason: '+[rowView callback]: 看到报错原因里的+就想到没有实现callback这个类方法。

// 由于self这个观察者是在类方法中添加的,指的是一个类,所以在调用方法的时候,他会去类方法中找有没有这个方法,不会去对象方法中找。因此我们也应该实现类方法。因此这里的self也只能调用类方法

// 由于实现的callback为对象方法  所以会报错

//  解决方法  把callback  写成类方法   供观察者调用

return viewtext;

}

//callback方法

- (void)callback

{

NSLog(@"11111111111");

}

解决方法,将callback 写成类方法 供观察者调用

//callback方法

+ (void)callback

{

NSLog(@"11111111111");

}

2.Xib是用来描述视图长什么样子,一个项目中允许有很多xib,因此我们需要给xib绑定一个标识,即他View中对应的class是谁,就代表描述哪个class。

Xib中owner的class是用来告诉xib中的View需要调用哪个对象的方法,就填谁。比如需要调用dog类中的方法,就填dog。

注意:在连线选择上别连错了,

步骤一:先考虑自己是想给视图添加控件了还是想给视图添加事件

步骤二:添加控件就跟xib中的view连线。添加一些事件就给xib中的File’s Owner 连线。

3.代码顺序问题

[UIView animateWithDuration:0.5 animations:^{

CGRect  tmpFrame = sender.superview.frame;

tmpFrame.origin.x = self.view.frame.size.width;

sender.superview.frame = tmpFrame;

sender.superview.alpha = 0;

} completion:^(BOOL finished) {

int index = [self.view.subviews indexOfObject:sender.superview];

[sender.superview removeFromSuperview];

[UIView animateWithDuration:0.2 animations:^{

for (int i = index; i<self.view.subviews.count; i++)

{

UIView *chlid = self.view.subviews[i];

CGRect tmp = chlid.frame;

tmp.origin.y -=kViewH+1;

chlid.frame =tmp;

}

}];

// 在这判断删除按钮是否允许点中,会在动画执行完毕的时候,判断。

_removeIteam.enabled = self.view.subviews.count>1;

}];

// 而在执行代码块之外,判断删除按钮是否允许点中是不对的,因为动画是在后台运行的,所以在执行动画的时候,就已经执行完判断语句了,而这时最后一个视图还没销毁掉,因此删除按钮永远不会不允许选中,也就不能在判断删除按钮是否允许点中。

// _removeIteam.enabled = self.view.subviews.count>1;

删完最后一行之后,正确的效果。

删完最后一行之后,错误的效果。原因,判断的位置放错了。

4.Xib描述视图的时候,已经固定好描述视图的宽高了,外界调用视图的时候,只需要设置x,y值就好了

1.出现的问题,创建xib描述的视图时,将宽度设置为一个按钮的宽度了,导致删除按钮不能点击。

#pragma mark 添加联系人

- (IBAction)AddPerson:(UIBarButtonItem *)sender {

NSString *imgName=[NSString stringWithFormat:@"01%d.png",arc4random_uniform(9)];

NSString *labelName = arr[arc4random_uniform(arr.count)];

RowView *rowView = [RowView rowViewWithIcon:imgName name:labelName];

UIView *lastView = [self.view.subviews lastObject];

int nextY = lastView.frame.origin.y + kSpace + kItemHW ;

// 设置rowView的位置和尺寸

CGRect cg =CGRectMake(0, nextY, kItemHW, kItemHW);

rowView.frame=cg;

[self.view addSubview:rowView];

}

错误原因:设置rowView的宽度为kItemHW,因此会有以上图片的出现。

错误会导致删除按钮不能点击,原因:父视图的尺寸不够,即父视图能接收事件的尺寸只有一点点,也就导致超出父视图尺寸的子视图不能监听点击事件。还有一点需要注意,将子视图添加到父视图尺寸之外的位置,只要还在屏幕上就会显示子视图,只不过它不能接收任何事件。

解决方法:CGRect cg =CGRectMake(0, nextY,rowView.frame.size.width , kItemHW);

这样设置就好了,因为xib里面已经设置了rowView的尺寸了,外界不需要更改视图的宽度了,直接获取视图的宽度即可。

正确效果:

5.    UIToolBar问题

注意UIToolBar中不能使用viewWithTag这个方法,获取UIToolBar里的子视图。因为UIToolBar里的子视图都是UIBarButtonItem,而UIBarButtonItem是继承NSObject的,因此不能使用viewWithTag获取UIToolBar里的子视图,

viewWithTag:实现原理

- (UIView *)viewWithTag:(NSInteger)tag

{

// 1.如果当前tag和当前视图tag相同,直接返回

if (self.tag == tag) return self;

// 2.如果和当前视图tag不相同,遍历当前视图的所有子控件,查找对应的tag。

for (UIView *view in self.subviews) {

// 3.如果view不是UIView类或者UIView的子类直接返回nil

if (![view isKindOfClass:[UIView class]]) return nil;

if (tag == view.tag) {

//  4. 返回有相匹配的视图

return view;

}

}

// 5.如果都没有找到,返回nil.

return nil;

}

11.27常见问题

1.结构体和对象问题

// 这样定义是错的,结构体不是对象,声明变量是不需要加*

CGRect *frame = self.view.frame;

结构体变量正确定义:

CGRect frame = self.view.frame;

CGPoint center = self.view.center;

CGSize size = self.view.frame.size;

2.内存管理问题

错误打印:

正确打印:

当对象被销毁,一定会调用的方法,可以用这个方法,判断对象在什么时候销毁,用这个调试。

3.创建模型的时候,尽量自定义一个工厂方法供外界调用。

// 工厂方法,简化对象的实例化

+ (id)provinceWithName:(NSString *)name;

工厂方法好处:简化对象的实例化,快速创建对象。

4.非ARC内存管理问题。

有些同学在创建项目的时候忘记点ARC了,导致一些成员属性都莫名其妙的释放了。然后出现了一系列莫名其妙的错误。

在滚动UITableView的时候出现野指针错误。

一出现这些野指针错误,首先应该想到某些对象被释放了,然后发现代码中,并没有什么造成对象被释放的情况,这时候应该马上想到很可能是非ARC弄的。下图为怎么查看项目是否是非ARC。

在非ARC中没有强引用的概念,因此下图的成员变量是没有被强引用的。

在看看下图,allPro数组没有通过alloc调用,没有调用alloc产生的对象都是自动释放的

allPro=@[

@{

kCities:@[@"浦东",@"杨浦",@"闸北",@"闵行"],

kHeader:@"上海",

kFooter:@"上海不错"

},

@{

kCities:@[@"海淀",@"昌平",@"*"],

kHeader:@"北京",

kFooter:@"北京很好"

}

];

所以在滚动的时候会出现野指针错误,因此需要将项目改成ARC。如下图

两个勾都得选中,然后一直点确认就OK了。

6.    数据模型属性采用的策略中除了基本类型需要用assign,字符串需要用copy,其他对象类型都需要用strong。而控制器中视图采用的策略需要根据情况而定。

下图就是数据模型中属性用错了策略导致,UITableViewcell重新出现到界面时,会导致数据丢失。

11.29 常见问题

1.想在点击cell时做些操作,方法选错了。

下面两个方法太相似了,很容易选错。

// 当点击一行cell时,会调用这个方法

-      (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath

// 当取消选择一行cell时,会调用这个方法

-      (void)tableView:(UITableView *)tableView didDeselectRowAtIndexPath:(NSIndexPath *)indexPath

2.字符串小调试技巧

当把一个字符串转换成基本数据类型时,字符串打印有值,但是转换成基本数据类型为0时,这个莫名其妙的问题,首先应该想到字符串中很可能有换行符合等,导致转换不成功。

NSString *str = @"                                                                                  123";

NSInteger i = [str integerValue];

NSLog(@"%@",str);

NSLog(@"%d",i);

碰到这种情况,可以在打印字符串的时候在占位符两边各加一个数字.

NSLog(@"1%@1",str);

然后看打印结果就能知道有字符串中有多少空行了

只要将空行去掉就能转换成功了。

字符串去掉空格的方法

// 此方法是通过什么字符集裁剪字符串。

- (NSString *)stringByTrimmingCharactersInSet:(NSCharacterSet *)set;

NSCharacterSet对象可以通过类方法创建

// 创建空格和换行字符集

[NSCharacterSet whitespaceAndNewlineCharacterSet];

// 创建空格字符集

[NSCharacterSet whitespaceCharacterSet];

3.下图的警告意思是:初始化时,类型指向不匹配,应该用NSArray * 而不是YZPerson *

找到原因后,然后看person方法是怎么声明。

解决方式:将NSArray * 改成id。

11.30 常见问题

1.UITableView数据源问题

1.1

错误原因:说YZViewController 没有实现 tableView:numberOfRowsInSection:

解决方式:实现tableView:numberOfRowsInSection:

1.2

这里返回空,会报错。

UITableView内部实现原理:

数据源实现了这个方法

-(UITableViewCell*)tableView:(UITableView*)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath

tableView内部自动会调用以下方法添加cell。

[tableView addSubview:cell];

如果返回的cell为空,也就意味着生成下面一行代码。

[tableView addSubview:nil];

而addSubview是将右边参数添加到数组中保存起来,而数组是不能添加空值的。所有集合对象都不能出传空。例如数组,字典,NSSet。

以上错误总结:作为tableView的数据源必须实现两个方法。

返回行数

-(NSInteger)tableView:(UITableView*)tableView numberOfRowsInSection:(NSInteger)section;

返回每一行显示的内容

-(UITableViewCell*)tableView:(UITableView*)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath

另外返回每一行显示的内容不能返回nil。

2.在数组删除一个模型,并不代表把这个模型给释放了。

上面步骤二,仅仅是将模型从数组中销毁,而模型并没有被销。

12.1 常见问题

1.stroyboard中显示的跟根视图是UIView,而stroyboard的控制器是UITableViewController就会报这个错误

原因是:UITableViewController控制器不能加载UITableView,因为它会去加载stroyboard中的UIView。

解决方式:将stroyboard中的UIView改成UITableView

12.2 常见问题

1.自定义视图的属性命名冲突问题

当发现自己描述的xib和运行的时候展现出来的不一样的时候,这时候已经想到自己命名的属性名称和系统命名的冲突了。

错误原因

系统自带的UITableViewCell中也有imageView这个属性,因此冲突了。

解决办法:将自定义视图的imageView属性名称改成iconView.

注意:以后自定义属性命名不要和系统自带的属性名称相同。

2.链接错误

以后看到duplicate这个词语,错误原因就是重复定义了类,函数方法等等。

一般都是因为导入了.m文件

错误:

解决方式:将#import "newsCell.m"这一行删掉。

3.注意将之前storyboard中控制器删除之后,拖入一个新的控制器的时候,stroyboard中控制器的class也要重新填入自己想要展示的控制器,告诉stroyboard去加载哪个控制器。

12.3常见错误

1.初始化方法命名规范问题。

看见这个错误,应该要想到初始化方法命名错误的问题。因为self只能在init开头的方法中赋值,init必须是一个独立的单词,因此init后的第一个字母必须大写。

12.4常见错误

1.重写set方法忘记赋值,以后重写set方法,第一步就先赋值。

2.strong和weak乱用

一般情况:代理和控件使用weak

其他对象使用strong

基本数据类型 使用assign

12.5常见错误

1.QQ好友列表中,展开了列表,但是箭头没动画。

原因:由于代理方法中重新刷新了表格,也就意味着把之前的头部视图给替换了,因此没有动画了,不要创建新的头部,才能让旧的头部执行动画

解决方法:用一个数组或者字典保存所有的头部视图,重新刷新的时候,直接取就OK了。

12.6 常见错误

1.加载xib时,名字是分大小写的,注意名字一定要保持一致。

报错原因:xib是大写的KeyboardTool,而加载的时候名字写成小写了。

解决方式:将加载的xib的名称改成大写。

上一篇:Android之旅十四 android中的xml文件解析


下一篇:[源码]随机获取虾米音乐song_id API文件