iOS 模拟终端控件

AKSDeviceConsole

AKSDeviceConsole.h

#import <Foundation/Foundation.h>

/**
 *   打印log的控件
 **/
@interface AKSDeviceConsole : NSObject
+ (void)startService;
@end

AKSDeviceConsole.m

#import "AKSDeviceConsole.h"
#import "AppDelegate.h"
#import <QuartzCore/QuartzCore.h>

#define AKS_LOG_FILE_PATH [[AKSDeviceConsole documentsDirectory] stringByAppendingPathComponent:@"ns.log"]
#define APPDELEGATE                                     ((AppDelegate *)[[UIApplication sharedApplication] delegate])


@interface AKSDeviceConsole () {
    UITextView *textView;
}
@end

@implementation AKSDeviceConsole

+ (id)sharedInstance {
    static id __sharedInstance;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        __sharedInstance = [[AKSDeviceConsole alloc]init];
    });
    return __sharedInstance;
}

+ (NSMutableString *)documentsDirectory {
    return [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES)objectAtIndex:0];
}

- (id)init {
    if (self = [super init]) {
        [self initialSetup];
    }
    return self;
}

- (void)initialSetup {
    [self resetLogData];
    [self addGestureRecogniser];
}

+ (void)startService {
    double delayInSeconds = 0.1;
    dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(delayInSeconds * NSEC_PER_SEC));
    dispatch_after(popTime, dispatch_get_main_queue(), ^(void) {
        [AKSDeviceConsole sharedInstance];
    });
}

- (void)resetLogData {
    [NSFileManager.defaultManager removeItemAtPath:AKS_LOG_FILE_PATH error:nil];
    freopen([AKS_LOG_FILE_PATH fileSystemRepresentation], "a", stderr);
}

- (void)addGestureRecogniser {
    UISwipeGestureRecognizer *recogniser = [[UISwipeGestureRecognizer alloc]initWithTarget:self action:@selector(showConsole)];
    [recogniser setDirection:UISwipeGestureRecognizerDirectionRight];
    [APPDELEGATE.window addGestureRecognizer:recogniser];
}

- (void)showConsole {
    if (textView == nil) {
        CGRect bounds = [[UIScreen mainScreen] bounds];
        float yG = 80.0;
        CGRect viewRectTextView = CGRectMake(0, yG, bounds.size.width, bounds.size.height - yG);

        textView = [[UITextView alloc]initWithFrame:viewRectTextView];
        [textView setBackgroundColor:[UIColor blackColor]];
        [textView setFont:[UIFont systemFontOfSize:12]];
        [textView setEditable:NO];
        [textView setTextColor:[UIColor whiteColor]];
        [[textView layer]setOpacity:0.8];

        [APPDELEGATE.window addSubview:textView];
        [APPDELEGATE.window bringSubviewToFront:textView];

        UISwipeGestureRecognizer *recogniser = [[UISwipeGestureRecognizer alloc]initWithTarget:self action:@selector(hideWithAnimation)];
        [recogniser setDirection:UISwipeGestureRecognizerDirectionLeft];
        [textView addGestureRecognizer:recogniser];

        [self moveThisViewTowardsLeftToRight:textView duration:0.30];
        [self setUpToGetLogData];
        [self scrollToLast];
    }
}
- (void)hideWithAnimation {
    [self moveThisViewTowardsLeft:textView duration:0.30];
    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 0.5 * NSEC_PER_SEC), dispatch_get_main_queue(), ^{
        [self hideConsole];
    });
}
- (void)hideConsole {
    [textView removeFromSuperview];
    [NSNotificationCenter.defaultCenter removeObserver:self];
    textView  = nil;
}
- (void)scrollToLast {
    NSRange txtOutputRange;
    txtOutputRange.location = textView.text.length;
    txtOutputRange.length = 0;
    textView.editable = YES;
    [textView scrollRangeToVisible:txtOutputRange];
    [textView setSelectedRange:txtOutputRange];
    textView.editable = NO;
}
- (void)setUpToGetLogData { 
    NSFileHandle *fileHandle = [NSFileHandle fileHandleForReadingAtPath:AKS_LOG_FILE_PATH];
    [NSNotificationCenter.defaultCenter addObserver:self selector:@selector(getData:) name:@"NSFileHandleReadCompletionNotification" object:fileHandle];
    [fileHandle readInBackgroundAndNotify];
}
- (void)getData:(NSNotification *)notification {
    NSData *data = notification.userInfo[NSFileHandleNotificationDataItem];
    if (data.length) {
        NSString *string = [NSString.alloc initWithData:data encoding:NSUTF8StringEncoding];
        textView.editable = YES;
        textView.text = [textView.text stringByAppendingString:string];
        textView.editable = NO;
        double delayInSeconds = 0.1;
        dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(delayInSeconds * NSEC_PER_SEC));
        dispatch_after(popTime, dispatch_get_main_queue(), ^(void) {
            [self scrollToLast];
        });
        [notification.object readInBackgroundAndNotify];
    }
    else {
        [self performSelector:@selector(refreshLog:) withObject:notification afterDelay:0.1];
    }
}
- (void)refreshLog:(NSNotification *)notification {
    [notification.object readInBackgroundAndNotify];
}
- (void)moveThisViewTowardsLeft:(UIView *)view duration:(float)dur; {
    [UIView animateWithDuration:dur animations: ^{
        [view setFrame:CGRectMake(view.frame.origin.x - [[UIScreen mainScreen]bounds].size.width, view.frame.origin.y, view.frame.size.width, view.frame.size.height)];
    } completion: ^(BOOL finished) {}];
}
- (void)moveThisViewTowardsLeftToRight:(UIView *)view duration:(float)dur; {
    CGRect original = [view frame];
    [view setFrame:CGRectMake(view.frame.origin.x - [[UIScreen mainScreen]bounds].size.width, view.frame.origin.y, view.frame.size.width, view.frame.size.height)];
    [UIView animateWithDuration:dur animations: ^{
        [view setFrame:original];
    } completion: ^(BOOL finished) {}];
}

@end
原文地址:https://www.cnblogs.com/huangzizhu/p/4596988.html