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
Thursday, November 6, 2014
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.
Note: You can read more about weak linking in Apple’s Framework Programming Guide.
Unsupported classesSometimes 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 } |
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 } |
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
Unsupported constants/C functionsFor 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)
.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 } |
UIApplicationWillEnterForegroundNotification
, you would simply validate it as so:if (&UIApplicationWillEnterForegroundNotification) { //Safe to assume multitasking support } else { //Fail gracefully } |
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 valuesChecking 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 checkingYou 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]; |
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.
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
FastImageCache: https://github.com/path/ FastImageCache
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:
- All images of the same dimension are stored in a single file(image table).
- Every image is stored with decompressing, original image never be stored.
- Image format can be specified before storing, so no need to format every time when using.
- All above prove it’s very fast to read the image and display them.
Weakness:
- All images are decompressed, it takes more space to store.
- The image table size is limited, the big images take more size and overall reduce the number of cached image.
- One image with multiple formats stores in multiple copies.
- Need initial configuration
SDWebImage: https://github.com/rs/ SDWebImage
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.
JMImageCache: https://github. com/jakemarsh/JMImageCache
It’s similar to SDWebImage.
TMCache: https://github.com/tumbir/ TMCache
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:
- It packs together images of the same dimensions to a single file.
- Uncompress image data to the file, so Fast Image Cache works best with smaller images.
- 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.
- Image table files are stored in the user's caches directory in a subdirectory called
ImageTables
Does not persist the original source images
Notes:
- 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.
- 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. -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:
.- 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.
- 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
* Use
* Switch don't need "break" any more
* You use
* Use a tuple to return multiple values from a function
*. Functions can be nested
*. You can refer to parameters by number instead of by name
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 optionalvar 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."
}
for
-in
to iterate over items in a dictionary by providing a pair of names to use for each key-value pairlet 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 bodynumbers.map({
(number: Int) -> Int in
let result = 3 * number
return result
})
or
numbers.map({ number in 3 * number })
sort([1, 5, 3, 12, 2]) { $0 > $1 }
Subscribe to:
Posts (Atom)