• 触摸事件

  因为 UIView 是 UIResponder 的子类,所以覆盖以下四个方法就可以处理四种不同的触摸事件:

  1.  一根手指或多根手指触摸屏幕

- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(nullable UIEvent *)event;

  2.  一根手指或多根手指在屏幕上移动(随着手指的移动,相关的对象会持续发送该消息)

- (void)touchesMoved:(NSSet<UITouch *> *)touches withEvent:(nullable UIEvent *)event;

  3.  一根手指或者多根手指离开屏幕

- (void)touchesEnded:(NSSet<UITouch *> *)touches withEvent:(nullable UIEvent *)event;

  4.  在触摸操作正常结束前,某个系统事件(例如电话进来)打断了触摸过程

- (void)touchesCancelled:(NSSet<UITouch *> *)touches withEvent:(nullable UIEvent *)event;

  当系统检测到手指触摸屏幕的事件后,就会创建 UITouch 对象(一根手指的触摸事件对应一个 UITouch 对象)。发生触摸事件的 UIView 对象会收到  touchesBegan:(NSSet<UITouch *> *)touches withEvent:(nullable UIEvent *)event 消息,系统传入的第一个实参  touches (NSSet 对象)会包含所有相关的 UITouch 对象。

  当手指在屏幕上移动的时候,系统会更新相应的 UITouch 对象,为其重新设置对应的手指在屏幕上的位置。最初发生触摸事件的那个 UIView 对象会收到  touchesMoved:(NSSet<UITouch *> *)touches withEvent:(nullable UIEvent *)event 消息,系统传入的第一个实参  touches (NSSet 对象)会包含所有相关的 UITouch 对象,而且这些 UITouch 对象都是最初发生触摸事件时创造的。

  当手指离开屏幕的时候,系统会最后一个更新相应的 UITouch 对象,为其重新设置对应的手指在屏幕上的位置。接着,最初发生该触摸事件的视图会收到  touchesEnded:(NSSet<UITouch *> *)touches withEvent:(nullable UIEvent *)event 消息。当收到该消息并执行完成之后,系统就会释放和当前事件有关的 UITouch 对象。

  下面对 UITouch 对象和事件响应方法的工作机制做一个归纳。

  1.  一个 UITouch 对象对应屏幕上的一根手指。只要手指没有离开屏幕,相应的 UITouch 对象就会一直存在。这些 UITouch 兑现都会保存对应的手指在屏幕上当前的位置。

  2.  在触摸事件的持续过程中,无论发生什么,最初发生触摸事件的那个视图都会在各个阶段收到相应的触摸事件消息。即使手指在移动时离开了这个视图的frame区域,系统还是会向该视图发送  touchesMoved:(NSSet<UITouch *> *)touches withEvent:(nullable UIEvent *)event  和  touchesEnded:(NSSet<UITouch *> *)touches withEvent:(nullable UIEvent *)event 消息。也就是说,当某个视图发生触摸事件之后,该视图将永远“拥有”当时创建的所有 UITouch 对象。

  3.  我们自己编写的代码不需要保存任何 UITouch 对象。当某个 UITouch 对象的状态发生变化时,系统会向指定的对象发送特定的时间消息,并传入发生变化的 UITouch 对象。

  当应用发生某个触摸事件后(例如触摸开始、手指一动、触摸结束),系统都会将该事件添加至一个由 UIApplication 单例管理的事件队列。通常情况下,很少会出现满队列的情况,所以 UIApplication 会立刻分发队列中的事件。分发某个触摸事件时,UIApplication 会向 “拥有” 该事件的视图发送特定的 UIResponder 消息。

  当多根手指在同一个视图、同一个时刻执行相同的触摸动作时,UIApplication 会用单个消、一次分发所有的 UITouch 对象。UIApplication 在发送特定的UIResponder 消息时,会传入一个 NSSet 对象,该对象将包含所有相关的 UITouch 对象(一个 UITouch 对象对应一根手指)。但是,因为 UIApplication 对 “同一时刻”的判断很严格,所以通常情况下,哪怕是一组事件都是在很短的一段时间内发生的,UIApplication 也会发送多个 UIResponder 消息,分批发送 UITouch 对象。

  • 创建 JXTouchTracker 应用

  首先,JXTouchTracker 需要一个能够描述线条的模型对象。创建一个新的 JXLine 子类。声明两个 CGPoint 属性。

