A Cocoa library to extend the Objective-C programming language.

Related tags

Utility libextobjc
Overview

The Extended Objective-C library extends the dynamism of the Objective-C programming language to support additional patterns present in other programming languages (including those that are not necessarily object-oriented).

libextobjc is meant to be very modular – most of its classes and modules can be used with no more than one or two dependencies.

Features

libextobjc currently includes the following features:

  • Safe categories, using EXTSafeCategory, for adding methods to a class without overwriting anything already there (identifying conflicts for you).
  • Concrete protocols, using EXTConcreteProtocol, for providing default implementations of the methods in a protocol.
  • Simpler and safer key paths, using EXTKeyPathCoding, which automatically checks key paths at compile-time.
  • Compile-time checking of selectors to ensure that an object declares a given selector, using EXTSelectorChecking.
  • Easier use of weak variables in blocks, using @weakify, @unsafeify, and @strongify from the EXTScope module.
  • Scope-based resource cleanup, using @onExit in the EXTScope module, for automatically cleaning up manually-allocated memory, file handles, locks, etc., at the end of a scope.
  • Algebraic data types generated completely at compile-time, defined using EXTADT.
  • Synthesized properties for categories, using EXTSynthesize.
  • Block-based coroutines, using EXTCoroutine.
  • EXTNil, which is like NSNull, but behaves much more closely to actual nil (i.e., doesn't crash when sent unrecognized messages).
  • Lots of extensions and additional functionality built on top of <objc/runtime.h>, including extremely customizable method injection, reflection upon object properties, and various functions to extend class hierarchy checks and method lookups.

The experimental branch contains additional features that may be interesting, but are not considered stable or safe for production use. Check out the headers for more information.

Running tests

To execute libextobjc's tests, first run git submodule update --init --recursive to bring in the xcconfigs submodule, then open the project file and choose the desired test target.

Adding to your project

If you want to add libextobjc as a dependency to an application, add the repository as a submodule, then include the source files you care about in your Xcode project.

If you want to add libextobjc as a dependency to a framework or library, prefer subtree merging, which will allow you to rename symbols to avoid conflicts, and make any tweaks you need to for your library.

To create a libextobjc subtree:

$ git remote add libextobjc https://github.com/jspahrsummers/libextobjc.git
$ git fetch libextobjc
$ git read-tree --prefix=External/ -u libextobjc/master
$ git reset

Rename any symbols or change whatever you want, git add the specific files that you want in your library, and then add them to your Xcode project.

To bring in upstream changes later:

$ git fetch -p libextobjc
$ git merge -Xsubtree=External/ libextobjc/master
$ git reset

Then, again, just add the changes you want.

License

Released under the MIT License. See the LICENSE file for more information.

Requirements

libextobjc must be built with ARC enabled, and many of its macros require ARC in the calling files as well. MRR usage is not supported.

Comments
  • @weakify/@strongify in nested blocks

    @weakify/@strongify in nested blocks

    Hi,

    I have been looking through the library documentation in order to find some guidance on how to use @weakify and @strongify in nested blocks, but cannot find any. For example, which is correct?

    1. @weakify once and subsequently @strongify in blocks

    - (void) test {
          @weakify(self)
          id block = ^{
            @strongify(self);
            [self doSomething];
            nestedBlock = ^{
              @strongify(self);
              [self doSomethingElse];
            }();
          };
          block();
    }
    

    2. Alternate @weakify/@strongify

    - (void) test {
          @weakify(self)
          id block = ^{
            @strongify(self);
            [self doSomething];
            @weakify(self)         // @weakify again before the nested block?
            nestedBlock = ^{
              @strongify(self);
              [self doSomethingElse];
            }();
          };
          block();
    }
    

    Would be great to get some guidance on what is appropriate here.

    Many thanks,

    J

    opened by itsthejb 17
  • Fix @keypath nullability warnings in Xcode 10

    Fix @keypath nullability warnings in Xcode 10

    In Xcode 10, the boxing operator @ now returns a NSString * _Nullable instead of NSString * when the parameter is char *. This change makes the @keypath and @collectionKeypath macros return nullable values as well. If you have CLANG_WARN_NULLABLE_TO_NONNULL_CONVERSION (-Wnullable-to-nonnull-conversion) enabled, Clang in Xcode 10 emits this warning for @keypath and @collectionKeypath expressions when assigning to a non-null NSString * variable/parameter:

    warning: Implicit conversion from nullable pointer 'NSString * _Nullable' to non-nullable pointer type 'NSString * _Nonnull'

    We can't use a pragma inside the macro defintion to silence the warning because the warning occurs through the boxing, which happens outside the macro.

    This fix wraps the existing macro defintion in a (YES).boolValue ? (NSString * _Nonnull)@(...) : (NSString * _Nonnull)nil expression. This gives us a chance to silence the warning with an explicit cast to _Nonnull, and since @(YES).boolValue always succeeds, doesn't change the result of the macro. The additional overhead should be minimal compared to the NSString allocation because @(YES) should be a tagged pointer. (The cast (NSString * _Nonnull)nil is there to suppress a static analyzer nullability warning.)

    I also had to extract the original macro definition into a separate cStringKeypath macro because @collectionKeypath depends on C strings.

    I added explicit _Nonnull annotations to the variables in the key path tests to make sure the compiler would emit the warnings if something goes wrong.

    opened by ole 11
  • synthesizeLazyAssociation

    synthesizeLazyAssociation

    Hey,

    Since 99% of our category properties are lazy, it is necessary we find an easy way to get libextobj to work nicely with this.

    First naive idea is to synthesizeAssociation an internal property that is initialized the first time the external property gets called, by adding a nil check. But... Why not take it one step further?

    Looking at the EXTSynthesize code, it doesn't seem hard at all to add a callback for initializing the property in the getter block. That's how the synthesizeLazyAssociation idea was born, and I would guess that I'll just have to add one more block parameter that returns an id type.

    I'll start implementing this on our fork, anyway, since we need it, but any better ideas are appreciated or if you think this is a good addition, will be happy to clean it up and submit a PR.

    Thanks!

    opened by Mazyod 10
  • [WIP] Compile time safe keypath

    [WIP] Compile time safe keypath

    :warning: Not yet ready for merge due to problems with class keypaths, e.g. @keypath(NSObject, version).

    This allows it to be used to initialize static variables with the same type-safety and autocompletion benefits, at the cost of complicating the macro’s definition.

    Note that this can only apply to the two-argument variant, since there is no way to split the string at compile-time.

    Further, an additional change allows types to be passed as the first argument of @keypath, removing the need for workarounds like @keypath(Foo.new, …) which can be jarring, and which may be inconvenient in cases where e.g. +new is unavailable or you don’t even have a concrete class (e.g. with protocols). However, as @lldong points out, this currently breaks generation of class keypaths (e.g. @keypath(NSObject, version)).

    ~~The trick this uses to take the type of a comma express compiler-visible mechanism might be useful elsewhere; is something like that already available elsewhere?~~ I ended up not requiring that trick at all; using the comma operator simplified this greatly. Seems like only multistatement things would need the block trick, and they’re probably already in one.

    • [ ] Can we pass classes directly for class key paths but also allow types?
    opened by robrix 10
  • Spin lock was replaced with os_unfair_lock

    Spin lock was replaced with os_unfair_lock

    Thanks for wanting to contribute to this project!

    Unfortunately, it's not really maintained anymore.

    Feel free to use it as-is, or fork it and modify as much as you want to suit your needs. However, I can't guarantee that I'll have time/energy to look at new issues and pull requests.

    Sorry for the trouble!

    opened by K-Be 9
  • Implemented self method on EXTNil

    Implemented self method on EXTNil

    Just found amazing solution for this case: https://github.com/jspahrsummers/libextobjc/pull/101

    Solution:

    NSArray<UIViewController *> *horizontalViewControllers = @[
        self.trendsViewController ?: [EXTNil null],
        self.trendGroupsViewController,
        self.searchViewController,
        self.bookmarksViewController ?: [EXTNil null],
    ];
    return [horizontalViewControllers[index] self];
    

    Just to call - (instancetype)self selector!!! I checked who ever called this selector in iOS application. This happenes only 2!!!! times on app start for 1!!!! private UIKit class. I think we can implement this method in our class EXTNil like we want, nobody cares - nothing will be broken :)

    opened by k06a 9
  • Replaced try/finally with autoreleasepool as a way to eat the @.

    Replaced try/finally with autoreleasepool as a way to eat the @.

    As reported in ReactiveCocoa/ReactiveCocoa#952 the presence of a @try block silences the warning about control reaching the end of a non-void block or function.

    This PR replaces @try with @autorelease as a way to eat the @.

    Both libextobjc's and RAC's tests pass with this change.

    opened by Coneko 9
  • Fix warning in ext_getPropertyAccessorsForClass

    Fix warning in ext_getPropertyAccessorsForClass

    I'm getting the following warning in Xcode 6 beta 6:

    Pods/libextobjc/extobjc/EXTRuntimeExtensions.m:710:18: Initialization of pointer of type 'ext_propertyAttributes *' to null from a constant boolean expression

    screen shot 2014-08-20 at 10 39 42 am

    My understanding is limited, but it seems as though attributes is no longer used after the free(attributes) line. My changes fix the warning, but would this change have any unintended consequences? I ran the tests and they pass (though they fail to compile without the fix due to the warning).

    opened by sibljon 7
  • EXTConcreteProtocol - improved inheritance support

    EXTConcreteProtocol - improved inheritance support

    • Do not override a selector implemented on a conforming class. Similar to current behavior, but checks only the target class, not it's super classes.
    • Supports cases where a @concreteprotocol is used to encapsulate methods expected on subclasses (e.g. various methods called back onto a UIViewController) that their super classes may call if defined.
    opened by greymouser 7
  • SafeCategory finds the conflict when implementing both class method and instance method using the same selector name.

    SafeCategory finds the conflict when implementing both class method and instance method using the same selector name.

    Implementing both class method and instance method using the same selector name will cause conflict:

    @safecategory(NSObject, HelloWorld)
    + (void) helloWorld{
        NSLog(@"helloWorld");
    }
    - (void) helloWorld{
        NSLog(@"helloWorld");
    }
    @end
    

    On console:

    ERROR: Could not add class method +helloWorld to NSObject (a method by the same name already exists)
    ERROR: Failed to fully load safe category NSObject (HelloWorld)
    

    And I found the instance method in the safe category will actually add the implementation into both the class selector and the instance selector:

    // Only implement the -helloWorld in the safe category
    @safecategory(NSObject, HelloWorld)
    - (void) helloWorld{
        NSLog(@"helloWorld");
    }
    @end
    

    Now, both +helloWorld and -helloWorld will print the helloWorld string on the console.

    By the way, my suggestion is changing the keyword safecategory to SafeCategoryImplementation to specify you are writing in the @implementation...@end block.

    opened by xareelee 7
  • EXTSynthesize objective-c++ compatibility

    EXTSynthesize objective-c++ compatibility

    Hello. I'm trying to use @synthesizeAssociation in my objective-c++ code and I have a problems. There are two compiler errors when I'm building the code. First is about using restrict keyword in ext_synthesizeBlockProperty function declaration. Seems like clang in c++ mode doesn't recognize this keyword(maybe it's undefined in libc++?) but it knows about __restrict. How about replace all restrict keywords with __restrict? It also works for pure C99(+ Objective-C)

    Second one is about initialization of global static variable ext_methodInjectionOverwriteBehaviorMask at EXTRuntimeExtensions.h — there is a type mismatch there — on the left side is a const ext_methodInjectionBehavior and on another — int, so compiler(again, in c++ mode) warns us about it in a strong manner :) As hotfix it can be fixed by explicit C-style cast from int to ext_methodInjectionBehavior but it seems a not good decision. What do you think about it?

    bug 
    opened by ikashkuta 7
  • use 'import <*/*>' to import third library header file

    use 'import <*/*>' to import third library header file

    I notice that you import mantle's header file using 'import ""', Could you use 'import </>' to import third library header file? Because This can cause many header file reference problem.

    Thanks

    opened by Luffy19960106 0
  • Add minimum OS versions to stop warnings

    Add minimum OS versions to stop warnings

    • with a podspec.json if a platform version isn’t defined, the lowest version available will be used.
    • ’os_unfair_lock_trylock' is only available on iOS 10.0, macOS 10.12, tvOS 10.0 and watchOS 3.0 or newer
    • see Apple Docs

    Thanks for wanting to contribute to this project!

    Unfortunately, it's not really maintained anymore.

    Feel free to use it as-is, or fork it and modify as much as you want to suit your needs. However, I can't guarantee that I'll have time/energy to look at new issues and pull requests.

    Sorry for the trouble!

    opened by CraigsOverItAll 0
  • How about improve concrete protocol macro?

    How about improve concrete protocol macro?

    Hi there, thanks for this fantastic lib, it's very useful and the code is very impressive. I really want to put concrete protocol into my project, however, I found some performance issue(this lib looks like not maintained, but why don't we just discuss this issue here).

    I checked the implementation of the concrete protocol function, and I found when loading concrete protocols, a lot of time will spent on traversing all Objc classes for making protocol connected target class automatically. I have a test in an almost empty project, and we will got more than 13000 classes in the system foundation. it will take very long time to load all the concrete protocols.

    In this simple test, I create 100 concrete protocols, more than 1.20s will spent on loading phase, it will be worse when we actually use it in a real project.

    So there is my solution, create a concreteprotocol2 macro to all the specific target classes(just increase a little bit writing complexity for making such a great high performance).

    for example:

    @concreteprotocol2( DemoProtocol, @"AppDelegate", @"Class1", @"Class2")
    

    That will drop the traversing code, and take less than 1ms to load all the 100 concrete protocols.

    opened by JianboYan 0
  • Update EXTKeyPathCoding.h

    Update EXTKeyPathCoding.h

    To support the following form of usage: (str is a instance of NSString *)

    • @keypath(str, lowercaseString.UTF8String)
    • @keypath(NSString *, lowercaseString.UTF8String)
    • @keypath(NSString.new, lowercaseString.UTF8String)
    opened by rickytan 0
  • EXTConcreteProtocol:Model Confirm Protocol Duplicate Symbol

    EXTConcreteProtocol:Model Confirm Protocol Duplicate Symbol

    Thanks for wanting to contribute to this project!

    Unfortunately, it's not really maintained anymore.

    Feel free to use it as-is, or fork it and modify as much as you want to suit your needs. However, I can't guarantee that I'll have time/energy to look at new issues and pull requests.

    Sorry for the trouble!

    Hi, I used EXTConcreteProtocol to extend my protocol. I met a question when I used it. When used liked this #import <EXTConcreteProtocol.h> @protocol TestProtocol @concrete

    • (void)changed; @end

    @concreteprotocol(TestProtocol)

    • (void)changed { NSLog(@"Update"); } @end interface TestObject:NSObject @end @implementation TestObject @end

    int main(int argc, const char * argv[]) { @autoreleasepool { TestObject *object = [TestObject new]; [object buzz]; } return 0; }

    it worked well.

    ======

    But when I used in a single application like let TestObject confirm TestProtocol, and I used it on my viewController, then, it cannot be complied success.

    Further, I let my viewController confirm TestProtocol, call function buzz in viewDidLoad, it worked.

    I found another git repository called ProtocolKit, which call do same work like EXTConcreteProtocol. Maybe I have problem in using protocol.

    I create a repository here to describe my question: [email protected]:tangzzz-fan/TGTestProtocol.git

    Thanks advanced.

    opened by tangzzz-fan 0
