Objective C
+ (SafeStorage*)sharedInstance
{
static SafeStorage *instance = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
instance = [[self alloc] init];
});
return instance;
}
Swift
class Server {
static let sharedInstance = Server()
private init() {
}
}
miércoles, 27 de enero de 2016
iOS: Semaphore, Locks, Multithreading
Semaphore
static dispatch_semaphore_t newAgent;
newAgent = dispatch_semaphore_create(0);
dispatch_semaphore_signal(newAgent);
dispatch_time_t timeout = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(kWaitForNewAgents * NSEC_PER_SEC));
dispatch_semaphore_wait(newAgent, timeout);
Lock
static NSLock *agentLock;
agentLock = [[NSLock alloc]init];
[agentLock lock];
[agentLock unlock];
static dispatch_semaphore_t newAgent;
newAgent = dispatch_semaphore_create(0);
dispatch_semaphore_signal(newAgent);
dispatch_time_t timeout = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(kWaitForNewAgents * NSEC_PER_SEC));
dispatch_semaphore_wait(newAgent, timeout);
dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
Lock
static NSLock *agentLock;
agentLock = [[NSLock alloc]init];
[agentLock lock];
[agentLock unlock];
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
});
Create own queue:
dispatch_queue_t myQueue = dispatch_queue_create("My Queue",NULL);
dispatch_async(myQueue, ^{
// Perform long running process
dispatch_async(dispatch_get_main_queue(), ^{
// Update the UI
});
});
Groups
dispatch_group_t group = dispatch_group_create();
dispatch_group_async(group,dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^ {
// block1
NSLog(@"Block1");
[NSThread sleepForTimeInterval:5.0];
NSLog(@"Block1 End");
});
dispatch_group_async(group,dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^ {
// block2
NSLog(@"Block2");
[NSThread sleepForTimeInterval:8.0];
NSLog(@"Block2 End");
});
dispatch_group_notify(group,dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0*), ^ {
// block3
NSLog(@"Block3");
});
Common usage
dispatch_async(dispatch_get_global_queue( DISPATCH_QUEUE_PRIORITY_DEFAULT, 0*), ^(void){
//Background Thread
dispatch_async(dispatch_get_main_queue(), ^(void){
//Run UI Updates
});
});
*Can be either 0 (or NULL), DISPATCH_QUEUE_CONCURRENT or DISPATCH_QUEUE_SERIAL.
Create own queue:
dispatch_queue_t myQueue = dispatch_queue_create("My Queue",NULL);
dispatch_async(myQueue, ^{
// Perform long running process
dispatch_async(dispatch_get_main_queue(), ^{
// Update the UI
});
});
Groups
dispatch_group_t group = dispatch_group_create();
dispatch_group_async(group,dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^ {
// block1
NSLog(@"Block1");
[NSThread sleepForTimeInterval:5.0];
NSLog(@"Block1 End");
});
dispatch_group_async(group,dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^ {
// block2
NSLog(@"Block2");
[NSThread sleepForTimeInterval:8.0];
NSLog(@"Block2 End");
});
dispatch_group_notify(group,dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0*), ^ {
// block3
NSLog(@"Block3");
});
Common usage
dispatch_async(dispatch_get_global_queue( DISPATCH_QUEUE_PRIORITY_DEFAULT, 0*), ^(void){
//Background Thread
dispatch_async(dispatch_get_main_queue(), ^(void){
//Run UI Updates
});
});
*Can be either 0 (or NULL), DISPATCH_QUEUE_CONCURRENT or DISPATCH_QUEUE_SERIAL.
martes, 26 de enero de 2016
iOS: AlertView deprecated
UIAlertController * alert= [UIAlertController
alertControllerWithTitle:@"Title"
message:@"Message"
preferredStyle:UIAlertControllerStyleAlert];
UIAlertAction* yesButton = [UIAlertAction
actionWithTitle:@"Yes, please"
style:UIAlertActionStyleDefault
handler:^(UIAlertAction * action)
{
}];
UIAlertAction* noButton = [UIAlertAction
actionWithTitle:@"No, thanks"
style:UIAlertActionStyleDefault
handler:^(UIAlertAction * action)
{
}];
[alert addAction:yesButton];
[alert addAction:noButton];
[self presentViewController:alert animated:YES completion:nil];
iOS: Dispatch on main thread
Objective C
dispatch_async(dispatch_get_main_queue(), ^(){
//Do something
});
Swift
DispatchQueue.main.asyncAfter(deadline: .now() + 1.0, execute: {
...
})
dispatch_async(dispatch_get_main_queue(), ^(){
//Do something
});
Swift
DispatchQueue.main.asyncAfter(deadline: .now() + 1.0, execute: {
...
})
iOS: Global constant in Xcode
Project Navigator > Select your project > Build Settings > Apple LLVM 7.0 - Preprocessing > Preprocesor Macros > Click on "debug" or "release" and add the desired value(s)
lunes, 25 de enero de 2016
iOS: LocalNotification
NSDate* date = [[NSDate date] dateByAddingTimeInterval:10];
UILocalNotification *localNotification = [[UILocalNotification alloc] init];
localNotification.fireDate = date;
localNotification.alertBody = [NSString stringWithFormat:@"Alert Fired at %@", date];
localNotification.soundName = UILocalNotificationDefaultSoundName;
localNotification.applicationIconBadgeNumber = 1;
[[UIApplication sharedApplication] scheduleLocalNotification:localNotification];
viernes, 22 de enero de 2016
iOS: NSNotificationCenter
Receiver
[[NSNotificationCenter defaultCenter] removeObserver:self];
[super viewDidDisappear: animated];
}
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(receiveNotification:) name:@"Notification" object:nil];
}
- (void) receiveNotification:(NSNotification *) notification
{
// Do something
}
Somewhere in another class
[[NSNotificationCenter defaultCenter] postNotificationName:@"Notification" object:self];
- (void)viewDidDisappear:(BOOL)animated
{[[NSNotificationCenter defaultCenter] removeObserver:self];
[super viewDidDisappear: animated];
}
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear: animated];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(receiveNotification:) name:@"Notification" object:nil];
}
- (void) receiveNotification:(NSNotification *) notification
{
// Do something
}
Somewhere in another class
[[NSNotificationCenter defaultCenter] postNotificationName:@"Notification" object:self];
martes, 19 de enero de 2016
iOS: Blocks
Property
@property (copy) void (^blockProperty)(void);
Method definition
- (void)beginTaskWithName:(NSString *)name completion:(void(^)(void))callback;
Inline implementation
[array enumerateObjectsUsingBlock:^ (id obj, NSUInteger idx, BOOL *stop) {
NSLog(@"Object at index %lu is %@", idx, obj);
}];
If you need to be able to change the value of a captured variable from within a block, you can use the __block storage type modifier on the original variable declaration.
__block int anInteger = 42;
@property (copy) void (^blockProperty)(void);
Method definition
- (void)beginTaskWithName:(NSString *)name completion:(void(^)(void))callback;
Inline implementation
[array enumerateObjectsUsingBlock:^ (id obj, NSUInteger idx, BOOL *stop) {
NSLog(@"Object at index %lu is %@", idx, obj);
}];
If you need to be able to change the value of a captured variable from within a block, you can use the __block storage type modifier on the original variable declaration.
__block int anInteger = 42;
iOS: Registering for remote notifications
- (void)applicationDidFinishLaunching:(UIApplication *)app {
// other setup tasks here....
// Register the supported interaction types.
UIUserNotificationType types = UIUserNotificationTypeBadge |
UIUserNotificationTypeSound | UIUserNotificationTypeAlert;
UIUserNotificationSettings *mySettings =
[UIUserNotificationSettings settingsForTypes:types categories:nil];
[[UIApplication sharedApplication] registerUserNotificationSettings:mySettings];
// Register for remote notifications.
[[UIApplication sharedApplication] registerForRemoteNotifications];
}
// Handle remote notification registration.
- (void)application:(UIApplication *)app
didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)devToken {
const void *devTokenBytes = [devToken bytes];
self.registered = YES;
[self sendProviderDeviceToken:devTokenBytes]; // custom method
}
- (void)application:(UIApplication *)app
didFailToRegisterForRemoteNotificationsWithError:(NSError *)err {
NSLog(@"Error in registration. Error: %@", err);
}
Note: 1) If a cellular or Wi-Fi connection is not available, neither the "application:didRegisterForRemoteNotificationsWithDeviceToken:" method nor the "application:didFailToRegisterForRemoteNotificationsWithError:" method is called.
2) Never cache a device token; always get the token from the system whenever you need it. If your app previously registered for remote notifications, calling the registerForRemoteNotifications method again does not incur any additional overhead, and iOS returns the existing device token to your app delegate immediately.
3) In addition, iOS calls your delegate method any time the device token changes, not just in response to your app registering or re-registering.
viernes, 15 de enero de 2016
jueves, 14 de enero de 2016
iOS: Add a view on top of every view
[[[UIApplication sharedApplication] keyWindow] addSubview:myView];
iOS: Editable UITableView
@interface ViewController ()
@property(nonatomic, retain) UIBarButtonItem* addButton;
@end
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
self.navigationItem.rightBarButtonItem = self.editButtonItem;
_addButton = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemAdd target:self action:@selector(addItem:)];
self.navigationItem.leftBarButtonItem = _addButton;
}
#pragma mark - UITableViewDelegate
- (void)setEditing:(BOOL)editing animated:(BOOL)animated
{
[super setEditing:editing animated:animated];
[self.tableview setEditing:editing animated:YES];
if (editing) {
_addButton.enabled = NO;
} else {
_addButton.enabled = YES;
}
}
- (UITableViewCellEditingStyle)tableView:(UITableView*)tableView editingStyleForRowAtIndexPath:(NSIndexPath*)indexPath
{
// if (indexPath.row == _list.count - 1) {
// return UITableViewCellEditingStyleInsert;
// } else {
// return UITableViewCellEditingStyleDelete;
// }
return UITableViewCellEditingStyleDelete;
}
- (void)addItem:(id)sender
{
[self performSegueWithIdentifier:@"AddViewController" sender:self]; // Presents AddViewController modally
}
#pragma mark - Unwind segues
- (IBAction)dimiss:(UIStoryboardSegue*)segue
{
}
- (IBAction)doAddItem:(UIStoryboardSegue*)segue
{
AddViewController* addViewController = segue.sourceViewController;
NSString* provider = addViewController.provider.text;
NSString* account = addViewController.account.text;
NSString* password = addViewController.password.text;
KeychainItemWrapper* item = [[KeychainItemWrapper alloc] initWithAccount:account service:provider accessGroup:nil];
[item setObject:password forKey:@"v_Data"];
self.list = [self getItemsFromKeychain];
[self.tableview reloadData];
}
iOS: Expandable UITableView
@interface ViewController ()
@property(nonatomic, retain) NSIndexPath* selectedIndexPath;
@end
#pragma mark - UITableViewDataSource
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return _list.count;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
NSDictionary* item = [self.list objectAtIndex:indexPath.row];
ExpandedTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"ExpandedCell"];
cell.clipsToBounds = YES;
// Populate cell
return cell;
}
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath;
{
return self.selectedIndexPath != nil && self.selectedIndexPath.row == indexPath.row ? expanded_height : normal_height;
}
#pragma mark - UITableViewDelegate
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
[self.tableview beginUpdates];
if (self.selectedIndexPath == nil) {
self.selectedIndexPath = indexPath;
} else {
self.selectedIndexPath = nil;
}
[self.tableview endUpdates];
}
Suscribirse a:
Entradas (Atom)