The Mobile Galaxy The New Mobile Era Has Come | Mobile – A Time To Remember

10Dec/110

Got Git? HOWTO git and github

Thanks to Steven Bristol .

From :http://lesseverything.com/blog/archives/2008/03/25/got-git-howto-git-and-github/

Share
6Dec/110

iPhone Program Crashes and Stability Issues

If you’re running into frequent iPhone program crashes, here are some tips for getting better stability.

Application memory management issues

Generally, it caused by memory management, such as a instance un-alloc, released, un-expected copy. This kind issues is easy to find through unit test and functionality test.

Apple firmware compatibility issues

As the IOS version change, API maybe different, sometimes it is serious and kill the app.

For example:

In IOS 5, the following statement is fine:

UIBarButtonItem* rightBtn= [[UIBarButtonItem alloc] initWithTitle:@"Upload" style:UIBarButtonItemStylePlain target:self action:@selector(upload)];

rightBtn.tintColor=[UIColor redColor]; // it will crash in IOS 4.0

In IOS 4.2.1

-(void)finishedTakePicture:(UIImage*)img{

_stillimage =[img copy]; // This run fine in IOS 4.2.1, but it will crash in IOS 4.1

// solution:   [_stillimage setValue:img forKey:@"image"];

}

So checking each IOS version API difference is most important to avoid random crash. generally this kind issues can not be found through unit test or simulator debug.

How to automatically check API diff maybe a interesting topic for iPhone testing.

For getting better stability, we have to do testing through three aspects:

Unit test and functionality test

Memory management test

IOS version compatibility test
PS: A list of all firmware:

Share
25Nov/110

Memory Management Advice – iphone

I am a little unclear about some of the conventions in memory management. I have tried to follow Slick and Duncan's advice and follow this style:

in .h

Class *_var

@property (nonatomic, retain) Class *var

in .m@synthesize var = _var;When assigning the variable

either (for example with UITextView):

self.var = [[[UITextView alloc] initWithFrame:(such and such frame)] autorelease];

(autorelease to avoid two retains)

or

UITextView *tempTextView = [[UITextView alloc] initWithFrame:(so on and so so)];
self.var = tempTextView;
[tempTextView release];

In dealloc

self.var = nil; (does the release automatically due to synthesize)

So, assuming I am doing this right, the question comes up in what I do when I am working with these variables. Do I use the instance variable or property when working with the variable in non "self.var = " purposes.

for instance:

If var is a UITextView, Do I use:

self.var.userInteractionEnabled = NO;
self.var.text = @"Some Text";

OR

_var.userInteractionEnabled = NO;
_var.text = @"Some Text";

Basically,

When is the property accessed when changing the "sub properties" vs. the instance variable. It seems like both work but I assume that one would have a preferred way above another.

I was under the impression that I should only call the property when directly assigning. e.g.

self.var = something;

Additionally, when adding a subView to a view (assuming a UITextView var), would I say:

[self.view addSubView: self.var];

or

[self.view addSubview:_var];

btw, I've color coded Instance Variables as Slick suggested in red but I am confused as it seems like everything shows up as an instance variable (including self.var) in red. The only time something shows up not red is like:

[something setSomething:self.var];

Where "var" is not red.

Otherwise:

self.var =

or

_var =

var is red.

I feel like this is a huge fundamental thing I am missing and although I have created a great number of successful apps, I keep having minor bugs haunt me that are associated with memory problems. All the tutorials you follow assign instance variables and properties with the same exact name so it isn't clear what is going on and why it works.

Thanks!
James

Share
21Nov/110

What is MailCore?

MailCore is a Cocoa framework designed to ease the pain of dealing with e-mail protocols by adding a nice Objective-C/Cocoa interface to the C library Libetpan!. MailCore makes the process of sending e-mail easy by hiding the nasty details like MIME composition from you. Instead, there is a nice interface for composing messages and then there is a single method required to send the message. Checking e-mail on an IMAP server is a more complex beast, but MailCore makes the job much simpler but presenting everything as a set of abstract objects like Messages, Folders and Accounts. Note, however, that MailCore is not multithreaded so any calls made will potentially block and not every IMAP detail is abstracted away. Also, MailCore stores everything in memory so if you want to save state to disk it has to be done by hand.

 

