Здравствуйте, дорогие читатели !
Вот и я решил сделать что-нибудь из тридцати строк на родном Objective-C. Попробуем в прямом эфире написать рисовалку под iPhone и iPad, уложившись в 30 строк кода.
Работать мы будем полностью в файле main.m для удобства подсчета строк. Создаем новый проект — Single View Application — и удаляем файлы классов ViewController'a и AppDelegat'a, так как их мы перенесем в main.m. Соответственно, в Storyboard'e отвязываем ViewController от автоматически созданного класса. Чтобы не париться из-за статус бара — убираем его в настройках, а так же фиксируем ориентацию экрана, чтобы не волноваться насчет поворотов девайса.
Сейчас main.m выглядит так:
//
// main.m
// LittleDrawer
//
// Created by Nikita Kolmogorov on 19.11.13.
// Copyright (c) 2013 Nikita Kolmogorov. All rights reserved.
//
#import <UIKit/UIKit.h>
#import "AppDelegate.h"
int main(int argc, char * argv[])
{
@autoreleasepool {
return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
}
}
Очень, очень жирно! Приведем его к минимальному виду, учитывая то, что код между {} можно писать в одну строку. Простите — иначе сложно влезть в 30 строк. Изменим main.m:
#import <UIKit/UIKit.h>
int main(int argc, char * argv[]) {@autoreleasepool {return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));} }
В разы лучше! Весь стандартный main.m теперь умещается в 2 строки. Но мы же удалили AppDelegate. Поправим эту оплошность. Файл main.m:
#import <UIKit/UIKit.h>
@interface AppDelegate : UIResponder <UIApplicationDelegate> @property (strong, nonatomic) UIWindow *window; @end
@implementation AppDelegate @end
int main(int argc, char * argv[]) {@autoreleasepool {return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));} }
Осталось всего 26 строк! Вызов принят.
Однако, AppDelegate, все-таки, придется немного поправить: нужно добавить нашу рисовалку на rootViewController:
@interface AppDelegate : UIResponder <UIApplicationDelegate> @property (strong, nonatomic) UIWindow *window; @end
@implementation AppDelegate
- (void)applicationDidFinishLaunching:(UIApplication *)application {
[self.window.rootViewController.view addSubview:[[Drawer alloc] init]];
} @end
Добавим класс нашей рисовалки, и main.m приобретает вид:
#import <UIKit/UIKit.h>
@interface Drawer : UIView @end
@implementation Drawer @end
@interface AppDelegate : UIResponder <UIApplicationDelegate> @property (strong, nonatomic) UIWindow *window; @end
@implementation AppDelegate
- (void)applicationDidFinishLaunching:(UIApplication *)application {
[self.window.rootViewController.view addSubview:[[Drawer alloc] initWithFrame:self.window.rootViewController.view.frame]];
}
@end
int main(int argc, char * argv[]) {@autoreleasepool {return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));} }
Использовали 9 строк, осталось 21 строка на рисование. Добавим текущий путь рисования и минимальный тач-функционал для правильной работы приложения в класс Drawer:
@implementation Drawer
static NSMutableArray *route;
- (void)drawRect:(CGRect)rect {
CGContextSetStrokeColorWithColor(UIGraphicsGetCurrentContext(), [UIColor whiteColor].CGColor);
CGContextMoveToPoint(UIGraphicsGetCurrentContext(),[route[0][0] intValue],[route[0][1] intValue]);
for (int i = 1; i < [route count]; i++)
CGContextAddLineToPoint(UIGraphicsGetCurrentContext(), [route[i][0] intValue], [route[i][1] intValue]);
CGContextStrokePath(UIGraphicsGetCurrentContext());
}
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
route = [NSMutableArray array];
[route addObject:@[@([[touches anyObject]locationInView:self].x),@([[touches anyObject]locationInView:self].y)]];
}
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
[route addObject:@[@([[touches anyObject]locationInView:self].x),@([[touches anyObject]locationInView:self].y)]];
[self setNeedsDisplay];
}
@end
Просто рисуем текущий путь по прикосновениям и не заботимся о уже нарисованном. Финальный файл main.m выглядит так:
#import <UIKit/UIKit.h>
@interface Drawer : UIView
@end
@implementation Drawer
static NSMutableArray *route;
- (void)drawRect:(CGRect)rect {
CGContextSetStrokeColorWithColor(UIGraphicsGetCurrentContext(), [UIColor whiteColor].CGColor);
CGContextMoveToPoint(UIGraphicsGetCurrentContext(),[route[0][0] intValue],[route[0][1] intValue]);
for (int i = 1; i < [route count]; i++)
CGContextAddLineToPoint(UIGraphicsGetCurrentContext(), [route[i][0] intValue], [route[i][1] intValue]);
CGContextStrokePath(UIGraphicsGetCurrentContext());
}
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
route = [NSMutableArray array];
[route addObject:@[@([[touches anyObject]locationInView:self].x),@([[touches anyObject]locationInView:self].y)]];
}
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
[route addObject:@[@([[touches anyObject]locationInView:self].x),@([[touches anyObject]locationInView:self].y)]];
[self setNeedsDisplay];
}
@end
@interface AppDelegate : UIResponder <UIApplicationDelegate>
@property (strong, nonatomic) UIWindow *window;
@end
@implementation AppDelegate
-(void)applicationDidFinishLaunching:(UIApplication *)application {
[self.window.rootViewController.view addSubview:[[Drawer alloc] initWithFrame:self.window.rootViewController.view.frame]];
}
@end
int main(int argc, char * argv[]) {@autoreleasepool {return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));} }
Ровно 30 строк кода на Objective-C. Вот и все! Мне даже почти удалось следовать своей стилистике кода. Единственное, на что не хватило строк — это расписать функцию main.
GitHub:
github.com/backmeupplz/LittleDrawer/
Instacode:
Автор: backmeupplz