2. Objective-C
3. Managing Memory with ARC
4. Views and the View Hierarchy
5. Views: Redrawing and UIScrollView
6. View Controllers
7. Delegation and Text Input
8. UITableView and UITableViewController
9. Editing UITableView
10. UINavigationController
11. Camera
12. Touch Events and UIResponder
13. UIGestureRecognizer and UIMenuController
14. Debugging Tools
15. Introduction to Auto Layout
16. Auto Layout: Programmatic Constraints
17. Autorotation, Popover Controllers, and Modal View Controllers
18. Saving, Loading, and Application States
19. Subclassing UITableViewCell
20. Dynamic Type
21. Web Services and UIWebView
22. UISplitViewController
23. Core Data
24. State Restoration
25. Localization
26. NSUserDefaults
27. Controlling Animations
28. UIStoryboard
29. Afterword
bignerd第10章 UINavigationController
1.rely on each other
drill-down interface.向下获取数据
2.UINavigationController 保持了所有screens的堆栈
root view controler: UIViewController是堆栈的最底层
when a UIViewController is pushed onto the stack,its view slides onto the screen from the right
|navigateBar ->
UIViewController| |rootViewController(ListViewController)
|viewControllers(array) |
| |appViewController(DetailViewController)
属性 topViewController获取最顶端的视图控制器
UINavigationController是 UIViewController的子类,也有view属性,
view 一般都有两个子view: UINavigationBar 和 the view of topViewController
3.tip
when writing IOS applications, it is important to treat each UIViewController as its own little world.
4.几个要点:
控制器之间传递数据
重写比如BNRItem *item的setter,
在viewDidAppear之类的函数中操作显示
手动push viewController
//几个章节做概览即可。然后去做实际的项目练习,不清楚的再回来翻/
11章Camera
UIImageView:
aspect fit contentMode
UIToolbar
UIImagePickerController
设定类型
image picker's source type UIImagePickerControllerSourceTypeCamera,PhotoLibrary,PhotosAlbum.类型
使用之前先判定 isSourceTypeAvailable:
设定delegata
头文件声明 <UINavigationControllerDelegate,UIImagePickerControllerDelegate>
image picker's delegate = self;
成功选择图片:
imagePickerController:didFinishPickingMediaWithInfo:
取消选择
imagePickerControllerDidCancel
presenting the image picker modally
- (IBAction)takePicture:(id)sender
{
UIImagePickerController *imagePicker =
[[UIImagePickerController alloc] init];
// If the device has a camera, take a picture, otherwise,
// just pick from photo library
if ([UIImagePickerController
isSourceTypeAvailable:UIImagePickerControllerSourceTypeCamera]) {
imagePicker.sourceType = UIImagePickerControllerSourceTypeCamera;
} else {
imagePicker.sourceType = UIImagePickerControllerSourceTypePhotoLibrary;
}
imagePicker.delegate = self;
[self presentViewController:imagePicker animated:YES completion:nil];
}
--------------------------------
获取图片saving image
- (void)imagePickerController:(UIImagePickerController *)picker
didFinishPickingMediaWithInfo:(NSDictionary *)info
{
// Get picked image from info dictionary
UIImage *image = info[UIImagePickerControllerOriginalImage];
// Put that image onto the screen in our image view
self.imageView.image = image;
// Take image picker off the screen -
// you must call this dismiss method
[self dismissViewControllerAnimated:YES completion:nil];
}
注意:按上面那种方式,当你保存很多图片时,很占内存,甚至应用被强行关闭。
用BNRImageStore来保存图片,当受到内存不足的警告时清理不需要的。
NSDictionary
NSUUID 创建一个唯一的 码?
#pragma mark
隐藏键盘:
-(BOOL)textFieldShouldReture:(UITextField *)textField
{
[textField resignFirstResponder];
return YES;
}
BNRDetailViewController.xib中,选择view,更改类为UIControl,将view链接出一个单击action,
[self.view endEditing:YES];
Recording Video
判断是否支持录像
UIImagePickerController *ipc = [[UIImagePickerController alloc] init];
NSArray *availableTypes = [UIImagePickerController
availableMediaTypesForSourceType:UIImagePickerControllerSourceTypeCamera];
ipc.mediaTypes = availableTypes;
ipc.sourceType = UIImagePickerControllerSourceTypeCamera;
ipc.delegate = self;
委托
- (void)imagePickerController:(UIImagePickerController *)picker
didFinishPickingMediaWithInfo:(NSDictionary *)info
{
// 保存在影片在磁盘中的地址
NSURL *mediaURL = info[UIImagePickerControllerMediaURL];
if (mediaURL) {
// Make sure this device supports videos in its photo album
if (UIVideoAtPathIsCompatibleWithSavedPhotosAlbum([mediaURL path])) {
// Save the video to the photos album
UISaveVideoAtPathToSavedPhotosAlbum([mediaURL path], nil, nil, nil);
// Remove the video from the temporary directory
[[NSFileManager defaultManager] removeItemAtPath:[mediaURL path]
error:nil];
}
}
}
注意:限制用户只选择拍照或者只录像
两者都可选:pass the return value from availableMediaTypesForSourceType:
拍照的话:保持mediaTypes为默认的即可
只要录像:First, you must make sure the device supports video, and then you must set the mediaTypes property to an array containing only the identifier for video.
NSArray *availableTypes = [UIImagePickerController
availableMediaTypesForSourceType:UIImagePickerControllerSourceTypeCamera];
if ([availableTypes containsObject:(__bridge NSString *)kUTTypeMovie]) {
[ipc setMediaTypes:@[(__bridge NSString *)kUTTypeMovie]];
}
12章 Touch Events and UIResponder
触摸事件touch events,手势 gestures, 调试 debugging application
UIView 继承UIResponder,所以可以重写以下四个方法:
touchBegan:(NSSet *)touches withEvent:
touchMoved:withEvent:
touchEnded:withEvent:
touchCancel:withEvent:
touche中有个UITouch的对象,包含了触碰的位置等信息
你不需要保存UITouch的对象,因为在事件中你可以访问得到。
当手指滑出初始触碰到视图,会受到touchMoved和touchEnded
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// 重写几个touch事件,获取location。
// setNeedDisplay,系统自动调用drawRect,
// 如何绘制、设置颜色、stoke等。
#import "BNRDrawView.h"
#import "BNRLine.h"
@interface BNRDrawView()
@property (nonatomic,strong) NSMutableArray *finishedLines;
@property (nonatomic,strong) BNRLine *currentLine;
@end
@implementation BNRDrawView
-(instanceType)initWithFrame:(CGRect)r
{
self = [super initWithFrame:r];
if(self)
{
self.finishedLines = [[NSMutableArray alloc] init];
self.backgroundColor = [UIColor grayColor];
}
}
- (void) strokeLine: (BNRLine *)line
{
UIBezierPath *bp = [UIBezierPath bezierPath];
bp.lineWith = 10;
bp.lineCapStyle = kCGLineCapRound;
[bp moveToPoint:line.begin];
[bp addLineToPoint: line.end];
[bp stroke];
}
-(void)drawRect:(CGRect) rect
{
// 每次都要重新遍历finishedLines再重新绘制???
[[UIColor blackColor] set];
for(BNRLine *line in self.finishedLines]
{
[self strokeLine:line];
}
if(self.currentLine){
[[UIColor redColor] set];
[self strokeLine:self.currentLine];
}
}
- (void) touchBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
UITouch *touch = [touches anyObject];
CGPoint location = [touch locationInView:self];
self.currentLine = [[BNRLine alloc] init];
self.currentLine.begin = location;
self.currentLine.end = location;
[self setNeedDisplay];
}
- (void) touchMoved:(NSSet *)touches withEvent:(UIEvent *)event
{
UITouch *t = [touches anyObject];
CGPoint location = [t locationInView:self];
self.currentLine.end = location;
[self setNeedDisplay];
}
-(void) touchEnded:(NSSet *)touches withEvent:(UIEvent *)event
{
[self.finishedLines addObject:self.currentLine];
self.currentLine = nil;
[self setNeedDisplay];
}
@end
-----------------------------------------------------------------------
多点触控。
默认情况下一个view只能接受一个finger的touch: 一个手指触发了touchBegan,但是没有ended。则view会忽略其他触碰
self.multipleTouchEnabled = YES;
touchCancelled发生在系统事件,比如电话来了~,一般这时候会把当前线段都移除掉
保存多个数据
for (UITouch *t in touches) {
CGPoint location = [t locationInView:self];
BNRLine *line = [[BNRLine alloc] init];
line.begin = location;
line.end = location;
NSValue *key = [NSValue valueWithNonretainedObject:t];
self.linesInProgress[key] = line;
}
//用NSValue *key来作为字典的key而不是直接用t,因为字典的key是实现了NSCopying协议
------------------------------------------------------------------------
#import "BNRDrawView.h"
#import "BNRLine.h"
@interface BNRDrawView
{
@property (nonatomic,strong) NSMutableDictionary *linesInProgress;
@property (nonatomic,strong) NSMutableArray *finishedLines;
// @property (nonatomic,strong) BNRLine *currentLine;
}
@end
@implementation BNRDrawView
-(instanceType)initWithFrame:(CGRect)r
{
self = [super initWithFrame:r];
if(self)
{
self.linesInProgress = [[NSMutableArray] alloc] init];
self.finishedLines = [[NSMutableArray alloc] init];
self.backgroundColor = [UIColor grayColor];
}
}
- (void) strokeLine: (BNRLine *)line
{
UIBezierPath *bp = [UIBezierPath bezierPath];
bp.lineWith = 10;
bp.lineCapStyle = kCGLineCapRound;
[bp moveToPoint:line.begin];
[bp addLineToPoint: line.end];
[bp stroke];
}
-(void)drawRect:(CGRect) rect
{
// finished
[[UIColor blackColor] set];
for(BNRLine *line in self.finishedLines]
{
[self strokeLine:line];
}
// current progress
[[UIColor redColor] set];
for(BNRLine *line in self.linesInProgress){
[self strokeLine:line];
}
}
- (void) touchBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
for(UITouch *t in touches){
CGPoint location = [t locationInView:self];
NSValue *key = [NSValue valueWithNonretainedObject:t];
BNRLine *line = [[BNRLine alloc] init];
line.begin = location;
line.end = location;
self.linesInProgress[key] = line;
}
[self setNeedDisplay];
}
- (void) touchMoved:(NSSet *)touches withEvent:(UIEvent *)event
{
for(UITouch *t in touches){
CGPoint location = [t locationInView:self];
NSValue *key = [NSValue valueWithNonretainedObject:t];
BNRLine *line = self.linesInProgress[key];
line.end = location;
}
[self setNeedDisplay];
}
-(void) touchEnded:(NSSet *)touches withEvent:(UIEvent *)event
{
for(UITouch *t in touches){
NSValue *key = [NSValue valueWithNonretainedObject:t];
BNRLine *line = self.linesInProgress[key];
[self.finishedLines addObject:line];
[self.linesInProgress removeObjectForKey:key];
}
[self setNeedDisplay];
}
-(void) touchCancelled:(NSSet *)touches withEvent:(UIEvent *)event
{
for(UITouch *t in touches){
NSValue *key = [NSValue valueWithNonretainedObject:t];
[self.linesInProgress removeObjectForKey:key];
}
[self setNeedDisplay];
}
@end
Responder chain
每个responder有一个nextResponder属性,构成chain。 rootView: window's nextResponder is UIApplication
'
UIControl:can set targets and actions
the superclass of UIButton,UISlider...
[rButton addTarget:tempController action:@selector(resetTemperature:) forControlEvents:UIControlEventTouchUpInSide | UIControlEventTouchUpOutSide]
then you can send event:
[self sendActionsForControlEvents:UIControlEventTouchUpInSide]
消息不是直接发送给目标view,而是通过UIApplication来找到target
-----------重写UIResponder---------------------
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
{
// Reference to the touch that is ending
UITouch *touch = [touches anyObject];
// Location of that point in this control's coordinate system
CGPoint touchLocation = [touch locationInView:self];
// Is that point still in my viewing bounds?
if (CGRectContainsPoint(self.bounds, touchLocation))
{
// Send out action messages to all targets registered for this event!
[self sendActionsForControlEvents:UIControlEventTouchUpInside];
} else {
// The touch ended outside the bounds, different control event
[self sendActionsForControlEvents:UIControlEventTouchUpOutside];
}
}
13章 UIGestureRecognizer and UIMenuController
创建自定义手势
按钮: 例如长按文本出现的按钮,自定义
UILongPressGestureRecognizer
UIPanGestureRecognizer and Simultaneous Recognizers
UIMenuController and UIResponderStajdardEditAction
-----------------------------------------------------------------------------------------------------------------------------------------
Chapter 13 UIGestureRecognizer and UIMenuController.
14章 Debugging Tools
Gauges
Instruments
leaks Instrument
static analyzer
Projects, targets and Build settings
15章 Introduction to Auto Layout
add constraints
Debugging constraints
unsatisfiable constraints
Debugging using the Auto Layout trace
multiple xib files
16章 programmatic constraints
NSAutoresizingMaskLayoutConstraint
17章 Autorotation,Popocwe controllers Modal view controllers
set in xib
rotation notification
prepareViewsForOrientation:orientation
UIPopoverController
Modal view controllers
Dismissing modal view controllers
modal view controller styles
Thread-Safe Singletons
block
View controller relationship
parent-child relationships
presenting-presenter relationships
Inter-family relationships
18章 Saving,Loading and Application States
Application Sandbox
Constructing a file path
NSKeyedArchiver and NSKeyedUnarchiver
Application States and Transitions
------------------------------------------------------------------------------------------------------------------------------------------------------------------------
存档
1.Archiving,永久存储数据。
Archiving:记录并存储属性
Unarchiving:从数据中重新重新创建对象。
实现NSCoding协议,实现两个方法 encodeWithCoder:, initWithCoder:
- (void)encodeWithCoder:(NSCoder *)aCoder
{
[aCoder encodeObject:self.itemName forKey:@"itemName"];
[aCoder encodeObject:self.serialNumber forKey:@"serialNumber"];
[aCoder encodeObject:self.dateCreated forKey:@"dateCreated"];
[aCoder encodeObject:self.itemKey forKey:@"itemKey"];
[aCoder encodeInt:self.valueInDollars forKey:@"valueInDollars"];
}
-(instancetype) initWithCoder:(NSCoder *)aDecoder
{
self = [super init];
if(self){
_itemName = [aDecoder decodeObjectForKey:@"itemName"];
}
return self;
}
2.应用沙箱, Application sandbox
程序的数据,缓存等。 不能访问其他应用的沙箱
!!!!!!!!!存储路径!!!!!!!!!!
-(NSString *)itemArchivePath
{
NSArray *documentDirectories =
NSSearchPathForDirectoriesInDomain(NSDocumentDirectory,
NSUserDomainMask, YES);
NSString *documentDirectiry = [documentDirectories firstObject];
return [documentDirectories stringByAppendingPathComponent:@"items.archive"];
}
**************上面的到了存储的路径,以及药存储的模型数据。那什么时候出发存储已经什么时候加载数据呢?******************
1.存储:
使用NSKeyedArchiver when application exits.
eg. BNRItem
-(BOOL) saveChanges
{
NSString *path = [self itemArchivePath];
return [NSKeyedArchiver archiveRootObject:self.privateItems];
}
!archiveRootObject:toFile: 工作流程:
1.创建NSKeyedArchiver 对象
2.privateItems发送消息 encodeWithCoder: 并且把 NSKeyedArchiver的对象作为参数。
3.privateItems发送每个其中的字对象 encodeWithCoder,并且传入 NSKeyedArchiver
4.NSKeyedArchiver 写数据到系统文件夹中
当按下home键,applicationDidEnterBackground:会发送到applicationDelegate中,你可以在其中调用saveChanges
它会存在系统文件夹下,一个document文件夹中 item.archive
加载!!:
-(instancetype)initPrivate
{
self = [super init];
if(self){
NSString *path = [self itemArchivePath];
_privateItems = [NSKeyedUnarchiver unarchiveObjectWithFile:path];
if(!_privateItems){
_privateItems = [[NSMutableArray alloc] init];
}
}
return self;
}
------------------------------------------------------------------------------------------------------------------------------------------------------------------------
~~~~~~~~~~~~~~~~~~
Application State and Transitions
Writing to the Filesystem with NSData
NSNotificationCenter and Low-Memory Warnings
Model-View-Controller Store Design Pattern
Cur:Application States Transitions
Cur:Reading and Writing to the Filesystem
Cur:the application bundle
19章 subclassing UITableViewCell 自定义单元格
Image Manipulation
Variable capturing
20章 Dynamic Type
动态
using preferred fonts
responding to user changes
updating auto Layout
21章 web services and UIWebView
Json data
the main thread
credentials
Cur:the request body
22章 UISplitViewController
like ipad app,left part is center ,right part is views
!Displaying the master view controller in portrait mode
Universalizing Nerdfeed
!23章 Core Data
Local saving
SQL
Faults
24章 State Restoration 对象恢复技术
25章 Localization
Internationalization using NSNumberFormat
Localizing resources
NSLocalizedString() and String Tables
Cur:Localizing XIB files without Base Internationalization
26章 NSUserDefauls
read a preference
change a preference
setting bundle
editing the root.plist
localized root.plist
27章 Controlling Animations
Base Animations
Timing functions
keyframe animations
animations completion
spring animations 弹簧 弹性
28章 UIStoryboard
creating a storyboard [xcode interface]
UITableViewControllers in storyboards // 指定root
segues // navigation type
enabling color changes
!passing data around
29章 afterword
next:
犯些错
阅读tedious乏味的文档
多问,多交流
建议:
1.动手写App
如果你没有立即使用你现在学到,知识将慢慢褪去。现在开始练习并且拓展你的知识
2.深入
本书的每个章节都可以更深入的写成一本书。找一个你感兴趣的然后去探索,做些联系,阅读苹果的官方文档,看博客或者stackoverflow上的问答
3.交流
多与别人交流
4.出bug,修bug
慢慢就能成长起来
5.分享知识
虚心回答别人的问题,分享代码