Sending E-mail

Sending e-mail with MailCore is very easy, it takes care of all the details like MIME encoding, and the SMTP protocol. First, start by creating a CTCoreMessage instance. Then set the subject, body, from, and atleast one to, bcc, or cc recipient. One detail to note is that the to, cc, bcc attributes take an NSSet of CTCoreAddress recipients.

CTCoreMessage *testMsg = [[CTCoreMessage alloc] init];
[testMsg setTo:[NSSet setWithObject:[CTCoreAddress addressWithName:@"Monkey" email:@"monkey@monkey.com"]]];
[testMsg setFrom:[NSSet setWithObject:[CTCoreAddress addressWithName:@"Someone" email:@"test@someone.com"]]];
[testMsg setBody:@"This is a test message!"];
[testMsg setSubject:@"This is a subject"];

Once the message attributes have been set, all that is left is sending the message usingCTSMTPConnection:

[CTSMTPConnection sendMessage:testMsg server:@"mail.test.com" username:@"test" password:@"test" port:25 useTLS:YES shouldAuth:YES];
[testMsg release];

That's all

 

Working with IMAP

Working with IMAP through MailCore is quite easy. First you need to instantiate aCTCoreAccount object and establish a connection like so:

CTCoreAccount *account = [[CTCoreAccount alloc] init];
[account connectToServer:@"mail.theronge.com" port:143 connectionType:CONNECTION_TYPE_PLAIN authType:IMAP_AUTH_TYPE_PLAIN login:@"test" password:@"none"];

If by any chance it fails to make a connection an exception will be thrown. Now that we have a connection to the server we can go ahead and get a list of folders. Note: I use the term folder in place of mailbox; the IMAP spec uses the term mailbox but I get that confused with account.

NSSet *subFolders = [account subscribedFolders];

If we take a look at the resulting NSSet, we see that what is returned is a set of NSStrings with folder path's.

<NSCFSet: 0x309d60> (INBOX.Test.Test22, INBOX, INBOX.TheArchive, INBOX.Test, INBOX.Trash)

We can use one of those strings to create a CTCoreFolder object or we can just pass in a path, for example this sets up a connection to the INBOX on the server.

CTCoreFolder *inbox = [account folderWithPath:@"INBOX"];

Now that we have a connection to a folder we can start to do more interesting things, like we can get a set of the messages in the particular folder, or we can delete the folder, or remove the folder from the subscribed list, check the CTCoreFolder for more information. For this particular example I am going to get a list of the messages in the INBOX (0 as the end index indicates that the entire inbox should be loaded).

NSSet *messageList = [inbox messageListFromIndex:1 toIndex:0];

Like the with folders, what is returned is a set of NSString's containing unique message identifiers (UID).

<NSCFSet: 0x309d60> (1142229815-5, 1142229815-6, 1142229815-7, 1142229815-8, 1142229815-10, 1142229815-1, 1142229815-9, 1142229815-2, 1142229815-11, 1142229815-3, 1142229815-4)

You might be wondering about the parameter to messageListFromIndex: now, it's exists because of a limitation of IMAP. IMAP was designed to be a protocol where you would always be connected to the server, it wasn't until later that people got the idea using IMAP as an offline protocol. Therefore, IMAP generally returns the entire list of message UID's, but this can be very time consuming for very large folders, and by a large folder I'm talking over 5000 messages. To download only new messages and not every message each time, you can save the last message UID you received. Since you have the last message UID you know the next UID has to be one after it. For example, if you receive the UID 1142229815-4 then you know the next UID has to be 1142229815-5. So if you pass 1142229815-4 into messageListFromIndex: it will only retrieve message with a higher UID.

