Thursday, November 20, 2014

Variables can be accessed by a javascript function

When a javascript function is called, sometime it is confusing on which variables it can access.
1. parameters passed by caller (decided at runtime)

2. local variables defined within the function,

3. closure variables
    closure variable only depends on where the function is defined, and it also includes different levels of parent scopes all the way up to the global scope.

4. global variables
   global variable is accessible in the sense of a special kind of closure variable, as all function will end up in the global scope.

5. this properties
   The properties of this object can be accessed by using this.property within a function. However, when the function is called, this object may be changed from time to time depending on how it is called. So be sure to check the property is valid before using it.

Wednesday, November 12, 2014

Get ipa file from xcode with itune

1. build the xocde project,
2. from Finder go to the product build folder to get the project's package,  for example
/Users/i826633/Library/Developer/Xcode/DerivedData/fiori-dktztqbnspcsocekrhfgynaddvhg/Build/Products/Debug-iphoneos/myproject
3. from iTune, select your device, then select App icon on top left tool bar, (it may hide in ... menu item), the app list shows and take the full window
4. select File->Add library menu, and select the project package file
5. after the app shows in the main app list window.
6. right click on the application just added, and select show in finder menu item
7. the ipa file should be in the opened Finder window

Note you can also view the content of ipa file, as the ipa file is actually a signed zipped file of the application bundle, just rename it to .zip and any zip utility is able to unzip it to a package folder.

Sunday, November 9, 2014

How to subclass NSMutableDictionary in Objective C

NSMutableDictionary (as well as other collection class) are cluster class, so they are actually abstract class, as a result, you cannot simply inherit your class from NSMutableDictionary and then just call super class' method to relay the request.

The way to do it is through a proxy object, so your derived class just creates a dummy NSMutableDictionary, but the only thing it does is to relay the caller's request to the proxy object, so you can monitor what methods are called on the NSMutableDictionaryobject, and what are the parameters are used.

The following is a sample class derived from NSMutableDictionary

@interface MyMutableDictionary : NSMutableDictionary
@end

@implementation MyMutableDictionary{
 NSMutableDictionary* _proxy;
}

- (void)removeObjectForKey:(id)aKey{
  [_proxy removeObjectForKey:aKey];
}

- (void)setObject:(id)anObject forKey:(id <NSCopying>)aKey{
  [_proxy setObject:anObject forKey:aKey];
}

- (id)objectForKey:(id)aKey{
  return [_proxy objectForKey:aKey];
}

- (NSEnumerator *)keyEnumerator{
    return [_proxy keyEnumerator];
}

- (NSUInteger) count{
    return [_proxy count];
}

- (instancetype)init {
    if (self = [super init]) {
        _proxy = [[NSMutableDictionary alloc] init];
    }
    return self;
}

- (instancetype)initWithCapacity:(NSUInteger)numItems{
    self = [super init];
    _proxy = [[NSMutableDictionary alloc] initWithCapacity:numItems];
   return self;
}

- (NSMutableDictionary *)initWithContentsOfFile:(NSString *)path{
    self = [self init];
    _proxy = [[NSMutableDictionary alloc] initWithContentsOfFile:path];
    return self;
}

- (instancetype)initWithCoder:(NSCoder *)aDecoder{
    self = [super init];
    _proxy = [[NSMutableDictionary alloc] initWithCoder:aDecoder];
    return self;
}

@end

Friday, November 7, 2014

How to reload the html page when debugging iOS/Android webview

When debugging the javascript using Safari for ios uiwebview or Chrome for android webview, sometime it needs to force to reload the html page to repeat the issues that only happens during the page loading, or to restart the page without restarting the app.

For ios, from safari's web inspector, select resource tab, and then select the root item, there is a refresh icon beside the root item, click it will reload the html page

For android, in chrome, first selecting the app from the page of
chrome://inspect/#devices
then in Chrome's Developer Tools, select Source tab, from the console window type

location.reload(true)

By doing so, any javascript breakpoints will be kept in there, and available when the html page gets reloaded.

Wednesday, November 5, 2014

Implement javascript encapsulation with closure

Javascript does not have build-in support for encapsulation, but it can realize the similar function with closure.

First, javascript cannot use scope to hide private method or variable, as local variable and function within a scope are accessible even out of scope, the following code shows this

function test() {
 
   {
  var m = "hello";
  function inner(){
alert("inner");
  }
   }

   alert(m);  //show hello
   inner(); //show inner
}


Second, object scope also does not help for encapsulation, as javascript object initializer cannot have local variables and methods, all properties and methods defined for an object are public, which cannot be used to hide internal implementation.

var Obj = {
      property1 : "my property",
      method1 : function(){
                         alert(this.property1);
                           }
     //cannot define local variable within object scope
}

Obj.method1();


So the only way to support encapsulation for javascript is by using function scope, as a function can define local variable including functions which are only visible inside the function scope. And the function can also return a set of public apis to caller to use. When caller calls the public APIs, the implementation of the Apis as inner function can access all the local variables and functions within the function scope due to the closure. Most javascript framework uses this approach to implement the encapsulation pattern in javascript. The below sample shows the basic idea of this usage.

function MyClass() {

      var privateVar = {
           property1 : "my property",
           method1 : function(){
                         alert(this.property1);
                      }
};

var privateMethod1 = function(v)
  {
  alert(v);
  privateVar.method1();
  };

var publicVariable = {
name: "John",
age: 10
};
var publicMethod = function(){
privateMethod1(privateVar.property1);
} ;
        //expose public method for caller to access
return {
publicFunc: publicMethod,
publicVar : publicVariable
};
}


function test() {
     var obj = MyClass();
     obj.publicFunc(); //call public method to access private info
     alert(obj.publicVar);
     //obj.privateMethod1(); //cannot access private member and throw exception
}