Recent Posts

Showing posts with label IOS. Show all posts
Showing posts with label IOS. Show all posts

IOS: Difference between atomic and non-atomic attributes

What do atomic and nonatomic mean in property declarations?

@property(nonatomic, retain) UITextField *userName;
@property(atomic, retain) UITextField *userName;
@property(retain) UITextField *userName;

Let's talk about the operational difference:

What do atomic and nonatomic mean in property declarations? atomic was added as a keyword in recent versions of llvm/clang).

Assuming that you are @synthesizing the method implementations, atomic vs. non-atomic changes the generated code. If you are writing your own setter/getters, atomic/nonatomic/retain/assign/copy are merely advisory. (Note: @synthesize is now the default behavior in recent versions of LLVM. There is also no need to declare instance variables; they will be synthesized automatically, too, and will have an _ prepended to their name to prevent accidental direct access).

With "atomic", the synthesized setter/getter will ensure that a whole value is always returned from the getter or set by the setter, regardless of setter activity on any other thread. That is, if thread A is in the middle of the getter while thread B calls the setter, an actual viable value -- an autoreleased object, most likely -- will be returned to the caller in A.

In nonatomic, no such guarantees are made. Thus, nonatomic is considerably faster than "atomic".

What "atomic" does not do is make any guarantees about thread safety. If thread A is calling the getter simultaneously with thread B and C calling the setter with different values, thread A may get any one of the three values returned -- the one prior to any setters being called or either of the values passed into the setters in B and C. Likewise, the object may end up with the value from B or C, no way to tell.

Ensuring data integrity -- one of the primary challenges of multi-threaded programming -- is achieved by other means.

iOS How to send SMS with iPhone

Restrictions


If you could send an SMS within a program on the iPhone, you'll be able to write games that spam people in the background. I'm sure you really want to have spams from your friends, "Try out this new game! It roxxers my boxxers, and yours will be too! roxxersboxxers.com!!!! If you sign up now you'll get 3,200 RB points!!"

Apple has restrictions for automated (or even partially automated) SMS and dialing operations. (Imagine if the game instead dialed 911 at a particular time of day)

Your best bet is to setup an intermediate server on the internet that uses an online SMS sending service, and send the SMSs via that route if you need complete automation. (ie, your program on the iPhone sends a UDP packet to your server, which sends the real SMS)

iOS 4 Update


iOS 4, however, now provides a viewcontroller you can import into your application. You prepopulate the SMS fields, then the user can initiate the SMS send within the controller. Unlike using the "sms:..." url format, this allows your application to stay open, and allows you to populate both the to and the body fields. You can even specify multiple recipients.

This prevents applications from sending automated SMS without the user explicitly aware of it. You still cannot send fully automated SMS from the iPhone itself, it requires some user interaction. But this at least allows you to populate everything, and avoids closing the application.

The MFMessageComposeViewController class is well documented, and tutorials show how easy it is to implement.

iOS 5 Update


iOS 5 includes messaging for iPod touch and iPad devices, so while I've not yet tested this myself, it may be that all iOS devices will be able to send SMS via MFMessageComposeViewController. If this is the case, then Apple is running an SMS server that sends messages on behalf of devices that don't have a cellular modem.

iOS 6 Update


No changes to this class.

iOS 7 Update


You can now check to see if the message medium you are using will accept a subject or attachments, and what kind of attachments it will accept. You can edit the subject and add attachments to the message, where the medium allows it.

Limitations to this class


Keep in mind that this won't work on phones without iOS 4, and it won't work on the iPod touch or the iPad, except, perhaps, under iOS 5. You must either detect the device and iOS limitations prior to using this controller, or risk restricting your app to recently upgraded 3G, 3GS, and 4 iPhones.

However, an intermediate server that sends SMS will allow any and all of these iOS devices to send SMS as long as they have internet access, so it may still be a better solution for many applications. Alternately, use both, and only fall back to an online SMS service when the device doesn't support it.

How to embed custom font in iOS iphone app


iOS 3.2 and later support this. Straight from the What's New in iPhone OS 3.2 doc:

Custom iOs Font Support
Applications that want to use custom fonts can now include those fonts in their application bundle and register those fonts with the system by including the UIAppFonts key in their Info.plist file.
The value of this key is an array of strings identifying the font files in the application’s bundle. When the system sees the key, it loads the specified fonts and makes them available to the application.

Once the fonts have been set in the Info.plist, you can use your custom fonts as any other font in IB or programatically.