While UID's are not supposed to change, a folder can change the message UID's on rare occasions. It's important to make sure that the cached UID"s are still valid by using the isUIDValid method. If a bad UID was used there is potential for data loss, since the former UID might not reference the message you intend on deleting. If you save a UID, you should make sure that the server is still using the same UID, otherwise start over by passing nil into messageListFromIndex.

Now back to working with messages, to retrieve with a particular message you need to use the method messageWithUID inside of CTCoreFolder. The resulting object will be of typeCTCoreMessage, from there you can retrieve the subject, body and other things by using the message object.

Share
21Nov/110

Capture IOS Screen code

1.
UIGraphicsBeginImageContextWithOptions(pageView.page.bounds.size, YES, zoomScale);
        [pageView.page.layer renderInContext:UIGraphicsGetCurrentContext()];
        UIImage *uiImage = UIGraphicsGetImageFromCurrentImageContext();
        UIGraphicsEndImageContext();
2.
- (UIImage *) glToUIImage {
    
    DWScrollView *pageView = [self getActivePageView];
       pageView.page.backgroundColor = [UIColor clearColor];
  //  self.backgroundColor=[UIColor clearColor];
    NSInteger myDataLength = 320 * 308 * 4;
    
    // allocate array and read pixels into it.
    GLubyte *buffer = (GLubyte *) malloc(myDataLength);
    glReadPixels(0, 0, 320, 308, GL_RGBA, GL_UNSIGNED_BYTE, buffer);
    
    // gl renders "upside down" so swap top to bottom into new array.
    // there's gotta be a better way, but this works.
    GLubyte *buffer2 = (GLubyte *) malloc(myDataLength);
    
    for(int y = 0; y <308; y++)
    {
        for(int x = 0; x <320 * 4; x++)
        {
            if(buffer[y* 4 * 320 + x]==0)
                buffer2[(307 - y) * 320 * 4 + x]=1;
            else
                buffer2[(307 - y) * 320 * 4 + x] = buffer[y* 4 * 320 + x];
        }
    }
    
    // make data provider with data.
    CGDataProviderRef provider = CGDataProviderCreateWithData(NULL, buffer2, myDataLength, NULL);
    
    // prep the ingredients
    int bitsPerComponent = 8;
    int bitsPerPixel = 32;
    int bytesPerRow = 4 * 320;
    CGColorSpaceRef colorSpaceRef = CGColorSpaceCreateDeviceRGB();
    CGBitmapInfo bitmapInfo = kCGBitmapByteOrderDefault;
    CGColorRenderingIntent renderingIntent = kCGRenderingIntentDefault;
    
    // make the cgimage
    CGImageRef imageRef = CGImageCreate(320, 308, bitsPerComponent, bitsPerPixel, bytesPerRow, colorSpaceRef, bitmapInfo, provider, NULL, NO, renderingIntent);
    
    // then make the uiimage from that
    UIImage *myImage = [UIImage imageWithCGImage:imageRef];
    UIImageWriteToSavedPhotosAlbum(myImage, nil, nil, nil);
    return myImage;
}

