Thursday, November 6, 2014

[iOS]Cocoapods: manage library dependencies for your Xcode projects

CocoaPods manages library dependencies for your Xcode projects

1. $ sudo gem install cocoapods
It requires your ruby is >= v1.9.x, if it isn't, you need to upgrade as the following steps:
 1.1. Suggest to install rvm (Ruby Version Manager) with the following command line:
$ curl -L https://get.rvm.io | bash -s stable --ruby
1.2. Check available version
$ rvm list known
1.3. Select one to install
$ rvm install ruby-2.1.1

2. $ sudo gem install cocoapods again if update needed.

3. Go to you project directory to do the following command
 I suppose there's been a Podfile there:
$ pod intall
it will automatically generate the *.xworkspace project and Pods project for your project.

Reference URL: http://guides.cocoapods.org/using/getting-started.html

Monday, November 3, 2014

[Android] Add gradle environment constant

Add gradle environment constant: 1. Create ~/.gradle/gradle.properties 2. Add content like: env=stage Add environment constant for running time: $ gradle assembleDebug -Penv=stage Use in gradle file 1. $buildEnv 2. project.ext['buildEnv']

Thursday, October 30, 2014

[iOS] Create NSArray for non-object data types

Example: MKMapPoint *points; points = malloc(2 * sizeof(MKMapPoint)); points[0] = MKMapPointForCoordinate(CLLocationCoordinate2DMake(0, 1)); points[1] = MKMapPointForCoordinate(CLLocationCoordinate2DMake(1, 1)); .... free(points);

Monday, August 18, 2014

[iOS] Solving Backwards Compatibility Issues

Solving Backwards Compatibility Issues

Once you have identified the backwards compatibility issues in your app, the next step is to figure out how to fix them. Each new version of iOS introduces new frameworks, classes, methods, constants and enumeration values — and there’s a specific strategy to deal with each of these.
Unsupported frameworks
Linking against a framework that doesn’t exist in your deployment target will just cause the dynamic linker to crash your app. To solve this, you mark unsupported frameworks as “Optional” in your project settings.
To do this, select your project under the “Targets” section, and open up Build Phases -> Link Binary With Libraries. Next to each framework you can specify either Required or Optional. Selecting Optional will weak link the framework and solve your compatibility issue.
Weakly linking a library in Xcode
Note: You can read more about weak linking in Apple’s Framework Programming Guide.
Unsupported classes
Sometimes you want to use a class that exists in your base SDK, but not in your deployment target. To do this you need to check the availability of this class at runtime to avoid crashing your app. It crashes because this is what the Objetive-C runtime will do if you try to use a class that doesn’t exist. As of iOS 4.2, classes are weakly linked so you can use the +class method to perform the runtime check. For example:
if ([SLComposeViewController class]) {
    //Safe to use SLComposeViewController 
} else {
    //Fail gracefully
}
Unsupported methods
Similarly, if you’re using a method in your base SDK that doesn’t exist in your deployment target, you can avoid nasty crashes by using a little introspection.
The methods -respondsToSelector: and +instancesRespondToSelector: will both do the trick, as shown in the code examples below:
if ([self.image respondsToSelector:@selector(resizableImageWithCapInsets:resizingMode:)]) {
    //Safe to use this way of creating resizable images
} else {
    //Fail gracefully
}
The same goes for verifying the existence of class methods, except you call respondsToSelector: on the class itself, like so:
if ([UIView respondsToSelector:@selector(requiresConstraintBasedLayout)]) {
    //Safe to use this method
} else {
    //Fail gracefully
}
Note: If you want to check for the presence of a certain property on a class, then you can do so by testing that instances respond to the property getter or setter.
For example, to check if UILabel can take an attributed string via its attributedText property (new in iOS 6), perform introspection against the implicit setter method @selector(setAttributedText).
Unsupported constants/C functions
Sometimes a constant value is the missing piece of the deployment target; it usually takes the form of an extern NSString * or a C function. In this case, you can perform a runtime check against NULL to determine if it exists.
For example, the C function ABAddressBookCreateWithOptions(...) was introduced in iOS 6 but can still live safely in your iOS 5 app like so:
if (ABAddressBookCreateWithOptions != NULL) {
    //Safe to use
}
else {
    //Fail gracefully
}
The same approach applies to constants. For example, iOS 4.0 introduced multitasking support. If you wanted to check for the existence of UIApplicationWillEnterForegroundNotification, you would simply validate it as so:
if (&UIApplicationWillEnterForegroundNotification) {
    //Safe to assume multitasking support
}
else {
    //Fail gracefully
}
For further proof, take a look at UIApplication.h in Xcode. You’ll see that UIApplicationWillEnterForegroundNotification is simply an extern NSString * declared at the bottom of the document.
When your application is loaded into memory, these strings are initialized and stay resident in memory. The & operator gets the string’s memory address. If the memory address is not equal to nil, then the NSString is available, otherwise it’s not available and your code will have to work around that fact.
Note: The mechanism that makes this work is weak linking, which was described earlier. When a binary is loaded the dynamic linker replaces in the app binary any addresses of things (functions, constants, etc) in dynamically loaded libraries. If it’s weakly linked then if the symbol in the library is not found then the address is set to NULL.
Unsupported enumeration values
Checking for the existence of enumeration or bit mask values — the kind that you would find inside an NS_ENUM or NS_OPTIONS declaration — is incredibly difficult to check at runtime. Why?
Under the hood, an enumeration is just a method of giving names to numeric constants. An enum is replaced with an int when compiled, which always exists!
If you’re faced with the situation of needing to see if a certain enumeration exists, all you can do is either explicitly check the OS version (which isn’t recommended) or alternatively check against another API element that was introduced at the same time as the new enumeration value.
Note: Whichever way you do this, be sure to add adequate comments to any such code and consider wrapping the code in a dedicated compatibility helper.
Explicit iOS version checking
You should generally stay away from checking explicit iOS versions but there are specific situations where it’s unavoidable. For example, if you need to account for a bugfix in a previously available method, use the following line of code to return the OS version:
NSString *osVersion = [[UIDevice currentDevice] systemVersion];
You can use NSString’s compare:options: method, passing NSNumericSearch as the options to compare OS versions. This takes into account the fact that 6.1.1 is greater than 6.1.0. If you converted them to floats first and then used standard arithmetic things would go wrong because both would parse as the number 6.1.
Note: You can find out more about this topic in Apple’s SDK Compatibility Guide.