#import <UIKit/UIKit.h>

@interface JXLine : NSObject
/** 开始位置 */
@property (nonatomic,assign) CGPoint begin;
/** 结束位置 */
@property (nonatomic,assign) CGPoint end;
@end
#import "JXLine.h"

@implementation JXLine

@end

  接着,创建一个新的自定义类。

#import <UIKit/UIKit.h>

@interface JXDrawView : UIView

@end
#import "JXDrawView.h"

@implementation JXDrawView

@end

  下面创建一个 UIViewController 子类,用于管理 JXDrawView 对象。

#import <UIKit/UIKit.h>

@interface JXDrawViewController : UIViewController

@end
#import "JXDrawViewController.h"

@interface JXDrawViewController ()

@end

@implementation JXDrawViewController

- (void)viewDidLoad {
[super viewDidLoad]; } @end

  接下来

#import "AppDelegate.h"
#import "JXDrawViewController.h"

@interface AppDelegate () @end @implementation AppDelegate - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds]; JXDrawViewController * drawController = [[JXDrawViewController alloc] init];
self.window.rootViewController = drawController;
self.window.backgroundColor = [UIColor whiteColor];
[self.window makeKeyAndVisible];
return YES;
}

  在 JXDrawViewController 中覆盖  loadView 方法,创建一个 JXDrawView 对象并将其赋值给 JXDrawViewController 对象的  view 属性

#import "JXDrawViewController.h"
#import "JXDrawView.h"

@interface JXDrawViewController () @end @implementation JXDrawViewController
- (void)loadView {
self.view = [[JXDrawView alloc] initWithFrame:CGRectZero];
}
- (void)viewDidLoad {
[super viewDidLoad]; } @end
  • 实现 JXDrawView 完成绘图功能

  JXDrawView 对象需要管理正在绘制的线条和绘制完成的线条。

#import "JXDrawView.h"
#import "JXLine.h"

@interface JXDrawView ()
/** 保存当前正在绘制线条 */
@property (nonatomic,strong) JXLine * currentLine;
/** 保存已经绘制完成的线条 */
@property (nonatomic,strong) NSMutableArray * finishedLines;
@end @implementation JXDrawView - (instancetype)initWithFrame:(CGRect)frame {
self = [super initWithFrame:frame];
if (self) {
self.finishedLines = [NSMutableArray array];
self.backgroundColor = [UIColor grayColor];
}
return self;
}
@end

  接下来需要编写绘制线条的代码。

#import "JXDrawView.h"
#import "JXLine.h" @interface JXDrawView ()
/** 保存当前正在绘制线条 */
@property (nonatomic,strong) JXLine * currentLine;
/** 保存已经绘制完成的线条 */
@property (nonatomic,strong) NSMutableArray * finishedLines; @end @implementation JXDrawView - (instancetype)initWithFrame:(CGRect)frame {
self = [super initWithFrame:frame];
if (self) {
self.finishedLines = [NSMutableArray array];
self.backgroundColor = [UIColor grayColor];
}
return self;
} - (void)strokeLine:(JXLine *)line {
UIBezierPath * bp = [UIBezierPath bezierPath];
bp.lineWidth = ;
bp.lineCapStyle = kCGLineCapRound; [bp moveToPoint:line.begin];
[bp addLineToPoint:line.end];
[bp stroke];
} - (void)drawRect:(CGRect)rect {
// 用黑色表示已经绘制完成的线条
[[UIColor blackColor] set];
for (JXLine * line in self.finishedLines) {
[self strokeLine:line];
} if (self.currentLine) {
// 用红色表示当前正在绘制的线条
[[UIColor redColor] set];
[self strokeLine:self.currentLine];
}
}
@end
  • 处理触摸事件并创建线条对象

  这里我们只创建直线,所以我们需要用 JXLine 的 begin  和  end  属性来保存这两个点。当触摸事件开始时,JXDrawView 对象需要创建一个 JXLine 对象,并将其两个属性都设置为触摸发生时的位置。当触摸事件继续时,JXDrawView 对象要将  end  属性设置为手指当前位置。当触摸结束时,这个 JXLine 对象就能代表完成后的线条。