3.
// get screen
- (void)grabScreen {
    unsigned char buffer[320*480*4];
    glReadPixels(0,0,320,480,GL_RGBA,GL_UNSIGNED_BYTE,&buffer);
    
    CGDataProviderRef ref = CGDataProviderCreateWithData(NULL, &buffer, 320*480*4, NULL);
    CGImageRef iref = CGImageCreate(320,480,8,32,320*4,CGColorSpaceCreateDeviceRGB(),kCGBitmapByteOrderDefault,ref,NULL,true,kCGRenderingIntentDefault);
    CGFloat width = CGImageGetWidth(iref);
    CGFloat height = CGImageGetHeight(iref);
    size_t length = width*height*4;
    uint32_t *pixels = (uint32_t *)malloc(length);
    CGContextRef context = CGBitmapContextCreate(pixels, width, height, 8, 320*4, CGImageGetColorSpace(iref), kCGImageAlphaLast | kCGBitmapByteOrder32Big);
    CGContextTranslateCTM(context, 0.0, height);
    CGContextScaleCTM(context, 1.0, -1.0);
    CGContextDrawImage(context, CGRectMake(0.0, 0.0, width, height), iref);
    CGImageRef outputRef = CGBitmapContextCreateImage(context);
    UIImage *outputImage = [UIImage imageWithCGImage:outputRef];
    
    UIImageWriteToSavedPhotosAlbum(outputImage, nil, nil, nil); 
    
    CGContextRelease(context);
    CGImageRelease(iref);
    CGDataProviderRelease(ref);
} 
4.
CGImageRef UIGetScreenImage();
void SaveScreenImage(NSString *path)
{
    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
    CGImageRef cgImage = UIGetScreenImage();
        void *imageBytes = NULL;
        if (cgImage == NULL) {
                CGColorSpaceRef colorspace = CGColorSpaceCreateDeviceRGB();
                imageBytes = malloc(320 * 480 * 4);
                CGContextRef context = CGBitmapContextCreate(imageBytes, 320, 480, 8, 320 * 4, colorspace, kCGImageAlphaNoneSkipFirst | kCGBitmapByteOrder32Big);
                CGColorSpaceRelease(colorspace);
                for (UIWindow *window in [[UIApplication sharedApplication] windows]) {
                        CGRect bounds = [window bounds];
                        CALayer *layer = [window layer];
                        CGContextSaveGState(context);
                        if ([layer contentsAreFlipped]) {
                                CGContextTranslateCTM(context, 0.0f, bounds.size.height);
                                CGContextScaleCTM(context, 1.0f, -1.0f);
                        }
                        [layer renderInContext:(CGContextRef)context];
                        CGContextRestoreGState(context);
                }
                cgImage = CGBitmapContextCreateImage(context);
                CGContextRelease(context);
        }
    NSData *pngData = UIImagePNGRepresentation([UIImage imageWithCGImage:cgImage]);
    CGImageRelease(cgImage);
        if (imageBytes)
                free(imageBytes);
    [pngData writeToFile:path atomically:YES];
    [pool release];
}

5.
  + (UIImage *)imageWithScreenContents
{
     CGImageRef cgScreen = UIGetScreenImage();
     if (cgScreen) {
         UIImage *result = [UIImage imageWithCGImage:cgScreen];
         CGImageRelease(cgScreen);
         return result;
     }
     return nil;
}
Share
8Oct/110

math.h

math.h里的一些数学计算的公式

1、 三角函数

  double sin (double);正弦
  double cos (double);余弦
  double tan (double);正切
  2 、反三角函数
  double asin (double); 结果介于[-PI/2, PI/2]
  double acos (double); 结果介于[0, PI]
  double atan (double); 反正切(主值), 结果介于[-PI/2, PI/2]
  double atan2 (double, double); 反正切(整圆值), 结果介于[-PI, PI]
  3 、双曲三角函数
  double sinh (double);
  double cosh (double);
  double tanh (double);
  4 、指数与对数
  double exp (double);求取自然数e的幂
  double sqrt (double);开平方
  double log (double); 以e为底的对数
  double log10 (double);以10为底的对数
  double pow(double x, double y);计算以x为底数的y次幂
  float powf(float x, float y); 功能与pow一致,只是输入与输出皆为浮点数
  5 、取整
  double ceil (double); 取上整
  double floor (double); 取下整
  6 、绝对值
  double fabs (double);求绝对值
  double cabs(struct complex znum) ;求复数的绝对值
  7 、标准化浮点数
  double frexp (double f, int *p); 标准化浮点数, f = x * 2^p, 已知f求x, p ( x介于[0.5, 1] )
  double ldexp (double x, int p); 与frexp相反, 已知x, p求f
  8 、取整与取余
  double modf (double, double*); 将参数的整数部分通过指针回传, 返回小数部分
  double fmod (double, double); 返回两参数相除的余数
  9 、其他
  double hypot(double x, double y);已知直角三角形两个直角边长度,求斜边长度
  double ldexp(double x, int exponent);计算x*(2的exponent次幂)
  double poly(double x, int degree, double coeffs [] );计算多项式
  nt matherr(struct exception *e);数学错误计算处理程序

