Using Parse SDK with Mantle

28 total views, 12 views today

Posted in iOS

Conditional Objects

Excerpted from Archives and Serializations Programming Guide

Another problem presented by object graphs is that it is not always appropriate to archive the entire graph. For example, when you encode an NSView object, the view can have many links to other objects: subviews, superviews, formatters, targets, windows, menus, and so on. If a view encoded all of its references to these objects, the entire application would get pulled in. Some objects are more important than others, though. A view’s subviews always should be archived, but not necessarily its superview. In this case, the superview is considered an extraneous part of the graph; a view can exist without its superview, but not its subviews. A view, however, needs to keep a reference to its superview, if the superview is also being encoded in the archive.

To solve this dilemma, NSCoder introduces the concept of a conditional object. A conditional object is an object that should be encoded only if it is being encoded unconditionally elsewhere in the object graph. A conditional object is encoded by invoking encodeConditionalObject:forKey:. If all requests to encode an object are made with these conditional methods, the object is not encoded and references to it decode to nil. If the object is encoded elsewhere, all the conditional references decode to the single encoded object.

Typically, conditional objects are used to encode weak references to objects.

NSCoder does not implement support for conditional objects; NSCoder’s implementation of encodeConditionalObject:forKey: simply encodes the object by invoking encodeObject:forKey:. It is the responsibility of its concrete subclasses to keep track of conditional objects and to not encode objects unless they are needed.

Example

Code sample is from Mantle

- (void)encodeWithCoder:(NSCoder *)coder {
	if (coderRequiresSecureCoding(coder)) verifyAllowedClassesByPropertyKey(self.class);

	[coder encodeObject:@(self.class.modelVersion) forKey:MTLModelVersionKey];

	NSDictionary *encodingBehaviors = self.class.encodingBehaviorsByPropertyKey;
	[self.dictionaryValue enumerateKeysAndObjectsUsingBlock:^(NSString *key, id value, BOOL *stop) {
		@try {
			// Skip nil values.
			if ([value isEqual:NSNull.null]) return;
			
			switch ([encodingBehaviors[key] unsignedIntegerValue]) {
					// This will also match a nil behavior.
				case MTLModelEncodingBehaviorExcluded:
					break;
					
				case MTLModelEncodingBehaviorUnconditional:
					[coder encodeObject:value forKey:key];
					break;
					
				case MTLModelEncodingBehaviorConditional:
					[coder encodeConditionalObject:value forKey:key];
					break;
					
				default:
					NSAssert(NO, @"Unrecognized encoding behavior %@ on class %@ for key \"%@\"", self.class, encodingBehaviors[key], key);
			}
		} @catch (NSException *ex) {
			NSLog(@"*** Caught exception encoding value for key \"%@\" on class %@: %@", key, self.class, ex);
			@throw ex;
		}
	}];
}

60 total views, 12 views today

Posted in iOS

Understand presentingViewController

444 total views, 4 views today

Posted in iOS

iOS Code Signing

492 total views, no views today

Posted in iOS

There are many iOS conferences and groups

There are many iOS conferences and groups. If you don’t have a chance to go, it is helpful that you know their existence and learn about them. In fact, some of them provides free slides, videos, sharing materials that you should not overlook

Some of the conferences are not really specific to iOS, but it is good for your development career

WWDC

The Apple Worldwide Developers Conference (WWDC) takes places June 2-6 in San Francisco with an in-depth look at the latest in iOS and OS X

WWDC 2014 Session Videos
ASCIIwwdc. Searchable full-text transcripts of WWDC sessions

Read more ›

708 total views, 8 views today

Posted in iOS

iOS dynamic table view cells with varying row height and Autolayout

This post tries to explain how to achieve varying cell height with Autolayout simply and with few steps as possible. Although the title says Table View, it works for Collection View also. This works for both iOS 7 and iOS 8

The Github repo for the demo is DynamicTableViewCellHeight

The demo display a list of famous quotes, it looks like this

preferredMaxLayoutWidth

The trick to all this come from preferredMaxLayoutWidth. For more advanced use case, see Auto Layout and Views that Wrap

User Interface

I use Storyboard, but you can use xib or create from code. For how to use code, please take a look AutoSize UITableViewCell height programmatically

Here the quote label is multiple lines (Set Lines to 0). Because we have 2 labels, Autolayout does not know which will expand, which will stay the same when the cell changes size. In this case, we want the quote label to expand, so decrease its Verticle Hugging Priority and increase its Content Compression Resistance Priority

Read more ›

2,036 total views, 28 views today

Posted in iOS

Fun with Objective C

I really love that moment when people try to use Objective C to imitate features of other languages or to make some cool tricks. It is a chance for you to learn more about Objective C

Statically typed Objective-C collections

Do you like typed arrays in Swift (or other languages)? Would you like to have them in Objective-C? Now you can.

“Currying” Objective-C Methods

In this blog post, I’ll show you a way to “curry” Objective-C methods. I’ll first talk about the problem I’m trying to solve, what currying is, and how currying can help solve the problem

Switching on Objects in Objective-C

A simple way to implement object based switch-like statements in Objective-C using blocks. Any object that conforms to NSCopying can be used to switched on.

OCUDL

OCUDL is an experiment to bring user defined literals to Objective-C. A literal is a shorthand expression that creates a value of a certain type. For example, 25ul creates an unsigned long of 25, and @”hello” creates an NSString of hello. User defined literals bring this brevity and expressivity to our own types.

