• Stars
    star
    2,633
  • Rank 17,384 (Top 0.4 %)
  • Language
    Objective-C
  • License
    Other
  • Created about 10 years ago
  • Updated over 2 years ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

Better playgrounds that work both for Objective-C and Swift

Swift Playgrounds... but supporting both Objective-C and Swift code, plus some superb features.

Watch demo

More in-depth overview video

Version License Platform

Playgrounds are one of the niftiest features of Swift. They allow you to quickly test out bits of code and see results in real time without going through traditional edit-compile-run-debug cycle.

"But surely playgrounds aren't possible in Objective-C" you say? ... In fact they can be much better than Swift ones.

Objective-C Playgrounds

Features:

  • Faster than Swift playgrounds (a lot)
  • Extra controls for tweaking:
    • values
    • images
  • Auto-animated values
  • Synchronizing DSL's
  • Buttons
  • IDE agnostic, once you run it, you can modify the code even from vim.
  • Full iOS simulator and access to all iOS features, so you can prototype production ready code.
  • Nice DSL for rapid prototyping
  • CocoaPods support, so you can add it to existing projects to experiment
  • Open source, anyone can contribute to make them better!

and it’s just a start.

Technical details

First, let’s establish naming:

  • Timeline is a place where you have snapshots and controls.
  • Worksheet is a place where you can add views / controls and have interaction with them. You can use all the stuff you’d normally use with iOS like UIGestureRecognizers etc.
  • Tick counter - number of times the code changes have been loaded, multiply by the time it takes to compile + load your project and you see how much time you saved.

DSL’s - Beautiful and fast way to prototype.

Timeline snapshots

KZPShow(obj)

  • CALayer
  • UIView
  • UIBezierPath
  • CGPathRef
  • CGImageRef
  • UIImage
  • NSString, with format or without
  • id

Implementing snapshotting for your custom classes

You can implement custom debug image:

- (UIImage*)kzp_debugImage;

If you have already implemented - (id)debugQuickLookObject that returns any of types supported by the KZPShow, you don’t need to do anything.

Controls

  • Button
KZPAction(@"Press me", ^{
// Magic code
})
  • Images

Picking an image from the library:

KZPAdjustImage(myImage);
KZPWhenChanged(myImage, ^(UIImage *img) {
  imageView.image = img;
});
  • Values
KZPAdjustValue(scale, 0.5f, 1.0f) //- for floats
KZPAdjustValue(position, 0, 100) //- for integers

you can also set default values:

KZPAdjustValue(position, 0, 100).defaultValue(50)
  • Block callbacks KZPAdjust are also available.

Animations

  • Block animation callback, code that will be executed with each screen refresh (display link). Useful for animating multiple values.
KZPAnimate(CGFloat from, CGFloat to, void (^block)(CGFloat));
KZPAnimate(void (^block)());
  • Auto-animated values, defines new variable and automatically animates them. AR -> AutoReverse
KZPAnimateValue(rotation, 0, 360)
KZPAnimateValueAR(scale, 0, 1)

Coordinating code execution

Executing code only once the value is set

KZPWhenSet(myImage, ^(UIImage *img) {
	//! magic
});

Executing code on value changes

KZPWhenChanged(myImage, ^(UIImage *img) {
	//! magic
});

Storing variables

Transient - Cleared with each code change

Instead of using instance variables / properties for KZPlayground class (you are fine to use them for normal classes that you create as part of playground), you should store playground specific variables that you need to reference between playground methods, eg. view you want to pan with UIPanGestureRecognizer inside transientObjects dictionary.

self.transientObjects[@"pannableView"] = view;

Persisted - Not cleared with recompilation

Implement setup method and use normal instance variables to store data you don't want to change on code change. eg. if you need to do some expensive operation.

Snapshots recorded during setup will persist in timeline.

- (void)setup
{
	self.data = [self fetchBigDataSet];
}

Installation and setup

KZPlayground is distributed as a CocoaPod: pod 'KZPlayground' so you can either add it to your existing project or clone this repository and play with it.

Remember to not add playgrounds in production builds (easy with new cocoapods configuration scoping).

Once you have pod installed, you need to create your playground, it’s simple:

  1. Subclass KZPPlayground
  2. Implement run method
  3. Conform to KZPActivePlayground protocol
    You can have many playgrounds in one project, but only one should be marked as KZPActivePlayground. It will be automatically loaded.
  4. present [KZPPlaygroundViewController playgroundViewController]

To apply your changes you have 2 approaches:

  1. Xcode/Appcode you can use cmd/ctrl + x (done via dyci plugin) while you are modifying your code.
  2. (My Preferrence) Automatic on file save (IDE agnostic) using kicker gem in terminal: (N.B. you need to have the kicker gem installed, see below)
kicker -sql 0.05 FOLDER_WITH_SOURCE_FILES

in case of Example project you'd call kicker from inside the project root folder (one containing the .kick file, which you will also need.)

kicker -sql 0.05 Example

This will react to all changes in .m files in the Example directory and reload your playground.

(Optional) Make Kicker autostart whenever you run your project

  1. Copy the .kick file to your project's directory.
  2. Add a new "Run Script" under your target's "Build Phases" tab with the following:
PID_PATH=/tmp/${PROJECT_NAME}_kicker.pid
if [ -e $PID_PATH ]
then
  kill $(cat $PID_PATH)
  rm $PID_PATH