#import "JXDrawView.h"
#import "JXLine.h" @interface JXDrawView ()
/** 保存当前正在绘制线条 */
@property (nonatomic,strong) JXLine * currentLine;
/** 保存已经绘制完成的线条 */
@property (nonatomic,strong) NSMutableArray * finishedLines; @end @implementation JXDrawView - (instancetype)initWithFrame:(CGRect)frame {
self = [super initWithFrame:frame];
if (self) {
self.finishedLines = [NSMutableArray array];
self.backgroundColor = [UIColor grayColor];
}
return self;
} - (void)strokeLine:(JXLine *)line {
UIBezierPath * bp = [UIBezierPath bezierPath];
bp.lineWidth = ;
bp.lineCapStyle = kCGLineCapRound; [bp moveToPoint:line.begin];
[bp addLineToPoint:line.end];
[bp stroke];
} - (void)drawRect:(CGRect)rect {
// 用黑色表示已经绘制完成的线条
[[UIColor blackColor] set];
for (JXLine * line in self.finishedLines) {
[self strokeLine:line];
} if (self.currentLine) {
// 用红色表示当前正在绘制的线条
[[UIColor redColor] set];
[self strokeLine:self.currentLine];
}
} - (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
UITouch * t = [touches anyObject]; // 根据触摸位置创建 JXLine 对象
CGPoint location = [t locationInView:self];
self.currentLine = [[JXLine alloc] init];
self.currentLine.begin = location;
self.currentLine.end = location; [self setNeedsDisplay];
} - (void)touchesMoved:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
UITouch * t = [touches anyObject]; CGPoint location = [t locationInView:self]; self.currentLine.end = location; [self setNeedsDisplay];
} - (void)touchesEnded:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
[self.finishedLines addObject:self.currentLine];
self.currentLine = nil;
[self setNeedsDisplay];
}
@end

  

  多点触摸

  默认情况下,视图在同一时刻只能接收一个触摸事件。如果一个手指已经触发了 touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event 方法,那么在手指离开前,其他触摸事件都会被忽略。

  为了使 JXDrawView 同时接受多个触摸事件,我们需要额外的处理。

