2012年11月16日 星期五

[WPF]Background dynamic fill with one direction

I have a very long and thin image, and I want to use it as a background image in WPF application, which the image should repeat horizontally.
My first code insight is from
WPF: How do i create a background that repeats horizontally without scalling?
But, it fails to repeats properly, the reason is that ViewportUnits="Absolute", so it actually stretch my image to very large. Which is kind of hardcode.

Then I saw this reference TileBrush.Viewport Property
So I use this this code to create the background brush instead
  <imagebrush imagesource="/Resources/Image/pattern.png" 
            tilemode="FlipY" viewport="0,0,0.033,1" 
            viewportunits="RelativeToBoundingBox"
            x:key="BackGroundBrush">
Which 0.033:1 is the width:height ratio of my background. With this brush, the image will be stretch to suitable height.

For repeat horizontally, just change tilemode to FlipX and viewport to "0,0,1,x" where 1:x is the ratio.

p.s. this method is a improved version of the stackoverflow solution on the way that it can show the whole image, but the drawback is the image might be stretched for a little. And seems there is no simple way to do this without binding.

2012年10月21日 星期日

Why Weibo SSO sdk don't jump back to my iOS app

This question is for those didn't watch the documentation of the SSO-sdk(me as an example).

The callback url is not set in the web. It should be placed when you initiate the SinaWeibo instance. It is provided 2 init method and they are:
-(id) initWithAppKey:(NSString*)_appKey 
           appSecret:(NSString *)_appSecrect 
      appRedirectURI:(NSString *) _appRedirectURI
         andDelegate:(id)_delegate 
and
- (id)initWithAppKey:(NSString *)_appKey 
           appSecret:(NSString *)_appSecrect 
      appRedirectURI:(NSString *) _appRedirectURI
   ssoCallbackScheme:(NSString *)_ssoCallbackScheme
         andDelegate:(id)_delegate
We should use the latter one and put the callback Uri as ssoCallbackScheme, then everything will be work fine.

2012年10月18日 星期四

Time to String? Date Format Patterns?

To convert time to string, we always use formats like "yyyy-MM-dd HH:mm:ss", but sometimes we want something more like "18 Oct 2012" or "Wed 12:34:56", then the reference page can help you.
Date Format Patterns

With the table in the page, you should be good enough to do more tricks on date formats.

2012年10月15日 星期一

[iOS] Why no privacy alerts in simulator?

This is not a bug. This is the restriction on simulator.
From the iOS6.0 release note, we seen that apple doesn't the privacy alerts in simulator.

Simulator

  • No privacy alerts are displayed in iOS Simulator for apps that access Photos, Contacts, Calendar, and Reminders.
  • For this release, iOS Simulator does not support testing In-App Purchase. Please use a device to test your apps that use this feature.
  • When attempting to play an MP3 sound in Simulator, you will hear a popping sound instead.
Source:iOS6.0 release note

Reset iPhone Privacy

To clear/reset iPhone Privacy Settings like contacts and location services, you can go to Settings and follow the routine:
Settings -> General -> Reset -> Reset Privacy and Location

Which is useful for developer, as the privacy prompt only prompt once if you never reset.

2012年10月14日 星期日

Toggling Privacy settings in iOS6 will kill the app

If you played with Location Services in iPhone, you knows that after you changed the location setting in iPhone Settings, you are able to get the change and update your application. While Contact(AddressBook) and Location Services are both packed in Privacy Setting, you would expect there is similar behaviour on Contact.

Sadly, its not true. After you changed the setting of contact, your app will receive a SIGKILL signal and stop.

Source:StackOverflow

2012年10月11日 星期四

Apple iDevice architecture

Since XCode4.5, apple have drop support to ARM architecture of ARMv6, and set the minimum device version to 4.3, which burden developers that need to support older version.

To understand how it affect developers, one should understand there are 2 fields they need to handle with, they are:
1. ARM Architecture
2. iOS Deployment Target

to know more about architecture, please visit instruction set architecture.

In this article, we mainly focus on the architecture of different apple device.

The first question you may want to ask is, what iDevice is using ARMv6 architecture? The answer is simple, For iPhone, it is iPhone(original) and iPhone 3G. For iPod Touch, it is only 1st generation.
For iPad, none of them are using ARMv6. Here is more detail:

iPhone:
Model CPU Core ARM architecture
iPhone 620 MHz (underclocked to 412 MHz) ARM 1176JZ(F)-S ARMv6
iPhone 3G
iPhone 3GS 833 MHz (underclocked to 600 MHz) ARM Cortex-A8 ARMv7
iPhone 4 1 GHz (underclocked to 800 MHz) Apple A4
iPhone 4S 1 GHz (underclocked to 800 MHz) Dual-core Apple A5
iPhone 5 Apple A6 ARMv7s

iPod Touch:
Model CPU Core ARM architecture
1st generation 620 MHz (underclocked to 412 MHz, originally 400 MHz) ARM 1176JZ(F)-S ARMv6
2nd generation 620 MHz (underclocked to 533 MHz) ARM 1176JZ(F)-S ARMv7
3rd generation 833 MHz (underclocked to 600 MHz) ARM Cortex-A8 core
4th generation 1 GHz (underclocked to 800 MHz) ARM Cortex-A8
5th generation ARM Cortex-A9
iPad:
Model CPU Core ARM architecture
iPad (original) 1 GHz ARM Cortex-A8 ARMv7
iPad 2 1 GHz dual-core ARM Cortex-A9
iPad (3rd generation) 1 GHz dual-core ARM Cortex-A9