There is an ongoing thread on Apple Developer Forums:
https://devforums.apple.com/thread/37824 (login required) and here's an excellent and simple 3 steps tutorial on how to achieve this (broken link removed)

  1. Add your custom font files into your project using Xcode as a resource
  2. Add a key to your Info.plist file called UIAppFonts.
  3. Make this key an array
  4. For each font you have, enter the full name of your font file (including the extension) as items to the UIAppFonts array
  5. Save Info.plist
  6. Now in your application you can simply call [UIFont fontWithName:@"CustomFontName" size:12]to get the custom font to use with your UILabels and UITextViews, etc…

Also: Make sure the fonts are in your Copy Bundle Resources.

Making filetypes handling association with ios iphone app


File type handling is new with iPhone OS 3.2, and is different than the already-existing custom URL schemes. You can register your application to handle particular document types, and any application that uses a document controller can hand off processing of these documents to your own application.

For example, Molecules handles the .pdb and .pdb.gz file types, if received via email or in another supported application.

To register support, you will need to have something like the following in your Info.plist:

<key>CFBundleDocumentTypes</key>
<array>
    <dict>
        <key>CFBundleTypeIconFiles</key>
        <array>
            <string>Document-molecules-320.png</string>
            <string>Document-molecules-64.png</string>
        </array>
        <key>CFBundleTypeName</key>
        <string>Molecules Structure File</string>
        <key>CFBundleTypeRole</key>
        <string>Viewer</string>
        <key>LSHandlerRank</key>
        <string>Owner</string>
        <key>LSItemContentTypes</key>
        <array>
            <string>com.sunsetlakesoftware.molecules.pdb</string>
            <string>org.gnu.gnu-zip-archive</string>
        </array>
    </dict>
</array>

Two images are provided that will be used as icons for the supported types in Mail and other applications capable of showing documents. The LSItemContentTypes key lets you provide an array of Uniform Type Identifiers (UTIs) that your application can open. For a list of system-defined UTIs, see Apple's Uniform Type Identifiers Reference. Even more detail on UTIs can be found in Apple'sUniform Type Identifiers Overview. Those guides reside in the Mac developer center, because this capability has been ported across from the Mac.

One of the UTIs used in the above example was system-defined, but the other was an application-specific UTI. The application-specific UTI will need to be exported so that other applications on the system can be made aware of it. To do this, you would add a section to your Info.plist like the following:

<key>UTExportedTypeDeclarations</key>
<array>
    <dict>
        <key>UTTypeConformsTo</key>
        <array>
            <string>public.plain-text</string>
            <string>public.text</string>
        </array>
        <key>UTTypeDescription</key>
        <string>Molecules Structure File</string>
        <key>UTTypeIdentifier</key>
        <string>com.sunsetlakesoftware.molecules.pdb</string>
        <key>UTTypeTagSpecification</key>
        <dict>
            <key>public.filename-extension</key>
            <string>pdb</string>
            <key>public.mime-type</key>
            <string>chemical/x-pdb</string>
        </dict>
    </dict>
</array>
This particular example exports the com.sunsetlakesoftware.molecules.pdb UTI with the .pdb file extension, corresponding to the MIME type chemical/x-pdb.



With this in place, your application will be able to handle documents attached to emails or from other applications on the system. In Mail, you can tap-and-hold to bring up a list of applications that can open a particular attachment.

When the attachment is opened, your application will be started and you will need to handle the processing of this file in your -application:didFinishLaunchingWithOptions: application delegate method. It appears that files loaded in this manner from Mail are copied into your application's Documents directory under a subdirectory corresponding to what email box they arrived in. You can get the URL for this file within the application delegate method using code like the following:
NSURL *url = (NSURL *)[launchOptions valueForKey:UIApplicationLaunchOptionsURLKey];
Note that this is the same approach we used for handling custom URL schemes. You can separate the file URLs from others by using code like the following:

if ([url isFileURL])
{
    // Handle file being passed in
}
else
{
    // Handle custom URL scheme
}

Objective-C: How to make UIText move up when keyboard is visible

With the iPhone SDK:

I have a UIView with UITextFields that brings up a keyboard. I need it to be able to:

Allow scrolling of the contents of the UIScrollView to see the other text fields once the keyboard is brought up

Automatically "jump" (by scrolling up) or shortening

I know that I need a UIScrollView. I've tried changing the class of my UIView to a UIScrollView but I'm still unable to scroll the textboxes up or down.