#import "JXDrawView.h"
#import "JXLine.h" @interface JXDrawView ()
/** 保存当前正在绘制线条 */
@property (nonatomic,strong) JXLine * currentLine;
/** 保存已经绘制完成的线条 */
@property (nonatomic,strong) NSMutableArray * finishedLines; @end @implementation JXDrawView - (instancetype)initWithFrame:(CGRect)frame {
self = [super initWithFrame:frame];
if (self) {
self.finishedLines = [NSMutableArray array];
self.backgroundColor = [UIColor grayColor]; // 支持多点触摸
self.multipleTouchEnabled =
YES;
}
return self;
} - (void)strokeLine:(JXLine *)line {
UIBezierPath * bp = [UIBezierPath bezierPath];
bp.lineWidth = ;
bp.lineCapStyle = kCGLineCapRound; [bp moveToPoint:line.begin];
[bp addLineToPoint:line.end];
[bp stroke];
} - (void)drawRect:(CGRect)rect {
// 用黑色表示已经绘制完成的线条
[[UIColor blackColor] set];
for (JXLine * line in self.finishedLines) {
[self strokeLine:line];
} if (self.currentLine) {
// 用红色表示当前正在绘制的线条
[[UIColor redColor] set];
[self strokeLine:self.currentLine];
}
} - (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
UITouch * t = [touches anyObject]; // 根据触摸位置创建 JXLine 对象
CGPoint location = [t locationInView:self];
self.currentLine = [[JXLine alloc] init];
self.currentLine.begin = location;
self.currentLine.end = location; [self setNeedsDisplay];
} - (void)touchesMoved:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
UITouch * t = [touches anyObject]; CGPoint location = [t locationInView:self]; self.currentLine.end = location; [self setNeedsDisplay];
} - (void)touchesEnded:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
[self.finishedLines addObject:self.currentLine];
self.currentLine = nil;
[self setNeedsDisplay];
}
@end

  现在当多根手指在屏幕上触摸、移动、离开时, JXDrawView 都将会收到相应的 UIResponder 消息。但是现有代码并不能正确处理这些消息:现在我们目前的代码只能处理一个触摸消息。

  之前实现的触摸方法中,代码向 NSSet 类型的一个  touches 发送了  anyObject 消息-在只能接收单点触摸的视图中, touches 在同一时刻只会包含一个触摸事件,因此  anyObject 可以正确返回唯一的触摸事件。但是在可以接收多点触摸的视图中, touches 在同一时刻可能包含一个或者多个触摸事件。

  目前为止,我们的代码中只有一个  currentLine 属性用于保存正在绘制的直线。当有多个触摸事件的时候,我们可能会想多用多个属性来保存正在绘制的直线,但是这样做是绝对不可取的,因为加入我们只移动一根手指的时候,那么我们应该用哪个属性来接收呢?

  所以更好的解决办法就是使用 NSMtableDictionary 对象来保存正在绘制的直线:之前触摸事件时,JXDrawView 可以根据传入的 UITouch 对象创建 JXLine 并将两者关联存储到字典中。

#import "JXDrawView.h"
#import "JXLine.h" @interface JXDrawView ()
/** 保存当前正在绘制线条 */
@property (nonatomic,strong) JXLine * currentLine;
/** 保存已经绘制完成的线条 */
@property (nonatomic,strong) NSMutableArray * finishedLines;
/** 保存正在绘制的多条直线 */
@property (nonatomic,strong) NSMutableDictionary * linesInProgress;
@end @implementation JXDrawView - (instancetype)initWithFrame:(CGRect)frame {
self = [super initWithFrame:frame];
if (self) { self.linesInProgress = [NSMutableDictionary dictionary];
self.finishedLines = [NSMutableArray array];
self.backgroundColor = [UIColor grayColor]; // 支持多点触摸
self.multipleTouchEnabled = YES;
}
return self;
} - (void)strokeLine:(JXLine *)line {
UIBezierPath * bp = [UIBezierPath bezierPath];
bp.lineWidth = ;
bp.lineCapStyle = kCGLineCapRound; [bp moveToPoint:line.begin];
[bp addLineToPoint:line.end];
[bp stroke];
} - (void)drawRect:(CGRect)rect {
// 用黑色表示已经绘制完成的线条
[[UIColor blackColor] set];
for (JXLine * line in self.finishedLines) {
[self strokeLine:line];
} // 用红色绘制正在画的线条
[[UIColor redColor] set];
for (NSValue * key in self.linesInProgress) {
[self strokeLine:self.linesInProgress[key]];
} if (self.currentLine) {
// 用红色表示当前正在绘制的线条
[[UIColor redColor] set
];
[self strokeLine:self.currentLine];
}

} - (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
UITouch * t = [touches anyObject]; for (UITouch * t in touches) {
CGPoint location = [t locationInView:self]; JXLine * line = [[JXLine alloc] init];
line.begin = location;
line.end = location; NSValue * key = [NSValue valueWithNonretainedObject:t];
self.linesInProgress[key] = line;
} // 根据触摸位置创建 JXLine 对象
CGPoint location = [t locationInView:self];
self.currentLine = [[JXLine alloc] init];
self.currentLine.begin = location;
self.currentLine.end =
location; [self setNeedsDisplay];
} - (void)touchesMoved:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event { for (UITouch * t in touches) {
NSValue * key = [NSValue valueWithNonretainedObject:t];
JXLine * line = self.linesInProgress[key];
line.end = [t locationInView:self];
} UITouch * t = [touches anyObject]; CGPoint location = [t locationInView:self]; self.currentLine.end =
location; [self setNeedsDisplay];
} - (void)touchesEnded:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event { for (UITouch *t in touches) {
NSValue * key = [NSValue valueWithNonretainedObject:t];
JXLine * line = self.linesInProgress[key]; [self.finishedLines addObject:line];
[self.linesInProgress removeObjectForKey:key];
} [self.finishedLines addObject:self.currentLine];
self.currentLine =
nil;
[self setNeedsDisplay];
}
@end

  最后还需要处理触摸取消事件。如果系统中断了应用,触摸事件将会被取消。这时应该将应用恢复到触摸事件发生前的状态。对于我们的应用来说是需要将正在绘制的线条删除。