Releases(0.6)
Owner
Justin Spahr-Summers
Engineering + People
Justin Spahr-Summers
A parser combinator library written in the Swift programming language.

SwiftParsec SwiftParsec is a Swift port of the Parsec parser combinator library. It allows the creation of sophisticated parsers from a set of simple

David Dufresne 219 Nov 6, 2022
Numerals is a package containing additional numeric types for the Swift programming language.

swift-numerals Numerals is a package containing additional numeric types for the Swift programming language. Contents The package currently provides t

Alexandre H. Saad 0 Jul 28, 2022
Cross-Platform, Protocol-Oriented Programming base library to complement the Swift Standard Library. (Pure Swift, Supports Linux)

SwiftFoundation Cross-Platform, Protocol-Oriented Programming base library to complement the Swift Standard Library. Goals Provide a cross-platform in

null 620 Oct 11, 2022
Sugar is a sweetener for your Cocoa implementations.

Sugar is a sweetener for your Cocoa implementations. Table of Contents iOS Application Screen Simulator Keyboard Observer iOS Extensions UIView

HyperRedink 1.1k Dec 29, 2022
🏹 Bow is a cross-platform library for Typed Functional Programming in Swift

Bow is a cross-platform library for Typed Functional Programming in Swift. Documentation All documentation and API reference is published in our websi

