Главная
Блог разработчиков phpBB
 
+ 17 предустановленных модов
+ SEO-оптимизация форума
+ авторизация через соц. сети
+ защита от спама

Developing Titanium module for iOS

Anna | 2.07.2014 | нет комментариев

В этой статье я опишу создание нативного iOS модуля для Titanium. Целью статьи является показать базовые вещи при создании Titanium модуля, Дабы при необходимости вы не опасались расширить/ускорить базовый функционал Titanium.SDK. Стержневой задачей модуля будет сохранение pdf файла с наложением картинок поверх страниц.

Кому легко нужно такой модуль — начальный код.

Titanium разрешает создавать мобильные приложение на JavaScript. Но в различие от phonegap он не легко оборачивает html5 приложение в WebView, а запускает nodeJS сервер, на котором все это вертится. Все это отлично, но с pdf JavaScript пока нехорошо дружит. Для рендеринга есть pdf.js в котором как раз на мобильном сафари не все гладко, для генерации есть jspdf где помимо дрянный документации задачи с памятью. Дело в том, что огромный файл генерируется в ОЗУ и потом только сохраняется, но нередко ОС убивает приложение до того как файл поспеет сохранится.
Выходит, под катом касательно легкой метод ускорить приложение.

Предполагается применение Titanium SDK не ниже 3й версии. Позже установки titanium на ваш MacOS в консоле будет доступна команда «titanium», это не то, что нам необходимо. А необходимо нам «titanium.py» из “~/Library/Application Support/Titanium/mobilesdk/osx/[SDK Version]/”. Додайте алиасы, если не сделали этого ранее.

$ cat ~/.bash_profile 
alias ios_builder="/Users/peinguin/Library/Application Support/Titanium/mobilesdk/osx/3.1.3.GA/iphone/builder.py"
alias titanium.py="/Users/peinguin/Library/Application Support/Titanium/mobilesdk/osx/3.1.3.GA/titanium.py"

Позже этого дозволено сделать скелет модуля.

$ titanium.py create --platform=iphone --type=module --dir=/Volumes/yanpix_projects --name=pdfsaver --id=ti.pdfsaver

Собрать модуль дозволено командой:

$ ./build.py

Но пока собирать нечего. Для начала отменнее каждого очертить как вы будете применять модуль. В моем случае у меня был начальный pdf документ и canvas для всякой его страницы с пометками. Еще в некоторых случаях мне необходим был thumbnail первой страницы pdf документа.

Позже того, как вы определитесь с требуемым функционалом, опишите его в «example/app.js».

// TODO: write your module tests here
var pdfsaver = require('ti.pdfsaver');
Ti.API.info("module is => "   pdfsaver);

var old = Titanium.Filesystem.getFile(Titanium.Filesystem.getTempDirectory(),'test.pdf');
var newpdf = Titanium.Filesystem.getFile(Titanium.Filesystem.getTempDirectory(),'export.pdf');

pdfsaver.saveInExportFileWithDrawings(
	old.resolve(),
	newpdf.resolve(),
	{
		1: 'data:image/png;base64,[base64 image representation],
		4: 'data:image/png;base64,[base64 image representation]'
	},
	1
);

var jpeg = Titanium.Filesystem.getFile(Titanium.Filesystem.getTempDirectory(),'export.jpeg');

pdfsaver.saveThumbnail(
	newpdf.resolve(),
	jpeg.resolve()
);

Если в приложении вы можете получить «Resource directory», то в даном случае отменнее легко кинуть файлы в «Temp directory» приложения (~/Library/Application Support/iPhone Simulator/5.1/Applications/[app ID]/tmp).

Если верить документации, то «TiPdfsaverModuleAssets.h» и «TiPdfsaverModuleAssets.m» изменять нет смысла — всеравно перетираются. Свой код следует писать в «TiPdfsaverModule.m» и, соответственно «TiPdfsaverModule.h». Вот код моих функций:

#pragma Public APIs