Do I need both a UIView and a UIScrollView? Does one go inside the other? [EDIT: I now know that you want a UIView inside of a UIScrollView, and the trick is to programatically set the content size of the UIScrollView to the frame size of the UIView.]

Then what needs to be implemented in order to automatically scroll to the active text field?

Ideally as much of the setup of the components as possible will be done in Interface Builder. I'd like to only write code for what needs it.

Note: the UIView (or UIScrollView) that I'm working with is brought up by a tabbar (UITabBar), which needs to function as normal.

Edit: I am adding the scroll bar just for when the keyboard comes up. Even though it's not needed, I feel like it provides a better interface because then the user can scroll and change textboxes, for example.

I've got it working where I change the frame size of the UIScrollView when the keyboard goes up and down. I'm simply using:

-(void)textFieldDidBeginEditing:(UITextField *)textField { 
    //Keyboard becomes visible
    scrollView.frame = CGRectMake(scrollView.frame.origin.x, 
                     scrollView.frame.origin.y, 
scrollView.frame.size.width,
scrollView.frame.size.height - 215 + 50);   //resize
}

-(void)textFieldDidEndEditing:(UITextField *)textField {
   //keyboard will hide
    scrollView.frame = CGRectMake(scrollView.frame.origin.x, 
       scrollView.frame.origin.y, 
     scrollView.frame.size.width,
      scrollView.frame.size.height + 215 - 50); //resize
}
However this doesn't automatically "move up" or center the lower text fields in the visible area, which is what I would really like.

Solution


  1. You will need a scroll view if the contents you have now does not fit in the iPhone screen. (If you are adding the scroll view just to make the textfield scroll up when keyboard comes up, then it's not needed.)
  2. For showing the textfields without being hidden by the keyboard, the standard way is to move up/down the view having textfields whenever the keyboard is shown.

#define kOFFSET_FOR_KEYBOARD 80.0

-(void)keyboardWillShow {
    // Animate the current view out of the way
    if (self.view.frame.origin.y >= 0)
    {
        [self setViewMovedUp:YES];
    }
    else if (self.view.frame.origin.y < 0)
    {
        [self setViewMovedUp:NO];
    }
}

-(void)keyboardWillHide {
    if (self.view.frame.origin.y >= 0)
    {
        [self setViewMovedUp:YES];
    }
    else if (self.view.frame.origin.y < 0)
    {
        [self setViewMovedUp:NO];
    }
}

-(void)textFieldDidBeginEditing:(UITextField *)sender
{
    if ([sender isEqual:mailTf])
    {
        //move the main view, so that the keyboard does not hide it.
        if  (self.view.frame.origin.y >= 0)
        {
            [self setViewMovedUp:YES];
        }
    }
}

//method to move the view up/down whenever the keyboard is shown/dismissed
-(void)setViewMovedUp:(BOOL)movedUp
{
    [UIView beginAnimations:nil context:NULL];
    [UIView setAnimationDuration:0.3]; // if you want to slide up the view

    CGRect rect = self.view.frame;
    if (movedUp)
    {
        // 1. move the view's origin up so that the text field that will be hidden come above the keyboard 
        // 2. increase the size of the view so that the area behind the keyboard is covered up.
        rect.origin.y -= kOFFSET_FOR_KEYBOARD;
        rect.size.height += kOFFSET_FOR_KEYBOARD;
    }
    else
    {
        // revert back to the normal state.
        rect.origin.y += kOFFSET_FOR_KEYBOARD;
        rect.size.height -= kOFFSET_FOR_KEYBOARD;
    }
    self.view.frame = rect;

    [UIView commitAnimations];
}


- (void)viewWillAppear:(BOOL)animated
{
    [super viewWillAppear:animated];
    // register for keyboard notifications
    [[NSNotificationCenter defaultCenter] addObserver:self
                                         selector:@selector(keyboardWillShow)
                                             name:UIKeyboardWillShowNotification
                                           object:nil];

    [[NSNotificationCenter defaultCenter] addObserver:self
                                         selector:@selector(keyboardWillHide)
                                             name:UIKeyboardWillHideNotification
                                           object:nil];
}

- (void)viewWillDisappear:(BOOL)animated
{
    [super viewWillDisappear:animated];
    // unregister for keyboard notifications while not visible.
    [[NSNotificationCenter defaultCenter] removeObserver:self
                                             name:UIKeyboardWillShowNotification
                                           object:nil];

    [[NSNotificationCenter defaultCenter] removeObserver:self
                                             name:UIKeyboardWillHideNotification
                                           object:nil];
}