Don’t take me wrong, I strongly believe that anyone writing a compiler deserves my respect. Is not a task for the feeblest. Yet, my relationship with GCC was not always a good one. How not to hate the cryptic messages spilled by the parser from time to time? Well, let’s praise Stallman irreducibility, Apple condemn GCC and replace it with LLVM1. Regardless of the actual reasons, the change brings a better compiler to the table. One that can parse and understand code even better than my cocker spaniel, which is much more of what GCC gives us. And because the compiler is able to understand the code, well, to understand it a little better than GCC, then Apple decided that LLVM can take care of the memory-management tasks. In Apple own words:
“The compiler has a complete understanding of your objects, and releases each object the instant it is no longer used, so apps run as fast as ever, with predictable, smooth performance.”
And yes, the best part is that this is not GC. It is just let the compiler insert the release when needed. ARC works on top of the familiar reference counting.
Basically, ARC requires Apple LLVM compiler 3.0 (or later, as the time of writing, the default compiler is Apple LLVM 3.1), and the compiler flag -fobjc-arc set. Both of these requirements are set by default by Xcode 4.2 and later.
As you must remember, the only secret of reference counting is to keep an eye on ownership.
+alloc, +allocWithZone: or +new. -copy, -mutableCopy or -retain)-release. To ease the task, ARC introduced a few qualifiers to instruct the compiler how the objects ownership would be handle.
__strongDefault qualifier.
Semantically,
NSString __strong * someString = [[NSString alloc] initWithString:@"some string"];
Is the same of
NSString * someString = [[NSString alloc] initWithString:@"some string"];
The ownership is relinquish at the end of the present scope. This means that the release message is send automatically when the control flow leaves the scope where the strong variable was obtained.
By the way, any variable qualified with __strong, __weak and __autoreleasing are initialized to nil.
id __strong someStringVar;
id __weak someWeakVar;
id __autoreleasing someAutoreleasingVar;
Is semantically the same of
id __strong someStringVar = nil;
id __weak someWeakVar = nil;
id __autoreleasing someAutoreleasingVar = nil;
This seems small, but add o the security of the code (we are no longer dealing with undefined states).
The strong reference will generate ownership even for objects that are not created.
NSSet __strong *set = [NSSet set];
Here set is owned for the whole life of the scope.
Members variables can be qualified as __strong as well. In fact, because the compiler can insert automatically the members variable, all we need to do is to define the property.
@property (strong) CLLocation *latestKnownLocation;
And obviously, synthesize it.
@synthesize latestKnownLocation;
As long as the class instance is alive, there is going to be a strong reference to latestKnownLocation.
__weakSo, by default (we don’t even have to type __strong), the compiler will take care of the memory management most of the time. But, what happens, for instance, when two objects refer each other. That’s exactly the kind of relationship that exists between an object and its delegate. We have a tableViewDelegate which is going to serve as a delegate for a UITableView. If the table view delegate property is qualified as strong, and the same happens with the tableView property of the delegate, then, when the delegate reference counter is never going to be zero, because there is always a reference from the table view, and the table view reference counter is also impossible to reduce to zero, because it is referenced from the delegate. This is circular reference.
To avoid these kind of situations, the rule of thumb is not to claim ownership of delegates and other objects that refers to each other (like IBOutlets for instance). Let’s revisit our previous example, because the table view does not claim ownership of the delegate, the delegate can be deallocated with no problem, and because there is no delegate referencing the table view, the the table view can also be deallocated. Even better, when the object that a variable qualified as __weak is discarded, the variable value is set to nil.
The __weak qualifier is only available for iOS 5 (or later) and OSX Lion (or later). For older OSs, __unsafe_unretained qualifier must be used instead.
__unsafe_unretainedThis qualifier exclude the variable from ARC mechanisms. Because no check is perform, and references are not niled, if you set a variable as __unsafe_unretained you hold the responsibility of checking if the object is still there when needed.
__autoreleasingBecause ARC handles the little nuances of memory management, it is very rare to use auto release mechanism explicitly, thou the environment provides the needed tools.
The thing is that when an object is referenced but not created, i.e., none of the methods in the family +alloc, or -copy is called, the object is automatically registered to the auto release pool. When an object is returned from a method, the compiler checks the name of the method. Naming convention is important here because the compiler used the method name to know how to handle the returned object ownership.
Most programmers are going to use __autoreleasing mainly to handle errors via indirect pointers. In ARC indirect pointers are by default qualified as __autoreleasing. The method that handle the error will take an __autoreleasing parameter:
- (BOOL)performWithError:(__autoreleasing NSError **)error {
// try something prone to failure
if ( failure ) {
*error = [[NSError alloc] initWithDomain:@"Some Error Domain"
code:101
userInfo:nil];
return NO;
}
return YES
}
And the caller portion would be something like
NSError __autoreleasing *error = nil;
if ( ![self performWithError:&error] ) {
// Deal with the error
NSLog(@"error: %@", error);
}
There are plenty of code that is not ARC ready (yet). That’s not a big deal. Once again, ARC is not GC, and it works on a a copyable unit basis. To add non-ARC units to your app, Select the Target you are working with, then the Build Phases tab, and look for legacy units in Compiled Sources. Add -fno-objc-arc to each one. Recompile. You are done.
You would like to think that they choose compiler over the other because one is better, but that’s not the whole history. The tipping point was the more forgiven nature of LLVM License ↩
Los momentos de mi vida en los que yo he crecido, tienen que ver con los fracasos; los momentos de mi vida en los que yo he empeorado, tienen que ver con el éxito. El éxito es deformante. Relaja, engaña, nos vuelve peores, nos ayuda a enamorarnos excesivamente de nosotros mismos. El fracaso es todo lo contrario: es formativo, nos vuelve más sólidos, nos acerca a las convicciones, nos vuelve coherentes. Si bien competimos para ganar, y yo trabajo siempre para ganar cuando compito, si no distinguiera qué es lo realmente formativo y qué es secundario, me estaría equivocando mucho.
Happy 94th Birthday, Richard Feynman!
Bonus: Here is a video of Dr. Feynman, playing bongos, and really wanting some orange juice.
Time after time good ideas are wasted in poorly designed apps. The problem, usually, is the lack of understanding of the target of the app, and how the app is going to be used in the real world. The world of the app has to be chartered before the first line of code. We have to figure out what we are going to deliver to our customers in advance. We have to be intentional. No real world architect dare to start building without a blueprint, and best architects spend lots of times with their customers in order to know what they want, even before the blueprint.
Most of the time, every single app starts with a ‘great idea’, and a big list of ‘nice to have’ features. The problem is that compiling a list of features is easy, and is also easy to implement them. Not trivial, but easy. The end result? Apps that are no longer solutions but containers where we shoehorn features. The true genius, we already know that, is not to add, but to remove what is not really needed. Ask Leonard Cohen if you don’t believe me.
That big list is not what we need. Our goal is to define a solution. The very best apps on the App Store are those that solve a problem for a customer. The problem doesn’t have to be huge, but the solution has to be useful.
One of the best way to make sure we are accurately defining a solution instead of just creating a container is to distill the most important aspects of the app in one sentence. We first need to define what makes out app different from the rest of gazillion apps in the store. What makes it special for the customer. And yes, it has to be something special, otherwise, why bother? Then we have to think about the best solution for the need, and finally, the audience. The audience definition, the target in marketing parlance, is critical here. It will help us to better understand the problem at hand, and obviously, improve the solution. Feel free to use the next template:
(app differentiator)(proposed solution), for (app audience)
Let’s try to exercise a little this idea. Let’s pretend we realize there is no good enough medical imaging apps in the store. Sure, there are plenty of excellent of excellent imaging apps out there, but they all lack tools to help doctors measure anatomical features. Our proposed solution, then, is to create an app that contains these measurement tools.
So, we already know the audience of the app is going to be composed by doctors. That’s not enough. Remember, the better we know our target, the best solution we can deliver. For instance, the prototypical customer of the app is going to use it in his or her office? When on the go? Or perhaps when performing a surgery? Three different scenarios that ask for three different solutions. And we might be talking about the same person, just changing the context. When in her office, the doctor has plenty of time to focus on details. We can add more items to the toolset, and let the doctor experience drive the flow. The UI might be monochromatic, clean, scalable and productivity oriented. When on the go, the doctor has no time to read the image and he can use the help of some Artificial Intelligence to focus on features that are particularly interesting. The toolset might be limited, but connectivity tools should be add to let the doctor report back to the hospital, if needed. When in the OR, the doctor does not need a lot of tools, and certainly she is not going to email anything. Buttons should be big, easy to tap, and colors should be shocking. Knowing a little bit more about the target pays, a lot.
With that in hand we can think on:
Easy to use Medical Imaging app to review and report for doctors on the go.
or
Comprehensive Medical Imaging app to analyze, edit, organize and share for doctors at the office.
or
*Really easy to use Medical Imaging tool to help visualize key anatomical features for doctors at the OR. *
The product definition statement then is going to be the cornerstone of the whole design process. Now you can start compiling the list of desired features, you have a tool that will help you to decided if the feature at hand worth the list. You can ask yourself if the new feature is critical or not to fulfill the product definition.
The relevance of each feature is really important. The smaller the feature set, the better. That’s not equals a cripple app. It make no sense to deliver with fewer features than the needed to accomplish the goal of the app. If the product definition ask for 50 features, then go for it.
The rule of thumb is to include the most frequently used features by the majority of the users. Because the app is simple, doesn’t mean it won’t be valuable to your customers.
But not features are critical. The ones that are, obviously, should be there since day one, but perhaps there are others that can be added later. A road map is a helpful tool to know what has to be there in each version. Version 1.0 is for the most critical features. If you are not embarrassed by version 1.0 feature set, then you waited too long. You have to build a road map, you have to know that feature x, as important as it is, might not be critical, if that’s the case, feature x is going to be introduced in version 1.1 or 2.0. Software development, specially nowadays, is not a hit or loose. At least not regarding the feature set (quality is a different issue, is hard to convince a user to give another try to a crappy app). We are not burning disk anymore to deploy software. Users are going to be happy if they discover a new version of the tiny app that does one thing, but does it really well, specially if this new version add more features. And the App Store is your friend here, it is going to pop your new version as soon as it is available to all the users. Software distribution is cheap, version 1.1 could be deployed a week later than 1.0. No problem.
Road Maps are key. You have to be able to allocate resources for the whole map. Version 1.0 is just one step, perhaps the most important (if it is crappy, then you have no second try). Please, read the article of Matt Mullenweg I’m linking above. The first version of the iPod was quite limited, but the people behind it was really careful when choosing the critical features that were needed to implement, and the implementation itself. The second generation packed more features, and the people love them.
But why wait till the whole feature set is complete. Because then you can be pretty sure your market is lost. And also because you are going to learn a lot from real users in the real world.
That being said, it is really, really important to remember that nothing is carved in stone. You have to be flexible, and hear what the audience is asking. Real world can be cruel, but if we are not working for our audience, then it doesn’t matter what we are doing. The application definition statement might be perfect, the feature set might be comprehensive, the road map might be smart. But as soon as version 1.0 hit the store a user will point the elephant in the room, and you might need to rethink the whole feature set and road map. That’s the beauty of this industry, is pretty much alive.
And because you need to be flexible, you have to learn the design patterns that will help you. We have talked about patterns in the past, and I promise I will be back to them. The important thing is to try to devise an architecture where the different modules are not tightly coupled, and you can easily change how they interact. For instance the delegate pattern is better than subclassing (or retain the responsibility of a task in a single class).
Perhaps one of the less known, and yet more useful commands in the git interactive add is patch. Let’s say you start working on a file to fix a bug (yes, I know, your code does not have bugs, but let’s pretend for a moment), Once in the file, you found a line that needs some refactoring, and just because you are a really nice person, you add some comment to a method that has nothing to do with the line you’ve refactored, or the bug you fixed. Three different things in the same file. Sounds familiar? Sure you can issue something like:
git commit -a -m "Cleaning Code"
And you are not lying. But, for the sake of being a good citizen, wouldn’t be better to split the whole stuff in three discreet commits, one for the line you’ve refactored, one for the bug you’ve fixed, and one for the comment you’ve added? This is exactly what path can do.
Instead of adding everything in just one stage, let’s enter the interactive session:
$ git add -i
staged unstaged path
1: unchanged +14/-14 algorithms.py
*** Commands ***
1: status 2: update 3: revert 4: add untracked
5: patch 6: diff 7: quit 8: help
What now> p
Type p in the prompt, and git will list all files in the working directory:
staged unstaged path
1: unchanged +16/-15 algorithms.py
Patch update>> 1
Then you just need to select the number of the file (or files, because you can add many files at one if you need) you want to path. In this case 1. Git is going to print out a lot of things once you’ve done selecting files. It might be a little overwhelming, so let’s take a look at it.
First, GIT will tell us what is taken into account, In this case the version a and the version b of the content of the file algorithms.py:
diff --git a/algorithms.py b/algorithms.py
index 5a835ea..f9d0cdb 100644
Then, it says that the content from file a (the HEAD), is identified with - and the content from b is identified with +
--- a/algorithms.py
+++ b/algorithms.py
And then the content of the file itself.
@@ -10,24 +10,25 @@ Copyright (c) 2012 __MyCompanyName__. All rights reserved.
import sys
import os
-from random import randrange
-
+from collections import defaultdict
def main():
- seq = [randrange(10**10) for i in range(100)]
- seq.sort()
- dd = float('inf')
- xx = 0
- yy = 0
- for x in seq:
- for y in seq:
- if x == y:
- continue
- d = abs(x-y)
- if d < dd:
- xx, yy, dd = x, y, d
- print '%d %d' % (xx, yy)
+ pass
+def max_perm(M, A=None):
+ """docstring for max_perm"""
+ if A is None:
+ A = set(range(len(M)))
+ if len(A) == 1:
+ return A
+ B = set(M[i] for i in A)
+ C = A - B
+ if C:
+ A.remove(C.pop())
+ return max_perm(M,A)
+ return A
if __name__ == '__main__':
- main()
+ main()
+
\ No newline at end of file
And finally, git ask what we want to do.
Stage this hunk [y,n,q,a,d,/,s,e,?]?
I know, I know, a bit intimidating the list of letters. And Linus seems to know that because, the default value is no other than ? which is going to print a help message:
y - stage this hunk
n - do not stage this hunk
q - quit; do not stage this hunk nor any of the remaining ones
a - stage this hunk and all later hunks in the file
d - do not stage this hunk nor any of the later hunks in the file
g - select a hunk to go to
/ - search for a hunk matching the given regex
j - leave this hunk undecided, see next undecided hunk
J - leave this hunk undecided, see next hunk
k - leave this hunk undecided, see previous undecided hunk
K - leave this hunk undecided, see previous hunk
s - split the current hunk into smaller hunks
e - manually edit the current hunk
? - print help
The option we are looking for is s.
Stage this hunk [y,n,q,a,d,/,s,e,?]? s
Split into 5 hunks.
@@ -10,6 +10,6 @@
import sys
import os
from random import randrange
-
+from collections import defaultdict
def main():
Stage this hunk [y,n,q,a,d,/,j,J,g,e,?]?
Then we can simply choose the hunks that we want to add for each commit. Once we are done selecting the hunk, we can update the content:
*** Commands ***
1: status 2: update 3: revert 4: add untracked
5: patch 6: diff 7: quit 8: help
What now> u
staged unstaged path
1: +1/-1 +15/-14 algorithms.py
Update>> 1
And commit with an appropriate message:
git commit -m "Importing defaultdict from collections"
If you don’t want to mess with the interactive session (truth be told, I rather not), then thee is also a shortcut to get right into patching mode.
git add -p
Perhaps, one of the most secure flows in the OAuth specs, because the access token is never exposed. The authorization is accomplished using an authorization code that then is traded for the actual access token in a server-to-server exchange. The client has no access to the access token. The flow starts when the resource owner is redirected to the API provider. In iOS we can simply start the process inside a UIWebView asking for the appropriate API endpoint, and passing the needed parameters
| Parameter name | Required | Description |
|---|---|---|
response_type |
Yes | A token describing what kind of response we are looking for. code if we are asking for an authorization code |
client_id |
No | string or number issued by the API provider |
redirect_uri |
No | URI where the resource owner is going to be redirected after authentication and authorization |
scope |
No | A list specifying the resources we are asking to access. Most API providers use space-delimited lists, Facebook use comma separated strings |
state |
No, but recommended | String with a unique value to validate the callback. Usually a hash |
To these parameters list, API providers can add their own values, for instance, in Foursquare you can specify if the device is touch based with display=touch.
Here the authorization call performed with Cocoa:
NSString *urlString = [[NSString alloc] initWithFormat:@"https://foursquare.com/oauth2/authenticate?display=touch&client_id=%@&response_type=code&redirect_uri=%@", kFourSquareOauthKey, kFourSquareRedirectURL];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:urlString]];
[urlString release];
[self.webView loadRequest:request];
[self.webView setDelegate:self];
[self.view addSubview:self.webView];
If the authorization is granted, the resource owner is then redirected to the redirect_uri with the following parameters added by the authorization server.
| Parameter name | Required | Description |
|---|---|---|
code |
Yes | This is the code generated by the server to be traded by the access token. Should not be used more than once. If used more than once, the server must deny the request and should revoke all tokens issued based on that authorization token |
client_id |
Yes when present in the request | The value send by the client. Should be used to validate the callback and prevent CSRF attacks. |
On the other hand, if the authorization is not granted, then the user is also redirected to the redirect_uri but this time with a parameter named error with a code identifying what wen wrong. The API provider can also add an error_description with a human readable string explaining the problem, and an error_uri with the location of a Web resource with more information about the problem.
The allowed codes for the error parameter are:
| Error Code | Description |
|---|---|
invalid_request |
The request is missing some required parameter or is otherwise malformed |
unauthorized_client |
The client is not authorized to use this method to request an authorization |
access_denied |
Either the resource owner or the authorization server have denied the request |
unsupported_response_type |
The request is not supported by the authorization server |
invalid_scope |
The requested scope is invalid, unknown, or malformed |
server_error |
The authorization server was unable to process the request |
temporarily_unavailable |
The* authorization server* is currently unable to handle the request due to a temporary overloading or maintenance of the server |
Once the client gets the authorization code, it can be traded for an access token performing a HTTP POST request composed with:
| Parameter name | Required | Description |
|---|---|---|
grant_type |
Yes | What type of gran access is required? authorization_code for a new authorization access code, refresh_token to renew the token, password when we have the resource owner password to trade for the access token, client_credentials when we have resource owner login credentials |
code |
Yes | The code obtained in step 1 |
redirect_uri |
Yes if the value was included in the authorization request | If redirect_uri was included in the authorization request, should be also included in this call. The UIR must be the same |
refresh_token |
Yes to renew the token | The refresh_token produced by this endpoint the first time it is called |
The client_id and the client_secret also has to be included in this call. They can be send as a HTTP Basic Authorization header (with client_id as the login, and the client_secret as the password). Some API providers allow users to send the two tokens as simple parameters for the request as well.
If the access token request is valid, and authorized, the authorization server issues an access token and sometimes a refresh_token as a JSON formatted payload:
HTTP/1.1 200 OK
Content-Type: application/json;charset=UTF-8
Cache-Control: no-store
Pragma: no-cache
{
"access_token":"2YotnFZFEjr1zCsicMWpAA",
"token_type":"example",
"expires_in":3600,
"refresh_token":"tGzv3JOkF0XG5Qx2TlKWIA",
"example_parameter":"example_value"
}
The access token and, if available, the refresh token should be kept secret. Many providers issue a short-lived access token. If that’s the case, you will find expires_in and refresh_token as parameters in the JSON response. The expires_in parameter indicates the remaining lifetime of the access_token in seconds. When the access token expires, the refresh token can be used to obtain a new one. To refresh the access token we need to perform a HTTP request to the token endpoint, specifying refresh_token for the grant_type parameter, and adding the refresh_token.
The access token is then used in all the API calls, without the need to crypto sign them anymore. Sometimes, we can add the token as a simple parameter in the request, thou, most of the API providers, prefer the token to be dispatched as a HTTP header.
OAuth defines four different grant types to obtain authorization:
client_id and the client_secret. Note included in the core specification, but also very popular, we can add two more flows:
It is there all the time, one of the most important task for engineers is to strike a balance between security and usability. You can build a pedestrian bridge performing a load rating for big trucks, but is going to be expensive, and harder to build. The same is also true in software engineering. There are zillions of reasons to prefer OAuth over other protocols, but some engineers found it hard to implement. They claim that OAuth 1.0 requirement to sign all API calls was challenging (to put it mildly). Because of that, and try to ease the learning curve, and thus increase the OAuth adoption rate, OAuth WRAP (OAuth Web Resource Authorization Profiles) was introduced as a predecessor to OAuth 2.0. Given the greater prevalence of SSL/TLS, OAuth WRAP eliminate the signing requirement introducing bearer tokens. Some people is not thrill about the tradeoff, but then we have a new standard.
###Certificates The major concern about bearer tokens is that users (and here users are developers of packages that consumes from sources guarded with OAuth 2.0) will fail to verify the SSL/TLS certificate chains. This is not a weak spot of the protocol itself, which, in fact, specify the correct use of certificates. The moral of this tale is certificates should be checked, always.
OAuth has a bad reputation. many claims that it is hard to implement, and some are really confused by the flow. And is a shame, because OAuth is a wonderful protocol to ensure how we want to share information. This is the first of a hopefully not so long series of post to explain how to use OAuth.
First, we are going to take a look at the basic terminology.
Wolfram is one of my personal heroes. He is brilliant.
Steven Wolfram: The Personal Analytics of My Life
One day I’m sure everyone will routinely collect all sorts of data about themselves. But because I’ve been interested in data for a very long time, I started doing this long ago. I actually assumed lots of other people were doing it too, but apparently they were not. And so now I have what is probably one of the world’s largest collections of personal data.
Every day—in an effort at “self awareness”—I have automated systems send me a few emails about the day before. But even though I’ve been accumulating data for years—and always meant to analyze it—I’ve never actually gotten around to doing it. But with Mathematica and the automated data analysis capabilities we just released in Wolfram|Alpha Pro, I thought now would be a good time to finally try taking a look—and to use myself as an experimental subject for studying what one might call “personal analytics”.
You’re going to want to click through and read all of this.
The Menu Controller is the main tool to let users edit data on device. It is a singleton that you can use to present the cut, copy, and paste menu. The message is percolated though the responder chain, until it find a suitable controller to perform the command.
Being a singleton, we don’t need to worry about initialization, we just need to instruct the shared instance where it needs to be positioned, and when it needs to be shown. We can also let the shared instance which action are enabled, ie, if don’t need to support cut, then we just let the menu controller that we don’t want it to show the command.
To show the menu, you just need to call:
-setMenuVisible:animated:
To position the menu, the call has to be made to
-setTargetRect:inView:
That obviously receives a CGRect structure as the first parameter, and a UIView instance as the second. The CGRect could be the area of the view that has been selected, or just the bounds of the view. It can also be zero width or height, meaning it can be just a point in the view. The menu will automatically positioned above or below that bounds so it always is on the screen. One important thing to notice is that, the rectangle passed, though it is in a view, is converted to the screen coordinates. That means that if the view scrolls programmatically, the program is responsible to reposition the menu adjusting the rectangle.
UIMenuController *controller = [UIMenuController sharedController];
[controller setTargetRect:CGRectMake(10,10,30,20)]
inView:self.view];
[controller setMenuVisible:YES animated:YES];
Obviously, you can programmatically hides the controller just passing NO as the first parameter in -setMenuVisible:animated:, but the menu automatically hides itself when the user taps in another view, or when an alert comes up. It also hides when the user select one the commands. Just in case we need to know when the menu is about to hide, we can subscribe to the UIMenuControllerWillHideMenuNotification notification.
GCD is a terrific technology introduced by Apple, first in OS X and then in iOS. The very basic core of CGD are dispatch queues. Queues are there to let as work with threads, without having to know, and worry about, anything about threads. Queues can be classified as:
dispatch_get_main_queue function will handle it for you. dispatch_get_global_queue. This function requires two parameters, the priority (DISPATCH_QUEUE_PRIORITY_HIGH, DISPATCH_QUEUE_PRIORITY_DEFAULT, DISPATCH_QUEUE_PRIORITY_LOW, DISPATCH_QUEUE_PRIORITY_BACKGROUND) and a flag reserved for future use. For now, you should always use 0.dispatch_queue_create that takes a const char* as a label, and NULL as the second param (in OS X, beginning with version 10.7, you can use this second parameter to specify what queue class you want to create, NULL or DISPATCH_QUEUE_SERIAL, gets you a serial queue, DISPATCH_QUEUE_CONCURRENT a concurrent one). Queues created this way should be released with the dispatch_release function.self is only accessible for blocks defined where self is also accessible. Since inline objects copy the local variables of their lexical scope, beware the use of self to avoid ownership loops. static (ie, they are living in the stack). You can also mark a variable to be writable inside the code with the directive __blockself is available, properties can be accessed through dot notation. If self is not available, setters and getters should be used instead.Mathematica code:
Animate[
Graphics[
Table[
Circle[{0, i}, t + (16 - n) (1 + Sign[16 - n])/2],
{n, 0, 100, 1}, {i, -5, 5,1}],
PlotRange -> 6],
{t, 0, 1, .01}]
With more than 3000 apps integrated with Twitter, is not really a big surprose to learn that iOS 5 adds APIs to make things even easier.
If all we need to to allow users to push tweets from our apps, then it is really easy. All we need to do is to link the ´Twitter.framework´ and then import Twitter/TWTweetComposeViewController.h where we need it. TWTweetComposeViewController is basically a modal view that supports user interactions to compose a tweet. One important method is the class method canSendTweet that returns either YESor NOdepending on whether the device can send a tweet. The rest is really simply, alloc and init and instance of TWTweetComposeViewControllerset a completion handler, and if appropriate, add some initial content like a URL, some text or images.
Here some code to play around.
There are a few useful warnings that should be set in any Xcode project. Here them, and why you should care:
void, but a return statement is found without a return value.@selector construct makes reference to an undeclared selector. Let’s say you are handling a notification with a method you are referring to the @selector expression. Later on, you change the signature of the method. Unless you set this alarm, the code will be unaware of this change until runtime, when is already too late, and the app crash.Werror In many other platforms, warnings are not that important. That’s not the case with Cocoa. Here a warning should be treated as an error, because most of the times, is just an error waiting to happens.Famous Physicists
By Heidi Sandhorst
Famous Physicists 2010 Trading Card Set for sale. 20 4″ x 6″ glossy cards with rounded corners featuring handmade artwork and information about each physicist on the back as well as an inspirational quote from each physicist. Each set comes in a black box with hand drawn label and gold rubber band to hold it shut. $20 plus s+h (if applicable).
Email me at heidisandhorst@gmail.com if you are interested in purchasing a set.
A few weeks ago, I was asked how to sort an array, and I was prompt to answer “using GCD”. Bilal LoLo (@anabillo) ask again “why not NSSortDescriptor”, and I was “because GCD is faster”. Is it? Well, there is an obvious way to know. Truth be told, I was using sort descriptors before GCD was introduced to the phone. And when it was introduced, I automatically assumed that because GCD is terrible fast, then anything is faster in GCD. Well, it turns out that the old fashion and well known sort descriptor beats GCD here. And not by a marging, but by an order of magnitude. Moral of a fable? It worth checking asumptions with real code.
And talking about code, here’s the meat.