Bow 613 Dec 20, 2022
Pure Declarative Programming in Swift, Among Other Things

Basis The Basis is an exploration of pure declarative programming and reasoning in Swift. It by no means contains idiomatic code, but is instead inten

TypeLift 314 Dec 22, 2022
Functional programming in Swift

Swiftz Swiftz is a Swift library for functional programming. It defines functional data structures, functions, idioms, and extensions that augment the

TypeLift 3.3k Dec 25, 2022
Data Mapping library for Objective C

OCMapper is a data mapping library for Objective C that converts NSDictionary to NSObject

Aryan Ghassemi 346 Dec 8, 2022
A functional tool-belt for Swift Language similar to Lo-Dash or Underscore.js in Javascript

Dollar Dollar is a Swift library that provides useful functional programming helper methods without extending any built in objects. It is similar to L

Ankur Patel 4.2k Jan 2, 2023
Soulful docs for Swift & Objective-C

jazzy is a command-line utility that generates documentation for Swift or Objective-C About Both Swift and Objective-C projects are supported. Instead

Realm 7.2k Jan 1, 2023
Catch Objective-C exceptions in Swift

ExceptionCatcher Catch Objective-C exceptions in Swift There are many Cocoa APIs that can throw exceptions that cannot be caught in Swift (NSKeyedUnar

Sindre Sorhus 98 Nov 23, 2022
💡 A light Swift wrapper around Objective-C Runtime

A light wrapper around Objective-C Runtime. What exactly is lumos? lumos as mentioned is a light wrapper around objective-c runtime functions to allow

Suyash Shekhar 139 Dec 19, 2022
Swift-friendly API for a set of powerful Objective C runtime functions.

ObjectiveKit ObjectiveKit provides a Swift friendly API for a set of powerful Objective C runtime functions. Usage To use ObjectiveKit: Import Objecti

Roy Marmelstein 850 Oct 25, 2022
Swift Property Wrappers, but in Objective-C. And done horribly.

TOPropertyAccessor is an open source, Objective-C abstract class. Similar to Realm's Cocoa API, it uses the dynamic nature of the Objective-C runtime to access the properties of any of its subclasses, and routes calling them through overridable access points.

Tim Oliver 3 May 23, 2021
Reflection for enumerations in Objective-C.

ReflectableEnum A macro and a set of functions introducing reflection for enumerations in Objective-C. Features: get a string value for an enumeration

Arek Holko 333 Nov 17, 2022
Because Objective-C should have inherited more from Smalltalk

OpinionatedC Sometimes, Objective-C is just overly verbose. Life is too short to enumerateObjectsUsingBlock and who has the time to create sub-arrays

Leo Schweizer 52 Apr 7, 2022
The Objective-C block utilities you always wish you had.

BlocksKit Blocks in C and Objective-C are downright magical. They make coding easier and potentially quicker, not to mention faster on the front end w

BlocksKit 6.9k Dec 28, 2022
Proper YAML support for Objective-C. Based on recommended libyaml.

YAML.framework for Objective-C Based on C LibYAML library (http://pyyaml.org/wiki/LibYAML) by Kirill Simonov. YAML.framework provides support for YAML

Mirek Rusin 236 Aug 29, 2022