text:
iOS Game Development Cookbook (2014)
Chapter 1. Laying Out a Game
Games are software, and the best software has had some thought put into it regarding how it's going to work. When you're writing a game, you need to keep in mind how you're going to handle the individual tasks that the game needs to perform, such as rendering graphics, updating artificial intelligence (AI), handling input, and the hundreds of other small tasks that your game will need to deal with.
In this chapter, you'll learn about ways you can lay out the structure of your game that will make development easier. You'll also learn how to organize the contents of your game so that adding more content and gameplay elements is easier, and find out how to make your game do multiple things at once.
Laying Out Your Engine
You want to determine the best way to lay out the architecture of your game.
The biggest thing to consider when you're thinking about how to best lay out your game is how the game will be updated. There are three main things that can cause the state of the game to change:
Input from the user
The game may change state when the user provides some input, such as tapping a button or typing some text. Turn-based games are often driven by user input (e.g., in a game of chess, the game state might only be updated when the user finishes moving a piece).
The game state may change every time a timer goes off. The delay between timer updates might be very long (some web-based strategy games have turns that update only once a day), or very short (such as going off every time the screen finishes drawing). Most real-time games, like shooters or real-time strategy games, use very short-duration timers.
Input from outside
The game state may change when information from outside the game arrives. The most common example of this is some information arriving from the network, but it can also include data arriving from built-in sensors, such as the accelerometer.
Sometimes, this kind of updating is actually a specific type of timer-based update, because some networks or sensors need to be periodically checked to see if new information has arrived.
None of these methods are mutually exclusive. You can, for example, run your game on a timer to animate content, and await user input to move from one state to the next.
Updating every frame is the least efficient option, but it lets you change state often, which makes the game look smooth.
Creating an Inheritance-Based Game Layout
You want to use an inheritance-based (i.e., a hierarchy-based) architecture for your game, which is simpler to implement.
First, define a class called GameObject:
@interface GameObject : NSObject {
- (void) update:(float)deltaTime;
@implementation GameObject
- (void) update:(float)deltaTime {
// Do some updating
When you want to create a new kind of game object, you create a subclass of the GameObject class, which inherits all of the behavior of its parent class and can be customized:
@interface Monster : GameObject {
@property (assign) float hitPoints; // num of times it can be hit without dying
@property (weak) GameObject* targetObject; // try to kill this object
@implementation Monster
- (void) update:(float)deltaTime {
[super update:deltaTime];
// Do some monster-specific updating
In an inheritance-based layout, as seen in Figure 1-1, you define a single base class for your game object (often called GameObject), which knows about general tasks like being updated, and then create subclasses for each specific type of game object. This hierarchy of subclasses can be multiple levels deep (e.g., you might subclass the GameObject class to make the Monster subclass, and then subclass that to create the Goblin and Dragon classes, each of which has its own different kinds of monster-like behavior).
Figure 1-1. An inheritance-based layout
The advantage of a hierarchy-based layout is that each object is able to stand alone: if you have a Dragon object, you know that all of its behavior is contained inside that single object, and it doesn't rely on other objects to work. The downside is that you can often end up with a very deep hierarchy of different game object types, which can be tricky to keep in your head as you program.
Creating a Component-Based Game Layout
You want to use a component-based architecture for your game, which allows for greater flexibility.
First, define a Component class. This class represents components that are attached to game objects—it is a very simple class that, at least initially, only has a single method and a single property:
@class GameObject;
@interface Component : NSObject
- (void) update:(float)deltaTime;
@property (weak) GameObject* gameObject;
Next, define a GameObject class. This class represents game objects:
#import "Component.h"
@interface GameObject : NSObject
@property (strong) NSSet* components;
- (void) addComponent:(Component*)component;
- (void) removeComponent:(Component*)component;
- (void)update:(float)deltaTime;
- (id)componentWithType:(Class)componentType;
- (NSArray*)componentsWithType:(Class)componentType;
The implementation for this class looks like this:
#import "GameObject.h"
@implementation GameObject {
NSMutableSet* _components;
@synthesize components = _components;
- (id)init {
self = [super init];
if (self) {
_components = [NSMutableSet set];
return self;
- (void)addComponent:(Component *)component {
[_components addObject:component];
component.gameObject = self;
- (void)removeComponent:(Component *)component {
[_components removeObject:component];
component.gameObject = nil;
- (void)update:(float)deltaTime {
for (Component* component in _components) {
[component update:deltaTime];
- (id)componentWithType:(Class)componentType {
// Helper function that just returns the first component with a given type
return [[self componentsWithType:componentType] firstObject];
- (NSArray*)componentsWithType:(Class)componentType {
// Return nil if the class isn't actually a type of component
if ([componentType isSubclassOfClass:[Component class]] == NO)
return nil;
// Work out which components match the component type, and return them all
return [[_components objectsPassingTest:^BOOL(id obj, BOOL *stop) {
return [obj isKindOfClass:componentType];
}] allObjects];
Using these objects looks like this:
// Make a new game object
GameObject gameObject = [[GameObject alloc] init];
// Add some components
Component* component = [[Component alloc] init];
[gameObject addComponent:component];
// When the game needs to update, send all game objects the "update" message
// This makes all components get updated as well
[gameObject update];
In a component-based architecture, as seen in Figure 1-2, each game object is made up of multiple components. Compare this to an inheritance-based architecture, where each game object is a subclass of some more general class (see Creating an Inheritance-Based Game Layout).
A component-based layout means you can be more flexible with your design and not worry about inheritance issues. For example, if you've got a bunch of monsters, and you want one specific monster to have some new behavior (such as, say, exploding every five seconds), you just write a new component and add it to that monster. If you later decide that you want other monsters to also have that behavior, you can add that behavior to them too.
In a component-based architecture, each game object has a list of components. In this recipe, we're using an NSMutableSet, which means that if you add the same component more than once, the list will only contain one copy of the component. When something happens to an object—for example, the game updates, or the object is added to or removed from the game—the object goes through each one of its components and notifies them. This gives them the opportunity to respond in their own way.
Figure 1-2. A component-based layout
The main problem with component-based architectures is that it's more laborious to create multiple copies of an object, because you have to create and add the same set of components every time you want a new copy.
Calculating Delta Times
You want to know how many seconds have elapsed since the last time the game updated.
First, decide which object should be used to keep track of time. This may be a view controller, an SKScene, a GLKViewController, or something entirely custom.
Create an instance variable inside that object:
@interface MyTimeKeepingObject {
double lastFrameTime;
Then, each time your game is updated, get the current time in milliseconds, and subtract lastFrameTime from that. This gives you the amount of time that has elapsed since the last update.
When you want to make something happen at a certain rate—for example, moving at 3 meters per second—multiply the rate by the delta time:
- (void)update:(double)currentTime {
double deltaTime = currentTime - lastFrameTime;
// Move at 3 units per second
float movementSpeed = 3;
[someObject moveAtSpeed:movementSpeed * deltaTime];
lastFrameTime = currentTime;
"Delta time" means "change in time." Delta times are useful to keep track of how much time has elapsed from one point in time to another—in games, this means the time from one frame to the next. Because the game content changes frame by frame, the amount of time between frames becomes important.
Additionally, the amount of time between frames might change a little. You should always be aiming for a constant frame rate of 60 frames per second (i.e., a delta time of 16 milliseconds: 1÷60 = 0.0166); however, this may not always be achievable, depending on how much work needs to be done in each frame. This means that delta time might vary slightly, so calculating the delta time between each frame becomes necessary if you want rates of change to appear constant.
Some engines give you the delta time directly. For example, CADisplayLink gives you a duration property (see Updating Based on When the Screen Updates), and GLKViewController gives you timeSinceLastUpdate (see Rotating a Cube).
Some engines give you just the current time, from which you can calculate the delta time. For example, the SKScene class passes the currentTime parameter to the update: method (discussed further in Adding Thrusters to Objects).
In other cases (e.g., if you're doing the main loop yourself), you won't have easy access to either. In these cases, you need to get the current time yourself:
double currentTime = [NSDate timeIntervalSinceReferenceDate];
Detecting When the User Enters and Exits Your Game
You want to detect when the user leaves your game, so that you can pause the game. You also want to know when the user comes back.
To get notified when the user enters and exits your game, you register to receive notifications from an NSNotificationCenter. The specific notifications that you want to receive are UIApplicationDidBecomeActiveNotification,UIApplicationWillEnterForegroundNotification, UIApplicationWillResignActiveNotification, and UIApplicationDidEnterBackgroundNotification:
- (void)viewDidAppear:(BOOL)animated {
// Called when the application becomes the active one
// (i.e., when nothing's covering it up)
[[NSNotificationCenter defaultCenter]
addObserver:self selector:@selector(applicationDidBecomeActive:)
name:UIApplicationDidBecomeActiveNotification object:nil];
// Called when the application will enter the foreground (i.e.,
// when the user has left another app and entered this one)
[[NSNotificationCenter defaultCenter]
addObserver:self selector:@selector(applicationWillEnterForeground:)
name:UIApplicationWillEnterForegroundNotification object:nil];
// Called when the application will resign active (i.e., when something's
// covering it up, like the notification tray or a phone call)
[[NSNotificationCenter defaultCenter]
addObserver:self selector:@selector(applicationWillResignActive:)
name:UIApplicationWillResignActiveNotification object:nil];
// Called when the application enters the background
// (i.e., when the user has left it)
[[NSNotificationCenter defaultCenter]
addObserver:self selector:@selector(applicationDidEnterBackground:)
name:UIApplicationDidEnterBackgroundNotification object:nil];
- (void)viewDidDisappear:(BOOL)animated {
[[NSNotificationCenter defaultCenter] removeObserver:self];
- (void) applicationDidBecomeActive:(NSNotification*)notification {
NSLog(@"Application did become active!");
- (void) applicationWillResignActive:(NSNotification*)notification {
NSLog(@"Application will resign active!");
- (void) applicationDidEnterBackground:(NSNotification*)notification {
NSLog(@"Application did enter background!");
- (void) applicationWillEnterForeground:(NSNotification*)notification {
NSLog(@"Application will enter foreground!");
On iOS, only one app can be the "active" application (i.e., the app that is taking up the screen and that the user is interacting with). This means that apps need to know when they become the active one, and when they stop being active.
When your game is no longer the active application, the player can't interact with it. This means that the game should pause (see Pausing a Game). When the game resumes being the active application, the player should see a pause screen.
Pausing, of course, only makes sense in real-time games, such as shooters, driving games, arcade games, and so on. In a turn-based game, like a strategy or puzzle game, you don't really need to worry about the game being paused or not.
In addition to being the active application, an application can be in the foreground or the background. When an application is in the foreground, it's being shown on the screen. When it's in the background, it isn't visible at all. Apps that are in the background become suspended after a short period of time, to save battery power. Apps that enter the background should reduce their memory consumption as much as possible; if your app consumes a large amount of memory while it is in the background, it is more likely to be terminated by iOS.
Updating Based on a Timer
You want to update your game after a fixed amount of time.
Use an NSTimer to receive a message after a certain amount of time, or to receive an update on a fixed schedule.
First, add an instance variable to your view controller:
NSTimer* timer;
Next, add a method that takes an NSTimer parameter:
- (void) updateWithTimer:(NSTimer*) timer {
// The timer's gone off; update the game
NSLog(@"Updated from timer!");
Finally, when you want to start the timer:
timer = [NSTimer scheduledTimerWithTimeInterval:0.5
target:self selector:@selector(updateWithTimer:) userInfo:nil repeats:YES];
To stop the timer:
[timer invalidate];
timer = nil;
An NSTimer waits for a specified number of seconds, and then calls a method on an object that you specify. You can change the number of seconds by changing the timeInterval parameter:
// Wait 2 seconds
[NSTimer scheduledTimerWithTimeInterval:2
target:self selector:@selector(updateWithTimer:) userInfo:nil repeats:YES];
// Wait 0.1 seconds (100 milliseconds)
[NSTimer scheduledTimerWithTimeInterval:0.1
target:self selector:@selector(updateWithTimer:) userInfo:nil repeats:YES];
You can also make a timer either fire only once or repeat forever, by changing the repeats parameter to NO or YES, respectively.
Updating Based on When the Screen Updates
You want to update your game every time the screen redraws.
Use a CADisplayLink, which sends a message every time the screen is redrawn.
First, add an instance variable to your view controller:
@interface ViewController () {
CADisplayLink* displayLink;
Next, add a method that takes a single parameter (a CADisplayLink):
- (void) update:(CADisplayLink*)displayLink {
// The screen's just updated; update the game
NSLog(@"Updated from display link!");
Finally, add this code when you want to begin receiving updates:
// Create the CADisplayLink; "self" will receive the updateWithDisplayLink:
// message every time the screen updates
displayLink = [CADisplayLink
displayLinkWithTarget:self selector:@selector(update:)];
// Add the display link and start receiving updates
[displayLink addToRunLoop:[NSRunLoop mainRunLoop] forMode:NSRunLoopCommonModes];
When you want to pause receiving updates, set the paused property of the CADisplayLink to YES:
displayLink.paused = YES;
When you want to stop receiving updates, call invalidate on the CADisplayLink:
[displayLink invalidate];
displayLink = nil;
When we talk about "real-time" games, what comes to mind is objects like the player, vehicles, and other things moving around the screen, looking like they're in continuous motion. This isn't actually what happens, however—what's really going on is that the screen is redrawing itself every 1/60th of a second, and every time it does this, the locations of some or all of the objects on the screen change slightly. If this is done fast enough, the human eye is fooled into thinking that everything's moving continuously.
In fact, you don't technically need to update as quickly as every 1/60th of a second—anything moving faster than 25 frames per second (in other words, one update every 1/25th of a second) will look like motion. However, faster updates yield smoother-looking movement, and you should always aim for 60 frames per second.
You'll get the best results if you update your game at the same rate as the screen. You can achieve this with a CADisplayLink, which uses the Core Animation system to figure out when the screen has updated. Every time this happens, the CADisplayLink sends its target a message, which you specify.
It's worth mentioning that you can have as many CADisplayLink objects as you like, though they'll all update at the same time.
Pausing a Game
You want to be able to pause parts of your game, but still have other parts continue to run.
Keep track of the game's "paused" state in a BOOL variable. Then, divide your game objects into two categories—ones that run while paused, and ones that don't run while paused:
// This is just pseudocode--your game will likely look slightly different
for (GameObject* gameObject in gameObjects) {
if (paused == NO || gameObject.shouldPause == NO) {
[gameObject update];
The simplest possible way to pause the game is to keep track of a pause state; every time the game updates, you check to see if the pause state is set to YES, and if it is, you don't update any game objects.
However, you often don't want every single thing in the game to freeze. For example:
§ The user interface may need to continue to animate.
§ The network may need to keep communicating with other computers, rather than stopping entirely.
In these cases, having special objects that never get paused makes more sense.
Calculating Time Elapsed Since the Game Start
You want to find out how much time has elapsed since the game started.
When the game starts, create an NSDate object and store it:
// In your class's @interface:
@property (strong) NSDate* gameStartDate;
// When the game starts:
self.gameStartDate = [NSDate date];
When you want to find out how much time has elapsed since the game started, create a second NSDate and use the timeIntervalSinceDate: method to calculate the time:
NSDate* now = [NSDate date];
NSTimeInterval timeSinceGameStart =
[self.gameStartDate timeIntervalSinceDate:self.gameStartDate];
NSLog(@"The game started %.2f seconds ago", timeSinceGameStart);
NSDate objects represent moments in time. They're the go-to object for representing any instant of time that you want to be able to refer to again later, such as when your game starts. NSDate objects can refer to practically any date in the past or future and are very precise.
When you create an NSDate with the [NSDate date] method, you get back an NSDate object that refers to the current time (i.e., the instant when the NSDate object was created).
To determine the interval between two dates, you use timeIntervalSinceDate:. This method returns an NSTimeInterval, which is actually another term for a floating-point number. These values are represented in seconds, so it's up to your code to do things like determine the number of hours and minutes:
NSTimeInterval timeElapsed = ... // an NSTimeInterval from somewhere
float minutes = timeElapsed / 60.0; // 60 seconds per minute
float hours = timeElapsed / 3600.0; // 3600 seconds per hour
float seconds = fmodf(timeElapsed, 60.0); // get the remainder
NSLog(@"Time elapsed:%.0f:%.0f:%.2f", hours, minutes, seconds);
Working with Blocks
You want to store some code in a variable, for later execution.
Blocks are ideal for this:
onCollision = ^(void) {
NSLog(@"Character collided with something!");
// Later, when a collision happens:
Blocks are a language feature in Objective-C that allow you to store chunks of code in variables, which can then be worked with like any other variable.
Here's an example of a simple block:
MyBlock = ^(void) {
NSLog(@"Hello from the block!");
This is how you define a block. In this case, the block returns void, is named MyBlock, and accepts no parameters.
Just like any other variable, once a block is defined, it needs to be given a value. In this case, we're providing a block that takes no parameters and returns nothing, just like the block variable's definition.
Calling a block works just like calling any other function.
How blocks work
So far, this just seems like a very roundabout way to call a function. However, the real power of blocks comes from two facts:
§ Blocks capture the state of any other variables their code references.
§ Blocks are objects, and they stay around until you need them. If you store a block, you can call it however often you like.
Let's talk about the first point. Say you had a block like this:
int i = 1;
void(^MyBlock)(void) = ^(void) {
NSLog(@"i = %i", i);
As you'd expect, running this code would print i = 1 to the console. But watch what happens when you change the value of i after creating the block, like this:
int i = 1;
void(^MyBlock)(void) = ^(void) {
NSLog(@"i = %i", i);
i = 5;
This code will print the following to the console:
i = 1
That's right—running this code produces the same result as the first version. Even though the i variable has been modified, the console will still print i = 1. This is because i had the value of 1 at the moment the block was created—the fact that i was later changed to 5 doesn't affect the block's copy of that variable.
This is extremely powerful, because it means that your game doesn't need to carefully store values for later use; if a block needs a value, it automatically keeps it.
The syntax for creating blocks is a little messy, with carets (^) and parentheses all over the place. An easier way to do it is to define a block type, which is just a simple type definition of a block. For example, here's a block type for the preceding examples:
typedef void(^ExampleBlock)(void);
This allows you to declare variables with nicer syntax, and with significantly fewer parentheses and carets:
ExampleBlock myBlock = ^(void) {
NSLog(@"i SPILL my DRINK!");
So far, we've talked entirely about blocks that don't have parameters or return types. These are easy to define, though. For example, here's a block that returns a BOOL and takes two parameters, one NSString and one int:
typedef BOOL(^ParameterBlock)(NSString* string, int number);
The syntax to create this block is very similar to the earlier examples:
ParameterBlock paramBlock = ^(NSString* string, int number) {
NSLog(@"I received a string %@, and a number %i!", string, number);
return YES;
paramBlock(@"Hello", 1337);
If your block doesn't take any parameters, you can actually skip the parameter list entirely:
typedef void(^ExampleBlock)(void);
ExampleBlock aBlock = ^{
Blocks and other objects
When a block is created, the compiler looks at all of the variables that the block is referencing. If a variable is a simple value, like an int or a float, that value is simply copied. However, if the variable is an Objective-C object, it can't be copied, because it could potentially be very large. Instead, the object is retained by the block. When a block is freed, any objects retained by the block are released.
This means that if you have a block that references another object, that block will keep the other object around.
For example, say you have code that looks like this:
NSString* aString = [NSString stringWithFormat:@"One = %i", 1];
void(^MyBlock)(void) = ^(void) {
NSLog(@"The string is %@", aString);
aString = nil;
// aString is still in memory, because MyBlock is keeping it around!
The block MyBlock, because it references the aString object, will maintain an owning reference to aString. This means that even if all other references to aString go away, the string is kept in memory, and it will only be released when MyBlock goes away. (This example only makes sense if you're using automatic reference counting, or ARC—which you should be.)
This is usually what you want, since it would be annoying to have to remember to keep the variables referenced by blocks in memory. However, sometimes that's not what you want.
One example is when you want a block to run in two seconds' time that causes an enemy object to run an attack animation. However, between the time you schedule the block and the time the block runs, the enemy is removed from the game. If the block has a strong reference to the enemy, the enemy isn't actually removed from memory until the block is scheduled to run, which could have unintended side effects.
To get around this problem, you use weak references. A weak reference is a reference that does not keep an object in memory; additionally, if the object that is being referred to is removed (because all owning references to it have gone away), the weak reference will automatically be set tonil.
You create a weak reference by prepending the keyword __weak to a variable declaration, like so:
__weak NSString* weakString = aString;
This makes weakString into a weak reference to aString. Now, when aString is removed from memory, the weakString reference will automatically point to nil instead.
Using weak references, the previous example code looks like this:
NSString* aString = [NSString stringWithFormat:@"One = %i", 1];
__weak NSString* weakString = aString;
void(^MyBlock)(void) = ^(void) {
NSLog(@"The string is %@", weakString);
aString = nil;
// aString is no longer in memory, and calling MyBlock will print
// "The string is (null)"
Writing a Method That Calls a Block
You want to write a method that, after performing its work, calls a block to indicate that the work is complete.
For example, you want to tell a character to start moving to a destination, and then run a block when the character finishes moving.
To create a method that takes a block as a parameter, you just do this:
- (void) moveToPosition:(CGPoint)position
completionBlock:(void (^)(void))completion {
// Do the actual work, which might take place over several frames
// Call the completion block
if (completion != nil) {
And to pass the block to the method, you do this:
CGPoint destination = ...
[someObject moveToPosition:destination completionBlock:^{
NSLog(@"Finished moving!");
Methods that take a block as a parameter are useful for when you're writing code that starts off a long-running process, and you want to run some code at the conclusion of that process but want to keep that conclusion code close to the original call itself.
Before blocks were added to the Objective-C language, the usual technique was to write two methods: one where you started the long-running process, and one that would be called when the process completed. This separates the various parts of the code, which decreases the readability of your code; additionally, passing around variables between these two methods is more complicated (because you need to manually store them in a temporary variable at the start, and retrieve them at the end; with blocks, you just use the variables without any additional work).
Working with Operation Queues
You want to put chunks of work in a queue, so that they're run when the operating system has a moment to do them.
Use an NSOperationQueue to schedule blocks to be run in the background without interfering with more time-critical tasks like rendering or accepting user input:
NSOperationQueue* concurrentQueue = [[NSOperationQueue alloc] init];
concurrentQueue.maxConcurrentOperationCount = 10;
[concurrentQueue addOperationWithBlock:^{
[concurrentQueue addOperationWithBlock:^{
[concurrentQueue addOperationWithBlock:^{
An operation queue is a tool for running chunks of work. Every application has an operation queue called the main queue. The main queue is the queue that normal application tasks (e.g., handling touches, redrawing the screen, etc.) are run on.
Many tasks can only be run on the main queue, including updating anything run by UIKit. It's also a good idea to only have a single operation queue that's in charge of sending OpenGL instructions.
The main queue is a specific NSOperationQueue, which you can access using the mainQueue method:
NSOperationQueue* mainQueue = [NSOperationQueue mainQueue];
[mainQueue addOperationWithBlock:^{
It's often the case that you want to do something in the background (i.e., on another operation queue), and then alert the user when it's finished. However, as we've already mentioned, you can only do UIKit or OpenGL tasks (e.g., displaying an alert box) on the main queue
To address this, you can put tasks on the main queue from inside a background queue:
NSOperationQueue* backgroundQueue = [[NSOperationQueue alloc] init];
[backgroundQueue addOperationWithBlock:^{
[[NSOperationQueue mainQueue] addOperationWithBlock:^{
NSLog(@"This is run on the main queue");
An operation queue runs as many operations as it can simultaneously. The number of concurrent operations that can be run depends on a number of conditions, including the number of processor cores available, and the different priorities that other operations may have.
By default, an operation queue determines the number of operations that it can run at the same time on its own. However, you can specify a maximum number of concurrent operations by using the maxConcurrentOperationCount property:
NSOperationQueue* aQueue = [[NSOperationQueue alloc] init];
aQueue.maxConcurrentOperationCount = 2;
Performing a Task in the Future
You want to run some code, but you want it to happen a couple of seconds from now.
Use dispatch_after to schedule a block of code to run in the future:
// Place a bomb, but make it explode in 10 seconds
double timeToWait = 10.0;
dispatch_time_t delayTime = dispatch_time(DISPATCH_TIME_NOW,
(int64_t)(timeToWait * NSEC_PER_SEC));
dispatch_queue_t queue = dispatch_get_main_queue();
dispatch_after(delayTime, queue, ^(void){
// Time's up. Kaboom.
NSOperationQueue is actually a higher-level wrapper around the lower-level features provided by the C-based Grand Central Dispatch API. Grand Central Dispatch, or GCD, works mostly with objects called "dispatch queues," which are basically NSOperationQueues. You do work with GCD by putting blocks onto a queue, which runs the blocks. Just as with NSOperationQueue, there can be many queues operating at the same time, and they can be serial or concurrent queues.
GCD provides a function called dispatch_after that runs a block on an operation queue at a given time. To use the function, you first need to figure out the time when the block should be run. GCD doesn't actually work in seconds, or even in nanoseconds, but rather with time units calleddispatch_time_t, which Apple's documentation describes as "a somewhat abstract representation of time."
To work with dispatch_time_t, you use the function dispatch_time, which takes two parameters: a base time and an amount of time to be added on top, measured in nanoseconds.
Therefore, to get a dispatch_time_t that represents 1 second in the future, you would use this:
double timeToWait = 1.0;
dispatch_time_t delayTime = dispatch_time(DISPATCH_TIME_NOW,
(int64_t)(timeToWait * NSEC_PER_SEC));
Once you have a time for the block to run at, you need to get a reference to a GCD dispatch_queue. You can create your own, but you generally only want the main queue, which you can get using dispatch_get_main_queue:
dispatch_queue_t queue = dispatch_get_main_queue();
Finally, you instruct GCD to run the block:
dispatch_after(delayTime, queue, ^(void){
NSLog(@"Delayed block");
Storing Blocks in Objects
You want to store a block in an object, so that the object can call it later.
Blocks can be stored as properties in objects. For example:
typedef void(^CallbackBlock)(void);
@interface Monster : NSObject
@property (copy) CallbackBlock onDeathBlock;
@property (copy) CallbackBlock onHitBlock;
// In the Monster class:
- (void) die {
- (void) hit {
Monster* monster = ...
monster.onDeathBlock = ^{
NSLog(@"Monster died!");
monster.onHitBlock = ^{
NSLog(@"Monster hit something")!
Note that the property settings for the aBlock copy in this example indicate that the block should be copied. This is important—if you don't do this, then your application will crash when you try to call it.
The reason for this is that when a block is created, it's created on the stack. When the function that it's created in returns, the block is destroyed.
Copying a block moves the block from the stack to the heap, which means that the block stays around after the function that created it returns. It also means that the block needs to be explicitly freed (though ARC handles this for you, either when you set the property that contains the block tonil or when the object is freed).
A block stored as a property can be accessed just like any other variable, and called like all blocks are:
- (void) doSomething {
If you call a block that's set to nil, your app will crash. For example:
ExampleBlock aBlock = nil;
aBlock(); // CRASH!
You need to do explicit checking if you want to be safe:
if (aBlock != nil) {
When you store a block as a property of an object, it's important to remember that blocks can retain objects. If an object is retaining a block, and that block is retaining the object as well, you have a retain cycle.
Say you have a block that looks like this:
void(^MyBlock)(void) = ^(void) {
NSLog(@"I am %@", self); // block now retains self
self.aBlock = MyBlock; // self now retains block; retain cycle!
Note how MyBlock references the self object. The compiler notices this, and will make the block retain the self object in memory (because in order for the block to function, it needs to be able to use that variable, which means that the object that that variable points to needs to be kept around). See Figure 1-3.
Figure 1-3. Retain cycles
However, if you store that block in a property in self, the block and the object will be retaining each other. This prevents the object from being removed from memory when all other strong references to it have gone away, as shown in Figure 1-4.
Figure 1-4. A fixed retain cycle
To prevent this from happening, you should always use weak references to self by declaring the variable with the __weak keyword:
__weak id weakSelf = self;
void(^MyBlock)(void) = ^(void) {
NSLog(@"I am %@", weakSelf); // block does NOT retain self
self.aBlock = MyBlock; // self now retains block; no retain cycle
Using a Timer
You want to create a timer that repeatedly calls a block.
First, create an instance variable to store the timer:
@interface ViewController () {
dispatch_source_t timer;
Then, create the timer like so:
// Get the queue to run the blocks on
dispatch_queue_t queue = dispatch_get_main_queue();
// Create a dispatch source, and make it into a timer that goes off every second
timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, queue);
dispatch_source_set_timer(timer, DISPATCH_TIME_NOW, 1 * NSEC_PER_SEC, 0);
// When the timer goes off, heal the player
dispatch_source_set_event_handler(timer, ^{
// Dispatch sources start out paused, so start the timer by resuming it
To cancel the timer, just set the timer variable to nil:
timer = nil;
In addition to dispatch queues, GCD has a concept called a dispatch source, which is something that triggers work to be done. Dispatch sources can be created for things like file I/O where you can run a block when data is available to be read, and timers, where you run a block at a fixed interval.
To create a dispatch timer, you first create a dispatch_source_t, and then configure it to be a timer. As part of setting it up, you also give it a dispatch_queue_t for it to run its code on:
dispatch_queue_t queue = dispatch_get_main_queue();
timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, queue);
The next step is to tell the timer how often it should be fired. This is defined in nanoseconds:
dispatch_source_set_timer(timer, DISPATCH_TIME_NOW, 1 * NSEC_PER_SEC, 0);
Finally, you provide the timer with the block that should be run every time the timer goes off. Dispatch sources start out paused, so you also need to unpause the timer by calling dispatch_resume:
dispatch_source_set_event_handler(timer, ^{
When you want to stop the timer, you just set it to nil. ARC knows about GCD objects, so setting it to nil will cause it to be cleaned up properly.
Making Operations Depend on Each Other
You want to run some operations, but they need to run only after certain other operations are done.
To make an operation wait for another operation to complete, store each individual operation in a variable, and then use the addDependency: method to indicate which operations need to complete before a given operation begins:
NSBlockOperation* firstOperation = [NSBlockOperation blockOperationWithBlock:^{
NSLog(@"First operation");
NSBlockOperation* secondOperation = [NSBlockOperation blockOperationWithBlock:^{
NSLog(@"Second operation (depends on third operation and first operation)");
NSBlockOperation* thirdOperation = [NSBlockOperation blockOperationWithBlock:^{
NSLog(@"Third operation");
[secondOperation addDependency:thirdOperation];
[secondOperation addDependency:firstOperation];
[[NSOperationQueue mainQueue] addOperations:@[firstOperation, secondOperation,
thirdOperation] waitUntilFinished:NO];
You can add an operation to another operation as a dependency. This is useful for cases where you want one block to run only after one or more operations have completed.
To add a dependency to an operation, you use the addDependency: method. Doing this doesn't run the operation, but just links the two together.
Once the operation dependencies have been set up, you can add the operations to the queue in any order that you like; operations will not run until all of their dependencies have finished running.
Filtering an Array with Blocks
You have an array, and you want to filter it with your own custom logic.
Use the filteredArrayUsingPredicate method to create an array that only contains objects that meet certain conditions:
NSArray* array = @[@"One", @"Two", @"Three", @"Four", @"Five"];
NSLog(@"Original array: %@", array);
array = [array filteredArrayUsingPredicate:
[NSPredicate predicateWithBlock:^BOOL(id evaluatedObject,
NSDictionary *bindings) {
NSString* string = evaluatedObject;
// Search for an "e" in the string
if ([string rangeOfString:@"e"].location != NSNotFound)
return YES;
return NO;
NSLog(@"Filtered array: %@", array);
Arrays can be filtered using the filteredArrayUsingPredicate: method. This method uses an NSPredicate to test each object in the array, and returns a new array; if an object passes the test, it's included in the new array.
NSPredicate objects can be set up to run their tests in a variety of ways. One of them is by providing a block, which receives the object to be tested and returns a BOOL value: YES means it's included, and NO means it's not.
Note that using filteredArrayUsingPredicate: doesn't modify the existing array, but rather creates a new one.
Loading New Assets During Gameplay
You want to load new resources without impacting the performance of the game.
For each resource that needs loading, run a block that does the loading into memory, and run it in the background. Then run a subsequent block when all of the blocks have completed.
You can do this through dispatch groups, which are a way to submit multiple units of work to Grand Central Dispatch:
NSArray* imagesToLoad = [NSArray array];
dispatch_group_t group = dispatch_group_create();
dispatch_queue_t backgroundQueue = dispatch_get_global_queue(
for (NSString* imageFileName in imagesToLoad) {
dispatch_group_async(group, backgroundQueue, ^{
// Load the file
dispatch_queue_t mainQueue = dispatch_get_main_queue();
dispatch_group_notify(group, mainQueue, ^{
// All images are done loading at this point
Using a dispatch group will make GCD spin up as many threads as it needs to load all of the resources.
You can control how much CPU time will be allocated to the loading task by changing the priority of the background queue. Here are the available priorities:
Blocks on this queue will be scheduled to run before those on all other lower-priority queues.
Blocks on this queue will be scheduled to run after those on high-priority queues, but before blocks on low-priority queues.
Blocks on this queue will be scheduled to run after those on all other higher-priority queues.
The same as PRIORITY_LOW, but the system will dedicate even fewer resources to it.
When you create a dispatch group with dispatch_group_create, you add one or more blocks to it. You can also add a notification block, which is run immediately after all blocks in the dispatch group have finished running. It's generally good practice to put the notification block on the main queue, so that it's easier to coordinate with other parts of your game's engine.
Adding Unit Tests to Your Game
You want to test different parts of your game's code in isolation, so that you can ensure that each part is working.
You can write code that tests different parts of your app in isolation using unit tests. By default, all newly created projects come with an empty set of unit tests, in which you can add isolated testing functions.
If you're working with an existing project, you can create a new set of unit tests by choosing File→New→Target and creating a Cocoa Touch Unit Testing Bundle.
You'll find your unit test files in a group whose name ends with Tests. For example, if your Xcode project is called MyAwesomeGame, your testing files will be in a group named MyAwesomeGameTests, and it will by default come with a file called MyAwesomeGameTests.m.
When you want to add a test, open your test file (the .m file) and add a method whose name begins with test:
- (void) testDoingSomethingCool {
SomeAwesomeObject* object = [[SomeAwesomeObject alloc] init];
BOOL succeeded = [object doSomethingCool];
if (succeeded == NO) {
XCTFail("Failed to do something cool");
When you want to run the tests, choose Product→Test or press Command-U. All of the methods in your testing classes that begin with test will be run, one after the other.
You can also add additional collections of tests, by creating a new test suite. You do this by choosing File→New→File and creating a new Objective-C test case class. When you create this new class, don't forget to make it belong to your testing target instead of your game target, or you'll get compile errors.
Unit testing is the practice of writing small tests that test specific features of your code. In normal use, your code is used in a variety of ways, and if there's a bug, it can be difficult to track down exactly why your code isn't behaving the way you want it to. By using unit tests, you can run multiple tests of your code and check each time to see if the results are what you expect. If a test fails, then the parts of your game that use your code in that particular way will also fail.
Each test is actually a method in a test case. Test cases are subclasses of XCTestCase whose names begin with test. The XCTestCase objects in a testing bundle make up a test suite, which is what's run when you tell Xcode to test your application.
When tests run, Xcode performs the following tasks for each test method, in each test case, in each test suite:
§ Call the test case's setUp method.
§ Call the test method itself, and note if the test succeeds or fails.
§ Call the test case's tearDown method.
§ Show a report showing which tests failed.
As you can see, the test case's setUp and tearDown methods are called for each test method. The idea behind this is that you use setUp to create whatever conditions you want to run your test under (e.g., if you're testing the behavior of an AI, you could use setUp to load the level that the AI needs to operate in). Conversely, the tearDown method is used to dismantle whatever resources are set up in setUp. This means that each time a test method is run, it's operating under the same conditions.
The contents of each test method are entirely up to you. Typically, you create objects that you want to test, run methods, and then check to see if the outcomes were what you expected. The actual way that you check the outcomes is through a collection of dedicated assertion methods, which flag the test as failing if the condition you pass in evaluates to false. The assertion methods also take a string parameter, which is shown to the user if the test fails.
For example:
// Fails if X is not nil
XCTAssertNil(X, @"X should be nil");
// Fails if X IS nil
XCTAssertNotNil(X, @"X should not be nil");
// Fails if X is not true
XCTAssertTrue(1 == 1, @"1 really should be equal to 1");
// Fails if X is not false
XCTAssertFalse(2 != 3, @"In this universe, 2 equals 3 apparently");
// Fails if X and Y are not equal (tested by calling [X equals:Y])
XCTAssertEqualObjects(@(2), @(1+1), @"Objects should be equal");
// Fails if X and Y ARE equal (tested by calling [X equals:Y])
XCTAssertNotEqualObjects(@"One", @"1", @"Objects should not be equal");
// Fails, regardless of circumstances
XCTFail("Everything is broken");
There are several other assertion methods available for you to use that won't fit in this book; for a comprehensive list, see the file XCTestAssertions.h (press Command-Shift-O and type XCTestAssertions then press Enter).
2D Grids
You want to store objects in a two-dimensional grid.
Figure 1-5. The grid: a digital frontier
Use a Grid class, which lets you store and look up objects.
Create an NSObject subclass called Grid, and put the following code in Grid.h:
#import <Foundation/Foundation.h>
// Grid points are just integers defining the location of an object
typedef struct {
int x;
int y;
} GridPoint;
enum {GridPointNotValid = INT_MAX};
@interface Grid : NSObject
// Returns the list of objects that occupy the given position
- (NSArray*) objectsAtPosition:(GridPoint)position;
// Returns a GridPoint describing the position of an object
- (GridPoint) positionForObject:(id)objectToFind;
// Adds or move the object to a location on the board
- (void) addObject:(id)object atPosition:(GridPoint)position;
// Removes a given object from the board
- (void) removeObjectFromGrid:(id)object;
// Removes all objects at a given point from the board
- (void) removeAllObjectsAtPosition:(GridPoint)position;
// Removes all objects from the board.
- (void) removeAllObjects;
Then, put the following code in Grid.m:
#import "Grid.h"
@implementation Grid {
NSMutableDictionary* _grid;
- (id)init
if((self = [super init]))
// Create the dictionary that maps all objects to locations
_grid = [[NSMutableDictionary alloc] init];
return self;
// Returns an NSString given a point. For example, the location (1,2)
// is turned into "1-2".
- (NSString*) keyForGridPoint:(GridPoint)position {
return [NSString stringWithFormat:@"%i-%i", position.x, position.y];
// Returns a GridPoint given a key. The string "1-2" is turned into (1,2).
- (GridPoint) gridPointForKey:(NSString*)key {
// Split the string into two
NSArray* components = [key componentsSeparatedByString:@"-"];
// Check to see if there are exactly two components; if not, it's not
// a valid grid point and so return (GridPointNotValid,GridPointNotValid).
if (components.count != 2)
return (GridPoint){GridPointNotValid,GridPointNotValid};
// Construct and return the grid point
return (GridPoint){[components[0] intValue], [components[1] intValue]};
// Returns the array containing all objects at a given position
- (NSArray*) objectsAtPosition:(GridPoint)position {
NSString* key = [self keyForGridPoint:position];
return [_grid objectForKey:key];
// Returns the array containing a specific object
- (NSMutableArray*) arrayContainingObject:(id)object {
for (NSMutableArray* array in _grid) {
if ([array containsObject:object])
return array;
return nil;
// Returns the GridPoint for an object on the board
- (GridPoint) positionForObject:(id)objectToFind {
// Find the array containing this object
NSArray* arrayWithObject = [self arrayContainingObject:objectToFind];
// Find the key associated with this array
NSString* key = [[_grid allKeysForObject:arrayWithObject] lastObject];
// Convert the key into a grid point and return it
return [self gridPointForKey:key];
// Adds an object to the board. It's moved from its previous location
// if necessary.
- (void) addObject:(id)object atPosition:(GridPoint)position {
// First, remove the object from its current location
[self removeObjectFromGrid:object];
// Next, work out which array it should go in. If no suitable array exists,
// create a new one.
NSString* key = [self keyForGridPoint:position];
NSMutableArray* foundArray = [_grid objectForKey:key];
if (foundArray == nil) {
foundArray = [NSMutableArray array];
[_grid setObject:foundArray forKey:key];
// Finally, add the object if it doesn't already exist.
if ([foundArray containsObject:object] == NO) {
[foundArray addObject:object];
// Removes an object from the board.
- (void) removeObjectFromGrid:(id)object {
NSMutableArray* arrayContainingObject = [self arrayContainingObject:object];
[arrayContainingObject removeObject:object];
// Removes all objects from a position on the board.
- (void) removeAllObjectsAtPosition:(GridPoint)position {
[_grid removeObjectForKey:[self keyForGridPoint:position]];
// Removes all objects.
- (void) removeAllObjects {
// Blow away the existing dictionary and replace it with an empty one.
_grid = [NSMutableDictionary dictionary];
When working with 2D grids, you usually have two main tasks that you want to perform with it:
§ You have a game object on the board, and want to work out where on the board it is.
§ You have a location on the board, and you want to work out what object (or objects) are at that point on the board.
This Grid class doesn't require that you limit the board to a pre-defined size. Any location works, as long the number doesn't exceeed the integer limit (that is, −2,147,483,648 to 2,147,483,647).
This class implements grids by using an NSDictionary to map locations to mutable arrays of objects. When you add a piece to the board, the class works out which array should contain the object (and creates one if necessary) and inserts it. Later, when you want to get the objects at a given location, it simply looks up the location in the dictionary.
For small boards (for example, those with a size of about 14×14), you can get away with a simple implementation. However, this implementation will slow down when you start having larger boards (especially with many objects on the board). In those cases, you'd be better off creating multiple dictionaries for different areas of the board (for example, one for the upper-left corner, one for the top-right, and so on). This improves the lookup speed of getting objects at a location, though it complicates your implementation.


text:
Fabric Online
Hi All
Does anyone else by fabric online? I'm looking for sites that do cute/kawaii/kitsch/quirky designer fabrics- Either UK sites or USA sites would be great if anyone has a favourite? Please recommend! ^__^
I've used http://fabricrehab.co.uk/ once, or twice (or possibly more often ... but don't tell anyone!)
They have a great selection, their customer service is great and delivery to the uk is only £2 no matter what size your order!
I buy about 90% of my fabric online because I can never find what i am looking for at Joanns (the only fabric selling store in my town). I use Ebay. This is my favorite seller: http://stores.ebay.com/neverenoughfabric. They have very cute kawaii, hello kitty, and skelanimal prints.
Spoonflower is amazing! You can design your own or buy someone else's design. It's not cheap, but you can find things there that you can't find anywhere else (and you can choose the fabric that the design is printed on).
thanks folks!
Sign up
We'd love to know what you think - Leave your reply right away

subset: commoncrawl


text:
Loans Direct
Suite 19, 17-19 Miles Street, Melbourne, VIC 3170
Harry Goyal
Loans Direct is the expert financial solutions provider in Australia, serving its clients from multiple locations at Sydney, Melbourne, Adelaide, Canberra, Darwin, Hobart, Perth and Brisbane. With the great experience of 8 years & success rate of 90%, Loans Direct is providing various types of money-saving loans, credit repair services & business financial solutions here.
5 out of 5 from 1 reviews


text:
This cute mini bag is a fashion-forward accessory that would have you feeling like the trendy woman you are.
The outside is made of dyed sisal fiber and the inside is a beautiful ankara lining. This sisal mini bag is woven by women from the Akamba community in Kenya.
Dimensions : 6in.(Top width) x 5in. ( Bottom Width) x 5.5in. (Height).
Top Handle drop: 4 in.
Gold/Silver-toned hardware
Interior Details: Beautiful Ankara Lining with Back Zip Pocket & Front Slip Pocket


text:
The Vape Station Vape Shop based in Hampden 01036 MA
The Vape Station Vape Wholesale in Hampden 01036 MA . Shop CBD Bath, Beauty and Skincare Products, vape juice by premium manufacturers such as Thomas & Knowles Made In UK E-liquid, Lazer Wolf eLiquid as well as Saucy Sweets Salts
Understand The Difference As Well As Resemblances In Between CBD Edibles And Also Capsules
Individuals looking for a non-addictive alternative for discomfort, anxiety, inflammation, and also anxiety monitoring can consider CBD. CBD is capable of lowering signs and symptoms. Choosing an option to pharmaceutical pain reliever and also antidepressants was straightforward, yet which is far better-- CBD capsules or edibles... a difficult concern. Thankfully, you can think about the benefits and drawbacks to determine.
CBD pills vs. edibles Interpretation
On the other hand, CBD edibles are food prepared from cannabidiol oil. Edibles can be made from CBD full-spectrum, broad-spectrum, and also isolate.
Edibles get soaked up throughout digestion and can take a hr to experience the result. The effect will last for 5 to 6 hrs. Because gel cap liquifies successfully plus there are check over here no other ingredients needed to absorb, pills obtain taken in a little faster than the CBD gummies. The time taken to kick in is around 1 hr as well as impacts last for 4 to 6 hrs.
CBD hinders the liver's cytochrome P450 enzyme system. When you try CBD, talk to your medical professional to avoid adverse communications.
Cannabidiol oil is included in the dish. Keep in mind, it is not a replacement for cooking oil, so maintain dosages small. You are in control! When you start with CBD edibles, begin low and also go slow. Allow the edible an hour to get absorbed, after that figure out if you need to boost or decrease the dosage.
CBD capsule dosing corresponds, regularly. this hyperlink They are simply like any other supplements or vitamins, which can be added conveniently to your health regimen. Every capsule uses an exact CBD dosage. You can check the bottle's label to get a suggestion of CBD milligrams in every pill. Start reduced and await one hr to experience the result, then make a decision to alter your dosage.
You can prepare with CBD instilled oil in your home but find out exactly how to locate the ideal dosing and parts. When you prepare with CBD oil makes sure to cook on low-temperature or simply include it to the prepared food or salad. Heats can degrade the CBD oil top quality, so be careful! The finest suggestion is to utilize CBD in topping or topping or plating. Be precise with a dropper to recognize the quantity of CBD in every part.
Clinical condition monitoring
Edibles can handle Alzheimer's, Crohn's disease, chronic discomfort, digestive system problems, and also conditions in children. Edibles are a lot more pleasurable for those that find it difficult to ingest the tablets. CBD pills aid to manage joint inflammation, anxiousness, epilepsy, diabetes mellitus, and obesity.
Which is better?
The choice of selecting a CBD pill or edible is individual. Then pick pills, if you are a diabetic individual. Youngsters will certainly locate edibles less intimidating than capsules.
Determining a choice to pharmaceutical discomfort killers as well as antidepressants was straightforward, yet which is much better-- CBD pills or edibles... Capsules are infused with hemp-based pure CBD oil. On the other hand, CBD edibles are food prepared from cannabidiol oil. Edibles can be made my link from CBD isolate, broad-spectrum, and also full-spectrum.
When you begin with CBD edibles, start reduced and go slow-moving.
This can be an 70% PG e-liquid, designed only to be used with mouth to lung vape Clown eLiquid Made In USA E-liquid kits, which include pod kits and vape starter kits. developing a discreet number of cloud, thanks to the PG concentration you can practical experience clearer flavour.
Burley Tobacco: wealthy and strong, this no-nonsense tobacco eliquid truly packs a punch. Available to be a fifty/fifty liquid, it is possible to love a clean Burley in almost any tank and with any coil.
Rolling Leaf: 88Vape's best-promoting tobacco flavour, this provides the heady toasted tang that reformed smokers pass up much. linked here Safer than smoking and at just £1 a bottle, Rolling Leaf tobacco e-liquid is far more affordable also!
far more importantly, our e-liquids are scrumptious and our knowledgeable vape employees are generally focusing on enjoyable new formulations to not simply keep up Together with the market, but to generally be the business leaders.
For example, we've got around forty five flavours in our small fill e liquid selection and it's continuing to grow. We're with a mission to vary perceptions and judging from the comments we get, we're accomplishing exactly that.
Switching to vaping from smoking will cut out lots of tar, many chemicals, and lots of perilous compounds. But Additionally, it lets you control precisely how much nicotine you're taking into One's body. With our 3mg e-liquid assortment, you'll be capable to keep the nicotine levels reduced as well as your style ranges large.
A:It can be constantly excellent to possess solutions. the objective of cigarette is being served whilst getting flavors besides tobacco.
presenting wonderfully contemporary flavour, the many benefits of nic salts and a gorgeous price tag tag, Menthol by 88Vape Nic strike is undoubtedly an exciting proposition.
VG stands for vegetable glycerin. It's one of many principal bases for eliquids (together with with PG). VG contains a thicker consistency than PG and sweeter taste. VG also gives bigger vapour clouds. superior VG liquids are commonly utilized for sub-ohm vaping.
Our totally free United kingdom supply service will typically signify that your get will arrive the working day after you location the get if positioned amongst Monday and Friday just before 4pm, nonetheless, over the scarce event, orders may choose for a longer period to reach.
When you are experiencing complications, dizziness and nausea you're most likely intaking an excessive amount nicotine. If this is now a problem, try out choosing a lower nicotine dosage. If you are working with liquid with 18mg nicotine energy, consider switching to 11mg or 6mg liquid.
88Vape E Liquids are designed in a very function-constructed facility which allows the crew to provide Fantastic good quality. This also means that they are in a position to produce their particular flavours in-house.
If you have frequently discovered menthol vapes for being a little bit far too severe, salt nicotine may be the solution and it is actually absorbed promptly to provide you with rapid gratification.
there are go here numerous e liquid additional info producers that may have equivalent manufacturing expenditures, but then market for an increased value that matches the "market place benefit". we do not. We just desire to promote extra and give everyone cost-effective use of the merchandise they need to have.


text:
Universal Pictures and Illumination have dropped the official trailer for Minions: The Rise of Gru, the sequel to Minions. The movie is all set to hit the theatre screens in July.
The film serves as a continuation of the 2015 film Minions, and features Minions (Pierre Coffin) first encounter with a young felonious Gru (Steve Carell), a 12-year-old with a dream to become the world's greatest supervillain.
Here's the official synopsis:
Long before he becomes the master of evil, Gru is just a 12-year-old boy in 1970s suburbia, plotting to take over the world from his basement … It's not going particularly well. When Gru crosses paths with the Minions, including Kevin, Stuart, Bob and Otto — a new Minion sporting braces and a desperate need to please — this unexpected family joins forces. Together, they build their first lair, design their first weapons, and strive to execute their first missions.
The voice cast features Jean-Claude Van Damme as the nihilistic Jean Clawed, who's armed (literally) with a giant robotic claw; Lucy Lawless as Nunchuck; Dolph Lundgren as Swedish roller-skate champion Svengeance, and Danny Trejo as Stronghold, Russell Brand as Young Dr. Nefario, and Oscar winner Julie Andrews as Gru's maddeningly self-absorbed mom. Pierre Coffin returns as the iconic voice of the Minions.
Minions: The Rise of Gru is produced by Illumination founder and CEO Chris Meledandri, Janet Healy and Chris Renaud. The film is directed by returning franchise filmmaker Kyle Balda, co-directed by Brad Ableson and Jonathan del Val.
Minions: The Rise of Gru will hit theaters on 1 July 2022.


text: Top Stories 150 unionised GTT employees to receive salary increases July 24, 2021 The Labour Ministry on Friday facilitated the signing of a Collective Labour Agreement between the Guyana Telephone and Telegraph Company (GT&T) and the Guyana Postal and Telecommunications Workers Union (GPTWU) which will see some 150 unionised workers benefitting from a salary increase. During the simple signing ceremony that was held at the Ministry's Boardroom on Brickdam, Georgetown, it was announced that 150 unionised employees will benefit from a four and six per cent raise in salary and wages. This will be facilitated through agreement between GTT and the Guyana Postal and Telecommunications Workers Union. The agreement will cover a period of two years from October 2020 to September 2021, and October 2021 to September 2022 with a review within the next six months. GTT and GPTWU representatives after the signing Chief Labour Officer, Michelle Baburam said she is pleased that both GTT and the Union were able to come to an agreement on this matter. "When I first took over the matter, they were at zero, one and two per cent being offered by GTT and then they went back to bilateral. They came back… and when I took over, they were in the conciliarity process. I had two meetings with them that brought to closure this matter of wages and salaries, where GTT would have moved from the two per cent to four and six per cent." Baburam said even with this agreement she is hopeful that in another six months, both parties can see some improvements and come to another consensus on another percentage. In response, Union Leader of the Guyana Postal and Telecommunications Workers Union Harold Shepherd said the process had commenced earlier this year during the bilateral discussions, and they were able to have a resolution. "The issue was referred to Labour for conciliation, and we are happy with the input of the Chief Labour Officer (acting), and more so the new Chief Executive Officer of the Guyana Telephone and Telegraph Company. The very first meeting here with him were able to reach the position in which we were able to agree to a four per cent increase on the basis salary for the GTT unionised members." "We are all aware that cost of living has skyrocketed over the last few months and obviously our membership at GTT, they have to face the market like anybody else and it is a welcome move by the company," he explained. Shepard further related that he understands the challenges faced by workers and as such, the Union is prepared to work with the company for the betterment of the organisation and its members. He added too, that even though they did not get what they had initially wanted, which is a 14 per cent increase, he is happy that they got something that they can work with.


text:
17th International Conference on Software and System Processes
The Schedule of ICSSP 2023 is up. ICSSP 2023 will feature three Keynotes from distinguished speakers on topics of AI-Augmented Software Engineering, Business Process Management, and AI-integrated Agile. The list of Accepted Papers are available. When registering for participation, please select ICSSP under co-located events. We look forward to your participation!
new! TechDebt & ICSSP Social Function will take place on Sunday 14 May 18:00 - 21:00 at BoHo South Wharf. The event will include dinner and a 3 hour beverage package (no spirits).
The theme of ICSSP 2023 is Software and System Processes for and with Emerging Technologies.
ICSSP 2023 will be held on 14-15 May 2023, and co-located with ICSE 2023.
A by-invitation workshop will be held on 13 May 2023.
Please use the contact form to contact PC Chairs.
About ICSSP Conference Series
ICSSP 2023 is the 17th in a series of ICSSP conferences that have been organized by the International Software and Systems Process Association (ISSPA) or its predecessor, the International Software Process Association (ISPA). The ICSSP series grew out of two earlier and partly overlapping series, the International Conferences on Software Process (ICSP), dating back to 1991, and the International Software Process Workshops (ISPW), dating back to 1984.
Recent ICSSP conferences have mostly been organized with or around ICSE, with proceedings published by ACM or IEEE. The 2021 and 2022 conferences were co-organized with the International Conference on Global Software Engineering (ICGSE), and ICSSP 2022 was co-sponsored and co-organized with the Carnegie Mellon University Software Engineering Institute. For the 2023 ICSSP, the ISSPA is pleased to be joining forces with representatives of CSRIO's Data61 unit, the data and digital specialist arm of Australia's national science agency.
About ICSSP 2023
In recent years, innovative software and systems technologies have been rapidly adopted with increasingly widespread but uncertain impacts. These technologies include various forms of AI; big data and data science; blockchain and distributed ledgers; augmented, virtual, and extended reality; low-code/no-code platforms; and even quantum computing (among others). By their novel nature, these new technologies and applications demand new approaches to software and systems development. Beyond that, the novelty and uncertainty surrounding these technologies and applications requires new and more effective approaches and processes to assuring correctness, understandability, predictability, responsibility, security, ethics and other vital qualities of our software and systems.
At the same time, many of these new technologies may have applications within the software life cycle. So the question naturally arises, can we put technologies such as AI, blockchain, low code, and big data, to work in improving our ability to develop, manage, and apply new software and systems applications. We can even ask whether it will become essential to do so.
ICSSP 2023 is focusing on software and systems processes for and with these new technologies, as well as on incorporating these new technologies into new modes of working in software and systems development for business, government, society, and the environment. ICSSP 2023 aims to bring together researchers and practitioners to share their research findings, experiences, and new ideas on diverse topics related to software and system processes. For 2023, the theme of the conference is: "Software and System Processes for and with Emerging Technologies". The goal is to advance both the state of the research and the state of the practice by applying innovative ideas from different fields of research to the future of software and system engineering processes.


text:
Monday 27th November 2023
Report written by Nicky Woodall (she/her)
😁 21 brilliant Goodgymmers gathered for this evening's group run, cited as possibly one of the most random and/or mudtastic yet. More on that later though.
🌧 Sadly, the weather wasn't quite as good as we might have hoped but we've never let that put us off!
🍮 Ed led the warm up where we got our mouths watering discussing our favourite puddings, in honour of national cream pie day. Winter classics such as crumble and sticky toffee pudding (with a variety of accompaniments) made the cut, along with some inspired by recent baking activity (cinnamon buns or white chocolate and ginger cheesecake, anyone?)
🏃♀🏃♂With our legs warm and our stomachs rumbling, Ed led the running group to West Bank Park whilst Abi led the walkers.
🌹 On arrival, Kristina gave us our expected compost-shovelling instructions for the new flowerbeds in the rose garden, along with some unexpected bonus tasks. Martin and Stef leapt into the skip to start shovelling from there into the first barrows. Meanwhile, Kristina took a few people with her to construct temporary barrow paths with cardboard.
⚽ She also sent some people to the goalposts on the football pitch with tampers to commence one of our more unusual tasks, something that was fondly named "wet mud flooring" (as opposed to dry stone walling). Once the barrowers had dropped off their compost at the new flowerbeds in the rose garden, they collected "turf" (mostly mud with the odd blade of grass) and barrowed that back to the football pitch. The ground around one goal mouth in particular was particularly sloppy so Team Tamp were charged with laying/tessellating the pieces of turf and tamping it down to form a new (and slightly less sloppy) layer on top.
🤔 Whilst some doubt was expressed when some water started soaking upwards through the new layer, Kristina reassured us that this is a tried and tested technique that will improve the ground. Whilst our housemates may not have appreciated the next level mud attached to the tampers' trainers, hopefully the footballers will appreciate their efforts.
💪 Soon, it was time to down tools and do a quick couple of rounds of "Meet and Retreat" for fitness before we headed back to base, stamping mud off en route.
🙌 Thanks everyone, and don't forget that Kristina's kindly letting us have the final compost scrapings for our Tiny Forest on Kimberlow Hill. So if you've got any spare time 11-12 on either Thursday morning or Friday morning please join Claire to help gather this invaluable resource!
Provide the public with green open space and play facilities
See morePlanet Food is a zero food waste community helping to break social isolation by bringing people together for food & drink..


text:
Utah Sweet Savings may earn a small commission via affiliate links in this post. Read our full disclosure policy here.
Grab this Ryobi 18-Volt Cordless Leaf Blower/Sweeper on a special buy price of $49.88 (Regularly $79.97). Choose to pick it up in store or have it shipped free to your store if it's not in stock. Buy this online before they sell out!
Ryobi 18-Volt Cordless Leaf Blower/Sweeper $49.88 (Regularly $79.97)


text:
Best Vitamin To Prevent Mosquito Bites
Nowadays, there are so many products of vitamin to prevent mosquito bites in the market and you are wondering to choose a best one.You have searched for vitamin to prevent mosquito bites in many merchants, compared about products prices & reviews before deciding to buy them.
You are in RIGHT PLACE.
Here are some of best sellings vitamin to prevent mosquito bites which we would like to recommend with high customer review ratings to guide you on quality & popularity of each items.
100% Natural & Organic Vitamin E Oil For Your Face & Skin, Unscented – 15,000/30,000 IU – Heals Stretch Marks & Surgical Scars. Essential Drops Lighter Than Cream or Gel. Raw Vit E Extract Sunflower.
Mosquito Repellent Patch 120 Count , Insect Repellent Resealable Stickers with 2 Bracelet – Non-Toxic, Nature Citronella, Lemongrass and Eucalyptus, Up To 24 Hour of Protection, Apply To Skin and Clot
- ✓100% Natural Materials - Our Insect repellent patch are made of 100% Natural citronella, Lemongrass and Geraniol essential oils, NON-toxic, deet-free, no chemical smell. Protecting your skin from bite without harmful chemicals, safety and healthy.
- ✓Lasting Protection - Healthy insect repellents keep mosquitoes away from you and your family. Each lasts up to 24 hours. The sticker come with high-quality sealed bag to preserve effectiveness when not in use.
Made from nature ingredients, these mosquito patches and bracelets can help keep the mosquitoes away from your loved ones.Enjoy the outdoors again!
Whether you're camping, fishing, garden barbecues, hiking, holding a party, family vacation or even just walking your pet, Our Mosquito Repellent Patches and Bands will protect you, your family and pets from mosquitoes, insects and pests.
Package Includes:
6 counts stickers per sheet, one sheet is individual wrapped in Aluminum foil bag.
Each mosquito repellent bracelet is individually wrapped in a resealable bag.
Long lasting Effective
Each Patch is most effective over a 72 hours period. from the moment you open the bag.
Each band will stay effective for up to 250 hours (10 days) from the moment you open the bag.
100% Natural Essential Oils, DEET FREE
– insect repellent bracelets are made with natural essential oils: Citronella oil Lemongrass Oil and Eucalyptus oil.
Warm tips:
Please keep out of reach of children to avoid eating.
For sensitive skin, please do not stick directly to the skin.
Natural Bite Relief Spray by BITE CARE I 100 ml I 100% Organic & Natural Insect Repellent Spray I Instantly Soothes bites, itches and redness I Alternative to Bug Powder and Insect Killer Spray
- ???? EFFECTIVE: This spray is very effective due to its essential ingredients including aloe vera & citrus oil. Immediate & quick relief from mosquito bites, wasps, bees, fleas and insects
- ???? MULTIPURPOSE: This spray relieves you from stings & bites. Furthermore, our BITE CARE can also be used in case of rashes, redness, itching & sunburn. Ideal for sensitive skin
- ???? NATURAL & ORGANIC: Aloe vera has an anti-inflammatory and moisturizing effect while vitamin E & lemon oil relieves from pain & itching. The perfect pain relief product for your bites
Bite Relief Spray by BITE CARE – Quick & Effective pain relief!
Who doesn't experience it, annoying stings from mosquitoes, wasps, bees,
fleas, ticks, and other insects? In order to prevent any further skin issues,
caused by bugs & other insects, we developed Bite Care. With this Bite Care
spray you immediately experience a relief regarding itches & irritations. The
quick reaction that our spray has on the skin in terms of reducing rashes and
redness comes due to its natural ingredients. Furthermore, essential oils such
as lemon oil, aloe vera & vitamin e ensure exclusively organic & vegan
additives while being suitable for all ages, whether young or old. Bite Care is
an all-natural bite relief spray containing Aloe Vera and Lemon oil to help calm
and soothe the skin from itches and redness caused by insect bites, allergic
reactions, and mild sunburn. Due to its practical packaging, this product can be
easily carried around, either at home or on your way to work – Because your
skin deserves it!
Bite Relief Spray by BITE CARE is:
???? A bite & sting reliever
???? Natural & Organic
???? Free from animal cruelty
???? Made in Germany
Shake well before use. Adults and children older than 3 years of age spray
directly on the bite or sting, rub gently and re-apply if needed. Consult a
doctor if symptoms worsen or last more than 7 days.
Aqua, Aloe Vera, Citrus Oil, Isopropyl
Skedattle – Natural Bug Spray | Non-Toxic, Chemical-Free Insect Repellent with Lemongrass and Essential Oils | Protection from Mosquitos, Ticks, Gnats | Safe for Kids and Pets
- ???? DEET-FREE, NATURAL BUG SPRAY - 100% All-Natural formula with no harsh chemicals or artificial fragrances. Skedattle is a safe alternative to potentially harmful insect repellent. We made sure our formula is perfect for sensitive skin, children, and even your pets!
- ???? HARNESS THE POWER OF ESSENTIAL OILS - Our lab-tested, powerfully effective combination of citronella, lemongrass, peppermint, and vanillin safely repels pesky bugs and has a pleasantly fresh scent.


text:
Home › Forums › Gutenberg › Block displaying another page's block?
I have a custom block called 'featured-content-row'.
I want to pull the content from that block on another page into this page, i/e about page content to home page blocks.
I've setup a block called 'featured-content-row-pull' where you can choose a pages ID as well as a title element from the block I'm targeting. This is to ensure it doesn't show all elements of that pages blocks, just the one i want.
It runs fine with the following…
<?php //Vars $page_choice = get_field( 'page_choice' ); $page_choice_row_title = get_field( 'page_choice_row_title' ); $post_id = $page_choice ; $row_title = $page_choice_row_title; $post = get_post($post_id); $blocks = parse_blocks($post->post_content); foreach($blocks as $block){ if( $block['blockName'] == 'acf/featured-content-row' && $block['attrs']['data']['site_row_title'] == $row_title ){ echo render_block($block); } } ?>
However, i get the following notice…
Notice: Undefined index: id in /local:5757/wp-content/plugins/advanced-custom-fields-pro/pro/blocks.php on line 395
I'm assuming this is because a block is appearing within a block and it doesn't like the mixing of IDs anything i can do?
You must be logged in to reply to this topic.
Welcome to the Advanced Custom Fields community forum.
Browse through ideas, snippets of code, questions and answers between fellow ACF users
Open a new forum thread
Helping others is a great way to earn karma, gain badges and help ACF development!
We use cookies to offer you a better browsing experience, analyze site traffic and personalize content. Read about how we use cookies and how you can control them in our Cookie Policy. If you continue to use this site, you consent to our use of cookies.


text:
Customizable TOC Ready Index Multicolor Dividers, Jan-Dec, Letter
Item #
Mfr. Model #
Organized documentation makes a business run like a well-oiled machine. These Ready Index® Table of Contents Dividers help you stay organized so you can locate documents quickly and efficiently. They feature preprinted multicolor tabs that can be displayed in either landscape or portrait format. Using free templates from Avery Design & Print you can customize the included table of contents page and print in minutes. Organization and efficiency—makes life better for your business. For laser and inkjet printers. Contemporary Colors. Index Divider Style: Monthly; Index Divider Size: 11 x 8.5; Punched/Unpunched: 3-Hole Punched; For Use With: Ring Binders.
- Organize your documents quickly and easily, no tab inserts or labels needed.
- Double-sided section titles page and tab dividers can be used in portrait or landscape orientation.
- Customize with a logo, name, date or project title to the left of section titles.
- Heavyweight paper with double-sided reinforced holes and extended tab reinforcements for added durability.
- Customize with free templates and designs from Avery Design & Print.
- For laser and inkjet printers.
Accessory Type | Index Dividers |
Brand Name | AVERY PRODUCTS |
Brand Part Number | 11847 |
Color | White |
For Use With | Ring Binders |
Length | 11" |
Material | Paper |
Number of Punched Holes | 3 Holes |
Recycled Content | Not Recycled |
Recycled Percentage | 0 |
Tab Message | Monthly |
Tab Orientation | Side |
Tabs per Set | 12 Tab |
Total Sets | 1 Set |
Width | 8-1/2" |
set of 12
Expected to ship Wed. Mar 06


text:
Legislative Reference Library
Texas Legislators: Past & Present
Archibald C. Hyde
Full Name: Archibald C. Hyde
Birth date: 1813
Death date: January 12, 1894
Terms of Service
Senate, 8th
& 7th
11/2/1857 - 11/4/1861
(1) Entire Senate went up for reelection due to Senatorial redistricting. Act passed Feb. 6, 1860, 8th Legislature, ch. 45,
Apportionment Laws of Texas, 1836-1950
(2) Listed in "New Senators elected: Democrats."
Civilian and Gazette. Weekly.
(Galveston, Texas), 9/8/1857, p. 2, crediting Dolph Briscoe Center for American History.
Portal to Texas History (University of North Texas Libraries)
(3) 7th Legislature - Roll of Senators elected since the last adjournment called by Districts, oath of office administered, 11/2/1857, p. 1.
Senate Journal
(4) 8th Legislature, Regular Session - Roll of Senators (holdover senators), 11/7/1859, p. 4.
Senate Journal
Biographical Notes and Resources
Resolutions and Journal entries
Estimated birth year based on age at beginning of 7th Legislature, Member List, pp. 679-685.
Senate Journal
Archibald C. Hyde,
Texas Album of the Eighth Legislature
Other Resources
United States Army, Company F, 3rd Texas Mounted Rangers. Mexican War, Archibald C. Hyde, pension filed 3/15/1887.
FamilySearch, United States Mexican War Pension Index, 1887-1926
Death notice, "A Texas Veteran,"
The Galveston Daily News
, 1/13/1894, p. 1, crediting Abilene Library Consortium. "He represented the El Paso district in the state senate." Death date 1/12/1894.
Portal to Texas History (University of North Texas Libraries)
Became Chief Justice of El Paso County on 8/20/1850, p. 18. Timmons, W.H. "American El Paso: The Formative Years, 1848-1854," Vol. 87, No. 1, July 1983, pp. 1-36.
Southwestern Historical Quarterly
Legislation re. land grant "to Juan Maria Ponce de Leon two caballerias of land, called 'El Rancho de Ponce,' now known as the Town of Franklin," p. 83. Yeilding, Kenneth Duane.
The Chamizal Dispute: An Exercise in Arbitration: 1845-1945
, A Dissertation in History, May 1973.
Texas Tech University Libraries
Biographical sketch, p. 76 (died in January, 1894, near Elmendorft, Texas); chief justice, 34; in El Paso, 45, 52; at Magoffin's ranch, 53; notary, 60; county judge ("El Paso County's second county judge was Archibald C. Hyde, who was born near Norwich, Connecticut, in 1813"), 61; at San Elizario, 65; property seized, 80-81; return to El Paso, 166.
The Legal Heritage of El Paso
Committee Information
8th R.S. - 1859
Claims and Accounts
Counties and County Boundaries
Indian Affairs
Private Land Claims
Public Debt
7th R.S. - 1857
Counties and County Boundaries
Indian Affairs
Public Debt
San Saba County, Memorials Regarding Indian Depredations
LRL Home
View full site


text:
Tagged in
Change is hard when it involves the ones we love
Hello Spark parents! Welcome to Session 2!
I had a good reminder this week that I am extremely blessed to be at Aim ever...
I'm the founder and Head of School at Aim Academy.
We'd love to hear from you. Schedule a call below:


text:
There are a lot of beautiful things on this green earth, but few are as beautiful as that of the equestrian farm amongst a slew of rolling hills and valleys. It doesn't matter where you are in the world, a well-kept farm with lively horses grazing at their leisure Continue reading
Trail riding on horseback has become quite popular over the years, making it a family fun activity for everyone to enjoy. Winter, Spring, Fall or Summer makes horseback riding enjoyable because the weather is usually mild. And what better place Continue reading
Buying and owning a horse farm can be a lifetime dream for some. When making the decision to purchase a horse farm there are many expenses to consider besides purchasing the property. Such as how much land is needed per horse, fences to build, barns to design if one is not located on property, farmhands to pay if needed, horse feed, vet costs, or true value of the land. Continue reading


text:
We're Happy, Free, Confused, and Lonely at the Same Time: Taylor Swift Returns with Red (Taylor's Version)
December 12, 2021
More than 9 years ago, in 2012, singer and songwriter Taylor Swift released her 4th studio album, Red. This was Swift's step away from country to a more pop-infused sound and featured hit songs "We Are Never Ever Getting Back Together" and "I Knew You Were Trouble." The album was praised by critics and fans alike for its songwriting and was also recognized at a multitude of award shows, with a nod from the Grammy's for an Album of the Year nomination. It has also been featured on many end-of-decade lists.
Now she's back for more.
In June 2019, it was reported that Scooter Braun, a Hollywood manager, had bought the masters of Swift's music without her knowledge. When offered co-ownership, she turned it down and announced that she would be re-recording her first 6 albums. She started with the re-release of Fearless (Taylor's Version), her sophomore album, in April 2021. She continues with Red.
We start with "State of Grace," a euphoric anthem, where powerful drums and dynamic guitar plucks accompany Swift's lyrics of the highs and lows of new love. This re-recorded song sets the tone for the album; a much more clean and mature sound compared to the original. "We Are Never Getting Back Together," "I Knew You Were Trouble," and "22" are fierce pop melodies that she's become known for, while "I Almost Do" and "Begin Again" are reminiscent of her country roots.
Red also showcases Taylor Swift's songwriting artistry. The tracks "Treacherous" and "Holy Ground" portray intricate lyrics of heartbreak and recovery, something that is a major theme in Swift's discography. "All Too Well" is another song that has been praised, with heartbreaking lyrics like "you call me up again just to break me like a promise" and "so casually cruel in the name of being honest."
However, the highlights are the songs from the vaults. These tracks were written during the original creation of the album but were not released. Red (Taylor's Version) contains nine songs from the vault, with features including Phoebe Bridgers, Ed Sheeran, and Chris Stapleton. Two of the songs, "Babe" and "Better Man", were originally given to other artists, but now sound more vibrant with the attachment of Taylor Swift's voice. "Message In A Bottle" is very much a pop song and sounds like it belongs on her 80s synth-infused album 1989, while "I Bet You Think About Me" calls out an ex-lover dreading the release of any songs about them. "Nothing New" is backed by the lovely Phoebe Bridgers and reflects on the anxiety that is brought on by romantic relationships and the music industry. The last song is "All Too Well (10 Minute Version)", a much longer extension of the original, with lyrics that are even more gut-wrenching and sorrowful.
The release of the album was also accompanied by a short film directed by Swift. Starring actors Dylan O'Brien (Teen Wolf) and Sadie Sink (Stranger Things), All Too Well (The Short Film) is based on the fan-favorite song of the same title. It follows a toxic relationship plagued by gaslighting, age differences, and a "F*ck the Patriarchy" keychain.
Through this process, Taylor Swift has managed to improve a classic. As she continues on this re-recording journey, fans new and old can marvel at Swift's ability to capture an audience with her art.


text:
Flights Of Fantasy
[ M Panging Pao ]
The Russo-Ukraine war has completed one month, during which there has been intense fighting with Russian forces assaulting many Ukrainian towns and cities.
Russia has the second largest armed forces in the world and is vastly superior to Ukraine. However, Ukraine has the second largest armed forces in the area and is supported by many western nations who have supplied them with modern arms and weapons. In addition, Russia has pitted only a part of its forces in the war against Ukraine. A forces comparison between Russia and Ukraine is shown in the table.
In warfare, the worldwide accepted ratio of attackers to defenders is 3:1. This ratio increases to 10:1 in urban areas. Despite counter claims, Russian armed forces have achieved large gains during the war, achieving control of the airspace over Ukraine. Russian forces have advanced along 4-5 axes. In the main attack towards the Ukrainian capital Kyiv, Russian forces have advanced 75 kms, encircling Kyiv. They have advanced 35 kms along the Kharkiv axis, and 75-100 kms along the Donetsk, Luhansk axis. The maximum gain by Russians is along the south of Ukraine, along the Black Sea, where they have advanced 141 kms towards Odessa and 275 kms towards Mariupol. Mariupol has been encircled by Russian forces and they have been able to establish a land corridor from Crimea to the pro-Russian regions of Donbas.
The next few weeks may be critical to the outcome of the war. It is expected that the critical town of Mariupol would fall, connecting Russian Crimea to the Pro-Russian Donbas region. In case Odessa is also attacked and taken, Ukraine would be cut off from the Black Sea and would be rendered landlocked. With Kyiv almost encircled, Russia may gain key objectives, and this may finally lead to a ceasefire.
The war has caused massive devastation and deaths, and created millions of refugees. Both Russians and Ukrainians have suffered with similar figures of 2-3,000 deaths and 5,000 wounded. In addition, 4-5,000 civilians were reportedly killed and many soldiers were taken prisoners of war. Many Ukrainian cities, like Kharkiv, Sumy, Mariupol, Melotopol and Kyiv, have been bombed extensively, causing massive destruction. The war has caused the biggest refugee crisis of recent times. About one crore refugees have left Ukraine and sought refuge in the neighbouring countries of Poland, Romania, Moldova, Hungary, Germany, Russia, etc.
With the Western nations in the NATO and the EU uniting against Russia, Russia is sabre-rattling the nuclear threat, and the Ukrainian leadership is still not giving up. There are very less chances of the war ending soon. It seems that human beings have forgotten about critical global pandemics like Covid-19, global warming and climate change, famine, hunger, etc. Hope this war does not escalate into World War III. (The contributor is retired Group Captain, Indian Air Force)


text:
Thursday, September 22, 2022 | 12:00 pm - 1:00 pm | Zoom
Add to Calendar: Google Outlook AppleFacilitators
jean amaral (Library) and Carla Macchiavello (Music and Art)
Join this meet and greet event with Odaelys Pollard, the new Director of Research Programs at BMCC. This will be a Zoom event and a great opportunity to learn about Dr. Pollard's vision for research at BMCC, grant development processes, funding, among other topics you might be interested in discussing.
Register here and you will receive a Zoom link via email. For more information, email Carla Macchiavello.


text:
SNEW assists Amador County with Benchmarking Report and Solar Installation Analysis
Sierra Nevada Energy Watch Supports Amador County with Free Energy Efficiency Services
Government & Community Affairs Director
Communications Manager
California is in the midst of what is shaping up to be one of the largest wildfire seasons on record… yet again.
Over the last several years, advocating for increased wildfire funding, forest management, and the accelerating need to reestablish a natural fire ecosystem has been a priority here at SBC. In this time, we've seen progress on how the state understands the importance of forest restoration and wildfire mitigation.
But unfortunately, the rate of progress we're seeing is simply not enough.
In order to actually restore our forests and protect the safety of Sierra communities, we need to deploy every tool in the toolbox we have at our disposal. Forest biomass is an underutilized, underfunded, and often misunderstood tool that can help us meet our forest health, community well-being, and climate resilience goals.
Forest biomass utilization, in which excess material from forest management treatments is converted to create electricity and innovative wood products, can restore our forests and reduce the risks of catastrophic wildfire, all while bolstering rural economic activity and expanding renewable energy resources.
In 2019, SBC explored the nuances and benefits of forest biomass utilization in Biomass in the Sierra Nevada: A Case for Healthy Forests and Rural Economies.
Our follow-up to this white paper report is a three-part video series, Balance & Biomass: A Solution to Emissions, Catastrophic Fire, & Communities in Crisis, that identifies the opportunities of forest biomass utilization at both the local and statewide levels and begs the question, why isn't the state doing more to support appropriately scaled forest biomass utilization in the Sierra's communities?
Forest biomass is a pragmatic piece of the puzzle that can solve our wildfire crisis, a crisis that state legislators are underestimating – and consequently underfunding – what it will take to fix.
Sierra Business Council is calling for the State of California to invest $3 billion in forest restoration efforts over the next 10 years. Without this level of investment in forest resilience solutions that we have at our disposal, including landscape scale restoration, prescribed fire, workforce training and development, ecological thinning, as well as forest biomass utilization, our wildfire crisis will continue to worsen year after year.
We can meet our forest health, community well-being, and climate resilience goals. But we need to invest now in our future.
Balance & Biomass makes the case for this investment in biomass utilization in the Sierra Nevada through the following chapters:
Balance & Biomass was made possible through the support of the BlueTechValley Innovation Cluster funded in part by the California Energy Commission EPIC program. Sierra Business Council would also like to thank the following individuals and organizations that made this series possible:
Walk Scherer, Paradise Resident
Judy and Bob Dean, Calaveras County Residents
Matthew Cunha-Rigby, HDR Architecture, Inc.
Julia Levin, Bioenergy Association of California
Jan Buck, Sierra Booster
Dan Sanchez, Joint Institute for Wood Product Innovation, UC Berkeley
Glenda Humiston, Agriculture and Natural Resources, University of California
Ryan Emmett Tompkins, Agriculture and Natural Resources, University of California
Teal Brown Zimring, Galvanize Partners
Thurman Roberts, Sierra Nevada Alliance Forestry Corps
Sierra Nevada Energy Watch Supports Amador County with Free Energy Efficiency Services
Four Sierra Nevada businesses, with technical assistance by Sierra Business Council, were awarded thousands of dollars in grant funding to upgrade their refrigeration and freezer units!
We're excited to announce a new, funded partnership between Sierra Business Council, Nevada County, and Climate Transformation Alliance's (CTA) governing partners (i.e., the Town of Truckee, Tahoe Donner Public Utility District, and Truckee Tahoe Airport District), and the Nevada City Rancheria Nisenan Tribe came together to develop a comprehensive climate resiliency project with multiple co-benefits.
we'd be poor advocates of the region if we failed to acknowledge the history and current role of the original stewards of the Sierra Nevada. From the Maidu to the Miwok, the Niesenan to the Shoshone, the Paiute to the Washoe, and all the other diverse cultures throughout the region, the Indigenous peoples of Sierra Nevada were the original caretakers of this landscape, and they are critical partners that should be respected and involved in this region's future.
For fear of sounding like a broken record, I will skip over the detailed account of how my fellowship/life is not exactly as I expected it to be, thanks to the pandemic. It's 2021 but you could also call it December 56th, 2020. It didn't become a brand new world January 1st, we are still wearing masks, working from home in our sweatpants, and trying to avoid refreshing the news. At the same time, I have been pondering the beauty of my unexpected journey to CivicSpark and SBC.
I entered college knowing I would major in environmental studies. This interest in the environment was the constant in my ever-changing adolescence (and involved many phases, including when I only wore green, yikes!) and it helped direct me when I arrived on campus as one of the 45,000 students at the University of Washington. I started taking environmental classes right off the bat and didn't have to flounder around, searching for some deep unstoked passion. It was already there.
Born and raised in the Pacific Northwest, I have grown up with the luxury of beautiful mountains, trails, rivers, and beaches. I spent most of my free time recreating outdoors and waited for any opportunity to venture to new places. Studying the environment seemed like an extension of the things I love. I could learn about the birds, trees, and rocks that I saw. I could learn about the tides and the rivers that I know. I could become an expert on my home.