A pattern to switch on an object’s value

I want to show, how we can achieve switching on a block with a similar two-closure approach — or in Objective-C: two-block approach.

FTGShorthand

Allows your category methods to be in shorthand form, like MagicalRecord MR_SHORTHAND

Reference

  1. Fun with Objective-C
  2. Some Nice Features of the Objective-C Language

936 total views, 4 views today

Posted in iOS

Objective-C has that named parameter

Swift supports named parameter. Objective-C in fact has that feature long ago

Swift

When encapsulated in a class (or struct or enum), the first parameter name of a method is not included externally, while all following parameter names are included externally when the method is called

class Person {
    func performThing1(thing1 :String, thing2 :String) {
        println("thing1 \(thing1) thing2 \(thing2)")
    }

    func performThing3(thing3 :String, _ thing4 :String) {
        println("thing3 \(thing3) thing4 \(thing4)")
    }

}

let person = Person()
person.performThing1("one", thing2: "two")
person.performThing3("three", "four")

Objective C

Methods can also take parameters, also called arguments. A message with a single argument affixes a colon (:) to the selector name and puts the parameter right after the colon. This construct is called a keyword; a keyword ends with a colon, and a parameter follows the colon. A method that takes multiple parameters has multiple keywords, each followed by a colon.

@implementation FTGPerson

- (void)performThing1:(NSString *)thing1 thing2:(NSString *)thing2
{
    NSLog(@"thing1 %@ thing 2 %@", thing1, thing2);
}

// Note how the 2nd external parameter name is discarded
- (void)performThing3:(NSString *)thing3 :(NSString *)thing4
{
    NSLog(@"thing3 %@ thing 4 %@", thing3, thing4);
}

@end

FTGPerson *person = [FTGPerson new];
[person performThing1:@"one" thing2:@"two"];
[person performThing3:@"three" :@"four"];

Reference

  1. Method names in Objective-C
  2. For Those Who Have Never Used Objective-C
  3. The Many Faces of Swift Functions
  4. Why must the last part of an Objective-C method name take an argument (when there is more than one part)?
  5. Message

736 total views, 8 views today

Posted in iOS

CocoaPods gotcha

Hi, in this post, I ‘ll share things I learn about Cocoapods

What goes into your .gitignore if you’re using Cocoapods

This question raises debate on SO, but I would recommend only track the Podfile and Podfile.lock. The Pods folder, .xcworkspace should go into .gitignore

Read more about the pros and cons Not Cuckoo for CocoaPods

pod install vs pod update

pod install

Every time the pod install command is run and it downloads and install new pods, it writes the version that it has installed, for each pods, in the Podfile.lock file. This file is intended to keep track of the installed version of each pod and to lock those versions

pod update

When you run pod update SomePodName, CocoaPods will try to find an updated version of the pod SomePodName, without taking into account the version listed in Podfile.lock. It will update the pod to the latest version possible (as long as it matches the version restrictions in your Podfile).

Read more Detailed presentation of the commands, Cocoa​Pods on NSHipster

You can edit the source of the Pod

Yes, you can edit the source of the Pod, and your change will be overriden by the next pod update, unless you use :path. See this reply by @orta

Your .xcodeproj remains unchanged

Actually, it remains unchanged after the first pod install
As pointed out Cocoapods

CocoaPods will create a new Xcode project that creates static library targets for each dependency, and then links them all together into a libPods.a target. This static library becomes a dependency for your original application target. An xcworkspace file is created, and should be used from that point onward. This allows the original xcodeproj file to remain unchanged.

The sandbox is not in sync with the Podfile.lock

It’s because of the Manifest.lock

This is a copy of the Podfile.lock that gets created every time you run pod install. If you’ve ever seen the error The sandbox is not in sync with the Podfile.lock, it’s because this file is no longer the same as the Podfile.lock. Since the Pods directory is not always under version control, this is a way of making sure that developers update their pods before running, as otherwise the app would crash, or the build would fail in another, less visible, way.

Where are the Specs stored locally

The Specs repo is pulled into ./cocoapods/repos/master/Specs

References

  1. February 2014 Tech Talk: CocoaPods
  2. UIKonf 2014 — Orta Therox: CocoaPods
  3. MCE 2014: Orta Therox – CocoaPods and the road to 1.0

1,044 total views, 12 views today

Posted in iOS

iOS static table view cells with varying row height and Autolayout

In this post, I ‘ll show how to achieve varying row height with static tableview and autolayout

Make sure your static cell Autolayout is setup correctly

This step is the same as dynamic table view, just make sure you add constraints to the contentView, not the cell

Dynamic height

Since this is a static tableview, you don’t need that prototypeCell trick, you can just use the IBOutlet directly. This is what happens in my UITableViewDelegate, note how I reference descriptionLabel

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
    if (indexPath.section == 1 && indexPath.row > 0) {
        return 0;
    }

    if (indexPath.section == 0 && indexPath.row == 2) {
        CGSize size = [self.descriptionLabel systemLayoutSizeFittingSize:UILayoutFittingCompressedSize];
        return size.height;
    }

    return [super tableView:tableView heightForRowAtIndexPath:indexPath];
}

Note

Make you you have set preferredMaxLayoutWidth for the descriptionLabel

Reference

  1. Using Auto Layout in UITableView for dynamic cell layouts & variable row heights
  2. Dynamic Table View Cell Height and Auto Layout
  3. Table View Cells With Varying Row Heights

1,964 total views, 16 views today

Posted in iOS