记录一下iOS开发中琐碎的点点_1

1. 左侧边缘右滑推出控制器

实际上iOS7之后都是支持这个功能的. 导航控制器默认是支持这个功能的, 但是这个功能有个局限, 当导航控制器包含自定义 leftBarButtonItem 时候, 右滑pop的功能就会失效.

有个代理方法:

self.navigationController.interactivePopGestureRecognizer.delegate = nil;

当设置这个代理为nil时候就可以实现右滑推出的功能了, 但是我们在项目中一般用另一种方法:

#pragma mark - 实现在navi的非根控制器中, 在左侧边缘右滑推出控制器
- (void)viewDidAppear:(BOOL)animated
{
    [super viewDidAppear:animated];
    
    //    self.navigationController.interactivePopGestureRecognizer.delegate = nil;
    __weak typeof(self) weakSelf = self;
    self.navigationController.interactivePopGestureRecognizer.delegate = weakSelf;
}
#pragma mark - UIGestureRecognizerDelegate
- (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer*)gestureRecognizer{
    //判断是否为rootViewController
    if (self.navigationController && self.navigationController.viewControllers.count == 1) {
        return NO;
    }
    return YES;
}

首先将代理设置为本控制器, 然后本控制器遵循UIGestureRecognizerDelegate协议, 实现其中的gestureRecognizerShouldBegin:方法, 在方法里面判断是否是根控制器, 如果不是允许右滑pop. 在项目中我们一般把这些代码放在BaseViewController中即可.

2. 加载storyboard中的控制器

2.1

我还是更习惯用纯代码实现界面的,这次自己做练习,搭个很简单的界面于是想用一下storyboard,创建一个storyboard文件, 拖个控制器, 拖几个控件, 然后创建控制器时候, 是需要通过以下的方式来创建的,如下所示:

UIStoryboard *storyboard = [UIStoryboard storyboardWithName:@"RouteNavigationViewController" bundle:[NSBundle mainBundle]];

UIViewController *vc = [storyboard instantiateViewControllerWithIdentifier:@"DaoHang"];

2.2

在晚上找到了如下的代码:

1> 下面的方法表示通过storyboard的名字从某个包中获取(一般设置为nil表示从主包中获取)storyboard
+ (UIStoryboard *)storyboardWithName:(NSString *)name bundle:(NSBundle *)storyboardBundleOrNil
2> 此方法获取到storyboard中初始的控制器
- (id)instantiateInitialViewController 
3> 此方法表示通过控制器的identifier获取到此控制器,新版本的Xcode用Storyboard ID来表示某个控制器的identifier
- (id)instantiateViewControllerWithIdentifier:(NSString *)identifier; 

总结:storyboard体验还是不错的,拖控件嘛, 很简单,很方便, 但是我想如果是非常复杂的界面, 不知道storyboard用起来怎么样, 我国我还是更喜欢用代码, 因为自己封装UI控件, 使用代码做UI也是很有意思的一件事.

3. Objective-C中枚举的移位操作

typedef NS_OPTIONS(NSUInteger, UIUserNotificationType) {
    UIUserNotificationTypeNone    = 0,      
    UIUserNotificationTypeBadge   = 1 << 0, 
    UIUserNotificationTypeSound   = 1 << 1, 
    UIUserNotificationTypeAlert   = 1 << 2, 
}

4. iOS中UI控件的weak和strong

4.1 xib或者storyboard拖出来的控件一般使用weak 因为将控件拖到storyboard上面, 就已经构成了了一个view的层级关系, 已经有一个引用关系,在代码中使用weak引用即可, 只有将view从父视图上面移除,weak引用才会被制空,但是在一个controller的生命周期内, 其子视图一般都不会被移除掉, 所以用weak是可行的. 一个xib或者storyboard拖出来的控件,不管被定义成weak类型还是strong类型,在viewController的生命周期内都是可以的, 都不会造成循环引用和内存泄露.

4.2 使用代码自定义控件 如下两个图所示,第一个图是storyboard拖得控件,声明为weak类型, 第二个图是使用代码声明一个控件,也声明为weak类型,并用如下的方法去赋值, 这样的赋值方法和直接拖一个控件在storyboard上面并在控制器中若引用效果和原理是完全一样的. 使用代码直接声明控件, 可以使用如下的方式, 标标准准的强引用. 试验证明,如果把控件声明成weak类型,定义控件时候直接去赋值,这样也是可以的,点击按钮把weak类型变量制空, UI上面的控件并不会消失,个人认为造成这样的原因是- (void)addSubview:(UIView *)view;这个方法的实现进行了copy操作.

结论, 不管使用哪种方式创建view,常规的操作并不会造成循环引用和内存泄露.

5. masonry使用注意事项

一般使用masonry时候加上这两个宏定义, 能方便很多.

 #define MAS_SHORTHAND_GLOBALS使用全局宏定义,可以使equalTo等效于mas_equalTo
 #define MAS_SHORTHAND使用全局宏定义, 可以在调用masonry方法的时候不使用mas_前缀

6. AutoLayout关于更新的几个方法的区别

  • setNeedsLayout:告知页面需要更新,但是不会立刻开始更新。执行后会立刻调用layoutSubviews。
  • layoutIfNeeded:告知页面布局立刻更新。所以一般都会和setNeedsLayout一起使用。如果希望立刻生成新的frame需要调用此方法,利用这点一般布局动画可以在更新布局后直接使用这个方法让动画生效。
  • layoutSubviews:系统重写布局
  • setNeedsUpdateConstraints:告知需要更新约束,但是不会立刻开始
  • updateConstraintsIfNeeded:告知立刻更新约束
  • updateConstraints:系统更新约束