2012年10月8日 星期一

iOS6 permissions [Contacts]

On iOS6, apple introduce new privacy control, user can control the accessment of contact and calender by each app. So, in the code side, you need to add some way to request the permission. In iOS5 or before, we can always call
ABAddressBookRef addressBook = ABAddressBookCreate();
to get the addressbook without any problem, but in iOS6, if you don't have permission, this call will just return empty pointer. That why we need to change the method to get ABAddressBookRef.

__block BOOL accessGranted = NO;
if (ABAddressBookRequestAccessWithCompletion != NULL) { // we're on iOS 6
    dispatch_semaphore_t sema = dispatch_semaphore_create(0);
    ABAddressBookRequestAccessWithCompletion(addressBook, ^(bool granted, CFErrorRef error) {
        accessGranted = granted;
        dispatch_semaphore_signal(sema);
    });
    dispatch_semaphore_wait(sema, DISPATCH_TIME_FOREVER);
    dispatch_release(sema);  
}
else { // we're on iOS 5 or older
    accessGranted = YES;
}

if (accessGranted) {
    // Do whatever you want here.
}
In the code,semaphore is used for blocking until response, while ABAddressBookRequestAccessWithCompletion will ask for permission if the app didn't ask before. Otherwise it will just follow the settings in Settings-Privacy-Contact.

2012年5月10日 星期四

[Windows] Depreciated in C#

To set a function in .net as depreciated, we can use code like this


        [Obsolete("Reason of depreciate.")]
        public void Your_Function(int parameters)
        {
            Your_Code_Here;
        }
After that, when you reference this function, it will shows as depreciated, and will have a warning saying your call is obsolete.

2012年5月4日 星期五

[Windows] Basic WPF UI template

When you creating a UI for your application, usually you will make several UI element of same type, it is kind of annoying if you need to copy and paste all attributes to make those object looks the same. So in XAML programming in WPF, you can define a template for your controls.

Code snapshot:
<UserControl>
    <UserControl.Resources>
        <Style x:Key="BaseBtn" TargetType="Button">
            <Setter Property="Width" Value="80px"/>
            <Setter Property="Height" Value="80px"/>
        </Style>
        <Style x:Key="BottomRightBtn" BasedOn="{StaticResource BaseBtn}" 
                TargetType="Button">
            <Setter Property="HorizontalAlignment" Value="Right"/>
            <Setter Property="VerticalAlignment" Value="Bottom"/>
            <Setter Property="Margin" Value="10"/>
        </Style>
        <Style x:Key="BottomLeftBtn" BasedOn="{StaticResource BaseBtn}"
                TargetType="Button">
            <Setter Property="HorizontalAlignment" Value="Left"/>
            <Setter Property="VerticalAlignment" Value="Bottom"/>
            <Setter Property="Margin" Value="10"/>
        </Style>
    </UserControl.Resources> 
    <Grid>
        <Button Content="BaseBtn" Style="{StaticResource BaseBtn}"/>
        <Button Content="BottomLeftBtn"
                Style="{StaticResource BottomLeftBtn}"/>
        <Button Content="BottomRightBtn"
                Style="{StaticResource BottomRightBtn}"/>
    </Grid>
</UserControl>


UserControl.Resources is a nice place to put all your styles.
Note that you need to specify the TargetType in style tag. So your style can be used on this type only.
Each Setter define a single property like width and height, which should also exist in the target type.
To use the style, just use something like Style="{StaticResource ResourceKey}" to reference them.
That how you do simple sytle in WPF XAML, probably will save you some time.

2012年4月29日 星期日

[iOS] Exception catching

Exception catching is essential in developing application in .net framework and java.
While in Objective-C, it is much less powerful and shouldn't rely on it, as usually it just crash and didn't catch anything. Yet, it is still a plus if you really catch something.

Usage is really simple
@try
{
    Function_You_Want_To_Catch_Exception;
}
@catch (NSException* exception)
{
   Do_Thing_After_Exception_Caught;
}


One example is to put it in main.m, in order to catch any uncaught exception.
int main(int argc, char *argv[]) {
    NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
    int retVal = -1;
    @try {
        retVal = UIApplicationMain(argc, argv, nil, nil);
    }
    @catch (NSException* exception) {
        NSLog(@"Uncaught exception: %@", exception.description);
        NSLog(@"Stack trace: %@", [exception callStackSymbols]);
    }
    [pool release];
    return retVal;
}
which shows how to catch all uncatched exception in the app.

Another usage is when you like "exception programming", you can raise your own exception, by using [NSException raise:format:] and catch it with above code.
Example:

[NSException raise:NSInvalidArgumentException format:@"Foo must not be nil"];

There are several exception name already defined by apple here. but if you want to use your own, put a NSString there is fine.

[iOS] Catch application end

Sometime we always want to catch the application terminate in mobile platform.

In iDevice, we can use
 - (void)applicationWillTerminate:(UIApplication *)application
to catch the terminate action.

But since iOS 4.0, application will goes to background instead of being killed when you press the home button.
If you are doing so,  
- (void)applicationWillTerminate:(UIApplication *)application 
might not be called.

From apple developer's guide,UIApplicationDelegate Protocol Reference 
- (void)applicationDidEnterBackground:(UIApplication *)application 
will be called instead.
 
When you goes to background, and kill the app bu double click the home button and click the red cross,
 - (void)applicationWillTerminate:(UIApplication *)application 

will still being called. But if it died naturally, then it won't be called.