#import "JXDrawView.h"
#import "JXLine.h" @interface JXDrawView ()
/** 保存当前正在绘制线条 */
@property (nonatomic,strong) JXLine * currentLine;
/** 保存已经绘制完成的线条 */
@property (nonatomic,strong) NSMutableArray * finishedLines;
/** 保存正在绘制的多条直线 */
@property (nonatomic,strong) NSMutableDictionary * linesInProgress; @end @implementation JXDrawView - (instancetype)initWithFrame:(CGRect)frame {
self = [super initWithFrame:frame];
if (self) { self.linesInProgress = [NSMutableDictionary dictionary];
self.finishedLines = [NSMutableArray array];
self.backgroundColor = [UIColor grayColor]; // 支持多点触摸
self.multipleTouchEnabled = YES;
}
return self;
} - (void)strokeLine:(JXLine *)line {
UIBezierPath * bp = [UIBezierPath bezierPath];
bp.lineWidth = ;
bp.lineCapStyle = kCGLineCapRound; [bp moveToPoint:line.begin];
[bp addLineToPoint:line.end];
[bp stroke];
} - (void)drawRect:(CGRect)rect {
// 用黑色表示已经绘制完成的线条
[[UIColor blackColor] set];
for (JXLine * line in self.finishedLines) {
[self strokeLine:line];
} // 用红色绘制正在画的线条
[[UIColor redColor] set];
for (NSValue * key in self.linesInProgress) {
[self strokeLine:self.linesInProgress[key]];
} } - (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event { for (UITouch * t in touches) {
CGPoint location = [t locationInView:self]; JXLine * line = [[JXLine alloc] init];
line.begin = location;
line.end = location; NSValue * key = [NSValue valueWithNonretainedObject:t];
self.linesInProgress[key] = line;
} [self setNeedsDisplay];
} - (void)touchesMoved:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event { for (UITouch * t in touches) {
NSValue * key = [NSValue valueWithNonretainedObject:t];
JXLine * line = self.linesInProgress[key];
line.end = [t locationInView:self];
} [self setNeedsDisplay];
} - (void)touchesEnded:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event { for (UITouch *t in touches) {
NSValue * key = [NSValue valueWithNonretainedObject:t];
JXLine * line = self.linesInProgress[key]; [self.finishedLines addObject:line];
[self.linesInProgress removeObjectForKey:key];
} [self setNeedsDisplay];
} - (void)touchesCancelled:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
for (UITouch *t in touches) {
NSValue * key = [NSValue valueWithNonretainedObject:t];
[self.linesInProgress removeObjectForKey:key];
}
[self setNeedsDisplay];
}
@end
  • 响应链

  UIResponder 对象可以接收触摸事件,而 UIView 是典型的 UIResponder 子类。除了 UIView ,还有很多其他的 UIResponder 子类,其中包括 UIViewController 、 UIApplication 、 UIWindowUIViewController 不是视图对象,也就是无法显示触摸,无法显示,为什么也是 UIResponder 子类呢?因为虽然不能向其直接发送触摸事件,但是该对象能够通过响应链来接收事件。

  UIResponder 对象拥有一个名为  nextResponder 的指针,相关的 UIResponder 对象可以通过该指针组成一个响应链。当 UIView 对象属于某个 UIViewController 对象时,其  nextResponder 指针就会指向包含该视图的 UIViewController 对象。当 UIView 对象不属于任何 UIViewController 对象时,其  nextResponder 指针就会指向该视图的父视图。UIViewController 对象的  nextResponder 通常会指向其视图的父视图。最顶层的父视图是 UIWindow 对象,而 UIWindow 对象的  nextResponder 指向的是 UIApplication 单例。

  如果 UIResponder 对爱国没有处理传给他的事件,会发生什么?该对象会将未处理的消息转发给自己的  nextResponder 。这也是  touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event  这类方法的默认实现。因此,如果没有为某个 UIResponder 对象覆盖特定的事件处理方法,那么该对象的  nextResponder 会尝试处理相应的触摸事件。最终,该事件会传递给 UIApplication ,如果它也无法处理,那么系统就会丢掉该事件。

  这里有一个操作技巧,获取 UIView 自定义文件的控制器