7. UIKIT_EXTERN的含义

转载自: http://blog.csdn.net/mrguanlingyu/article/details/23337885

// If nil is specified for principalClassName, the value for NSPrincipalClass from the Info.plist is used. If there is no
// NSPrincipalClass key specified, the UIApplication class is used. The delegate class will be instantiated using init.
UIKIT_EXTERN int UIApplicationMain(int argc, char *argv[], NSString *principalClassName, NSString *delegateClassName);
这个函数被main.m调用作为入口点来创建应用程序对象和应用程序委托,并成立了事件循环。
我这里首先关注UIKIT_EXTERN这个宏定义,点进去会发现跳到UIKitDefines.h里面,宏定义代码如下:
#ifdef __cplusplus
#define UIKIT_EXTERN  extern "C" __attribute__((visibility ("default")))
#else
#define UIKIT_EXTERN          extern __attribute__((visibility ("default")))
#endif
其中__cplusplus 是cpp中的自定义宏,那么定义了这个宏的话表示这是一段cpp的代码,也就是说,上面的代码的含义是:如果这是一段cpp的代码,那么加入extern"C"和其中的代码。
extern是C/C++语言中表明函数和全局变量作用范围(可见性)的关键字,该关键字告诉编译器,其声明的函数和变量可以在本模块或其它模块中使用。
那extern "C"呢?C++之父在设计C++之时,kao虑到当时已经存在了大量的C代码,为了支持原来的C代码和已经写好C库,需要在C++中尽可能的支持C,而 extern "C"就是其中的一个策略。
__attribute__是GNU C的一种机制,用法为_attribute__ ((attribute-list))。当项目需要作为一个库被外包引用的时候通常在编译时可以用参数-fvisibility指定所有符号的可见性。在编译命令中加入 -fvisibility=hidden参数,会将所有默认的public的属性变为hidden。此时,如果对函数设置__attribute__((visibility ("default")))参数,使特定的函数仍然按默认的public属性处理,则-fvisibility=hidden参数不会对该函数起作用。所以,设置了-fvisibility=hidden参数之后,只有设置了__attribute__((visibility ("default")))的函数才是对外可见的。
总结:如果需要让类或方法可以让库外被引用,就需要使用以上代码确保代码的可见性。

8. NSObject的load和initialize方法

转载自:http://www.molotang.com/articles/1929.html

在Objective-C中,NSObject是根类,而NSObject.h的头文件中前两个方法就是load和initialize两个类方法,本篇文章就对这两个方法做下说明和整理。

Objective-C作为一门面向对象语言,有类和对象的概念。编译后,类相关的数据结构会保留在目标文件中,在运行时得到解析和使用。在应用程序运行起来的时候,类的信息会有加载和初始化过程。

就像Application有生命周期回调方法一样,在Objective-C的类被加载和初始化的时候,也可以收到方法回调,可以在适当的情况下做一些定制处理。而这正是load和initialize方法可以帮我们做到的。

+ (void)load;
+ (void)initialize;

可以看到这两个方法都是以“+”开头的类方法,返回为空。通常情况下,我们在开发过程中可能不必关注这两个方法。如果有需要定制,我们可以在自定义的NSObject子类中给出这两个方法的实现,这样在类的加载和初始化过程中,自定义的方法可以得到调用。

从如上声明上来看,也许这两个方法和其它的类方法相比没什么特别。但是,这两个方法具有一定的“特殊性”,这也是这两个方法经常会被放在一起特殊提到的原因。详细请看如下几小节的整理。

load和initialize的共同特点

load和initialize有很多共同特点,下面简单列一下:

  • 在不kao虑开发者主动使用的情况下,系统最多会调用一次
  • 如果父类和子类都被调用,父类的调用一定在子类之前
  • 都是为了应用运行提前创建合适的运行环境
  • 在使用时都不要过重地依赖于这两个方法,除非真正必要

load方法相关要点

废话不多说,直接上要点列表:

  • 调用时机比较早,运行环境有不确定因素。具体说来,在iOS上通常就是App启动时进行加载(已测试),但当load调用的时候,并不能保证所有类都加载完成且可用,必要时还要自己负责做auto release处理。
  • 补充上面一点,对于有依赖关系的两个库中,被依赖的类的load会优先调用。但在一个库之内,调用顺序是不确定的。
  • 对于一个类而言,没有load方法实现就不会调用,不会kao虑对NSObject的继承。
  • 一个类的load方法不用写明[super load],父类就会收到调用,并且在子类之前。
  • Category的load也会收到调用,但顺序上在主类的load调用之后。
  • 不会直接触发initialize的调用。

initialize方法相关要点

同样,直接整理要点:

  • initialize的自然调用是在第一次主动使用当前类的时候(lazy,这一点和Java类的“clinit”的很像)。
  • 在initialize方法收到调用时,运行环境基本健全。
  • initialize的运行过程中是能保证线程安全的。
  • 和load不同,即使子类不实现initialize方法,会把父类的实现继承过来调用一遍。注意的是在此之前,父类的方法已经被执行过一次了,同样不需要super调用。 由于initialize的这些特点,使得其应用比load要略微广泛一些。可用来做一些初始化工作,或者单例模式的一种实现方案。

9. 停止tableView的滑动

代码停止tableView的滚动.

//Stop UITableView : UIScrollView from scrolling
[self.tableView setContentOffset:self.tableView.contentOffset animated:NO];

10. 使用UITextField或者UITextView长按选中弹出select文字中文

效果如下图所示: 需要做的:

  1. 在Info.plist中修改 Localization native development region 为China.
  2. 修改 Application Language, Application Regin. 如下:

转载于:https://my.oschina.net/whforever/blog/638329

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值