Ecosyste.ms: Awesome

An open API service indexing awesome lists of open source software.

Awesome Lists | Featured Topics | Projects

https://github.com/andreyvit/SoloComponents-iOS

Self-contained, two-file (.h/.m) iPhone/iPad components that are dead-easy to drop into your projects
https://github.com/andreyvit/SoloComponents-iOS

Last synced: 3 months ago
JSON representation

Self-contained, two-file (.h/.m) iPhone/iPad components that are dead-easy to drop into your projects

Awesome Lists containing this project

README

        

Self-Contained Components for iOS
=================================

Two-file (.h / .m) useful components and utility classes that are dead-easy to drop into your iOS projects.

License: MIT (free for any use, no attribution required).

Follow us on twitter: [@SoloComponents](http://twitter.com/SoloComponents/).

Note: I want to collect as many open-source components as possible,
not just publish my own ones. If you have a useful iOS class that does
not depend on anything, feel free to fork, add and send me a pull
request!

ATPagingView
------------

ATPagingView is a wrapper around UIScrollView in (horizontal) paging
mode, with an API similar to UITableView.

Status: production-ready, used by at least one App Store app.

You provide the page views by implementing two delegate methods:

- (NSInteger)numberOfPagesInPagingView:(ATPagingView *)pagingView {
return 10;
}

- (UIView *)viewForPageInPagingView:(ATPagingView *)pagingView atIndex:(NSInteger)index {
UIView *view = [pagingView dequeueReusablePage];
if (view == nil) {
view = [[[DemoPageView alloc] init] autorelease];
}
return view;
}

You are also notified when the user navigates between pages:

- (void)currentPageDidChangeInPagingView:(ATPagingView *)pagingView {
self.navigationItem.title = [NSString stringWithFormat:@"%d of %d", pagingView.currentPageIndex+1, pagingView.pageCount];
}

You can use ATPagingView directly or derive your view controller from
ATPagingViewController.

ATPagingViewController is similar to UITableViewController and:

* defines `loadView` to create ATPagingView automatically,
* sets itself as a delegate of ATPagingView,
* calls `reloadData` in `viewWillAppear:` if the paging view is empty,
* additionally it forwards orientation events to the paging view (see below).

If you want to use ATPagingView without ATPagingViewController, you
need to:

* provide your delegate object using the `delegate` property,
* call `reloadData` to populate the view,
* if you want to support rotation, you need to invoke
`willAnimateRotation` and `didRotate` methods from your view
controller:

- (void)willAnimateRotationToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration {
[self.pagingView willAnimateRotation];
}

- (void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation {
[self.pagingView didRotate];
}

ATArrayView
-----------

A container that arranges its items in rows and columns similar to the
thumbnails screen in Photos.app, the API is modeled after UITableView.

Status: beta.

Enjoy the familiar delegate methods:

- (NSInteger)numberOfItemsInArrayView:(ATArrayView *)arrayView {
return 97;
}

- (UIView *)viewForItemInArrayView:(ATArrayView *)arrayView atIndex:(NSInteger)index {
DemoItemView *itemView = (DemoItemView *) [arrayView dequeueReusableItem];
if (itemView == nil) {
itemView = [[[DemoItemView alloc] init] autorelease];
}
return itemView;
}

There's ATArrayViewController which further reduces the amount of
boilerplate code you have to write. Similar to UITableViewController,
it:

* overrides `loadView` to create ATArrayView automatically,
* sets itself as a delegate of the array view,
* calls `reloadData` in `viewWillAppear:` if the array view is empty.

ATByteImage
-----------

Allows to easily use an image (CGImageRef) backed by a malloc'ed chunk
of memory. This means you can read or manipulate image bytes directly.

Status: ready for production use.

Using ATByteImage:

ATByteImage *blurred = [[ATByteImage alloc] initWithSize:blurredSize];
[blurred clear];

ATByteImageContext *blurredContext = [blurred newContext];
CGContextSetBlendMode(blurredContext.CGContext, kCGBlendModeNormal);
... draw using blurredContext.CGContext ...
[blurredContext release];

UIImage *myOverlay = [blurred extractImage];

Here's another example. The following function is useful in background
image loading code:

// Returns an uncompressed (decoded) UIImage, optimized for drawing speed.
//
// This is a middle ground between [UIImage imageNamed:] and a plain
// [UIImage imageWithContentsOfFile:], as follows:
//
// * [UIImage imageWithContentsOfFile:] loads image data from disk and
// decodes it each time you display the image.
//
// If you are using CATiledLayer to display a large image (and you should,
// since UIImageView is not recommended for images bigger than ~1024x1024),
// the whole JPEG will decoded for EACH tile you display.
//
// * [UIImage imageNamed:@"xxx"] only ever decodes the image once, just as you
// wanted. However it also caches the image and seems to sometimes (always?)
// not release the data even after you release your UIImage.
//
// An app that loads several large images via 'imageNamed' will thus crash
// quite soon with unfamous "error 0".
//
// Another undesired quality of 'imageNamed' is that the image is loaded and
// decoded when it is displayed for the first time, which means you can't
// really do the decoding in a background thread.
//
// * DecompressUIImage([UIImage imageWithContentsOfFile:@"xx.jpg"]) is the
// sweet spot between the two — it returns a fully decoded image which can
// be displayed quickly, and memory management is entirely up to you.
//
UIImage *DecompressUIImage(UIImage *image) {
ATByteImage *byteImage = [[[ATByteImage alloc] initWithImage:image] autorelease];
return [byteImage extractImage];
}