Tuesday, August 5, 2014

[iOS]Ojbective C async call sample

1. Define block method:
typedef void (^MyTestBlock)(void);

MyTestBlock myBlock = ^void() {
    // your implementation
}];

2. Consumer
[[NSNotificationCenter defaultCenter] addObserverForName:@"key" object:nil queue:nil usingBlock:^(NSNotification *note) {
            myBlock();
        }];

3. Trigger
[[NSNotificationCenter defaultCenter] postNotificationName:@"key" object:nil userInfo:nil];

Friday, August 1, 2014

[iOS] Error: Synthesis of weak property only allowed in arc or gc mode

Go to Targets -> Build Phases -> Compile Sources, find the file

double click it to add: -fobjc-arc

and rebuild again.

Tuesday, July 15, 2014

[iOS] Unit Test Frameworks

Apple provide its default test framework XCTestCase, but it's hard to use it to test async / block /delegate / protocol methods.

Here are some open source tools which can help you do everything as you want:
  • OCMockito - https://github.com/jonreid/OCMockito
    It's easy to mock any object, protocol can also be mocked, but can't handle the async methods.
  • Expecta - https://github.com/specta/expecta
    It provides powerful matchers and easy to use.
  • Aspects - https://github.com/steipete/Aspects
    Just like the name, you can do something before or after the methods or replace the methods' implementation.
  • Kiwi - https://github.com/kiwi-bdd/Kiwi
    It's very very powful to do asynchronous testing, stub methods to capture any methods' parameter, protocol mock and handle any you want to do.

    Kiwi docs  - https://github.com/kiwi-bdd/Kiwi/wiki

Wednesday, July 2, 2014

[JAVA]How to fix PIX Exception - HTTPS issue

Go to  /System/Library/Java/JavaVirtualMachines/1.6.0.jdk/Contents/Home/lib/security

java InstallCert DOMAIN_NAME
eg:  java InstallCert 1800tao.com

Tuesday, June 10, 2014

[iOS] Image Cache Libraries Comparison

The implementation is to pack together images of the same dimensions to a single file(image table), all images in image table are decompressed, and original image never be cached. 
When an image request is coming, it’s going to check the image table and simply return it immediately if it can be found, or else to download asynchronously from remote server, by the way, the decompressed image is added to the image table after it is done.
Advantage:
  1. All images of the same dimension are stored in a single file(image table).
  2. Every image is stored with decompressing, original image never be stored.
  3. Image format can be specified before storing, so no need to format every time when using.
  4. All above prove it’s very fast to read the image and display them. 
Weakness:
  1. All images are decompressed, it takes more space to store.
  2. The image table size is limited, the big images take more size and overall reduce the number of cached image.
  3. One image with multiple formats stores in multiple copies.
  4. Need initial configuration
The implementation is common, the original image is automatically cached when downloading from remote, and decompress and resize it when it’s about to using it. 
When image request is coming, it’s going to check the cache and simply return it immediately if it can be found, or else to download asynchronously from remote server.