-(UIViewController *)viewcontroller{

    UIResponder *next = [self nextResponder];

    while (next) {

        if ([next isKindOfClass:[UIViewController class]]) {

            return (UIViewController *)next;

        }

        next = [next nextResponder];

    }

    return nil;

}

  项目地址

iOS 触摸事件与UIResponder(内容根据iOS编程编写)的更多相关文章

  1. IOS——触摸事件 视图检测和事件传递

    iPhone上有非常流畅的用户触摸交互体验,能检测各种手势:点击,滑动,放大缩小,旋转.大多数情况都是用UI*GestureRecognizer这样的手势对象来关联手势事件和手势处理函数.也有时候,会 ...

  2. IOS 触摸事件分发机制详解

    欢迎大家前往云+社区,获取更多腾讯海量技术实践干货哦~ 作者:MelonTeam 前言 很多时候大家都不关心IOS触摸事件的分发机制的实现原理,当遇到以下几种情形的时候你很可能抓破头皮都找不到解决方案 ...

  3. IOS触摸事件和手势识别

    IOS触摸事件和手势识别 目录 概述 触摸事件 手势识别 概述 为了实现一些新的需求,我们常常需要给IOS添加触摸事件和手势识别 触摸事件 触摸事件的四种方法 -(void)touchesBegan: ...

  4. 【原】iOS触摸事件深度解析

    概述 本文主要解析从我们的手指触摸苹果设备到最终响应事件的整个处理机制.本质上讲,整个过程可以分为两个步骤: 步骤1:找目标.在iOS视图层次结构中找到触摸事件的最终接受者: 步骤2:事件响应.基于i ...

  5. iOS触摸事件深度解析-备用

    概述 本文主要解析从我们的手指触摸苹果设备到最终响应事件的整个处理机制.本质上讲,整个过程可以分为两个步骤: 步骤1:找目标.在iOS视图层次结构中找到触摸事件的最终接受者: 步骤2:事件响应.基于i ...

  6. iOS触摸事件深入

    转载自:http://www.cnblogs.com/wengzilin/p/4720550.html 概述 本文主要解析从我们的手指触摸苹果设备到最终响应事件的整个处理机制.本质上讲,整个过程可以分 ...

  7. iOS 触摸事件与手势识别器(Gesture Recognizers)

    Gesture Recognizers与触摸事件分发 通过一个问题引出今天的知识: 1.大家应该都遇见过 当需要给tableView 添加一个tap 手势识别 但是tableView 的上的事件(滑动 ...

  8. iOS - UIEvent事件及UIResponder响应者

    在iOS中不是所有的对象都能处理事件,只有继承了UIResponder的对象才能接收并处理事件,称之为响应者对象: UIApplication.UIViewController.UIView都继承自U ...

  9. 浅谈iOS触摸事件理解

    iOS的触摸事件个人总结,分为两步: 第一步:是找到哪个视图上触摸 第二步:分析由谁去响应(响应者连) 1.寻找被触摸的视图原理如下图 hitText:withEvent:的方法处理流程: 首先会在当 ...

随机推荐

  1. [APUE]标准IO库(上)

    一.流和FILE对象 系统IO都是针对文件描述符,当打开一个文件时,即返回一个文件描述符,然后用该文件描述符来进行下面的操作,而对于标准IO库,它们的操作则是围绕流(stream)进行的. 当打开一个 ...

  2. CoreCRM 开发实录——开始之新项目的技术选择

    2016年11月,接受了一个工作,是对"悟空CRM"进行一些修补.这是一个不错的 CRM,开源,并提供一个 SaaS 的服务.正好微软的 .NET Core 和 ASP.NET C ...

  3. .NET平台开源项目速览(13)机器学习组件Accord.NET框架功能介绍

    Accord.NET Framework是在AForge.NET项目的基础上封装和进一步开发而来.因为AForge.NET更注重与一些底层和广度,而Accord.NET Framework更注重与机器 ...

  4. Photoshop将普通照片快速制作二次元漫画风格效果

    今天为大家分享Photoshop将普通照片快速制作二次元漫画风格效果,教程很不错,对于喜欢漫画的朋友可以参考本文,希望能对大家有所帮助! 一提到日本动画电影,大家第一印象肯定是宫崎骏,但是日本除了宫崎 ...

  5. Xamarin+Prism小试牛刀:定制跨平台Outlook邮箱应用

    通过本文你将学会如下内容: 1,如何使用Xamarin开发跨平台(Windows,Android,iOS)应用. 2,如何使用微软的登录界面登入Microsoft账号. 3,如何使用Outlook邮箱 ...

  6. My TWI

    前言 对TWI没有什么特别的印象,因为有一个更出名的TWU,而我去年又刚好错过了它,因此TWU的光辉完全掩盖了TWI.对TWI印象最深的是在邮件中看到的38th北京的这期,看到他们的图文记录,在圈子中 ...

  7. C#如何在PDF文件添加图片印章

    文档中添加印章可以起一定的作用,比如,防止文件随意被使用,或者确保文档内容的安全性和权威性.C#添加图片印章其实也有很多实现方法,这里我使用的是免费的第三方软件Free Spire.PDF,向大家阐述 ...

  8. 如何在Elasticsearch中安装中文分词器(IK+pinyin)

    如果直接使用Elasticsearch的朋友在处理中文内容的搜索时,肯定会遇到很尴尬的问题--中文词语被分成了一个一个的汉字,当用Kibana作图的时候,按照term来分组,结果一个汉字被分成了一组. ...

  9. Springboot搭建web项目

    最近因为项目需要接触了springboot,然后被其快速零配置的特点惊呆了.关于springboot相关的介绍我就不赘述了,大家自行百度google. 一.pom配置 首先,建立一个maven项目,修 ...

  10. Android Socket连接PC出错问题及解决

    最近测试问题:Android 通过Socket链接电脑,ip和端口都是正确的,也在同一网段,可android端就是报异常如下: 解决办法:测试电脑的防火墙可能开着,在控制面板把防火墙打开即可.