Index: src/OFObject.h ================================================================== --- src/OFObject.h +++ src/OFObject.h @@ -276,11 +276,11 @@ /*! * @brief Performs the specified selector with the specified objects. * * @param selector The selector to perform * @param object1 The first object that is passed to the method specified by the - * selector + * selector * @param object2 The second object that is passed to the method specified by * the selector * @return The object returned by the method specified by the selector */ - (nullable id)performSelector: (SEL)selector @@ -290,11 +290,11 @@ /*! * @brief Performs the specified selector with the specified objects. * * @param selector The selector to perform * @param object1 The first object that is passed to the method specified by the - * selector + * selector * @param object2 The second object that is passed to the method specified by * the selector * @param object3 The third object that is passed to the method specified by the * selector * @return The object returned by the method specified by the selector @@ -302,10 +302,30 @@ - (nullable id)performSelector: (SEL)selector withObject: (nullable id)object1 withObject: (nullable id)object2 withObject: (nullable id)object3; +/*! + * @brief Performs the specified selector with the specified objects. + * + * @param selector The selector to perform + * @param object1 The first object that is passed to the method specified by the + * selector + * @param object2 The second object that is passed to the method specified by + * the selector + * @param object3 The third object that is passed to the method specified by the + * selector + * @param object4 The fourth object that is passed to the method specified by + * the selector + * @return The object returned by the method specified by the selector + */ +- (nullable id)performSelector: (SEL)selector + withObject: (nullable id)object1 + withObject: (nullable id)object2 + withObject: (nullable id)object3 + withObject: (nullable id)object4; + /*! * @brief Checks two objects for equality. * * Classes containing data (like strings, arrays, lists etc.) should reimplement * this! @@ -740,37 +760,59 @@ * @brief Performs the specified selector with the specified objects after the * specified delay. * * @param selector The selector to perform * @param object1 The first object that is passed to the method specified by the - * selector + * selector + * @param object2 The second object that is passed to the method specified by + * the selector + * @param delay The delay after which the selector will be performed + */ +- (void)performSelector: (SEL)selector + withObject: (nullable id)object1 + withObject: (nullable id)object2 + afterDelay: (of_time_interval_t)delay; + +/*! + * @brief Performs the specified selector with the specified objects after the + * specified delay. + * + * @param selector The selector to perform + * @param object1 The first object that is passed to the method specified by the + * selector * @param object2 The second object that is passed to the method specified by * the selector + * @param object3 The third object that is passed to the method specified by the + * selector * @param delay The delay after which the selector will be performed */ - (void)performSelector: (SEL)selector withObject: (nullable id)object1 withObject: (nullable id)object2 + withObject: (nullable id)object3 afterDelay: (of_time_interval_t)delay; /*! * @brief Performs the specified selector with the specified objects after the * specified delay. * * @param selector The selector to perform * @param object1 The first object that is passed to the method specified by the - * selector + * selector * @param object2 The second object that is passed to the method specified by * the selector * @param object3 The third object that is passed to the method specified by the * selector + * @param object4 The fourth object that is passed to the method specified by + * the selector * @param delay The delay after which the selector will be performed */ - (void)performSelector: (SEL)selector withObject: (nullable id)object1 withObject: (nullable id)object2 withObject: (nullable id)object3 + withObject: (nullable id)object4 afterDelay: (of_time_interval_t)delay; #ifdef OF_HAVE_THREADS /*! * @brief Performs the specified selector on the specified thread. @@ -803,40 +845,64 @@ * specified objects. * * @param selector The selector to perform * @param thread The thread on which to perform the selector * @param object1 The first object that is passed to the method specified by the - * selector + * selector + * @param object2 The second object that is passed to the method specified by + * the selector + * @param waitUntilDone Whether to wait until the perform finished + */ +- (void)performSelector: (SEL)selector + onThread: (OFThread *)thread + withObject: (nullable id)object1 + withObject: (nullable id)object2 + waitUntilDone: (bool)waitUntilDone; + +/*! + * @brief Performs the specified selector on the specified thread with the + * specified objects. + * + * @param selector The selector to perform + * @param thread The thread on which to perform the selector + * @param object1 The first object that is passed to the method specified by the + * selector * @param object2 The second object that is passed to the method specified by * the selector + * @param object3 The third object that is passed to the method specified by the + * selector * @param waitUntilDone Whether to wait until the perform finished */ - (void)performSelector: (SEL)selector onThread: (OFThread *)thread withObject: (nullable id)object1 withObject: (nullable id)object2 + withObject: (nullable id)object3 waitUntilDone: (bool)waitUntilDone; /*! * @brief Performs the specified selector on the specified thread with the * specified objects. * * @param selector The selector to perform * @param thread The thread on which to perform the selector * @param object1 The first object that is passed to the method specified by the - * selector + * selector * @param object2 The second object that is passed to the method specified by * the selector * @param object3 The third object that is passed to the method specified by the * selector + * @param object4 The fourth object that is passed to the method specified by + * the selector * @param waitUntilDone Whether to wait until the perform finished */ - (void)performSelector: (SEL)selector onThread: (OFThread *)thread withObject: (nullable id)object1 withObject: (nullable id)object2 withObject: (nullable id)object3 + withObject: (nullable id)object4 waitUntilDone: (bool)waitUntilDone; /*! * @brief Performs the specified selector on the main thread. * @@ -863,37 +929,59 @@ * @brief Performs the specified selector on the main thread with the specified * objects. * * @param selector The selector to perform * @param object1 The first object that is passed to the method specified by the - * selector + * selector + * @param object2 The second object that is passed to the method specified by + * the selector + * @param waitUntilDone Whether to wait until the perform finished + */ +- (void)performSelectorOnMainThread: (SEL)selector + withObject: (nullable id)object1 + withObject: (nullable id)object2 + waitUntilDone: (bool)waitUntilDone; + +/*! + * @brief Performs the specified selector on the main thread with the specified + * objects. + * + * @param selector The selector to perform + * @param object1 The first object that is passed to the method specified by the + * selector * @param object2 The second object that is passed to the method specified by * the selector + * @param object3 The third object that is passed to the method specified by the + * selector * @param waitUntilDone Whether to wait until the perform finished */ - (void)performSelectorOnMainThread: (SEL)selector withObject: (nullable id)object1 withObject: (nullable id)object2 + withObject: (nullable id)object3 waitUntilDone: (bool)waitUntilDone; /*! * @brief Performs the specified selector on the main thread with the specified * objects. * * @param selector The selector to perform * @param object1 The first object that is passed to the method specified by the - * selector + * selector * @param object2 The second object that is passed to the method specified by * the selector * @param object3 The third object that is passed to the method specified by the * selector + * @param object4 The fourth object that is passed to the method specified by + * the selector * @param waitUntilDone Whether to wait until the perform finished */ - (void)performSelectorOnMainThread: (SEL)selector withObject: (nullable id)object1 withObject: (nullable id)object2 withObject: (nullable id)object3 + withObject: (nullable id)object4 waitUntilDone: (bool)waitUntilDone; /*! * @brief Performs the specified selector on the specified thread after the * specified delay. @@ -926,40 +1014,64 @@ * specified objects after the specified delay. * * @param selector The selector to perform * @param thread The thread on which to perform the selector * @param object1 The first object that is passed to the method specified by the - * selector + * selector + * @param object2 The second object that is passed to the method specified by + * the selector + * @param delay The delay after which the selector will be performed + */ +- (void)performSelector: (SEL)selector + onThread: (OFThread *)thread + withObject: (nullable id)object1 + withObject: (nullable id)object2 + afterDelay: (of_time_interval_t)delay; + +/*! + * @brief Performs the specified selector on the specified thread with the + * specified objects after the specified delay. + * + * @param selector The selector to perform + * @param thread The thread on which to perform the selector + * @param object1 The first object that is passed to the method specified by the + * selector * @param object2 The second object that is passed to the method specified by * the selector + * @param object3 The third object that is passed to the method specified by the + * selector * @param delay The delay after which the selector will be performed */ - (void)performSelector: (SEL)selector onThread: (OFThread *)thread withObject: (nullable id)object1 withObject: (nullable id)object2 + withObject: (nullable id)object3 afterDelay: (of_time_interval_t)delay; /*! * @brief Performs the specified selector on the specified thread with the * specified objects after the specified delay. * * @param selector The selector to perform * @param thread The thread on which to perform the selector * @param object1 The first object that is passed to the method specified by the - * selector + * selector * @param object2 The second object that is passed to the method specified by * the selector * @param object3 The third object that is passed to the method specified by the * selector + * @param object4 The fourth object that is passed to the method specified by + * the selector * @param delay The delay after which the selector will be performed */ - (void)performSelector: (SEL)selector onThread: (OFThread *)thread withObject: (nullable id)object1 withObject: (nullable id)object2 withObject: (nullable id)object3 + withObject: (nullable id)object4 afterDelay: (of_time_interval_t)delay; #endif /*! * @brief This method is called when @ref resolveClassMethod: or Index: src/OFObject.m ================================================================== --- src/OFObject.m +++ src/OFObject.m @@ -571,10 +571,27 @@ (id (*)(id, SEL, id, id, id))objc_msgSend; #endif return imp(self, selector, object1, object2, object3); } + +- (id)performSelector: (SEL)selector + withObject: (id)object1 + withObject: (id)object2 + withObject: (id)object3 + withObject: (id)object4 +{ +#if defined(OF_OBJFW_RUNTIME) + id (*imp)(id, SEL, id, id, id, id) = + (id (*)(id, SEL, id, id, id, id))objc_msg_lookup(self, selector); +#elif defined(OF_APPLE_RUNTIME) + id (*imp)(id, SEL, id, id, id, id) = + (id (*)(id, SEL, id, id, id, id))objc_msgSend; +#endif + + return imp(self, selector, object1, object2, object3, object4); +} - (void)performSelector: (SEL)selector afterDelay: (of_time_interval_t)delay { void *pool = objc_autoreleasePoolPush(); @@ -632,10 +649,31 @@ selector: selector object: object1 object: object2 object: object3 repeats: false]; + + objc_autoreleasePoolPop(pool); +} + +- (void)performSelector: (SEL)selector + withObject: (id)object1 + withObject: (id)object2 + withObject: (id)object3 + withObject: (id)object4 + afterDelay: (of_time_interval_t)delay +{ + void *pool = objc_autoreleasePoolPush(); + + [OFTimer scheduledTimerWithTimeInterval: delay + target: self + selector: selector + object: object1 + object: object2 + object: object3 + object: object4 + repeats: false]; objc_autoreleasePoolPop(pool); } #ifdef OF_HAVE_THREADS @@ -716,10 +754,35 @@ if (waitUntilDone) [timer waitUntilDone]; objc_autoreleasePoolPop(pool); } + +- (void)performSelector: (SEL)selector + onThread: (OFThread *)thread + withObject: (id)object1 + withObject: (id)object2 + withObject: (id)object3 + withObject: (id)object4 + waitUntilDone: (bool)waitUntilDone +{ + void *pool = objc_autoreleasePoolPush(); + OFTimer *timer = [OFTimer timerWithTimeInterval: 0 + target: self + selector: selector + object: object1 + object: object2 + object: object3 + object: object4 + repeats: false]; + [[thread runLoop] addTimer: timer]; + + if (waitUntilDone) + [timer waitUntilDone]; + + objc_autoreleasePoolPop(pool); +} - (void)performSelectorOnMainThread: (SEL)selector waitUntilDone: (bool)waitUntilDone { void *pool = objc_autoreleasePoolPush(); @@ -792,10 +855,34 @@ if (waitUntilDone) [timer waitUntilDone]; objc_autoreleasePoolPop(pool); } + +- (void)performSelectorOnMainThread: (SEL)selector + withObject: (id)object1 + withObject: (id)object2 + withObject: (id)object3 + withObject: (id)object4 + waitUntilDone: (bool)waitUntilDone +{ + void *pool = objc_autoreleasePoolPush(); + OFTimer *timer = [OFTimer timerWithTimeInterval: 0 + target: self + selector: selector + object: object1 + object: object2 + object: object3 + object: object4 + repeats: false]; + [[OFRunLoop mainRunLoop] addTimer: timer]; + + if (waitUntilDone) + [timer waitUntilDone]; + + objc_autoreleasePoolPop(pool); +} - (void)performSelector: (SEL)selector onThread: (OFThread *)thread afterDelay: (of_time_interval_t)delay { @@ -857,10 +944,32 @@ selector: selector object: object1 object: object2 object: object3 repeats: false]]; + + objc_autoreleasePoolPop(pool); +} + +- (void)performSelector: (SEL)selector + onThread: (OFThread *)thread + withObject: (id)object1 + withObject: (id)object2 + withObject: (id)object3 + withObject: (id)object4 + afterDelay: (of_time_interval_t)delay +{ + void *pool = objc_autoreleasePoolPush(); + + [[thread runLoop] addTimer: [OFTimer timerWithTimeInterval: delay + target: self + selector: selector + object: object1 + object: object2 + object: object3 + object: object4 + repeats: false]]; objc_autoreleasePoolPop(pool); } #endif Index: src/OFTimer.h ================================================================== --- src/OFTimer.h +++ src/OFTimer.h @@ -43,11 +43,11 @@ */ @interface OFTimer: OFObject { OFDate *_fireDate; of_time_interval_t _interval; - id _target, _object1, _object2, _object3; + id _target, _object1, _object2, _object3, _object4; SEL _selector; uint8_t _arguments; bool _repeats; #ifdef OF_HAVE_BLOCKS of_timer_block_t _block; @@ -147,10 +147,36 @@ object: (nullable id)object1 object: (nullable id)object2 object: (nullable id)object3 repeats: (bool)repeats; +/*! + * @brief Creates and schedules a new timer with the specified time interval. + * + * @param timeInterval The time interval after which the timer should be fired + * @param target The target on which to call the selector + * @param selector The selector to call on the target + * @param object1 The first object to pass when calling the selector on the + * target + * @param object2 The second object to pass when calling the selector on the + * target + * @param object3 The third object to pass when calling the selector on the + * target + * @param object4 The fourth object to pass when calling the selector on the + * target + * @param repeats Whether the timer repeats after it has been executed + * @return A new, autoreleased timer + */ ++ (instancetype)scheduledTimerWithTimeInterval: (of_time_interval_t)timeInterval + target: (id)target + selector: (SEL)selector + object: (nullable id)object1 + object: (nullable id)object2 + object: (nullable id)object3 + object: (nullable id)object4 + repeats: (bool)repeats; + #ifdef OF_HAVE_BLOCKS /*! * @brief Creates and schedules a new timer with the specified time interval. * * @param timeInterval The time interval after which the timer should be fired @@ -234,10 +260,36 @@ object: (nullable id)object1 object: (nullable id)object2 object: (nullable id)object3 repeats: (bool)repeats; +/*! + * @brief Creates a new timer with the specified time interval. + * + * @param timeInterval The time interval after which the timer should be fired + * @param target The target on which to call the selector + * @param selector The selector to call on the target + * @param object1 The first object to pass when calling the selector on the + * target + * @param object2 The second object to pass when calling the selector on the + * target + * @param object3 The third object to pass when calling the selector on the + * target + * @param object4 The fourth object to pass when calling the selector on the + * target + * @param repeats Whether the timer repeats after it has been executed + * @return A new, autoreleased timer + */ ++ (instancetype)timerWithTimeInterval: (of_time_interval_t)timeInterval + target: (id)target + selector: (SEL)selector + object: (nullable id)object1 + object: (nullable id)object2 + object: (nullable id)object3 + object: (nullable id)object4 + repeats: (bool)repeats; + #ifdef OF_HAVE_BLOCKS /*! * @brief Creates a new timer with the specified time interval. * * @param timeInterval The time interval after which the timer should be fired @@ -339,10 +391,40 @@ object: (nullable id)object1 object: (nullable id)object2 object: (nullable id)object3 repeats: (bool)repeats; +/*! + * @brief Initializes an already allocated timer with the specified time + * interval. + * + * @param fireDate The date at which the timer should fire + * @param interval The time interval after which to repeat the timer, if it is + * a repeating timer + * @param target The target on which to call the selector + * @param selector The selector to call on the target + * @param object1 The first object to pass when calling the selector on the + * target + * @param object2 The second object to pass when calling the selector on the + * target + * @param object3 The third object to pass when calling the selector on the + * target + * @param object4 The fourth object to pass when calling the selector on the + * target + * @param repeats Whether the timer repeats after it has been executed + * @return An initialized timer + */ +- initWithFireDate: (OFDate *)fireDate + interval: (of_time_interval_t)interval + target: (id)target + selector: (SEL)selector + object: (nullable id)object1 + object: (nullable id)object2 + object: (nullable id)object3 + object: (nullable id)object4 + repeats: (bool)repeats; + #ifdef OF_HAVE_BLOCKS /*! * @brief Initializes an already allocated timer with the specified time * interval. * Index: src/OFTimer.m ================================================================== --- src/OFTimer.m +++ src/OFTimer.m @@ -128,10 +128,39 @@ [timer retain]; objc_autoreleasePoolPop(pool); return [timer autorelease]; } + ++ (instancetype)scheduledTimerWithTimeInterval: (of_time_interval_t)timeInterval + target: (id)target + selector: (SEL)selector + object: (id)object1 + object: (id)object2 + object: (id)object3 + object: (id)object4 + repeats: (bool)repeats +{ + void *pool = objc_autoreleasePoolPush(); + OFDate *fireDate = [OFDate dateWithTimeIntervalSinceNow: timeInterval]; + id timer = [[[self alloc] initWithFireDate: fireDate + interval: timeInterval + target: target + selector: selector + object: object1 + object: object2 + object: object3 + object: object4 + repeats: repeats] autorelease]; + + [[OFRunLoop currentRunLoop] addTimer: timer]; + + [timer retain]; + objc_autoreleasePoolPop(pool); + + return [timer autorelease]; +} #ifdef OF_HAVE_BLOCKS + (instancetype)scheduledTimerWithTimeInterval: (of_time_interval_t)timeInterval repeats: (bool)repeats block: (of_timer_block_t)block @@ -237,10 +266,37 @@ [timer retain]; objc_autoreleasePoolPop(pool); return [timer autorelease]; } + ++ (instancetype)timerWithTimeInterval: (of_time_interval_t)timeInterval + target: (id)target + selector: (SEL)selector + object: (id)object1 + object: (id)object2 + object: (id)object3 + object: (id)object4 + repeats: (bool)repeats +{ + void *pool = objc_autoreleasePoolPush(); + OFDate *fireDate = [OFDate dateWithTimeIntervalSinceNow: timeInterval]; + id timer = [[[self alloc] initWithFireDate: fireDate + interval: timeInterval + target: target + selector: selector + object: object1 + object: object2 + object: object3 + object: object4 + repeats: repeats] autorelease]; + + [timer retain]; + objc_autoreleasePoolPop(pool); + + return [timer autorelease]; +} #ifdef OF_HAVE_BLOCKS + (instancetype)timerWithTimeInterval: (of_time_interval_t)timeInterval repeats: (bool)repeats block: (of_timer_block_t)block @@ -269,10 +325,11 @@ target: (id)target selector: (SEL)selector object: (id)object1 object: (id)object2 object: (id)object3 + object: (id)object4 arguments: (uint8_t)arguments repeats: (bool)repeats OF_METHOD_FAMILY(init) { self = [super init]; @@ -282,10 +339,11 @@ _target = [target retain]; _selector = selector; _object1 = [object1 retain]; _object2 = [object2 retain]; _object3 = [object3 retain]; + _object4 = [object4 retain]; _arguments = arguments; _repeats = repeats; _valid = true; #ifdef OF_HAVE_THREADS _condition = [[OFCondition alloc] init]; @@ -308,10 +366,11 @@ interval: interval target: target selector: selector object: nil object: nil + object: nil object: nil arguments: 0 repeats: repeats]; } @@ -325,10 +384,11 @@ return [self of_initWithFireDate: fireDate interval: interval target: target selector: selector object: object + object: nil object: nil object: nil arguments: 1 repeats: repeats]; } @@ -345,10 +405,11 @@ interval: interval target: target selector: selector object: object1 object: object2 + object: nil object: nil arguments: 2 repeats: repeats]; } @@ -366,13 +427,36 @@ target: target selector: selector object: object1 object: object2 object: object3 + object: nil arguments: 3 repeats: repeats]; } + +- initWithFireDate: (OFDate *)fireDate + interval: (of_time_interval_t)interval + target: (id)target + selector: (SEL)selector + object: (id)object1 + object: (id)object2 + object: (id)object3 + object: (id)object4 + repeats: (bool)repeats +{ + return [self of_initWithFireDate: fireDate + interval: interval + target: target + selector: selector + object: object1 + object: object2 + object: object3 + object: object4 + arguments: 4 + repeats: repeats]; +} #ifdef OF_HAVE_BLOCKS - initWithFireDate: (OFDate *)fireDate interval: (of_time_interval_t)interval repeats: (bool)repeats @@ -409,10 +493,11 @@ [_fireDate release]; [_target release]; [_object1 release]; [_object2 release]; [_object3 release]; + [_object4 release]; #ifdef OF_HAVE_BLOCKS [_block release]; #endif #ifdef OF_HAVE_THREADS [_condition release]; @@ -438,12 +523,13 @@ void *pool = objc_autoreleasePoolPush(); id target = [[_target retain] autorelease]; id object1 = [[_object1 retain] autorelease]; id object2 = [[_object2 retain] autorelease]; id object3 = [[_object3 retain] autorelease]; + id object4 = [[_object4 retain] autorelease]; - OF_ENSURE(_arguments <= 3); + OF_ENSURE(_arguments <= 4); if (_repeats && _valid) { int missedIntervals = -[_fireDate timeIntervalSinceNow] / _interval; of_time_interval_t newFireDate; @@ -485,10 +571,17 @@ [target performSelector: _selector withObject: object1 withObject: object2 withObject: object3]; break; + case 4: + [target performSelector: _selector + withObject: object1 + withObject: object2 + withObject: object3 + withObject: object4]; + break; } #ifdef OF_HAVE_BLOCKS } #endif @@ -536,15 +629,17 @@ [_target release]; [_object1 release]; [_object2 release]; [_object3 release]; + [_object4 release]; _target = nil; _object1 = nil; _object2 = nil; _object3 = nil; + _object4 = nil; } #ifdef OF_HAVE_THREADS - (void)waitUntilDone {