It’s similar to SDWebImage.

It provides two types of cache mechanism, memory cache and disk cache, it applies to cache any object. If using it, you have to check if need to download image from remote by yourself.

Monday, June 9, 2014

[iOS] Fast Image Cache

  • Stores images of similar sizes and styles together
  • Persists image data to disk
  • Returns images to the user significantly faster than traditional methods
  • Automatically manages cache expiry based on recency of usage
  • Utilizes a model-based approach for storing and retrieving images
  • Allows images to be processed on a per-model basis before being stored into the cache
Specials:
  1. It packs together images of the same dimensions to a single file.
  2. Uncompress image data to the file, so Fast Image Cache works best with smaller images.
  3. Image table size is limited, how many images can it stores that depends on the images size, it will replace the old ones when it's to add more when it's full.
  4. Image table files are stored in the user's caches directory in a subdirectory called ImageTables
  5. Does not persist the original source images
Notes:
  1. Note that it is an entity and an image format name that uniquely identifies the desired image in the image cache. As a format name uniquely identifies an image table, the entity alone uniquely identifies the desired image data in an image table.
  2. The image cache never returns a UIImage directly. The requested image is included in the completion block. The return value will indicate whether or not the image already exists in the image cache.
  3. -retrieveImageForEntity:withFormatName:completionBlock: is a synchronous method. If the requested image already exists in the image cache, the completion block will be called immediately. There is an asynchronous counterpart to this method called -asynchronouslyRetrieveImageForEntity:withFormatName:completionBlock:.
  4. If a requested image does not already exist in the image cache, then the image cache invokes the necessary actions to request the source image for its delegate. Afterwards, perhaps some time later, the completion block will be called.
  5. If an image request is already in progress, it can be cancelled.


Saturday, June 7, 2014

[iOS] Learning note: Swift new features - constant, variable, control and function

Use let to make a constant and var to make a variable

* Use if and let together to work with values that might be missing. These values are represented as optionals. An optional value either contains a value or contains nil to indicate that the value is missing. Write a question mark (?) after the type of a value to mark the value as optional
  • var optionalString: String? = "Hello"
  • optionalString == nil
  • var optionalName: String? = "John Appleseed"
  • var greeting = "Hello!"
  • if let name = optionalName {
  • greeting = "Hello, \(name)"
  • }

* Switch don't need "break" any more
  • let vegetable = "red pepper"
  • switch vegetable {
  • case "celery":
  • let vegetableComment = "Add some raisins and make ants on a log."
  • case "cucumber", "watercress":
  • let vegetableComment = "That would make a good tea sandwich."
  • case let x where x.hasSuffix("pepper"):
  • let vegetableComment = "Is it a spicy \(x)?"
  • default:
  • let vegetableComment = "Everything tastes good in soup."
  • }

You use for-in to iterate over items in a dictionary by providing a pair of names to use for each key-value pair
  • let interestingNumbers = [
  • "Prime": [2, 3, 5, 7, 11, 13],
  • "Fibonacci": [1, 1, 2, 3, 5, 8],
  • "Square": [1, 4, 9, 16, 25],
  • ]
  • var largest = 0
  • for (kind, numbers) in interestingNumbers {
  • for number in numbers {
  • if number > largest {
  • largest = number
  • }
  • }
  • }

Use a tuple to return multiple values from a function
  • func getGasPrices() -> (Double, Double, Double) {
  • return (3.59, 3.69, 3.79)
  • }

*. Functions can be nested
  • func returnFifteen() -> Int {
  • var y = 10
  • func add() {
  • y += 5
  • }
  • add()
  • return y
  • }

*. Function can return another function as its value
  • func makeIncrementer() -> (Int -> Int) {
  • func addOne(number: Int) -> Int {
  • return 1 + number
  • }
  • return addOne
  • }
  • var increment = makeIncrementer()

*. Function can take another function as one of its arguments
  • func hasAnyMatches(list: Int[], condition: Int -> Bool) -> Bool {
  • for item in list {
  • if condition(item) {
  • return true
  • }
  • }
  • return false
  • }
  • func lessThanTen(number: Int) -> Bool {
  • return number < 10
  • }
  • var numbers = [20, 19, 7, 12]
  • hasAnyMatches(numbers, lessThanTen)

*. Functions are actually a special case of closures. You can write a closure without a name by surrounding code with braces ({}). Use in to separate the arguments and return type from the body
  • numbers.map({
  • (number: Int) -> Int in
  • let result = 3 * number
  • return result
  • })
  • or
  • numbers.map({ number in 3 * number })

*. You can refer to parameters by number instead of by name
  • sort([1, 5, 3, 12, 2]) { $0 > $1 }