Share
6Oct/110

Amazing function about storyboard in Xcode 4.2

In Xcode 4.2, the Interface Builder user interface for iOS applications is based on the storyboarding of view controllers. Storyboarding enables you to use Interface Builder to specify not only all the screens in your application, but the transitions between them and the controls used to trigger the transitions. Thus you can lay out every possible path through your application graphically, greatly reducing the amount of code you need to write for a complex multiscreen application.

To storyboard your application, you link each object that’s in a view controller and that can cause a change in the display, to another view controller that configures and implements the new scene. You link the various view controllers in Interface Builder by Control-dragging between controls and view controllers. You can drag from any control that has an output to the header of any other view controller. You can add controls and views to each view controller’s view just as you would add objects to a window or a view in the nib file of an Xcode 3 or Xcode 4.0 application.

Share
24Sep/110

Objective-C 声明中加减号区别

减号表示一个函数、或者方法、或者消息的开始,或者可以说是实例方法。

-(void) action:(bool) enable
{
    //do something
}
在Objective-C里面没有public和private的概念,你可以认为全是public。
而用加号的意思就是其他函数可以直接调用这个类中的这个函数,而不用创建这个类的实例及类方法。
Share
5Sep/110

zbar扫描条形码/二维码

1.新建一个工程A:view-base   
2.拖动zbar框架到工程目录下  
3.然后把zbar/iphone目录下的工程.xproj文件拖到A  
4.在工程的Link Binary添加框架如下:  
libzbar.a  
QuartzCore.framework  
libiconv.dylib  
5.添加#import "ZBarReaderController.h"  
-(IBAction) startScan  
{  
    ZBarReaderController *reader = [[[ZBarReaderController alloc] init] autorelease];  
    reader.delegate = self;  
    reader.cameraMode = ZBarReaderControllerCameraModeSampling;  
      
    ZBarImageScanner *scanner = reader.scanner;  
    [scanner setSymbology: ZBAR_I25 config: ZBAR_CFG_ENABLE to:0];  
      
    [self presentModalViewController: reader animated:YES];  
      
}  
- (void) imagePickerController: (UIImagePickerController*) picker didFinishPickingMediaWithInfo: (NSDictionary*) info  
{  
    UIImage *image = [info objectForKey: UIImagePickerControllerOriginalImage];  
      
    id<NSFastEnumeration> results = [info objectForKey: ZBarReaderControllerResults];  
    ZBarSymbol *symbol = nil;  
      
    for(symbol in results)  
    {  
        break;  
    }  
      
    if(!symbol || !image)  
    {  
        return;  
    }  
      
    NSLog(@"symbol.data = %@", symbol.data);  
      
//最关键的移行代码  
    self.resultLabel.text = symbol.data;  
      
    [picker dismissModalViewControllerAnimated: YES];  
}  
6.给.h添加<UINavigationControllerDelegate,UIImagePickerControllerDelegate>
Share
28Aug/110

UITableVIew实现类似于电话本的首字母索引

实际上UITableView默认就支持象电话本那样的按首字母索引。 实现sectionIndexTitlesForTableView 和 sectionForSectionIndexTitle 这两个接口即可。 细节请参考UITableViewDataSource帮助文档。

- (NSArray *)sectionIndexTitlesForTableView:(UITableView *)tableView
{

NSMutableArray *toBeReturned = [[NSMutableArray alloc]init];

for(char c = ‘A’;c<=‘Z’;c++)

[toBeReturned addObject:[NSString stringWithFormat:@"%c",c]];

return toBeReturned;

}

- (NSInteger)tableView:(UITableView *)tableView sectionForSectionIndexTitle:(NSString *)title atIndex:(NSInteger)index
{

NSInteger count = 0;

for(NSString *character in arrayOfCharacters)

{

if([character isEqualToString:title])

{

return count;

}

count ++;

}

return 0;

}

- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section
{

if([arrayOfCharacters count]==0)

{

return @”";

}

return [arrayOfCharacters objectAtIndex:section];

}
Share