-(void)saveThumbnail:(id)args{
	NSString *pdf = [args objectAtIndex:0];
	NSString *jpeg = [args objectAtIndex:1];

	CFURLRef url = CFURLCreateWithFileSystemPath (NULL, (CFStringRef)pdf, kCFURLPOSIXPathStyle, 0);
	CGPDFDocumentRef templateDocument = CGPDFDocumentCreateWithURL(url);
	CFRelease(url);

	CGPDFPageRef templatePage = CGPDFDocumentGetPage(templateDocument, 1); // get the first page
	CGRect templatePageBounds = CGPDFPageGetBoxRect(templatePage, kCGPDFCropBox);
	UIGraphicsBeginImageContext(templatePageBounds.size);

	CGContextRef contextRef = UIGraphicsGetCurrentContext();

	CGContextTranslateCTM(contextRef, 0.0, templatePageBounds.size.height);
	CGContextScaleCTM(contextRef, 1.0, -1.0);

	CGContextDrawPDFPage(contextRef, templatePage);

	UIImage *imageToReturn = UIGraphicsGetImageFromCurrentImageContext();
	UIGraphicsEndImageContext();
	CGPDFDocumentRelease(templateDocument);

	[UIImageJPEGRepresentation(imageToReturn, 1.0) writeToFile:jpeg atomically:YES];
}

-(void)saveInExportFileWithDrawings:(id)args{

	NSString *fresh = [args objectAtIndex:0];
	NSString *exportpath = [args objectAtIndex:1];
	NSDictionary *drawings = [args objectAtIndex:2];
	NSNumber *all = [args objectAtIndex:3];
	CFURLRef url = CFURLCreateWithFileSystemPath (NULL, (CFStringRef)fresh, kCFURLPOSIXPathStyle, 0);
	CGPDFDocumentRef templateDocument = CGPDFDocumentCreateWithURL(url);
	CFRelease(url);
	size_t count = CGPDFDocumentGetNumberOfPages(templateDocument);

	UIGraphicsBeginPDFContextToFile(exportpath, CGRectMake(0, 0, 612, 792), nil);
	for (int pageNumber = 1; pageNumber <= count; pageNumber  ) {
		id image = [drawings objectForKey:[NSString stringWithFormat:@"%d",pageNumber ]];
		if(image == nil && [all boolValue] == NO){
			continue;
		}

	    CGPDFPageRef templatePage = CGPDFDocumentGetPage(templateDocument, pageNumber);
	    CGRect templatePageBounds = CGPDFPageGetBoxRect(templatePage, kCGPDFCropBox);
	    UIGraphicsBeginPDFPageWithInfo(templatePageBounds, nil);
	    CGContextRef context = UIGraphicsGetCurrentContext();
	    CGContextTranslateCTM(context, 0.0, templatePageBounds.size.height);
	    CGContextScaleCTM(context, 1.0, -1.0);

	    CGContextDrawPDFPage(context, templatePage);

	    CGContextTranslateCTM(context, 0.0, templatePageBounds.size.height);
	    CGContextScaleCTM(context, 1.0, -1.0);

	    if(image != nil){
	    	NSURL *url = [NSURL URLWithString:image];    
			NSData *imageData = [NSData dataWithContentsOfURL:url];
			UIImage *ret = [UIImage imageWithData:imageData];

	    	[ret drawInRect:CGRectMake(0, 0, templatePageBounds.size.width, templatePageBounds.size.height)];
	    }
	}
	CGPDFDocumentRelease(templateDocument);
	UIGraphicsEndPDFContext();
}

Дозволено передавать сколько желательно доводов в функции и получать значения через «objectAtIndex». Либо проверять на присутствие индекса. Все параметры передаются как объекты по ссылке.

Сейчас Дабы проверить верную работу модуля необходимо исполнить:

$ titanium.py run

Когда вы удостоверитесь, что все работает верно. Соберите через «build.py» и разархивируйте zip файл, что находится в корне модуля, в корень вашего плана. А также додайте тег «module» в тег «modules» в файле «tiapp.xml» плана.

<modules>
    <module platform="iphone">ti.pdfsaver</module>
</modules>

В статье описаны только базовые вещи. Ни слова не сказано о View и Proxy. Но этого хватит Дабы не впадать в депресию, когда клиент умоляет что-то, что будет крепко тормозить на JS, но переписывать приложение с нуля теснее позно. На JS дозволено стремительно разрабатывать само приложение, ловить exception`ы, но Дабы само приложение стремительно работало стоит все-таки применять нативный код. Я думаю со временем каждый код моего приложения перепишется на objective-c что даст, в выводе, вероятность всецело отказатся от Titanium.

 

Источник: programmingmaster.ru

Оставить комментарий
Форум phpBB, русская поддержка форума phpBB
Рейтинг@Mail.ru 2008 - 2017 © BB3x.ru - русская поддержка форума phpBB