fi
kicker -sql 0.05 . > /dev/null 2>&1 & echo $! > $PID_PATH

Note: You will need to manually kill the kicker process when you're done since it won't be killed after you stop running your project.

Only once

KZPlayground is powered by Code Injection, currently using Dyci code injection tool, you only need to install it once on your machine (You’ll need to reinstall it on Xcode updates):

git clone https://github.com/DyCI/dyci-main.git
cd dyci-main/Install/
./install.sh

In order to use the kicker gem, you need to install it as follows:

(sudo) gem install kicker

Swift support

My playgrounds now support Swift code, to use that you should use injectionforxcode instead of Dyci, make sure to grab 0.4 Release for some simpler API.

Contributing

Pull-requests are welcomed.

Changelog

0.4

  • Basic Swift support
  • Added Swift example

0.3.2

  • Ability to hide timeline

0.3.1

  • XCAsset images picking.
  • Persisting selected images.

0.3.0

  • Image picking.
  • Synchronisations.
  • Change observing.
  • Localizable strings are injected.

0.2.5

  • Persistent setup functionality.
  • Improved snapshots details.

0.2.0

  • All files in the project can be now changed to trigger playground reload.
  • Better kicker setup.
  • Transient objects.

License

KZPlayground is available under the modified MIT license. See the LICENSE file for more info.

Author

Krzysztof Zablocki, [email protected]

Follow me on twitter.

Check-out my blog or GitHub profile for more cool stuff.

Cool usages

Check out AudioKit examples using playgrounds

Attribution

SceneKit example code has been taken from David Ronnqvist upcoming SceneKit book, recommended.

More Repositories

1

Sourcery

Meta-programming for Swift, stop writing boilerplate code.
Swift
7,677
star
2

LifetimeTracker

Find retain cycles / memory leaks sooner.
Swift
3,144
star
3

Inject

Hot Reloading for Swift applications!
Swift
2,127
star
4

Swift-Macros

A curated list of awesome Swift Macros
Swift
2,120
star
5

Bootstrap

iOS project bootstrap aimed at high quality coding.
Objective-C
2,047
star
6

LineDrawing

Beatiful and fast smooth line drawing algorithm for iOS - as seen in Foldify.
Objective-C
1,288
star
7

Difference

Simple way to identify what is different between 2 instances of any type. Must have for TDD.
Swift
1,217
star
8

PropertyMapper

Property mapping for Objective-C iOS apps.
Objective-C
1,124
star
9

KZFileWatchers

A micro-framework for observing file changes, both local and remote. Helpful in building developer tools.
Swift
1,078
star
10

LinkedConsole

Clickable links in your Xcode console, so you never wonder which class logged the message.
Swift
931
star
11

Traits

Modify your native iOS app in real time.
Swift
904
star
12

IconOverlaying

Build informations on top of your app icon.
Shell
650
star
13

crafter

Crafter - Xcode project configuration CLI made easy.
Ruby
547
star
14

Strongify

Strongify is a 1-file µframework providing a nicer API for avoiding weak-strong dance.
Swift
444
star
15

KZNodes

Have you ever wonder how you could make Origami like editor in 1h ?
Objective-C
336
star
16

SFObservers

NSNotificationCenter and KVO auto removal of observers.
Objective-C
307
star
17

AutomaticSettings

Data driven settings UI generation.
Swift
302
star
18

CCNode-SFGestureRecognizers

Adding UIGestureRecognizers to cocos2d, painless.
Objective-C
202
star
19

DetailsMatter

Objective-C
199
star
20

Pinch-to-reveal

Pinch to reveal animation transition built with Layer masking, as seen in boeing app for iPad.
Objective-C
192
star
21

ViewModelOwners

Protocols that help make your MVVM setup more consistent
Swift
143
star
22

KZAsserts

Asserts on roids, test all your assumptions with ease.
Objective-C
100
star
23

OhSnap

Reproduce bugs your user saw by capturing and replaying data snapshots with ease.
Swift
89
star
24

Versionable

Migration for `Codable` objects.
Swift
83
star
25

SFContainerViewController

UIViewControllers containment predating Apple implementation. Works in both 4.x and 5.x iOS, no memory or hierarchy issues.
Objective-C
82
star
26

Swift-Observable

Native KVO like behaviour build in Swift.
Swift
64
star
27

BehavioursExample

Objective-C
58
star
28

SourceryWorkshops

Swift
45
star
29

Learn-iOS-GameDev-Level-0

Teeter clone accompanying tutorial at http://merowing.info/2013/04/learn-ios-game-dev-level-0/
Objective-C
24
star
30

XibReferencing

Simple category and sample showing how you can reference one Xib view from another
Objective-C
20
star
31

KZImageSplitView

Objective-C
17
star
32

NSObject-SFExecuteOnDealloc

A simple category on NSObject that allows you to execute block when object is deallocated
Objective-C
17
star
33

jenkins_jobs_to_statusboard

Ruby script that generates html table for embedding in StatusBoard by Panic http://panic.com/statusboard/
Ruby
15
star
34

SourceryPro-Feedback

Repository for discussing https://merowing.info/sourcery-pro/
12
star
35

krzysztofzablocki

2
star
36

krzysztofzablocki.github.io

Blog
HTML
2
star
37

starter-hugo-academic

Jupyter Notebook
1
star